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 10 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) {