forked from p30928647/excelize
save bytes on memory instead of string
This commit is contained in:
parent
bc451a78de
commit
38ad20efc1
4
chart.go
4
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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
11
excelize.go
11
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
|
||||
|
|
20
file.go
20
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),
|
||||
|
|
19
lib.go
19
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
|
||||
|
|
10
picture.go
10
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
|
||||
|
|
14
rows.go
14
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)
|
||||
|
|
2
shape.go
2
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
|
||||
|
|
16
sheet.go
16
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
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
2
table.go
2
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
|
||||
|
|
|
@ -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>`
|
||||
|
|
Loading…
Reference in New Issue