summaryrefslogtreecommitdiff
path: root/sheet.go
diff options
context:
space:
mode:
authorxuri <xuri.me@gmail.com>2020-11-04 00:28:20 +0800
committerxuri <xuri.me@gmail.com>2020-11-04 00:28:20 +0800
commitc82a185af83b8b3934efcb0b227e494a18f426ea (patch)
treecb87009836fd0b879c4af1516ff9e6daf6faa043 /sheet.go
parentfcca8a38389c7a7f99639dc142b9b10c827ac7ce (diff)
Compatibility improvement: parse document core part (workbook) dynamically
Diffstat (limited to 'sheet.go')
-rw-r--r--sheet.go62
1 files changed, 41 insertions, 21 deletions
diff --git a/sheet.go b/sheet.go
index caf87d9..9c9def7 100644
--- a/sheet.go
+++ b/sheet.go
@@ -22,6 +22,7 @@ import (
"log"
"os"
"path"
+ "path/filepath"
"reflect"
"regexp"
"strconv"
@@ -57,9 +58,11 @@ func (f *File) NewSheet(name string) int {
f.setContentTypes("/xl/worksheets/sheet"+strconv.Itoa(sheetID)+".xml", ContentTypeSpreadSheetMLWorksheet)
// Create new sheet /xl/worksheets/sheet%d.xml
f.setSheet(sheetID, name)
- // Update xl/_rels/workbook.xml.rels
- rID := f.addRels("xl/_rels/workbook.xml.rels", SourceRelationshipWorkSheet, fmt.Sprintf("worksheets/sheet%d.xml", sheetID), "")
- // Update xl/workbook.xml
+ // Update workbook.xml.rels
+ wbPath := f.getWorkbookPath()
+ wbRelsPath := strings.TrimPrefix(filepath.Join(filepath.Dir(wbPath), "_rels", filepath.Base(wbPath)+".rels"), string(filepath.Separator))
+ rID := f.addRels(wbRelsPath, SourceRelationshipWorkSheet, fmt.Sprintf("/xl/worksheets/sheet%d.xml", sheetID), "")
+ // Update workbook.xml
f.setWorkbook(name, sheetID, rID)
return f.GetSheetIndex(name)
}
@@ -89,18 +92,33 @@ func (f *File) contentTypesWriter() {
}
}
-// workbookReader provides a function to get the pointer to the xl/workbook.xml
+// getWorkbookPath provides a function to get the path of the workbook.xml in
+// the spreadsheet.
+func (f *File) getWorkbookPath() (path string) {
+ if rels := f.relsReader("_rels/.rels"); rels != nil {
+ for _, rel := range rels.Relationships {
+ if rel.Type == SourceRelationshipOfficeDocument {
+ path = strings.TrimPrefix(rel.Target, string(filepath.Separator))
+ return
+ }
+ }
+ }
+ return
+}
+
+// workbookReader provides a function to get the pointer to the workbook.xml
// structure after deserialization.
func (f *File) workbookReader() *xlsxWorkbook {
var err error
if f.WorkBook == nil {
+ wbPath := f.getWorkbookPath()
f.WorkBook = new(xlsxWorkbook)
- if _, ok := f.xmlAttr["xl/workbook.xml"]; !ok {
- d := f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML("xl/workbook.xml"))))
- f.xmlAttr["xl/workbook.xml"] = append(f.xmlAttr["xl/workbook.xml"], getRootElement(d)...)
- f.addNameSpaces("xl/workbook.xml", SourceRelationship)
+ if _, ok := f.xmlAttr[wbPath]; !ok {
+ d := f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(wbPath))))
+ f.xmlAttr[wbPath] = append(f.xmlAttr[wbPath], getRootElement(d)...)
+ f.addNameSpaces(wbPath, SourceRelationship)
}
- if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML("xl/workbook.xml")))).
+ if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(wbPath)))).
Decode(f.WorkBook); err != nil && err != io.EOF {
log.Printf("xml decode error: %s", err)
}
@@ -108,31 +126,28 @@ 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 workbook.xml after serialize
// structure.
func (f *File) workBookWriter() {
if f.WorkBook != nil {
output, _ := xml.Marshal(f.WorkBook)
- f.saveFileList("xl/workbook.xml", replaceRelationshipsBytes(f.replaceNameSpaceBytes("xl/workbook.xml", output)))
+ f.saveFileList(f.getWorkbookPath(), replaceRelationshipsBytes(f.replaceNameSpaceBytes(f.getWorkbookPath(), output)))
}
}
// workSheetWriter provides a function to save xl/worksheets/sheet%d.xml after
// serialize structure.
func (f *File) workSheetWriter() {
-
- // optimize memory alloc
var arr []byte
buffer := bytes.NewBuffer(arr)
encoder := xml.NewEncoder(buffer)
-
for p, sheet := range f.Sheet {
if sheet != nil {
for k, v := range sheet.SheetData.Row {
f.Sheet[p].SheetData.Row[k].C = trimCell(v.C)
}
// reusing buffer
- encoder.Encode(sheet)
+ _ = encoder.Encode(sheet)
f.saveFileList(p, replaceRelationshipsBytes(f.replaceNameSpaceBytes(p, buffer.Bytes())))
ok := f.checked[p]
if ok {
@@ -419,10 +434,12 @@ func (f *File) GetSheetList() (list []string) {
}
// getSheetMap provides a function to get worksheet name and XML file path map
-// of XLSX.
+// of the spreadsheet.
func (f *File) getSheetMap() map[string]string {
content := f.workbookReader()
- rels := f.relsReader("xl/_rels/workbook.xml.rels")
+ wbPath := f.getWorkbookPath()
+ wbRelsPath := strings.TrimPrefix(filepath.Join(filepath.Dir(wbPath), "_rels", filepath.Base(wbPath)+".rels"), string(filepath.Separator))
+ rels := f.relsReader(wbRelsPath)
maps := map[string]string{}
for _, v := range content.Sheets.Sheet {
for _, rel := range rels.Relationships {
@@ -472,7 +489,9 @@ func (f *File) DeleteSheet(name string) {
}
sheetName := trimSheetName(name)
wb := f.workbookReader()
- wbRels := f.relsReader("xl/_rels/workbook.xml.rels")
+ wbPath := f.getWorkbookPath()
+ wbRelsPath := strings.TrimPrefix(filepath.Join(filepath.Dir(wbPath), "_rels", filepath.Base(wbPath)+".rels"), string(filepath.Separator))
+ wbRels := f.relsReader(wbRelsPath)
for idx, sheet := range wb.Sheets.Sheet {
if sheet.Name == sheetName {
wb.Sheets.Sheet = append(wb.Sheets.Sheet[:idx], wb.Sheets.Sheet[idx+1:]...)
@@ -511,10 +530,11 @@ func (f *File) DeleteSheet(name string) {
}
// deleteSheetFromWorkbookRels provides a function to remove worksheet
-// relationships by given relationships ID in the file
-// xl/_rels/workbook.xml.rels.
+// relationships by given relationships ID in the file workbook.xml.rels.
func (f *File) deleteSheetFromWorkbookRels(rID string) string {
- content := f.relsReader("xl/_rels/workbook.xml.rels")
+ wbPath := f.getWorkbookPath()
+ wbRelsPath := strings.TrimPrefix(filepath.Join(filepath.Dir(wbPath), "_rels", filepath.Base(wbPath)+".rels"), string(filepath.Separator))
+ content := f.relsReader(wbRelsPath)
for k, v := range content.Relationships {
if v.ID == rID {
content.Relationships = append(content.Relationships[:k], content.Relationships[k+1:]...)