Explorar o código

Merge pull request #220 from lunny/lunny/refactor

save bytes on memory instead of string
xuri %!s(int64=7) %!d(string=hai) anos
pai
achega
038e34250f
Modificáronse 12 ficheiros con 64 adicións e 44 borrados
  1. 2 2
      chart.go
  2. 2 2
      comment.go
  3. 9 2
      excelize.go
  4. 10 10
      file.go
  5. 11 8
      lib.go
  6. 5 5
      picture.go
  7. 7 7
      rows.go
  8. 1 1
      shape.go
  9. 11 5
      sheet.go
  10. 1 1
      styles.go
  11. 1 1
      table.go
  12. 4 0
      templates.go

+ 2 - 2
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)
 }

+ 2 - 2
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

+ 9 - 2
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

+ 10 - 10
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),

+ 11 - 8
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

+ 5 - 5
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

+ 7 - 7
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 {
@@ -148,18 +148,18 @@ func (f *File) Rows(sheet string) (*Rows, error) {
 	}
 	if xlsx != nil {
 		output, _ := xml.Marshal(f.Sheet[name])
-		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
@@ -237,7 +237,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)

+ 1 - 1
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

+ 11 - 5
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

+ 1 - 1
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))
 	}
 }
 

+ 1 - 1
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

+ 4 - 0
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>`