From f2df344739146189a1dea7cfb81239231af5135b Mon Sep 17 00:00:00 2001 From: xuri Date: Mon, 15 Apr 2019 11:22:57 +0800 Subject: [PATCH] Resolve #369,#370 add error return value exported functions: GetMergeCells ProtectSheet UnprotectSheet UpdateLinkedValue GetMergeCells SetSheetVisible inner functions: workSheetReader copySheet --- adjust.go | 10 +++-- adjust_test.go | 5 ++- cell.go | 102 ++++++++++++++++++++++++++++++---------------- chart.go | 5 ++- col.go | 37 +++++++++++++---- comment.go | 5 ++- datavalidation.go | 14 ++++--- excelize.go | 26 +++++++----- excelize_test.go | 21 ++++------ file.go | 2 +- picture.go | 17 +++++--- picture_test.go | 2 +- rows.go | 52 ++++++++++++++++++----- rows_test.go | 17 ++++---- shape.go | 5 ++- sheet.go | 82 +++++++++++++++++++++++++------------ sheetpr.go | 14 +++++-- sheetview.go | 7 +++- styles.go | 17 ++++++-- styles_test.go | 3 +- table.go | 7 +++- 21 files changed, 304 insertions(+), 146 deletions(-) diff --git a/adjust.go b/adjust.go index 009860b1..51db57ec 100644 --- a/adjust.go +++ b/adjust.go @@ -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 } diff --git a/adjust_test.go b/adjust_test.go index 104eff95..a35e6098 100644 --- a/adjust_test.go +++ b/adjust_test.go @@ -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"`) } diff --git a/cell.go b/cell.go index f9bf1741..6a8eebec 100644 --- a/cell.go +++ b/cell.go @@ -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 diff --git a/chart.go b/chart.go index 5429b771..c657be8b 100644 --- a/chart.go +++ b/chart.go @@ -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 diff --git a/col.go b/col.go index 3660783c..ad63b8ca 100644 --- a/col.go +++ b/col.go @@ -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 { diff --git a/comment.go b/comment.go index ca79779b..ed3d4a74 100644 --- a/comment.go +++ b/comment.go @@ -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" diff --git a/datavalidation.go b/datavalidation.go index 3035bb2e..e5ea5a54 100644 --- a/datavalidation.go +++ b/datavalidation.go @@ -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 } diff --git a/excelize.go b/excelize.go index 857f3ace..2f0db1e2 100644 --- a/excelize.go +++ b/excelize.go @@ -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 // // // -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. diff --git a/excelize_test.go b/excelize_test.go index 2fea9a94..4bd53236 100644 --- a/excelize_test.go +++ b/excelize_test.go @@ -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.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, i+1))) - } + assert.EqualError(t, err, "Sheet Sheet3 is not exist") + assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, i+1))) }) } diff --git a/file.go b/file.go index 2f5164f3..a9e7eecf 100644 --- a/file.go +++ b/file.go @@ -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 diff --git a/picture.go b/picture.go index 16572d41..274a4acd 100644 --- a/picture.go +++ b/picture.go @@ -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 } diff --git a/picture_test.go b/picture_test.go index 2b39ed80..5b1a9e32 100644 --- a/picture_test.go +++ b/picture_test.go @@ -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) diff --git a/rows.go b/rows.go index 6ece77bd..7de18d30 100644 --- a/rows.go +++ b/rows.go @@ -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 } diff --git a/rows_test.go b/rows_test.go index f576efcc..6a107ad3 100644 --- a/rows_test.go +++ b/rows_test.go @@ -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)) diff --git a/shape.go b/shape.go index e6b0456d..5cac776e 100644 --- a/shape.go +++ b/shape.go @@ -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" diff --git a/sheet.go b/sheet.go index 9960ef8e..f1f89bab 100644 --- a/sheet.go +++ b/sheet.go @@ -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 diff --git a/sheetpr.go b/sheetpr.go index 14c18da0..66761f3f 100644 --- a/sheetpr.go +++ b/sheetpr.go @@ -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 } diff --git a/sheetview.go b/sheetview.go index 6b191e92..8ffc9bcd 100644 --- a/sheetview.go +++ b/sheetview.go @@ -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. diff --git a/styles.go b/styles.go index 1cc025cc..a515756e 100644 --- a/styles.go +++ b/styles.go @@ -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 diff --git a/styles_test.go b/styles_test.go index c6fbbef0..b6f6042e 100644 --- a/styles_test.go +++ b/styles_test.go @@ -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) diff --git a/table.go b/table.go index 2ed86547..4505994b 100644 --- a/table.go +++ b/table.go @@ -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 }