Explorar o código

Resolve #470, export Style structs to allow create the style for cells by given JSON or structure

xuri %!s(int64=5) %!d(string=hai) anos
pai
achega
9e2318cefa
Modificáronse 8 ficheiros con 207 adicións e 126 borrados
  1. 1 1
      excelize.go
  2. 39 1
      excelize_test.go
  3. 1 1
      shape.go
  4. 92 84
      styles.go
  5. 23 0
      styles_test.go
  6. 1 1
      xmlChart.go
  7. 2 2
      xmlDrawing.go
  8. 48 36
      xmlStyles.go

+ 1 - 1
excelize.go

@@ -137,7 +137,7 @@ func (f *File) setDefaultTimeStyle(sheet, axis string, format int) error {
 		return err
 	}
 	if s == 0 {
-		style, _ := f.NewStyle(`{"number_format": ` + strconv.Itoa(format) + `}`)
+		style, _ := f.NewStyle(&Style{NumFmt: format})
 		_ = f.SetCellStyle(sheet, axis, axis, style)
 	}
 	return err

+ 39 - 1
excelize_test.go

@@ -580,7 +580,45 @@ func TestSetCellStyleBorder(t *testing.T) {
 	assert.NoError(t, f.SetCellStyle("Sheet1", "M28", "K24", style))
 
 	// Test set border and solid style pattern fill for a single cell.
-	style, err = f.NewStyle(`{"border":[{"type":"left","color":"0000FF","style":8},{"type":"top","color":"00FF00","style":9},{"type":"bottom","color":"FFFF00","style":10},{"type":"right","color":"FF0000","style":11},{"type":"diagonalDown","color":"A020F0","style":12},{"type":"diagonalUp","color":"A020F0","style":13}],"fill":{"type":"pattern","color":["#E0EBF5"],"pattern":1}}`)
+	style, err = f.NewStyle(&Style{
+		Border: []Border{
+			{
+				Type:  "left",
+				Color: "0000FF",
+				Style: 8,
+			},
+			{
+				Type:  "top",
+				Color: "00FF00",
+				Style: 9,
+			},
+			{
+				Type:  "bottom",
+				Color: "FFFF00",
+				Style: 10,
+			},
+			{
+				Type:  "right",
+				Color: "FF0000",
+				Style: 11,
+			},
+			{
+				Type:  "diagonalDown",
+				Color: "A020F0",
+				Style: 12,
+			},
+			{
+				Type:  "diagonalUp",
+				Color: "A020F0",
+				Style: 13,
+			},
+		},
+		Fill: Fill{
+			Type:    "pattern",
+			Color:   []string{"#E0EBF5"},
+			Pattern: 1,
+		},
+	})
 	if !assert.NoError(t, err) {
 		t.FailNow()
 	}

+ 1 - 1
shape.go

@@ -378,7 +378,7 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, formatSet *format
 	if len(formatSet.Paragraph) < 1 {
 		formatSet.Paragraph = []formatShapeParagraph{
 			{
-				Font: formatFont{
+				Font: Font{
 					Bold:      false,
 					Italic:    false,
 					Underline: "none",

+ 92 - 84
styles.go

@@ -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)

+ 23 - 0
styles_test.go

@@ -191,6 +191,8 @@ func TestNewStyle(t *testing.T) {
 	font := styles.Fonts.Font[fontID]
 	assert.Contains(t, *font.Name.Val, "Times New Roman", "Stored font should contain font name")
 	assert.Equal(t, 2, styles.CellXfs.Count, "Should have 2 styles")
+	_, err = f.NewStyle(&Style{})
+	assert.NoError(t, err)
 }
 
 func TestGetDefaultFont(t *testing.T) {
@@ -207,3 +209,24 @@ func TestSetDefaultFont(t *testing.T) {
 	assert.Equal(t, s, "Ariel", "Default font should change to Ariel")
 	assert.Equal(t, *styles.CellStyles.CellStyle[0].CustomBuiltIn, true)
 }
+
+func TestStylesReader(t *testing.T) {
+	f := NewFile()
+	// Test read styles with unsupport charset.
+	f.Styles = nil
+	f.XLSX["xl/styles.xml"] = MacintoshCyrillicCharset
+	assert.EqualValues(t, new(xlsxStyleSheet), f.stylesReader())
+}
+
+func TestThemeReader(t *testing.T) {
+	f := NewFile()
+	// Test read theme with unsupport charset.
+	f.XLSX["xl/theme/theme1.xml"] = MacintoshCyrillicCharset
+	assert.EqualValues(t, new(xlsxTheme), f.themeReader())
+}
+
+func TestSetCellStyle(t *testing.T) {
+	f := NewFile()
+	// Test set cell style on not exists worksheet.
+	assert.EqualError(t, f.SetCellStyle("SheetN", "A1", "A2", 1), "sheet SheetN is not exist")
+}

+ 1 - 1
xmlChart.go

@@ -604,7 +604,7 @@ type formatChart struct {
 type formatChartLegend struct {
 	None            bool         `json:"none"`
 	DeleteSeries    []int        `json:"delete_series"`
-	Font            formatFont   `json:"font"`
+	Font            Font         `json:"font"`
 	Layout          formatLayout `json:"layout"`
 	Position        string       `json:"position"`
 	ShowLegendEntry bool         `json:"show_legend_entry"`

+ 2 - 2
xmlDrawing.go

@@ -417,8 +417,8 @@ type formatShape struct {
 // formatShapeParagraph directly maps the format settings of the paragraph in
 // the shape.
 type formatShapeParagraph struct {
-	Font formatFont `json:"font"`
-	Text string     `json:"text"`
+	Font Font   `json:"font"`
+	Text string `json:"text"`
 }
 
 // formatShapeColor directly maps the color settings of the shape.

+ 48 - 36
xmlStyles.go

@@ -313,8 +313,28 @@ type xlsxStyleColors struct {
 	Color string `xml:",innerxml"`
 }
 
-// formatFont directly maps the styles settings of the fonts.
-type formatFont struct {
+// Alignment directly maps the alignment settings of the cells.
+type Alignment struct {
+	Horizontal      string `json:"horizontal"`
+	Indent          int    `json:"indent"`
+	JustifyLastLine bool   `json:"justify_last_line"`
+	ReadingOrder    uint64 `json:"reading_order"`
+	RelativeIndent  int    `json:"relative_indent"`
+	ShrinkToFit     bool   `json:"shrink_to_fit"`
+	TextRotation    int    `json:"text_rotation"`
+	Vertical        string `json:"vertical"`
+	WrapText        bool   `json:"wrap_text"`
+}
+
+// Border directly maps the border settings of the cells.
+type Border struct {
+	Type  string `json:"type"`
+	Color string `json:"color"`
+	Style int    `json:"style"`
+}
+
+// Font directly maps the font settings of the fonts.
+type Font struct {
 	Bold      bool    `json:"bold"`
 	Italic    bool    `json:"italic"`
 	Underline string  `json:"underline"`
@@ -324,38 +344,30 @@ type formatFont struct {
 	Color     string  `json:"color"`
 }
 
-// formatStyle directly maps the styles settings of the cells.
-type formatStyle struct {
-	Border []struct {
-		Type  string `json:"type"`
-		Color string `json:"color"`
-		Style int    `json:"style"`
-	} `json:"border"`
-	Fill struct {
-		Type    string   `json:"type"`
-		Pattern int      `json:"pattern"`
-		Color   []string `json:"color"`
-		Shading int      `json:"shading"`
-	} `json:"fill"`
-	Font      *formatFont `json:"font"`
-	Alignment *struct {
-		Horizontal      string `json:"horizontal"`
-		Indent          int    `json:"indent"`
-		JustifyLastLine bool   `json:"justify_last_line"`
-		ReadingOrder    uint64 `json:"reading_order"`
-		RelativeIndent  int    `json:"relative_indent"`
-		ShrinkToFit     bool   `json:"shrink_to_fit"`
-		TextRotation    int    `json:"text_rotation"`
-		Vertical        string `json:"vertical"`
-		WrapText        bool   `json:"wrap_text"`
-	} `json:"alignment"`
-	Protection *struct {
-		Hidden bool `json:"hidden"`
-		Locked bool `json:"locked"`
-	} `json:"protection"`
-	NumFmt        int     `json:"number_format"`
-	DecimalPlaces int     `json:"decimal_places"`
-	CustomNumFmt  *string `json:"custom_number_format"`
-	Lang          string  `json:"lang"`
-	NegRed        bool    `json:"negred"`
+// Fill directly maps the fill settings of the cells.
+type Fill struct {
+	Type    string   `json:"type"`
+	Pattern int      `json:"pattern"`
+	Color   []string `json:"color"`
+	Shading int      `json:"shading"`
+}
+
+// Protection directly maps the protection settings of the cells.
+type Protection struct {
+	Hidden bool `json:"hidden"`
+	Locked bool `json:"locked"`
+}
+
+// Style directly maps the style settings of the cells.
+type Style struct {
+	Border        []Border    `json:"border"`
+	Fill          Fill        `json:"fill"`
+	Font          *Font       `json:"font"`
+	Alignment     *Alignment  `json:"alignment"`
+	Protection    *Protection `json:"protection"`
+	NumFmt        int         `json:"number_format"`
+	DecimalPlaces int         `json:"decimal_places"`
+	CustomNumFmt  *string     `json:"custom_number_format"`
+	Lang          string      `json:"lang"`
+	NegRed        bool        `json:"negred"`
 }