Browse Source

Merge output-styles branch.

Geoffrey J. Teale 11 năm trước cách đây
mục cha
commit
87677e0c11
10 tập tin đã thay đổi với 234 bổ sung118 xóa
  1. 4 0
      cell.go
  2. 6 3
      file.go
  3. 65 13
      file_test.go
  4. 5 5
      lib.go
  5. 1 1
      row.go
  6. 1 1
      sheet.go
  7. 31 31
      sheet_test.go
  8. 3 1
      style.go
  9. 0 4
      templates.go
  10. 118 59
      xmlStyle.go

+ 4 - 0
cell.go

@@ -22,6 +22,10 @@ type CellInterface interface {
 	FormattedValue() string
 }
 
+func NewCell() *Cell {
+	return &Cell{style: *NewStyle()}
+}
+
 // String returns the value of a Cell as a string.
 func (c *Cell) String() string {
 	return c.FormattedValue()

+ 6 - 3
file.go

@@ -16,7 +16,7 @@ type File struct {
 	numFmtRefTable map[int]xlsxNumFmt
 	referenceTable *RefTable
 	Date1904       bool
-	styles         *xlsxStyles
+	styles         *xlsxStyleSheet
 	Sheets         []*Sheet
 	Sheet          map[string]*Sheet
 }
@@ -144,7 +144,7 @@ func (f *File) MarshallParts() (map[string]string, error) {
 	workbook = f.makeWorkbook()
 	sheetIndex := 1
 
-	styles := &xlsxStyles{}
+	styles := &xlsxStyleSheet{}
 	for _, sheet := range f.Sheets {
 		xSheet := sheet.makeXLSXSheet(refTable, styles)
 		rId := fmt.Sprintf("rId%d", sheetIndex)
@@ -197,7 +197,10 @@ func (f *File) MarshallParts() (map[string]string, error) {
 		return parts, err
 	}
 
-	parts["xl/styles.xml"] = TEMPLATE_XL_STYLES
+	parts["xl/styles.xml"], err = marshal(styles)
+	if err != nil {
+		return parts, err
+	}
 
 	return parts, nil
 }

+ 65 - 13
file_test.go

@@ -71,32 +71,32 @@ func (l *FileSuite) TestReadStylesFromZipFile(c *C) {
 	c.Assert(err, IsNil)
 	c.Assert(xlsxFile.styles, NotNil)
 
-	fontCount = len(xlsxFile.styles.Fonts)
+	fontCount = len(xlsxFile.styles.Fonts.Font)
 	c.Assert(fontCount, Equals, 4)
 
-	font = xlsxFile.styles.Fonts[0]
+	font = xlsxFile.styles.Fonts.Font[0]
 	c.Assert(font.Sz.Val, Equals, "11")
 	c.Assert(font.Name.Val, Equals, "Calibri")
 
-	fillCount = len(xlsxFile.styles.Fills)
+	fillCount = xlsxFile.styles.Fills.Count
 	c.Assert(fillCount, Equals, 3)
 
-	fill = xlsxFile.styles.Fills[2]
+	fill = xlsxFile.styles.Fills.Fill[2]
 	c.Assert(fill.PatternFill.PatternType, Equals, "solid")
 
-	borderCount = len(xlsxFile.styles.Borders)
+	borderCount = xlsxFile.styles.Borders.Count
 	c.Assert(borderCount, Equals, 2)
 
-	border = xlsxFile.styles.Borders[1]
+	border = xlsxFile.styles.Borders.Border[1]
 	c.Assert(border.Left.Style, Equals, "thin")
 	c.Assert(border.Right.Style, Equals, "thin")
 	c.Assert(border.Top.Style, Equals, "thin")
 	c.Assert(border.Bottom.Style, Equals, "thin")
 
-	cellStyleXfCount = len(xlsxFile.styles.CellStyleXfs)
+	cellStyleXfCount = xlsxFile.styles.CellStyleXfs.Count
 	c.Assert(cellStyleXfCount, Equals, 20)
 
-	xf = xlsxFile.styles.CellStyleXfs[0]
+	xf = xlsxFile.styles.CellStyleXfs.Xf[0]
 	expectedXf := &xlsxXf{
 		ApplyAlignment:  true,
 		ApplyBorder:     true,
@@ -109,10 +109,10 @@ func (l *FileSuite) TestReadStylesFromZipFile(c *C) {
 		NumFmtId:        164}
 	testXf(c, &xf, expectedXf)
 
-	cellXfCount = len(xlsxFile.styles.CellXfs)
+	cellXfCount = xlsxFile.styles.CellXfs.Count
 	c.Assert(cellXfCount, Equals, 3)
 
-	xf = xlsxFile.styles.CellXfs[0]
+	xf = xlsxFile.styles.CellXfs.Xf[0]
 	expectedXf = &xlsxXf{
 		ApplyAlignment:  false,
 		ApplyBorder:     false,
@@ -717,9 +717,61 @@ func (l *FileSuite) TestMarshalFile(c *C) {
 	//
 	// For now we only allow simple string data in the
 	// spreadsheet.  Style support will follow.
-	expectedStyles := `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
-</styleSheet>`
+	expectedStyles := `<?xml version="1.0" encoding="UTF-8"?>
+  <styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
+    <fonts count="2">
+      <font>
+        <sz val="12"></sz>
+        <name val="Verdana"></name>
+        <family val="0"></family>
+        <charset val="0"></charset>
+        <color></color>
+      </font>
+      <font>
+        <sz val="12"></sz>
+        <name val="Verdana"></name>
+        <family val="0"></family>
+        <charset val="0"></charset>
+        <color></color>
+      </font>
+    </fonts>
+    <fills count="2">
+      <fill>
+        <patternFill>
+          <fgColor></fgColor>
+          <bgColor></bgColor>
+        </patternFill>
+      </fill>
+      <fill>
+        <patternFill>
+          <fgColor></fgColor>
+          <bgColor></bgColor>
+        </patternFill>
+      </fill>
+    </fills>
+    <borders count="2">
+      <border>
+        <left></left>
+        <right></right>
+        <top></top>
+        <bottom></bottom>
+      </border>
+      <border>
+        <left></left>
+        <right></right>
+        <top></top>
+        <bottom></bottom>
+      </border>
+    </borders>
+    <cellStyleXfs count="2">
+      <xf applyAlignment="false" applyBorder="false" applyFont="false" applyFill="false" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"></xf>
+      <xf applyAlignment="false" applyBorder="false" applyFont="false" applyFill="false" applyProtection="false" borderId="1" fillId="1" fontId="1" numFmtId="0"></xf>
+    </cellStyleXfs>
+    <cellXfs count="2">
+      <xf applyAlignment="false" applyBorder="false" applyFont="false" applyFill="false" applyProtection="false" borderId="0" fillId="0" fontId="0" numFmtId="0"></xf>
+      <xf applyAlignment="false" applyBorder="false" applyFont="false" applyFill="false" applyProtection="false" borderId="1" fillId="1" fontId="1" numFmtId="0"></xf>
+    </cellXfs>
+  </styleSheet>`
 	c.Assert(parts["xl/styles.xml"], Equals, expectedStyles)
 }
 

+ 5 - 5
lib.go

@@ -517,8 +517,8 @@ func readSharedStringsFromZipFile(f *zip.File) (*RefTable, error) {
 // readStylesFromZipFile() is an internal helper function to
 // extract a style table from the style.xml file within
 // the XLSX zip file.
-func readStylesFromZipFile(f *zip.File) (*xlsxStyles, error) {
-	var style *xlsxStyles
+func readStylesFromZipFile(f *zip.File) (*xlsxStyleSheet, error) {
+	var style *xlsxStyleSheet
 	var error error
 	var rc io.ReadCloser
 	var decoder *xml.Decoder
@@ -526,7 +526,7 @@ func readStylesFromZipFile(f *zip.File) (*xlsxStyles, error) {
 	if error != nil {
 		return nil, error
 	}
-	style = new(xlsxStyles)
+	style = new(xlsxStyleSheet)
 	decoder = xml.NewDecoder(rc)
 	error = decoder.Decode(style)
 	if error != nil {
@@ -535,7 +535,7 @@ func readStylesFromZipFile(f *zip.File) (*xlsxStyles, error) {
 	return style, nil
 }
 
-func buildNumFmtRefTable(style *xlsxStyles) map[int]xlsxNumFmt {
+func buildNumFmtRefTable(style *xlsxStyleSheet) map[int]xlsxNumFmt {
 	refTable := make(map[int]xlsxNumFmt)
 	for _, numFmt := range style.NumFmts {
 		refTable[numFmt.NumFmtId] = numFmt
@@ -633,7 +633,7 @@ func ReadZipReader(r *zip.Reader) (*File, error) {
 	var sheetXMLMap map[string]string
 	var sheetsByName map[string]*Sheet
 	var sheets []*Sheet
-	var style *xlsxStyles
+	var style *xlsxStyleSheet
 	var styles *zip.File
 	var v *zip.File
 	var workbook *zip.File

+ 1 - 1
row.go

@@ -7,7 +7,7 @@ type Row struct {
 }
 
 func (r *Row) AddCell() *Cell {
-	cell := &Cell{}
+	cell := NewCell()
 	r.Cells = append(r.Cells, cell)
 	r.sheet.maybeAddCol(len(r.Cells))
 	return cell

+ 1 - 1
sheet.go

@@ -54,7 +54,7 @@ func (sh *Sheet) Cell(row, col int) *Cell {
 }
 
 // Dump sheet to it's XML representation, intended for internal use only
-func (s *Sheet) makeXLSXSheet(refTable *RefTable, styles *xlsxStyles) *xlsxWorksheet {
+func (s *Sheet) makeXLSXSheet(refTable *RefTable, styles *xlsxStyleSheet) *xlsxWorksheet {
 	worksheet := &xlsxWorksheet{}
 	xSheet := xlsxSheetData{}
 	maxRow := 0

+ 31 - 31
sheet_test.go

@@ -28,7 +28,7 @@ func (s *SheetSuite) TestMakeXLSXSheetFromRows(c *C) {
 	cell := row.AddCell()
 	cell.Value = "A cell!"
 	refTable := NewSharedStringRefTable()
-	styles := &xlsxStyles{}
+	styles := &xlsxStyleSheet{}
 	xSheet := sheet.makeXLSXSheet(refTable, styles)
 	c.Assert(xSheet.Dimension.Ref, Equals, "A1:A1")
 	c.Assert(xSheet.SheetData.Row, HasLen, 1)
@@ -74,43 +74,43 @@ func (s *SheetSuite) TestMakeXLSXSheetAlsoPopulatesXLSXSTyles(c *C) {
 	cell2.SetStyle(style2)
 
 	refTable := NewSharedStringRefTable()
-	styles := &xlsxStyles{}
+	styles := &xlsxStyleSheet{}
 	worksheet := sheet.makeXLSXSheet(refTable, styles)
 
-	c.Assert(len(styles.Fonts), Equals, 2)
-	c.Assert(styles.Fonts[0].Sz.Val, Equals, "10")
-	c.Assert(styles.Fonts[0].Name.Val, Equals, "Verdana")
+	c.Assert(styles.Fonts.Count, Equals, 2)
+	c.Assert(styles.Fonts.Font[0].Sz.Val, Equals, "10")
+	c.Assert(styles.Fonts.Font[0].Name.Val, Equals, "Verdana")
 
-	c.Assert(len(styles.Fills), Equals, 2)
-	c.Assert(styles.Fills[0].PatternFill.PatternType, Equals, "solid")
-	c.Assert(styles.Fills[0].PatternFill.FgColor.RGB, Equals, "FFFFFFFF")
-	c.Assert(styles.Fills[0].PatternFill.BgColor.RGB, Equals, "00000000")
+	c.Assert(styles.Fills.Count, Equals, 2)
+	c.Assert(styles.Fills.Fill[0].PatternFill.PatternType, Equals, "solid")
+	c.Assert(styles.Fills.Fill[0].PatternFill.FgColor.RGB, Equals, "FFFFFFFF")
+	c.Assert(styles.Fills.Fill[0].PatternFill.BgColor.RGB, Equals, "00000000")
 
-	c.Assert(len(styles.Borders), Equals, 2)
-	c.Assert(styles.Borders[0].Left.Style, Equals, "none")
-	c.Assert(styles.Borders[0].Right.Style, Equals, "thin")
-	c.Assert(styles.Borders[0].Top.Style, Equals, "none")
-	c.Assert(styles.Borders[0].Bottom.Style, Equals, "thin")
+	c.Assert(styles.Borders.Count, Equals, 2)
+	c.Assert(styles.Borders.Border[0].Left.Style, Equals, "none")
+	c.Assert(styles.Borders.Border[0].Right.Style, Equals, "thin")
+	c.Assert(styles.Borders.Border[0].Top.Style, Equals, "none")
+	c.Assert(styles.Borders.Border[0].Bottom.Style, Equals, "thin")
 
-	c.Assert(len(styles.CellStyleXfs), Equals, 2)
+	c.Assert(styles.CellStyleXfs.Count, Equals, 2)
 	// The 0th CellStyleXf could just be getting the zero values by default
-	c.Assert(styles.CellStyleXfs[0].FontId, Equals, 0)
-	c.Assert(styles.CellStyleXfs[0].FillId, Equals, 0)
-	c.Assert(styles.CellStyleXfs[0].BorderId, Equals, 0)
+	c.Assert(styles.CellStyleXfs.Xf[0].FontId, Equals, 0)
+	c.Assert(styles.CellStyleXfs.Xf[0].FillId, Equals, 0)
+	c.Assert(styles.CellStyleXfs.Xf[0].BorderId, Equals, 0)
 	// The 1st element cannot get initialised this way by accident.
-	c.Assert(styles.CellStyleXfs[1].FontId, Equals, 1)
-	c.Assert(styles.CellStyleXfs[1].FillId, Equals, 1)
-	c.Assert(styles.CellStyleXfs[1].BorderId, Equals, 1)
-
-	c.Assert(len(styles.CellXfs), Equals, 2)
-	c.Assert(styles.CellXfs[0].FontId, Equals, 0)
-	c.Assert(styles.CellXfs[0].FillId, Equals, 0)
-	c.Assert(styles.CellXfs[0].BorderId, Equals, 0)
+	c.Assert(styles.CellStyleXfs.Xf[1].FontId, Equals, 1)
+	c.Assert(styles.CellStyleXfs.Xf[1].FillId, Equals, 1)
+	c.Assert(styles.CellStyleXfs.Xf[1].BorderId, Equals, 1)
+
+	c.Assert(styles.CellXfs.Count, Equals, 2)
+	c.Assert(styles.CellXfs.Xf[0].FontId, Equals, 0)
+	c.Assert(styles.CellXfs.Xf[0].FillId, Equals, 0)
+	c.Assert(styles.CellXfs.Xf[0].BorderId, Equals, 0)
 	// As above, we need the 1st element to make the test fail
 	// when it should.
-	c.Assert(styles.CellXfs[1].FontId, Equals, 1)
-	c.Assert(styles.CellXfs[1].FillId, Equals, 1)
-	c.Assert(styles.CellXfs[1].BorderId, Equals, 1)
+	c.Assert(styles.CellXfs.Xf[1].FontId, Equals, 1)
+	c.Assert(styles.CellXfs.Xf[1].FillId, Equals, 1)
+	c.Assert(styles.CellXfs.Xf[1].BorderId, Equals, 1)
 
 	// Finally we check that the cell points to the right CellXf /
 	// CellStyleXf.
@@ -125,7 +125,7 @@ func (s *SheetSuite) TestMarshalSheet(c *C) {
 	cell := row.AddCell()
 	cell.Value = "A cell!"
 	refTable := NewSharedStringRefTable()
-	styles := &xlsxStyles{}
+	styles := &xlsxStyleSheet{}
 	xSheet := sheet.makeXLSXSheet(refTable, styles)
 
 	output := bytes.NewBufferString(xml.Header)
@@ -160,7 +160,7 @@ func (s *SheetSuite) TestMarshalSheetWithMultipleCells(c *C) {
 	cell = row.AddCell()
 	cell.Value = "A cell (with value 2)!"
 	refTable := NewSharedStringRefTable()
-	styles := &xlsxStyles{}
+	styles := &xlsxStyleSheet{}
 	xSheet := sheet.makeXLSXSheet(refTable, styles)
 
 	output := bytes.NewBufferString(xml.Header)

+ 3 - 1
style.go

@@ -15,7 +15,7 @@ type Style struct {
 
 // Return a new Style structure initialised with the default values.
 func NewStyle() *Style {
-	return &Style{}
+	return &Style{Font: *NewFont(12, "Verdana")}
 }
 
 // Generate the underlying XLSX style elements that correspond to the Style.
@@ -29,6 +29,7 @@ func (style *Style) makeXLSXStyleElements() (xFont xlsxFont, xFill xlsxFill, xBo
 	xFont.Name.Val = style.Font.Name
 	xFont.Family.Val = strconv.Itoa(style.Font.Family)
 	xFont.Charset.Val = strconv.Itoa(style.Font.Charset)
+	xFont.Color.RGB = style.Font.Color
 	xPatternFill := xlsxPatternFill{}
 	xPatternFill.PatternType = style.Fill.PatternType
 	xPatternFill.FgColor.RGB = style.Fill.FgColor
@@ -77,6 +78,7 @@ type Font struct {
 	Name    string
 	Family  int
 	Charset int
+	Color   string
 }
 
 func NewFont(size int, name string) *Font {

+ 0 - 4
templates.go

@@ -337,7 +337,3 @@ const TEMPLATE_XL_THEME_THEME = `<?xml version="1.0" encoding="UTF-8" standalone
   </a:objectDefaults>
   <a:extraClrSchemeLst/>
 </a:theme>`
-
-const TEMPLATE_XL_STYLES = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
-</styleSheet>`

+ 118 - 59
xmlStyle.go

@@ -8,21 +8,24 @@
 package xlsx
 
 import (
+	"encoding/xml"
 	"strconv"
 	"strings"
 )
 
-// xlsxStyle directly maps the style element in the namespace
+// xlsxStyle directly maps the styleSheet element in the namespace
 // http://schemas.openxmlformats.org/spreadsheetml/2006/main -
 // currently I have not checked it for completeness - it does as much
 // as I need.
-type xlsxStyles struct {
-	Fonts        []xlsxFont   `xml:"fonts>font,"`
-	Fills        []xlsxFill   `xml:"fills>fill"`
-	Borders      []xlsxBorder `xml:"borders>border"`
-	CellStyleXfs []xlsxXf     `xml:"cellStyleXfs>xf"`
-	CellXfs      []xlsxXf     `xml:"cellXfs>xf"`
-	NumFmts      []xlsxNumFmt `xml:numFmts>numFmt"`
+type xlsxStyleSheet struct {
+	XMLName xml.Name `xml:"http://schemas.openxmlformats.org/spreadsheetml/2006/main styleSheet"`
+
+	Fonts        xlsxFonts        `xml:"fonts,omitempty"`
+	Fills        xlsxFills        `xml:"fills,omitempty"`
+	Borders      xlsxBorders      `xml:"borders,omitempty"`
+	CellStyleXfs xlsxCellStyleXfs `xml:"cellStyleXfs,omitempty"`
+	CellXfs      xlsxCellXfs      `xml:"cellXfs,omitempty"`
+	NumFmts      []xlsxNumFmt     `xml:numFmts>numFmt,omitempty"`
 }
 
 // xlsxNumFmt directly maps the numFmt element in the namespace
@@ -30,8 +33,17 @@ type xlsxStyles struct {
 // currently I have not checked it for completeness - it does as much
 // as I need.
 type xlsxNumFmt struct {
-	NumFmtId   int    `xml:"numFmtId"`
-	FormatCode string `xml:"formatCode"`
+	NumFmtId   int    `xml:"numFmtId,omitempty"`
+	FormatCode string `xml:"formatCode,omitempty"`
+}
+
+// xlsxFonts directly maps the fonts element in the namespace
+// http://schemas.openxmlformats.org/spreadsheetml/2006/main -
+// currently I have not checked it for completeness - it does as much
+// as I need.
+type xlsxFonts struct {
+	Count int        `xml:"count,attr"`
+	Font  []xlsxFont `xml:"font,omitempty"`
 }
 
 // xlsxFont directly maps the font element in the namespace
@@ -39,10 +51,11 @@ type xlsxNumFmt struct {
 // currently I have not checked it for completeness - it does as much
 // as I need.
 type xlsxFont struct {
-	Sz      xlsxVal `xml:"sz"`
-	Name    xlsxVal `xml:"name"`
-	Family  xlsxVal `xml:"family"`
-	Charset xlsxVal `xml:"charset"`
+	Sz      xlsxVal   `xml:"sz,omitempty"`
+	Name    xlsxVal   `xml:"name,omitempty"`
+	Family  xlsxVal   `xml:"family,omitempty"`
+	Charset xlsxVal   `xml:"charset,omitempty"`
+	Color   xlsxColor `xml:"color,omitempty"`
 }
 
 // xlsxVal directly maps the val element in the namespace
@@ -50,7 +63,16 @@ type xlsxFont struct {
 // currently I have not checked it for completeness - it does as much
 // as I need.
 type xlsxVal struct {
-	Val string `xml:"val,attr"`
+	Val string `xml:"val,attr,omitempty"`
+}
+
+// xlsxFills directly maps the fills element in the namespace
+// http://schemas.openxmlformats.org/spreadsheetml/2006/main -
+// currently I have not checked it for completeness - it does as much
+// as I need.
+type xlsxFills struct {
+	Count int        `xml:"count,attr"`
+	Fill  []xlsxFill `xml:"fill,omitempty"`
 }
 
 // xlsxFill directly maps the fill element in the namespace
@@ -58,7 +80,7 @@ type xlsxVal struct {
 // currently I have not checked it for completeness - it does as much
 // as I need.
 type xlsxFill struct {
-	PatternFill xlsxPatternFill `xml:"patternFill"`
+	PatternFill xlsxPatternFill `xml:"patternFill,omitempty"`
 }
 
 // xlsxPatternFill directly maps the patternFill element in the namespace
@@ -66,9 +88,9 @@ type xlsxFill struct {
 // currently I have not checked it for completeness - it does as much
 // as I need.
 type xlsxPatternFill struct {
-	PatternType string    `xml:"patternType,attr"`
-	FgColor     xlsxColor `xml:"fgColor"`
-	BgColor     xlsxColor `xml:"bgColor"`
+	PatternType string    `xml:"patternType,attr,omitempty"`
+	FgColor     xlsxColor `xml:"fgColor,omitempty"`
+	BgColor     xlsxColor `xml:"bgColor,omitempty"`
 }
 
 // xlsxColor is a common mapping used for both the fgColor and bgColor
@@ -77,7 +99,16 @@ type xlsxPatternFill struct {
 // currently I have not checked it for completeness - it does as much
 // as I need.
 type xlsxColor struct {
-	RGB string `xml:"rgb,attr"`
+	RGB string `xml:"rgb,attr,omitempty"`
+}
+
+// xlsxBorders directly maps the borders element in the namespace
+// http://schemas.openxmlformats.org/spreadsheetml/2006/main -
+// currently I have not checked it for completeness - it does as much
+// as I need.
+type xlsxBorders struct {
+	Count  int          `xml:"count,attr"`
+	Border []xlsxBorder `xml:"border,omitempty"`
 }
 
 // xlsxBorder directly maps the border element in the namespace
@@ -85,10 +116,10 @@ type xlsxColor struct {
 // currently I have not checked it for completeness - it does as much
 // as I need.
 type xlsxBorder struct {
-	Left   xlsxLine `xml:"left"`
-	Right  xlsxLine `xml:"right"`
-	Top    xlsxLine `xml:"top"`
-	Bottom xlsxLine `xml:"bottom"`
+	Left   xlsxLine `xml:"left,omitempty"`
+	Right  xlsxLine `xml:"right,omitempty"`
+	Top    xlsxLine `xml:"top,omitempty"`
+	Bottom xlsxLine `xml:"bottom,omitempty"`
 }
 
 // xlsxLine directly maps the line style element in the namespace
@@ -96,7 +127,25 @@ type xlsxBorder struct {
 // currently I have not checked it for completeness - it does as much
 // as I need.
 type xlsxLine struct {
-	Style string `xml:"style,attr"`
+	Style string `xml:"style,attr,omitempty"`
+}
+
+// xlsxCellStyleXfs directly maps the cellStyleXfs element in the
+// namespace http://schemas.openxmlformats.org/spreadsheetml/2006/main
+// - currently I have not checked it for completeness - it does as
+// much as I need.
+type xlsxCellStyleXfs struct {
+	Count int      `xml:"count,attr"`
+	Xf    []xlsxXf `xml:"xf,omitempty"`
+}
+
+// xlsxCellXfs directly maps the cellXfs element in the namespace
+// http://schemas.openxmlformats.org/spreadsheetml/2006/main -
+// currently I have not checked it for completeness - it does as much
+// as I need.
+type xlsxCellXfs struct {
+	Count int      `xml:"count,attr"`
+	Xf    []xlsxXf `xml:"xf,omitempty"`
 }
 
 // xlsxXf directly maps the xf element in the namespace
@@ -113,7 +162,7 @@ type xlsxXf struct {
 	FillId          int           `xml:"fillId,attr"`
 	FontId          int           `xml:"fontId,attr"`
 	NumFmtId        int           `xml:"numFmtId,attr"`
-	alignment       xlsxAlignment `xml:"alignement"`
+	alignment       xlsxAlignment `xml:"alignment"`
 }
 
 type xlsxAlignment struct {
@@ -125,21 +174,21 @@ type xlsxAlignment struct {
 	WrapText     bool   `xml:"wrapText,attr"`
 }
 
-func (styles *xlsxStyles) getStyle(styleIndex int) (style Style) {
+func (styles *xlsxStyleSheet) getStyle(styleIndex int) (style Style) {
 	var styleXf xlsxXf
 	style = Style{}
 	style.Border = Border{}
 	style.Fill = Fill{}
 	style.Font = Font{}
 
-	xfCount := len(styles.CellXfs)
+	xfCount := styles.CellXfs.Count
 	if styleIndex > -1 && xfCount > 0 && styleIndex <= xfCount {
-		xf := styles.CellXfs[styleIndex]
+		xf := styles.CellXfs.Xf[styleIndex]
 
 		// Google docs can produce output that has fewer
 		// CellStyleXfs than CellXfs - this copes with that.
-		if styleIndex < len(styles.CellStyleXfs) {
-			styleXf = styles.CellStyleXfs[styleIndex]
+		if styleIndex < styles.CellStyleXfs.Count {
+			styleXf = styles.CellStyleXfs.Xf[styleIndex]
 		} else {
 			styleXf = xlsxXf{}
 		}
@@ -148,22 +197,22 @@ func (styles *xlsxStyles) getStyle(styleIndex int) (style Style) {
 		style.ApplyFill = xf.ApplyFill || styleXf.ApplyFill
 		style.ApplyFont = xf.ApplyFont || styleXf.ApplyFont
 
-		if xf.BorderId > -1 && xf.BorderId < len(styles.Borders) {
-			style.Border.Left = styles.Borders[xf.BorderId].Left.Style
-			style.Border.Right = styles.Borders[xf.BorderId].Right.Style
-			style.Border.Top = styles.Borders[xf.BorderId].Top.Style
-			style.Border.Bottom = styles.Borders[xf.BorderId].Bottom.Style
+		if xf.BorderId > -1 && xf.BorderId < styles.Borders.Count {
+			style.Border.Left = styles.Borders.Border[xf.BorderId].Left.Style
+			style.Border.Right = styles.Borders.Border[xf.BorderId].Right.Style
+			style.Border.Top = styles.Borders.Border[xf.BorderId].Top.Style
+			style.Border.Bottom = styles.Borders.Border[xf.BorderId].Bottom.Style
 		}
 
-		if xf.FillId > -1 && xf.FillId < len(styles.Fills) {
-			xFill := styles.Fills[xf.FillId]
+		if xf.FillId > -1 && xf.FillId < styles.Fills.Count {
+			xFill := styles.Fills.Fill[xf.FillId]
 			style.Fill.PatternType = xFill.PatternFill.PatternType
 			style.Fill.FgColor = xFill.PatternFill.FgColor.RGB
 			style.Fill.BgColor = xFill.PatternFill.BgColor.RGB
 		}
 
-		if xf.FontId > -1 && xf.FontId < len(styles.Fonts) {
-			xfont := styles.Fonts[xf.FontId]
+		if xf.FontId > -1 && xf.FontId < styles.Fonts.Count {
+			xfont := styles.Fonts.Font[xf.FontId]
 			style.Font.Size, _ = strconv.Atoi(xfont.Sz.Val)
 			style.Font.Name = xfont.Name.Val
 			style.Font.Family, _ = strconv.Atoi(xfont.Family.Val)
@@ -174,40 +223,50 @@ func (styles *xlsxStyles) getStyle(styleIndex int) (style Style) {
 
 }
 
-func (styles *xlsxStyles) getNumberFormat(styleIndex int, numFmtRefTable map[int]xlsxNumFmt) string {
-	if styles.CellXfs == nil {
+func (styles *xlsxStyleSheet) getNumberFormat(styleIndex int, numFmtRefTable map[int]xlsxNumFmt) string {
+	if styles.CellXfs.Xf == nil {
 		return ""
 	}
 	var numberFormat string = ""
-	if styleIndex > -1 && styleIndex <= len(styles.CellXfs) {
-		xf := styles.CellXfs[styleIndex]
+	if styleIndex > -1 && styleIndex <= styles.CellXfs.Count {
+		xf := styles.CellXfs.Xf[styleIndex]
 		numFmt := numFmtRefTable[xf.NumFmtId]
 		numberFormat = numFmt.FormatCode
 	}
 	return strings.ToLower(numberFormat)
 }
 
-func (styles *xlsxStyles) addFont(xFont xlsxFont) int {
-	styles.Fonts = append(styles.Fonts, xFont)
-	return len(styles.Fonts) - 1
+func (styles *xlsxStyleSheet) addFont(xFont xlsxFont) (index int) {
+	styles.Fonts.Font = append(styles.Fonts.Font, xFont)
+	index = styles.Fonts.Count
+	styles.Fonts.Count += 1
+	return
 }
 
-func (styles *xlsxStyles) addFill(xFill xlsxFill) int {
-	styles.Fills = append(styles.Fills, xFill)
-	return len(styles.Fills) - 1
+func (styles *xlsxStyleSheet) addFill(xFill xlsxFill) (index int) {
+	styles.Fills.Fill = append(styles.Fills.Fill, xFill)
+	index = styles.Fills.Count
+	styles.Fills.Count += 1
+	return
 }
 
-func (styles *xlsxStyles) addBorder(xBorder xlsxBorder) int {
-	styles.Borders = append(styles.Borders, xBorder)
-	return len(styles.Borders) - 1
+func (styles *xlsxStyleSheet) addBorder(xBorder xlsxBorder) (index int) {
+	styles.Borders.Border = append(styles.Borders.Border, xBorder)
+	index = styles.Borders.Count
+	styles.Borders.Count += 1
+	return
 }
 
-func (styles *xlsxStyles) addCellStyleXf(xCellStyleXf xlsxXf) int {
-	styles.CellStyleXfs = append(styles.CellStyleXfs, xCellStyleXf)
-	return len(styles.CellStyleXfs) - 1
+func (styles *xlsxStyleSheet) addCellStyleXf(xCellStyleXf xlsxXf) (index int) {
+	styles.CellStyleXfs.Xf = append(styles.CellStyleXfs.Xf, xCellStyleXf)
+	index = styles.CellStyleXfs.Count
+	styles.CellStyleXfs.Count += 1
+	return
 }
 
-func (styles *xlsxStyles) addCellXf(xCellXf xlsxXf) int {
-	styles.CellXfs = append(styles.CellXfs, xCellXf)
-	return len(styles.CellXfs) - 1
+func (styles *xlsxStyleSheet) addCellXf(xCellXf xlsxXf) (index int) {
+	styles.CellXfs.Xf = append(styles.CellXfs.Xf, xCellXf)
+	index = styles.CellXfs.Count
+	styles.CellXfs.Count += 1
+	return
 }