diff options
Diffstat (limited to 'sheet.go')
-rw-r--r-- | sheet.go | 62 |
1 files changed, 41 insertions, 21 deletions
@@ -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:]...) |