Skip to content

Commit 753969d

Browse files
committed
Support creating a conditional format with an "icon sets" rule
- Improvement compatibility for the worksheet extension lists - Update unit test
1 parent 3e24060 commit 753969d

6 files changed

+245
-108
lines changed

sparkline.go

+48-57
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ package excelize
1414
import (
1515
"encoding/xml"
1616
"io"
17+
"sort"
1718
"strings"
1819
)
1920

@@ -389,15 +390,14 @@ func (f *File) addSparklineGroupByStyle(ID int) *xlsxX14SparklineGroup {
389390
// Axis | Show sparkline axis
390391
func (f *File) AddSparkline(sheet string, opts *SparklineOptions) error {
391392
var (
392-
err error
393-
ws *xlsxWorksheet
394-
sparkType string
395-
sparkTypes map[string]string
396-
specifiedSparkTypes string
397-
ok bool
398-
group *xlsxX14SparklineGroup
399-
groups *xlsxX14SparklineGroups
400-
sparklineGroupsBytes, extBytes []byte
393+
err error
394+
ws *xlsxWorksheet
395+
sparkType string
396+
sparkTypes map[string]string
397+
specifiedSparkTypes string
398+
ok bool
399+
group *xlsxX14SparklineGroup
400+
groups *xlsxX14SparklineGroups
401401
)
402402

403403
// parameter validation
@@ -434,25 +434,8 @@ func (f *File) AddSparkline(sheet string, opts *SparklineOptions) error {
434434
group.RightToLeft = opts.Reverse
435435
}
436436
f.addSparkline(opts, group)
437-
if ws.ExtLst.Ext != "" { // append mode ext
438-
if err = f.appendSparkline(ws, group, groups); err != nil {
439-
return err
440-
}
441-
} else {
442-
groups = &xlsxX14SparklineGroups{
443-
XMLNSXM: NameSpaceSpreadSheetExcel2006Main.Value,
444-
SparklineGroups: []*xlsxX14SparklineGroup{group},
445-
}
446-
if sparklineGroupsBytes, err = xml.Marshal(groups); err != nil {
447-
return err
448-
}
449-
if extBytes, err = xml.Marshal(&xlsxWorksheetExt{
450-
URI: ExtURISparklineGroups,
451-
Content: string(sparklineGroupsBytes),
452-
}); err != nil {
453-
return err
454-
}
455-
ws.ExtLst.Ext = string(extBytes)
437+
if err = f.appendSparkline(ws, group, groups); err != nil {
438+
return err
456439
}
457440
f.addSheetNameSpace(sheet, NameSpaceSpreadSheetX14)
458441
return err
@@ -504,42 +487,50 @@ func (f *File) appendSparkline(ws *xlsxWorksheet, group *xlsxX14SparklineGroup,
504487
var (
505488
err error
506489
idx int
507-
decodeExtLst *decodeWorksheetExt
490+
appendMode bool
491+
decodeExtLst = new(decodeWorksheetExt)
508492
decodeSparklineGroups *decodeX14SparklineGroups
509493
ext *xlsxWorksheetExt
510494
sparklineGroupsBytes, sparklineGroupBytes, extLstBytes []byte
511495
)
512-
decodeExtLst = new(decodeWorksheetExt)
513-
if err = f.xmlNewDecoder(strings.NewReader("<extLst>" + ws.ExtLst.Ext + "</extLst>")).
514-
Decode(decodeExtLst); err != nil && err != io.EOF {
515-
return err
516-
}
517-
for idx, ext = range decodeExtLst.Ext {
518-
if ext.URI == ExtURISparklineGroups {
519-
decodeSparklineGroups = new(decodeX14SparklineGroups)
520-
if err = f.xmlNewDecoder(strings.NewReader(ext.Content)).
521-
Decode(decodeSparklineGroups); err != nil && err != io.EOF {
522-
return err
523-
}
524-
if sparklineGroupBytes, err = xml.Marshal(group); err != nil {
525-
return err
526-
}
527-
if groups == nil {
528-
groups = &xlsxX14SparklineGroups{}
529-
}
530-
groups.XMLNSXM = NameSpaceSpreadSheetExcel2006Main.Value
531-
groups.Content = decodeSparklineGroups.Content + string(sparklineGroupBytes)
532-
if sparklineGroupsBytes, err = xml.Marshal(groups); err != nil {
533-
return err
496+
sparklineGroupBytes, _ = xml.Marshal(group)
497+
if ws.ExtLst != nil { // append mode ext
498+
if err = f.xmlNewDecoder(strings.NewReader("<extLst>" + ws.ExtLst.Ext + "</extLst>")).
499+
Decode(decodeExtLst); err != nil && err != io.EOF {
500+
return err
501+
}
502+
for idx, ext = range decodeExtLst.Ext {
503+
if ext.URI == ExtURISparklineGroups {
504+
decodeSparklineGroups = new(decodeX14SparklineGroups)
505+
if err = f.xmlNewDecoder(strings.NewReader(ext.Content)).
506+
Decode(decodeSparklineGroups); err != nil && err != io.EOF {
507+
return err
508+
}
509+
if groups == nil {
510+
groups = &xlsxX14SparklineGroups{}
511+
}
512+
groups.XMLNSXM = NameSpaceSpreadSheetExcel2006Main.Value
513+
groups.Content = decodeSparklineGroups.Content + string(sparklineGroupBytes)
514+
sparklineGroupsBytes, _ = xml.Marshal(groups)
515+
decodeExtLst.Ext[idx].Content = string(sparklineGroupsBytes)
516+
appendMode = true
534517
}
535-
decodeExtLst.Ext[idx].Content = string(sparklineGroupsBytes)
536518
}
537519
}
538-
if extLstBytes, err = xml.Marshal(decodeExtLst); err != nil {
539-
return err
540-
}
541-
ws.ExtLst = &xlsxExtLst{
542-
Ext: strings.TrimSuffix(strings.TrimPrefix(string(extLstBytes), "<extLst>"), "</extLst>"),
520+
if !appendMode {
521+
sparklineGroupsBytes, _ = xml.Marshal(&xlsxX14SparklineGroups{
522+
XMLNSXM: NameSpaceSpreadSheetExcel2006Main.Value,
523+
SparklineGroups: []*xlsxX14SparklineGroup{group},
524+
})
525+
decodeExtLst.Ext = append(decodeExtLst.Ext, &xlsxWorksheetExt{
526+
URI: ExtURISparklineGroups, Content: string(sparklineGroupsBytes),
527+
})
543528
}
529+
sort.Slice(decodeExtLst.Ext, func(i, j int) bool {
530+
return inStrSlice(extensionURIPriority, decodeExtLst.Ext[i].URI, false) <
531+
inStrSlice(extensionURIPriority, decodeExtLst.Ext[j].URI, false)
532+
})
533+
extLstBytes, err = xml.Marshal(decodeExtLst)
534+
ws.ExtLst = &xlsxExtLst{Ext: strings.TrimSuffix(strings.TrimPrefix(string(extLstBytes), "<extLst>"), "</extLst>")}
544535
return err
545536
}

sparkline_test.go

+12-12
Original file line numberDiff line numberDiff line change
@@ -264,23 +264,23 @@ func TestAddSparkline(t *testing.T) {
264264
Range: []string{"Sheet2!A3:E3"},
265265
Style: -1,
266266
}), ErrSparklineStyle.Error())
267-
267+
// Test creating a conditional format with existing extension lists
268268
ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
269269
assert.True(t, ok)
270-
ws.(*xlsxWorksheet).ExtLst.Ext = `<extLst>
271-
<ext x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main" uri="{05C60535-1F16-4fd2-B633-F4F36F0B64E0}">
272-
<x14:sparklineGroups
273-
xmlns:xm="http://schemas.microsoft.com/office/excel/2006/main">
274-
<x14:sparklineGroup>
275-
</x14:sparklines>
276-
</x14:sparklineGroup>
277-
</x14:sparklineGroups>
278-
</ext>
279-
</extLst>`
270+
ws.(*xlsxWorksheet).ExtLst = &xlsxExtLst{Ext: `
271+
<ext uri="{A8765BA9-456A-4dab-B4F3-ACF838C121DE}"><x14:slicerList /></ext>
272+
<ext uri="{05C60535-1F16-4fd2-B633-F4F36F0B64E0}"><x14:sparklineGroups /></ext>`}
273+
assert.NoError(t, f.AddSparkline("Sheet1", &SparklineOptions{
274+
Location: []string{"A3"},
275+
Range: []string{"Sheet3!A2:J2"},
276+
Type: "column",
277+
}))
278+
// Test creating a conditional format with invalid extension list characters
279+
ws.(*xlsxWorksheet).ExtLst.Ext = `<ext uri="{05C60535-1F16-4fd2-B633-F4F36F0B64E0}"><x14:sparklineGroups><x14:sparklineGroup></x14:sparklines></x14:sparklineGroup></x14:sparklineGroups></ext>`
280280
assert.EqualError(t, f.AddSparkline("Sheet1", &SparklineOptions{
281281
Location: []string{"A2"},
282282
Range: []string{"Sheet3!A1:J1"},
283-
}), "XML syntax error on line 6: element <sparklineGroup> closed by </sparklines>")
283+
}), "XML syntax error on line 1: element <sparklineGroup> closed by </sparklines>")
284284
}
285285

286286
func TestAppendSparkline(t *testing.T) {

0 commit comments

Comments
 (0)