Browse Source

Correctly setup named styles.

Previously the relationship assumed that there was a cellStyleXfs.Xf at
the same index as the cellXf.Xf - however really we only use a
cellStyleXf.Xf when the cellXf.Xf has an XfId (which points to the
cellStyleXf.Xf index).  Reflect this when reading from file, and
output when marshaling.
Geoffrey J. Teale 9 years ago
parent
commit
715e7540fc
3 changed files with 70 additions and 24 deletions
  1. 9 8
      style.go
  2. 41 16
      xmlStyle.go
  3. 20 0
      xmlStyle_test.go

+ 9 - 8
style.go

@@ -5,14 +5,15 @@ import "strconv"
 // Style is a high level structure intended to provide user access to
 // the contents of Style within an XLSX file.
 type Style struct {
-	Border         Border
-	Fill           Fill
-	Font           Font
-	ApplyBorder    bool
-	ApplyFill      bool
-	ApplyFont      bool
-	ApplyAlignment bool
-	Alignment      Alignment
+	Border          Border
+	Fill            Fill
+	Font            Font
+	ApplyBorder     bool
+	ApplyFill       bool
+	ApplyFont       bool
+	ApplyAlignment  bool
+	Alignment       Alignment
+	NamedStyleIndex *int
 }
 
 // Return a new Style structure initialised with the default values.

+ 41 - 16
xmlStyle.go

@@ -116,7 +116,7 @@ func (styles *xlsxStyleSheet) getStyle(styleIndex int) (style *Style) {
 	if ok {
 		return
 	}
-	var styleXf xlsxXf
+	var namedStyleXf xlsxXf
 	style = &Style{}
 	style.Border = Border{}
 	style.Fill = Fill{}
@@ -126,18 +126,17 @@ func (styles *xlsxStyleSheet) getStyle(styleIndex int) (style *Style) {
 	if styleIndex > -1 && xfCount > 0 && styleIndex <= xfCount {
 		xf := styles.CellXfs.Xf[styleIndex]
 
-		// Google docs can produce output that has fewer
-		// CellStyleXfs than CellXfs - this copes with that.
-		if styleIndex < styles.CellStyleXfs.Count {
-			styleXf = styles.CellStyleXfs.Xf[styleIndex]
+		if xf.XfId != nil {
+			namedStyleXf = styles.CellStyleXfs.Xf[*xf.XfId]
+			style.NamedStyleIndex = xf.XfId
 		} else {
-			styleXf = xlsxXf{}
+			namedStyleXf = xlsxXf{}
 		}
 
-		style.ApplyBorder = xf.ApplyBorder || styleXf.ApplyBorder
-		style.ApplyFill = xf.ApplyFill || styleXf.ApplyFill
-		style.ApplyFont = xf.ApplyFont || styleXf.ApplyFont
-		style.ApplyAlignment = xf.ApplyAlignment || styleXf.ApplyAlignment
+		style.ApplyBorder = xf.ApplyBorder || namedStyleXf.ApplyBorder
+		style.ApplyFill = xf.ApplyFill || namedStyleXf.ApplyFill
+		style.ApplyFont = xf.ApplyFont || namedStyleXf.ApplyFont
+		style.ApplyAlignment = xf.ApplyAlignment || namedStyleXf.ApplyAlignment
 
 		if xf.BorderId > -1 && xf.BorderId < styles.Borders.Count {
 			var border xlsxBorder
@@ -356,6 +355,7 @@ func (styles *xlsxStyleSheet) Marshal() (result string, err error) {
 	var xborders string
 	var xcellStyleXfs string
 	var xcellXfs string
+	var xcellStyles string
 
 	var outputFontMap map[int]int = make(map[int]int)
 	var outputFillMap map[int]int = make(map[int]int)
@@ -400,6 +400,12 @@ func (styles *xlsxStyleSheet) Marshal() (result string, err error) {
 	}
 	result += xcellXfs
 
+	xcellStyles, err = styles.CellStyles.Marshal()
+	if err != nil {
+		return
+	}
+	result += xcellStyles
+
 	result += `</styleSheet>`
 	return
 }
@@ -754,17 +760,36 @@ func (line *xlsxLine) Equals(other xlsxLine) bool {
 }
 
 type xlsxCellStyles struct {
+	XMLName   xml.Name        `xml:"cellStyles"`
 	Count     int             `xml:"count,attr"`
 	CellStyle []xlsxCellStyle `xml:"cellStyle,omitempty"`
 }
 
+func (cellStyles *xlsxCellStyles) Marshal() (result string, err error) {
+	if cellStyles.Count > 0 {
+		result = fmt.Sprintf(`<cellStyles count="%d">`, cellStyles.Count)
+		for _, cellStyle := range cellStyles.CellStyle {
+			var xCellStyle []byte
+			xCellStyle, err = xml.Marshal(cellStyle)
+			if err != nil {
+				return
+			}
+			result += string(xCellStyle)
+		}
+		result += `</cellStyles>`
+	}
+	return
+
+}
+
 type xlsxCellStyle struct {
-	BuiltInId     *int   `xml:"builtInId,attr,omitempty"`
-	CustomBuiltIn *bool  `xml:"customBuiltIn,attr,omitempty"`
-	Hidden        *bool  `xml:"hidden,attr,omitempty"`
-	ILevel        *bool  `xml:"iLevel,attr,omitempty"`
-	Name          string `xml:"name,attr"`
-	XFId          int    `xml:"xfId,att"`
+	XMLName       xml.Name `xml:"cellStyle"`
+	BuiltInId     *int     `xml:"builtInId,attr,omitempty"`
+	CustomBuiltIn *bool    `xml:"customBuiltIn,attr,omitempty"`
+	Hidden        *bool    `xml:"hidden,attr,omitempty"`
+	ILevel        *bool    `xml:"iLevel,attr,omitempty"`
+	Name          string   `xml:"name,attr"`
+	XfId          int      `xml:"xfId,attr"`
 }
 
 // xlsxCellStyleXfs directly maps the cellStyleXfs element in the

+ 20 - 0
xmlStyle_test.go

@@ -110,6 +110,26 @@ func (x *XMLStyleSuite) TestMarshalXlsxStyleSheetWithACellStyleXf(c *C) {
 	c.Assert(string(result), Equals, expected)
 }
 
+// Test we produce valid output for a style file with one cellStyle definition.
+func (x *XMLStyleSuite) TestMarshalXlsxStyleSheetWithACellStyle(c *C) {
+	var builtInId int
+	styles := newXlsxStyleSheet(nil)
+	styles.CellStyles = xlsxCellStyles{Count: 1}
+	styles.CellStyles.CellStyle = make([]xlsxCellStyle, 1)
+
+	builtInId = 31
+	styles.CellStyles.CellStyle[0] = xlsxCellStyle{
+		Name:      "Bob",
+		BuiltInId: &builtInId, // XXX Todo - work out built-ins!
+		XfId:      0,
+	}
+	expected := `<?xml version="1.0" encoding="UTF-8"?>
+<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><cellStyles count="1"><cellStyle builtInId="31" name="Bob" xfId="0"></cellStyle></cellStyles></styleSheet>`
+	result, err := styles.Marshal()
+	c.Assert(err, IsNil)
+	c.Assert(string(result), Equals, expected)
+}
+
 // Test we produce valid output for a style file with one cellXf
 // definition.
 func (x *XMLStyleSuite) TestMarshalXlsxStyleSheetWithACellXf(c *C) {