summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLunny Xiao <xiaolunwen@gmail.com>2018-05-07 16:12:51 +0800
committerLunny Xiao <xiaolunwen@gmail.com>2018-05-07 16:12:51 +0800
commit38ad20efc11c1872c4e62a12617f0300c138b867 (patch)
tree7190083ed4fa8ddaa1ec3b9ecb260423451f3164
parentbc451a78de32ccde2a4f6d0851ea6e41e45408f1 (diff)
save bytes on memory instead of string
-rw-r--r--chart.go4
-rw-r--r--comment.go4
-rw-r--r--excelize.go11
-rw-r--r--file.go20
-rw-r--r--lib.go19
-rw-r--r--picture.go10
-rw-r--r--rows.go14
-rw-r--r--shape.go2
-rw-r--r--sheet.go16
-rw-r--r--styles.go2
-rw-r--r--table.go2
-rw-r--r--templates.go4
12 files changed, 64 insertions, 44 deletions
diff --git a/chart.go b/chart.go
index 6168553..c71dd9f 100644
--- a/chart.go
+++ b/chart.go
@@ -549,7 +549,7 @@ func (f *File) addChart(formatSet *formatChart) {
chart, _ := xml.Marshal(xlsxChartSpace)
media := "xl/charts/chart" + strconv.Itoa(count+1) + ".xml"
- f.saveFileList(media, string(chart))
+ f.saveFileList(media, chart)
}
// drawBaseChart provides function to draw the c:plotArea element for bar,
@@ -1151,5 +1151,5 @@ func (f *File) addDrawingChart(sheet, drawingXML, cell string, width, height, rI
}
content.TwoCellAnchor = append(content.TwoCellAnchor, &twoCellAnchor)
output, _ := xml.Marshal(content)
- f.saveFileList(drawingXML, string(output))
+ f.saveFileList(drawingXML, output)
}
diff --git a/comment.go b/comment.go
index 6f2d624..41b4d6b 100644
--- a/comment.go
+++ b/comment.go
@@ -142,7 +142,7 @@ func (f *File) addDrawingVML(commentID int, drawingVML, cell string) {
}
vml.Shape = append(vml.Shape, shape)
v, _ := xml.Marshal(vml)
- f.XLSX[drawingVML] = string(v)
+ f.XLSX[drawingVML] = v
}
// addComment provides function to create chart as xl/comments%d.xml by given
@@ -202,7 +202,7 @@ func (f *File) addComment(commentsXML, cell string, formatSet *formatComment) {
}
comments.CommentList.Comment = append(comments.CommentList.Comment, cmt)
v, _ := xml.Marshal(comments)
- f.saveFileList(commentsXML, string(v))
+ f.saveFileList(commentsXML, v)
}
// countComments provides function to get comments files count storage in the
diff --git a/excelize.go b/excelize.go
index 0b1e410..31fa370 100644
--- a/excelize.go
+++ b/excelize.go
@@ -23,7 +23,7 @@ type File struct {
Styles *xlsxStyleSheet
WorkBook *xlsxWorkbook
WorkBookRels *xlsxWorkbookRels
- XLSX map[string]string
+ XLSX map[string][]byte
}
// OpenFile take the name of an XLSX file and returns a populated XLSX file
@@ -88,7 +88,7 @@ func (f *File) workSheetReader(sheet string) *xlsxWorksheet {
}
if f.Sheet[name] == nil {
var xlsx xlsxWorksheet
- xml.Unmarshal([]byte(f.readXML(name)), &xlsx)
+ xml.Unmarshal(f.readXML(name), &xlsx)
if f.checked == nil {
f.checked = make(map[string]bool)
}
@@ -141,6 +141,13 @@ func replaceWorkSheetsRelationshipsNameSpace(workbookMarshal string) string {
return workbookMarshal
}
+func replaceWorkSheetsRelationshipsNameSpaceBytes(workbookMarshal []byte) []byte {
+ var oldXmlns = []byte(`<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">`)
+ var newXmlns = []byte(`<worksheet xr:uid="{00000000-0001-0000-0000-000000000000}" xmlns:xr3="http://schemas.microsoft.com/office/spreadsheetml/2016/revision3" xmlns:xr2="http://schemas.microsoft.com/office/spreadsheetml/2015/revision2" xmlns:xr="http://schemas.microsoft.com/office/spreadsheetml/2014/revision" xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac" mc:Ignorable="x14ac xr xr2 xr3" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mx="http://schemas.microsoft.com/office/mac/excel/2008/main" xmlns:mv="urn:schemas-microsoft-com:mac:vml" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">`)
+ workbookMarshal = bytes.Replace(workbookMarshal, oldXmlns, newXmlns, -1)
+ return workbookMarshal
+}
+
// UpdateLinkedValue fix linked values within a spreadsheet are not updating in
// Office Excel 2007 and 2010. This function will be remove value tag when met a
// cell have a linked value. Reference
diff --git a/file.go b/file.go
index 01e856d..36af6f8 100644
--- a/file.go
+++ b/file.go
@@ -14,16 +14,16 @@ import (
// xlsx := NewFile()
//
func NewFile() *File {
- file := make(map[string]string)
- file["_rels/.rels"] = XMLHeader + templateRels
- file["docProps/app.xml"] = XMLHeader + templateDocpropsApp
- file["docProps/core.xml"] = XMLHeader + templateDocpropsCore
- file["xl/_rels/workbook.xml.rels"] = XMLHeader + templateWorkbookRels
- file["xl/theme/theme1.xml"] = XMLHeader + templateTheme
- file["xl/worksheets/sheet1.xml"] = XMLHeader + templateSheet
- file["xl/styles.xml"] = XMLHeader + templateStyles
- file["xl/workbook.xml"] = XMLHeader + templateWorkbook
- file["[Content_Types].xml"] = XMLHeader + templateContentTypes
+ file := make(map[string][]byte)
+ file["_rels/.rels"] = []byte(XMLHeader + templateRels)
+ file["docProps/app.xml"] = []byte(XMLHeader + templateDocpropsApp)
+ file["docProps/core.xml"] = []byte(XMLHeader + templateDocpropsCore)
+ file["xl/_rels/workbook.xml.rels"] = []byte(XMLHeader + templateWorkbookRels)
+ file["xl/theme/theme1.xml"] = []byte(XMLHeader + templateTheme)
+ file["xl/worksheets/sheet1.xml"] = []byte(XMLHeader + templateSheet)
+ file["xl/styles.xml"] = []byte(XMLHeader + templateStyles)
+ file["xl/workbook.xml"] = []byte(XMLHeader + templateWorkbook)
+ file["[Content_Types].xml"] = []byte(XMLHeader + templateContentTypes)
f := &File{
sheetMap: make(map[string]string),
Sheet: make(map[string]*xlsxWorksheet),
diff --git a/lib.go b/lib.go
index c0426d6..a168781 100644
--- a/lib.go
+++ b/lib.go
@@ -12,8 +12,8 @@ import (
// ReadZipReader can be used to read an XLSX in memory without touching the
// filesystem.
-func ReadZipReader(r *zip.Reader) (map[string]string, int, error) {
- fileList := make(map[string]string)
+func ReadZipReader(r *zip.Reader) (map[string][]byte, int, error) {
+ fileList := make(map[string][]byte)
worksheets := 0
for _, v := range r.File {
fileList[v.Name] = readFile(v)
@@ -27,21 +27,24 @@ func ReadZipReader(r *zip.Reader) (map[string]string, int, error) {
}
// readXML provides function to read XML content as string.
-func (f *File) readXML(name string) string {
+func (f *File) readXML(name string) []byte {
if content, ok := f.XLSX[name]; ok {
return content
}
- return ""
+ return []byte{}
}
// saveFileList provides function to update given file content in file list of
// XLSX.
-func (f *File) saveFileList(name, content string) {
- f.XLSX[name] = XMLHeader + content
+func (f *File) saveFileList(name string, content []byte) {
+ newContent := make([]byte, 0, len(XMLHeader)+len(content))
+ newContent = append(newContent, []byte(XMLHeader)...)
+ newContent = append(newContent, content...)
+ f.XLSX[name] = newContent
}
// Read file content as string in a archive file.
-func readFile(file *zip.File) string {
+func readFile(file *zip.File) []byte {
rc, err := file.Open()
if err != nil {
log.Fatal(err)
@@ -49,7 +52,7 @@ func readFile(file *zip.File) string {
buff := bytes.NewBuffer(nil)
io.Copy(buff, rc)
rc.Close()
- return string(buff.Bytes())
+ return buff.Bytes()
}
// ToAlphaString provides function to convert integer to Excel sheet column
diff --git a/picture.go b/picture.go
index a7f48d1..6c84cdd 100644
--- a/picture.go
+++ b/picture.go
@@ -142,7 +142,7 @@ func (f *File) addSheetRelationships(sheet, relType, target, targetMode string)
TargetMode: targetMode,
})
output, _ := xml.Marshal(sheetRels)
- f.saveFileList(rels, string(output))
+ f.saveFileList(rels, output)
return rID
}
@@ -163,7 +163,7 @@ func (f *File) deleteSheetRelationships(sheet, rID string) {
}
}
output, _ := xml.Marshal(sheetRels)
- f.saveFileList(rels, string(output))
+ f.saveFileList(rels, output)
}
// addSheetLegacyDrawing provides function to add legacy drawing element to
@@ -257,7 +257,7 @@ func (f *File) addDrawingPicture(sheet, drawingXML, cell, file string, width, he
}
content.TwoCellAnchor = append(content.TwoCellAnchor, &twoCellAnchor)
output, _ := xml.Marshal(content)
- f.saveFileList(drawingXML, string(output))
+ f.saveFileList(drawingXML, output)
}
// addDrawingRelationships provides function to add image part relationships in
@@ -285,7 +285,7 @@ func (f *File) addDrawingRelationships(index int, relType, target, targetMode st
TargetMode: targetMode,
})
output, _ := xml.Marshal(drawingRels)
- f.saveFileList(rels, string(output))
+ f.saveFileList(rels, output)
return rID
}
@@ -307,7 +307,7 @@ func (f *File) addMedia(file, ext string) {
count := f.countMedia()
dat, _ := ioutil.ReadFile(file)
media := "xl/media/image" + strconv.Itoa(count+1) + ext
- f.XLSX[media] = string(dat)
+ f.XLSX[media] = dat
}
// setContentTypePartImageExtensions provides function to set the content type
diff --git a/rows.go b/rows.go
index 02a6876..ff1a8c3 100644
--- a/rows.go
+++ b/rows.go
@@ -29,9 +29,9 @@ func (f *File) GetRows(sheet string) [][]string {
}
if xlsx != nil {
output, _ := xml.Marshal(f.Sheet[name])
- f.saveFileList(name, replaceWorkSheetsRelationshipsNameSpace(string(output)))
+ f.saveFileList(name, replaceWorkSheetsRelationshipsNameSpaceBytes(output))
}
- decoder := xml.NewDecoder(strings.NewReader(f.readXML(name)))
+ decoder := xml.NewDecoder(bytes.NewReader(f.readXML(name)))
d := f.sharedStringsReader()
var inElement string
var r xlsxRow
@@ -44,7 +44,7 @@ func (f *File) GetRows(sheet string) [][]string {
}
rows = append(rows, row)
}
- decoder = xml.NewDecoder(strings.NewReader(f.readXML(name)))
+ decoder = xml.NewDecoder(bytes.NewReader(f.readXML(name)))
for {
token, _ := decoder.Token()
if token == nil {
@@ -154,19 +154,19 @@ func (f *File) Rows(sheet string) (*Rows, error) {
if err != nil {
return nil, err
}
- f.saveFileList(name, replaceWorkSheetsRelationshipsNameSpace(string(output)))
+ f.saveFileList(name, replaceWorkSheetsRelationshipsNameSpaceBytes(output))
}
return &Rows{
f: f,
- decoder: xml.NewDecoder(strings.NewReader(f.readXML(name))),
+ decoder: xml.NewDecoder(bytes.NewReader(f.readXML(name))),
}, nil
}
// getTotalRowsCols provides a function to get total columns and rows in a
// worksheet.
func (f *File) getTotalRowsCols(name string) (int, int) {
- decoder := xml.NewDecoder(strings.NewReader(f.readXML(name)))
+ decoder := xml.NewDecoder(bytes.NewReader(f.readXML(name)))
var inElement string
var r xlsxRow
var tr, tc int
@@ -244,7 +244,7 @@ func (f *File) sharedStringsReader() *xlsxSST {
if f.SharedStrings == nil {
var sharedStrings xlsxSST
ss := f.readXML("xl/sharedStrings.xml")
- if ss == "" {
+ if len(ss) == 0 {
ss = f.readXML("xl/SharedStrings.xml")
}
xml.Unmarshal([]byte(ss), &sharedStrings)
diff --git a/shape.go b/shape.go
index f1328f7..0b93752 100644
--- a/shape.go
+++ b/shape.go
@@ -390,7 +390,7 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, formatSet *format
}
content.TwoCellAnchor = append(content.TwoCellAnchor, &twoCellAnchor)
output, _ := xml.Marshal(content)
- f.saveFileList(drawingXML, string(output))
+ f.saveFileList(drawingXML, output)
}
// setShapeRef provides function to set color with hex model by given actual
diff --git a/sheet.go b/sheet.go
index f42226b..cb50d61 100644
--- a/sheet.go
+++ b/sheet.go
@@ -50,7 +50,7 @@ func (f *File) contentTypesReader() *xlsxTypes {
func (f *File) contentTypesWriter() {
if f.ContentTypes != nil {
output, _ := xml.Marshal(f.ContentTypes)
- f.saveFileList("[Content_Types].xml", string(output))
+ f.saveFileList("[Content_Types].xml", output)
}
}
@@ -70,7 +70,7 @@ func (f *File) workbookReader() *xlsxWorkbook {
func (f *File) workbookWriter() {
if f.WorkBook != nil {
output, _ := xml.Marshal(f.WorkBook)
- f.saveFileList("xl/workbook.xml", replaceRelationshipsNameSpace(string(output)))
+ f.saveFileList("xl/workbook.xml", replaceRelationshipsNameSpaceBytes(output))
}
}
@@ -83,7 +83,7 @@ func (f *File) worksheetWriter() {
f.Sheet[path].SheetData.Row[k].C = trimCell(v.C)
}
output, _ := xml.Marshal(sheet)
- f.saveFileList(path, replaceWorkSheetsRelationshipsNameSpace(string(output)))
+ f.saveFileList(path, replaceWorkSheetsRelationshipsNameSpaceBytes(output))
ok := f.checked[path]
if ok {
f.checked[path] = false
@@ -151,7 +151,7 @@ func (f *File) workbookRelsReader() *xlsxWorkbookRels {
func (f *File) workbookRelsWriter() {
if f.WorkBookRels != nil {
output, _ := xml.Marshal(f.WorkBookRels)
- f.saveFileList("xl/_rels/workbook.xml.rels", string(output))
+ f.saveFileList("xl/_rels/workbook.xml.rels", output)
}
}
@@ -183,7 +183,7 @@ func (f *File) addXlsxWorkbookRels(sheet int) int {
// setAppXML update docProps/app.xml file of XML.
func (f *File) setAppXML() {
- f.saveFileList("docProps/app.xml", templateDocpropsApp)
+ f.saveFileList("docProps/app.xml", []byte(templateDocpropsApp))
}
// Some tools that read XLSX files have very strict requirements about the
@@ -199,6 +199,12 @@ func replaceRelationshipsNameSpace(workbookMarshal string) string {
return strings.Replace(workbookMarshal, oldXmlns, newXmlns, -1)
}
+func replaceRelationshipsNameSpaceBytes(workbookMarshal []byte) []byte {
+ oldXmlns := []byte(`<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">`)
+ newXmlns := []byte(`<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x15" xmlns:x15="http://schemas.microsoft.com/office/spreadsheetml/2010/11/main">`)
+ return bytes.Replace(workbookMarshal, oldXmlns, newXmlns, -1)
+}
+
// SetActiveSheet provides function to set default active worksheet of XLSX by
// given index. Note that active index is different with the index that got by
// function GetSheetMap, and it should be greater than 0 and less than total
diff --git a/styles.go b/styles.go
index 6ebb603..0a9cbef 100644
--- a/styles.go
+++ b/styles.go
@@ -999,7 +999,7 @@ func (f *File) stylesReader() *xlsxStyleSheet {
func (f *File) styleSheetWriter() {
if f.Styles != nil {
output, _ := xml.Marshal(f.Styles)
- f.saveFileList("xl/styles.xml", replaceWorkSheetsRelationshipsNameSpace(string(output)))
+ f.saveFileList("xl/styles.xml", replaceWorkSheetsRelationshipsNameSpaceBytes(output))
}
}
diff --git a/table.go b/table.go
index 5c00a2d..5af4b04 100644
--- a/table.go
+++ b/table.go
@@ -150,7 +150,7 @@ func (f *File) addTable(sheet, tableXML string, hxAxis, hyAxis, vxAxis, vyAxis,
},
}
table, _ := xml.Marshal(t)
- f.saveFileList(tableXML, string(table))
+ f.saveFileList(tableXML, table)
}
// parseAutoFilterSet provides function to parse the settings of the auto
diff --git a/templates.go b/templates.go
index b5f4f8c..d3f82ee 100644
--- a/templates.go
+++ b/templates.go
@@ -6,6 +6,10 @@ package excelize
// XMLHeader define an XML declaration can also contain a standalone declaration.
const XMLHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
+var (
+ XMLHeaderByte = []byte(XMLHeader)
+)
+
const templateDocpropsApp = `<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"><TotalTime>0</TotalTime><Application>Golang Excelize</Application></Properties>`
const templateContentTypes = `<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Override PartName="/xl/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/><Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/><Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/><Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/><Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/></Types>`