Skip to content

Commit e51aff2

Browse files
committed
Resolve qax-os#570, flat columns for the column's operation
1 parent a691c10 commit e51aff2

9 files changed

+117
-67
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ os:
1414
- osx
1515

1616
env:
17-
matrix:
17+
jobs:
1818
- GOARCH=amd64
1919
- GOARCH=386
2020

CONTRIBUTING.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,9 @@ By making a contribution to this project, I certify that:
234234

235235
Then you just add a line to every git commit message:
236236

237-
Signed-off-by: Ri Xu https://xuri.me
237+
```text
238+
Signed-off-by: Ri Xu https://xuri.me
239+
```
238240

239241
Use your real name (sorry, no pseudonyms or anonymous contributions.)
240242

@@ -460,4 +462,4 @@ Do not use package math/rand to generate keys, even
460462
throwaway ones. Unseeded, the generator is completely predictable.
461463
Seeded with time.Nanoseconds(), there are just a few bits of entropy.
462464
Instead, use crypto/rand's Reader, and if you need text, print to
463-
hexadecimal or base64
465+
hexadecimal or base64.

col.go

+87-38
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import (
1313
"errors"
1414
"math"
1515
"strings"
16+
17+
"github.com/mohae/deepcopy"
1618
)
1719

1820
// Define the default cell size and EMU unit of measurement.
@@ -59,7 +61,7 @@ func (f *File) GetColVisible(sheet, col string) (bool, error) {
5961
//
6062
// err := f.SetColVisible("Sheet1", "D", false)
6163
//
62-
// Hide the columns from D to F (included)
64+
// Hide the columns from D to F (included):
6365
//
6466
// err := f.SetColVisible("Sheet1", "D:F", false)
6567
//
@@ -87,23 +89,31 @@ func (f *File) SetColVisible(sheet, columns string, visible bool) error {
8789
return err
8890
}
8991
colData := xlsxCol{
90-
Min: min,
91-
Max: max,
92-
Width: 9, // default width
93-
Hidden: !visible,
92+
Min: min,
93+
Max: max,
94+
Width: 9, // default width
95+
Hidden: !visible,
9496
CustomWidth: true,
9597
}
96-
if xlsx.Cols != nil {
97-
xlsx.Cols.Col = append(xlsx.Cols.Col, colData)
98-
} else {
98+
if xlsx.Cols == nil {
9999
cols := xlsxCols{}
100100
cols.Col = append(cols.Col, colData)
101101
xlsx.Cols = &cols
102-
}
102+
return nil
103+
}
104+
xlsx.Cols.Col = flatCols(colData, xlsx.Cols.Col, func(fc, c xlsxCol) xlsxCol {
105+
fc.BestFit = c.BestFit
106+
fc.Collapsed = c.Collapsed
107+
fc.CustomWidth = c.CustomWidth
108+
fc.OutlineLevel = c.OutlineLevel
109+
fc.Phonetic = c.Phonetic
110+
fc.Style = c.Style
111+
fc.Width = c.Width
112+
return fc
113+
})
103114
return nil
104115
}
105116

106-
107117
// GetColOutlineLevel provides a function to get outline level of a single
108118
// column by given worksheet name and column name. For example, get outline
109119
// level of column D in Sheet1:
@@ -162,16 +172,16 @@ func (f *File) SetColOutlineLevel(sheet, col string, level uint8) error {
162172
xlsx.Cols = &cols
163173
return err
164174
}
165-
for v := range xlsx.Cols.Col {
166-
if xlsx.Cols.Col[v].Min <= colNum && colNum <= xlsx.Cols.Col[v].Max {
167-
colData = xlsx.Cols.Col[v]
168-
}
169-
}
170-
colData.Min = colNum
171-
colData.Max = colNum
172-
colData.OutlineLevel = level
173-
colData.CustomWidth = true
174-
xlsx.Cols.Col = append(xlsx.Cols.Col, colData)
175+
xlsx.Cols.Col = flatCols(colData, xlsx.Cols.Col, func(fc, c xlsxCol) xlsxCol {
176+
fc.BestFit = c.BestFit
177+
fc.Collapsed = c.Collapsed
178+
fc.CustomWidth = c.CustomWidth
179+
fc.Hidden = c.Hidden
180+
fc.Phonetic = c.Phonetic
181+
fc.Style = c.Style
182+
fc.Width = c.Width
183+
return fc
184+
})
175185
return err
176186
}
177187

@@ -214,21 +224,21 @@ func (f *File) SetColStyle(sheet, columns string, styleID int) error {
214224
if xlsx.Cols == nil {
215225
xlsx.Cols = &xlsxCols{}
216226
}
217-
var find bool
218-
for idx, col := range xlsx.Cols.Col {
219-
if col.Min == min && col.Max == max {
220-
xlsx.Cols.Col[idx].Style = styleID
221-
find = true
222-
}
223-
}
224-
if !find {
225-
xlsx.Cols.Col = append(xlsx.Cols.Col, xlsxCol{
226-
Min: min,
227-
Max: max,
228-
Width: 9,
229-
Style: styleID,
230-
})
231-
}
227+
xlsx.Cols.Col = flatCols(xlsxCol{
228+
Min: min,
229+
Max: max,
230+
Width: 9,
231+
Style: styleID,
232+
}, xlsx.Cols.Col, func(fc, c xlsxCol) xlsxCol {
233+
fc.BestFit = c.BestFit
234+
fc.Collapsed = c.Collapsed
235+
fc.CustomWidth = c.CustomWidth
236+
fc.Hidden = c.Hidden
237+
fc.OutlineLevel = c.OutlineLevel
238+
fc.Phonetic = c.Phonetic
239+
fc.Width = c.Width
240+
return fc
241+
})
232242
return nil
233243
}
234244

@@ -261,16 +271,55 @@ func (f *File) SetColWidth(sheet, startcol, endcol string, width float64) error
261271
Width: width,
262272
CustomWidth: true,
263273
}
264-
if xlsx.Cols != nil {
265-
xlsx.Cols.Col = append(xlsx.Cols.Col, col)
266-
} else {
274+
if xlsx.Cols == nil {
267275
cols := xlsxCols{}
268276
cols.Col = append(cols.Col, col)
269277
xlsx.Cols = &cols
278+
return err
270279
}
280+
xlsx.Cols.Col = flatCols(col, xlsx.Cols.Col, func(fc, c xlsxCol) xlsxCol {
281+
fc.BestFit = c.BestFit
282+
fc.Collapsed = c.Collapsed
283+
fc.Hidden = c.Hidden
284+
fc.OutlineLevel = c.OutlineLevel
285+
fc.Phonetic = c.Phonetic
286+
fc.Style = c.Style
287+
return fc
288+
})
271289
return err
272290
}
273291

292+
// flatCols provides a method for the column's operation functions to flatten
293+
// and check the worksheet columns.
294+
func flatCols(col xlsxCol, cols []xlsxCol, replacer func(fc, c xlsxCol) xlsxCol) []xlsxCol {
295+
fc := []xlsxCol{}
296+
for i := col.Min; i <= col.Max; i++ {
297+
c := deepcopy.Copy(col).(xlsxCol)
298+
c.Min, c.Max = i, i
299+
fc = append(fc, c)
300+
}
301+
inFlat := func(colID int, cols []xlsxCol) (int, bool) {
302+
for idx, c := range cols {
303+
if c.Max == colID && c.Min == colID {
304+
return idx, true
305+
}
306+
}
307+
return -1, false
308+
}
309+
for _, column := range cols {
310+
for i := column.Min; i <= column.Max; i++ {
311+
if idx, ok := inFlat(i, fc); ok {
312+
fc[idx] = replacer(fc[idx], column)
313+
continue
314+
}
315+
c := deepcopy.Copy(column).(xlsxCol)
316+
c.Min, c.Max = i, i
317+
fc = append(fc, c)
318+
}
319+
}
320+
return fc
321+
}
322+
274323
// positionObjectPixels calculate the vertices that define the position of a
275324
// graphical object within the worksheet in pixels.
276325
//

col_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ func TestColumnVisibility(t *testing.T) {
3131
assert.Equal(t, false, visible)
3232
assert.NoError(t, err)
3333
// ...and displaying them back SetColVisible(...true)
34-
assert.NoError(t, f.SetColVisible("Sheet1", "F:V", true))
34+
assert.NoError(t, f.SetColVisible("Sheet1", "V:F", true))
3535
visible, err = f.GetColVisible("Sheet1", "F")
3636
assert.Equal(t, true, visible)
3737
assert.NoError(t, err)
@@ -53,7 +53,7 @@ func TestColumnVisibility(t *testing.T) {
5353

5454
f.NewSheet("Sheet3")
5555
assert.NoError(t, f.SetColVisible("Sheet3", "E", false))
56-
56+
assert.EqualError(t, f.SetColVisible("Sheet1", "A:-1", true), "invalid column name \"-1\"")
5757
assert.EqualError(t, f.SetColVisible("SheetN", "E", false), "sheet SheetN is not exist")
5858
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestColumnVisibility.xlsx")))
5959
})

merge.go

+11-14
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,17 @@ import (
2222
// If you create a merged cell that overlaps with another existing merged cell,
2323
// those merged cells that already exist will be removed.
2424
//
25-
// B1(x1,y1) D1(x2,y1)
26-
// +--------------------------------+
27-
// | |
28-
// | |
29-
// A4(x3,y3) | C4(x4,y3) |
30-
// +-----------------------------+ |
31-
// | | | |
32-
// | | | |
33-
// | |B5(x1,y2) | D5(x2,y2)|
34-
// | +--------------------------------+
35-
// | |
36-
// | |
37-
// |A8(x3,y4) C8(x4,y4)|
38-
// +-----------------------------+
25+
// B1(x1,y1) D1(x2,y1)
26+
// +------------------------+
27+
// | |
28+
// A4(x3,y3) | C4(x4,y3) |
29+
// +------------------------+ |
30+
// | | | |
31+
// | |B5(x1,y2) | D5(x2,y2)|
32+
// | +------------------------+
33+
// | |
34+
// |A8(x3,y4) C8(x4,y4)|
35+
// +------------------------+
3936
//
4037
func (f *File) MergeCell(sheet, hcell, vcell string) error {
4138
rect1, err := f.areaRefToCoordinates(hcell + ":" + vcell)

picture.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -462,8 +462,8 @@ func (f *File) GetPicture(sheet, cell string) (string, []byte, error) {
462462
return f.getPicture(row, col, drawingXML, drawingRelationships)
463463
}
464464

465-
// DeletePicture provides a function to delete chart in XLSX by given
466-
// worksheet and cell name. Note that the image file won't deleted from the
465+
// DeletePicture provides a function to delete charts in XLSX by given
466+
// worksheet and cell name. Note that the image file won't be deleted from the
467467
// document currently.
468468
func (f *File) DeletePicture(sheet, cell string) (err error) {
469469
col, row, err := CellNameToCoordinates(cell)

sheet.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,8 @@ func (f *File) GetActiveSheetIndex() int {
287287
return 0
288288
}
289289

290-
// SetSheetName provides a function to set the worksheet name be given old and
291-
// new worksheet name. Maximum 31 characters are allowed in sheet title and
290+
// SetSheetName provides a function to set the worksheet name by given old and
291+
// new worksheet names. Maximum 31 characters are allowed in sheet title and
292292
// this function only changes the name of the sheet and will not update the
293293
// sheet name in the formula or reference associated with the cell. So there
294294
// may be problem formula error or reference missing.

table.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@ func parseFormatTableSet(formatSet string) (*formatTable, error) {
3939
//
4040
// err := f.AddTable("Sheet2", "F2", "H6", `{"table_name":"table","table_style":"TableStyleMedium2", "show_first_column":true,"show_last_column":true,"show_row_stripes":false,"show_column_stripes":true}`)
4141
//
42-
// Note that the table at least two lines include string type header. Multiple
43-
// tables coordinate areas can't have an intersection.
42+
// Note that the table must be at least two lines including the header. The
43+
// header cells must contain strings and must be unique, and must set the
44+
// header row data of the table before calling the AddTable function. Multiple
45+
// tables coordinate areas that can't have an intersection.
4446
//
4547
// table_name: The name of the table, in the same worksheet name of the table should be unique
4648
//

xmlWorksheet.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -278,15 +278,15 @@ type xlsxCols struct {
278278
// width and column formatting for one or more columns of the worksheet.
279279
type xlsxCol struct {
280280
BestFit bool `xml:"bestFit,attr,omitempty"`
281-
Collapsed bool `xml:"collapsed,attr"`
281+
Collapsed bool `xml:"collapsed,attr,omitempty"`
282282
CustomWidth bool `xml:"customWidth,attr,omitempty"`
283-
Hidden bool `xml:"hidden,attr"`
283+
Hidden bool `xml:"hidden,attr,omitempty"`
284284
Max int `xml:"max,attr"`
285285
Min int `xml:"min,attr"`
286286
OutlineLevel uint8 `xml:"outlineLevel,attr,omitempty"`
287287
Phonetic bool `xml:"phonetic,attr,omitempty"`
288-
Style int `xml:"style,attr"`
289-
Width float64 `xml:"width,attr"`
288+
Style int `xml:"style,attr,omitempty"`
289+
Width float64 `xml:"width,attr,omitempty"`
290290
}
291291

292292
// xlsxDimension directly maps the dimension element in the namespace

0 commit comments

Comments
 (0)