@ -10,8 +10,10 @@
package excelize
package excelize
import (
import (
"bytes"
"encoding/xml"
"encoding/xml"
"errors"
"errors"
"io"
"strings"
"strings"
)
)
@ -386,23 +388,40 @@ func (f *File) addSparklineGroupByStyle(ID int) *xlsxX14SparklineGroup {
// ColorAxis | An RGB Color is specified as RRGGBB
// ColorAxis | An RGB Color is specified as RRGGBB
// Axis | Show sparkline axis
// Axis | Show sparkline axis
//
//
func ( f * File ) AddSparkline ( sheet string , opt * SparklineOption ) error {
func ( f * File ) AddSparkline ( sheet string , opt * SparklineOption ) ( err error ) {
var (
ws * xlsxWorksheet
sparkType string
sparkTypes map [ string ] string
specifiedSparkTypes string
ok bool
group * xlsxX14SparklineGroup
groups * xlsxX14SparklineGroups
decodeExtLst * decodeWorksheetExt
idx int
ext * xlsxWorksheetExt
decodeSparklineGroups * decodeX14SparklineGroups
sparklineGroupBytes [ ] byte
sparklineGroupsBytes [ ] byte
extLst string
extLstBytes , extBytes [ ] byte
)
// parameter validation
// parameter validation
ws , err := f . parseFormatAddSparklineSet ( sheet , opt )
if ws , err = f . parseFormatAddSparklineSet ( sheet , opt ) ; err != nil {
if err != nil {
return
return err
}
}
// Handle the sparkline type
// Handle the sparkline type
sparkType := "line"
sparkType = "line"
sparkTypes := map [ string ] string { "line" : "line" , "column" : "column" , "win_loss" : "stacked" }
sparkTypes = map [ string ] string { "line" : "line" , "column" : "column" , "win_loss" : "stacked" }
if opt . Type != "" {
if opt . Type != "" {
specifiedSparkTypes , ok := sparkTypes [ opt . Type ]
if specifiedSparkTypes , ok = sparkTypes [ opt . Type ] ; ! ok {
if ! ok {
err = errors . New ( "parameter 'Type' must be 'line', 'column' or 'win_loss'" )
return errors . New ( "parameter 'Type' must be 'line', 'column' or 'win_loss'" )
return
}
}
sparkType = specifiedSparkTypes
sparkType = specifiedSparkTypes
}
}
group := f . addSparklineGroupByStyle ( opt . Style )
group = f . addSparklineGroupByStyle ( opt . Style )
group . Type = sparkType
group . Type = sparkType
group . ColorAxis = & xlsxColor { RGB : "FF000000" }
group . ColorAxis = & xlsxColor { RGB : "FF000000" }
group . DisplayEmptyCellsAs = "gap"
group . DisplayEmptyCellsAs = "gap"
@ -423,43 +442,57 @@ func (f *File) AddSparkline(sheet string, opt *SparklineOption) error {
}
}
f . addSparkline ( opt , group )
f . addSparkline ( opt , group )
if ws . ExtLst . Ext != "" { // append mode ext
if ws . ExtLst . Ext != "" { // append mode ext
decodeExtLst := decodeWorksheetExt { }
decodeExtLst = new ( decodeWorksheetExt )
err = xml . Unmarshal ( [ ] byte ( "<extLst>" + ws . ExtLst . Ext + "</extLst>" ) , & decodeExtLst )
if err = f . xmlNewDecoder ( bytes . NewReader ( [ ] byte ( "<extLst>" + ws . ExtLst . Ext + "</extLst>" ) ) ) .
if err != nil {
Decode ( decodeExtLst ) ; err != nil && err != io . EOF {
return err
return
}
}
for idx , ext : = range decodeExtLst . Ext {
for idx , ext = range decodeExtLst . Ext {
if ext . URI == ExtURISparklineGroups {
if ext . URI == ExtURISparklineGroups {
decodeSparklineGroups := decodeX14SparklineGroups { }
decodeSparklineGroups = new ( decodeX14SparklineGroups )
_ = xml . Unmarshal ( [ ] byte ( ext . Content ) , & decodeSparklineGroups )
if err = f . xmlNewDecoder ( bytes . NewReader ( [ ] byte ( ext . Content ) ) ) .
sparklineGroupBytes , _ := xml . Marshal ( group )
Decode ( decodeSparklineGroups ) ; err != nil && err != io . EOF {
groups := xlsxX14SparklineGroups {
return
}
if sparklineGroupBytes , err = xml . Marshal ( group ) ; err != nil {
return
}
groups = & xlsxX14SparklineGroups {
XMLNSXM : NameSpaceSpreadSheetExcel2006Main ,
XMLNSXM : NameSpaceSpreadSheetExcel2006Main ,
Content : decodeSparklineGroups . Content + string ( sparklineGroupBytes ) ,
Content : decodeSparklineGroups . Content + string ( sparklineGroupBytes ) ,
}
}
sparklineGroupsBytes , _ := xml . Marshal ( groups )
if sparklineGroupsBytes , err = xml . Marshal ( groups ) ; err != nil {
return
}
decodeExtLst . Ext [ idx ] . Content = string ( sparklineGroupsBytes )
decodeExtLst . Ext [ idx ] . Content = string ( sparklineGroupsBytes )
}
}
}
}
extLstBytes , _ := xml . Marshal ( decodeExtLst )
if extLstBytes , err = xml . Marshal ( decodeExtLst ) ; err != nil {
extLst := string ( extLstBytes )
return
}
extLst = string ( extLstBytes )
ws . ExtLst = & xlsxExtLst {
ws . ExtLst = & xlsxExtLst {
Ext : strings . TrimSuffix ( strings . TrimPrefix ( extLst , "<extLst>" ) , "</extLst>" ) ,
Ext : strings . TrimSuffix ( strings . TrimPrefix ( extLst , "<extLst>" ) , "</extLst>" ) ,
}
}
} else {
} else {
groups := xlsxX14SparklineGroups {
groups = & xlsxX14SparklineGroups {
XMLNSXM : NameSpaceSpreadSheetExcel2006Main ,
XMLNSXM : NameSpaceSpreadSheetExcel2006Main ,
SparklineGroups : [ ] * xlsxX14SparklineGroup { group } ,
SparklineGroups : [ ] * xlsxX14SparklineGroup { group } ,
}
}
sparklineGroupsBytes , _ := xml . Marshal ( groups )
if sparklineGroupsBytes , err = xml . Marshal ( groups ) ; err != nil {
extLst := xlsxWorksheetExt {
return
}
ext = & xlsxWorksheetExt {
URI : ExtURISparklineGroups ,
URI : ExtURISparklineGroups ,
Content : string ( sparklineGroupsBytes ) ,
Content : string ( sparklineGroupsBytes ) ,
}
}
extBytes , _ := xml . Marshal ( extLst )
if extBytes , err = xml . Marshal ( ext ) ; err != nil {
return
}
ws . ExtLst . Ext = string ( extBytes )
ws . ExtLst . Ext = string ( extBytes )
}
}
return nil
return
}
}
// parseFormatAddSparklineSet provides a function to validate sparkline
// parseFormatAddSparklineSet provides a function to validate sparkline