- Fix SheetCount count error;
- Optimize deserialization operations; - README updated, add go version required notice
This commit is contained in:
parent
330c7a0925
commit
8fd061b98f
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
Excelize is a library written in pure Golang and providing a set of functions that allow you to write to and read from XLSX files. Support reads and writes XLSX file generated by Office Excel 2007 and later. Support save file without losing original charts of XLSX. The full API docs can be seen using go's built-in documentation tool, or online at [godoc.org](https://godoc.org/github.com/Luxurioust/excelize).
|
Excelize is a library written in pure Golang and providing a set of functions that allow you to write to and read from XLSX files. Support reads and writes XLSX file generated by Office Excel 2007 and later. Support save file without losing original charts of XLSX. This library needs Go version 1.8 or later. The full API docs can be seen using go's built-in documentation tool, or online at [godoc.org](https://godoc.org/github.com/Luxurioust/excelize).
|
||||||
|
|
||||||
## Basic Usage
|
## Basic Usage
|
||||||
|
|
||||||
|
|
18
excelize.go
18
excelize.go
|
@ -13,11 +13,14 @@ import (
|
||||||
|
|
||||||
// File define a populated XLSX file struct.
|
// File define a populated XLSX file struct.
|
||||||
type File struct {
|
type File struct {
|
||||||
checked map[string]bool
|
checked map[string]bool
|
||||||
XLSX map[string]string
|
ContentTypes *xlsxTypes
|
||||||
Path string
|
Path string
|
||||||
Sheet map[string]*xlsxWorksheet
|
Sheet map[string]*xlsxWorksheet
|
||||||
SheetCount int
|
SheetCount int
|
||||||
|
WorkBook *xlsxWorkbook
|
||||||
|
WorkBookRels *xlsxWorkbookRels
|
||||||
|
XLSX map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenFile take the name of an XLSX file and returns a populated XLSX file
|
// OpenFile take the name of an XLSX file and returns a populated XLSX file
|
||||||
|
@ -53,11 +56,10 @@ func OpenReader(r io.Reader) (*File, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &File{
|
return &File{
|
||||||
Sheet: make(map[string]*xlsxWorksheet),
|
|
||||||
checked: make(map[string]bool),
|
checked: make(map[string]bool),
|
||||||
XLSX: file,
|
Sheet: make(map[string]*xlsxWorksheet),
|
||||||
Path: "",
|
|
||||||
SheetCount: sheetCount,
|
SheetCount: sheetCount,
|
||||||
|
XLSX: file,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
17
file.go
17
file.go
|
@ -3,7 +3,6 @@ package excelize
|
||||||
import (
|
import (
|
||||||
"archive/zip"
|
"archive/zip"
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/xml"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
@ -26,8 +25,8 @@ func CreateFile() *File {
|
||||||
file["xl/workbook.xml"] = templateWorkbook
|
file["xl/workbook.xml"] = templateWorkbook
|
||||||
file["[Content_Types].xml"] = templateContentTypes
|
file["[Content_Types].xml"] = templateContentTypes
|
||||||
return &File{
|
return &File{
|
||||||
XLSX: file,
|
|
||||||
Sheet: make(map[string]*xlsxWorksheet),
|
Sheet: make(map[string]*xlsxWorksheet),
|
||||||
|
XLSX: file,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,16 +53,10 @@ func (f *File) WriteTo(name string) error {
|
||||||
func (f *File) Write(w io.Writer) error {
|
func (f *File) Write(w io.Writer) error {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
zw := zip.NewWriter(buf)
|
zw := zip.NewWriter(buf)
|
||||||
for path, sheet := range f.Sheet {
|
f.contentTypesWriter()
|
||||||
if sheet == nil {
|
f.workbookWriter()
|
||||||
continue
|
f.workbookRelsWriter()
|
||||||
}
|
f.worksheetWriter()
|
||||||
output, err := xml.Marshal(sheet)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
f.saveFileList(path, replaceWorkSheetsRelationshipsNameSpace(string(output)))
|
|
||||||
}
|
|
||||||
for path, content := range f.XLSX {
|
for path, content := range f.XLSX {
|
||||||
fi, err := zw.Create(path)
|
fi, err := zw.Create(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
12
picture.go
12
picture.go
|
@ -303,8 +303,7 @@ func (f *File) addMedia(file string, ext string) {
|
||||||
// for relationship parts and the Main Document part.
|
// for relationship parts and the Main Document part.
|
||||||
func (f *File) setContentTypePartImageExtensions() {
|
func (f *File) setContentTypePartImageExtensions() {
|
||||||
var imageTypes = map[string]bool{"jpeg": false, "png": false, "gif": false}
|
var imageTypes = map[string]bool{"jpeg": false, "png": false, "gif": false}
|
||||||
var content xlsxTypes
|
content := f.contentTypesReader()
|
||||||
xml.Unmarshal([]byte(f.readXML("[Content_Types].xml")), &content)
|
|
||||||
for _, v := range content.Defaults {
|
for _, v := range content.Defaults {
|
||||||
_, ok := imageTypes[v.Extension]
|
_, ok := imageTypes[v.Extension]
|
||||||
if ok {
|
if ok {
|
||||||
|
@ -319,8 +318,6 @@ func (f *File) setContentTypePartImageExtensions() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output, _ := xml.Marshal(content)
|
|
||||||
f.saveFileList("[Content_Types].xml", string(output))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// addDrawingContentTypePart provides function to add image part relationships
|
// addDrawingContentTypePart provides function to add image part relationships
|
||||||
|
@ -328,12 +325,9 @@ func (f *File) setContentTypePartImageExtensions() {
|
||||||
// appropriate content type.
|
// appropriate content type.
|
||||||
func (f *File) addDrawingContentTypePart(index int) {
|
func (f *File) addDrawingContentTypePart(index int) {
|
||||||
f.setContentTypePartImageExtensions()
|
f.setContentTypePartImageExtensions()
|
||||||
var content xlsxTypes
|
content := f.contentTypesReader()
|
||||||
xml.Unmarshal([]byte(f.readXML("[Content_Types].xml")), &content)
|
|
||||||
for _, v := range content.Overrides {
|
for _, v := range content.Overrides {
|
||||||
if v.PartName == "/xl/drawings/drawing"+strconv.Itoa(index)+".xml" {
|
if v.PartName == "/xl/drawings/drawing"+strconv.Itoa(index)+".xml" {
|
||||||
output, _ := xml.Marshal(content)
|
|
||||||
f.saveFileList(`[Content_Types].xml`, string(output))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -341,8 +335,6 @@ func (f *File) addDrawingContentTypePart(index int) {
|
||||||
PartName: "/xl/drawings/drawing" + strconv.Itoa(index) + ".xml",
|
PartName: "/xl/drawings/drawing" + strconv.Itoa(index) + ".xml",
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.drawing+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.drawing+xml",
|
||||||
})
|
})
|
||||||
output, _ := xml.Marshal(content)
|
|
||||||
f.saveFileList("[Content_Types].xml", string(output))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getSheetRelationshipsTargetByID provides function to get Target attribute
|
// getSheetRelationshipsTargetByID provides function to get Target attribute
|
||||||
|
|
137
sheet.go
137
sheet.go
|
@ -4,7 +4,6 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -25,21 +24,67 @@ func (f *File) NewSheet(index int, name string) {
|
||||||
rID := f.addXlsxWorkbookRels(index)
|
rID := f.addXlsxWorkbookRels(index)
|
||||||
// Update xl/workbook.xml
|
// Update xl/workbook.xml
|
||||||
f.setWorkbook(name, rID)
|
f.setWorkbook(name, rID)
|
||||||
|
f.SheetCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
// contentTypesReader provides function to get the pointer to the
|
||||||
|
// [Content_Types].xml structure after deserialization.
|
||||||
|
func (f *File) contentTypesReader() *xlsxTypes {
|
||||||
|
if f.ContentTypes == nil {
|
||||||
|
var content xlsxTypes
|
||||||
|
xml.Unmarshal([]byte(f.readXML("[Content_Types].xml")), &content)
|
||||||
|
f.ContentTypes = &content
|
||||||
|
}
|
||||||
|
return f.ContentTypes
|
||||||
|
}
|
||||||
|
|
||||||
|
// contentTypesWriter provides function to save [Content_Types].xml after
|
||||||
|
// serialize structure.
|
||||||
|
func (f *File) contentTypesWriter() {
|
||||||
|
if f.ContentTypes != nil {
|
||||||
|
output, _ := xml.Marshal(f.ContentTypes)
|
||||||
|
f.saveFileList("[Content_Types].xml", string(output))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// workbookReader provides function to get the pointer to the xl/workbook.xml
|
||||||
|
// structure after deserialization.
|
||||||
|
func (f *File) workbookReader() *xlsxWorkbook {
|
||||||
|
if f.WorkBook == nil {
|
||||||
|
var content xlsxWorkbook
|
||||||
|
xml.Unmarshal([]byte(f.readXML("xl/workbook.xml")), &content)
|
||||||
|
f.WorkBook = &content
|
||||||
|
}
|
||||||
|
return f.WorkBook
|
||||||
|
}
|
||||||
|
|
||||||
|
// workbookWriter provides function to save xl/workbook.xml after serialize
|
||||||
|
// structure.
|
||||||
|
func (f *File) workbookWriter() {
|
||||||
|
if f.WorkBook != nil {
|
||||||
|
output, _ := xml.Marshal(f.WorkBook)
|
||||||
|
f.saveFileList("xl/workbook.xml", replaceRelationshipsNameSpace(string(output)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// worksheetWriter provides function to save xl/worksheets/sheet%d.xml after
|
||||||
|
// serialize structure.
|
||||||
|
func (f *File) worksheetWriter() {
|
||||||
|
for path, sheet := range f.Sheet {
|
||||||
|
if sheet != nil {
|
||||||
|
output, _ := xml.Marshal(sheet)
|
||||||
|
f.saveFileList(path, replaceWorkSheetsRelationshipsNameSpace(string(output)))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read and update property of contents type of XLSX.
|
// Read and update property of contents type of XLSX.
|
||||||
func (f *File) setContentTypes(index int) {
|
func (f *File) setContentTypes(index int) {
|
||||||
var content xlsxTypes
|
content := f.contentTypesReader()
|
||||||
xml.Unmarshal([]byte(f.readXML("[Content_Types].xml")), &content)
|
|
||||||
content.Overrides = append(content.Overrides, xlsxOverride{
|
content.Overrides = append(content.Overrides, xlsxOverride{
|
||||||
PartName: "/xl/worksheets/sheet" + strconv.Itoa(index) + ".xml",
|
PartName: "/xl/worksheets/sheet" + strconv.Itoa(index) + ".xml",
|
||||||
ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
|
ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
|
||||||
})
|
})
|
||||||
output, err := xml.Marshal(content)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
f.saveFileList("[Content_Types].xml", string(output))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update sheet property by given index.
|
// Update sheet property by given index.
|
||||||
|
@ -56,35 +101,42 @@ func (f *File) setSheet(index int) {
|
||||||
// setWorkbook update workbook property of XLSX. Maximum 31 characters are
|
// setWorkbook update workbook property of XLSX. Maximum 31 characters are
|
||||||
// allowed in sheet title.
|
// allowed in sheet title.
|
||||||
func (f *File) setWorkbook(name string, rid int) {
|
func (f *File) setWorkbook(name string, rid int) {
|
||||||
var content xlsxWorkbook
|
|
||||||
r := strings.NewReplacer(":", "", "\\", "", "/", "", "?", "", "*", "", "[", "", "]", "")
|
r := strings.NewReplacer(":", "", "\\", "", "/", "", "?", "", "*", "", "[", "", "]", "")
|
||||||
name = r.Replace(name)
|
name = r.Replace(name)
|
||||||
if len(name) > 31 {
|
if len(name) > 31 {
|
||||||
name = name[0:31]
|
name = name[0:31]
|
||||||
}
|
}
|
||||||
xml.Unmarshal([]byte(f.readXML("xl/workbook.xml")), &content)
|
content := f.workbookReader()
|
||||||
content.Sheets.Sheet = append(content.Sheets.Sheet, xlsxSheet{
|
content.Sheets.Sheet = append(content.Sheets.Sheet, xlsxSheet{
|
||||||
Name: name,
|
Name: name,
|
||||||
SheetID: strconv.Itoa(rid),
|
SheetID: strconv.Itoa(rid),
|
||||||
ID: "rId" + strconv.Itoa(rid),
|
ID: "rId" + strconv.Itoa(rid),
|
||||||
})
|
})
|
||||||
output, err := xml.Marshal(content)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
f.saveFileList("xl/workbook.xml", replaceRelationshipsNameSpace(string(output)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// readXlsxWorkbookRels read and unmarshal workbook relationships of XLSX file.
|
// workbookRelsReader provides function to read and unmarshal workbook
|
||||||
func (f *File) readXlsxWorkbookRels() xlsxWorkbookRels {
|
// relationships of XLSX file.
|
||||||
var content xlsxWorkbookRels
|
func (f *File) workbookRelsReader() *xlsxWorkbookRels {
|
||||||
xml.Unmarshal([]byte(f.readXML("xl/_rels/workbook.xml.rels")), &content)
|
if f.WorkBookRels == nil {
|
||||||
return content
|
var content xlsxWorkbookRels
|
||||||
|
xml.Unmarshal([]byte(f.readXML("xl/_rels/workbook.xml.rels")), &content)
|
||||||
|
f.WorkBookRels = &content
|
||||||
|
}
|
||||||
|
return f.WorkBookRels
|
||||||
|
}
|
||||||
|
|
||||||
|
// workbookRelsWriter provides function to save xl/_rels/workbook.xml.rels after
|
||||||
|
// serialize structure.
|
||||||
|
func (f *File) workbookRelsWriter() {
|
||||||
|
if f.WorkBookRels != nil {
|
||||||
|
output, _ := xml.Marshal(f.WorkBookRels)
|
||||||
|
f.saveFileList("xl/_rels/workbook.xml.rels", string(output))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// addXlsxWorkbookRels update workbook relationships property of XLSX.
|
// addXlsxWorkbookRels update workbook relationships property of XLSX.
|
||||||
func (f *File) addXlsxWorkbookRels(sheet int) int {
|
func (f *File) addXlsxWorkbookRels(sheet int) int {
|
||||||
content := f.readXlsxWorkbookRels()
|
content := f.workbookRelsReader()
|
||||||
rID := 0
|
rID := 0
|
||||||
for _, v := range content.Relationships {
|
for _, v := range content.Relationships {
|
||||||
t, _ := strconv.Atoi(strings.TrimPrefix(v.ID, "rId"))
|
t, _ := strconv.Atoi(strings.TrimPrefix(v.ID, "rId"))
|
||||||
|
@ -105,11 +157,6 @@ func (f *File) addXlsxWorkbookRels(sheet int) int {
|
||||||
Target: target.String(),
|
Target: target.String(),
|
||||||
Type: SourceRelationshipWorkSheet,
|
Type: SourceRelationshipWorkSheet,
|
||||||
})
|
})
|
||||||
output, err := xml.Marshal(content)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
f.saveFileList("xl/_rels/workbook.xml.rels", string(output))
|
|
||||||
return rID
|
return rID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,12 +181,11 @@ func replaceRelationshipsNameSpace(workbookMarshal string) string {
|
||||||
// SetActiveSheet provides function to set default active sheet of XLSX by given
|
// SetActiveSheet provides function to set default active sheet of XLSX by given
|
||||||
// index.
|
// index.
|
||||||
func (f *File) SetActiveSheet(index int) {
|
func (f *File) SetActiveSheet(index int) {
|
||||||
var content xlsxWorkbook
|
|
||||||
if index < 1 {
|
if index < 1 {
|
||||||
index = 1
|
index = 1
|
||||||
}
|
}
|
||||||
index--
|
index--
|
||||||
xml.Unmarshal([]byte(f.readXML("xl/workbook.xml")), &content)
|
content := f.workbookReader()
|
||||||
if len(content.BookViews.WorkBookView) > 0 {
|
if len(content.BookViews.WorkBookView) > 0 {
|
||||||
content.BookViews.WorkBookView[0].ActiveTab = index
|
content.BookViews.WorkBookView[0].ActiveTab = index
|
||||||
} else {
|
} else {
|
||||||
|
@ -148,11 +194,6 @@ func (f *File) SetActiveSheet(index int) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
sheets := len(content.Sheets.Sheet)
|
sheets := len(content.Sheets.Sheet)
|
||||||
output, err := xml.Marshal(content)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
f.saveFileList("xl/workbook.xml", replaceRelationshipsNameSpace(string(output)))
|
|
||||||
index++
|
index++
|
||||||
for i := 0; i < sheets; i++ {
|
for i := 0; i < sheets; i++ {
|
||||||
sheetIndex := i + 1
|
sheetIndex := i + 1
|
||||||
|
@ -177,9 +218,8 @@ func (f *File) SetActiveSheet(index int) {
|
||||||
// GetActiveSheetIndex provides function to get active sheet of XLSX. If not
|
// GetActiveSheetIndex provides function to get active sheet of XLSX. If not
|
||||||
// found the active sheet will be return integer 0.
|
// found the active sheet will be return integer 0.
|
||||||
func (f *File) GetActiveSheetIndex() int {
|
func (f *File) GetActiveSheetIndex() int {
|
||||||
content := xlsxWorkbook{}
|
|
||||||
buffer := bytes.Buffer{}
|
buffer := bytes.Buffer{}
|
||||||
xml.Unmarshal([]byte(f.readXML("xl/workbook.xml")), &content)
|
content := f.workbookReader()
|
||||||
for _, v := range content.Sheets.Sheet {
|
for _, v := range content.Sheets.Sheet {
|
||||||
xlsx := xlsxWorksheet{}
|
xlsx := xlsxWorksheet{}
|
||||||
buffer.WriteString("xl/worksheets/sheet")
|
buffer.WriteString("xl/worksheets/sheet")
|
||||||
|
@ -203,27 +243,23 @@ func (f *File) GetActiveSheetIndex() int {
|
||||||
// name in the formula or reference associated with the cell. So there may be
|
// name in the formula or reference associated with the cell. So there may be
|
||||||
// problem formula error or reference missing.
|
// problem formula error or reference missing.
|
||||||
func (f *File) SetSheetName(oldName, newName string) {
|
func (f *File) SetSheetName(oldName, newName string) {
|
||||||
var content = xlsxWorkbook{}
|
|
||||||
r := strings.NewReplacer(":", "", "\\", "", "/", "", "?", "", "*", "", "[", "", "]", "")
|
r := strings.NewReplacer(":", "", "\\", "", "/", "", "?", "", "*", "", "[", "", "]", "")
|
||||||
newName = r.Replace(newName)
|
newName = r.Replace(newName)
|
||||||
if len(newName) > 31 {
|
if len(newName) > 31 {
|
||||||
newName = newName[0:31]
|
newName = newName[0:31]
|
||||||
}
|
}
|
||||||
xml.Unmarshal([]byte(f.readXML("xl/workbook.xml")), &content)
|
content := f.workbookReader()
|
||||||
for k, v := range content.Sheets.Sheet {
|
for k, v := range content.Sheets.Sheet {
|
||||||
if v.Name == oldName {
|
if v.Name == oldName {
|
||||||
content.Sheets.Sheet[k].Name = newName
|
content.Sheets.Sheet[k].Name = newName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output, _ := xml.Marshal(content)
|
|
||||||
f.saveFileList("xl/workbook.xml", replaceRelationshipsNameSpace(string(output)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSheetName provides function to get sheet name of XLSX by given sheet
|
// GetSheetName provides function to get sheet name of XLSX by given sheet
|
||||||
// index. If given sheet index is invalid, will return an empty string.
|
// index. If given sheet index is invalid, will return an empty string.
|
||||||
func (f *File) GetSheetName(index int) string {
|
func (f *File) GetSheetName(index int) string {
|
||||||
var content = xlsxWorkbook{}
|
content := f.workbookReader()
|
||||||
xml.Unmarshal([]byte(f.readXML("xl/workbook.xml")), &content)
|
|
||||||
for _, v := range content.Sheets.Sheet {
|
for _, v := range content.Sheets.Sheet {
|
||||||
if v.ID == "rId"+strconv.Itoa(index) {
|
if v.ID == "rId"+strconv.Itoa(index) {
|
||||||
return v.Name
|
return v.Name
|
||||||
|
@ -244,9 +280,8 @@ func (f *File) GetSheetName(index int) string {
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
func (f *File) GetSheetMap() map[int]string {
|
func (f *File) GetSheetMap() map[int]string {
|
||||||
content := xlsxWorkbook{}
|
content := f.workbookReader()
|
||||||
sheetMap := map[int]string{}
|
sheetMap := map[int]string{}
|
||||||
xml.Unmarshal([]byte(f.readXML("xl/workbook.xml")), &content)
|
|
||||||
for _, v := range content.Sheets.Sheet {
|
for _, v := range content.Sheets.Sheet {
|
||||||
id, _ := strconv.Atoi(strings.TrimPrefix(v.ID, "rId"))
|
id, _ := strconv.Atoi(strings.TrimPrefix(v.ID, "rId"))
|
||||||
sheetMap[id] = v.Name
|
sheetMap[id] = v.Name
|
||||||
|
@ -280,15 +315,12 @@ func (f *File) SetSheetBackground(sheet, picture string) error {
|
||||||
// value of the deleted worksheet, it will cause a file error when you open it.
|
// value of the deleted worksheet, it will cause a file error when you open it.
|
||||||
// This function will be invalid when only the one worksheet is left.
|
// This function will be invalid when only the one worksheet is left.
|
||||||
func (f *File) DeleteSheet(name string) {
|
func (f *File) DeleteSheet(name string) {
|
||||||
var content xlsxWorkbook
|
content := f.workbookReader()
|
||||||
xml.Unmarshal([]byte(f.readXML("xl/workbook.xml")), &content)
|
|
||||||
for k, v := range content.Sheets.Sheet {
|
for k, v := range content.Sheets.Sheet {
|
||||||
if v.Name != name || len(content.Sheets.Sheet) < 2 {
|
if v.Name != name || len(content.Sheets.Sheet) < 2 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
content.Sheets.Sheet = append(content.Sheets.Sheet[:k], content.Sheets.Sheet[k+1:]...)
|
content.Sheets.Sheet = append(content.Sheets.Sheet[:k], content.Sheets.Sheet[k+1:]...)
|
||||||
output, _ := xml.Marshal(content)
|
|
||||||
f.saveFileList("xl/workbook.xml", replaceRelationshipsNameSpace(string(output)))
|
|
||||||
sheet := "xl/worksheets/sheet" + strings.TrimPrefix(v.ID, "rId") + ".xml"
|
sheet := "xl/worksheets/sheet" + strings.TrimPrefix(v.ID, "rId") + ".xml"
|
||||||
rels := "xl/worksheets/_rels/sheet" + strings.TrimPrefix(v.ID, "rId") + ".xml.rels"
|
rels := "xl/worksheets/_rels/sheet" + strings.TrimPrefix(v.ID, "rId") + ".xml.rels"
|
||||||
target := f.deteleSheetFromWorkbookRels(v.ID)
|
target := f.deteleSheetFromWorkbookRels(v.ID)
|
||||||
|
@ -305,6 +337,7 @@ func (f *File) DeleteSheet(name string) {
|
||||||
if ok {
|
if ok {
|
||||||
delete(f.Sheet, sheet)
|
delete(f.Sheet, sheet)
|
||||||
}
|
}
|
||||||
|
f.SheetCount--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,15 +345,12 @@ func (f *File) DeleteSheet(name string) {
|
||||||
// relationships by given relationships ID in the file
|
// relationships by given relationships ID in the file
|
||||||
// xl/_rels/workbook.xml.rels.
|
// xl/_rels/workbook.xml.rels.
|
||||||
func (f *File) deteleSheetFromWorkbookRels(rID string) string {
|
func (f *File) deteleSheetFromWorkbookRels(rID string) string {
|
||||||
var content xlsxWorkbookRels
|
content := f.workbookRelsReader()
|
||||||
xml.Unmarshal([]byte(f.readXML("xl/_rels/workbook.xml.rels")), &content)
|
|
||||||
for k, v := range content.Relationships {
|
for k, v := range content.Relationships {
|
||||||
if v.ID != rID {
|
if v.ID != rID {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
content.Relationships = append(content.Relationships[:k], content.Relationships[k+1:]...)
|
content.Relationships = append(content.Relationships[:k], content.Relationships[k+1:]...)
|
||||||
output, _ := xml.Marshal(content)
|
|
||||||
f.saveFileList("xl/_rels/workbook.xml.rels", string(output))
|
|
||||||
return v.Target
|
return v.Target
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
|
@ -329,14 +359,11 @@ func (f *File) deteleSheetFromWorkbookRels(rID string) string {
|
||||||
// deteleSheetFromContentTypes provides function to remove worksheet
|
// deteleSheetFromContentTypes provides function to remove worksheet
|
||||||
// relationships by given target name in the file [Content_Types].xml.
|
// relationships by given target name in the file [Content_Types].xml.
|
||||||
func (f *File) deteleSheetFromContentTypes(target string) {
|
func (f *File) deteleSheetFromContentTypes(target string) {
|
||||||
var content xlsxTypes
|
content := f.contentTypesReader()
|
||||||
xml.Unmarshal([]byte(f.readXML("[Content_Types].xml")), &content)
|
|
||||||
for k, v := range content.Overrides {
|
for k, v := range content.Overrides {
|
||||||
if v.PartName != "/xl/"+target {
|
if v.PartName != "/xl/"+target {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
content.Overrides = append(content.Overrides[:k], content.Overrides[k+1:]...)
|
content.Overrides = append(content.Overrides[:k], content.Overrides[k+1:]...)
|
||||||
output, _ := xml.Marshal(content)
|
|
||||||
f.saveFileList("[Content_Types].xml", string(output))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue