Skip to content

Commit 4eb3486

Browse files
authored
This closes #1783, support set conditional formatting with multiple cell ranges (#1787)
1 parent 50e23df commit 4eb3486

File tree

3 files changed

+54
-13
lines changed

3 files changed

+54
-13
lines changed

adjust.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -471,12 +471,12 @@ func (af *arrayFormulaOperandToken) setCoordinates() error {
471471
}
472472
var c, r int
473473
if col {
474-
if cellRef.Row = TotalRows; i == 1 {
474+
if cellRef.Row = TotalRows; i == 0 {
475475
cellRef.Row = 1
476476
}
477477
}
478478
if row {
479-
if cellRef.Col = MaxColumns; i == 1 {
479+
if cellRef.Col = MaxColumns; i == 0 {
480480
cellRef.Col = 1
481481
}
482482
}

styles.go

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2760,13 +2760,9 @@ func (f *File) SetConditionalFormat(sheet, rangeRef string, opts []ConditionalFo
27602760
if err != nil {
27612761
return err
27622762
}
2763-
if strings.Contains(rangeRef, ":") {
2764-
rect, err := rangeRefToCoordinates(rangeRef)
2765-
if err != nil {
2766-
return err
2767-
}
2768-
_ = sortCoordinates(rect)
2769-
rangeRef, _ = f.coordinatesToRangeRef(rect, strings.Contains(rangeRef, "$"))
2763+
SQRef, mastCell, err := prepareConditionalFormatRange(rangeRef)
2764+
if err != nil {
2765+
return err
27702766
}
27712767
// Create a pseudo GUID for each unique rule.
27722768
var rules int
@@ -2796,7 +2792,7 @@ func (f *File) SetConditionalFormat(sheet, rangeRef string, opts []ConditionalFo
27962792
drawFunc, ok := drawContFmtFunc[vt]
27972793
if ok {
27982794
priority := rules + i
2799-
rule, x14rule := drawFunc(priority, ct, strings.Split(rangeRef, ":")[0],
2795+
rule, x14rule := drawFunc(priority, ct, mastCell,
28002796
fmt.Sprintf("{00000000-0000-0000-%04X-%012X}", f.getSheetID(sheet), priority), &opt)
28012797
if rule == nil {
28022798
return ErrParameterInvalid
@@ -2817,12 +2813,53 @@ func (f *File) SetConditionalFormat(sheet, rangeRef string, opts []ConditionalFo
28172813
}
28182814

28192815
ws.ConditionalFormatting = append(ws.ConditionalFormatting, &xlsxConditionalFormatting{
2820-
SQRef: rangeRef,
2816+
SQRef: SQRef,
28212817
CfRule: cfRule,
28222818
})
28232819
return err
28242820
}
28252821

2822+
// prepareConditionalFormatRange returns checked cell range and master cell
2823+
// reference by giving conditional formatting range reference.
2824+
func prepareConditionalFormatRange(rangeRef string) (string, string, error) {
2825+
var SQRef, mastCell string
2826+
if rangeRef == "" {
2827+
return SQRef, mastCell, ErrParameterRequired
2828+
}
2829+
rangeRef = strings.ReplaceAll(rangeRef, ",", " ")
2830+
for i, cellRange := range strings.Split(rangeRef, " ") {
2831+
var cellNames []string
2832+
for j, ref := range strings.Split(cellRange, ":") {
2833+
if j > 1 {
2834+
return SQRef, mastCell, ErrParameterInvalid
2835+
}
2836+
cellRef, col, row, err := parseRef(ref)
2837+
if err != nil {
2838+
return SQRef, mastCell, err
2839+
}
2840+
var c, r int
2841+
if col {
2842+
if cellRef.Row = TotalRows; j == 0 {
2843+
cellRef.Row = 1
2844+
}
2845+
}
2846+
if row {
2847+
if cellRef.Col = MaxColumns; j == 0 {
2848+
cellRef.Col = 1
2849+
}
2850+
}
2851+
c, r = cellRef.Col, cellRef.Row
2852+
cellName, _ := CoordinatesToCellName(c, r)
2853+
cellNames = append(cellNames, cellName)
2854+
if i == 0 && j == 0 {
2855+
mastCell = cellName
2856+
}
2857+
}
2858+
SQRef += strings.Join(cellNames, ":") + " "
2859+
}
2860+
return strings.TrimSuffix(SQRef, " "), mastCell, nil
2861+
}
2862+
28262863
// appendCfRule provides a function to append rules to conditional formatting.
28272864
func (f *File) appendCfRule(ws *xlsxWorksheet, rule *xlsxX14CfRule) error {
28282865
var (

styles_test.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,10 @@ func TestSetConditionalFormat(t *testing.T) {
178178
assert.NoError(t, f.SetConditionalFormat("Sheet1", ref, condFmts))
179179
}
180180
f = NewFile()
181+
// Test creating a conditional format without cell reference
182+
assert.Equal(t, ErrParameterRequired, f.SetConditionalFormat("Sheet1", "", nil))
183+
// Test creating a conditional format with invalid cell reference
184+
assert.Equal(t, ErrParameterInvalid, f.SetConditionalFormat("Sheet1", "A1:A2:A3", nil))
181185
// Test creating a conditional format with existing extension lists
182186
ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
183187
assert.True(t, ok)
@@ -272,11 +276,11 @@ func TestGetConditionalFormats(t *testing.T) {
272276
{{Type: "icon_set", IconStyle: "3Arrows", ReverseIcons: true, IconsOnly: true}},
273277
} {
274278
f := NewFile()
275-
err := f.SetConditionalFormat("Sheet1", "A2:A1", format)
279+
err := f.SetConditionalFormat("Sheet1", "A2:A1,B:B,2:2", format)
276280
assert.NoError(t, err)
277281
opts, err := f.GetConditionalFormats("Sheet1")
278282
assert.NoError(t, err)
279-
assert.Equal(t, format, opts["A1:A2"])
283+
assert.Equal(t, format, opts["A2:A1 B1:B1048576 A2:XFD2"])
280284
}
281285
// Test get multiple conditional formats
282286
f := NewFile()

0 commit comments

Comments
 (0)