summaryrefslogtreecommitdiff
path: root/sheet.go
diff options
context:
space:
mode:
Diffstat (limited to 'sheet.go')
-rw-r--r--sheet.go102
1 files changed, 59 insertions, 43 deletions
diff --git a/sheet.go b/sheet.go
index d087df4..2344218 100644
--- a/sheet.go
+++ b/sheet.go
@@ -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{}