Skip to content

Commit c2f09da

Browse files
committed
WIP add support for new icon sets
1 parent 3ca60f8 commit c2f09da

File tree

3 files changed

+86
-16
lines changed

3 files changed

+86
-16
lines changed

styles.go

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,6 +1374,26 @@ var (
13741374
"5Quarters": cfvo5,
13751375
"5Rating": cfvo5,
13761376
}
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+
}
13771397
)
13781398

13791399
// colorChoice returns a hex color code from the actual color values.
@@ -2764,17 +2784,20 @@ func (f *File) SetCellStyle(sheet, topLeftCell, bottomRightCell string, styleID
27642784
// 3ArrowsGray
27652785
// 3Flags
27662786
// 3Signs
2787+
// 3Stars
27672788
// 3Symbols
27682789
// 3Symbols2
27692790
// 3TrafficLights1
27702791
// 3TrafficLights2
2792+
// 3Triangles
27712793
// 4Arrows
27722794
// 4ArrowsGray
27732795
// 4Rating
27742796
// 4RedToBlack
27752797
// 4TrafficLights
27762798
// 5Arrows
27772799
// 5ArrowsGray
2800+
// 5Boxes
27782801
// 5Quarters
27792802
// 5Rating
27802803
//
@@ -2802,6 +2825,7 @@ func (f *File) SetConditionalFormat(sheet, rangeRef string, opts []ConditionalFo
28022825
}
28032826
var (
28042827
cfRule []*xlsxCfRule
2828+
x14CfRule []*xlsxX14CfRule
28052829
noCriteriaTypes = []string{
28062830
"containsBlanks",
28072831
"notContainsBlanks",
@@ -2825,16 +2849,15 @@ func (f *File) SetConditionalFormat(sheet, rangeRef string, opts []ConditionalFo
28252849
priority := rules + i
28262850
rule, x14rule := drawFunc(priority, ct, mastCell,
28272851
fmt.Sprintf("{00000000-0000-0000-%04X-%012X}", f.getSheetID(sheet), priority), &opt)
2828-
if rule == nil {
2852+
if rule == nil && x14rule == nil {
28292853
return ErrParameterInvalid
28302854
}
28312855
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)
28362860
}
2837-
cfRule = append(cfRule, rule)
28382861
continue
28392862
}
28402863
}
@@ -2843,10 +2866,19 @@ func (f *File) SetConditionalFormat(sheet, rangeRef string, opts []ConditionalFo
28432866
return ErrParameterInvalid
28442867
}
28452868

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+
}
28502882
return err
28512883
}
28522884

@@ -2892,7 +2924,7 @@ func prepareConditionalFormatRange(rangeRef string) (string, string, error) {
28922924
}
28932925

28942926
// 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 {
28962928
var (
28972929
err error
28982930
idx int
@@ -2904,7 +2936,7 @@ func (f *File) appendCfRule(ws *xlsxWorksheet, rule *xlsxX14CfRule) error {
29042936
condFmtBytes, condFmtsBytes, extLstBytes []byte
29052937
)
29062938
condFmtBytes, _ = xml.Marshal([]*xlsxX14ConditionalFormatting{
2907-
{XMLNSXM: NameSpaceSpreadSheetExcel2006Main.Value, CfRule: []*xlsxX14CfRule{rule}},
2939+
{XMLNSXM: NameSpaceSpreadSheetExcel2006Main.Value, CfRule: rules, SQRef: SQRef},
29082940
})
29092941
if ws.ExtLst != nil { // append mode ext
29102942
if err = f.xmlNewDecoder(strings.NewReader("<extLst>" + ws.ExtLst.Ext + "</extLst>")).
@@ -3467,7 +3499,16 @@ func drawCondFmtNoBlanks(p int, ct, ref, GUID string, format *ConditionalFormatO
34673499
func drawCondFmtIconSet(p int, ct, ref, GUID string, format *ConditionalFormatOptions) (*xlsxCfRule, *xlsxX14CfRule) {
34683500
cfRule, ok := condFmtIconSetPresets[format.IconStyle]
34693501
if !ok {
3470-
return nil, nil
3502+
x14CfRule, ok := condFmtNewIconSetPresets[format.IconStyle]
3503+
if !ok {
3504+
return nil, nil
3505+
}
3506+
x14CfRule.Priority = p + 1
3507+
x14CfRule.IconSet.IconSet = format.IconStyle
3508+
x14CfRule.IconSet.Reverse = format.ReverseIcons
3509+
x14CfRule.IconSet.ShowValue = boolPtr(!format.IconsOnly)
3510+
x14CfRule.Type = validType[format.Type]
3511+
return nil, x14CfRule
34713512
}
34723513
cfRule.Priority = p + 1
34733514
cfRule.IconSet.IconSet = format.IconStyle

styles_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,15 @@ func TestSetConditionalFormat(t *testing.T) {
177177
for _, ref := range []string{"A1:A2", "B1:B2"} {
178178
assert.NoError(t, f.SetConditionalFormat("Sheet1", ref, condFmts))
179179
}
180+
// Test creating a conditional format with a "new" icon set
181+
f = NewFile()
182+
condFmts = []ConditionalFormatOptions{
183+
{Type: "icon_set", IconStyle: "3Triangles"},
184+
}
185+
for _, ref := range []string{"A1:A2", "B1:B2"} {
186+
assert.NoError(t, f.SetConditionalFormat("Sheet1", ref, condFmts))
187+
}
188+
180189
f = NewFile()
181190
// Test creating a conditional format without cell reference
182191
assert.Equal(t, ErrParameterRequired, f.SetConditionalFormat("Sheet1", "", nil))
@@ -274,6 +283,7 @@ func TestGetConditionalFormats(t *testing.T) {
274283
{{Type: "errors", Format: intPtr(1)}},
275284
{{Type: "no_errors", Format: intPtr(1)}},
276285
{{Type: "icon_set", IconStyle: "3Arrows", ReverseIcons: true, IconsOnly: true}},
286+
// TODO: {{Type: "icon_set", IconStyle: "3Triangles", ReverseIcons: true, IconsOnly: true}},
277287
} {
278288
f := NewFile()
279289
err := f.SetConditionalFormat("Sheet1", "A2:A1,B:B,2:2", format)

xmlWorksheet.go

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -772,13 +772,16 @@ type xlsxX14ConditionalFormatting struct {
772772
XMLName xml.Name `xml:"x14:conditionalFormatting"`
773773
XMLNSXM string `xml:"xmlns:xm,attr"`
774774
CfRule []*xlsxX14CfRule `xml:"x14:cfRule"`
775+
SQRef string `xml:"xm:sqref"`
775776
}
776777

777778
// xlsxX14CfRule directly maps the cfRule element.
778779
type xlsxX14CfRule struct {
779-
Type string `xml:"type,attr,omitempty"`
780-
ID string `xml:"id,attr,omitempty"`
781-
DataBar *xlsx14DataBar `xml:"x14:dataBar"`
780+
Type string `xml:"type,attr,omitempty"`
781+
ID string `xml:"id,attr,omitempty"`
782+
Priority int `xml:"priority,attr,omitempty"`
783+
DataBar *xlsx14DataBar `xml:"x14:dataBar"`
784+
IconSet *xlsx14IconSet `xml:"x14:iconSet"`
782785
}
783786

784787
// xlsx14DataBar directly maps the dataBar element.
@@ -795,6 +798,22 @@ type xlsx14DataBar struct {
795798
AxisColor *xlsxColor `xml:"x14:axisColor"`
796799
}
797800

801+
// xlsxIconSet (Icon Set) describes an icon set conditional formatting rule.
802+
type xlsx14IconSet struct {
803+
Cfvo []*xlsx14Cfvo `xml:"x14:cfvo"`
804+
IconSet string `xml:"iconSet,attr,omitempty"`
805+
ShowValue *bool `xml:"showValue,attr"`
806+
Reverse bool `xml:"reverse,attr,omitempty"`
807+
}
808+
809+
// cfvo (Conditional Format Value Object) describes the values of the
810+
// interpolation points in a gradient scale.
811+
type xlsx14Cfvo struct {
812+
Gte bool `xml:"gte,attr,omitempty"`
813+
Type string `xml:"type,attr,omitempty"`
814+
Val string `xml:"xm:f"`
815+
}
816+
798817
// xlsxX14SparklineGroups directly maps the sparklineGroups element.
799818
type xlsxX14SparklineGroups struct {
800819
XMLName xml.Name `xml:"x14:sparklineGroups"`

0 commit comments

Comments
 (0)