diff --git a/adjust.go b/adjust.go index bae49bc94a117a0e9539f6d89a9d201f8a326314..9346bd1a6f9ab2e7ac9b996ef30242418a860740 100644 --- a/adjust.go +++ b/adjust.go @@ -471,12 +471,12 @@ func (af *arrayFormulaOperandToken) setCoordinates() error { } var c, r int if col { - if cellRef.Row = TotalRows; i == 1 { + if cellRef.Row = TotalRows; i == 0 { cellRef.Row = 1 } } if row { - if cellRef.Col = MaxColumns; i == 1 { + if cellRef.Col = MaxColumns; i == 0 { cellRef.Col = 1 } } diff --git a/styles.go b/styles.go index 489ce1de5cfe69d92e0566ac31ef089c0cae062e..54635042ac04c9dc6bc757a5c73eef861513ce2d 100644 --- a/styles.go +++ b/styles.go @@ -2760,13 +2760,9 @@ func (f *File) SetConditionalFormat(sheet, rangeRef string, opts []ConditionalFo if err != nil { return err } - if strings.Contains(rangeRef, ":") { - rect, err := rangeRefToCoordinates(rangeRef) - if err != nil { - return err - } - _ = sortCoordinates(rect) - rangeRef, _ = f.coordinatesToRangeRef(rect, strings.Contains(rangeRef, "$")) + SQRef, mastCell, err := prepareConditionalFormatRange(rangeRef) + if err != nil { + return err } // Create a pseudo GUID for each unique rule. var rules int @@ -2796,7 +2792,7 @@ func (f *File) SetConditionalFormat(sheet, rangeRef string, opts []ConditionalFo drawFunc, ok := drawContFmtFunc[vt] if ok { priority := rules + i - rule, x14rule := drawFunc(priority, ct, strings.Split(rangeRef, ":")[0], + rule, x14rule := drawFunc(priority, ct, mastCell, fmt.Sprintf("{00000000-0000-0000-%04X-%012X}", f.getSheetID(sheet), priority), &opt) if rule == nil { return ErrParameterInvalid @@ -2817,12 +2813,53 @@ func (f *File) SetConditionalFormat(sheet, rangeRef string, opts []ConditionalFo } ws.ConditionalFormatting = append(ws.ConditionalFormatting, &xlsxConditionalFormatting{ - SQRef: rangeRef, + SQRef: SQRef, CfRule: cfRule, }) return err } +// prepareConditionalFormatRange returns checked cell range and master cell +// reference by giving conditional formatting range reference. +func prepareConditionalFormatRange(rangeRef string) (string, string, error) { + var SQRef, mastCell string + if rangeRef == "" { + return SQRef, mastCell, ErrParameterRequired + } + rangeRef = strings.ReplaceAll(rangeRef, ",", " ") + for i, cellRange := range strings.Split(rangeRef, " ") { + var cellNames []string + for j, ref := range strings.Split(cellRange, ":") { + if j > 1 { + return SQRef, mastCell, ErrParameterInvalid + } + cellRef, col, row, err := parseRef(ref) + if err != nil { + return SQRef, mastCell, err + } + var c, r int + if col { + if cellRef.Row = TotalRows; j == 0 { + cellRef.Row = 1 + } + } + if row { + if cellRef.Col = MaxColumns; j == 0 { + cellRef.Col = 1 + } + } + c, r = cellRef.Col, cellRef.Row + cellName, _ := CoordinatesToCellName(c, r) + cellNames = append(cellNames, cellName) + if i == 0 && j == 0 { + mastCell = cellName + } + } + SQRef += strings.Join(cellNames, ":") + " " + } + return strings.TrimSuffix(SQRef, " "), mastCell, nil +} + // appendCfRule provides a function to append rules to conditional formatting. func (f *File) appendCfRule(ws *xlsxWorksheet, rule *xlsxX14CfRule) error { var ( diff --git a/styles_test.go b/styles_test.go index 9680fab70475be9dbb4e14f0c510f80da1df9fc5..9267da951e25228e66e8e14ec76da70749c8aacf 100644 --- a/styles_test.go +++ b/styles_test.go @@ -178,6 +178,10 @@ func TestSetConditionalFormat(t *testing.T) { assert.NoError(t, f.SetConditionalFormat("Sheet1", ref, condFmts)) } f = NewFile() + // Test creating a conditional format without cell reference + assert.Equal(t, ErrParameterRequired, f.SetConditionalFormat("Sheet1", "", nil)) + // Test creating a conditional format with invalid cell reference + assert.Equal(t, ErrParameterInvalid, f.SetConditionalFormat("Sheet1", "A1:A2:A3", nil)) // Test creating a conditional format with existing extension lists ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml") assert.True(t, ok) @@ -272,11 +276,11 @@ func TestGetConditionalFormats(t *testing.T) { {{Type: "icon_set", IconStyle: "3Arrows", ReverseIcons: true, IconsOnly: true}}, } { f := NewFile() - err := f.SetConditionalFormat("Sheet1", "A2:A1", format) + err := f.SetConditionalFormat("Sheet1", "A2:A1,B:B,2:2", format) assert.NoError(t, err) opts, err := f.GetConditionalFormats("Sheet1") assert.NoError(t, err) - assert.Equal(t, format, opts["A1:A2"]) + assert.Equal(t, format, opts["A2:A1 B1:B1048576 A2:XFD2"]) } // Test get multiple conditional formats f := NewFile()