diff --git a/merge.go b/merge.go index 48783d1e2cc9d3d64e48c291171bfe4a6cbbbf45..fedd9ec48ef37f55542b3816732c6279f9d390d0 100644 --- a/merge.go +++ b/merge.go @@ -49,16 +49,16 @@ func (mc *xlsxMergeCell) Rect() ([]int, error) { // | | // |A8(x3,y4) C8(x4,y4)| // +------------------------+ -func (f *File) MergeCell(sheet, hCell, vCell string) error { - rect, err := rangeRefToCoordinates(hCell + ":" + vCell) +func (f *File) MergeCell(sheet, topLeftCell, bottomRightCell string) error { + rect, err := rangeRefToCoordinates(topLeftCell + ":" + bottomRightCell) if err != nil { return err } // Correct the range reference, such correct C1:B3 to B1:C3. _ = sortCoordinates(rect) - hCell, _ = CoordinatesToCellName(rect[0], rect[1]) - vCell, _ = CoordinatesToCellName(rect[2], rect[3]) + topLeftCell, _ = CoordinatesToCellName(rect[0], rect[1]) + bottomRightCell, _ = CoordinatesToCellName(rect[2], rect[3]) ws, err := f.workSheetReader(sheet) if err != nil { @@ -66,7 +66,7 @@ func (f *File) MergeCell(sheet, hCell, vCell string) error { } ws.mu.Lock() defer ws.mu.Unlock() - ref := hCell + ":" + vCell + ref := topLeftCell + ":" + bottomRightCell if ws.MergeCells != nil { ws.MergeCells.Cells = append(ws.MergeCells.Cells, &xlsxMergeCell{Ref: ref, rect: rect}) } else { @@ -82,14 +82,14 @@ func (f *File) MergeCell(sheet, hCell, vCell string) error { // err := f.UnmergeCell("Sheet1", "D3", "E9") // // Attention: overlapped range will also be unmerged. -func (f *File) UnmergeCell(sheet, hCell, vCell string) error { +func (f *File) UnmergeCell(sheet, topLeftCell, bottomRightCell string) error { ws, err := f.workSheetReader(sheet) if err != nil { return err } ws.mu.Lock() defer ws.mu.Unlock() - rect1, err := rangeRefToCoordinates(hCell + ":" + vCell) + rect1, err := rangeRefToCoordinates(topLeftCell + ":" + bottomRightCell) if err != nil { return err } @@ -265,9 +265,9 @@ func mergeCell(cell1, cell2 *xlsxMergeCell) *xlsxMergeCell { if rect1[3] < rect2[3] { rect1[3], rect2[3] = rect2[3], rect1[3] } - hCell, _ := CoordinatesToCellName(rect1[0], rect1[1]) - vCell, _ := CoordinatesToCellName(rect1[2], rect1[3]) - return &xlsxMergeCell{rect: rect1, Ref: hCell + ":" + vCell} + topLeftCell, _ := CoordinatesToCellName(rect1[0], rect1[1]) + bottomRightCell, _ := CoordinatesToCellName(rect1[2], rect1[3]) + return &xlsxMergeCell{rect: rect1, Ref: topLeftCell + ":" + bottomRightCell} } // MergeCell define a merged cell data. diff --git a/pivotTable.go b/pivotTable.go index 9512c27a948d6e0a675bed590f5e6df289faf9ba..04bc56259ca1a9d22e815562ccc4b5a6536c07a2 100644 --- a/pivotTable.go +++ b/pivotTable.go @@ -274,8 +274,8 @@ func (f *File) addPivotCache(opts *PivotTableOptions) error { } // data range has been checked order, _ := f.getTableFieldsOrder(opts) - hCell, _ := CoordinatesToCellName(coordinates[0], coordinates[1]) - vCell, _ := CoordinatesToCellName(coordinates[2], coordinates[3]) + topLeftCell, _ := CoordinatesToCellName(coordinates[0], coordinates[1]) + bottomRightCell, _ := CoordinatesToCellName(coordinates[2], coordinates[3]) pc := xlsxPivotCacheDefinition{ SaveData: false, RefreshOnLoad: true, @@ -285,7 +285,7 @@ func (f *File) addPivotCache(opts *PivotTableOptions) error { CacheSource: &xlsxCacheSource{ Type: "worksheet", WorksheetSource: &xlsxWorksheetSource{ - Ref: hCell + ":" + vCell, + Ref: topLeftCell + ":" + bottomRightCell, Sheet: dataSheet, }, }, @@ -315,8 +315,8 @@ func (f *File) addPivotTable(cacheID, pivotTableID int, opts *PivotTableOptions) return newPivotTableRangeError(err.Error()) } - hCell, _ := CoordinatesToCellName(coordinates[0], coordinates[1]) - vCell, _ := CoordinatesToCellName(coordinates[2], coordinates[3]) + topLeftCell, _ := CoordinatesToCellName(coordinates[0], coordinates[1]) + bottomRightCell, _ := CoordinatesToCellName(coordinates[2], coordinates[3]) pivotTableStyle := func() string { if opts.PivotTableStyleName == "" { @@ -340,7 +340,7 @@ func (f *File) addPivotTable(cacheID, pivotTableID int, opts *PivotTableOptions) ShowError: &opts.ShowError, DataCaption: "Values", Location: &xlsxLocation{ - Ref: hCell + ":" + vCell, + Ref: topLeftCell + ":" + bottomRightCell, FirstDataCol: 1, FirstDataRow: 1, FirstHeaderRow: 1, diff --git a/stream.go b/stream.go index 2247bcb8cc1e2198ab41133c3d88c5fd613263f1..05fb4cbde89d8256cc40fcdbddd6ad36e84ac4d1 100644 --- a/stream.go +++ b/stream.go @@ -484,16 +484,16 @@ func (sw *StreamWriter) SetPanes(panes *Panes) error { // MergeCell provides a function to merge cells by a given range reference for // the StreamWriter. Don't create a merged cell that overlaps with another // existing merged cell. -func (sw *StreamWriter) MergeCell(hCell, vCell string) error { - _, err := cellRefsToCoordinates(hCell, vCell) +func (sw *StreamWriter) MergeCell(topLeftCell, bottomRightCell string) error { + _, err := cellRefsToCoordinates(topLeftCell, bottomRightCell) if err != nil { return err } sw.mergeCellsCount++ _, _ = sw.mergeCells.WriteString(``) return nil } diff --git a/styles.go b/styles.go index 73bbdef955bcf4e017b0f84f3835f9449332cea4..2782c4dfeff3c14226bba75c7d1dce8017d3fee3 100644 --- a/styles.go +++ b/styles.go @@ -2262,13 +2262,13 @@ func (f *File) GetCellStyle(sheet, cell string) (int, error) { // fmt.Println(err) // } // err = f.SetCellStyle("Sheet1", "H9", "H9", style) -func (f *File) SetCellStyle(sheet, hCell, vCell string, styleID int) error { - hCol, hRow, err := CellNameToCoordinates(hCell) +func (f *File) SetCellStyle(sheet, topLeftCell, bottomRightCell string, styleID int) error { + hCol, hRow, err := CellNameToCoordinates(topLeftCell) if err != nil { return err } - vCol, vRow, err := CellNameToCoordinates(vCell) + vCol, vRow, err := CellNameToCoordinates(bottomRightCell) if err != nil { return err } @@ -2759,19 +2759,20 @@ func (f *File) SetConditionalFormat(sheet, rangeRef string, opts []ConditionalFo "iconSet", } ) - for p, v := range opts { + for i, opt := range opts { var vt, ct string var ok bool // "type" is a required parameter, check for valid validation types. - vt, ok = validType[v.Type] + vt, ok = validType[opt.Type] if ok { // Check for valid criteria types. - ct, ok = criteriaType[v.Criteria] + ct, ok = criteriaType[opt.Criteria] if ok || inStrSlice(noCriteriaTypes, vt, true) != -1 { drawFunc, ok := drawContFmtFunc[vt] if ok { - rule, x14rule := drawFunc(p, ct, strings.Split(rangeRef, ":")[0], - fmt.Sprintf("{00000000-0000-0000-%04X-%012X}", f.getSheetID(sheet), rules+p), &v) + priority := rules + i + rule, x14rule := drawFunc(priority, ct, strings.Split(rangeRef, ":")[0], + fmt.Sprintf("{00000000-0000-0000-%04X-%012X}", f.getSheetID(sheet), priority), &opt) if rule == nil { return ErrParameterInvalid } diff --git a/styles_test.go b/styles_test.go index 89dad301ce51c83380de9f82bd3c4240ae2ea046..6674dbe9573a21b97d83bac830e33a5bd2d13e71 100644 --- a/styles_test.go +++ b/styles_test.go @@ -193,6 +193,48 @@ func TestSetConditionalFormat(t *testing.T) { assert.Equal(t, ErrParameterInvalid, f.SetConditionalFormat("Sheet1", "A1:A2", []ConditionalFormatOptions{{Type: "icon_set", IconStyle: "unknown"}})) // Test unsupported conditional formatting rule types assert.Equal(t, ErrParameterInvalid, f.SetConditionalFormat("Sheet1", "A1", []ConditionalFormatOptions{{Type: "unsupported"}})) + + t.Run("multi_conditional_formatting_rules_priority", func(t *testing.T) { + f := NewFile() + var condFmts []ConditionalFormatOptions + for _, color := range []string{ + "#264B96", // Blue + "#F9A73E", // Yellow + "#006F3C", // Green + } { + condFmts = append(condFmts, ConditionalFormatOptions{ + Type: "data_bar", + Criteria: "=", + MinType: "num", + MaxType: "num", + MinValue: "0", + MaxValue: "5", + BarColor: color, + BarSolid: true, + }) + } + assert.NoError(t, f.SetConditionalFormat("Sheet1", "A1:A5", condFmts)) + assert.NoError(t, f.SetConditionalFormat("Sheet1", "B1:B5", condFmts)) + for r := 1; r <= 20; r++ { + cell, err := CoordinatesToCellName(1, r) + assert.NoError(t, err) + assert.NoError(t, f.SetCellValue("Sheet1", cell, r)) + cell, err = CoordinatesToCellName(2, r) + assert.NoError(t, err) + assert.NoError(t, f.SetCellValue("Sheet1", cell, r)) + } + ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml") + assert.True(t, ok) + var priorities []int + expected := []int{1, 2, 3, 4, 5, 6} + for _, condFmt := range ws.(*xlsxWorksheet).ConditionalFormatting { + for _, rule := range condFmt.CfRule { + priorities = append(priorities, rule.Priority) + } + } + assert.Equal(t, expected, priorities) + assert.NoError(t, f.Close()) + }) } func TestGetConditionalFormats(t *testing.T) {