Resolve #106, #294 performance optimization for add hyperlink

This commit is contained in:
xuri 2019-02-26 14:21:44 +08:00
parent 1aed1d744b
commit f66212da9b
No known key found for this signature in database
GPG Key ID: BA5E5BB1C948EDF7
6 changed files with 61 additions and 31 deletions

View File

@ -57,13 +57,13 @@ func (f *File) GetComments() (comments map[string][]Comment) {
// given worksheet index. // given worksheet index.
func (f *File) getSheetComments(sheetID int) string { func (f *File) getSheetComments(sheetID int) string {
var rels = "xl/worksheets/_rels/sheet" + strconv.Itoa(sheetID) + ".xml.rels" var rels = "xl/worksheets/_rels/sheet" + strconv.Itoa(sheetID) + ".xml.rels"
var sheetRels xlsxWorkbookRels if sheetRels := f.workSheetRelsReader(rels); sheetRels != nil {
_ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML(rels)), &sheetRels)
for _, v := range sheetRels.Relationships { for _, v := range sheetRels.Relationships {
if v.Type == SourceRelationshipComments { if v.Type == SourceRelationshipComments {
return v.Target return v.Target
} }
} }
}
return "" return ""
} }

View File

@ -40,6 +40,7 @@ type File struct {
VMLDrawing map[string]*vmlDrawing VMLDrawing map[string]*vmlDrawing
WorkBook *xlsxWorkbook WorkBook *xlsxWorkbook
WorkBookRels *xlsxWorkbookRels WorkBookRels *xlsxWorkbookRels
WorkSheetRels map[string]*xlsxWorkbookRels
XLSX map[string][]byte XLSX map[string][]byte
} }
@ -84,6 +85,7 @@ func OpenReader(r io.Reader) (*File, error) {
SheetCount: sheetCount, SheetCount: sheetCount,
DecodeVMLDrawing: make(map[string]*decodeVmlDrawing), DecodeVMLDrawing: make(map[string]*decodeVmlDrawing),
VMLDrawing: make(map[string]*vmlDrawing), VMLDrawing: make(map[string]*vmlDrawing),
WorkSheetRels: make(map[string]*xlsxWorkbookRels),
XLSX: file, XLSX: file,
} }
f.CalcChain = f.calcChainReader() f.CalcChain = f.calcChainReader()

View File

@ -49,6 +49,7 @@ func NewFile() *File {
f.VMLDrawing = make(map[string]*vmlDrawing) f.VMLDrawing = make(map[string]*vmlDrawing)
f.WorkBook = f.workbookReader() f.WorkBook = f.workbookReader()
f.WorkBookRels = f.workbookRelsReader() f.WorkBookRels = f.workbookRelsReader()
f.WorkSheetRels = make(map[string]*xlsxWorkbookRels)
f.Sheet["xl/worksheets/sheet1.xml"] = f.workSheetReader("Sheet1") f.Sheet["xl/worksheets/sheet1.xml"] = f.workSheetReader("Sheet1")
f.sheetMap["Sheet1"] = "xl/worksheets/sheet1.xml" f.sheetMap["Sheet1"] = "xl/worksheets/sheet1.xml"
f.Theme = f.themeReader() f.Theme = f.themeReader()
@ -99,9 +100,10 @@ func (f *File) WriteToBuffer() (*bytes.Buffer, error) {
f.drawingRelsWriter() f.drawingRelsWriter()
f.drawingsWriter() f.drawingsWriter()
f.vmlDrawingWriter() f.vmlDrawingWriter()
f.workbookWriter() f.workBookWriter()
f.workbookRelsWriter() f.workBookRelsWriter()
f.worksheetWriter() f.workSheetWriter()
f.workSheetRelsWriter()
f.styleSheetWriter() f.styleSheetWriter()
for path, content := range f.XLSX { for path, content := range f.XLSX {

View File

@ -177,27 +177,25 @@ func (f *File) addSheetRelationships(sheet, relType, target, targetMode string)
name = strings.ToLower(sheet) + ".xml" name = strings.ToLower(sheet) + ".xml"
} }
var rels = "xl/worksheets/_rels/" + strings.TrimPrefix(name, "xl/worksheets/") + ".rels" 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 rID = 1
var ID bytes.Buffer var ID bytes.Buffer
ID.WriteString("rId") ID.WriteString("rId")
ID.WriteString(strconv.Itoa(rID)) ID.WriteString(strconv.Itoa(rID))
_, ok = f.XLSX[rels]
if ok {
ID.Reset() ID.Reset()
_ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML(rels)), &sheetRels)
rID = len(sheetRels.Relationships) + 1 rID = len(sheetRels.Relationships) + 1
ID.WriteString("rId") ID.WriteString("rId")
ID.WriteString(strconv.Itoa(rID)) ID.WriteString(strconv.Itoa(rID))
}
sheetRels.Relationships = append(sheetRels.Relationships, xlsxWorkbookRelation{ sheetRels.Relationships = append(sheetRels.Relationships, xlsxWorkbookRelation{
ID: ID.String(), ID: ID.String(),
Type: relType, Type: relType,
Target: target, Target: target,
TargetMode: targetMode, TargetMode: targetMode,
}) })
output, _ := xml.Marshal(sheetRels) f.WorkSheetRels[rels] = sheetRels
f.saveFileList(rels, output)
return rID return rID
} }
@ -210,15 +208,16 @@ func (f *File) deleteSheetRelationships(sheet, rID string) {
name = strings.ToLower(sheet) + ".xml" name = strings.ToLower(sheet) + ".xml"
} }
var rels = "xl/worksheets/_rels/" + strings.TrimPrefix(name, "xl/worksheets/") + ".rels" var rels = "xl/worksheets/_rels/" + strings.TrimPrefix(name, "xl/worksheets/") + ".rels"
var sheetRels xlsxWorkbookRels sheetRels := f.workSheetRelsReader(rels)
_ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML(rels)), &sheetRels) if sheetRels == nil {
sheetRels = &xlsxWorkbookRels{}
}
for k, v := range sheetRels.Relationships { for k, v := range sheetRels.Relationships {
if v.ID == rID { if v.ID == rID {
sheetRels.Relationships = append(sheetRels.Relationships[:k], sheetRels.Relationships[k+1:]...) sheetRels.Relationships = append(sheetRels.Relationships[:k], sheetRels.Relationships[k+1:]...)
} }
} }
output, _ := xml.Marshal(sheetRels) f.WorkSheetRels[rels] = sheetRels
f.saveFileList(rels, output)
} }
// addSheetLegacyDrawing provides a function to add legacy drawing element to // 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" name = strings.ToLower(sheet) + ".xml"
} }
var rels = "xl/worksheets/_rels/" + strings.TrimPrefix(name, "xl/worksheets/") + ".rels" var rels = "xl/worksheets/_rels/" + strings.TrimPrefix(name, "xl/worksheets/") + ".rels"
var sheetRels xlsxWorkbookRels sheetRels := f.workSheetRelsReader(rels)
_ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML(rels)), &sheetRels) if sheetRels == nil {
sheetRels = &xlsxWorkbookRels{}
}
for _, v := range sheetRels.Relationships { for _, v := range sheetRels.Relationships {
if v.ID == rID { if v.ID == rID {
return v.Target return v.Target

View File

@ -88,18 +88,18 @@ func (f *File) workbookReader() *xlsxWorkbook {
return f.WorkBook 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. // structure.
func (f *File) workbookWriter() { func (f *File) workBookWriter() {
if f.WorkBook != nil { if f.WorkBook != nil {
output, _ := xml.Marshal(f.WorkBook) output, _ := xml.Marshal(f.WorkBook)
f.saveFileList("xl/workbook.xml", replaceRelationshipsNameSpaceBytes(output)) 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. // serialize structure.
func (f *File) worksheetWriter() { func (f *File) workSheetWriter() {
for path, sheet := range f.Sheet { for path, sheet := range f.Sheet {
if sheet != nil { if sheet != nil {
for k, v := range sheet.SheetData.Row { for k, v := range sheet.SheetData.Row {
@ -172,9 +172,9 @@ func (f *File) workbookRelsReader() *xlsxWorkbookRels {
return f.WorkBookRels 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. // serialize structure.
func (f *File) workbookRelsWriter() { func (f *File) workBookRelsWriter() {
if f.WorkBookRels != nil { if f.WorkBookRels != nil {
output, _ := xml.Marshal(f.WorkBookRels) output, _ := xml.Marshal(f.WorkBookRels)
f.saveFileList("xl/_rels/workbook.xml.rels", output) f.saveFileList("xl/_rels/workbook.xml.rels", output)
@ -1003,3 +1003,28 @@ func (f *File) GetPageLayout(sheet string, opts ...PageLayoutOptionPtr) error {
} }
return nil 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)
}
}
}

0
test/CalcChain.xlsx Executable file → Normal file
View File