|
|
|
|
@ -1024,16 +1024,16 @@ func (f *File) styleSheetWriter() {
|
|
|
|
|
|
|
|
|
|
// parseFormatStyleSet provides a function to parse the format settings of the
|
|
|
|
|
// cells and conditional formats.
|
|
|
|
|
func parseFormatStyleSet(style string) (*formatStyle, error) {
|
|
|
|
|
format := formatStyle{
|
|
|
|
|
func parseFormatStyleSet(style string) (*Style, error) {
|
|
|
|
|
format := Style{
|
|
|
|
|
DecimalPlaces: 2,
|
|
|
|
|
}
|
|
|
|
|
err := json.Unmarshal([]byte(style), &format)
|
|
|
|
|
return &format, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NewStyle provides a function to create style for cells by given style
|
|
|
|
|
// format. Note that the color field uses RGB color code.
|
|
|
|
|
// NewStyle provides a function to create the style for cells by given JSON or
|
|
|
|
|
// structure. Note that the color field uses RGB color code.
|
|
|
|
|
//
|
|
|
|
|
// The following shows the border styles sorted by excelize index number:
|
|
|
|
|
//
|
|
|
|
|
@ -1888,18 +1888,26 @@ func parseFormatStyleSet(style string) (*formatStyle, error) {
|
|
|
|
|
//
|
|
|
|
|
// f := excelize.NewFile()
|
|
|
|
|
// f.SetCellValue("Sheet1", "A6", 42920.5)
|
|
|
|
|
// style, err := f.NewStyle(`{"custom_number_format": "[$-380A]dddd\\,\\ dd\" de \"mmmm\" de \"yyyy;@"}`)
|
|
|
|
|
// exp := "[$-380A]dddd\\,\\ dd\" de \"mmmm\" de \"yyyy;@"
|
|
|
|
|
// style, err := f.NewStyle(&excelize.Style{CustomNumFmt: &exp})
|
|
|
|
|
// err = f.SetCellStyle("Sheet1", "A6", "A6", style)
|
|
|
|
|
//
|
|
|
|
|
// Cell Sheet1!A6 in the Excel Application: martes, 04 de Julio de 2017
|
|
|
|
|
//
|
|
|
|
|
func (f *File) NewStyle(style string) (int, error) {
|
|
|
|
|
func (f *File) NewStyle(style interface{}) (int, error) {
|
|
|
|
|
var fs *Style
|
|
|
|
|
var err error
|
|
|
|
|
var cellXfsID, fontID, borderID, fillID int
|
|
|
|
|
s := f.stylesReader()
|
|
|
|
|
fs, err := parseFormatStyleSet(style)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return cellXfsID, err
|
|
|
|
|
switch v := style.(type) {
|
|
|
|
|
case string:
|
|
|
|
|
fs, err = parseFormatStyleSet(v)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return cellXfsID, err
|
|
|
|
|
}
|
|
|
|
|
case *Style:
|
|
|
|
|
fs = v
|
|
|
|
|
}
|
|
|
|
|
s := f.stylesReader()
|
|
|
|
|
numFmtID := setNumFmt(s, fs)
|
|
|
|
|
|
|
|
|
|
if fs.Font != nil {
|
|
|
|
|
@ -1978,34 +1986,34 @@ func (f *File) readDefaultFont() *xlsxFont {
|
|
|
|
|
|
|
|
|
|
// setFont provides a function to add font style by given cell format
|
|
|
|
|
// settings.
|
|
|
|
|
func (f *File) setFont(formatStyle *formatStyle) *xlsxFont {
|
|
|
|
|
func (f *File) setFont(style *Style) *xlsxFont {
|
|
|
|
|
fontUnderlineType := map[string]string{"single": "single", "double": "double"}
|
|
|
|
|
if formatStyle.Font.Size < 1 {
|
|
|
|
|
formatStyle.Font.Size = 11
|
|
|
|
|
if style.Font.Size < 1 {
|
|
|
|
|
style.Font.Size = 11
|
|
|
|
|
}
|
|
|
|
|
if formatStyle.Font.Color == "" {
|
|
|
|
|
formatStyle.Font.Color = "#000000"
|
|
|
|
|
if style.Font.Color == "" {
|
|
|
|
|
style.Font.Color = "#000000"
|
|
|
|
|
}
|
|
|
|
|
fnt := xlsxFont{
|
|
|
|
|
Sz: &attrValFloat{Val: float64Ptr(formatStyle.Font.Size)},
|
|
|
|
|
Color: &xlsxColor{RGB: getPaletteColor(formatStyle.Font.Color)},
|
|
|
|
|
Name: &attrValString{Val: stringPtr(formatStyle.Font.Family)},
|
|
|
|
|
Sz: &attrValFloat{Val: float64Ptr(style.Font.Size)},
|
|
|
|
|
Color: &xlsxColor{RGB: getPaletteColor(style.Font.Color)},
|
|
|
|
|
Name: &attrValString{Val: stringPtr(style.Font.Family)},
|
|
|
|
|
Family: &attrValInt{Val: intPtr(2)},
|
|
|
|
|
}
|
|
|
|
|
if formatStyle.Font.Bold {
|
|
|
|
|
fnt.B = &formatStyle.Font.Bold
|
|
|
|
|
if style.Font.Bold {
|
|
|
|
|
fnt.B = &style.Font.Bold
|
|
|
|
|
}
|
|
|
|
|
if formatStyle.Font.Italic {
|
|
|
|
|
fnt.I = &formatStyle.Font.Italic
|
|
|
|
|
if style.Font.Italic {
|
|
|
|
|
fnt.I = &style.Font.Italic
|
|
|
|
|
}
|
|
|
|
|
if *fnt.Name.Val == "" {
|
|
|
|
|
*fnt.Name.Val = f.GetDefaultFont()
|
|
|
|
|
}
|
|
|
|
|
if formatStyle.Font.Strike {
|
|
|
|
|
if style.Font.Strike {
|
|
|
|
|
strike := true
|
|
|
|
|
fnt.Strike = &strike
|
|
|
|
|
}
|
|
|
|
|
val, ok := fontUnderlineType[formatStyle.Font.Underline]
|
|
|
|
|
val, ok := fontUnderlineType[style.Font.Underline]
|
|
|
|
|
if ok {
|
|
|
|
|
fnt.U = &attrValString{Val: stringPtr(val)}
|
|
|
|
|
}
|
|
|
|
|
@ -2014,36 +2022,36 @@ func (f *File) setFont(formatStyle *formatStyle) *xlsxFont {
|
|
|
|
|
|
|
|
|
|
// setNumFmt provides a function to check if number format code in the range
|
|
|
|
|
// of built-in values.
|
|
|
|
|
func setNumFmt(style *xlsxStyleSheet, formatStyle *formatStyle) int {
|
|
|
|
|
func setNumFmt(styleSheet *xlsxStyleSheet, style *Style) int {
|
|
|
|
|
dp := "0."
|
|
|
|
|
numFmtID := 164 // Default custom number format code from 164.
|
|
|
|
|
if formatStyle.DecimalPlaces < 0 || formatStyle.DecimalPlaces > 30 {
|
|
|
|
|
formatStyle.DecimalPlaces = 2
|
|
|
|
|
if style.DecimalPlaces < 0 || style.DecimalPlaces > 30 {
|
|
|
|
|
style.DecimalPlaces = 2
|
|
|
|
|
}
|
|
|
|
|
for i := 0; i < formatStyle.DecimalPlaces; i++ {
|
|
|
|
|
for i := 0; i < style.DecimalPlaces; i++ {
|
|
|
|
|
dp += "0"
|
|
|
|
|
}
|
|
|
|
|
if formatStyle.CustomNumFmt != nil {
|
|
|
|
|
return setCustomNumFmt(style, formatStyle)
|
|
|
|
|
if style.CustomNumFmt != nil {
|
|
|
|
|
return setCustomNumFmt(styleSheet, style)
|
|
|
|
|
}
|
|
|
|
|
_, ok := builtInNumFmt[formatStyle.NumFmt]
|
|
|
|
|
_, ok := builtInNumFmt[style.NumFmt]
|
|
|
|
|
if !ok {
|
|
|
|
|
fc, currency := currencyNumFmt[formatStyle.NumFmt]
|
|
|
|
|
fc, currency := currencyNumFmt[style.NumFmt]
|
|
|
|
|
if !currency {
|
|
|
|
|
return setLangNumFmt(style, formatStyle)
|
|
|
|
|
return setLangNumFmt(styleSheet, style)
|
|
|
|
|
}
|
|
|
|
|
fc = strings.Replace(fc, "0.00", dp, -1)
|
|
|
|
|
if formatStyle.NegRed {
|
|
|
|
|
if style.NegRed {
|
|
|
|
|
fc = fc + ";[Red]" + fc
|
|
|
|
|
}
|
|
|
|
|
if style.NumFmts != nil {
|
|
|
|
|
numFmtID = style.NumFmts.NumFmt[len(style.NumFmts.NumFmt)-1].NumFmtID + 1
|
|
|
|
|
if styleSheet.NumFmts != nil {
|
|
|
|
|
numFmtID = styleSheet.NumFmts.NumFmt[len(styleSheet.NumFmts.NumFmt)-1].NumFmtID + 1
|
|
|
|
|
nf := xlsxNumFmt{
|
|
|
|
|
FormatCode: fc,
|
|
|
|
|
NumFmtID: numFmtID,
|
|
|
|
|
}
|
|
|
|
|
style.NumFmts.NumFmt = append(style.NumFmts.NumFmt, &nf)
|
|
|
|
|
style.NumFmts.Count++
|
|
|
|
|
styleSheet.NumFmts.NumFmt = append(styleSheet.NumFmts.NumFmt, &nf)
|
|
|
|
|
styleSheet.NumFmts.Count++
|
|
|
|
|
} else {
|
|
|
|
|
nf := xlsxNumFmt{
|
|
|
|
|
FormatCode: fc,
|
|
|
|
|
@ -2053,61 +2061,61 @@ func setNumFmt(style *xlsxStyleSheet, formatStyle *formatStyle) int {
|
|
|
|
|
NumFmt: []*xlsxNumFmt{&nf},
|
|
|
|
|
Count: 1,
|
|
|
|
|
}
|
|
|
|
|
style.NumFmts = &numFmts
|
|
|
|
|
styleSheet.NumFmts = &numFmts
|
|
|
|
|
}
|
|
|
|
|
return numFmtID
|
|
|
|
|
}
|
|
|
|
|
return formatStyle.NumFmt
|
|
|
|
|
return style.NumFmt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// setCustomNumFmt provides a function to set custom number format code.
|
|
|
|
|
func setCustomNumFmt(style *xlsxStyleSheet, formatStyle *formatStyle) int {
|
|
|
|
|
nf := xlsxNumFmt{FormatCode: *formatStyle.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)
|
|
|
|
|
style.NumFmts.Count++
|
|
|
|
|
func setCustomNumFmt(styleSheet *xlsxStyleSheet, style *Style) int {
|
|
|
|
|
nf := xlsxNumFmt{FormatCode: *style.CustomNumFmt}
|
|
|
|
|
if styleSheet.NumFmts != nil {
|
|
|
|
|
nf.NumFmtID = styleSheet.NumFmts.NumFmt[len(styleSheet.NumFmts.NumFmt)-1].NumFmtID + 1
|
|
|
|
|
styleSheet.NumFmts.NumFmt = append(styleSheet.NumFmts.NumFmt, &nf)
|
|
|
|
|
styleSheet.NumFmts.Count++
|
|
|
|
|
} else {
|
|
|
|
|
nf.NumFmtID = 164
|
|
|
|
|
numFmts := xlsxNumFmts{
|
|
|
|
|
NumFmt: []*xlsxNumFmt{&nf},
|
|
|
|
|
Count: 1,
|
|
|
|
|
}
|
|
|
|
|
style.NumFmts = &numFmts
|
|
|
|
|
styleSheet.NumFmts = &numFmts
|
|
|
|
|
}
|
|
|
|
|
return nf.NumFmtID
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// setLangNumFmt provides a function to set number format code with language.
|
|
|
|
|
func setLangNumFmt(style *xlsxStyleSheet, formatStyle *formatStyle) int {
|
|
|
|
|
numFmts, ok := langNumFmt[formatStyle.Lang]
|
|
|
|
|
func setLangNumFmt(styleSheet *xlsxStyleSheet, style *Style) int {
|
|
|
|
|
numFmts, ok := langNumFmt[style.Lang]
|
|
|
|
|
if !ok {
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
var fc string
|
|
|
|
|
fc, ok = numFmts[formatStyle.NumFmt]
|
|
|
|
|
fc, ok = numFmts[style.NumFmt]
|
|
|
|
|
if !ok {
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
nf := xlsxNumFmt{FormatCode: fc}
|
|
|
|
|
if style.NumFmts != nil {
|
|
|
|
|
nf.NumFmtID = style.NumFmts.NumFmt[len(style.NumFmts.NumFmt)-1].NumFmtID + 1
|
|
|
|
|
style.NumFmts.NumFmt = append(style.NumFmts.NumFmt, &nf)
|
|
|
|
|
style.NumFmts.Count++
|
|
|
|
|
if styleSheet.NumFmts != nil {
|
|
|
|
|
nf.NumFmtID = styleSheet.NumFmts.NumFmt[len(styleSheet.NumFmts.NumFmt)-1].NumFmtID + 1
|
|
|
|
|
styleSheet.NumFmts.NumFmt = append(styleSheet.NumFmts.NumFmt, &nf)
|
|
|
|
|
styleSheet.NumFmts.Count++
|
|
|
|
|
} else {
|
|
|
|
|
nf.NumFmtID = formatStyle.NumFmt
|
|
|
|
|
nf.NumFmtID = style.NumFmt
|
|
|
|
|
numFmts := xlsxNumFmts{
|
|
|
|
|
NumFmt: []*xlsxNumFmt{&nf},
|
|
|
|
|
Count: 1,
|
|
|
|
|
}
|
|
|
|
|
style.NumFmts = &numFmts
|
|
|
|
|
styleSheet.NumFmts = &numFmts
|
|
|
|
|
}
|
|
|
|
|
return nf.NumFmtID
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// setFills provides a function to add fill elements in the styles.xml by
|
|
|
|
|
// given cell format settings.
|
|
|
|
|
func setFills(formatStyle *formatStyle, fg bool) *xlsxFill {
|
|
|
|
|
func setFills(style *Style, fg bool) *xlsxFill {
|
|
|
|
|
var patterns = []string{
|
|
|
|
|
"none",
|
|
|
|
|
"solid",
|
|
|
|
|
@ -2138,15 +2146,15 @@ func setFills(formatStyle *formatStyle, fg bool) *xlsxFill {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var fill xlsxFill
|
|
|
|
|
switch formatStyle.Fill.Type {
|
|
|
|
|
switch style.Fill.Type {
|
|
|
|
|
case "gradient":
|
|
|
|
|
if len(formatStyle.Fill.Color) != 2 {
|
|
|
|
|
if len(style.Fill.Color) != 2 {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
var gradient xlsxGradientFill
|
|
|
|
|
switch formatStyle.Fill.Shading {
|
|
|
|
|
switch style.Fill.Shading {
|
|
|
|
|
case 0, 1, 2, 3:
|
|
|
|
|
gradient.Degree = variants[formatStyle.Fill.Shading]
|
|
|
|
|
gradient.Degree = variants[style.Fill.Shading]
|
|
|
|
|
case 4:
|
|
|
|
|
gradient.Type = "path"
|
|
|
|
|
case 5:
|
|
|
|
|
@ -2159,7 +2167,7 @@ func setFills(formatStyle *formatStyle, fg bool) *xlsxFill {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
var stops []*xlsxGradientFillStop
|
|
|
|
|
for index, color := range formatStyle.Fill.Color {
|
|
|
|
|
for index, color := range style.Fill.Color {
|
|
|
|
|
var stop xlsxGradientFillStop
|
|
|
|
|
stop.Position = float64(index)
|
|
|
|
|
stop.Color.RGB = getPaletteColor(color)
|
|
|
|
|
@ -2168,18 +2176,18 @@ func setFills(formatStyle *formatStyle, fg bool) *xlsxFill {
|
|
|
|
|
gradient.Stop = stops
|
|
|
|
|
fill.GradientFill = &gradient
|
|
|
|
|
case "pattern":
|
|
|
|
|
if formatStyle.Fill.Pattern > 18 || formatStyle.Fill.Pattern < 0 {
|
|
|
|
|
if style.Fill.Pattern > 18 || style.Fill.Pattern < 0 {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
if len(formatStyle.Fill.Color) < 1 {
|
|
|
|
|
if len(style.Fill.Color) < 1 {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
var pattern xlsxPatternFill
|
|
|
|
|
pattern.PatternType = patterns[formatStyle.Fill.Pattern]
|
|
|
|
|
pattern.PatternType = patterns[style.Fill.Pattern]
|
|
|
|
|
if fg {
|
|
|
|
|
pattern.FgColor.RGB = getPaletteColor(formatStyle.Fill.Color[0])
|
|
|
|
|
pattern.FgColor.RGB = getPaletteColor(style.Fill.Color[0])
|
|
|
|
|
} else {
|
|
|
|
|
pattern.BgColor.RGB = getPaletteColor(formatStyle.Fill.Color[0])
|
|
|
|
|
pattern.BgColor.RGB = getPaletteColor(style.Fill.Color[0])
|
|
|
|
|
}
|
|
|
|
|
fill.PatternFill = &pattern
|
|
|
|
|
default:
|
|
|
|
|
@ -2192,36 +2200,36 @@ func setFills(formatStyle *formatStyle, fg bool) *xlsxFill {
|
|
|
|
|
// 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(formatStyle *formatStyle) *xlsxAlignment {
|
|
|
|
|
func setAlignment(style *Style) *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
|
|
|
|
|
if style.Alignment != nil {
|
|
|
|
|
alignment.Horizontal = style.Alignment.Horizontal
|
|
|
|
|
alignment.Indent = style.Alignment.Indent
|
|
|
|
|
alignment.JustifyLastLine = style.Alignment.JustifyLastLine
|
|
|
|
|
alignment.ReadingOrder = style.Alignment.ReadingOrder
|
|
|
|
|
alignment.RelativeIndent = style.Alignment.RelativeIndent
|
|
|
|
|
alignment.ShrinkToFit = style.Alignment.ShrinkToFit
|
|
|
|
|
alignment.TextRotation = style.Alignment.TextRotation
|
|
|
|
|
alignment.Vertical = style.Alignment.Vertical
|
|
|
|
|
alignment.WrapText = style.Alignment.WrapText
|
|
|
|
|
}
|
|
|
|
|
return &alignment
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// setProtection provides a function to set protection properties associated
|
|
|
|
|
// with the cell.
|
|
|
|
|
func setProtection(formatStyle *formatStyle) *xlsxProtection {
|
|
|
|
|
func setProtection(style *Style) *xlsxProtection {
|
|
|
|
|
var protection xlsxProtection
|
|
|
|
|
if formatStyle.Protection != nil {
|
|
|
|
|
protection.Hidden = formatStyle.Protection.Hidden
|
|
|
|
|
protection.Locked = formatStyle.Protection.Locked
|
|
|
|
|
if style.Protection != nil {
|
|
|
|
|
protection.Hidden = style.Protection.Hidden
|
|
|
|
|
protection.Locked = style.Protection.Locked
|
|
|
|
|
}
|
|
|
|
|
return &protection
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// setBorders provides a function to add border elements in the styles.xml by
|
|
|
|
|
// given borders format settings.
|
|
|
|
|
func setBorders(formatStyle *formatStyle) *xlsxBorder {
|
|
|
|
|
func setBorders(style *Style) *xlsxBorder {
|
|
|
|
|
var styles = []string{
|
|
|
|
|
"none",
|
|
|
|
|
"thin",
|
|
|
|
|
@ -2240,7 +2248,7 @@ func setBorders(formatStyle *formatStyle) *xlsxBorder {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var border xlsxBorder
|
|
|
|
|
for _, v := range formatStyle.Border {
|
|
|
|
|
for _, v := range style.Border {
|
|
|
|
|
if 0 <= v.Style && v.Style < 14 {
|
|
|
|
|
var color xlsxColor
|
|
|
|
|
color.RGB = getPaletteColor(v.Color)
|
|
|
|
|
|