فهرست منبع

Write parts to zip file.

Geoffrey J. Teale 11 سال پیش
والد
کامیت
2885f593c6
6فایلهای تغییر یافته به همراه87 افزوده شده و 8 حذف شده
  1. 13 0
      contenttypes.go
  2. 6 0
      contenttypes_test.go
  3. 41 2
      file.go
  4. 25 4
      file_test.go
  5. 1 1
      sharedstrings.go
  6. 1 1
      sharedstrings_test.go

+ 13 - 0
contenttypes.go

@@ -8,6 +8,7 @@ type xlsxTypes struct {
 	XMLName xml.Name `xml:"http://schemas.openxmlformats.org/package/2006/content-types Types"`
 	XMLName xml.Name `xml:"http://schemas.openxmlformats.org/package/2006/content-types Types"`
 
 
 	Overrides []xlsxOverride `xml:"Override"`
 	Overrides []xlsxOverride `xml:"Override"`
+	Defaults []xlsxDefault `xml:"Default"`
 }
 }
 
 
 type xlsxOverride struct {
 type xlsxOverride struct {
@@ -15,8 +16,15 @@ type xlsxOverride struct {
 	ContentType string `xml:",attr"`
 	ContentType string `xml:",attr"`
 }
 }
 
 
+type xlsxDefault struct {
+	Extension	string `xml:",attr"`
+	ContentType	string `xml:",attr"`
+}
+
 func MakeDefaultContentTypes() (types xlsxTypes) {
 func MakeDefaultContentTypes() (types xlsxTypes) {
 	types.Overrides = make([]xlsxOverride, 7)
 	types.Overrides = make([]xlsxOverride, 7)
+	types.Defaults = make([]xlsxDefault, 2)
+
 	types.Overrides[0].PartName = "/_rels/.rels"
 	types.Overrides[0].PartName = "/_rels/.rels"
 	types.Overrides[0].ContentType = "application/vnd.openxmlformats-package.relationships+xml"
 	types.Overrides[0].ContentType = "application/vnd.openxmlformats-package.relationships+xml"
 	types.Overrides[1].PartName = "/docProps/app.xml"
 	types.Overrides[1].PartName = "/docProps/app.xml"
@@ -31,5 +39,10 @@ func MakeDefaultContentTypes() (types xlsxTypes) {
 	types.Overrides[5].ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"
 	types.Overrides[5].ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"
 	types.Overrides[6].PartName = "/xl/workbook.xml"
 	types.Overrides[6].PartName = "/xl/workbook.xml"
 	types.Overrides[6].ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"
 	types.Overrides[6].ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"
+
+	types.Defaults[0].Extension = "rels"
+	types.Defaults[0].ContentType = "application/vnd.openxmlformats-package.relationships+xml"
+	types.Defaults[1].Extension = "xml"
+	types.Defaults[1].ContentType = "application/xml"
 	return
 	return
 }
 }

+ 6 - 0
contenttypes_test.go

@@ -41,4 +41,10 @@ func (l *ContentTypesSuite) TestMakeDefaultContentTypes(c *C) {
 	c.Assert(types.Overrides[6].PartName, Equals, "/xl/workbook.xml")
 	c.Assert(types.Overrides[6].PartName, Equals, "/xl/workbook.xml")
 	c.Assert(types.Overrides[6].ContentType, Equals, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml")
 	c.Assert(types.Overrides[6].ContentType, Equals, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml")
 
 
+	c.Assert(types.Defaults[0].Extension, Equals, "rels")
+	c.Assert(types.Defaults[0].ContentType, Equals, "application/vnd.openxmlformats-package.relationships+xml")
+	c.Assert(types.Defaults[1].Extension, Equals, "xml")
+	c.Assert(types.Defaults[1].ContentType, Equals, "application/xml")
+
+
 }
 }

+ 41 - 2
file.go

@@ -4,6 +4,8 @@ import (
 	"archive/zip"
 	"archive/zip"
 	"encoding/xml"
 	"encoding/xml"
 	"fmt"
 	"fmt"
+	"io"
+	"os"
 	"strconv"
 	"strconv"
 )
 )
 
 
@@ -35,6 +37,43 @@ func OpenFile(filename string) (*File, error) {
 	return ReadZip(f)
 	return ReadZip(f)
 }
 }
 
 
+func (f *File) Save(path string) (err error) {
+	var parts map[string]string
+	var target *os.File
+	var zipWriter *zip.Writer
+
+	parts, err = f.MarshallParts()
+	if err != nil {
+		return
+	}
+
+	target, err = os.Create(path)
+	if err != nil {
+		return
+	}
+
+	zipWriter = zip.NewWriter(target)
+
+	for partName, part := range parts {
+		var writer io.Writer
+		writer, err = zipWriter.Create(partName)
+		if err != nil {
+			return
+		}
+		_, err = writer.Write([]byte(part))
+		if err != nil {
+			return
+		}
+	}
+	err = zipWriter.Close()
+	if err != nil {
+		return
+	}
+
+	return target.Close()
+}
+
+
 // Add a new Sheet, with the provided name, to a File
 // Add a new Sheet, with the provided name, to a File
 func (f *File) AddSheet(sheetName string) (sheet *Sheet) {
 func (f *File) AddSheet(sheetName string) (sheet *Sheet) {
 	sheet = &Sheet{}
 	sheet = &Sheet{}
@@ -94,7 +133,7 @@ func (f *File) MarshallParts() (map[string]string, error) {
 			Name: sheetName,
 			Name: sheetName,
 			SheetId: sheetId,
 			SheetId: sheetId,
 			Id: rId}
 			Id: rId}
-		parts[sheetPath], err = marshal(xSheet)
+		parts[partName], err = marshal(xSheet)
 		if err != nil {
 		if err != nil {
 			return parts, err
 			return parts, err
 		}
 		}
@@ -106,7 +145,7 @@ func (f *File) MarshallParts() (map[string]string, error) {
 		return parts, err
 		return parts, err
 	}
 	}
 
 
-	parts[".rels"] = `<?xml version="1.0" encoding="UTF-8"?>
+	parts["_rels/.rels"] = `<?xml version="1.0" encoding="UTF-8"?>
 <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
 <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
   <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>
   <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>
   <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>
   <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>

+ 25 - 4
file_test.go

@@ -2,6 +2,7 @@ package xlsx
 
 
 import (
 import (
 	"encoding/xml"
 	"encoding/xml"
+	"path/filepath"
 	. "gopkg.in/check.v1"
 	. "gopkg.in/check.v1"
 )
 )
 
 
@@ -129,8 +130,8 @@ func (l *FileSuite) TestMarshalFile(c *C) {
       </row>
       </row>
     </sheetData>
     </sheetData>
   </worksheet>`
   </worksheet>`
-	c.Assert(parts["worksheets/sheet1.xml"], Equals, expectedSheet)
-	c.Assert(parts["worksheets/sheet2.xml"], Equals, expectedSheet)
+	c.Assert(parts["xl/worksheets/sheet1.xml"], Equals, expectedSheet)
+	c.Assert(parts["xl/worksheets/sheet2.xml"], Equals, expectedSheet)
 
 
 	// .rels.xml
 	// .rels.xml
 	expectedRels := `<?xml version="1.0" encoding="UTF-8"?>
 	expectedRels := `<?xml version="1.0" encoding="UTF-8"?>
@@ -139,7 +140,7 @@ func (l *FileSuite) TestMarshalFile(c *C) {
   <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>
   <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>
   <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/>
   <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/>
 </Relationships>`
 </Relationships>`
-	c.Assert(parts[".rels"], Equals, expectedRels)
+	c.Assert(parts["_rels/.rels"], Equals, expectedRels)
 
 
 	// app.xml
 	// app.xml
 	expectedApp := `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 	expectedApp := `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
@@ -156,7 +157,7 @@ func (l *FileSuite) TestMarshalFile(c *C) {
 
 
 	// sharedStrings.xml
 	// sharedStrings.xml
 	expectedXLSXSST := `<?xml version="1.0" encoding="UTF-8"?>
 	expectedXLSXSST := `<?xml version="1.0" encoding="UTF-8"?>
-  <sst count="1" uniqueCount="1">
+  <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="1" uniqueCount="1">
     <si>
     <si>
       <t>A cell!</t>
       <t>A cell!</t>
     </si>
     </si>
@@ -201,6 +202,8 @@ func (l *FileSuite) TestMarshalFile(c *C) {
     <Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"></Override>
     <Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"></Override>
     <Override PartName="xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"></Override>
     <Override PartName="xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"></Override>
     <Override PartName="xl/worksheets/sheet2.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"></Override>
     <Override PartName="xl/worksheets/sheet2.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"></Override>
+    <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"></Default>
+    <Default Extension="xml" ContentType="application/xml"></Default>
   </Types>`
   </Types>`
 	c.Assert(parts["[Content_Types].xml"], Equals, expectedContentTypes)
 	c.Assert(parts["[Content_Types].xml"], Equals, expectedContentTypes)
 
 
@@ -214,3 +217,21 @@ func (l *FileSuite) TestMarshalFile(c *C) {
 </styleSheet>`
 </styleSheet>`
 	c.Assert(parts["xl/styles.xml"], Equals, expectedStyles)
 	c.Assert(parts["xl/styles.xml"], Equals, expectedStyles)
 }
 }
+
+
+func (l *FileSuite) TestSaveFile(c *C) {
+	var tmpPath string = c.MkDir()
+	var f *File
+	f = NewFile()
+	sheet1 := f.AddSheet("MySheet")
+	row1 := sheet1.AddRow()
+	cell1 := row1.AddCell()
+	cell1.Value = "A cell!"
+	sheet2 := f.AddSheet("AnotherSheet")
+	row2 := sheet2.AddRow()
+	cell2 := row2.AddCell()
+	cell2.Value = "A cell!"
+	tmpPath = "/tmp"
+	err := f.Save(filepath.Join(tmpPath, "TestSaveFile.xlsx"))
+	c.Assert(err, IsNil)
+}

+ 1 - 1
sharedstrings.go

@@ -9,7 +9,7 @@ import (
 // http://schemas.openxmlformats.org/spreadsheetml/2006/main currently
 // http://schemas.openxmlformats.org/spreadsheetml/2006/main currently
 // I have not checked this for completeness - it does as much as need.
 // I have not checked this for completeness - it does as much as need.
 type xlsxSST struct {
 type xlsxSST struct {
-	XMLName     xml.Name `xml:"sst"`
+	XMLName     xml.Name `xml:"http://schemas.openxmlformats.org/spreadsheetml/2006/main sst"`
 	Count       int   `xml:"count,attr"`
 	Count       int   `xml:"count,attr"`
 	UniqueCount int   `xml:"uniqueCount,attr"`
 	UniqueCount int   `xml:"uniqueCount,attr"`
 	SI          []xlsxSI `xml:"si"`
 	SI          []xlsxSI `xml:"si"`

+ 1 - 1
sharedstrings_test.go

@@ -112,7 +112,7 @@ func (s *SharedStringsSuite) TestMarshalSST(c *C) {
 	c.Assert(err, IsNil)
 	c.Assert(err, IsNil)
 
 
 	expectedXLSXSST := `<?xml version="1.0" encoding="UTF-8"?>
 	expectedXLSXSST := `<?xml version="1.0" encoding="UTF-8"?>
-  <sst count="1" uniqueCount="1">
+  <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="1" uniqueCount="1">
     <si>
     <si>
       <t>Foo</t>
       <t>Foo</t>
     </si>
     </si>