@@ -1374,6 +1374,26 @@ var (
1374
1374
"5Quarters" : cfvo5 ,
1375
1375
"5Rating" : cfvo5 ,
1376
1376
}
1377
+
1378
+ // cfvo3 defined the icon set conditional formatting rules.
1379
+ x14cfvo3 = & xlsxX14CfRule {IconSet : & xlsx14IconSet {Cfvo : []* xlsx14Cfvo {
1380
+ {Type : "percent" , Val : "0" },
1381
+ {Type : "percent" , Val : "33" },
1382
+ {Type : "percent" , Val : "67" },
1383
+ }}}
1384
+ // cfvo5 defined the icon set conditional formatting rules.
1385
+ x14cfvo5 = & xlsxX14CfRule {IconSet : & xlsx14IconSet {Cfvo : []* xlsx14Cfvo {
1386
+ {Type : "percent" , Val : "0" },
1387
+ {Type : "percent" , Val : "20" },
1388
+ {Type : "percent" , Val : "40" },
1389
+ {Type : "percent" , Val : "60" },
1390
+ {Type : "percent" , Val : "80" },
1391
+ }}}
1392
+ condFmtNewIconSetPresets = map [string ]* xlsxX14CfRule {
1393
+ "3Stars" : x14cfvo3 ,
1394
+ "3Triangles" : x14cfvo3 ,
1395
+ "5Boxes" : x14cfvo5 ,
1396
+ }
1377
1397
)
1378
1398
1379
1399
// colorChoice returns a hex color code from the actual color values.
@@ -2764,17 +2784,20 @@ func (f *File) SetCellStyle(sheet, topLeftCell, bottomRightCell string, styleID
2764
2784
// 3ArrowsGray
2765
2785
// 3Flags
2766
2786
// 3Signs
2787
+ // 3Stars
2767
2788
// 3Symbols
2768
2789
// 3Symbols2
2769
2790
// 3TrafficLights1
2770
2791
// 3TrafficLights2
2792
+ // 3Triangles
2771
2793
// 4Arrows
2772
2794
// 4ArrowsGray
2773
2795
// 4Rating
2774
2796
// 4RedToBlack
2775
2797
// 4TrafficLights
2776
2798
// 5Arrows
2777
2799
// 5ArrowsGray
2800
+ // 5Boxes
2778
2801
// 5Quarters
2779
2802
// 5Rating
2780
2803
//
@@ -2802,6 +2825,7 @@ func (f *File) SetConditionalFormat(sheet, rangeRef string, opts []ConditionalFo
2802
2825
}
2803
2826
var (
2804
2827
cfRule []* xlsxCfRule
2828
+ x14CfRule []* xlsxX14CfRule
2805
2829
noCriteriaTypes = []string {
2806
2830
"containsBlanks" ,
2807
2831
"notContainsBlanks" ,
@@ -2825,16 +2849,15 @@ func (f *File) SetConditionalFormat(sheet, rangeRef string, opts []ConditionalFo
2825
2849
priority := rules + i
2826
2850
rule , x14rule := drawFunc (priority , ct , mastCell ,
2827
2851
fmt .Sprintf ("{00000000-0000-0000-%04X-%012X}" , f .getSheetID (sheet ), priority ), & opt )
2828
- if rule == nil {
2852
+ if rule == nil && x14rule == nil {
2829
2853
return ErrParameterInvalid
2830
2854
}
2831
2855
if x14rule != nil {
2832
- if err = f . appendCfRule ( ws , x14rule ); err != nil {
2833
- return err
2834
- }
2835
- f . addSheetNameSpace ( sheet , NameSpaceSpreadSheetX14 )
2856
+ x14CfRule = append ( x14CfRule , x14rule )
2857
+ }
2858
+ if rule != nil {
2859
+ cfRule = append ( cfRule , rule )
2836
2860
}
2837
- cfRule = append (cfRule , rule )
2838
2861
continue
2839
2862
}
2840
2863
}
@@ -2843,10 +2866,19 @@ func (f *File) SetConditionalFormat(sheet, rangeRef string, opts []ConditionalFo
2843
2866
return ErrParameterInvalid
2844
2867
}
2845
2868
2846
- ws .ConditionalFormatting = append (ws .ConditionalFormatting , & xlsxConditionalFormatting {
2847
- SQRef : SQRef ,
2848
- CfRule : cfRule ,
2849
- })
2869
+ if len (cfRule ) > 0 {
2870
+ ws .ConditionalFormatting = append (ws .ConditionalFormatting , & xlsxConditionalFormatting {
2871
+ SQRef : SQRef ,
2872
+ CfRule : cfRule ,
2873
+ })
2874
+ }
2875
+
2876
+ if len (x14CfRule ) > 0 {
2877
+ if err = f .appendCfRule (ws , x14CfRule , SQRef ); err != nil {
2878
+ return err
2879
+ }
2880
+ f .addSheetNameSpace (sheet , NameSpaceSpreadSheetX14 )
2881
+ }
2850
2882
return err
2851
2883
}
2852
2884
@@ -2892,7 +2924,7 @@ func prepareConditionalFormatRange(rangeRef string) (string, string, error) {
2892
2924
}
2893
2925
2894
2926
// appendCfRule provides a function to append rules to conditional formatting.
2895
- func (f * File ) appendCfRule (ws * xlsxWorksheet , rule * xlsxX14CfRule ) error {
2927
+ func (f * File ) appendCfRule (ws * xlsxWorksheet , rules [] * xlsxX14CfRule , SQRef string ) error {
2896
2928
var (
2897
2929
err error
2898
2930
idx int
@@ -2904,7 +2936,7 @@ func (f *File) appendCfRule(ws *xlsxWorksheet, rule *xlsxX14CfRule) error {
2904
2936
condFmtBytes , condFmtsBytes , extLstBytes []byte
2905
2937
)
2906
2938
condFmtBytes , _ = xml .Marshal ([]* xlsxX14ConditionalFormatting {
2907
- {XMLNSXM : NameSpaceSpreadSheetExcel2006Main .Value , CfRule : [] * xlsxX14CfRule { rule } },
2939
+ {XMLNSXM : NameSpaceSpreadSheetExcel2006Main .Value , CfRule : rules , SQRef : SQRef },
2908
2940
})
2909
2941
if ws .ExtLst != nil { // append mode ext
2910
2942
if err = f .xmlNewDecoder (strings .NewReader ("<extLst>" + ws .ExtLst .Ext + "</extLst>" )).
@@ -3155,6 +3187,20 @@ func (f *File) extractCondFmtExp(c *xlsxCfRule, extLst *xlsxExtLst) ConditionalF
3155
3187
return format
3156
3188
}
3157
3189
3190
+ // extractCondFmtIconSetRule provides a function to extract conditional format
3191
+ // settings for icon set by given conditional formatting rule extension list.
3192
+ func (f * File ) extractCondFmtIconSetRule (c * decodeX14CfRule ) ConditionalFormatOptions {
3193
+ format := ConditionalFormatOptions {Type : "icon_set" }
3194
+ if c .IconSet != nil {
3195
+ if c .IconSet .ShowValue != nil {
3196
+ format .IconsOnly = ! * c .IconSet .ShowValue
3197
+ }
3198
+ format .IconStyle = c .IconSet .IconSet
3199
+ format .ReverseIcons = c .IconSet .Reverse
3200
+ }
3201
+ return format
3202
+ }
3203
+
3158
3204
// extractCondFmtIconSet provides a function to extract conditional format
3159
3205
// settings for icon sets by given conditional formatting rule.
3160
3206
func (f * File ) extractCondFmtIconSet (c * xlsxCfRule , extLst * xlsxExtLst ) ConditionalFormatOptions {
@@ -3186,6 +3232,29 @@ func (f *File) GetConditionalFormats(sheet string) (map[string][]ConditionalForm
3186
3232
}
3187
3233
conditionalFormats [cf .SQRef ] = opts
3188
3234
}
3235
+ if ws .ExtLst != nil {
3236
+ decodeExtLst := new (decodeExtLst )
3237
+ if err = f .xmlNewDecoder (strings .NewReader ("<extLst>" + ws .ExtLst .Ext + "</extLst>" )).
3238
+ Decode (decodeExtLst ); err != nil && err != io .EOF {
3239
+ return conditionalFormats , err
3240
+ }
3241
+ for _ , ext := range decodeExtLst .Ext {
3242
+ if ext .URI == ExtURIConditionalFormattings {
3243
+ decodeCondFmts := new (decodeX14ConditionalFormattingRules )
3244
+ _ = f .xmlNewDecoder (strings .NewReader (ext .Content )).Decode (decodeCondFmts )
3245
+ for _ , condFmt := range decodeCondFmts .CondFmt {
3246
+ var opts []ConditionalFormatOptions
3247
+ for _ , rule := range condFmt .CfRule {
3248
+ if rule .Type == "iconSet" {
3249
+ opts = append (opts , f .extractCondFmtIconSetRule (rule ))
3250
+ }
3251
+ }
3252
+ conditionalFormats [condFmt .SQRef ] = append (conditionalFormats [condFmt .SQRef ], opts ... )
3253
+ }
3254
+ }
3255
+ }
3256
+ }
3257
+
3189
3258
return conditionalFormats , err
3190
3259
}
3191
3260
@@ -3467,7 +3536,16 @@ func drawCondFmtNoBlanks(p int, ct, ref, GUID string, format *ConditionalFormatO
3467
3536
func drawCondFmtIconSet (p int , ct , ref , GUID string , format * ConditionalFormatOptions ) (* xlsxCfRule , * xlsxX14CfRule ) {
3468
3537
cfRule , ok := condFmtIconSetPresets [format .IconStyle ]
3469
3538
if ! ok {
3470
- return nil , nil
3539
+ x14CfRule , ok := condFmtNewIconSetPresets [format .IconStyle ]
3540
+ if ! ok {
3541
+ return nil , nil
3542
+ }
3543
+ x14CfRule .Priority = p + 1
3544
+ x14CfRule .IconSet .IconSet = format .IconStyle
3545
+ x14CfRule .IconSet .Reverse = format .ReverseIcons
3546
+ x14CfRule .IconSet .ShowValue = boolPtr (! format .IconsOnly )
3547
+ x14CfRule .Type = validType [format .Type ]
3548
+ return nil , x14CfRule
3471
3549
}
3472
3550
cfRule .Priority = p + 1
3473
3551
cfRule .IconSet .IconSet = format .IconStyle
0 commit comments