forked from p30928647/excelize
- Support creating a conditional format with a "stop if true" rule - Support set border color and create solid color for the color data bar - Fix incorrect cell type when modifying string cell with the time number - Update unit test for the add pivot table to avoid pivot table range overlap
This commit is contained in:
parent
1f69f6b24a
commit
3e2406096f
2
cell.go
2
cell.go
|
@ -527,7 +527,7 @@ func (c *xlsxC) setCellDefault(value string) {
|
||||||
c.T, c.V, c.IS = value, value, nil
|
c.T, c.V, c.IS = value, value, nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.V = value
|
c.T, c.V = "", value
|
||||||
}
|
}
|
||||||
|
|
||||||
// getCellDate parse cell value which contains a date in the ISO 8601 format.
|
// getCellDate parse cell value which contains a date in the ISO 8601 format.
|
||||||
|
|
|
@ -305,7 +305,7 @@ var (
|
||||||
monthNamesYiSuffix = []string{"\ua2cd\ua1aa", "\ua44d\ua1aa", "\ua315\ua1aa", "\ua1d6\ua1aa", "\ua26c\ua1aa", "\ua0d8\ua1aa", "\ua3c3\ua1aa", "\ua246\ua1aa", "\ua22c\ua1aa", "\ua2b0\ua1aa", "\ua2b0\ua2aa\ua1aa", "\ua2b0\ua44b\ua1aa"}
|
monthNamesYiSuffix = []string{"\ua2cd\ua1aa", "\ua44d\ua1aa", "\ua315\ua1aa", "\ua1d6\ua1aa", "\ua26c\ua1aa", "\ua0d8\ua1aa", "\ua3c3\ua1aa", "\ua246\ua1aa", "\ua22c\ua1aa", "\ua2b0\ua1aa", "\ua2b0\ua2aa\ua1aa", "\ua2b0\ua44b\ua1aa"}
|
||||||
// monthNamesZulu list the month names in the Zulu.
|
// monthNamesZulu list the month names in the Zulu.
|
||||||
monthNamesZulu = []string{"Januwari", "Febhuwari", "Mashi", "Ephreli", "Meyi", "Juni", "Julayi", "Agasti", "Septemba", "Okthoba", "Novemba", "Disemba"}
|
monthNamesZulu = []string{"Januwari", "Febhuwari", "Mashi", "Ephreli", "Meyi", "Juni", "Julayi", "Agasti", "Septemba", "Okthoba", "Novemba", "Disemba"}
|
||||||
// monthNamesZuluAbbr list teh month name abbreviations in Zulu
|
// monthNamesZuluAbbr list the month name abbreviations in Zulu
|
||||||
monthNamesZuluAbbr = []string{"Jan", "Feb", "Mas", "Eph", "Mey", "Jun", "Jul", "Agas", "Sep", "Okt", "Nov", "Dis"}
|
monthNamesZuluAbbr = []string{"Jan", "Feb", "Mas", "Eph", "Mey", "Jun", "Jul", "Agas", "Sep", "Okt", "Nov", "Dis"}
|
||||||
// apFmtAfrikaans defined the AM/PM name in the Afrikaans.
|
// apFmtAfrikaans defined the AM/PM name in the Afrikaans.
|
||||||
apFmtAfrikaans = "vm./nm."
|
apFmtAfrikaans = "vm./nm."
|
||||||
|
|
|
@ -70,7 +70,7 @@ func TestAddPivotTable(t *testing.T) {
|
||||||
}))
|
}))
|
||||||
assert.NoError(t, f.AddPivotTable(&PivotTableOptions{
|
assert.NoError(t, f.AddPivotTable(&PivotTableOptions{
|
||||||
DataRange: "Sheet1!$A$1:$E$31",
|
DataRange: "Sheet1!$A$1:$E$31",
|
||||||
PivotTableRange: "Sheet1!$G$37:$W$50",
|
PivotTableRange: "Sheet1!$G$39:$W$52",
|
||||||
Rows: []PivotTableField{{Data: "Month"}},
|
Rows: []PivotTableField{{Data: "Month"}},
|
||||||
Columns: []PivotTableField{{Data: "Region", DefaultSubtotal: true}, {Data: "Year"}},
|
Columns: []PivotTableField{{Data: "Region", DefaultSubtotal: true}, {Data: "Year"}},
|
||||||
Data: []PivotTableField{{Data: "Sales", Subtotal: "CountNums", Name: "Summarize by CountNums"}},
|
Data: []PivotTableField{{Data: "Sales", Subtotal: "CountNums", Name: "Summarize by CountNums"}},
|
||||||
|
|
203
styles.go
203
styles.go
|
@ -3190,8 +3190,21 @@ func (f *File) SetCellStyle(sheet, hCell, vCell string, styleID int) error {
|
||||||
// MaxColor - Same as MinColor, see above.
|
// MaxColor - Same as MinColor, see above.
|
||||||
//
|
//
|
||||||
// BarColor - Used for data_bar. Same as MinColor, see above.
|
// BarColor - Used for data_bar. Same as MinColor, see above.
|
||||||
|
//
|
||||||
|
// BarBorderColor - Used for sets the color for the border line of a data bar,
|
||||||
|
// this is only visible in Excel 2010 and later.
|
||||||
|
//
|
||||||
|
// BarOnly - Used for displays a bar data but not the data in the cells.
|
||||||
|
//
|
||||||
|
// BarSolid - Used for turns on a solid (non-gradient) fill for data bars, this
|
||||||
|
// is only visible in Excel 2010 and later.
|
||||||
|
//
|
||||||
|
// StopIfTrue - used to set the "stop if true" feature of a conditional
|
||||||
|
// formatting rule when more than one rule is applied to a cell or a range of
|
||||||
|
// cells. When this parameter is set then subsequent rules are not evaluated
|
||||||
|
// if the current rule is true.
|
||||||
func (f *File) SetConditionalFormat(sheet, rangeRef string, opts []ConditionalFormatOptions) error {
|
func (f *File) SetConditionalFormat(sheet, rangeRef string, opts []ConditionalFormatOptions) error {
|
||||||
drawContFmtFunc := map[string]func(p int, ct string, fmtCond *ConditionalFormatOptions) *xlsxCfRule{
|
drawContFmtFunc := map[string]func(p int, ct, GUID string, fmtCond *ConditionalFormatOptions) (*xlsxCfRule, *xlsxX14CfRule){
|
||||||
"cellIs": drawCondFmtCellIs,
|
"cellIs": drawCondFmtCellIs,
|
||||||
"top10": drawCondFmtTop10,
|
"top10": drawCondFmtTop10,
|
||||||
"aboveAverage": drawCondFmtAboveAverage,
|
"aboveAverage": drawCondFmtAboveAverage,
|
||||||
|
@ -3207,6 +3220,12 @@ func (f *File) SetConditionalFormat(sheet, rangeRef string, opts []ConditionalFo
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// Create a pseudo GUID for each unique rule.
|
||||||
|
var rules int
|
||||||
|
for _, cf := range ws.ConditionalFormatting {
|
||||||
|
rules += len(cf.CfRule)
|
||||||
|
}
|
||||||
|
GUID := fmt.Sprintf("{00000000-0000-0000-%04X-%012X}", f.getSheetID(sheet), rules)
|
||||||
var cfRule []*xlsxCfRule
|
var cfRule []*xlsxCfRule
|
||||||
for p, v := range opts {
|
for p, v := range opts {
|
||||||
var vt, ct string
|
var vt, ct string
|
||||||
|
@ -3219,7 +3238,14 @@ func (f *File) SetConditionalFormat(sheet, rangeRef string, opts []ConditionalFo
|
||||||
if ok || vt == "expression" {
|
if ok || vt == "expression" {
|
||||||
drawFunc, ok := drawContFmtFunc[vt]
|
drawFunc, ok := drawContFmtFunc[vt]
|
||||||
if ok {
|
if ok {
|
||||||
cfRule = append(cfRule, drawFunc(p, ct, &v))
|
rule, x14rule := drawFunc(p, ct, GUID, &v)
|
||||||
|
if x14rule != nil {
|
||||||
|
if err = f.appendCfRule(ws, x14rule); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f.addSheetNameSpace(sheet, NameSpaceSpreadSheetX14)
|
||||||
|
}
|
||||||
|
cfRule = append(cfRule, rule)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3232,11 +3258,64 @@ func (f *File) SetConditionalFormat(sheet, rangeRef string, opts []ConditionalFo
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// appendCfRule provides a function to append rules to conditional formatting.
|
||||||
|
func (f *File) appendCfRule(ws *xlsxWorksheet, rule *xlsxX14CfRule) error {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
idx int
|
||||||
|
decodeExtLst *decodeWorksheetExt
|
||||||
|
condFmts *xlsxX14ConditionalFormattings
|
||||||
|
decodeCondFmts *decodeX14ConditionalFormattings
|
||||||
|
ext *xlsxWorksheetExt
|
||||||
|
condFmtBytes, condFmtsBytes, extLstBytes, extBytes []byte
|
||||||
|
)
|
||||||
|
if ws.ExtLst != nil { // append mode ext
|
||||||
|
decodeExtLst = new(decodeWorksheetExt)
|
||||||
|
if err = f.xmlNewDecoder(strings.NewReader("<extLst>" + ws.ExtLst.Ext + "</extLst>")).
|
||||||
|
Decode(decodeExtLst); err != nil && err != io.EOF {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for idx, ext = range decodeExtLst.Ext {
|
||||||
|
if ext.URI == ExtURIConditionalFormattings {
|
||||||
|
decodeCondFmts = new(decodeX14ConditionalFormattings)
|
||||||
|
_ = f.xmlNewDecoder(strings.NewReader(ext.Content)).Decode(decodeCondFmts)
|
||||||
|
condFmtBytes, _ = xml.Marshal([]*xlsxX14ConditionalFormatting{
|
||||||
|
{
|
||||||
|
XMLNSXM: NameSpaceSpreadSheetExcel2006Main.Value,
|
||||||
|
CfRule: []*xlsxX14CfRule{rule},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if condFmts == nil {
|
||||||
|
condFmts = &xlsxX14ConditionalFormattings{}
|
||||||
|
}
|
||||||
|
condFmts.Content = decodeCondFmts.Content + string(condFmtBytes)
|
||||||
|
condFmtsBytes, _ = xml.Marshal(condFmts)
|
||||||
|
decodeExtLst.Ext[idx].Content = string(condFmtsBytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extLstBytes, _ = xml.Marshal(decodeExtLst)
|
||||||
|
ws.ExtLst = &xlsxExtLst{
|
||||||
|
Ext: strings.TrimSuffix(strings.TrimPrefix(string(extLstBytes), "<extLst>"), "</extLst>"),
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
condFmtBytes, _ = xml.Marshal([]*xlsxX14ConditionalFormatting{
|
||||||
|
{XMLNSXM: NameSpaceSpreadSheetExcel2006Main.Value, CfRule: []*xlsxX14CfRule{rule}},
|
||||||
|
})
|
||||||
|
condFmtsBytes, _ = xml.Marshal(&xlsxX14ConditionalFormattings{Content: string(condFmtBytes)})
|
||||||
|
extBytes, err = xml.Marshal(&xlsxWorksheetExt{
|
||||||
|
URI: ExtURIConditionalFormattings,
|
||||||
|
Content: string(condFmtsBytes),
|
||||||
|
})
|
||||||
|
ws.ExtLst = &xlsxExtLst{Ext: strings.TrimSuffix(strings.TrimPrefix(string(extBytes), "<extLst>"), "</extLst>")}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// extractCondFmtCellIs provides a function to extract conditional format
|
// extractCondFmtCellIs provides a function to extract conditional format
|
||||||
// settings for cell value (include between, not between, equal, not equal,
|
// settings for cell value (include between, not between, equal, not equal,
|
||||||
// greater than and less than) by given conditional formatting rule.
|
// greater than and less than) by given conditional formatting rule.
|
||||||
func extractCondFmtCellIs(c *xlsxCfRule) ConditionalFormatOptions {
|
func extractCondFmtCellIs(c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
|
||||||
format := ConditionalFormatOptions{Type: "cell", Criteria: operatorType[c.Operator], Format: *c.DxfID}
|
format := ConditionalFormatOptions{StopIfTrue: c.StopIfTrue, Type: "cell", Criteria: operatorType[c.Operator], Format: *c.DxfID}
|
||||||
if len(c.Formula) == 2 {
|
if len(c.Formula) == 2 {
|
||||||
format.Minimum, format.Maximum = c.Formula[0], c.Formula[1]
|
format.Minimum, format.Maximum = c.Formula[0], c.Formula[1]
|
||||||
return format
|
return format
|
||||||
|
@ -3248,8 +3327,9 @@ func extractCondFmtCellIs(c *xlsxCfRule) ConditionalFormatOptions {
|
||||||
// extractCondFmtTop10 provides a function to extract conditional format
|
// extractCondFmtTop10 provides a function to extract conditional format
|
||||||
// settings for top N (default is top 10) by given conditional formatting
|
// settings for top N (default is top 10) by given conditional formatting
|
||||||
// rule.
|
// rule.
|
||||||
func extractCondFmtTop10(c *xlsxCfRule) ConditionalFormatOptions {
|
func extractCondFmtTop10(c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
|
||||||
format := ConditionalFormatOptions{
|
format := ConditionalFormatOptions{
|
||||||
|
StopIfTrue: c.StopIfTrue,
|
||||||
Type: "top",
|
Type: "top",
|
||||||
Criteria: "=",
|
Criteria: "=",
|
||||||
Format: *c.DxfID,
|
Format: *c.DxfID,
|
||||||
|
@ -3265,8 +3345,9 @@ func extractCondFmtTop10(c *xlsxCfRule) ConditionalFormatOptions {
|
||||||
// extractCondFmtAboveAverage provides a function to extract conditional format
|
// extractCondFmtAboveAverage provides a function to extract conditional format
|
||||||
// settings for above average and below average by given conditional formatting
|
// settings for above average and below average by given conditional formatting
|
||||||
// rule.
|
// rule.
|
||||||
func extractCondFmtAboveAverage(c *xlsxCfRule) ConditionalFormatOptions {
|
func extractCondFmtAboveAverage(c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
|
||||||
return ConditionalFormatOptions{
|
return ConditionalFormatOptions{
|
||||||
|
StopIfTrue: c.StopIfTrue,
|
||||||
Type: "average",
|
Type: "average",
|
||||||
Criteria: "=",
|
Criteria: "=",
|
||||||
Format: *c.DxfID,
|
Format: *c.DxfID,
|
||||||
|
@ -3277,8 +3358,9 @@ func extractCondFmtAboveAverage(c *xlsxCfRule) ConditionalFormatOptions {
|
||||||
// extractCondFmtDuplicateUniqueValues provides a function to extract
|
// extractCondFmtDuplicateUniqueValues provides a function to extract
|
||||||
// conditional format settings for duplicate and unique values by given
|
// conditional format settings for duplicate and unique values by given
|
||||||
// conditional formatting rule.
|
// conditional formatting rule.
|
||||||
func extractCondFmtDuplicateUniqueValues(c *xlsxCfRule) ConditionalFormatOptions {
|
func extractCondFmtDuplicateUniqueValues(c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
|
||||||
return ConditionalFormatOptions{
|
return ConditionalFormatOptions{
|
||||||
|
StopIfTrue: c.StopIfTrue,
|
||||||
Type: map[string]string{
|
Type: map[string]string{
|
||||||
"duplicateValues": "duplicate",
|
"duplicateValues": "duplicate",
|
||||||
"uniqueValues": "unique",
|
"uniqueValues": "unique",
|
||||||
|
@ -3291,8 +3373,8 @@ func extractCondFmtDuplicateUniqueValues(c *xlsxCfRule) ConditionalFormatOptions
|
||||||
// extractCondFmtColorScale provides a function to extract conditional format
|
// extractCondFmtColorScale provides a function to extract conditional format
|
||||||
// settings for color scale (include 2 color scale and 3 color scale) by given
|
// settings for color scale (include 2 color scale and 3 color scale) by given
|
||||||
// conditional formatting rule.
|
// conditional formatting rule.
|
||||||
func extractCondFmtColorScale(c *xlsxCfRule) ConditionalFormatOptions {
|
func extractCondFmtColorScale(c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
|
||||||
var format ConditionalFormatOptions
|
format := ConditionalFormatOptions{StopIfTrue: c.StopIfTrue}
|
||||||
format.Type, format.Criteria = "2_color_scale", "="
|
format.Type, format.Criteria = "2_color_scale", "="
|
||||||
values := len(c.ColorScale.Cfvo)
|
values := len(c.ColorScale.Cfvo)
|
||||||
colors := len(c.ColorScale.Color)
|
colors := len(c.ColorScale.Color)
|
||||||
|
@ -3326,20 +3408,58 @@ func extractCondFmtColorScale(c *xlsxCfRule) ConditionalFormatOptions {
|
||||||
|
|
||||||
// extractCondFmtDataBar provides a function to extract conditional format
|
// extractCondFmtDataBar provides a function to extract conditional format
|
||||||
// settings for data bar by given conditional formatting rule.
|
// settings for data bar by given conditional formatting rule.
|
||||||
func extractCondFmtDataBar(c *xlsxCfRule) ConditionalFormatOptions {
|
func extractCondFmtDataBar(c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
|
||||||
format := ConditionalFormatOptions{Type: "data_bar", Criteria: "="}
|
format := ConditionalFormatOptions{Type: "data_bar", Criteria: "="}
|
||||||
if c.DataBar != nil {
|
if c.DataBar != nil {
|
||||||
|
format.StopIfTrue = c.StopIfTrue
|
||||||
format.MinType = c.DataBar.Cfvo[0].Type
|
format.MinType = c.DataBar.Cfvo[0].Type
|
||||||
format.MaxType = c.DataBar.Cfvo[1].Type
|
format.MaxType = c.DataBar.Cfvo[1].Type
|
||||||
format.BarColor = "#" + strings.TrimPrefix(strings.ToUpper(c.DataBar.Color[0].RGB), "FF")
|
format.BarColor = "#" + strings.TrimPrefix(strings.ToUpper(c.DataBar.Color[0].RGB), "FF")
|
||||||
|
if c.DataBar.ShowValue != nil {
|
||||||
|
format.BarOnly = !*c.DataBar.ShowValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extractDataBarRule := func(condFmts []decodeX14ConditionalFormatting) {
|
||||||
|
for _, condFmt := range condFmts {
|
||||||
|
for _, rule := range condFmt.CfRule {
|
||||||
|
if rule.DataBar != nil {
|
||||||
|
format.BarSolid = !rule.DataBar.Gradient
|
||||||
|
if rule.DataBar.BorderColor != nil {
|
||||||
|
format.BarBorderColor = "#" + strings.TrimPrefix(strings.ToUpper(rule.DataBar.BorderColor.RGB), "FF")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extractExtLst := func(extLst *decodeWorksheetExt) {
|
||||||
|
for _, ext := range extLst.Ext {
|
||||||
|
if ext.URI == ExtURIConditionalFormattings {
|
||||||
|
decodeCondFmts := new(decodeX14ConditionalFormattings)
|
||||||
|
if err := xml.Unmarshal([]byte(ext.Content), &decodeCondFmts); err == nil {
|
||||||
|
condFmts := []decodeX14ConditionalFormatting{}
|
||||||
|
if err = xml.Unmarshal([]byte(decodeCondFmts.Content), &condFmts); err == nil {
|
||||||
|
extractDataBarRule(condFmts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if c.ExtLst != nil {
|
||||||
|
ext := decodeX14ConditionalFormattingExt{}
|
||||||
|
if err := xml.Unmarshal([]byte(c.ExtLst.Ext), &ext); err == nil && extLst != nil {
|
||||||
|
decodeExtLst := new(decodeWorksheetExt)
|
||||||
|
if err = xml.Unmarshal([]byte("<extLst>"+extLst.Ext+"</extLst>"), decodeExtLst); err == nil {
|
||||||
|
extractExtLst(decodeExtLst)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return format
|
return format
|
||||||
}
|
}
|
||||||
|
|
||||||
// extractCondFmtExp provides a function to extract conditional format settings
|
// extractCondFmtExp provides a function to extract conditional format settings
|
||||||
// for expression by given conditional formatting rule.
|
// for expression by given conditional formatting rule.
|
||||||
func extractCondFmtExp(c *xlsxCfRule) ConditionalFormatOptions {
|
func extractCondFmtExp(c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions {
|
||||||
format := ConditionalFormatOptions{Type: "formula", Format: *c.DxfID}
|
format := ConditionalFormatOptions{StopIfTrue: c.StopIfTrue, Type: "formula", Format: *c.DxfID}
|
||||||
if len(c.Formula) > 0 {
|
if len(c.Formula) > 0 {
|
||||||
format.Criteria = c.Formula[0]
|
format.Criteria = c.Formula[0]
|
||||||
}
|
}
|
||||||
|
@ -3349,7 +3469,7 @@ func extractCondFmtExp(c *xlsxCfRule) ConditionalFormatOptions {
|
||||||
// GetConditionalFormats returns conditional format settings by given worksheet
|
// GetConditionalFormats returns conditional format settings by given worksheet
|
||||||
// name.
|
// name.
|
||||||
func (f *File) GetConditionalFormats(sheet string) (map[string][]ConditionalFormatOptions, error) {
|
func (f *File) GetConditionalFormats(sheet string) (map[string][]ConditionalFormatOptions, error) {
|
||||||
extractContFmtFunc := map[string]func(c *xlsxCfRule) ConditionalFormatOptions{
|
extractContFmtFunc := map[string]func(c *xlsxCfRule, extLst *xlsxExtLst) ConditionalFormatOptions{
|
||||||
"cellIs": extractCondFmtCellIs,
|
"cellIs": extractCondFmtCellIs,
|
||||||
"top10": extractCondFmtTop10,
|
"top10": extractCondFmtTop10,
|
||||||
"aboveAverage": extractCondFmtAboveAverage,
|
"aboveAverage": extractCondFmtAboveAverage,
|
||||||
|
@ -3369,7 +3489,7 @@ func (f *File) GetConditionalFormats(sheet string) (map[string][]ConditionalForm
|
||||||
var opts []ConditionalFormatOptions
|
var opts []ConditionalFormatOptions
|
||||||
for _, cr := range cf.CfRule {
|
for _, cr := range cf.CfRule {
|
||||||
if extractFunc, ok := extractContFmtFunc[cr.Type]; ok {
|
if extractFunc, ok := extractContFmtFunc[cr.Type]; ok {
|
||||||
opts = append(opts, extractFunc(cr))
|
opts = append(opts, extractFunc(cr, ws.ExtLst))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
conditionalFormats[cf.SQRef] = opts
|
conditionalFormats[cf.SQRef] = opts
|
||||||
|
@ -3396,9 +3516,10 @@ func (f *File) UnsetConditionalFormat(sheet, rangeRef string) error {
|
||||||
// drawCondFmtCellIs provides a function to create conditional formatting rule
|
// drawCondFmtCellIs provides a function to create conditional formatting rule
|
||||||
// for cell value (include between, not between, equal, not equal, greater
|
// for cell value (include between, not between, equal, not equal, greater
|
||||||
// than and less than) by given priority, criteria type and format settings.
|
// than and less than) by given priority, criteria type and format settings.
|
||||||
func drawCondFmtCellIs(p int, ct string, format *ConditionalFormatOptions) *xlsxCfRule {
|
func drawCondFmtCellIs(p int, ct, GUID string, format *ConditionalFormatOptions) (*xlsxCfRule, *xlsxX14CfRule) {
|
||||||
c := &xlsxCfRule{
|
c := &xlsxCfRule{
|
||||||
Priority: p + 1,
|
Priority: p + 1,
|
||||||
|
StopIfTrue: format.StopIfTrue,
|
||||||
Type: validType[format.Type],
|
Type: validType[format.Type],
|
||||||
Operator: ct,
|
Operator: ct,
|
||||||
DxfID: &format.Format,
|
DxfID: &format.Format,
|
||||||
|
@ -3410,15 +3531,16 @@ func drawCondFmtCellIs(p int, ct string, format *ConditionalFormatOptions) *xlsx
|
||||||
if idx := inStrSlice([]string{"equal", "notEqual", "greaterThan", "lessThan", "greaterThanOrEqual", "lessThanOrEqual", "containsText", "notContains", "beginsWith", "endsWith"}, ct, true); idx != -1 {
|
if idx := inStrSlice([]string{"equal", "notEqual", "greaterThan", "lessThan", "greaterThanOrEqual", "lessThanOrEqual", "containsText", "notContains", "beginsWith", "endsWith"}, ct, true); idx != -1 {
|
||||||
c.Formula = append(c.Formula, format.Value)
|
c.Formula = append(c.Formula, format.Value)
|
||||||
}
|
}
|
||||||
return c
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// drawCondFmtTop10 provides a function to create conditional formatting rule
|
// drawCondFmtTop10 provides a function to create conditional formatting rule
|
||||||
// for top N (default is top 10) by given priority, criteria type and format
|
// for top N (default is top 10) by given priority, criteria type and format
|
||||||
// settings.
|
// settings.
|
||||||
func drawCondFmtTop10(p int, ct string, format *ConditionalFormatOptions) *xlsxCfRule {
|
func drawCondFmtTop10(p int, ct, GUID string, format *ConditionalFormatOptions) (*xlsxCfRule, *xlsxX14CfRule) {
|
||||||
c := &xlsxCfRule{
|
c := &xlsxCfRule{
|
||||||
Priority: p + 1,
|
Priority: p + 1,
|
||||||
|
StopIfTrue: format.StopIfTrue,
|
||||||
Bottom: format.Type == "bottom",
|
Bottom: format.Type == "bottom",
|
||||||
Type: validType[format.Type],
|
Type: validType[format.Type],
|
||||||
Rank: 10,
|
Rank: 10,
|
||||||
|
@ -3428,36 +3550,38 @@ func drawCondFmtTop10(p int, ct string, format *ConditionalFormatOptions) *xlsxC
|
||||||
if rank, err := strconv.Atoi(format.Value); err == nil {
|
if rank, err := strconv.Atoi(format.Value); err == nil {
|
||||||
c.Rank = rank
|
c.Rank = rank
|
||||||
}
|
}
|
||||||
return c
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// drawCondFmtAboveAverage provides a function to create conditional
|
// drawCondFmtAboveAverage provides a function to create conditional
|
||||||
// formatting rule for above average and below average by given priority,
|
// formatting rule for above average and below average by given priority,
|
||||||
// criteria type and format settings.
|
// criteria type and format settings.
|
||||||
func drawCondFmtAboveAverage(p int, ct string, format *ConditionalFormatOptions) *xlsxCfRule {
|
func drawCondFmtAboveAverage(p int, ct, GUID string, format *ConditionalFormatOptions) (*xlsxCfRule, *xlsxX14CfRule) {
|
||||||
return &xlsxCfRule{
|
return &xlsxCfRule{
|
||||||
Priority: p + 1,
|
Priority: p + 1,
|
||||||
|
StopIfTrue: format.StopIfTrue,
|
||||||
Type: validType[format.Type],
|
Type: validType[format.Type],
|
||||||
AboveAverage: &format.AboveAverage,
|
AboveAverage: &format.AboveAverage,
|
||||||
DxfID: &format.Format,
|
DxfID: &format.Format,
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// drawCondFmtDuplicateUniqueValues provides a function to create conditional
|
// drawCondFmtDuplicateUniqueValues provides a function to create conditional
|
||||||
// formatting rule for duplicate and unique values by given priority, criteria
|
// formatting rule for duplicate and unique values by given priority, criteria
|
||||||
// type and format settings.
|
// type and format settings.
|
||||||
func drawCondFmtDuplicateUniqueValues(p int, ct string, format *ConditionalFormatOptions) *xlsxCfRule {
|
func drawCondFmtDuplicateUniqueValues(p int, ct, GUID string, format *ConditionalFormatOptions) (*xlsxCfRule, *xlsxX14CfRule) {
|
||||||
return &xlsxCfRule{
|
return &xlsxCfRule{
|
||||||
Priority: p + 1,
|
Priority: p + 1,
|
||||||
|
StopIfTrue: format.StopIfTrue,
|
||||||
Type: validType[format.Type],
|
Type: validType[format.Type],
|
||||||
DxfID: &format.Format,
|
DxfID: &format.Format,
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// drawCondFmtColorScale provides a function to create conditional formatting
|
// drawCondFmtColorScale provides a function to create conditional formatting
|
||||||
// rule for color scale (include 2 color scale and 3 color scale) by given
|
// rule for color scale (include 2 color scale and 3 color scale) by given
|
||||||
// priority, criteria type and format settings.
|
// priority, criteria type and format settings.
|
||||||
func drawCondFmtColorScale(p int, ct string, format *ConditionalFormatOptions) *xlsxCfRule {
|
func drawCondFmtColorScale(p int, ct, GUID string, format *ConditionalFormatOptions) (*xlsxCfRule, *xlsxX14CfRule) {
|
||||||
minValue := format.MinValue
|
minValue := format.MinValue
|
||||||
if minValue == "" {
|
if minValue == "" {
|
||||||
minValue = "0"
|
minValue = "0"
|
||||||
|
@ -3473,6 +3597,7 @@ func drawCondFmtColorScale(p int, ct string, format *ConditionalFormatOptions) *
|
||||||
|
|
||||||
c := &xlsxCfRule{
|
c := &xlsxCfRule{
|
||||||
Priority: p + 1,
|
Priority: p + 1,
|
||||||
|
StopIfTrue: format.StopIfTrue,
|
||||||
Type: "colorScale",
|
Type: "colorScale",
|
||||||
ColorScale: &xlsxColorScale{
|
ColorScale: &xlsxColorScale{
|
||||||
Cfvo: []*xlsxCfvo{
|
Cfvo: []*xlsxCfvo{
|
||||||
|
@ -3489,31 +3614,53 @@ func drawCondFmtColorScale(p int, ct string, format *ConditionalFormatOptions) *
|
||||||
}
|
}
|
||||||
c.ColorScale.Cfvo = append(c.ColorScale.Cfvo, &xlsxCfvo{Type: format.MaxType, Val: maxValue})
|
c.ColorScale.Cfvo = append(c.ColorScale.Cfvo, &xlsxCfvo{Type: format.MaxType, Val: maxValue})
|
||||||
c.ColorScale.Color = append(c.ColorScale.Color, &xlsxColor{RGB: getPaletteColor(format.MaxColor)})
|
c.ColorScale.Color = append(c.ColorScale.Color, &xlsxColor{RGB: getPaletteColor(format.MaxColor)})
|
||||||
return c
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// drawCondFmtDataBar provides a function to create conditional formatting
|
// drawCondFmtDataBar provides a function to create conditional formatting
|
||||||
// rule for data bar by given priority, criteria type and format settings.
|
// rule for data bar by given priority, criteria type and format settings.
|
||||||
func drawCondFmtDataBar(p int, ct string, format *ConditionalFormatOptions) *xlsxCfRule {
|
func drawCondFmtDataBar(p int, ct, GUID string, format *ConditionalFormatOptions) (*xlsxCfRule, *xlsxX14CfRule) {
|
||||||
|
var x14CfRule *xlsxX14CfRule
|
||||||
|
var extLst *xlsxExtLst
|
||||||
|
if format.BarSolid {
|
||||||
|
extLst = &xlsxExtLst{Ext: fmt.Sprintf(`<ext uri="%s" xmlns:x14="%s"><x14:id>%s</x14:id></ext>`, ExtURIConditionalFormattingRuleID, NameSpaceSpreadSheetX14.Value, GUID)}
|
||||||
|
x14CfRule = &xlsxX14CfRule{
|
||||||
|
Type: validType[format.Type],
|
||||||
|
ID: GUID,
|
||||||
|
DataBar: &xlsx14DataBar{
|
||||||
|
MaxLength: 100,
|
||||||
|
Cfvo: []*xlsxCfvo{{Type: "autoMin"}, {Type: "autoMax"}},
|
||||||
|
NegativeFillColor: &xlsxColor{RGB: "FFFF0000"},
|
||||||
|
AxisColor: &xlsxColor{RGB: "FFFF0000"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if format.BarBorderColor != "" {
|
||||||
|
x14CfRule.DataBar.BorderColor = &xlsxColor{RGB: getPaletteColor(format.BarBorderColor)}
|
||||||
|
}
|
||||||
|
}
|
||||||
return &xlsxCfRule{
|
return &xlsxCfRule{
|
||||||
Priority: p + 1,
|
Priority: p + 1,
|
||||||
|
StopIfTrue: format.StopIfTrue,
|
||||||
Type: validType[format.Type],
|
Type: validType[format.Type],
|
||||||
DataBar: &xlsxDataBar{
|
DataBar: &xlsxDataBar{
|
||||||
|
ShowValue: boolPtr(!format.BarOnly),
|
||||||
Cfvo: []*xlsxCfvo{{Type: format.MinType}, {Type: format.MaxType}},
|
Cfvo: []*xlsxCfvo{{Type: format.MinType}, {Type: format.MaxType}},
|
||||||
Color: []*xlsxColor{{RGB: getPaletteColor(format.BarColor)}},
|
Color: []*xlsxColor{{RGB: getPaletteColor(format.BarColor)}},
|
||||||
},
|
},
|
||||||
}
|
ExtLst: extLst,
|
||||||
|
}, x14CfRule
|
||||||
}
|
}
|
||||||
|
|
||||||
// drawCondFmtExp provides a function to create conditional formatting rule
|
// drawCondFmtExp provides a function to create conditional formatting rule
|
||||||
// for expression by given priority, criteria type and format settings.
|
// for expression by given priority, criteria type and format settings.
|
||||||
func drawCondFmtExp(p int, ct string, format *ConditionalFormatOptions) *xlsxCfRule {
|
func drawCondFmtExp(p int, ct, GUID string, format *ConditionalFormatOptions) (*xlsxCfRule, *xlsxX14CfRule) {
|
||||||
return &xlsxCfRule{
|
return &xlsxCfRule{
|
||||||
Priority: p + 1,
|
Priority: p + 1,
|
||||||
|
StopIfTrue: format.StopIfTrue,
|
||||||
Type: validType[format.Type],
|
Type: validType[format.Type],
|
||||||
Formula: []string{format.Criteria},
|
Formula: []string{format.Criteria},
|
||||||
DxfID: &format.Format,
|
DxfID: &format.Format,
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getPaletteColor provides a function to convert the RBG color by given
|
// getPaletteColor provides a function to convert the RBG color by given
|
||||||
|
|
|
@ -159,12 +159,7 @@ func TestSetConditionalFormat(t *testing.T) {
|
||||||
f := NewFile()
|
f := NewFile()
|
||||||
const sheet = "Sheet1"
|
const sheet = "Sheet1"
|
||||||
const rangeRef = "A1:A1"
|
const rangeRef = "A1:A1"
|
||||||
|
assert.NoError(t, f.SetConditionalFormat(sheet, rangeRef, testCase.format))
|
||||||
err := f.SetConditionalFormat(sheet, rangeRef, testCase.format)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("%s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ws, err := f.workSheetReader(sheet)
|
ws, err := f.workSheetReader(sheet)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
cf := ws.ConditionalFormatting
|
cf := ws.ConditionalFormatting
|
||||||
|
@ -173,6 +168,19 @@ func TestSetConditionalFormat(t *testing.T) {
|
||||||
assert.Equal(t, rangeRef, cf[0].SQRef, testCase.label)
|
assert.Equal(t, rangeRef, cf[0].SQRef, testCase.label)
|
||||||
assert.EqualValues(t, testCase.rules, cf[0].CfRule, testCase.label)
|
assert.EqualValues(t, testCase.rules, cf[0].CfRule, testCase.label)
|
||||||
}
|
}
|
||||||
|
// Test creating a conditional format with a solid color data bar style
|
||||||
|
f := NewFile()
|
||||||
|
condFmts := []ConditionalFormatOptions{
|
||||||
|
{Type: "data_bar", BarColor: "#A9D08E", BarSolid: true, Format: 0, Criteria: "=", MinType: "min", MaxType: "max"},
|
||||||
|
}
|
||||||
|
for _, ref := range []string{"A1:A2", "B1:B2"} {
|
||||||
|
assert.NoError(t, f.SetConditionalFormat("Sheet1", ref, condFmts))
|
||||||
|
}
|
||||||
|
// Test creating a conditional format with invalid extension list characters
|
||||||
|
ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
|
||||||
|
assert.True(t, ok)
|
||||||
|
ws.(*xlsxWorksheet).ExtLst.Ext = "<extLst><ext><x14:conditionalFormattings></x14:conditionalFormatting></x14:conditionalFormattings></ext></extLst>"
|
||||||
|
assert.EqualError(t, f.SetConditionalFormat("Sheet1", "A1:A2", condFmts), "XML syntax error on line 1: element <conditionalFormattings> closed by </conditionalFormatting>")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetConditionalFormats(t *testing.T) {
|
func TestGetConditionalFormats(t *testing.T) {
|
||||||
|
@ -186,7 +194,7 @@ func TestGetConditionalFormats(t *testing.T) {
|
||||||
{{Type: "unique", Format: 1, Criteria: "="}},
|
{{Type: "unique", Format: 1, Criteria: "="}},
|
||||||
{{Type: "3_color_scale", Criteria: "=", MinType: "num", MidType: "num", MaxType: "num", MinValue: "-10", MidValue: "50", MaxValue: "10", MinColor: "#FF0000", MidColor: "#00FF00", MaxColor: "#0000FF"}},
|
{{Type: "3_color_scale", Criteria: "=", MinType: "num", MidType: "num", MaxType: "num", MinValue: "-10", MidValue: "50", MaxValue: "10", MinColor: "#FF0000", MidColor: "#00FF00", MaxColor: "#0000FF"}},
|
||||||
{{Type: "2_color_scale", Criteria: "=", MinType: "num", MaxType: "num", MinColor: "#FF0000", MaxColor: "#0000FF"}},
|
{{Type: "2_color_scale", Criteria: "=", MinType: "num", MaxType: "num", MinColor: "#FF0000", MaxColor: "#0000FF"}},
|
||||||
{{Type: "data_bar", Criteria: "=", MinType: "min", MaxType: "max", BarColor: "#638EC6"}},
|
{{Type: "data_bar", Criteria: "=", MinType: "min", MaxType: "max", BarColor: "#638EC6", BarBorderColor: "#0000FF", BarOnly: true, BarSolid: true, StopIfTrue: true}},
|
||||||
{{Type: "formula", Format: 1, Criteria: "="}},
|
{{Type: "formula", Format: 1, Criteria: "="}},
|
||||||
} {
|
} {
|
||||||
f := NewFile()
|
f := NewFile()
|
||||||
|
|
|
@ -91,7 +91,8 @@ const (
|
||||||
// ([ISO/IEC29500-1:2016] section 18.2.10) of the worksheet element
|
// ([ISO/IEC29500-1:2016] section 18.2.10) of the worksheet element
|
||||||
// ([ISO/IEC29500-1:2016] section 18.3.1.99) is extended by the addition of
|
// ([ISO/IEC29500-1:2016] section 18.3.1.99) is extended by the addition of
|
||||||
// new child ext elements ([ISO/IEC29500-1:2016] section 18.2.7)
|
// new child ext elements ([ISO/IEC29500-1:2016] section 18.2.7)
|
||||||
ExtURIConditionalFormattings = "{78C0D931-6437-407D-A8EE-F0AAD7539E65}"
|
ExtURIConditionalFormattingRuleID = "{B025F937-C7B1-47D3-B67F-A62EFF666E3E}"
|
||||||
|
ExtURIConditionalFormattings = "{78C0D931-6437-407d-A8EE-F0AAD7539E65}"
|
||||||
ExtURIDataValidations = "{CCE6A557-97BC-4B89-ADB6-D9C93CAAB3DF}"
|
ExtURIDataValidations = "{CCE6A557-97BC-4B89-ADB6-D9C93CAAB3DF}"
|
||||||
ExtURIDrawingBlip = "{28A0092B-C50C-407E-A947-70E740481C1C}"
|
ExtURIDrawingBlip = "{28A0092B-C50C-407E-A947-70E740481C1C}"
|
||||||
ExtURIIgnoredErrors = "{01252117-D84E-4E92-8308-4BE1C098FCBB}"
|
ExtURIIgnoredErrors = "{01252117-D84E-4E92-8308-4BE1C098FCBB}"
|
||||||
|
|
|
@ -592,7 +592,7 @@ type xlsxColorScale struct {
|
||||||
type xlsxDataBar struct {
|
type xlsxDataBar struct {
|
||||||
MaxLength int `xml:"maxLength,attr,omitempty"`
|
MaxLength int `xml:"maxLength,attr,omitempty"`
|
||||||
MinLength int `xml:"minLength,attr,omitempty"`
|
MinLength int `xml:"minLength,attr,omitempty"`
|
||||||
ShowValue bool `xml:"showValue,attr,omitempty"`
|
ShowValue *bool `xml:"showValue,attr"`
|
||||||
Cfvo []*xlsxCfvo `xml:"cfvo"`
|
Cfvo []*xlsxCfvo `xml:"cfvo"`
|
||||||
Color []*xlsxColor `xml:"color"`
|
Color []*xlsxColor `xml:"color"`
|
||||||
}
|
}
|
||||||
|
@ -601,7 +601,7 @@ type xlsxDataBar struct {
|
||||||
type xlsxIconSet struct {
|
type xlsxIconSet struct {
|
||||||
Cfvo []*xlsxCfvo `xml:"cfvo"`
|
Cfvo []*xlsxCfvo `xml:"cfvo"`
|
||||||
IconSet string `xml:"iconSet,attr,omitempty"`
|
IconSet string `xml:"iconSet,attr,omitempty"`
|
||||||
ShowValue bool `xml:"showValue,attr,omitempty"`
|
ShowValue *bool `xml:"showValue,attr"`
|
||||||
Percent bool `xml:"percent,attr,omitempty"`
|
Percent bool `xml:"percent,attr,omitempty"`
|
||||||
Reverse bool `xml:"reverse,attr,omitempty"`
|
Reverse bool `xml:"reverse,attr,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -742,6 +742,84 @@ type decodeX14SparklineGroups struct {
|
||||||
Content string `xml:",innerxml"`
|
Content string `xml:",innerxml"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// decodeX14ConditionalFormattingExt directly maps the ext
|
||||||
|
// element.
|
||||||
|
type decodeX14ConditionalFormattingExt struct {
|
||||||
|
XMLName xml.Name `xml:"ext"`
|
||||||
|
ID string `xml:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// decodeX14ConditionalFormattings directly maps the conditionalFormattings
|
||||||
|
// element.
|
||||||
|
type decodeX14ConditionalFormattings struct {
|
||||||
|
XMLName xml.Name `xml:"conditionalFormattings"`
|
||||||
|
XMLNSXM string `xml:"xmlns:xm,attr"`
|
||||||
|
Content string `xml:",innerxml"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// decodeX14ConditionalFormatting directly maps the conditionalFormatting
|
||||||
|
// element.
|
||||||
|
type decodeX14ConditionalFormatting struct {
|
||||||
|
XMLName xml.Name `xml:"conditionalFormatting"`
|
||||||
|
CfRule []*decodeX14CfRule `xml:"cfRule"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// decodeX14CfRule directly maps the cfRule element.
|
||||||
|
type decodeX14CfRule struct {
|
||||||
|
XNLName xml.Name `xml:"cfRule"`
|
||||||
|
Type string `xml:"type,attr,omitempty"`
|
||||||
|
ID string `xml:"id,attr,omitempty"`
|
||||||
|
DataBar *decodeX14DataBar `xml:"dataBar"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// decodeX14DataBar directly maps the dataBar element.
|
||||||
|
type decodeX14DataBar struct {
|
||||||
|
XNLName xml.Name `xml:"dataBar"`
|
||||||
|
MaxLength int `xml:"maxLength,attr"`
|
||||||
|
MinLength int `xml:"minLength,attr"`
|
||||||
|
Gradient bool `xml:"gradient,attr"`
|
||||||
|
ShowValue bool `xml:"showValue,attr,omitempty"`
|
||||||
|
Cfvo []*xlsxCfvo `xml:"cfvo"`
|
||||||
|
BorderColor *xlsxColor `xml:"borderColor"`
|
||||||
|
NegativeFillColor *xlsxColor `xml:"negativeFillColor"`
|
||||||
|
AxisColor *xlsxColor `xml:"axisColor"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// xlsxX14ConditionalFormattings directly maps the conditionalFormattings
|
||||||
|
// element.
|
||||||
|
type xlsxX14ConditionalFormattings struct {
|
||||||
|
XMLName xml.Name `xml:"x14:conditionalFormattings"`
|
||||||
|
Content string `xml:",innerxml"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// xlsxX14ConditionalFormatting directly maps the conditionalFormatting element.
|
||||||
|
type xlsxX14ConditionalFormatting struct {
|
||||||
|
XMLName xml.Name `xml:"x14:conditionalFormatting"`
|
||||||
|
XMLNSXM string `xml:"xmlns:xm,attr"`
|
||||||
|
CfRule []*xlsxX14CfRule `xml:"x14:cfRule"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// xlsxX14CfRule directly maps the cfRule element.
|
||||||
|
type xlsxX14CfRule struct {
|
||||||
|
XNLName xml.Name `xml:"x14:cfRule"`
|
||||||
|
Type string `xml:"type,attr,omitempty"`
|
||||||
|
ID string `xml:"id,attr,omitempty"`
|
||||||
|
DataBar *xlsx14DataBar `xml:"x14:dataBar"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// xlsx14DataBar directly maps the dataBar element.
|
||||||
|
type xlsx14DataBar struct {
|
||||||
|
XNLName xml.Name `xml:"x14:dataBar"`
|
||||||
|
MaxLength int `xml:"maxLength,attr"`
|
||||||
|
MinLength int `xml:"minLength,attr"`
|
||||||
|
Gradient bool `xml:"gradient,attr"`
|
||||||
|
ShowValue bool `xml:"showValue,attr,omitempty"`
|
||||||
|
Cfvo []*xlsxCfvo `xml:"x14:cfvo"`
|
||||||
|
BorderColor *xlsxColor `xml:"x14:borderColor"`
|
||||||
|
NegativeFillColor *xlsxColor `xml:"x14:negativeFillColor"`
|
||||||
|
AxisColor *xlsxColor `xml:"x14:axisColor"`
|
||||||
|
}
|
||||||
|
|
||||||
// xlsxX14SparklineGroups directly maps the sparklineGroups element.
|
// xlsxX14SparklineGroups directly maps the sparklineGroups element.
|
||||||
type xlsxX14SparklineGroups struct {
|
type xlsxX14SparklineGroups struct {
|
||||||
XMLName xml.Name `xml:"x14:sparklineGroups"`
|
XMLName xml.Name `xml:"x14:sparklineGroups"`
|
||||||
|
@ -863,6 +941,10 @@ type ConditionalFormatOptions struct {
|
||||||
MinLength string
|
MinLength string
|
||||||
MaxLength string
|
MaxLength string
|
||||||
BarColor string
|
BarColor string
|
||||||
|
BarBorderColor string
|
||||||
|
BarOnly bool
|
||||||
|
BarSolid bool
|
||||||
|
StopIfTrue bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// SheetProtectionOptions directly maps the settings of worksheet protection.
|
// SheetProtectionOptions directly maps the settings of worksheet protection.
|
||||||
|
|
Loading…
Reference in New Issue