diff options
Diffstat (limited to 'sheet.go')
-rw-r--r-- | sheet.go | 102 |
1 files changed, 59 insertions, 43 deletions
@@ -1,3 +1,12 @@ +// Copyright 2016 - 2018 The excelize Authors. All rights reserved. Use of +// this source code is governed by a BSD-style license that can be found in +// the LICENSE file. +// +// Package excelize providing a set of functions that allow you to write to +// and read from XLSX files. Support reads and writes XLSX file generated by +// Microsoft Excelâ„¢ 2007 and later. Support save file without losing original +// charts of XLSX. This library needs Go version 1.8 or later. + package excelize import ( @@ -5,17 +14,19 @@ import ( "encoding/json" "encoding/xml" "errors" + "io/ioutil" "os" "path" "strconv" "strings" "unicode/utf8" + + "github.com/mohae/deepcopy" ) // NewSheet provides function to create a new sheet by given worksheet name. -// When creating a new XLSX file, the default sheet will be created. -// Returns the number of sheets in the workbook (file) after appending the new -// sheet. +// When creating a new XLSX file, the default sheet will be created. Returns +// the number of sheets in the workbook (file) after appending the new sheet. func (f *File) NewSheet(name string) int { // Check if the worksheet already exists if f.GetSheetIndex(name) != 0 { @@ -35,7 +46,7 @@ func (f *File) NewSheet(name string) int { return f.SheetCount } -// contentTypesReader provides function to get the pointer to the +// contentTypesReader provides a function to get the pointer to the // [Content_Types].xml structure after deserialization. func (f *File) contentTypesReader() *xlsxTypes { if f.ContentTypes == nil { @@ -46,7 +57,7 @@ func (f *File) contentTypesReader() *xlsxTypes { return f.ContentTypes } -// contentTypesWriter provides function to save [Content_Types].xml after +// contentTypesWriter provides a function to save [Content_Types].xml after // serialize structure. func (f *File) contentTypesWriter() { if f.ContentTypes != nil { @@ -55,7 +66,7 @@ func (f *File) contentTypesWriter() { } } -// workbookReader provides function to get the pointer to the xl/workbook.xml +// workbookReader provides a function to get the pointer to the xl/workbook.xml // structure after deserialization. func (f *File) workbookReader() *xlsxWorkbook { if f.WorkBook == nil { @@ -66,7 +77,7 @@ func (f *File) workbookReader() *xlsxWorkbook { return f.WorkBook } -// workbookWriter provides function to save xl/workbook.xml after serialize +// workbookWriter provides a function to save xl/workbook.xml after serialize // structure. func (f *File) workbookWriter() { if f.WorkBook != nil { @@ -75,7 +86,7 @@ func (f *File) workbookWriter() { } } -// worksheetWriter provides 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() { for path, sheet := range f.Sheet { @@ -93,7 +104,7 @@ func (f *File) worksheetWriter() { } } -// trimCell provides function to trim blank cells which created by completeCol. +// trimCell provides a function to trim blank cells which created by completeCol. func trimCell(column []xlsxC) []xlsxC { col := make([]xlsxC, len(column)) i := 0 @@ -131,14 +142,22 @@ func (f *File) setSheet(index int, name string) { // allowed in sheet title. func (f *File) setWorkbook(name string, rid int) { content := f.workbookReader() + rID := 0 + for _, v := range content.Sheets.Sheet { + t, _ := strconv.Atoi(v.SheetID) + if t > rID { + rID = t + } + } + rID++ content.Sheets.Sheet = append(content.Sheets.Sheet, xlsxSheet{ Name: trimSheetName(name), - SheetID: strconv.Itoa(rid), + SheetID: strconv.Itoa(rID), ID: "rId" + strconv.Itoa(rid), }) } -// workbookRelsReader provides function to read and unmarshal workbook +// workbookRelsReader provides a function to read and unmarshal workbook // relationships of XLSX file. func (f *File) workbookRelsReader() *xlsxWorkbookRels { if f.WorkBookRels == nil { @@ -149,7 +168,7 @@ func (f *File) workbookRelsReader() *xlsxWorkbookRels { return f.WorkBookRels } -// workbookRelsWriter provides 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() { if f.WorkBookRels != nil { @@ -238,8 +257,8 @@ func (f *File) SetActiveSheet(index int) { } } -// GetActiveSheetIndex provides function to get active sheet index of the XLSX. If not -// found the active sheet will be return integer 0. +// GetActiveSheetIndex provides a function to get active sheet index of the +// XLSX. If not found the active sheet will be return integer 0. func (f *File) GetActiveSheetIndex() int { buffer := bytes.Buffer{} content := f.workbookReader() @@ -260,7 +279,7 @@ func (f *File) GetActiveSheetIndex() int { return 0 } -// SetSheetName provides function to set the worksheet name be given old and new +// SetSheetName provides a function to set the worksheet name be given old and new // worksheet name. Maximum 31 characters are allowed in sheet title and this // function only changes the name of the sheet and will not update the sheet // name in the formula or reference associated with the cell. So there may be @@ -278,7 +297,7 @@ func (f *File) SetSheetName(oldName, newName string) { } } -// GetSheetName provides function to get worksheet name of XLSX by given +// GetSheetName provides a function to get worksheet name of XLSX by given // worksheet index. If given sheet index is invalid, will return an empty // string. func (f *File) GetSheetName(index int) string { @@ -297,7 +316,7 @@ func (f *File) GetSheetName(index int) string { return "" } -// GetSheetIndex provides function to get worksheet index of XLSX by given sheet +// GetSheetIndex provides a function to get worksheet index of XLSX by given sheet // name. If given worksheet name is invalid, will return an integer type value // 0. func (f *File) GetSheetIndex(name string) int { @@ -316,7 +335,7 @@ func (f *File) GetSheetIndex(name string) int { return 0 } -// GetSheetMap provides function to get worksheet name and index map of XLSX. +// GetSheetMap provides a function to get worksheet name and index map of XLSX. // For example: // // xlsx, err := excelize.OpenFile("./Book1.xlsx") @@ -342,7 +361,7 @@ func (f *File) GetSheetMap() map[int]string { return sheetMap } -// getSheetMap provides function to get worksheet name and XML file path map of +// getSheetMap provides a function to get worksheet name and XML file path map of // XLSX. func (f *File) getSheetMap() map[string]string { maps := make(map[string]string) @@ -352,8 +371,8 @@ func (f *File) getSheetMap() map[string]string { return maps } -// SetSheetBackground provides function to set background picture by given -// worksheet name. +// SetSheetBackground provides a function to set background picture by given +// worksheet name and file path. func (f *File) SetSheetBackground(sheet, picture string) error { var err error // Check picture exists first. @@ -362,17 +381,18 @@ func (f *File) SetSheetBackground(sheet, picture string) error { } ext, ok := supportImageTypes[path.Ext(picture)] if !ok { - return errors.New("Unsupported image extension") + return errors.New("unsupported image extension") } pictureID := f.countMedia() + 1 rID := f.addSheetRelationships(sheet, SourceRelationshipImage, "../media/image"+strconv.Itoa(pictureID)+ext, "") f.addSheetPicture(sheet, rID) - f.addMedia(picture, ext) + file, _ := ioutil.ReadFile(picture) + f.addMedia(file, ext) f.setContentTypePartImageExtensions() return err } -// DeleteSheet provides function to delete worksheet in a workbook by given +// DeleteSheet provides a function to delete worksheet in a workbook by given // worksheet name. Use this method with caution, which will affect changes in // references such as formulas, charts, and so on. If there is any referenced // value of the deleted worksheet, it will cause a file error when you open it. @@ -396,7 +416,7 @@ func (f *File) DeleteSheet(name string) { f.SetActiveSheet(len(f.GetSheetMap())) } -// deleteSheetFromWorkbookRels provides function to remove worksheet +// deleteSheetFromWorkbookRels provides a function to remove worksheet // relationships by given relationships ID in the file // xl/_rels/workbook.xml.rels. func (f *File) deleteSheetFromWorkbookRels(rID string) string { @@ -410,7 +430,7 @@ func (f *File) deleteSheetFromWorkbookRels(rID string) string { return "" } -// deleteSheetFromContentTypes provides function to remove worksheet +// deleteSheetFromContentTypes provides a function to remove worksheet // relationships by given target name in the file [Content_Types].xml. func (f *File) deleteSheetFromContentTypes(target string) { content := f.contentTypesReader() @@ -421,7 +441,7 @@ func (f *File) deleteSheetFromContentTypes(target string) { } } -// CopySheet provides function to duplicate a worksheet by gave source and +// CopySheet provides a function to duplicate a worksheet by gave source and // target worksheet index. Note that currently doesn't support duplicate // workbooks that contain tables, charts or pictures. For Example: // @@ -432,20 +452,17 @@ func (f *File) deleteSheetFromContentTypes(target string) { // func (f *File) CopySheet(from, to int) error { if from < 1 || to < 1 || from == to || f.GetSheetName(from) == "" || f.GetSheetName(to) == "" { - return errors.New("Invalid worksheet index") + return errors.New("invalid worksheet index") } - return f.copySheet(from, to) + f.copySheet(from, to) + return nil } -// copySheet provides function to duplicate a worksheet by gave source and +// copySheet provides a function to duplicate a worksheet by gave source and // target worksheet name. -func (f *File) copySheet(from, to int) error { +func (f *File) copySheet(from, to int) { sheet := f.workSheetReader("sheet" + strconv.Itoa(from)) - worksheet := xlsxWorksheet{} - err := deepCopy(&worksheet, &sheet) - if err != nil { - return err - } + worksheet := deepcopy.Copy(sheet).(*xlsxWorksheet) path := "xl/worksheets/sheet" + strconv.Itoa(to) + ".xml" if len(worksheet.SheetViews.SheetView) > 0 { worksheet.SheetViews.SheetView[0].TabSelected = false @@ -453,17 +470,16 @@ func (f *File) copySheet(from, to int) error { worksheet.Drawing = nil worksheet.TableParts = nil worksheet.PageSetUp = nil - f.Sheet[path] = &worksheet + f.Sheet[path] = worksheet toRels := "xl/worksheets/_rels/sheet" + strconv.Itoa(to) + ".xml.rels" fromRels := "xl/worksheets/_rels/sheet" + strconv.Itoa(from) + ".xml.rels" _, ok := f.XLSX[fromRels] if ok { f.XLSX[toRels] = f.XLSX[fromRels] } - return err } -// SetSheetVisible provides function to set worksheet visible by given worksheet +// SetSheetVisible provides a function to set worksheet visible by given worksheet // name. A workbook must contain at least one visible worksheet. If the given // worksheet has been activated, this setting will be invalidated. Sheet state // values as defined by http://msdn.microsoft.com/en-us/library/office/documentformat.openxml.spreadsheet.sheetstatevalues.aspx @@ -505,14 +521,14 @@ func (f *File) SetSheetVisible(name string, visible bool) { } } -// parseFormatPanesSet provides function to parse the panes settings. +// parseFormatPanesSet provides a function to parse the panes settings. func parseFormatPanesSet(formatSet string) (*formatPanes, error) { format := formatPanes{} err := json.Unmarshal([]byte(formatSet), &format) return &format, err } -// SetPanes provides function to create and remove freeze panes and split panes +// SetPanes provides a function to create and remove freeze panes and split panes // by given worksheet name and panes format set. // // activePane defines the pane that is active. The possible values for this @@ -626,7 +642,7 @@ func (f *File) SetPanes(sheet, panes string) { xlsx.SheetViews.SheetView[len(xlsx.SheetViews.SheetView)-1].Selection = s } -// GetSheetVisible provides function to get worksheet visible by given worksheet +// GetSheetVisible provides a function to get worksheet visible by given worksheet // name. For example, get visible state of Sheet1: // // xlsx.GetSheetVisible("Sheet1") @@ -644,7 +660,7 @@ func (f *File) GetSheetVisible(name string) bool { return visible } -// trimSheetName provides function to trim invaild characters by given worksheet +// trimSheetName provides a function to trim invaild characters by given worksheet // name. func trimSheetName(name string) string { r := []rune{} |