Skip to content

Commit 7b57409

Browse files
committed
Support delete conditional format rule or data validation by specific cell from a cells range
- Remove operator attribute for time period condition format rules to prevent generate workbook corrupted - Update unit tests
1 parent 8b325dc commit 7b57409

File tree

4 files changed

+185
-70
lines changed

4 files changed

+185
-70
lines changed

datavalidation.go

Lines changed: 53 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ func (f *File) DeleteDataValidation(sheet string, sqref ...string) error {
407407
}
408408
}
409409
if ws.ExtLst != nil {
410-
return f.deleteX14DataValidation(ws, sqref)
410+
return f.deleteX14DataValidation(ws, delCells)
411411
}
412412
return nil
413413
}
@@ -416,25 +416,12 @@ func (f *File) DeleteDataValidation(sheet string, sqref ...string) error {
416416
// reference list.
417417
func (f *File) deleteDataValidation(ws *xlsxWorksheet, delCells map[int][][]int) error {
418418
dv := ws.DataValidations
419+
var err error
419420
for i := 0; i < len(dv.DataValidation); i++ {
420-
var applySqref []string
421-
colCells, err := flatSqref(dv.DataValidation[i].Sqref)
422-
if err != nil {
421+
if dv.DataValidation[i].Sqref, err = deleteCellsFromSqref(dv.DataValidation[i].Sqref, delCells); err != nil {
423422
return err
424423
}
425-
for col, cells := range delCells {
426-
for _, cell := range cells {
427-
idx := inCoordinates(colCells[col], cell)
428-
if idx != -1 {
429-
colCells[col] = append(colCells[col][:idx], colCells[col][idx+1:]...)
430-
}
431-
}
432-
}
433-
for _, col := range colCells {
434-
applySqref = append(applySqref, squashSqref(col)...)
435-
}
436-
dv.DataValidation[i].Sqref = strings.Join(applySqref, " ")
437-
if len(applySqref) == 0 {
424+
if len(dv.DataValidation[i].Sqref) == 0 {
438425
dv.DataValidation = append(dv.DataValidation[:i], dv.DataValidation[i+1:]...)
439426
i--
440427
}
@@ -448,8 +435,9 @@ func (f *File) deleteDataValidation(ws *xlsxWorksheet, delCells map[int][][]int)
448435

449436
// deleteX14DataValidation deletes data validation in the extLst element by
450437
// given worksheet and cell reference list.
451-
func (f *File) deleteX14DataValidation(ws *xlsxWorksheet, sqref []string) error {
438+
func (f *File) deleteX14DataValidation(ws *xlsxWorksheet, delCells map[int][][]int) error {
452439
var (
440+
err error
453441
decodeExtLst = new(decodeExtLst)
454442
decodeDataValidations *xlsxDataValidations
455443
x14DataValidations *xlsxX14DataValidations
@@ -468,25 +456,29 @@ func (f *File) deleteX14DataValidation(ws *xlsxWorksheet, sqref []string) error
468456
x14DataValidations.XWindow = decodeDataValidations.XWindow
469457
x14DataValidations.YWindow = decodeDataValidations.YWindow
470458
for _, dv := range decodeDataValidations.DataValidation {
471-
if inStrSlice(sqref, dv.XMSqref, false) == -1 {
472-
x14DataValidations.DataValidation = append(x14DataValidations.DataValidation, &xlsxX14DataValidation{
473-
AllowBlank: dv.AllowBlank,
474-
Error: dv.Error,
475-
ErrorStyle: dv.ErrorStyle,
476-
ErrorTitle: dv.ErrorTitle,
477-
Operator: dv.Operator,
478-
Prompt: dv.Prompt,
479-
PromptTitle: dv.PromptTitle,
480-
ShowDropDown: dv.ShowDropDown,
481-
ShowErrorMessage: dv.ShowErrorMessage,
482-
ShowInputMessage: dv.ShowInputMessage,
483-
Sqref: dv.Sqref,
484-
XMSqref: dv.XMSqref,
485-
Type: dv.Type,
486-
Formula1: dv.Formula1,
487-
Formula2: dv.Formula2,
488-
})
459+
if dv.XMSqref, err = deleteCellsFromSqref(dv.XMSqref, delCells); err != nil {
460+
return err
489461
}
462+
if len(dv.XMSqref) == 0 {
463+
continue
464+
}
465+
x14DataValidations.DataValidation = append(x14DataValidations.DataValidation, &xlsxX14DataValidation{
466+
AllowBlank: dv.AllowBlank,
467+
Error: dv.Error,
468+
ErrorStyle: dv.ErrorStyle,
469+
ErrorTitle: dv.ErrorTitle,
470+
Operator: dv.Operator,
471+
Prompt: dv.Prompt,
472+
PromptTitle: dv.PromptTitle,
473+
ShowDropDown: dv.ShowDropDown,
474+
ShowErrorMessage: dv.ShowErrorMessage,
475+
ShowInputMessage: dv.ShowInputMessage,
476+
Sqref: dv.Sqref,
477+
XMSqref: dv.XMSqref,
478+
Type: dv.Type,
479+
Formula1: dv.Formula1,
480+
Formula2: dv.Formula2,
481+
})
490482
}
491483
x14DataValidations.Count = len(x14DataValidations.DataValidation)
492484
x14DataValidationsBytes, _ := xml.Marshal(x14DataValidations)
@@ -533,6 +525,31 @@ func squashSqref(cells [][]int) []string {
533525
return append(refs, ref)
534526
}
535527

528+
// deleteCellsFromSqref deletes cells from given sqref by delCells map and
529+
// returns the updated sqref.
530+
func deleteCellsFromSqref(sqref string, delCells map[int][][]int) (string, error) {
531+
var (
532+
ref string
533+
applySqref []string
534+
)
535+
colCells, err := flatSqref(sqref)
536+
if err != nil {
537+
return ref, err
538+
}
539+
for col, cells := range delCells {
540+
for _, cell := range cells {
541+
idx := inCoordinates(colCells[col], cell)
542+
if idx != -1 {
543+
colCells[col] = append(colCells[col][:idx], colCells[col][idx+1:]...)
544+
}
545+
}
546+
}
547+
for _, col := range colCells {
548+
applySqref = append(applySqref, squashSqref(col)...)
549+
}
550+
return strings.Join(applySqref, " "), err
551+
}
552+
536553
// isFormulaDataValidation returns whether the data validation rule is a formula.
537554
func (dv *xlsxInnerXML) isFormula() bool {
538555
return dv != nil && !(strings.HasPrefix(dv.Content, "&quot;") && strings.HasSuffix(dv.Content, "&quot;"))

datavalidation_test.go

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ func TestDeleteDataValidation(t *testing.T) {
244244
assert.NoError(t, f.DeleteDataValidation("Sheet1"))
245245
assert.Nil(t, ws.(*xlsxWorksheet).DataValidations)
246246

247-
t.Run("delete_data_validation_from_extLst", func(t *testing.T) {
247+
t.Run("with_data_validation_in_extLst", func(t *testing.T) {
248248
f := NewFile()
249249
f.Sheet.Delete("xl/worksheets/sheet1.xml")
250250
f.Pkg.Store("xl/worksheets/sheet1.xml", fmt.Appendf(nil,
@@ -264,14 +264,14 @@ func TestDeleteDataValidation(t *testing.T) {
264264
assert.Empty(t, dvs)
265265
})
266266

267-
t.Run("delete_data_validation_failed_from_extLst", func(t *testing.T) {
267+
t.Run("with_invalid_data_validation_in_extLst", func(t *testing.T) {
268268
f := NewFile()
269269
assert.EqualError(t, f.deleteX14DataValidation(&xlsxWorksheet{
270270
ExtLst: &xlsxExtLst{Ext: "<extLst><x14:dataValidations></x14:dataValidation></x14:dataValidations></ext></extLst>"},
271271
}, nil), "XML syntax error on line 1: element <dataValidations> closed by </dataValidation>")
272272
})
273273

274-
t.Run("delete_data_validation_with_unordered_sqref", func(t *testing.T) {
274+
t.Run("with_unordered_sqref", func(t *testing.T) {
275275
// Test deleting data validation when sqref has unordered ranges
276276
f := NewFile()
277277
ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
@@ -298,4 +298,28 @@ func TestDeleteDataValidation(t *testing.T) {
298298
assert.Len(t, dvs, 1)
299299
assert.Equal(t, "A3:A6 A8:A10 A15:A20", dvs[0].Sqref)
300300
})
301+
302+
t.Run("with_unordered_sqref_in_extLst", func(t *testing.T) {
303+
f := NewFile()
304+
f.Sheet.Delete("xl/worksheets/sheet1.xml")
305+
f.Pkg.Store("xl/worksheets/sheet1.xml", fmt.Appendf(nil,
306+
`<worksheet xmlns="%s"><sheetData/><extLst><ext xmlns:x14="%s" uri="%s"><x14:dataValidations xmlns:xm="%s" count="1"><x14:dataValidation><xm:sqref>A5:A10 A15:A20 A3:A4</xm:sqref><x14:formula1></x14:formula1></x14:dataValidation></x14:dataValidations></ext></extLst></worksheet>`,
307+
NameSpaceSpreadSheet.Value, NameSpaceSpreadSheetExcel2006Main.Value,
308+
ExtURIDataValidations, NameSpaceSpreadSheetExcel2006Main.Value))
309+
f.checked = sync.Map{}
310+
assert.NoError(t, f.DeleteDataValidation("Sheet1", "A7"))
311+
dvs, err := f.GetDataValidations("Sheet1")
312+
assert.NoError(t, err)
313+
assert.Len(t, dvs, 1)
314+
assert.Equal(t, "A3:A6 A8:A10 A15:A20", dvs[0].Sqref)
315+
// Test deleting data validation with invalid sqref
316+
f = NewFile()
317+
f.Sheet.Delete("xl/worksheets/sheet1.xml")
318+
f.Pkg.Store("xl/worksheets/sheet1.xml", fmt.Appendf(nil,
319+
`<worksheet xmlns="%s"><sheetData/><extLst><ext xmlns:x14="%s" uri="%s"><x14:dataValidations xmlns:xm="%s" count="1"><x14:dataValidation><xm:sqref>A</xm:sqref><x14:formula1></x14:formula1></x14:dataValidation></x14:dataValidations></ext></extLst></worksheet>`,
320+
NameSpaceSpreadSheet.Value, NameSpaceSpreadSheetExcel2006Main.Value,
321+
ExtURIDataValidations, NameSpaceSpreadSheetExcel2006Main.Value))
322+
f.checked = sync.Map{}
323+
assert.Equal(t, f.DeleteDataValidation("Sheet1", "A7"), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")))
324+
})
301325
}

styles.go

Lines changed: 67 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,59 +1193,59 @@ var (
11931193
}
11941194

11951195
// extractContFmtFunc defines functions to get conditional formats.
1196-
extractContFmtFunc = map[string]func(*File, *xlsxCfRule, *xlsxExtLst) ConditionalFormatOptions{
1197-
"cellIs": func(f *File, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
1196+
extractContFmtFunc = map[string]func(*File, string, *xlsxCfRule, *xlsxExtLst) ConditionalFormatOptions{
1197+
"cellIs": func(f *File, ref string, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
11981198
return f.extractCondFmtCellIs(c, extLst)
11991199
},
1200-
"timePeriod": func(f *File, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
1201-
return f.extractCondFmtTimePeriod(c, extLst)
1200+
"timePeriod": func(f *File, ref string, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
1201+
return f.extractCondFmtTimePeriod(c, ref, extLst)
12021202
},
1203-
"containsText": func(f *File, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
1203+
"containsText": func(f *File, ref string, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
12041204
return f.extractCondFmtText(c, extLst)
12051205
},
1206-
"notContainsText": func(f *File, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
1206+
"notContainsText": func(f *File, ref string, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
12071207
return f.extractCondFmtText(c, extLst)
12081208
},
1209-
"beginsWith": func(f *File, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
1209+
"beginsWith": func(f *File, ref string, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
12101210
return f.extractCondFmtText(c, extLst)
12111211
},
1212-
"endsWith": func(f *File, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
1212+
"endsWith": func(f *File, ref string, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
12131213
return f.extractCondFmtText(c, extLst)
12141214
},
1215-
"top10": func(f *File, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
1215+
"top10": func(f *File, ref string, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
12161216
return f.extractCondFmtTop10(c, extLst)
12171217
},
1218-
"aboveAverage": func(f *File, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
1218+
"aboveAverage": func(f *File, ref string, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
12191219
return f.extractCondFmtAboveAverage(c, extLst)
12201220
},
1221-
"duplicateValues": func(f *File, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
1221+
"duplicateValues": func(f *File, ref string, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
12221222
return f.extractCondFmtDuplicateUniqueValues(c, extLst)
12231223
},
1224-
"uniqueValues": func(f *File, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
1224+
"uniqueValues": func(f *File, ref string, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
12251225
return f.extractCondFmtDuplicateUniqueValues(c, extLst)
12261226
},
1227-
"containsBlanks": func(f *File, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
1227+
"containsBlanks": func(f *File, ref string, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
12281228
return f.extractCondFmtBlanks(c, extLst)
12291229
},
1230-
"notContainsBlanks": func(f *File, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
1230+
"notContainsBlanks": func(f *File, ref string, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
12311231
return f.extractCondFmtNoBlanks(c, extLst)
12321232
},
1233-
"containsErrors": func(f *File, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
1233+
"containsErrors": func(f *File, ref string, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
12341234
return f.extractCondFmtErrors(c, extLst)
12351235
},
1236-
"notContainsErrors": func(f *File, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
1236+
"notContainsErrors": func(f *File, ref string, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
12371237
return f.extractCondFmtNoErrors(c, extLst)
12381238
},
1239-
"colorScale": func(f *File, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
1239+
"colorScale": func(f *File, ref string, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
12401240
return f.extractCondFmtColorScale(c, extLst)
12411241
},
1242-
"dataBar": func(f *File, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
1242+
"dataBar": func(f *File, ref string, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
12431243
return f.extractCondFmtDataBar(c, extLst)
12441244
},
1245-
"expression": func(f *File, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
1245+
"expression": func(f *File, ref string, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
12461246
return f.extractCondFmtExp(c, extLst)
12471247
},
1248-
"iconSet": func(f *File, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
1248+
"iconSet": func(f *File, ref string, c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
12491249
return f.extractCondFmtIconSet(c, extLst)
12501250
},
12511251
}
@@ -2969,8 +2969,26 @@ func (f *File) extractCondFmtCellIs(c *xlsxCfRule, extLst *xlsxExtLst) Condition
29692969

29702970
// extractCondFmtTimePeriod provides a function to extract conditional format
29712971
// settings for time period by given conditional formatting rule.
2972-
func (f *File) extractCondFmtTimePeriod(c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
2973-
return ConditionalFormatOptions{Format: c.DxfID, StopIfTrue: c.StopIfTrue, Type: "time_period", Criteria: operatorType[c.Operator]}
2972+
func (f *File) extractCondFmtTimePeriod(c *xlsxCfRule, ref string, extLst *xlsxExtLst) ConditionalFormatOptions {
2973+
var critera string
2974+
for _, formula := range c.Formula {
2975+
if c, ok := map[string]string{
2976+
fmt.Sprintf("FLOOR(%s,1)=TODAY()-1", ref): "yesterday",
2977+
fmt.Sprintf("FLOOR(%s,1)=TODAY()", ref): "today",
2978+
fmt.Sprintf("FLOOR(%s,1)=TODAY()+1", ref): "tomorrow",
2979+
fmt.Sprintf("AND(TODAY()-FLOOR(%[1]s,1)<=6,FLOOR(%[1]s,1)<=TODAY())", ref): "last 7 days",
2980+
fmt.Sprintf("AND(TODAY()-ROUNDDOWN(%[1]s,0)>=(WEEKDAY(TODAY())),TODAY()-ROUNDDOWN(%[1]s,0)<(WEEKDAY(TODAY())+7))", ref): "last week",
2981+
fmt.Sprintf("AND(TODAY()-ROUNDDOWN(%[1]s,0)<=WEEKDAY(TODAY())-1,ROUNDDOWN(%[1]s,0)-TODAY()>=7-WEEKDAY(TODAY()))", ref): "this week",
2982+
fmt.Sprintf("AND(ROUNDDOWN(%[1]s,0)-TODAY()>(7-WEEKDAY(TODAY())),ROUNDDOWN(%[1]s,0)-TODAY()<(15-WEEKDAY(TODAY())))", ref): "continue week",
2983+
fmt.Sprintf("AND(MONTH(%[1]s)=MONTH(TODAY())-1,OR(YEAR(%[1]s)=YEAR(TODAY()),AND(MONTH(%[1]s)=1,YEAR(%[1]s)=YEAR(TODAY())-1)))", ref): "last month",
2984+
fmt.Sprintf("AND(MONTH(%[1]s)=MONTH(TODAY()),YEAR(%[1]s)=YEAR(TODAY()))", ref): "this month",
2985+
fmt.Sprintf("AND(MONTH(%[1]s)=MONTH(TODAY())+1,OR(YEAR(%[1]s)=YEAR(TODAY()),AND(MONTH(%[1]s)=12,YEAR(%[1]s)=YEAR(TODAY())+1)))", ref): "continue month",
2986+
}[formula]; ok {
2987+
critera = c
2988+
break
2989+
}
2990+
}
2991+
return ConditionalFormatOptions{Format: c.DxfID, StopIfTrue: c.StopIfTrue, Type: "time_period", Criteria: critera}
29742992
}
29752993

29762994
// extractCondFmtText provides a function to extract conditional format
@@ -3207,9 +3225,13 @@ func (f *File) GetConditionalFormats(sheet string) (map[string][]ConditionalForm
32073225
}
32083226
for _, cf := range ws.ConditionalFormatting {
32093227
var opts []ConditionalFormatOptions
3228+
_, mastCell, err := prepareConditionalFormatRange(cf.SQRef)
3229+
if err != nil {
3230+
return conditionalFormats, err
3231+
}
32103232
for _, cr := range cf.CfRule {
32113233
if extractFunc, ok := extractContFmtFunc[cr.Type]; ok {
3212-
opts = append(opts, extractFunc(f, cr, ws.ExtLst))
3234+
opts = append(opts, extractFunc(f, mastCell, cr, ws.ExtLst))
32133235
}
32143236
}
32153237
conditionalFormats[cf.SQRef] = opts
@@ -3246,9 +3268,17 @@ func (f *File) UnsetConditionalFormat(sheet, rangeRef string) error {
32463268
if err != nil {
32473269
return err
32483270
}
3249-
for i, cf := range ws.ConditionalFormatting {
3250-
if cf.SQRef == rangeRef {
3271+
delCells, err := flatSqref(rangeRef)
3272+
if err != nil {
3273+
return err
3274+
}
3275+
for i := 0; i < len(ws.ConditionalFormatting); i++ {
3276+
if ws.ConditionalFormatting[i].SQRef, err = deleteCellsFromSqref(ws.ConditionalFormatting[i].SQRef, delCells); err != nil {
3277+
return err
3278+
}
3279+
if len(ws.ConditionalFormatting[i].SQRef) == 0 {
32513280
ws.ConditionalFormatting = append(ws.ConditionalFormatting[:i], ws.ConditionalFormatting[i+1:]...)
3281+
i--
32523282
}
32533283
}
32543284
if ws.ExtLst != nil {
@@ -3263,7 +3293,9 @@ func (f *File) UnsetConditionalFormat(sheet, rangeRef string) error {
32633293
if ext.URI == ExtURIConditionalFormattings {
32643294
decodeCondFmts := new(decodeX14ConditionalFormattingRules)
32653295
_ = f.xmlNewDecoder(strings.NewReader(ext.Content)).Decode(decodeCondFmts)
3266-
condFmtsBytes, _ = decodeCondFmts.deleteCfRule(rangeRef)
3296+
if condFmtsBytes, err = decodeCondFmts.deleteCfRule(delCells); err != nil {
3297+
return err
3298+
}
32673299
decodeExtLst.Ext[idx].Content = string(condFmtsBytes)
32683300
if len(decodeExtLst.Ext[idx].Content) == 57 { // empty x14:conditionalFormattings element
32693301
decodeExtLst.Ext = append(decodeExtLst.Ext[:idx], decodeExtLst.Ext[idx+1:]...)
@@ -3287,10 +3319,16 @@ func (f *File) UnsetConditionalFormat(sheet, rangeRef string) error {
32873319
// deleteCfRule provides a function to delete conditional formatting rule by
32883320
// given range reference and return the updated x14:conditionalFormattings
32893321
// element content.
3290-
func (r *decodeX14ConditionalFormattingRules) deleteCfRule(rangeRef string) ([]byte, error) {
3291-
condFmts := &xlsxX14ConditionalFormattings{}
3322+
func (r *decodeX14ConditionalFormattingRules) deleteCfRule(delCells map[int][][]int) ([]byte, error) {
3323+
var (
3324+
err error
3325+
condFmts = &xlsxX14ConditionalFormattings{}
3326+
)
32923327
for _, condFmt := range r.CondFmt {
3293-
if condFmt.Sqref == rangeRef {
3328+
if condFmt.Sqref, err = deleteCellsFromSqref(condFmt.Sqref, delCells); err != nil {
3329+
return nil, err
3330+
}
3331+
if len(condFmt.Sqref) == 0 {
32943332
continue
32953333
}
32963334
x14ConditionalFormatting := xlsxX14ConditionalFormatting{
@@ -3403,7 +3441,6 @@ func drawCondFmtTimePeriod(p int, ct, ref, GUID string, format *ConditionalForma
34033441
Priority: p + 1,
34043442
StopIfTrue: format.StopIfTrue,
34053443
Type: "timePeriod",
3406-
Operator: ct,
34073444
Formula: []string{
34083445
map[string]string{
34093446
"yesterday": fmt.Sprintf("FLOOR(%s,1)=TODAY()-1", ref),

0 commit comments

Comments
 (0)