From f66212da9bab1c39ab791d41881c70ae7ba00c20 Mon Sep 17 00:00:00 2001 From: xuri Date: Tue, 26 Feb 2019 14:21:44 +0800 Subject: [PATCH] Resolve #106, #294 performance optimization for add hyperlink --- comment.go | 10 +++++----- excelize.go | 2 ++ file.go | 8 +++++--- picture.go | 35 ++++++++++++++++++----------------- sheet.go | 37 +++++++++++++++++++++++++++++++------ test/CalcChain.xlsx | Bin 6 files changed, 61 insertions(+), 31 deletions(-) mode change 100755 => 100644 test/CalcChain.xlsx diff --git a/comment.go b/comment.go index c86e932..7fb1739 100644 --- a/comment.go +++ b/comment.go @@ -57,11 +57,11 @@ func (f *File) GetComments() (comments map[string][]Comment) { // given worksheet index. func (f *File) getSheetComments(sheetID int) string { var rels = "xl/worksheets/_rels/sheet" + strconv.Itoa(sheetID) + ".xml.rels" - var sheetRels xlsxWorkbookRels - _ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML(rels)), &sheetRels) - for _, v := range sheetRels.Relationships { - if v.Type == SourceRelationshipComments { - return v.Target + if sheetRels := f.workSheetRelsReader(rels); sheetRels != nil { + for _, v := range sheetRels.Relationships { + if v.Type == SourceRelationshipComments { + return v.Target + } } } return "" diff --git a/excelize.go b/excelize.go index a2bec07..feb41cb 100644 --- a/excelize.go +++ b/excelize.go @@ -40,6 +40,7 @@ type File struct { VMLDrawing map[string]*vmlDrawing WorkBook *xlsxWorkbook WorkBookRels *xlsxWorkbookRels + WorkSheetRels map[string]*xlsxWorkbookRels XLSX map[string][]byte } @@ -84,6 +85,7 @@ func OpenReader(r io.Reader) (*File, error) { SheetCount: sheetCount, DecodeVMLDrawing: make(map[string]*decodeVmlDrawing), VMLDrawing: make(map[string]*vmlDrawing), + WorkSheetRels: make(map[string]*xlsxWorkbookRels), XLSX: file, } f.CalcChain = f.calcChainReader() diff --git a/file.go b/file.go index 8d68851..2f5164f 100644 --- a/file.go +++ b/file.go @@ -49,6 +49,7 @@ func NewFile() *File { f.VMLDrawing = make(map[string]*vmlDrawing) f.WorkBook = f.workbookReader() f.WorkBookRels = f.workbookRelsReader() + f.WorkSheetRels = make(map[string]*xlsxWorkbookRels) f.Sheet["xl/worksheets/sheet1.xml"] = f.workSheetReader("Sheet1") f.sheetMap["Sheet1"] = "xl/worksheets/sheet1.xml" f.Theme = f.themeReader() @@ -99,9 +100,10 @@ func (f *File) WriteToBuffer() (*bytes.Buffer, error) { f.drawingRelsWriter() f.drawingsWriter() f.vmlDrawingWriter() - f.workbookWriter() - f.workbookRelsWriter() - f.worksheetWriter() + f.workBookWriter() + f.workBookRelsWriter() + f.workSheetWriter() + f.workSheetRelsWriter() f.styleSheetWriter() for path, content := range f.XLSX { diff --git a/picture.go b/picture.go index 2ad9db2..131b15c 100644 --- a/picture.go +++ b/picture.go @@ -177,27 +177,25 @@ func (f *File) addSheetRelationships(sheet, relType, target, targetMode string) name = strings.ToLower(sheet) + ".xml" } var rels = "xl/worksheets/_rels/" + strings.TrimPrefix(name, "xl/worksheets/") + ".rels" - var sheetRels xlsxWorkbookRels + sheetRels := f.workSheetRelsReader(rels) + if sheetRels == nil { + sheetRels = &xlsxWorkbookRels{} + } var rID = 1 var ID bytes.Buffer ID.WriteString("rId") ID.WriteString(strconv.Itoa(rID)) - _, ok = f.XLSX[rels] - if ok { - ID.Reset() - _ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML(rels)), &sheetRels) - rID = len(sheetRels.Relationships) + 1 - ID.WriteString("rId") - ID.WriteString(strconv.Itoa(rID)) - } + ID.Reset() + rID = len(sheetRels.Relationships) + 1 + ID.WriteString("rId") + ID.WriteString(strconv.Itoa(rID)) sheetRels.Relationships = append(sheetRels.Relationships, xlsxWorkbookRelation{ ID: ID.String(), Type: relType, Target: target, TargetMode: targetMode, }) - output, _ := xml.Marshal(sheetRels) - f.saveFileList(rels, output) + f.WorkSheetRels[rels] = sheetRels return rID } @@ -210,15 +208,16 @@ func (f *File) deleteSheetRelationships(sheet, rID string) { name = strings.ToLower(sheet) + ".xml" } var rels = "xl/worksheets/_rels/" + strings.TrimPrefix(name, "xl/worksheets/") + ".rels" - var sheetRels xlsxWorkbookRels - _ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML(rels)), &sheetRels) + sheetRels := f.workSheetRelsReader(rels) + if sheetRels == nil { + sheetRels = &xlsxWorkbookRels{} + } for k, v := range sheetRels.Relationships { if v.ID == rID { sheetRels.Relationships = append(sheetRels.Relationships[:k], sheetRels.Relationships[k+1:]...) } } - output, _ := xml.Marshal(sheetRels) - f.saveFileList(rels, output) + f.WorkSheetRels[rels] = sheetRels } // addSheetLegacyDrawing provides a function to add legacy drawing element to @@ -441,8 +440,10 @@ func (f *File) getSheetRelationshipsTargetByID(sheet, rID string) string { name = strings.ToLower(sheet) + ".xml" } var rels = "xl/worksheets/_rels/" + strings.TrimPrefix(name, "xl/worksheets/") + ".rels" - var sheetRels xlsxWorkbookRels - _ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML(rels)), &sheetRels) + sheetRels := f.workSheetRelsReader(rels) + if sheetRels == nil { + sheetRels = &xlsxWorkbookRels{} + } for _, v := range sheetRels.Relationships { if v.ID == rID { return v.Target diff --git a/sheet.go b/sheet.go index efbd466..26d4b4c 100644 --- a/sheet.go +++ b/sheet.go @@ -88,18 +88,18 @@ func (f *File) workbookReader() *xlsxWorkbook { return f.WorkBook } -// workbookWriter provides a function to save xl/workbook.xml after serialize +// workBookWriter provides a function to save xl/workbook.xml after serialize // structure. -func (f *File) workbookWriter() { +func (f *File) workBookWriter() { if f.WorkBook != nil { output, _ := xml.Marshal(f.WorkBook) f.saveFileList("xl/workbook.xml", replaceRelationshipsNameSpaceBytes(output)) } } -// worksheetWriter provides a function to save xl/worksheets/sheet%d.xml after +// workSheetWriter provides a function to save xl/worksheets/sheet%d.xml after // serialize structure. -func (f *File) worksheetWriter() { +func (f *File) workSheetWriter() { for path, sheet := range f.Sheet { if sheet != nil { for k, v := range sheet.SheetData.Row { @@ -172,9 +172,9 @@ func (f *File) workbookRelsReader() *xlsxWorkbookRels { return f.WorkBookRels } -// workbookRelsWriter provides a function to save xl/_rels/workbook.xml.rels after +// workBookRelsWriter provides a function to save xl/_rels/workbook.xml.rels after // serialize structure. -func (f *File) workbookRelsWriter() { +func (f *File) workBookRelsWriter() { if f.WorkBookRels != nil { output, _ := xml.Marshal(f.WorkBookRels) f.saveFileList("xl/_rels/workbook.xml.rels", output) @@ -1003,3 +1003,28 @@ func (f *File) GetPageLayout(sheet string, opts ...PageLayoutOptionPtr) error { } return nil } + +// workSheetRelsReader provides a function to get the pointer to the structure +// after deserialization of xl/worksheets/_rels/sheet%d.xml.rels. +func (f *File) workSheetRelsReader(path string) *xlsxWorkbookRels { + if f.WorkSheetRels[path] == nil { + _, ok := f.XLSX[path] + if ok { + c := xlsxWorkbookRels{} + _ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML(path)), &c) + f.WorkSheetRels[path] = &c + } + } + return f.WorkSheetRels[path] +} + +// workSheetRelsWriter provides a function to save +// xl/worksheets/_rels/sheet%d.xml.rels after serialize structure. +func (f *File) workSheetRelsWriter() { + for path, r := range f.WorkSheetRels { + if r != nil { + v, _ := xml.Marshal(r) + f.saveFileList(path, v) + } + } +} diff --git a/test/CalcChain.xlsx b/test/CalcChain.xlsx old mode 100755 new mode 100644