@ -774,6 +774,61 @@ var builtInNumFmtFunc = map[int]func(i int, v string) string{
49 : formatToString ,
}
// validType defined the list of valid validation types.
var validType = map [ string ] string {
"cell" : "cellIs" ,
"date" : "date" , // Doesn't support currently
"time" : "time" , // Doesn't support currently
"average" : "aboveAverage" ,
"duplicate" : "duplicateValues" ,
"unique" : "uniqueValues" ,
"top" : "top10" ,
"bottom" : "top10" ,
"text" : "text" , // Doesn't support currently
"time_period" : "timePeriod" , // Doesn't support currently
"blanks" : "containsBlanks" , // Doesn't support currently
"no_blanks" : "notContainsBlanks" , // Doesn't support currently
"errors" : "containsErrors" , // Doesn't support currently
"no_errors" : "notContainsErrors" , // Doesn't support currently
"2_color_scale" : "2_color_scale" ,
"3_color_scale" : "3_color_scale" ,
"data_bar" : "dataBar" ,
"formula" : "expression" , // Doesn't support currently
}
// criteriaType defined the list of valid criteria types.
var criteriaType = map [ string ] string {
"between" : "between" ,
"not between" : "notBetween" ,
"equal to" : "equal" ,
"=" : "equal" ,
"==" : "equal" ,
"not equal to" : "notEqual" ,
"!=" : "notEqual" ,
"<>" : "notEqual" ,
"greater than" : "greaterThan" ,
">" : "greaterThan" ,
"less than" : "lessThan" ,
"<" : "lessThan" ,
"greater than or equal to" : "greaterThanOrEqual" ,
">=" : "greaterThanOrEqual" ,
"less than or equal to" : "lessThanOrEqual" ,
"<=" : "lessThanOrEqual" ,
"containing" : "containsText" ,
"not containing" : "notContains" ,
"begins with" : "beginsWith" ,
"ends with" : "endsWith" ,
"yesterday" : "yesterday" ,
"today" : "today" ,
"last 7 days" : "last7Days" ,
"last week" : "lastWeek" ,
"this week" : "thisWeek" ,
"continue week" : "continueWeek" ,
"last month" : "lastMonth" ,
"this month" : "thisMonth" ,
"continue month" : "continueMonth" ,
}
// formatToString provides function to return original string by given built-in
// number formats code and cell string.
func formatToString ( i int , v string ) string {
@ -935,9 +990,9 @@ func (f *File) styleSheetWriter() {
}
// parseFormatStyleSet provides function to parse the format settings of the
// border s.
func parseFormatStyleSet ( style string ) ( * format Cell Style, error ) {
format := format Cell Style{
// cells and conditional format s.
func parseFormatStyleSet ( style string ) ( * format Style, error ) {
format := format Style{
DecimalPlaces : 2 ,
}
err := json . Unmarshal ( [ ] byte ( style ) , & format )
@ -1806,79 +1861,114 @@ func parseFormatStyleSet(style string) (*formatCellStyle, error) {
// Cell Sheet1!A6 in the Excel Application: martes, 04 de Julio de 2017
//
func ( f * File ) NewStyle ( style string ) ( int , error ) {
var cellXfsID int
s tyleSheet := f . stylesReader ( )
f ormatCellStyle , err := parseFormatStyleSet ( style )
var cellXfsID , fontID , borderID , fillID int
s := f . stylesReader ( )
f s , err := parseFormatStyleSet ( style )
if err != nil {
return cellXfsID , err
}
numFmtID := setNumFmt ( styleSheet , formatCellStyle )
fontID := setFont ( styleSheet , formatCellStyle )
borderID := setBorders ( styleSheet , formatCellStyle )
fillID := setFills ( styleSheet , formatCellStyle )
applyAlignment , alignment := setAlignment ( styleSheet , formatCellStyle )
cellXfsID = setCellXfs ( styleSheet , fontID , numFmtID , fillID , borderID , applyAlignment , alignment )
numFmtID := setNumFmt ( s , fs )
if fs . Font != nil {
font , _ := xml . Marshal ( setFont ( fs ) )
s . Fonts . Count ++
s . Fonts . Font = append ( s . Fonts . Font , & xlsxFont {
Font : string ( font [ 6 : len ( font ) - 7 ] ) ,
} )
fontID = s . Fonts . Count - 1
}
s . Borders . Count ++
s . Borders . Border = append ( s . Borders . Border , setBorders ( fs ) )
borderID = s . Borders . Count - 1
s . Fills . Count ++
s . Fills . Fill = append ( s . Fills . Fill , setFills ( fs , true ) )
fillID = s . Fills . Count - 1
applyAlignment , alignment := fs . Alignment != nil , setAlignment ( fs )
cellXfsID = setCellXfs ( s , fontID , numFmtID , fillID , borderID , applyAlignment , alignment )
return cellXfsID , nil
}
// setFont provides function to add font style by given cell format settings.
func setFont ( style * xlsxStyleSheet , formatCellStyle * formatCellStyle ) int {
if formatCellStyle . Font == nil {
return 0
// NewConditionalStyle provides function to create style for conditional format
// by given style format. Note that the color field uses RGB color code. Only
// support set font, fills, alignment and borders currently.
func ( f * File ) NewConditionalStyle ( style string ) ( int , error ) {
s := f . stylesReader ( )
fs , err := parseFormatStyleSet ( style )
if err != nil {
return 0 , err
}
dxf := dxf {
Fill : setFills ( fs , false ) ,
Alignment : setAlignment ( fs ) ,
Border : setBorders ( fs ) ,
}
if fs . Font != nil {
dxf . Font = setFont ( fs )
}
dxfStr , _ := xml . Marshal ( dxf )
if s . Dxfs == nil {
s . Dxfs = & xlsxDxfs { }
}
s . Dxfs . Count ++
s . Dxfs . Dxfs = append ( s . Dxfs . Dxfs , & xlsxDxf {
Dxf : string ( dxfStr [ 5 : len ( dxfStr ) - 6 ] ) ,
} )
return s . Dxfs . Count - 1 , nil
}
// setFont provides function to add font style by given cell format settings.
func setFont ( formatStyle * formatStyle ) * font {
fontUnderlineType := map [ string ] string { "single" : "single" , "double" : "double" }
if formatCellStyle . Font . Family == "" {
formatCellStyle . Font . Family = "Calibri"
if format Style. Font . Family == "" {
format Style. Font . Family = "Calibri"
}
if formatCellStyle . Font . Size < 1 {
formatCellStyle . Font . Size = 11
if format Style. Font . Size < 1 {
format Style. Font . Size = 11
}
if formatCellStyle . Font . Color == "" {
formatCellStyle . Font . Color = "#000000"
if format Style. Font . Color == "" {
format Style. Font . Color = "#000000"
}
f := font {
B : formatCellStyle . Font . Bold ,
I : formatCellStyle . Font . Italic ,
Sz : & attrValInt { Val : format Cell Style. Font . Size } ,
Color : & xlsxColor { RGB : getPaletteColor ( format Cell Style. Font . Color ) } ,
Name : & attrValString { Val : format Cell Style. Font . Family } ,
B : format Style. Font . Bold ,
I : format Style. Font . Italic ,
Sz : & attrValInt { Val : format Style. Font . Size } ,
Color : & xlsxColor { RGB : getPaletteColor ( format Style. Font . Color ) } ,
Name : & attrValString { Val : format Style. Font . Family } ,
Family : & attrValInt { Val : 2 } ,
Scheme : & attrValString { Val : "minor" } ,
}
val , ok := fontUnderlineType [ format Cell Style. Font . Underline ]
val , ok := fontUnderlineType [ format Style. Font . Underline ]
if ok {
f . U = & attrValString { Val : val }
}
font , _ := xml . Marshal ( f )
style . Fonts . Count ++
style . Fonts . Font = append ( style . Fonts . Font , & xlsxFont {
Font : string ( font [ 6 : len ( font ) - 7 ] ) ,
} )
return style . Fonts . Count - 1
return & f
}
// setNumFmt provides function to check if number format code in the range of
// built-in values.
func setNumFmt ( style * xlsxStyleSheet , format Cell Style * format Cell Style) int {
func setNumFmt ( style * xlsxStyleSheet , formatStyle * formatStyle ) int {
dp := "0."
numFmtID := 164 // Default custom number format code from 164.
if format Cell Style. DecimalPlaces < 0 || format Cell Style. DecimalPlaces > 30 {
format Cell Style. DecimalPlaces = 2
if format Style. DecimalPlaces < 0 || format Style. DecimalPlaces > 30 {
format Style. DecimalPlaces = 2
}
for i := 0 ; i < format Cell Style. DecimalPlaces ; i ++ {
for i := 0 ; i < format Style. DecimalPlaces ; i ++ {
dp += "0"
}
if format Cell Style. CustomNumFmt != nil {
return setCustomNumFmt ( style , format Cell Style)
if format Style. CustomNumFmt != nil {
return setCustomNumFmt ( style , format Style)
}
_ , ok := builtInNumFmt [ format Cell Style. NumFmt ]
_ , ok := builtInNumFmt [ format Style. NumFmt ]
if ! ok {
fc , currency := currencyNumFmt [ format Cell Style. NumFmt ]
fc , currency := currencyNumFmt [ format Style. NumFmt ]
if ! currency {
return setLangNumFmt ( style , format Cell Style)
return setLangNumFmt ( style , format Style)
}
fc = strings . Replace ( fc , "0.00" , dp , - 1 )
if format Cell Style. NegRed {
if format Style. NegRed {
fc = fc + ";[Red]" + fc
}
if style . NumFmts != nil {
@ -1902,12 +1992,12 @@ func setNumFmt(style *xlsxStyleSheet, formatCellStyle *formatCellStyle) int {
}
return numFmtID
}
return format Cell Style. NumFmt
return format Style. NumFmt
}
// setCustomNumFmt provides function to set custom number format code.
func setCustomNumFmt ( style * xlsxStyleSheet , format Cell Style * format Cell Style) int {
nf := xlsxNumFmt { FormatCode : * format Cell Style. CustomNumFmt }
func setCustomNumFmt ( style * xlsxStyleSheet , format Style * format Style) int {
nf := xlsxNumFmt { FormatCode : * format Style. CustomNumFmt }
if style . NumFmts != nil {
nf . NumFmtID = style . NumFmts . NumFmt [ len ( style . NumFmts . NumFmt ) - 1 ] . NumFmtID + 1
style . NumFmts . NumFmt = append ( style . NumFmts . NumFmt , & nf )
@ -1924,13 +2014,13 @@ func setCustomNumFmt(style *xlsxStyleSheet, formatCellStyle *formatCellStyle) in
}
// setLangNumFmt provides function to set number format code with language.
func setLangNumFmt ( style * xlsxStyleSheet , format Cell Style * format Cell Style) int {
numFmts , ok := langNumFmt [ format Cell Style. Lang ]
func setLangNumFmt ( style * xlsxStyleSheet , format Style * format Style) int {
numFmts , ok := langNumFmt [ format Style. Lang ]
if ! ok {
return 0
}
var fc string
fc , ok = numFmts [ format Cell Style. NumFmt ]
fc , ok = numFmts [ format Style. NumFmt ]
if ! ok {
return 0
}
@ -1940,7 +2030,7 @@ func setLangNumFmt(style *xlsxStyleSheet, formatCellStyle *formatCellStyle) int
style . NumFmts . NumFmt = append ( style . NumFmts . NumFmt , & nf )
style . NumFmts . Count ++
} else {
nf . NumFmtID = format Cell Style. NumFmt
nf . NumFmtID = format Style. NumFmt
numFmts := xlsxNumFmts {
NumFmt : [ ] * xlsxNumFmt { & nf } ,
Count : 1 ,
@ -1952,7 +2042,7 @@ func setLangNumFmt(style *xlsxStyleSheet, formatCellStyle *formatCellStyle) int
// setFills provides function to add fill elements in the styles.xml by given
// cell format settings.
func setFills ( style * xlsxStyleSheet , formatCellStyle * formatCellStyle ) int {
func setFills ( formatStyle * formatStyle , fg bool ) * xlsxFill {
var patterns = [ ] string {
"none" ,
"solid" ,
@ -1983,15 +2073,15 @@ func setFills(style *xlsxStyleSheet, formatCellStyle *formatCellStyle) int {
}
var fill xlsxFill
switch format Cell Style. Fill . Type {
switch format Style. Fill . Type {
case "gradient" :
if len ( format Cell Style. Fill . Color ) != 2 {
if len ( format Style. Fill . Color ) != 2 {
break
}
var gradient xlsxGradientFill
switch format Cell Style. Fill . Shading {
switch format Style. Fill . Shading {
case 0 , 1 , 2 , 3 :
gradient . Degree = variants [ format Cell Style. Fill . Shading ]
gradient . Degree = variants [ format Style. Fill . Shading ]
case 4 :
gradient . Type = "path"
case 5 :
@ -2004,7 +2094,7 @@ func setFills(style *xlsxStyleSheet, formatCellStyle *formatCellStyle) int {
break
}
var stops [ ] * xlsxGradientFillStop
for index , color := range format Cell Style. Fill . Color {
for index , color := range format Style. Fill . Color {
var stop xlsxGradientFillStop
stop . Position = float64 ( index )
stop . Color . RGB = getPaletteColor ( color )
@ -2013,46 +2103,46 @@ func setFills(style *xlsxStyleSheet, formatCellStyle *formatCellStyle) int {
gradient . Stop = stops
fill . GradientFill = & gradient
case "pattern" :
if format Cell Style. Fill . Pattern > 18 || format Cell Style. Fill . Pattern < 0 {
if format Style. Fill . Pattern > 18 || format Style. Fill . Pattern < 0 {
break
}
if len ( format Cell Style. Fill . Color ) < 1 {
if len ( format Style. Fill . Color ) < 1 {
break
}
var pattern xlsxPatternFill
pattern . PatternType = patterns [ formatCellStyle . Fill . Pattern ]
pattern . FgColor . RGB = getPaletteColor ( formatCellStyle . Fill . Color [ 0 ] )
pattern . PatternType = patterns [ formatStyle . Fill . Pattern ]
if fg {
pattern . FgColor . RGB = getPaletteColor ( formatStyle . Fill . Color [ 0 ] )
} else {
pattern . BgColor . RGB = getPaletteColor ( formatStyle . Fill . Color [ 0 ] )
}
fill . PatternFill = & pattern
}
style . Fills . Count ++
style . Fills . Fill = append ( style . Fills . Fill , & fill )
return style . Fills . Count - 1
return & fill
}
// setAlignment provides function to formatting information pertaining to text
// alignment in cells. There are a variety of choices for how text is aligned
// both horizontally and vertically, as well as indentation settings, and so on.
func setAlignment ( style * xlsxStyleSheet , formatCellStyle * formatCellStyle ) ( bool , * xlsxAlignment ) {
if formatCellStyle . Alignment == nil {
return false , & xlsxAlignment { }
}
var alignment = xlsxAlignment {
Horizontal : formatCellStyle . Alignment . Horizontal ,
Indent : formatCellStyle . Alignment . Indent ,
JustifyLastLine : formatCellStyle . Alignment . JustifyLastLine ,
ReadingOrder : formatCellStyle . Alignment . ReadingOrder ,
RelativeIndent : formatCellStyle . Alignment . RelativeIndent ,
ShrinkToFit : formatCellStyle . Alignment . ShrinkToFit ,
TextRotation : formatCellStyle . Alignment . TextRotation ,
Vertical : formatCellStyle . Alignment . Vertical ,
WrapText : formatCellStyle . Alignment . WrapText ,
}
return true , & alignment
func setAlignment ( formatStyle * formatStyle ) * xlsxAlignment {
var alignment xlsxAlignment
if formatStyle . Alignment != nil {
alignment . Horizontal = formatStyle . Alignment . Horizontal
alignment . Indent = formatStyle . Alignment . Indent
alignment . JustifyLastLine = formatStyle . Alignment . JustifyLastLine
alignment . ReadingOrder = formatStyle . Alignment . ReadingOrder
alignment . RelativeIndent = formatStyle . Alignment . RelativeIndent
alignment . ShrinkToFit = formatStyle . Alignment . ShrinkToFit
alignment . TextRotation = formatStyle . Alignment . TextRotation
alignment . Vertical = formatStyle . Alignment . Vertical
alignment . WrapText = formatStyle . Alignment . WrapText
}
return & alignment
}
// setBorders provides function to add border elements in the styles.xml by
// given borders format settings.
func setBorders ( style * xlsxStyleSheet , formatCellStyle * formatCellStyle ) int {
func setBorders ( formatStyle * formatStyle ) * xlsxBorder {
var styles = [ ] string {
"none" ,
"thin" ,
@ -2071,7 +2161,7 @@ func setBorders(style *xlsxStyleSheet, formatCellStyle *formatCellStyle) int {
}
var border xlsxBorder
for _ , v := range format Cell Style. Border {
for _ , v := range format Style. Border {
if v . Style > 13 || v . Style < 0 {
continue
}
@ -2100,9 +2190,7 @@ func setBorders(style *xlsxStyleSheet, formatCellStyle *formatCellStyle) int {
border . DiagonalDown = true
}
}
style . Borders . Count ++
style . Borders . Border = append ( style . Borders . Border , & border )
return style . Borders . Count - 1
return & border
}
// setCellXfs provides function to set describes all of the formatting for a
@ -2228,6 +2316,362 @@ func (f *File) SetCellStyle(sheet, hcell, vcell string, styleID int) {
}
}
// SetConditionalFormat provides function to create conditional formatting rule
// for cell value. Conditional formatting is a feature of Excel which allows you
// to apply a format to a cell or a range of cells based on certain criteria.
//
// The type option is a required parameter and it has no default value.
// Allowable type values and their associated parameters are:
//
// Type | Parameters
// ---------------+------------------------------------
// cell | criteria
// | value
// | minimum
// | maximum
// date | criteria
// | value
// | minimum
// | maximum
// time_period | criteria
// text | criteria
// | value
// average | criteria
// duplicate | (none)
// unique | (none)
// top | criteria
// | value
// bottom | criteria
// | value
// blanks | (none)
// no_blanks | (none)
// errors | (none)
// no_errors | (none)
// 2_color_scale | min_type
// | max_type
// | min_value
// | max_value
// | min_color
// | max_color
// 3_color_scale | min_type
// | mid_type
// | max_type
// | min_value
// | mid_value
// | max_value
// | min_color
// | mid_color
// | max_color
// data_bar | min_type
// | max_type
// | min_value
// | max_value
// | bar_color
// formula | criteria
//
// The criteria parameter is used to set the criteria by which the cell data
// will be evaluated. It has no default value. The most common criteria as
// applied to {'type': 'cell'} are:
//
// between |
// not between |
// equal to | ==
// not equal to | !=
// greater than | >
// less than | <
// greater than or equal to | >=
// less than or equal to | <=
//
// You can either use Excel's textual description strings, in the first column
// above, or the more common symbolic alternatives.
//
// Additional criteria which are specific to other conditional format types are
// shown in the relevant sections below.
//
// value: The value is generally used along with the criteria parameter to set
// the rule by which the cell data will be evaluated:
//
// xlsx.SetConditionalFormat("Sheet1", "D1:D10", fmt.Sprintf(`[{"type":"cell","criteria":">","format":%d,"value":"6"}]`, format))
//
// The value property can also be an cell reference:
//
// xlsx.SetConditionalFormat("Sheet1", "D1:D10", fmt.Sprintf(`[{"type":"cell","criteria":">","format":%d,"value":"$C$1"}]`, format))
//
// type: format - The format parameter is used to specify the format that will
// be applied to the cell when the conditional formatting criterion is met. The
// format is created using the NewConditionalStyle() method in the same way as
// cell formats:
//
// format1, err = xlsx.NewConditionalStyle(`{"font":{"color":"#9A0511"},"fill":{"type":"pattern","color":["#FEC7CE"],"pattern":1}}`)
// if err != nil {
// fmt.Println(err)
// }
// xlsx.SetConditionalFormat("Sheet1", "D1:D10", fmt.Sprintf(`[{"type":"cell","criteria":">","format":%d,"value":"6"}]`, format1))
//
// Note: In Excel, a conditional format is superimposed over the existing cell
// format and not all cell format properties can be modified. Properties that
// cannot be modified in a conditional format are font name, font size,
// superscript and subscript, diagonal borders, all alignment properties and all
// protection properties.
//
// Excel specifies some default formats to be used with conditional formatting.
// These can be replicated using the following excelize formats:
//
// // Rose format for bad conditional.
// format1, err = xlsx.NewConditionalStyle(`{"font":{"color":"#9A0511"},"fill":{"type":"pattern","color":["#FEC7CE"],"pattern":1}}`)
//
// // Light yellow format for neutral conditional.
// format2, err = xlsx.NewConditionalStyle(`{"fill":{"type":"pattern","color":["#FEEAA0"],"pattern":1}}`)
//
// // Light green format for good conditional.
// format3, err = xlsx.NewConditionalStyle(`{"font":{"color":"#09600B"},"fill":{"type":"pattern","color":["#C7EECF"],"pattern":1}}`)
// t.Log(err)
//
// type: minimum - The minimum parameter is used to set the lower limiting value
// when the criteria is either "between" or "not between".
//
// // Hightlight cells rules: between...
// xlsx.SetConditionalFormat("Sheet1", "C1:C10", fmt.Sprintf(`[{"type":"cell","criteria":"between","format":%d,"minimum":"6","maximum":"8"}]`, format1))
//
// type: maximum - The maximum parameter is used to set the upper limiting value
// when the criteria is either "between" or "not between". See the previous
// example.
//
// type: average - The average type is used to specify Excel's "Average" style
// conditional format:
//
// // Top/Bottom rules: Above Average...
// xlsx.SetConditionalFormat("Sheet1", "I1:I10", fmt.Sprintf(`[{"type":"average","criteria":"=","format":%d, "above_average": true}]`, format1))
//
// // Top/Bottom rules: Below Average...
// xlsx.SetConditionalFormat("Sheet1", "J1:J10", fmt.Sprintf(`[{"type":"average","criteria":"=","format":%d, "above_average": false}]`, format2))
//
// type: duplicate - The duplicate type is used to highlight duplicate cells in a range:
//
// // Hightlight cells rules: Duplicate Values...
// xlsx.SetConditionalFormat("Sheet1", "G1:G10", fmt.Sprintf(`[{"type":"duplicate","criteria":"=","format":%d}]`, format1))
//
// type: unique - The unique type is used to highlight unique cells in a range:
//
// // Hightlight cells rules: Not Equal To...
// xlsx.SetConditionalFormat("Sheet1", "F1:F10", fmt.Sprintf(`[{"type":"unique","criteria":"=","format":%d}]`, format1))
//
// type: top - The top type is used to specify the top n values by number or percentage in a range:
//
// // Top/Bottom rules: Top 10.
// xlsx.SetConditionalFormat("Sheet1", "H1:H10", fmt.Sprintf(`[{"type":"top","criteria":"=","format":%d,"value":"6"}]`, format1))
//
// The criteria can be used to indicate that a percentage condition is required:
//
// xlsx.SetConditionalFormat("Sheet1", "H1:H10", fmt.Sprintf(`[{"type":"top","criteria":"=","format":%d,"value":"6","percent":true}]`, format1))
//
// type: 2_color_scale - The 2_color_scale type is used to specify Excel's "2
// Color Scale" style conditional format:
//
// // Color scales: 2 color.
// xlsx.SetConditionalFormat("Sheet1", "A1:A10", `[{"type":"2_color_scale","criteria":"=","min_type":"min","max_type":"max","min_color":"#F8696B","max_color":"#63BE7B"}]`)
//
// This conditional type can be modified with min_type, max_type, min_value,
// max_value, min_color and max_color, see below.
//
// type: 3_color_scale - The 3_color_scale type is used to specify Excel's "3
// Color Scale" style conditional format:
//
// // Color scales: 3 color.
// xlsx.SetConditionalFormat("Sheet1", "B1:B10", `[{"type":"3_color_scale","criteria":"=","min_type":"min","mid_type":"percentile","max_type":"max","min_color":"#F8696B","mid_color":"#FFEB84","max_color":"#63BE7B"}]`)
//
// This conditional type can be modified with min_type, mid_type, max_type,
// min_value, mid_value, max_value, min_color, mid_color and max_color, see
// below.
//
// type: data_bar - The data_bar type is used to specify Excel's "Data Bar"
// style conditional format.
//
// min_type - The min_type and max_type properties are available when the conditional formatting type is 2_color_scale, 3_color_scale or data_bar. The mid_type is available for 3_color_scale. The properties are used as follows:
//
// // Data Bars: Gradient Fill.
// xlsx.SetConditionalFormat("Sheet1", "K1:K10", `[{"type":"data_bar", "criteria":"=", "min_type":"min","max_type":"max","bar_color":"#638EC6"}]`)
//
// The available min/mid/max types are:
//
// min (for min_type only)
// num
// percent
// percentile
// formula
// max (for max_type only)
//
// mid_type - Used for 3_color_scale. Same as min_type, see above.
//
// max_type - Same as min_type, see above.
//
// min_value - The min_value and max_value properties are available when the
// conditional formatting type is 2_color_scale, 3_color_scale or data_bar. The
// mid_value is available for 3_color_scale.
//
// mid_value - Used for 3_color_scale. Same as min_value, see above.
//
// max_value - Same as min_value, see above.
//
// min_color - The min_color and max_color properties are available when the
// conditional formatting type is 2_color_scale, 3_color_scale or data_bar.
// The mid_color is available for 3_color_scale. The properties are used as
// follows:
//
// // Color scales: 3 color.
// xlsx.SetConditionalFormat("Sheet1", "B1:B10", `[{"type":"3_color_scale","criteria":"=","min_type":"min","mid_type":"percentile","max_type":"max","min_color":"#F8696B","mid_color":"#FFEB84","max_color":"#63BE7B"}]`)
//
// mid_color - Used for 3_color_scale. Same as min_color, see above.
//
// max_color - Same as min_color, see above.
//
// bar_color - Used for data_bar. Same as min_color, see above.
//
func ( f * File ) SetConditionalFormat ( sheet , area , formatSet string ) {
var format [ ] * formatConditional
json . Unmarshal ( [ ] byte ( formatSet ) , & format )
drawContFmtFunc := map [ string ] func ( p int , ct string , fmtCond * formatConditional ) * xlsxCfRule {
"cellIs" : drawCondFmtCellIs ,
"top10" : drawCondFmtTop10 ,
"aboveAverage" : drawCondFmtAboveAverage ,
"duplicateValues" : drawCondFmtDuplicateUniqueValues ,
"uniqueValues" : drawCondFmtDuplicateUniqueValues ,
"2_color_scale" : drawCondFmtColorScale ,
"3_color_scale" : drawCondFmtColorScale ,
"dataBar" : drawCondFmtDataBar ,
}
xlsx := f . workSheetReader ( sheet )
cfRule := [ ] * xlsxCfRule { }
for p , v := range format {
var vt , ct string
var ok bool
// "type" is a required parameter, check for valid validation types.
vt , ok = validType [ v . Type ]
if ! ok {
continue
}
// Check for valid criteria types.
ct , ok = criteriaType [ v . Criteria ]
if ! ok {
continue
}
drawfunc , ok := drawContFmtFunc [ vt ]
if ok {
cfRule = append ( cfRule , drawfunc ( p , ct , v ) )
}
}
xlsx . ConditionalFormatting = append ( xlsx . ConditionalFormatting , & xlsxConditionalFormatting {
SQRef : area ,
CfRule : cfRule ,
} )
}
// drawCondFmtCellIs provides function to create conditional formatting rule for
// cell value (include between, not between, equal, not equal, greater than and
// less than) by given priority, criteria type and format settings.
func drawCondFmtCellIs ( p int , ct string , format * formatConditional ) * xlsxCfRule {
c := & xlsxCfRule {
Priority : p + 1 ,
Type : validType [ format . Type ] ,
Operator : ct ,
DxfID : & format . Format ,
}
// "between" and "not between" criteria require 2 values.
_ , ok := map [ string ] bool { "between" : true , "notBetween" : true } [ ct ]
if ok {
c . Formula = append ( c . Formula , format . Minimum )
c . Formula = append ( c . Formula , format . Maximum )
}
_ , ok = map [ string ] bool { "equal" : true , "notEqual" : true , "greaterThan" : true , "lessThan" : true } [ ct ]
if ok {
c . Formula = append ( c . Formula , format . Value )
}
return c
}
// drawCondFmtTop10 provides function to create conditional formatting rule for
// top N (default is top 10) by given priority, criteria type and format
// settings.
func drawCondFmtTop10 ( p int , ct string , format * formatConditional ) * xlsxCfRule {
c := & xlsxCfRule {
Priority : p + 1 ,
Type : validType [ format . Type ] ,
Rank : 10 ,
DxfID : & format . Format ,
Percent : format . Percent ,
}
rank , err := strconv . Atoi ( format . Value )
if err == nil {
c . Rank = rank
}
return c
}
// drawCondFmtAboveAverage provides function to create conditional formatting
// rule for above average and below average by given priority, criteria type and
// format settings.
func drawCondFmtAboveAverage ( p int , ct string , format * formatConditional ) * xlsxCfRule {
return & xlsxCfRule {
Priority : p + 1 ,
Type : validType [ format . Type ] ,
AboveAverage : & format . AboveAverage ,
DxfID : & format . Format ,
}
}
// drawCondFmtDuplicateUniqueValues provides function to create conditional
// formatting rule for duplicate and unique values by given priority, criteria
// type and format settings.
func drawCondFmtDuplicateUniqueValues ( p int , ct string , format * formatConditional ) * xlsxCfRule {
return & xlsxCfRule {
Priority : p + 1 ,
Type : validType [ format . Type ] ,
DxfID : & format . Format ,
}
}
// drawCondFmtColorScale provides function to create conditional formatting rule
// for color scale (include 2 color scale and 3 color scale) by given priority,
// criteria type and format settings.
func drawCondFmtColorScale ( p int , ct string , format * formatConditional ) * xlsxCfRule {
c := & xlsxCfRule {
Priority : p + 1 ,
Type : "colorScale" ,
ColorScale : & xlsxColorScale {
Cfvo : [ ] * xlsxCfvo {
{ Type : format . MinType } ,
} ,
Color : [ ] * xlsxColor {
{ RGB : getPaletteColor ( format . MinColor ) } ,
} ,
} ,
}
if validType [ format . Type ] == "3_color_scale" {
c . ColorScale . Cfvo = append ( c . ColorScale . Cfvo , & xlsxCfvo { Type : format . MidType , Val : 50 } )
c . ColorScale . Color = append ( c . ColorScale . Color , & xlsxColor { RGB : getPaletteColor ( format . MidColor ) } )
}
c . ColorScale . Cfvo = append ( c . ColorScale . Cfvo , & xlsxCfvo { Type : format . MaxType } )
c . ColorScale . Color = append ( c . ColorScale . Color , & xlsxColor { RGB : getPaletteColor ( format . MaxColor ) } )
return c
}
// drawCondFmtDataBar provides function to create conditional formatting rule
// for data bar by given priority, criteria type and format settings.
func drawCondFmtDataBar ( p int , ct string , format * formatConditional ) * xlsxCfRule {
return & xlsxCfRule {
Priority : p + 1 ,
Type : validType [ format . Type ] ,
DataBar : & xlsxDataBar {
Cfvo : [ ] * xlsxCfvo { { Type : format . MinType } , { Type : format . MaxType } } ,
Color : [ ] * xlsxColor { { RGB : getPaletteColor ( format . BarColor ) } } ,
} ,
}
}
// getPaletteColor provides function to convert the RBG color by given string.
func getPaletteColor ( color string ) string {
return "FF" + strings . Replace ( strings . ToUpper ( color ) , "#" , "" , - 1 )