Resolve #369,#370

add error return value

exported functions:

GetMergeCells
ProtectSheet
UnprotectSheet
UpdateLinkedValue
GetMergeCells
SetSheetVisible

inner functions:

workSheetReader
copySheet
This commit is contained in:
xuri 2019-04-15 11:22:57 +08:00
parent c423617e9d
commit f2df344739
No known key found for this signature in database
GPG Key ID: BA5E5BB1C948EDF7
21 changed files with 304 additions and 146 deletions

View File

@ -31,18 +31,20 @@ const (
// adjustDataValidations, adjustProtectedCells
//
func (f *File) adjustHelper(sheet string, dir adjustDirection, num, offset int) error {
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
if dir == rows {
f.adjustRowDimensions(xlsx, num, offset)
} else {
f.adjustColDimensions(xlsx, num, offset)
}
f.adjustHyperlinks(xlsx, sheet, dir, num, offset)
if err := f.adjustMergeCells(xlsx, dir, num, offset); err != nil {
if err = f.adjustMergeCells(xlsx, dir, num, offset); err != nil {
return err
}
if err := f.adjustAutoFilter(xlsx, dir, num, offset); err != nil {
if err = f.adjustAutoFilter(xlsx, dir, num, offset); err != nil {
return err
}

View File

@ -46,6 +46,7 @@ func TestAdjustAutoFilter(t *testing.T) {
func TestAdjustHelper(t *testing.T) {
f := NewFile()
f.NewSheet("Sheet2")
f.Sheet["xl/worksheets/sheet1.xml"] = &xlsxWorksheet{
MergeCells: &xlsxMergeCells{
Cells: []*xlsxMergeCell{
@ -61,6 +62,6 @@ func TestAdjustHelper(t *testing.T) {
},
}
// testing adjustHelper with illegal cell coordinates.
assert.EqualError(t, f.adjustHelper("sheet1", rows, 0, 0), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
assert.EqualError(t, f.adjustHelper("sheet2", rows, 0, 0), `cannot convert cell "B" to coordinates: invalid cell name "B"`)
assert.EqualError(t, f.adjustHelper("Sheet1", rows, 0, 0), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
assert.EqualError(t, f.adjustHelper("Sheet2", rows, 0, 0), `cannot convert cell "B" to coordinates: invalid cell name "B"`)
}

102
cell.go
View File

@ -69,63 +69,67 @@ func (f *File) GetCellValue(sheet, axis string) (string, error) {
// Note that default date format is m/d/yy h:mm of time.Time type value. You can
// set numbers format by SetCellStyle() method.
func (f *File) SetCellValue(sheet, axis string, value interface{}) error {
var err error
switch v := value.(type) {
case int:
f.SetCellInt(sheet, axis, v)
err = f.SetCellInt(sheet, axis, v)
case int8:
f.SetCellInt(sheet, axis, int(v))
err = f.SetCellInt(sheet, axis, int(v))
case int16:
f.SetCellInt(sheet, axis, int(v))
err = f.SetCellInt(sheet, axis, int(v))
case int32:
f.SetCellInt(sheet, axis, int(v))
err = f.SetCellInt(sheet, axis, int(v))
case int64:
f.SetCellInt(sheet, axis, int(v))
err = f.SetCellInt(sheet, axis, int(v))
case uint:
f.SetCellInt(sheet, axis, int(v))
err = f.SetCellInt(sheet, axis, int(v))
case uint8:
f.SetCellInt(sheet, axis, int(v))
err = f.SetCellInt(sheet, axis, int(v))
case uint16:
f.SetCellInt(sheet, axis, int(v))
err = f.SetCellInt(sheet, axis, int(v))
case uint32:
f.SetCellInt(sheet, axis, int(v))
err = f.SetCellInt(sheet, axis, int(v))
case uint64:
f.SetCellInt(sheet, axis, int(v))
err = f.SetCellInt(sheet, axis, int(v))
case float32:
f.SetCellFloat(sheet, axis, float64(v), -1, 32)
err = f.SetCellFloat(sheet, axis, float64(v), -1, 32)
case float64:
f.SetCellFloat(sheet, axis, v, -1, 64)
err = f.SetCellFloat(sheet, axis, v, -1, 64)
case string:
f.SetCellStr(sheet, axis, v)
err = f.SetCellStr(sheet, axis, v)
case []byte:
f.SetCellStr(sheet, axis, string(v))
err = f.SetCellStr(sheet, axis, string(v))
case time.Duration:
f.SetCellDefault(sheet, axis, strconv.FormatFloat(v.Seconds()/86400.0, 'f', -1, 32))
f.setDefaultTimeStyle(sheet, axis, 21)
err = f.SetCellDefault(sheet, axis, strconv.FormatFloat(v.Seconds()/86400.0, 'f', -1, 32))
err = f.setDefaultTimeStyle(sheet, axis, 21)
case time.Time:
excelTime, err := timeToExcelTime(v)
if err != nil {
return err
}
if excelTime > 0 {
f.SetCellDefault(sheet, axis, strconv.FormatFloat(excelTime, 'f', -1, 64))
f.setDefaultTimeStyle(sheet, axis, 22)
err = f.SetCellDefault(sheet, axis, strconv.FormatFloat(excelTime, 'f', -1, 64))
err = f.setDefaultTimeStyle(sheet, axis, 22)
} else {
f.SetCellStr(sheet, axis, v.Format(time.RFC3339Nano))
err = f.SetCellStr(sheet, axis, v.Format(time.RFC3339Nano))
}
case bool:
f.SetCellBool(sheet, axis, v)
err = f.SetCellBool(sheet, axis, v)
case nil:
f.SetCellStr(sheet, axis, "")
err = f.SetCellStr(sheet, axis, "")
default:
f.SetCellStr(sheet, axis, fmt.Sprintf("%v", value))
err = f.SetCellStr(sheet, axis, fmt.Sprintf("%v", value))
}
return nil
return err
}
// SetCellInt provides a function to set int type value of a cell by given
// worksheet name, cell coordinates and cell value.
func (f *File) SetCellInt(sheet, axis string, value int) error {
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
cellData, col, _, err := f.prepareCell(xlsx, sheet, axis)
if err != nil {
return err
@ -139,7 +143,10 @@ func (f *File) SetCellInt(sheet, axis string, value int) error {
// SetCellBool provides a function to set bool type value of a cell by given
// worksheet name, cell name and cell value.
func (f *File) SetCellBool(sheet, axis string, value bool) error {
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
cellData, col, _, err := f.prepareCell(xlsx, sheet, axis)
if err != nil {
return err
@ -164,7 +171,10 @@ func (f *File) SetCellBool(sheet, axis string, value bool) error {
// f.SetCellFloat("Sheet1", "A1", float64(x), 2, 32)
//
func (f *File) SetCellFloat(sheet, axis string, value float64, prec, bitSize int) error {
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
cellData, col, _, err := f.prepareCell(xlsx, sheet, axis)
if err != nil {
return err
@ -178,7 +188,10 @@ func (f *File) SetCellFloat(sheet, axis string, value float64, prec, bitSize int
// SetCellStr provides a function to set string type value of a cell. Total
// number of characters that a cell can contain 32767 characters.
func (f *File) SetCellStr(sheet, axis, value string) error {
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
cellData, col, _, err := f.prepareCell(xlsx, sheet, axis)
if err != nil {
return err
@ -203,7 +216,10 @@ func (f *File) SetCellStr(sheet, axis, value string) error {
// SetCellDefault provides a function to set string type value of a cell as
// default format without escaping the cell.
func (f *File) SetCellDefault(sheet, axis, value string) error {
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
cellData, col, _, err := f.prepareCell(xlsx, sheet, axis)
if err != nil {
return err
@ -231,7 +247,10 @@ func (f *File) GetCellFormula(sheet, axis string) (string, error) {
// SetCellFormula provides a function to set cell formula by given string and
// worksheet name.
func (f *File) SetCellFormula(sheet, axis, formula string) error {
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
cellData, _, _, err := f.prepareCell(xlsx, sheet, axis)
if err != nil {
return err
@ -264,8 +283,11 @@ func (f *File) GetCellHyperLink(sheet, axis string) (bool, string, error) {
return false, "", err
}
xlsx := f.workSheetReader(sheet)
axis, err := f.mergeCellsParser(xlsx, axis)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return false, "", err
}
axis, err = f.mergeCellsParser(xlsx, axis)
if err != nil {
return false, "", err
}
@ -302,8 +324,11 @@ func (f *File) SetCellHyperLink(sheet, axis, link, linkType string) error {
return err
}
xlsx := f.workSheetReader(sheet)
axis, err := f.mergeCellsParser(xlsx, axis)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
axis, err = f.mergeCellsParser(xlsx, axis)
if err != nil {
return err
}
@ -367,7 +392,10 @@ func (f *File) MergeCell(sheet, hcell, vcell string) error {
hcell, _ = CoordinatesToCellName(hcol, hrow)
vcell, _ = CoordinatesToCellName(vcol, vrow)
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
if xlsx.MergeCells != nil {
ref := hcell + ":" + vcell
cells := make([]*xlsxMergeCell, 0, len(xlsx.MergeCells.Cells))
@ -446,8 +474,10 @@ func (f *File) prepareCell(xlsx *xlsxWorksheet, sheet, cell string) (*xlsxC, int
// getCellStringFunc does common value extraction workflow for all GetCell*
// methods. Passed function implements specific part of required logic.
func (f *File) getCellStringFunc(sheet, axis string, fn func(x *xlsxWorksheet, c *xlsxC) (string, bool, error)) (string, error) {
xlsx := f.workSheetReader(sheet)
var err error
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return "", err
}
axis, err = f.mergeCellsParser(xlsx, axis)
if err != nil {
return "", err

View File

@ -449,7 +449,10 @@ func (f *File) AddChart(sheet, cell, format string) error {
return err
}
// Read sheet data.
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
// Add first picture for given sheet, create xl/drawings/ and xl/drawings/_rels/ folder.
drawingID := f.countDrawings() + 1
chartID := f.countCharts() + 1

37
col.go
View File

@ -31,7 +31,10 @@ func (f *File) GetColVisible(sheet, col string) (bool, error) {
return visible, err
}
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return false, err
}
if xlsx.Cols == nil {
return visible, err
}
@ -61,7 +64,10 @@ func (f *File) SetColVisible(sheet, col string, visible bool) error {
Hidden: !visible,
CustomWidth: true,
}
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
if xlsx.Cols == nil {
cols := xlsxCols{}
cols.Col = append(cols.Col, colData)
@ -93,7 +99,10 @@ func (f *File) GetColOutlineLevel(sheet, col string) (uint8, error) {
if err != nil {
return level, err
}
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return 0, err
}
if xlsx.Cols == nil {
return level, err
}
@ -123,7 +132,10 @@ func (f *File) SetColOutlineLevel(sheet, col string, level uint8) error {
OutlineLevel: level,
CustomWidth: true,
}
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
if xlsx.Cols == nil {
cols := xlsxCols{}
cols.Col = append(cols.Col, colData)
@ -162,7 +174,10 @@ func (f *File) SetColWidth(sheet, startcol, endcol string, width float64) error
min, max = max, min
}
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
col := xlsxCol{
Min: min,
Max: max,
@ -288,7 +303,7 @@ func (f *File) positionObjectPixels(sheet string, col, row, x1, y1, width, heigh
// getColWidth provides a function to get column width in pixels by given
// sheet name and column index.
func (f *File) getColWidth(sheet string, col int) int {
xlsx := f.workSheetReader(sheet)
xlsx, _ := f.workSheetReader(sheet)
if xlsx.Cols != nil {
var width float64
for _, v := range xlsx.Cols.Col {
@ -311,7 +326,10 @@ func (f *File) GetColWidth(sheet, col string) (float64, error) {
if err != nil {
return defaultColWidthPixels, err
}
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return defaultColWidthPixels, err
}
if xlsx.Cols != nil {
var width float64
for _, v := range xlsx.Cols.Col {
@ -355,7 +373,10 @@ func (f *File) RemoveCol(sheet, col string) error {
return err
}
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
for rowIdx := range xlsx.SheetData.Row {
rowData := &xlsx.SheetData.Row[rowIdx]
for colIdx := range rowData.C {

View File

@ -80,7 +80,10 @@ func (f *File) AddComment(sheet, cell, format string) error {
return err
}
// Read sheet data.
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
commentID := f.countComments() + 1
drawingVML := "xl/drawings/vmlDrawing" + strconv.Itoa(commentID) + ".vml"
sheetRelationshipsComments := "../comments" + strconv.Itoa(commentID) + ".xml"

View File

@ -208,7 +208,7 @@ func convDataValidationOperatior(o DataValidationOperator) string {
// dvRange.Sqref = "A1:B2"
// dvRange.SetRange(10, 20, excelize.DataValidationTypeWhole, excelize.DataValidationOperatorBetween)
// dvRange.SetError(excelize.DataValidationErrorStyleStop, "error title", "error body")
// xlsx.AddDataValidation("Sheet1", dvRange)
// err := xlsx.AddDataValidation("Sheet1", dvRange)
//
// Example 2, set data validation on Sheet1!A3:B4 with validation criteria
// settings, and show input message when cell is selected:
@ -217,7 +217,7 @@ func convDataValidationOperatior(o DataValidationOperator) string {
// dvRange.Sqref = "A3:B4"
// dvRange.SetRange(10, 20, excelize.DataValidationTypeWhole, excelize.DataValidationOperatorGreaterThan)
// dvRange.SetInput("input title", "input body")
// xlsx.AddDataValidation("Sheet1", dvRange)
// err = xlsx.AddDataValidation("Sheet1", dvRange)
//
// Example 3, set data validation on Sheet1!A5:B6 with validation criteria
// settings, create in-cell dropdown by allowing list source:
@ -225,13 +225,17 @@ func convDataValidationOperatior(o DataValidationOperator) string {
// dvRange = excelize.NewDataValidation(true)
// dvRange.Sqref = "A5:B6"
// dvRange.SetDropList([]string{"1", "2", "3"})
// xlsx.AddDataValidation("Sheet1", dvRange)
// err = xlsx.AddDataValidation("Sheet1", dvRange)
//
func (f *File) AddDataValidation(sheet string, dv *DataValidation) {
xlsx := f.workSheetReader(sheet)
func (f *File) AddDataValidation(sheet string, dv *DataValidation) error {
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
if nil == xlsx.DataValidations {
xlsx.DataValidations = new(xlsxDataValidations)
}
xlsx.DataValidations.DataValidation = append(xlsx.DataValidations.DataValidation, dv)
xlsx.DataValidations.Count = len(xlsx.DataValidations.DataValidation)
return err
}

View File

@ -14,6 +14,7 @@ import (
"archive/zip"
"bytes"
"encoding/xml"
"fmt"
"io"
"io/ioutil"
"os"
@ -112,10 +113,10 @@ func (f *File) setDefaultTimeStyle(sheet, axis string, format int) error {
// workSheetReader provides a function to get the pointer to the structure
// after deserialization by given worksheet name.
func (f *File) workSheetReader(sheet string) *xlsxWorksheet {
func (f *File) workSheetReader(sheet string) (*xlsxWorksheet, error) {
name, ok := f.sheetMap[trimSheetName(sheet)]
if !ok {
name = "xl/worksheets/" + strings.ToLower(sheet) + ".xml"
return nil, fmt.Errorf("Sheet %s is not exist", sheet)
}
if f.Sheet[name] == nil {
var xlsx xlsxWorksheet
@ -131,7 +132,7 @@ func (f *File) workSheetReader(sheet string) *xlsxWorksheet {
}
f.Sheet[name] = &xlsx
}
return f.Sheet[name]
return f.Sheet[name], nil
}
// checkSheet provides a function to fill each row element and make that is
@ -197,9 +198,12 @@ func replaceWorkSheetsRelationshipsNameSpaceBytes(workbookMarshal []byte) []byte
// </c>
// </row>
//
func (f *File) UpdateLinkedValue() {
func (f *File) UpdateLinkedValue() error {
for _, name := range f.GetSheetMap() {
xlsx := f.workSheetReader(name)
xlsx, err := f.workSheetReader(name)
if err != nil {
return err
}
for indexR := range xlsx.SheetData.Row {
for indexC, col := range xlsx.SheetData.Row[indexR].C {
if col.F != nil && col.V != "" {
@ -209,14 +213,16 @@ func (f *File) UpdateLinkedValue() {
}
}
}
return nil
}
// GetMergeCells provides a function to get all merged cells from a worksheet currently.
func (f *File) GetMergeCells(sheet string) []MergeCell {
xlsx := f.workSheetReader(sheet)
func (f *File) GetMergeCells(sheet string) ([]MergeCell, error) {
var mergeCells []MergeCell
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return mergeCells, err
}
if xlsx.MergeCells != nil {
mergeCells = make([]MergeCell, 0, len(xlsx.MergeCells.Cells))
@ -228,7 +234,7 @@ func (f *File) GetMergeCells(sheet string) []MergeCell {
}
}
return mergeCells
return mergeCells, err
}
// MergeCell define a merged cell data.

View File

@ -57,10 +57,10 @@ func TestOpenFile(t *testing.T) {
xlsx.SetSheetName("Maximum 31 characters allowed i", "[Rename]:\\/?* Maximum 31 characters allowed in sheet title.")
xlsx.SetCellInt("Sheet3", "A23", 10)
xlsx.SetCellStr("Sheet3", "b230", "10")
xlsx.SetCellStr("Sheet10", "b230", "10")
assert.EqualError(t, xlsx.SetCellStr("Sheet10", "b230", "10"), "Sheet Sheet10 is not exist")
// Test set cell string value with illegal row number.
assert.EqualError(t, xlsx.SetCellStr("Sheet10", "A", "10"), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
assert.EqualError(t, xlsx.SetCellStr("Sheet1", "A", "10"), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
xlsx.SetActiveSheet(2)
// Test get cell formula with given rows number.
@ -298,7 +298,7 @@ func TestGetCellHyperLink(t *testing.T) {
assert.NoError(t, err)
t.Log(link, target)
link, target, err = xlsx.GetCellHyperLink("Sheet3", "H3")
assert.NoError(t, err)
assert.EqualError(t, err, "Sheet Sheet3 is not exist")
t.Log(link, target)
}
@ -417,7 +417,7 @@ func TestGetMergeCells(t *testing.T) {
}
sheet1 := xlsx.GetSheetName(1)
mergeCells := xlsx.GetMergeCells(sheet1)
mergeCells, err := xlsx.GetMergeCells(sheet1)
if !assert.Len(t, mergeCells, len(wants)) {
t.FailNow()
}
@ -784,7 +784,8 @@ func TestColumnVisibility(t *testing.T) {
assert.EqualError(t, err, `invalid column name "*"`)
assert.EqualError(t, xlsx.SetColVisible("Sheet1", "*", false), `invalid column name "*"`)
assert.NoError(t, xlsx.SetColVisible("Sheet3", "E", false))
err = xlsx.SetColVisible("Sheet3", "E", false)
assert.EqualError(t, err, "Sheet Sheet3 is not exist")
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestColumnVisibility.xlsx")))
})
@ -804,10 +805,7 @@ func TestCopySheet(t *testing.T) {
}
idx := xlsx.NewSheet("CopySheet")
err = xlsx.CopySheet(1, idx)
if !assert.NoError(t, err) {
t.FailNow()
}
assert.EqualError(t, xlsx.CopySheet(1, idx), "Sheet sheet1 is not exist")
xlsx.SetCellValue("Sheet4", "F1", "Hello")
val, err := xlsx.GetCellValue("Sheet1", "F1")
@ -923,9 +921,8 @@ func TestAutoFilter(t *testing.T) {
for i, format := range formats {
t.Run(fmt.Sprintf("Expression%d", i+1), func(t *testing.T) {
err = xlsx.AutoFilter("Sheet3", "D4", "B1", format)
if assert.NoError(t, err) {
assert.EqualError(t, err, "Sheet Sheet3 is not exist")
assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, i+1)))
}
})
}

View File

@ -50,7 +50,7 @@ func NewFile() *File {
f.WorkBook = f.workbookReader()
f.WorkBookRels = f.workbookRelsReader()
f.WorkSheetRels = make(map[string]*xlsxWorkbookRels)
f.Sheet["xl/worksheets/sheet1.xml"] = f.workSheetReader("Sheet1")
f.Sheet["xl/worksheets/sheet1.xml"], _ = f.workSheetReader("Sheet1")
f.sheetMap["Sheet1"] = "xl/worksheets/sheet1.xml"
f.Theme = f.themeReader()
return f

View File

@ -132,7 +132,6 @@ func (f *File) AddPicture(sheet, cell, picture, format string) error {
// }
//
func (f *File) AddPictureFromBytes(sheet, cell, format, name, extension string, file []byte) error {
var err error
var drawingHyperlinkRID int
var hyperlinkType string
ext, ok := supportImageTypes[extension]
@ -148,7 +147,10 @@ func (f *File) AddPictureFromBytes(sheet, cell, format, name, extension string,
return err
}
// Read sheet data.
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
// Add first picture for given sheet, create xl/drawings/ and xl/drawings/_rels/ folder.
drawingID := f.countDrawings() + 1
drawingXML := "xl/drawings/drawing" + strconv.Itoa(drawingID) + ".xml"
@ -225,7 +227,7 @@ func (f *File) deleteSheetRelationships(sheet, rID string) {
// addSheetLegacyDrawing provides a function to add legacy drawing element to
// xl/worksheets/sheet%d.xml by given worksheet name and relationship index.
func (f *File) addSheetLegacyDrawing(sheet string, rID int) {
xlsx := f.workSheetReader(sheet)
xlsx, _ := f.workSheetReader(sheet)
xlsx.LegacyDrawing = &xlsxLegacyDrawing{
RID: "rId" + strconv.Itoa(rID),
}
@ -234,7 +236,7 @@ func (f *File) addSheetLegacyDrawing(sheet string, rID int) {
// addSheetDrawing provides a function to add drawing element to
// xl/worksheets/sheet%d.xml by given worksheet name and relationship index.
func (f *File) addSheetDrawing(sheet string, rID int) {
xlsx := f.workSheetReader(sheet)
xlsx, _ := f.workSheetReader(sheet)
xlsx.Drawing = &xlsxDrawing{
RID: "rId" + strconv.Itoa(rID),
}
@ -243,7 +245,7 @@ func (f *File) addSheetDrawing(sheet string, rID int) {
// addSheetPicture provides a function to add picture element to
// xl/worksheets/sheet%d.xml by given worksheet name and relationship index.
func (f *File) addSheetPicture(sheet string, rID int) {
xlsx := f.workSheetReader(sheet)
xlsx, _ := f.workSheetReader(sheet)
xlsx.Picture = &xlsxPicture{
RID: "rId" + strconv.Itoa(rID),
}
@ -500,7 +502,10 @@ func (f *File) GetPicture(sheet, cell string) (string, []byte, error) {
}
col--
row--
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return "", []byte{}, err
}
if xlsx.Drawing == nil {
return "", []byte{}, err
}

View File

@ -102,7 +102,7 @@ func TestGetPicture(t *testing.T) {
// Try to get picture from a worksheet that doesn't contain any images.
file, raw, err = xlsx.GetPicture("Sheet3", "I9")
assert.NoError(t, err)
assert.EqualError(t, err, "Sheet Sheet3 is not exist")
assert.Empty(t, file)
assert.Empty(t, raw)

52
rows.go
View File

@ -35,7 +35,10 @@ func (f *File) GetRows(sheet string) ([][]string, error) {
return nil, nil
}
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return nil, err
}
if xlsx != nil {
output, _ := xml.Marshal(f.Sheet[name])
f.saveFileList(name, replaceWorkSheetsRelationshipsNameSpaceBytes(output))
@ -165,7 +168,10 @@ func (err ErrSheetNotExist) Error() string {
// }
//
func (f *File) Rows(sheet string) (*Rows, error) {
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return nil, err
}
name, ok := f.sheetMap[trimSheetName(sheet)]
if !ok {
return nil, ErrSheetNotExist{sheet}
@ -225,7 +231,10 @@ func (f *File) SetRowHeight(sheet string, row int, height float64) error {
return newInvalidRowNumberError(row)
}
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
prepareSheetXML(xlsx, 0, row)
@ -238,7 +247,7 @@ func (f *File) SetRowHeight(sheet string, row int, height float64) error {
// getRowHeight provides a function to get row height in pixels by given sheet
// name and row index.
func (f *File) getRowHeight(sheet string, row int) int {
xlsx := f.workSheetReader(sheet)
xlsx, _ := f.workSheetReader(sheet)
for _, v := range xlsx.SheetData.Row {
if v.R == row+1 && v.Ht != 0 {
return int(convertRowHeightToPixels(v.Ht))
@ -258,7 +267,10 @@ func (f *File) GetRowHeight(sheet string, row int) (float64, error) {
return defaultRowHeightPixels, newInvalidRowNumberError(row)
}
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return defaultRowHeightPixels, err
}
if row > len(xlsx.SheetData.Row) {
return defaultRowHeightPixels, nil // it will be better to use 0, but we take care with BC
}
@ -321,7 +333,10 @@ func (f *File) SetRowVisible(sheet string, row int, visible bool) error {
return newInvalidRowNumberError(row)
}
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
prepareSheetXML(xlsx, 0, row)
xlsx.SheetData.Row[row-1].Hidden = !visible
return nil
@ -338,7 +353,10 @@ func (f *File) GetRowVisible(sheet string, row int) (bool, error) {
return false, newInvalidRowNumberError(row)
}
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return false, err
}
if row > len(xlsx.SheetData.Row) {
return false, nil
}
@ -355,7 +373,10 @@ func (f *File) SetRowOutlineLevel(sheet string, row int, level uint8) error {
if row < 1 {
return newInvalidRowNumberError(row)
}
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
prepareSheetXML(xlsx, 0, row)
xlsx.SheetData.Row[row-1].OutlineLevel = level
return nil
@ -371,7 +392,10 @@ func (f *File) GetRowOutlineLevel(sheet string, row int) (uint8, error) {
if row < 1 {
return 0, newInvalidRowNumberError(row)
}
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return 0, err
}
if row > len(xlsx.SheetData.Row) {
return 0, nil
}
@ -392,7 +416,10 @@ func (f *File) RemoveRow(sheet string, row int) error {
return newInvalidRowNumberError(row)
}
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
if row > len(xlsx.SheetData.Row) {
return nil
}
@ -445,7 +472,10 @@ func (f *File) DuplicateRowTo(sheet string, row, row2 int) error {
return newInvalidRowNumberError(row)
}
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
if row > len(xlsx.SheetData.Row) || row2 < 1 || row == row2 {
return nil
}

View File

@ -96,8 +96,8 @@ func TestRowVisibility(t *testing.T) {
t.FailNow()
}
assert.NoError(t, xlsx.SetRowVisible("Sheet3", 2, false))
assert.NoError(t, xlsx.SetRowVisible("Sheet3", 2, true))
assert.EqualError(t, xlsx.SetRowVisible("Sheet3", 2, false), "Sheet Sheet3 is not exist")
assert.EqualError(t, xlsx.SetRowVisible("Sheet3", 2, true), "Sheet Sheet3 is not exist")
xlsx.GetRowVisible("Sheet3", 2)
xlsx.GetRowVisible("Sheet3", 25)
assert.EqualError(t, xlsx.SetRowVisible("Sheet3", 0, true), "invalid row number 0")
@ -112,8 +112,8 @@ func TestRowVisibility(t *testing.T) {
func TestRemoveRow(t *testing.T) {
xlsx := NewFile()
sheet1 := xlsx.GetSheetName(1)
r := xlsx.workSheetReader(sheet1)
r, err := xlsx.workSheetReader(sheet1)
assert.NoError(t, err)
const (
colCount = 10
rowCount = 10
@ -143,7 +143,7 @@ func TestRemoveRow(t *testing.T) {
t.FailNow()
}
err := xlsx.AutoFilter(sheet1, "A2", "A2", `{"column":"A","expression":"x != blanks"}`)
err = xlsx.AutoFilter(sheet1, "A2", "A2", `{"column":"A","expression":"x != blanks"}`)
if !assert.NoError(t, err) {
t.FailNow()
}
@ -170,8 +170,8 @@ func TestRemoveRow(t *testing.T) {
func TestInsertRow(t *testing.T) {
xlsx := NewFile()
sheet1 := xlsx.GetSheetName(1)
r := xlsx.workSheetReader(sheet1)
r, err := xlsx.workSheetReader(sheet1)
assert.NoError(t, err)
const (
colCount = 10
rowCount = 10
@ -202,7 +202,8 @@ func TestInsertRow(t *testing.T) {
func TestInsertRowInEmptyFile(t *testing.T) {
xlsx := NewFile()
sheet1 := xlsx.GetSheetName(1)
r := xlsx.workSheetReader(sheet1)
r, err := xlsx.workSheetReader(sheet1)
assert.NoError(t, err)
assert.NoError(t, xlsx.InsertRow(sheet1, 1))
assert.Len(t, r.SheetData.Row, 0)
assert.NoError(t, xlsx.InsertRow(sheet1, 2))

View File

@ -259,7 +259,10 @@ func (f *File) AddShape(sheet, cell, format string) error {
return err
}
// Read sheet data.
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
// Add first shape for given sheet, create xl/drawings/ and xl/drawings/_rels/ folder.
drawingID := f.countDrawings() + 1
drawingXML := "xl/drawings/drawing" + strconv.Itoa(drawingID) + ".xml"

View File

@ -245,7 +245,7 @@ func (f *File) SetActiveSheet(index int) {
}
}
for idx, name := range f.GetSheetMap() {
xlsx := f.workSheetReader(name)
xlsx, _ := f.workSheetReader(name)
if len(xlsx.SheetViews.SheetView) > 0 {
xlsx.SheetViews.SheetView[0].TabSelected = false
}
@ -265,7 +265,7 @@ func (f *File) SetActiveSheet(index int) {
// XLSX. If not found the active sheet will be return integer 0.
func (f *File) GetActiveSheetIndex() int {
for idx, name := range f.GetSheetMap() {
xlsx := f.workSheetReader(name)
xlsx, _ := f.workSheetReader(name)
for _, sheetView := range xlsx.SheetViews.SheetView {
if sheetView.TabSelected {
return idx
@ -380,11 +380,10 @@ func (f *File) SetSheetBackground(sheet, picture string) error {
if !ok {
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)
file, _ := ioutil.ReadFile(picture)
f.addMedia(file, ext)
name := f.addMedia(file, ext)
rID := f.addSheetRelationships(sheet, SourceRelationshipImage, strings.Replace(name, "xl", "..", 1), "")
f.addSheetPicture(sheet, rID)
f.setContentTypePartImageExtensions()
return err
}
@ -452,14 +451,16 @@ 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")
}
f.copySheet(from, to)
return nil
return f.copySheet(from, to)
}
// copySheet provides a function to duplicate a worksheet by gave source and
// target worksheet name.
func (f *File) copySheet(from, to int) {
sheet := f.workSheetReader("sheet" + strconv.Itoa(from))
func (f *File) copySheet(from, to int) error {
sheet, err := f.workSheetReader("sheet" + strconv.Itoa(from))
if err != nil {
return err
}
worksheet := deepcopy.Copy(sheet).(*xlsxWorksheet)
path := "xl/worksheets/sheet" + strconv.Itoa(to) + ".xml"
if len(worksheet.SheetViews.SheetView) > 0 {
@ -475,6 +476,7 @@ func (f *File) copySheet(from, to int) {
if ok {
f.XLSX[toRels] = f.XLSX[fromRels]
}
return err
}
// SetSheetVisible provides a function to set worksheet visible by given worksheet
@ -488,9 +490,9 @@ func (f *File) copySheet(from, to int) {
//
// For example, hide Sheet1:
//
// xlsx.SetSheetVisible("Sheet1", false)
// err := xlsx.SetSheetVisible("Sheet1", false)
//
func (f *File) SetSheetVisible(name string, visible bool) {
func (f *File) SetSheetVisible(name string, visible bool) error {
name = trimSheetName(name)
content := f.workbookReader()
if visible {
@ -499,7 +501,7 @@ func (f *File) SetSheetVisible(name string, visible bool) {
content.Sheets.Sheet[k].State = ""
}
}
return
return nil
}
count := 0
for _, v := range content.Sheets.Sheet {
@ -508,7 +510,10 @@ func (f *File) SetSheetVisible(name string, visible bool) {
}
}
for k, v := range content.Sheets.Sheet {
xlsx := f.workSheetReader(f.GetSheetMap()[k])
xlsx, err := f.workSheetReader(f.GetSheetMap()[k])
if err != nil {
return err
}
tabSelected := false
if len(xlsx.SheetViews.SheetView) > 0 {
tabSelected = xlsx.SheetViews.SheetView[0].TabSelected
@ -517,6 +522,7 @@ func (f *File) SetSheetVisible(name string, visible bool) {
content.Sheets.Sheet[k].State = "hidden"
}
}
return nil
}
// parseFormatPanesSet provides a function to parse the panes settings.
@ -611,9 +617,12 @@ func parseFormatPanesSet(formatSet string) (*formatPanes, error) {
//
// xlsx.SetPanes("Sheet1", `{"freeze":false,"split":false}`)
//
func (f *File) SetPanes(sheet, panes string) {
func (f *File) SetPanes(sheet, panes string) error {
fs, _ := parseFormatPanesSet(panes)
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
p := &xlsxPane{
ActivePane: fs.ActivePane,
TopLeftCell: fs.TopLeftCell,
@ -638,6 +647,7 @@ func (f *File) SetPanes(sheet, panes string) {
})
}
xlsx.SheetViews.SheetView[len(xlsx.SheetViews.SheetView)-1].Selection = s
return err
}
// GetSheetVisible provides a function to get worksheet visible by given worksheet
@ -678,10 +688,16 @@ func (f *File) SearchSheet(sheet, value string, reg ...bool) ([]string, error) {
for _, r := range reg {
regSearch = r
}
xlsx := f.workSheetReader(sheet)
var (
result []string
)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return result, err
}
name, ok := f.sheetMap[trimSheetName(sheet)]
if !ok {
return result, nil
@ -740,13 +756,16 @@ func (f *File) SearchSheet(sheet, value string, reg ...bool) ([]string, error) {
// or deliberately changing, moving, or deleting data in a worksheet. For
// example, protect Sheet1 with protection settings:
//
// xlsx.ProtectSheet("Sheet1", &excelize.FormatSheetProtection{
// err := xlsx.ProtectSheet("Sheet1", &excelize.FormatSheetProtection{
// Password: "password",
// EditScenarios: false,
// })
//
func (f *File) ProtectSheet(sheet string, settings *FormatSheetProtection) {
xlsx := f.workSheetReader(sheet)
func (f *File) ProtectSheet(sheet string, settings *FormatSheetProtection) error {
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
if settings == nil {
settings = &FormatSheetProtection{
EditObjects: true,
@ -775,12 +794,17 @@ func (f *File) ProtectSheet(sheet string, settings *FormatSheetProtection) {
if settings.Password != "" {
xlsx.SheetProtection.Password = genSheetPasswd(settings.Password)
}
return err
}
// UnprotectSheet provides a function to unprotect an Excel worksheet.
func (f *File) UnprotectSheet(sheet string) {
xlsx := f.workSheetReader(sheet)
func (f *File) UnprotectSheet(sheet string) error {
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
xlsx.SheetProtection = nil
return err
}
// trimSheetName provides a function to trim invaild characters by given worksheet
@ -989,7 +1013,10 @@ func (p *PageLayoutPaperSize) getPageLayout(ps *xlsxPageSetUp) {
// 118 | PRC Envelope #10 Rotated (458 mm x 324 mm)
//
func (f *File) SetPageLayout(sheet string, opts ...PageLayoutOption) error {
s := f.workSheetReader(sheet)
s, err := f.workSheetReader(sheet)
if err != nil {
return err
}
ps := s.PageSetUp
if ps == nil {
ps = new(xlsxPageSetUp)
@ -999,7 +1026,7 @@ func (f *File) SetPageLayout(sheet string, opts ...PageLayoutOption) error {
for _, opt := range opts {
opt.setPageLayout(ps)
}
return nil
return err
}
// GetPageLayout provides a function to gets worksheet page layout.
@ -1008,13 +1035,16 @@ func (f *File) SetPageLayout(sheet string, opts ...PageLayoutOption) error {
// PageLayoutOrientation(string)
// PageLayoutPaperSize(int)
func (f *File) GetPageLayout(sheet string, opts ...PageLayoutOptionPtr) error {
s := f.workSheetReader(sheet)
s, err := f.workSheetReader(sheet)
if err != nil {
return err
}
ps := s.PageSetUp
for _, opt := range opts {
opt.getPageLayout(ps)
}
return nil
return err
}
// workSheetRelsReader provides a function to get the pointer to the structure

View File

@ -154,7 +154,10 @@ func (o *AutoPageBreaks) getSheetPrOption(pr *xlsxSheetPr) {
// AutoPageBreaks(bool)
// OutlineSummaryBelow(bool)
func (f *File) SetSheetPrOptions(name string, opts ...SheetPrOption) error {
sheet := f.workSheetReader(name)
sheet, err := f.workSheetReader(name)
if err != nil {
return err
}
pr := sheet.SheetPr
if pr == nil {
pr = new(xlsxSheetPr)
@ -164,7 +167,7 @@ func (f *File) SetSheetPrOptions(name string, opts ...SheetPrOption) error {
for _, opt := range opts {
opt.setSheetPrOption(pr)
}
return nil
return err
}
// GetSheetPrOptions provides a function to gets worksheet properties.
@ -177,11 +180,14 @@ func (f *File) SetSheetPrOptions(name string, opts ...SheetPrOption) error {
// AutoPageBreaks(bool)
// OutlineSummaryBelow(bool)
func (f *File) GetSheetPrOptions(name string, opts ...SheetPrOptionPtr) error {
sheet := f.workSheetReader(name)
sheet, err := f.workSheetReader(name)
if err != nil {
return err
}
pr := sheet.SheetPr
for _, opt := range opts {
opt.getSheetPrOption(pr)
}
return nil
return err
}

View File

@ -110,7 +110,10 @@ func (o *ZoomScale) getSheetViewOption(view *xlsxSheetView) {
// getSheetView returns the SheetView object
func (f *File) getSheetView(sheetName string, viewIndex int) (*xlsxSheetView, error) {
xlsx := f.workSheetReader(sheetName)
xlsx, err := f.workSheetReader(sheetName)
if err != nil {
return nil, err
}
if viewIndex < 0 {
if viewIndex < -len(xlsx.SheetViews.SheetView) {
return nil, fmt.Errorf("view index %d out of range", viewIndex)
@ -120,7 +123,7 @@ func (f *File) getSheetView(sheetName string, viewIndex int) (*xlsxSheetView, er
return nil, fmt.Errorf("view index %d out of range", viewIndex)
}
return &(xlsx.SheetViews.SheetView[viewIndex]), nil
return &(xlsx.SheetViews.SheetView[viewIndex]), err
}
// SetSheetViewOptions sets sheet view options.

View File

@ -2266,7 +2266,10 @@ func setCellXfs(style *xlsxStyleSheet, fontID, numFmtID, fillID, borderID int, a
// GetCellStyle provides a function to get cell style index by given worksheet
// name and cell coordinates.
func (f *File) GetCellStyle(sheet, axis string) (int, error) {
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return 0, err
}
cellData, col, _, err := f.prepareCell(xlsx, sheet, axis)
if err != nil {
return 0, err
@ -2365,7 +2368,10 @@ func (f *File) SetCellStyle(sheet, hcell, vcell string, styleID int) error {
vcolIdx := vcol - 1
vrowIdx := vrow - 1
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
prepareSheetXML(xlsx, vcol, vrow)
for r := hrowIdx; r <= vrowIdx; r++ {
@ -2373,7 +2379,7 @@ func (f *File) SetCellStyle(sheet, hcell, vcell string, styleID int) error {
xlsx.SheetData.Row[r].C[k].S = styleID
}
}
return nil
return err
}
// SetConditionalFormat provides a function to create conditional formatting
@ -2605,7 +2611,10 @@ func (f *File) SetConditionalFormat(sheet, area, formatSet string) error {
"expression": drawConfFmtExp,
}
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
cfRule := []*xlsxCfRule{}
for p, v := range format {
var vt, ct string

View File

@ -158,7 +158,8 @@ func TestSetConditionalFormat(t *testing.T) {
t.Fatalf("%s", err)
}
xlsx := xl.workSheetReader(sheet)
xlsx, err := xl.workSheetReader(sheet)
assert.NoError(t, err)
cf := xlsx.ConditionalFormatting
assert.Len(t, cf, 1, testCase.label)
assert.Len(t, cf[0].CfRule, 1, testCase.label)

View File

@ -102,7 +102,7 @@ func (f *File) countTables() int {
// addSheetTable provides a function to add tablePart element to
// xl/worksheets/sheet%d.xml by given worksheet name and relationship index.
func (f *File) addSheetTable(sheet string, rID int) {
xlsx := f.workSheetReader(sheet)
xlsx, _ := f.workSheetReader(sheet)
table := &xlsxTablePart{
RID: "rId" + strconv.Itoa(rID),
}
@ -299,7 +299,10 @@ func (f *File) AutoFilter(sheet, hcell, vcell, format string) error {
// autoFilter provides a function to extract the tokens from the filter
// expression. The tokens are mainly non-whitespace groups.
func (f *File) autoFilter(sheet, ref string, refRange, col int, formatSet *formatAutoFilter) error {
xlsx := f.workSheetReader(sheet)
xlsx, err := f.workSheetReader(sheet)
if err != nil {
return err
}
if xlsx.SheetPr != nil {
xlsx.SheetPr.FilterMode = true
}