Browse Source

Produce workbook.xml file.

Geoffrey J. Teale 12 years ago
parent
commit
13c68c81e5
4 changed files with 107 additions and 12 deletions
  1. 43 8
      file.go
  2. 58 2
      file_test.go
  3. 5 1
      workbook.go
  4. 1 1
      workbook_test.go

+ 43 - 8
file.go

@@ -4,6 +4,7 @@ import (
 	"archive/zip"
 	"encoding/xml"
 	"fmt"
+	"strconv"
 )
 
 // File is a high level structure providing a slice of Sheet structs
@@ -41,12 +42,35 @@ func (f *File) AddSheet(sheetName string) (sheet *Sheet) {
 	return sheet
 }
 
+func (f *File) makeWorkbook() xlsxWorkbook {
+	var workbook xlsxWorkbook
+	workbook = xlsxWorkbook{}
+	workbook.FileVersion = xlsxFileVersion{}
+	workbook.FileVersion.AppName = "Go XLSX"
+	workbook.WorkbookPr = xlsxWorkbookPr{BackupFile: false}
+	workbook.BookViews = xlsxBookViews{}
+	workbook.BookViews.WorkBookView = make([]xlsxWorkBookView, 1)
+	workbook.BookViews.WorkBookView[0] = xlsxWorkBookView{}
+	workbook.Sheets = xlsxSheets{}
+	workbook.Sheets.Sheet = make([]xlsxSheet, len(f.Sheets))
+	return workbook
+}
+
+// 	for sheetName, sheet := range f.Sheets {
+		
+// 	}
+// 	body, err := xml.MarshalIndent(workbook, "  ", "  ")
+// 	if err != nil { return "", err }
+// 	return xml.Header + string(body), nil
+// }
+
 
 func (f *File) MarshallParts() (map[string]string, error) {
 	var parts map[string]string
 	var refTable *RefTable = NewSharedStringRefTable()
 	var workbookRels WorkBookRels = make(WorkBookRels)
 	var err error
+	var workbook xlsxWorkbook
 
 	marshal := func(thing interface{}) (string, error) {
 		body, err := xml.MarshalIndent(thing, "  ", "  ")
@@ -58,18 +82,29 @@ func (f *File) MarshallParts() (map[string]string, error) {
 
 
 	parts = make(map[string]string)
+	workbook = f.makeWorkbook()
 	sheetIndex := 1
-	// _ here is sheet name.
-	for _, sheet := range f.Sheets {
+
+	for sheetName, sheet := range f.Sheets {
 		xSheet := sheet.makeXLSXSheet(refTable)
-		sheetId := fmt.Sprintf("rId%d", sheetIndex)
+		rId := fmt.Sprintf("rId%d", sheetIndex)
+		sheetId := strconv.Itoa(sheetIndex)
 		sheetPath := fmt.Sprintf("worksheets/sheet%d.xml", sheetIndex)
-		workbookRels[sheetId] = sheetPath
+		workbookRels[rId] = sheetPath
+		workbook.Sheets.Sheet[sheetIndex - 1] = xlsxSheet{
+			Name: sheetName,
+			SheetId: sheetId,
+			Id: rId}
 		parts[sheetPath], err = marshal(xSheet)
 		if err != nil {
 			return parts, err
 		}
-sheetIndex++
+		sheetIndex++
+	}
+
+	parts["xl/workbook.xml"], err = marshal(workbook)
+	if err != nil {
+		return parts, err
 	}
 
 	parts[".rels"] = `<?xml version="1.0" encoding="UTF-8"?>
@@ -91,13 +126,13 @@ sheetIndex++
 
 	xSST := refTable.makeXLSXSST()
 	parts["xl/sharedStrings.xml"], err = marshal(xSST)
+	if err != nil {
+		return parts, err
+	}
 	sheetId := fmt.Sprintf("rId%d", sheetIndex)
 	sheetPath := "sharedStrings.xml"
 	workbookRels[sheetId] = sheetPath
 	sheetIndex++
-	if err != nil {
-		return parts, err
-	}
 	xWRel := workbookRels.MakeXLSXWorkbookRels()
 	parts["xl/_rels/workbook.xml.rels"], err = marshal(xWRel)
 	if err != nil {

+ 58 - 2
file_test.go

@@ -1,6 +1,7 @@
-package xlsx
+ package xlsx
 
 import (
+	"encoding/xml"
 	. "gopkg.in/check.v1"
 )
 
@@ -53,6 +54,7 @@ func (l *FileSuite) TestCreateSheet(c *C) {
 // Test that we can add a sheet to a File
 func (l *FileSuite) TestAddSheet(c *C) {
 	var f *File
+	
 	f = NewFile()
 	sheet := f.AddSheet("MySheet")
 	c.Assert(sheet, NotNil)
@@ -60,6 +62,44 @@ func (l *FileSuite) TestAddSheet(c *C) {
 	c.Assert(f.Sheets["MySheet"], Equals, sheet)
 }
 
+func (l *FileSuite) TestMarshalWorkbook(c *C) {
+	var f *File
+
+	f = NewFile()
+
+	f.AddSheet("MyFirstSheet")
+	f.AddSheet("MySecondSheet")
+	workbook := f.makeWorkbook()
+	workbook.Sheets.Sheet[0] = xlsxSheet{
+		Name: "MyFirstSheet",
+		SheetId: "1",
+		Id: "rId1"}
+
+	workbook.Sheets.Sheet[1] = xlsxSheet{
+		Name: "MySecondSheet",
+		SheetId: "2",
+		Id: "rId2"}
+
+	expectedWorkbook := `<?xml version="1.0" encoding="UTF-8"?>
+   <workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
+      <fileVersion appName="Go XLSX"></fileVersion>
+      <workbookPr date1904="false"></workbookPr>
+      <bookViews>
+         <workbookView></workbookView>
+      </bookViews>
+      <sheets>
+         <sheet name="MyFirstSheet" sheetId="1" xmlns:relationships="http://schemas.openxmlformats.org/officeDocument/2006/relationships" relationships:id="rId1"></sheet>
+         <sheet name="MySecondSheet" sheetId="2" xmlns:relationships="http://schemas.openxmlformats.org/officeDocument/2006/relationships" relationships:id="rId2"></sheet>
+      </sheets>
+      <definedNames></definedNames>
+      <calcPr></calcPr>
+   </workbook>`
+	output, err := xml.MarshalIndent(workbook, "   ", "   ")
+	c.Assert(err, IsNil)
+	stringOutput := xml.Header + string(output)
+	c.Assert(stringOutput, Equals, expectedWorkbook)
+}
+
 // Test that we can marshall a File to a collection of xml files
 func (l *FileSuite) TestMarshalFile(c *C) {
 	var f *File
@@ -74,7 +114,7 @@ func (l *FileSuite) TestMarshalFile(c *C) {
 	cell2.Value = "A cell!"
 	parts, err := f.MarshallParts()
 	c.Assert(err, IsNil)
-	c.Assert(len(parts), Equals, 7)
+	c.Assert(len(parts), Equals, 8)
 	expectedSheet := `<?xml version="1.0" encoding="UTF-8"?>
   <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
     <dimension ref="A1:A1"></dimension>
@@ -124,4 +164,20 @@ func (l *FileSuite) TestMarshalFile(c *C) {
   </Relationships>`
 	c.Assert(parts["xl/_rels/workbook.xml.rels"], Equals, expectedXLSXWorkbookRels)
 
+	expectedWorkbook := `<?xml version="1.0" encoding="UTF-8"?>
+  <workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
+    <fileVersion appName="Go XLSX"></fileVersion>
+    <workbookPr date1904="false"></workbookPr>
+    <bookViews>
+      <workbookView></workbookView>
+    </bookViews>
+    <sheets>
+      <sheet name="MySheet" sheetId="1" xmlns:relationships="http://schemas.openxmlformats.org/officeDocument/2006/relationships" relationships:id="rId1"></sheet>
+      <sheet name="AnotherSheet" sheetId="2" xmlns:relationships="http://schemas.openxmlformats.org/officeDocument/2006/relationships" relationships:id="rId2"></sheet>
+    </sheets>
+    <definedNames></definedNames>
+    <calcPr></calcPr>
+  </workbook>`
+	c.Assert(parts["xl/workbook.xml"], Equals, expectedWorkbook)
+
 }

+ 5 - 1
workbook.go

@@ -123,7 +123,11 @@ type xlsxDefinedName struct {
 // currently I have not checked it for completeness - it does as much
 // as I need.
 type xlsxCalcPr struct {
-	CalcId string `xml:"calcId,attr"`
+	CalcId string `xml:"calcId,attr,omitempty"`
+	IterateCount int `xml:"iterateCount,attr,omitempty"`
+	RefMode string `xml:"refMode,attr,omitempty"`
+	Iterate bool `xml:"iterate,attr,omitempty"`
+	IterateDelta float64 `xml:"iterateDelta,attr,omitempty"`
 }
 
 // getWorksheetFromSheet() is an internal helper function to open a

+ 1 - 1
workbook_test.go

@@ -102,7 +102,7 @@ func (w *WorkbookSuite) TestMarshallWorkbook(c *C) {
       <sheet name="sheet1" sheetId="1" xmlns:relationships="http://schemas.openxmlformats.org/officeDocument/2006/relationships" relationships:id="rId2"></sheet>
     </sheets>
     <definedNames></definedNames>
-    <calcPr calcId=""></calcPr>
+    <calcPr></calcPr>
   </workbook>`
 	c.Assert(string(body), Equals, expectedWorkbook)