summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--README.md6
-rw-r--r--README_zh.md4
-rw-r--r--adjust.go35
-rw-r--r--cell.go210
-rw-r--r--cell_test.go35
-rw-r--r--chart.go13
-rw-r--r--col.go100
-rw-r--r--comment.go15
-rw-r--r--date.go9
-rw-r--r--date_test.go9
-rw-r--r--excelize.go12
-rw-r--r--excelize_test.go202
-rw-r--r--lib.go53
-rw-r--r--lib_test.go9
-rw-r--r--picture.go32
-rw-r--r--picture_test.go7
-rw-r--r--rows.go157
-rw-r--r--rows_test.go175
-rw-r--r--shape.go13
-rw-r--r--sheet.go31
-rw-r--r--styles.go34
-rw-r--r--table.go70
23 files changed, 692 insertions, 540 deletions
diff --git a/.gitignore b/.gitignore
index 096dbdd..bafda04 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,4 @@
~$*.xlsx
test/Test*.xlsx
*.out
-test/image3.png
*.test \ No newline at end of file
diff --git a/README.md b/README.md
index 7e81202..84ddde0 100644
--- a/README.md
+++ b/README.md
@@ -15,11 +15,6 @@
Excelize is a library written in pure Go and providing a set of functions that allow you to write to and read from XLSX files. Support reads and writes XLSX file generated by Microsoft Excel™ 2007 and later. Support save file without losing original charts of XLSX. This library needs Go version 1.8 or later. The full API docs can be seen using go's built-in documentation tool, or online at [godoc.org](https://godoc.org/github.com/360EntSecGroup-Skylar/excelize) and [docs reference](https://xuri.me/excelize/).
-**WARNING!**
-
-From version 1.5.0 all row manipulation methods uses Excel row numbering starting with `1` instead of zero-based numbering
-which take place in some methods in eraler versions.
-
## Basic Usage
### Installation
@@ -123,7 +118,6 @@ func main() {
fmt.Println(err)
}
}
-
```
### Add picture to XLSX file
diff --git a/README_zh.md b/README_zh.md
index cb0de08..f8ace28 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -15,10 +15,6 @@
Excelize 是 Go 语言编写的用于操作 Office Excel 文档类库,基于 ECMA-376 Office OpenXML 标准。可以使用它来读取、写入由 Microsoft Excel™ 2007 及以上版本创建的 XLSX 文档。相比较其他的开源类库,Excelize 支持写入原本带有图片(表)、透视表和切片器等复杂样式的文档,还支持向 Excel 文档中插入图片与图表,并且在保存后不会丢失文档原有样式,可以应用于各类报表系统中。使用本类库要求使用的 Go 语言为 1.8 或更高版本,完整的 API 使用文档请访问 [godoc.org](https://godoc.org/github.com/360EntSecGroup-Skylar/excelize) 或查看 [参考文档](https://xuri.me/excelize/)。
-**重要提示**
-
-从版本 1.5.0 开始,所有行操作方法都使用从 `1` 开始的 Excel 行编号,早期版本中某些方法中的基于 `0` 的行编号将不再使用。
-
## 快速上手
### 安装
diff --git a/adjust.go b/adjust.go
index e69eee1..009860b 100644
--- a/adjust.go
+++ b/adjust.go
@@ -30,7 +30,7 @@ const (
// TODO: adjustCalcChain, adjustPageBreaks, adjustComments,
// adjustDataValidations, adjustProtectedCells
//
-func (f *File) adjustHelper(sheet string, dir adjustDirection, num, offset int) {
+func (f *File) adjustHelper(sheet string, dir adjustDirection, num, offset int) error {
xlsx := f.workSheetReader(sheet)
if dir == rows {
@@ -39,11 +39,16 @@ func (f *File) adjustHelper(sheet string, dir adjustDirection, num, offset int)
f.adjustColDimensions(xlsx, num, offset)
}
f.adjustHyperlinks(xlsx, sheet, dir, num, offset)
- f.adjustMergeCells(xlsx, dir, num, offset)
- f.adjustAutoFilter(xlsx, dir, num, offset)
+ if err := f.adjustMergeCells(xlsx, dir, num, offset); err != nil {
+ return err
+ }
+ if err := f.adjustAutoFilter(xlsx, dir, num, offset); err != nil {
+ return err
+ }
checkSheet(xlsx)
checkRow(xlsx)
+ return nil
}
// adjustColDimensions provides a function to update column dimensions when
@@ -127,9 +132,9 @@ func (f *File) adjustHyperlinks(xlsx *xlsxWorksheet, sheet string, dir adjustDir
// adjustAutoFilter provides a function to update the auto filter when
// inserting or deleting rows or columns.
-func (f *File) adjustAutoFilter(xlsx *xlsxWorksheet, dir adjustDirection, num, offset int) {
+func (f *File) adjustAutoFilter(xlsx *xlsxWorksheet, dir adjustDirection, num, offset int) error {
if xlsx.AutoFilter == nil {
- return
+ return nil
}
rng := strings.Split(xlsx.AutoFilter.Ref, ":")
@@ -138,12 +143,12 @@ func (f *File) adjustAutoFilter(xlsx *xlsxWorksheet, dir adjustDirection, num, o
firstCol, firstRow, err := CellNameToCoordinates(firstCell)
if err != nil {
- panic(err)
+ return err
}
lastCol, lastRow, err := CellNameToCoordinates(lastCell)
if err != nil {
- panic(err)
+ return err
}
if (dir == rows && firstRow == num && offset < 0) || (dir == columns && firstCol == num && lastCol == num) {
@@ -154,7 +159,7 @@ func (f *File) adjustAutoFilter(xlsx *xlsxWorksheet, dir adjustDirection, num, o
rowData.Hidden = false
}
}
- return
+ return nil
}
if dir == rows {
@@ -171,13 +176,14 @@ func (f *File) adjustAutoFilter(xlsx *xlsxWorksheet, dir adjustDirection, num, o
}
xlsx.AutoFilter.Ref = firstCell + ":" + lastCell
+ return nil
}
// adjustMergeCells provides a function to update merged cells when inserting
// or deleting rows or columns.
-func (f *File) adjustMergeCells(xlsx *xlsxWorksheet, dir adjustDirection, num, offset int) {
+func (f *File) adjustMergeCells(xlsx *xlsxWorksheet, dir adjustDirection, num, offset int) error {
if xlsx.MergeCells == nil {
- return
+ return nil
}
for i, areaData := range xlsx.MergeCells.Cells {
@@ -187,12 +193,12 @@ func (f *File) adjustMergeCells(xlsx *xlsxWorksheet, dir adjustDirection, num, o
firstCol, firstRow, err := CellNameToCoordinates(firstCell)
if err != nil {
- panic(err)
+ return err
}
lastCol, lastRow, err := CellNameToCoordinates(lastCell)
if err != nil {
- panic(err)
+ return err
}
adjust := func(v int) int {
@@ -224,13 +230,14 @@ func (f *File) adjustMergeCells(xlsx *xlsxWorksheet, dir adjustDirection, num, o
}
if firstCell, err = CoordinatesToCellName(firstCol, firstRow); err != nil {
- panic(err)
+ return err
}
if lastCell, err = CoordinatesToCellName(lastCol, lastRow); err != nil {
- panic(err)
+ return err
}
areaData.Ref = firstCell + ":" + lastCell
}
+ return nil
}
diff --git a/cell.go b/cell.go
index a3a1c19..a1b6dbf 100644
--- a/cell.go
+++ b/cell.go
@@ -34,13 +34,13 @@ const (
// worksheet name and axis in XLSX file. If it is possible to apply a format
// to the cell value, it will do so, if not then an error will be returned,
// along with the raw value of the cell.
-func (f *File) GetCellValue(sheet, axis string) string {
- return f.getCellStringFunc(sheet, axis, func(x *xlsxWorksheet, c *xlsxC) (string, bool) {
+func (f *File) GetCellValue(sheet, axis string) (string, error) {
+ return f.getCellStringFunc(sheet, axis, func(x *xlsxWorksheet, c *xlsxC) (string, bool, error) {
val, err := c.getValueFrom(f, f.sharedStringsReader())
if err != nil {
- panic(err) // Fail fast to avoid future side effects!
+ return val, false, err
}
- return val, true
+ return val, true, err
})
}
@@ -68,7 +68,7 @@ func (f *File) GetCellValue(sheet, axis string) string {
//
// 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{}) {
+func (f *File) SetCellValue(sheet, axis string, value interface{}) error {
switch v := value.(type) {
case int:
f.SetCellInt(sheet, axis, v)
@@ -102,9 +102,12 @@ func (f *File) SetCellValue(sheet, axis string, value interface{}) {
f.SetCellDefault(sheet, axis, strconv.FormatFloat(v.Seconds()/86400.0, 'f', -1, 32))
f.setDefaultTimeStyle(sheet, axis, 21)
case time.Time:
- vv := timeToExcelTime(v)
- if vv > 0 {
- f.SetCellDefault(sheet, axis, strconv.FormatFloat(timeToExcelTime(v), 'f', -1, 64))
+ 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)
} else {
f.SetCellStr(sheet, axis, v.Format(time.RFC3339Nano))
@@ -116,23 +119,31 @@ func (f *File) SetCellValue(sheet, axis string, value interface{}) {
default:
f.SetCellStr(sheet, axis, fmt.Sprintf("%v", value))
}
+ return nil
}
// 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) {
+func (f *File) SetCellInt(sheet, axis string, value int) error {
xlsx := f.workSheetReader(sheet)
- cellData, col, _ := f.prepareCell(xlsx, sheet, axis)
+ cellData, col, _, err := f.prepareCell(xlsx, sheet, axis)
+ if err != nil {
+ return err
+ }
cellData.S = f.prepareCellStyle(xlsx, col, cellData.S)
cellData.T = ""
cellData.V = strconv.Itoa(value)
+ return err
}
// 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) {
+func (f *File) SetCellBool(sheet, axis string, value bool) error {
xlsx := f.workSheetReader(sheet)
- cellData, col, _ := f.prepareCell(xlsx, sheet, axis)
+ cellData, col, _, err := f.prepareCell(xlsx, sheet, axis)
+ if err != nil {
+ return err
+ }
cellData.S = f.prepareCellStyle(xlsx, col, cellData.S)
cellData.T = "b"
if value {
@@ -140,6 +151,7 @@ func (f *File) SetCellBool(sheet, axis string, value bool) {
} else {
cellData.V = "0"
}
+ return err
}
// SetCellFloat sets a floating point value into a cell. The prec parameter
@@ -151,20 +163,26 @@ func (f *File) SetCellBool(sheet, axis string, value bool) {
// var x float32 = 1.325
// f.SetCellFloat("Sheet1", "A1", float64(x), 2, 32)
//
-func (f *File) SetCellFloat(sheet, axis string, value float64, prec, bitSize int) {
+func (f *File) SetCellFloat(sheet, axis string, value float64, prec, bitSize int) error {
xlsx := f.workSheetReader(sheet)
- cellData, col, _ := f.prepareCell(xlsx, sheet, axis)
+ cellData, col, _, err := f.prepareCell(xlsx, sheet, axis)
+ if err != nil {
+ return err
+ }
cellData.S = f.prepareCellStyle(xlsx, col, cellData.S)
cellData.T = ""
cellData.V = strconv.FormatFloat(value, 'f', prec, bitSize)
+ return err
}
// 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) {
+func (f *File) SetCellStr(sheet, axis, value string) error {
xlsx := f.workSheetReader(sheet)
- cellData, col, _ := f.prepareCell(xlsx, sheet, axis)
-
+ cellData, col, _, err := f.prepareCell(xlsx, sheet, axis)
+ if err != nil {
+ return err
+ }
// Leading space(s) character detection.
if len(value) > 0 && value[0] == 32 {
cellData.XMLSpace = xml.Attr{
@@ -176,42 +194,49 @@ func (f *File) SetCellStr(sheet, axis, value string) {
cellData.S = f.prepareCellStyle(xlsx, col, cellData.S)
cellData.T = "str"
cellData.V = value
+ return err
}
// 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) {
+func (f *File) SetCellDefault(sheet, axis, value string) error {
xlsx := f.workSheetReader(sheet)
- cellData, col, _ := f.prepareCell(xlsx, sheet, axis)
+ cellData, col, _, err := f.prepareCell(xlsx, sheet, axis)
+ if err != nil {
+ return err
+ }
cellData.S = f.prepareCellStyle(xlsx, col, cellData.S)
cellData.T = ""
cellData.V = value
+ return err
}
// GetCellFormula provides a function to get formula from cell by given
// worksheet name and axis in XLSX file.
-func (f *File) GetCellFormula(sheet, axis string) string {
- return f.getCellStringFunc(sheet, axis, func(x *xlsxWorksheet, c *xlsxC) (string, bool) {
+func (f *File) GetCellFormula(sheet, axis string) (string, error) {
+ return f.getCellStringFunc(sheet, axis, func(x *xlsxWorksheet, c *xlsxC) (string, bool, error) {
if c.F == nil {
- return "", false
+ return "", false, nil
}
if c.F.T == STCellFormulaTypeShared {
- return getSharedForumula(x, c.F.Si), true
+ return getSharedForumula(x, c.F.Si), true, nil
}
- return c.F.Content, true
+ return c.F.Content, true, nil
})
}
// SetCellFormula provides a function to set cell formula by given string and
// worksheet name.
-func (f *File) SetCellFormula(sheet, axis, formula string) {
+func (f *File) SetCellFormula(sheet, axis, formula string) error {
xlsx := f.workSheetReader(sheet)
- cellData, _, _ := f.prepareCell(xlsx, sheet, axis)
-
+ cellData, _, _, err := f.prepareCell(xlsx, sheet, axis)
+ if err != nil {
+ return err
+ }
if formula == "" {
cellData.F = nil
f.deleteCalcChain(axis)
- return
+ return err
}
if cellData.F != nil {
@@ -219,6 +244,7 @@ func (f *File) SetCellFormula(sheet, axis, formula string) {
} else {
cellData.F = &xlsxF{Content: formula}
}
+ return err
}
// GetCellHyperLink provides a function to get cell hyperlink by given
@@ -227,28 +253,30 @@ func (f *File) SetCellFormula(sheet, axis, formula string) {
// the value of link will be false and the value of the target will be a blank
// string. For example get hyperlink of Sheet1!H6:
//
-// link, target := xlsx.GetCellHyperLink("Sheet1", "H6")
+// link, target, err := xlsx.GetCellHyperLink("Sheet1", "H6")
//
-func (f *File) GetCellHyperLink(sheet, axis string) (bool, string) {
+func (f *File) GetCellHyperLink(sheet, axis string) (bool, string, error) {
// Check for correct cell name
if _, _, err := SplitCellName(axis); err != nil {
- panic(err) // Fail fast to avoid possible future side effects
+ return false, "", err
}
xlsx := f.workSheetReader(sheet)
- axis = f.mergeCellsParser(xlsx, axis)
-
+ axis, err := f.mergeCellsParser(xlsx, axis)
+ if err != nil {
+ return false, "", err
+ }
if xlsx.Hyperlinks != nil {
for _, link := range xlsx.Hyperlinks.Hyperlink {
if link.Ref == axis {
if link.RID != "" {
- return true, f.getSheetRelationshipsTargetByID(sheet, link.RID)
+ return true, f.getSheetRelationshipsTargetByID(sheet, link.RID), err
}
- return true, link.Location
+ return true, link.Location, err
}
}
}
- return false, ""
+ return false, "", err
}
// SetCellHyperLink provides a function to set cell hyperlink by given
@@ -256,23 +284,26 @@ func (f *File) GetCellHyperLink(sheet, axis string) (bool, string) {
// hyperlink "External" for web site or "Location" for moving to one of cell
// in this workbook. The below is example for external link.
//
-// xlsx.SetCellHyperLink("Sheet1", "A3", "https://github.com/360EntSecGroup-Skylar/excelize", "External")
+// err := xlsx.SetCellHyperLink("Sheet1", "A3", "https://github.com/360EntSecGroup-Skylar/excelize", "External")
// // Set underline and font color style for the cell.
-// style, _ := xlsx.NewStyle(`{"font":{"color":"#1265BE","underline":"single"}}`)
-// xlsx.SetCellStyle("Sheet1", "A3", "A3", style)
+// style, err := xlsx.NewStyle(`{"font":{"color":"#1265BE","underline":"single"}}`)
+// err = xlsx.SetCellStyle("Sheet1", "A3", "A3", style)
//
// A this is another example for "Location":
//
-// xlsx.SetCellHyperLink("Sheet1", "A3", "Sheet1!A40", "Location")
+// err := xlsx.SetCellHyperLink("Sheet1", "A3", "Sheet1!A40", "Location")
//
-func (f *File) SetCellHyperLink(sheet, axis, link, linkType string) {
+func (f *File) SetCellHyperLink(sheet, axis, link, linkType string) error {
// Check for correct cell name
if _, _, err := SplitCellName(axis); err != nil {
- panic(err) // Fail fast to avoid possible future side effects
+ return err
}
xlsx := f.workSheetReader(sheet)
- axis = f.mergeCellsParser(xlsx, axis)
+ axis, err := f.mergeCellsParser(xlsx, axis)
+ if err != nil {
+ return err
+ }
var linkData xlsxHyperlink
@@ -289,35 +320,36 @@ func (f *File) SetCellHyperLink(sheet, axis, link, linkType string) {
Location: link,
}
default:
- panic(fmt.Errorf("invalid link type %q", linkType))
+ return fmt.Errorf("invalid link type %q", linkType)
}
if xlsx.Hyperlinks == nil {
xlsx.Hyperlinks = new(xlsxHyperlinks)
}
xlsx.Hyperlinks.Hyperlink = append(xlsx.Hyperlinks.Hyperlink, linkData)
+ return nil
}
// MergeCell provides a function to merge cells by given coordinate area and
// sheet name. For example create a merged cell of D3:E9 on Sheet1:
//
-// xlsx.MergeCell("Sheet1", "D3", "E9")
+// err := xlsx.MergeCell("Sheet1", "D3", "E9")
//
// If you create a merged cell that overlaps with another existing merged cell,
// those merged cells that already exist will be removed.
-func (f *File) MergeCell(sheet, hcell, vcell string) {
+func (f *File) MergeCell(sheet, hcell, vcell string) error {
hcol, hrow, err := CellNameToCoordinates(hcell)
if err != nil {
- panic(err)
+ return err
}
vcol, vrow, err := CellNameToCoordinates(vcell)
if err != nil {
- panic(err)
+ return err
}
if hcol == vcol && hrow == vrow {
- return
+ return err
}
if vcol < hcol {
@@ -340,11 +372,13 @@ func (f *File) MergeCell(sheet, hcell, vcell string) {
for _, cellData := range xlsx.MergeCells.Cells {
cc := strings.Split(cellData.Ref, ":")
if len(cc) != 2 {
- panic(fmt.Errorf("invalid area %q", cellData.Ref))
+ return fmt.Errorf("invalid area %q", cellData.Ref)
}
-
- if !checkCellInArea(hcell, cellData.Ref) && !checkCellInArea(vcell, cellData.Ref) &&
- !checkCellInArea(cc[0], ref) && !checkCellInArea(cc[1], ref) {
+ c1, _ := checkCellInArea(hcell, cellData.Ref)
+ c2, _ := checkCellInArea(vcell, cellData.Ref)
+ c3, _ := checkCellInArea(cc[0], ref)
+ c4, _ := checkCellInArea(cc[1], ref)
+ if !c1 && !c2 && !c3 && !c4 {
cells = append(cells, cellData)
}
}
@@ -353,24 +387,25 @@ func (f *File) MergeCell(sheet, hcell, vcell string) {
} else {
xlsx.MergeCells = &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: hcell + ":" + vcell}}}
}
+ return err
}
// SetSheetRow writes an array to row by given worksheet name, starting
// coordinate and a pointer to array type 'slice'. For example, writes an
// array to row 6 start with the cell B6 on Sheet1:
//
-// xlsx.SetSheetRow("Sheet1", "B6", &[]interface{}{"1", nil, 2})
+// err := xlsx.SetSheetRow("Sheet1", "B6", &[]interface{}{"1", nil, 2})
//
-func (f *File) SetSheetRow(sheet, axis string, slice interface{}) {
+func (f *File) SetSheetRow(sheet, axis string, slice interface{}) error {
col, row, err := CellNameToCoordinates(axis)
if err != nil {
- panic(err) // Fail fast to avoid future side effects!
+ return err
}
// Make sure 'slice' is a Ptr to Slice
v := reflect.ValueOf(slice)
if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Slice {
- panic(errors.New("pointer to slice expected")) // Fail fast to avoid future side effects!
+ return errors.New("pointer to slice expected")
}
v = v.Elem()
@@ -379,35 +414,42 @@ func (f *File) SetSheetRow(sheet, axis string, slice interface{}) {
// Error should never happens here. But keep ckecking to early detect regresions
// if it will be introduced in furure
if err != nil {
- panic(err) // Fail fast to avoid future side effects!
+ return err
}
f.SetCellValue(sheet, cell, v.Index(i).Interface())
}
+ return err
}
// getCellInfo does common preparation for all SetCell* methods.
-func (f *File) prepareCell(xlsx *xlsxWorksheet, sheet, cell string) (*xlsxC, int, int) {
- cell = f.mergeCellsParser(xlsx, cell)
-
+func (f *File) prepareCell(xlsx *xlsxWorksheet, sheet, cell string) (*xlsxC, int, int, error) {
+ var err error
+ cell, err = f.mergeCellsParser(xlsx, cell)
+ if err != nil {
+ return nil, 0, 0, err
+ }
col, row, err := CellNameToCoordinates(cell)
if err != nil {
- panic(err) // Fail fast and prevent future side effects
+ return nil, 0, 0, err
}
prepareSheetXML(xlsx, col, row)
- return &xlsx.SheetData.Row[row-1].C[col-1], col, row
+ return &xlsx.SheetData.Row[row-1].C[col-1], col, row, err
}
-// 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)) string {
+// 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)
- axis = f.mergeCellsParser(xlsx, axis)
-
+ var err error
+ axis, err = f.mergeCellsParser(xlsx, axis)
+ if err != nil {
+ return "", err
+ }
_, row, err := CellNameToCoordinates(axis)
if err != nil {
- panic(err) // Fail fast to avoid future side effects!
+ return "", err
}
lastRowNum := 0
@@ -417,7 +459,7 @@ func (f *File) getCellStringFunc(sheet, axis string, fn func(x *xlsxWorksheet, c
// keep in mind: row starts from 1
if row > lastRowNum {
- return ""
+ return "", nil
}
for rowIdx := range xlsx.SheetData.Row {
@@ -430,12 +472,16 @@ func (f *File) getCellStringFunc(sheet, axis string, fn func(x *xlsxWorksheet, c
if axis != colData.R {
continue
}
- if val, ok := fn(xlsx, colData); ok {
- return val
+ val, ok, err := fn(xlsx, colData)
+ if err != nil {
+ return "", err
+ }
+ if ok {
+ return val, nil
}
}
}
- return ""
+ return "", nil
}
// formattedValue provides a function to returns a value after formatted. If
@@ -468,35 +514,39 @@ func (f *File) prepareCellStyle(xlsx *xlsxWorksheet, col, style int) int {
// mergeCellsParser provides a function to check merged cells in worksheet by
// given axis.
-func (f *File) mergeCellsParser(xlsx *xlsxWorksheet, axis string) string {
+func (f *File) mergeCellsParser(xlsx *xlsxWorksheet, axis string) (string, error) {
axis = strings.ToUpper(axis)
if xlsx.MergeCells != nil {
for i := 0; i < len(xlsx.MergeCells.Cells); i++ {
- if checkCellInArea(axis, xlsx.MergeCells.Cells[i].Ref) {
+ ok, err := checkCellInArea(axis, xlsx.MergeCells.Cells[i].Ref)
+ if err != nil {
+ return axis, err
+ }
+ if ok {
axis = strings.Split(xlsx.MergeCells.Cells[i].Ref, ":")[0]
}
}
}
- return axis
+ return axis, nil
}
// checkCellInArea provides a function to determine if a given coordinate is
// within an area.
-func checkCellInArea(cell, area string) bool {
+func checkCellInArea(cell, area string) (bool, error) {
col, row, err := CellNameToCoordinates(cell)
if err != nil {
- panic(err)
+ return false, err
}
rng := strings.Split(area, ":")
if len(rng) != 2 {
- return false
+ return false, err
}
firstCol, firtsRow, _ := CellNameToCoordinates(rng[0])
lastCol, lastRow, _ := CellNameToCoordinates(rng[1])
- return col >= firstCol && col <= lastCol && row >= firtsRow && row <= lastRow
+ return col >= firstCol && col <= lastCol && row >= firtsRow && row <= lastRow, err
}
// getSharedForumula find a cell contains the same formula as another cell,
diff --git a/cell_test.go b/cell_test.go
index 12efc17..7b1381f 100644
--- a/cell_test.go
+++ b/cell_test.go
@@ -17,8 +17,9 @@ func TestCheckCellInArea(t *testing.T) {
for _, expectedTrueCellInArea := range expectedTrueCellInAreaList {
cell := expectedTrueCellInArea[0]
area := expectedTrueCellInArea[1]
-
- assert.Truef(t, checkCellInArea(cell, area),
+ ok, err := checkCellInArea(cell, area)
+ assert.NoError(t, err)
+ assert.Truef(t, ok,
"Expected cell %v to be in area %v, got false\n", cell, area)
}
@@ -31,14 +32,15 @@ func TestCheckCellInArea(t *testing.T) {
for _, expectedFalseCellInArea := range expectedFalseCellInAreaList {
cell := expectedFalseCellInArea[0]
area := expectedFalseCellInArea[1]
-
- assert.Falsef(t, checkCellInArea(cell, area),
+ ok, err := checkCellInArea(cell, area)
+ assert.NoError(t, err)
+ assert.Falsef(t, ok,
"Expected cell %v not to be inside of area %v, but got true\n", cell, area)
}
- assert.Panics(t, func() {
- checkCellInArea("AA0", "Z0:AB1")
- })
+ ok, err := checkCellInArea("AA0", "Z0:AB1")
+ assert.EqualError(t, err, `cannot convert cell "AA0" to coordinates: invalid cell name "AA0"`)
+ assert.False(t, ok)
}
func TestSetCellFloat(t *testing.T) {
@@ -47,20 +49,28 @@ func TestSetCellFloat(t *testing.T) {
f := NewFile()
f.SetCellFloat(sheet, "A1", 123.0, -1, 64)
f.SetCellFloat(sheet, "A2", 123.0, 1, 64)
- assert.Equal(t, "123", f.GetCellValue(sheet, "A1"), "A1 should be 123")
- assert.Equal(t, "123.0", f.GetCellValue(sheet, "A2"), "A2 should be 123.0")
+ val, err := f.GetCellValue(sheet, "A1")
+ assert.NoError(t, err)
+ assert.Equal(t, "123", val, "A1 should be 123")
+ val, err = f.GetCellValue(sheet, "A2")
+ assert.NoError(t, err)
+ assert.Equal(t, "123.0", val, "A2 should be 123.0")
})
t.Run("with a decimal and precision limit", func(t *testing.T) {
f := NewFile()
f.SetCellFloat(sheet, "A1", 123.42, 1, 64)
- assert.Equal(t, "123.4", f.GetCellValue(sheet, "A1"), "A1 should be 123.4")
+ val, err := f.GetCellValue(sheet, "A1")
+ assert.NoError(t, err)
+ assert.Equal(t, "123.4", val, "A1 should be 123.4")
})
t.Run("with a decimal and no limit", func(t *testing.T) {
f := NewFile()
f.SetCellFloat(sheet, "A1", 123.42, -1, 64)
- assert.Equal(t, "123.42", f.GetCellValue(sheet, "A1"), "A1 should be 123.42")
+ val, err := f.GetCellValue(sheet, "A1")
+ assert.NoError(t, err)
+ assert.Equal(t, "123.42", val, "A1 should be 123.42")
})
}
@@ -68,6 +78,7 @@ func ExampleFile_SetCellFloat() {
f := NewFile()
var x = 3.14159265
f.SetCellFloat("Sheet1", "A1", x, 2, 64)
- fmt.Println(f.GetCellValue("Sheet1", "A1"))
+ val, _ := f.GetCellValue("Sheet1", "A1")
+ fmt.Println(val)
// Output: 3.14
}
diff --git a/chart.go b/chart.go
index c31995e..5429b77 100644
--- a/chart.go
+++ b/chart.go
@@ -456,7 +456,10 @@ func (f *File) AddChart(sheet, cell, format string) error {
drawingXML := "xl/drawings/drawing" + strconv.Itoa(drawingID) + ".xml"
drawingID, drawingXML = f.prepareDrawing(xlsx, drawingID, sheet, drawingXML)
drawingRID := f.addDrawingRelationships(drawingID, SourceRelationshipChart, "../charts/chart"+strconv.Itoa(chartID)+".xml", "")
- f.addDrawingChart(sheet, drawingXML, cell, formatSet.Dimension.Width, formatSet.Dimension.Height, drawingRID, &formatSet.Format)
+ err = f.addDrawingChart(sheet, drawingXML, cell, formatSet.Dimension.Width, formatSet.Dimension.Height, drawingRID, &formatSet.Format)
+ if err != nil {
+ return err
+ }
f.addChart(formatSet)
f.addContentTypePart(chartID, "chart")
f.addContentTypePart(drawingID, "drawings")
@@ -1239,8 +1242,11 @@ func (f *File) drawingParser(path string) (*xlsxWsDr, int) {
// addDrawingChart provides a function to add chart graphic frame by given
// sheet, drawingXML, cell, width, height, relationship index and format sets.
-func (f *File) addDrawingChart(sheet, drawingXML, cell string, width, height, rID int, formatSet *formatPicture) {
- col, row := MustCellNameToCoordinates(cell)
+func (f *File) addDrawingChart(sheet, drawingXML, cell string, width, height, rID int, formatSet *formatPicture) error {
+ col, row, err := CellNameToCoordinates(cell)
+ if err != nil {
+ return err
+ }
colIdx := col - 1
rowIdx := row - 1
@@ -1290,4 +1296,5 @@ func (f *File) addDrawingChart(sheet, drawingXML, cell string, width, height, rI
}
content.TwoCellAnchor = append(content.TwoCellAnchor, &twoCellAnchor)
f.Drawings[drawingXML] = content
+ return err
}
diff --git a/col.go b/col.go
index 7eb7831..e3e057c 100644
--- a/col.go
+++ b/col.go
@@ -22,33 +22,39 @@ const (
// worksheet name and column name. For example, get visible state of column D
// in Sheet1:
//
-// xlsx.GetColVisible("Sheet1", "D")
+// visiable, err := xlsx.GetColVisible("Sheet1", "D")
//
-func (f *File) GetColVisible(sheet, col string) bool {
- colNum := MustColumnNameToNumber(col)
+func (f *File) GetColVisible(sheet, col string) (bool, error) {
+ visible := true
+ colNum, err := ColumnNameToNumber(col)
+ if err != nil {
+ return visible, err
+ }
xlsx := f.workSheetReader(sheet)
if xlsx.Cols == nil {
- return true
+ return visible, err
}
- visible := true
for c := range xlsx.Cols.Col {
colData := &xlsx.Cols.Col[c]
if colData.Min <= colNum && colNum <= colData.Max {
visible = !colData.Hidden
}
}
- return visible
+ return visible, err
}
// SetColVisible provides a function to set visible of a single column by given
// worksheet name and column name. For example, hide column D in Sheet1:
//
-// xlsx.SetColVisible("Sheet1", "D", false)
+// err := xlsx.SetColVisible("Sheet1", "D", false)
//
-func (f *File) SetColVisible(sheet, col string, visible bool) {
- colNum := MustColumnNameToNumber(col)
+func (f *File) SetColVisible(sheet, col string, visible bool) error {
+ colNum, err := ColumnNameToNumber(col)
+ if err != nil {
+ return err
+ }
colData := xlsxCol{
Min: colNum,
Max: colNum,
@@ -60,7 +66,7 @@ func (f *File) SetColVisible(sheet, col string, visible bool) {
cols := xlsxCols{}
cols.Col = append(cols.Col, colData)
xlsx.Cols = &cols
- return
+ return err
}
for v := range xlsx.Cols.Col {
if xlsx.Cols.Col[v].Min <= colNum && colNum <= xlsx.Cols.Col[v].Max {
@@ -72,20 +78,24 @@ func (f *File) SetColVisible(sheet, col string, visible bool) {
colData.Hidden = !visible
colData.CustomWidth = true
xlsx.Cols.Col = append(xlsx.Cols.Col, colData)
+ return err
}
// GetColOutlineLevel provides a function to get outline level of a single
// column by given worksheet name and column name. For example, get outline
// level of column D in Sheet1:
//
-// xlsx.GetColOutlineLevel("Sheet1", "D")
+// level, err := xlsx.GetColOutlineLevel("Sheet1", "D")
//
-func (f *File) GetColOutlineLevel(sheet, col string) uint8 {
- colNum := MustColumnNameToNumber(col)
- xlsx := f.workSheetReader(sheet)
+func (f *File) GetColOutlineLevel(sheet, col string) (uint8, error) {
level := uint8(0)
+ colNum, err := ColumnNameToNumber(col)
+ if err != nil {
+ return level, err
+ }
+ xlsx := f.workSheetReader(sheet)
if xlsx.Cols == nil {
- return level
+ return level, err
}
for c := range xlsx.Cols.Col {
colData := &xlsx.Cols.Col[c]
@@ -93,17 +103,20 @@ func (f *File) GetColOutlineLevel(sheet, col string) uint8 {
level = colData.OutlineLevel
}
}
- return level
+ return level, err
}
// SetColOutlineLevel provides a function to set outline level of a single
// column by given worksheet name and column name. For example, set outline
// level of column D in Sheet1 to 2:
//
-// xlsx.SetColOutlineLevel("Sheet1", "D", 2)
+// err := xlsx.SetColOutlineLevel("Sheet1", "D", 2)
//
-func (f *File) SetColOutlineLevel(sheet, col string, level uint8) {
- colNum := MustColumnNameToNumber(col)
+func (f *File) SetColOutlineLevel(sheet, col string, level uint8) error {
+ colNum, err := ColumnNameToNumber(col)
+ if err != nil {
+ return err
+ }
colData := xlsxCol{
Min: colNum,
Max: colNum,
@@ -115,7 +128,7 @@ func (f *File) SetColOutlineLevel(sheet, col string, level uint8) {
cols := xlsxCols{}
cols.Col = append(cols.Col, colData)
xlsx.Cols = &cols
- return
+ return err
}
for v := range xlsx.Cols.Col {
if xlsx.Cols.Col[v].Min <= colNum && colNum <= xlsx.Cols.Col[v].Max {
@@ -127,21 +140,24 @@ func (f *File) SetColOutlineLevel(sheet, col string, level uint8) {
colData.OutlineLevel = level
colData.CustomWidth = true
xlsx.Cols.Col = append(xlsx.Cols.Col, colData)
+ return err
}
// SetColWidth provides a function to set the width of a single column or
// multiple columns. For example:
//
// xlsx := excelize.NewFile()
-// xlsx.SetColWidth("Sheet1", "A", "H", 20)
-// err := xlsx.Save()
-// if err != nil {
-// fmt.Println(err)
-// }
+// err := xlsx.SetColWidth("Sheet1", "A", "H", 20)
//
-func (f *File) SetColWidth(sheet, startcol, endcol string, width float64) {
- min := MustColumnNameToNumber(startcol)
- max := MustColumnNameToNumber(endcol)
+func (f *File) SetColWidth(sheet, startcol, endcol string, width float64) error {
+ min, err := ColumnNameToNumber(startcol)
+ if err != nil {
+ return err
+ }
+ max, err := ColumnNameToNumber(endcol)
+ if err != nil {
+ return err
+ }
if min > max {
min, max = max, min
}
@@ -160,6 +176,7 @@ func (f *File) SetColWidth(sheet, startcol, endcol string, width float64) {
cols.Col = append(cols.Col, col)
xlsx.Cols = &cols
}
+ return err
}
// positionObjectPixels calculate the vertices that define the position of a
@@ -289,8 +306,11 @@ func (f *File) getColWidth(sheet string, col int) int {
// GetColWidth provides a function to get column width by given worksheet name
// and column index.
-func (f *File) GetColWidth(sheet, col string) float64 {
- colNum := MustColumnNameToNumber(col)
+func (f *File) GetColWidth(sheet, col string) (float64, error) {
+ colNum, err := ColumnNameToNumber(col)
+ if err != nil {
+ return defaultColWidthPixels, err
+ }
xlsx := f.workSheetReader(sheet)
if xlsx.Cols != nil {
var width float64
@@ -300,39 +320,39 @@ func (f *File) GetColWidth(sheet, col string) float64 {
}
}
if width != 0 {
- return width
+ return width, err
}
}
// Optimisation for when the column widths haven't changed.
- return defaultColWidthPixels
+ return defaultColWidthPixels, err
}
// InsertCol provides a function to insert a new column before given column
// index. For example, create a new column before column C in Sheet1:
//
-// xlsx.InsertCol("Sheet1", "C")
+// err := xlsx.InsertCol("Sheet1", "C")
//
-func (f *File) InsertCol(sheet, col string) {
+func (f *File) InsertCol(sheet, col string) error {
num, err := ColumnNameToNumber(col)
if err != nil {
- panic(err)
+ return err
}
- f.adjustHelper(sheet, columns, num, 1)
+ return f.adjustHelper(sheet, columns, num, 1)
}
// RemoveCol provides a function to remove single column by given worksheet
// name and column index. For example, remove column C in Sheet1:
//
-// xlsx.RemoveCol("Sheet1", "C")
+// err := xlsx.RemoveCol("Sheet1", "C")
//
// 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
// worksheet, it will cause a file error when you open it. The excelize only
// partially updates these references currently.
-func (f *File) RemoveCol(sheet, col string) {
+func (f *File) RemoveCol(sheet, col string) error {
num, err := ColumnNameToNumber(col)
if err != nil {
- panic(err) // Fail fast to avoid possible future side effects!
+ return err
}
xlsx := f.workSheetReader(sheet)
@@ -346,7 +366,7 @@ func (f *File) RemoveCol(sheet, col string) {
}
}
}
- f.adjustHelper(sheet, columns, num, -1)
+ return f.adjustHelper(sheet, columns, num, -1)
}
// convertColWidthToPixels provieds function to convert the width of a cell
diff --git a/comment.go b/comment.go
index a94194d..ca79779 100644
--- a/comment.go
+++ b/comment.go
@@ -72,7 +72,7 @@ func (f *File) getSheetComments(sheetID int) string {
// author length is 255 and the max text length is 32512. For example, add a
// comment in Sheet1!$A$30:
//
-// xlsx.AddComment("Sheet1", "A30", `{"author":"Excelize: ","text":"This is a comment."}`)
+// err := xlsx.AddComment("Sheet1", "A30", `{"author":"Excelize: ","text":"This is a comment."}`)
//
func (f *File) AddComment(sheet, cell, format string) error {
formatSet, err := parseFormatCommentsSet(format)
@@ -107,15 +107,21 @@ func (f *File) AddComment(sheet, cell, format string) error {
colCount = ll
}
}
- f.addDrawingVML(commentID, drawingVML, cell, strings.Count(formatSet.Text, "\n")+1, colCount)
+ err = f.addDrawingVML(commentID, drawingVML, cell, strings.Count(formatSet.Text, "\n")+1, colCount)
+ if err != nil {
+ return err
+ }
f.addContentTypePart(commentID, "comments")
return err
}
// addDrawingVML provides a function to create comment as
// xl/drawings/vmlDrawing%d.vml by given commit ID and cell.
-func (f *File) addDrawingVML(commentID int, drawingVML, cell string, lineCount, colCount int) {
- col, row := MustCellNameToCoordinates(cell)
+func (f *File) addDrawingVML(commentID int, drawingVML, cell string, lineCount, colCount int) error {
+ col, row, err := CellNameToCoordinates(cell)
+ if err != nil {
+ return err
+ }
yAxis := col - 1
xAxis := row - 1
vml := f.VMLDrawing[drawingVML]
@@ -206,6 +212,7 @@ func (f *File) addDrawingVML(commentID int, drawingVML, cell string, lineCount,
}
vml.Shape = append(vml.Shape, shape)
f.VMLDrawing[drawingVML] = vml
+ return err
}
// addComment provides a function to create chart as xl/comments%d.xml by
diff --git a/date.go b/date.go
index e550feb..b49a695 100644
--- a/date.go
+++ b/date.go
@@ -10,6 +10,7 @@
package excelize
import (
+ "errors"
"math"
"time"
)
@@ -25,18 +26,18 @@ var (
)
// timeToExcelTime provides a function to convert time to Excel time.
-func timeToExcelTime(t time.Time) float64 {
+func timeToExcelTime(t time.Time) (float64, error) {
// TODO in future this should probably also handle date1904 and like TimeFromExcelTime
// Force user to explicit convet passed value to UTC time.
// Because for example 1900-01-01 00:00:00 +0300 MSK converts to 1900-01-01 00:00:00 +0230 LMT
// probably due to daylight saving.
if t.Location() != time.UTC {
- panic("only UTC time expected")
+ return 0.0, errors.New("only UTC time expected")
}
if t.Before(excelMinTime1900) {
- return 0.0
+ return 0.0, nil
}
tt := t
@@ -60,7 +61,7 @@ func timeToExcelTime(t time.Time) float64 {
if t.After(excelBuggyPeriodStart) {
result += 1.0
}
- return result
+ return result, nil
}
// shiftJulianToNoon provides a function to process julian date to noon.
diff --git a/date_test.go b/date_test.go
index 3ec0b69..63cb19e 100644
--- a/date_test.go
+++ b/date_test.go
@@ -31,7 +31,9 @@ var trueExpectedDateList = []dateTest{
func TestTimeToExcelTime(t *testing.T) {
for i, test := range trueExpectedDateList {
t.Run(fmt.Sprintf("TestData%d", i+1), func(t *testing.T) {
- assert.Equalf(t, test.ExcelValue, timeToExcelTime(test.GoValue),
+ excelTime, err := timeToExcelTime(test.GoValue)
+ assert.NoError(t, err)
+ assert.Equalf(t, test.ExcelValue, excelTime,
"Time: %s", test.GoValue.String())
})
}
@@ -44,9 +46,8 @@ func TestTimeToExcelTime_Timezone(t *testing.T) {
}
for i, test := range trueExpectedDateList {
t.Run(fmt.Sprintf("TestData%d", i+1), func(t *testing.T) {
- assert.Panics(t, func() {
- timeToExcelTime(test.GoValue.In(location))
- }, "Time: %s", test.GoValue.String())
+ _, err := timeToExcelTime(test.GoValue.In(location))
+ assert.EqualError(t, err, "only UTC time expected")
})
}
}
diff --git a/excelize.go b/excelize.go
index 7a50460..857f3ac 100644
--- a/excelize.go
+++ b/excelize.go
@@ -98,11 +98,16 @@ func OpenReader(r io.Reader) (*File, error) {
// setDefaultTimeStyle provides a function to set default numbers format for
// time.Time type cell value by given worksheet name, cell coordinates and
// number format code.
-func (f *File) setDefaultTimeStyle(sheet, axis string, format int) {
- if f.GetCellStyle(sheet, axis) == 0 {
+func (f *File) setDefaultTimeStyle(sheet, axis string, format int) error {
+ s, err := f.GetCellStyle(sheet, axis)
+ if err != nil {
+ return err
+ }
+ if s == 0 {
style, _ := f.NewStyle(`{"number_format": ` + strconv.Itoa(format) + `}`)
f.SetCellStyle(sheet, axis, axis, style)
}
+ return err
}
// workSheetReader provides a function to get the pointer to the structure
@@ -218,7 +223,8 @@ func (f *File) GetMergeCells(sheet string) []MergeCell {
for i := range xlsx.MergeCells.Cells {
ref := xlsx.MergeCells.Cells[i].Ref
axis := strings.Split(ref, ":")[0]
- mergeCells = append(mergeCells, []string{ref, f.GetCellValue(sheet, axis)})
+ val, _ := f.GetCellValue(sheet, axis)
+ mergeCells = append(mergeCells, []string{ref, val})
}
}
diff --git a/excelize_test.go b/excelize_test.go
index 9671130..ab5e17b 100644
--- a/excelize_test.go
+++ b/excelize_test.go
@@ -27,7 +27,8 @@ func TestOpenFile(t *testing.T) {
// Test get all the rows in a not exists worksheet.
xlsx.GetRows("Sheet4")
// Test get all the rows in a worksheet.
- rows := xlsx.GetRows("Sheet2")
+ rows, err := xlsx.GetRows("Sheet2")
+ assert.NoError(t, err)
for _, row := range rows {
for _, cell := range row {
t.Log(cell, "\t")
@@ -40,16 +41,13 @@ func TestOpenFile(t *testing.T) {
xlsx.SetCellDefault("Sheet2", "A1", strconv.FormatFloat(float64(-100.1588), 'f', -1, 64))
// Test set cell value with illegal row number.
- assert.Panics(t, func() {
- xlsx.SetCellDefault("Sheet2", "A", strconv.FormatFloat(float64(-100.1588), 'f', -1, 64))
- })
+ assert.EqualError(t, xlsx.SetCellDefault("Sheet2", "A", strconv.FormatFloat(float64(-100.1588), 'f', -1, 64)),
+ `cannot convert cell "A" to coordinates: invalid cell name "A"`)
xlsx.SetCellInt("Sheet2", "A1", 100)
// Test set cell integer value with illegal row number.
- assert.Panics(t, func() {
- xlsx.SetCellInt("Sheet2", "A", 100)
- })
+ assert.EqualError(t, xlsx.SetCellInt("Sheet2", "A", 100), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
xlsx.SetCellStr("Sheet2", "C11", "Knowns")
// Test max characters in a cell.
@@ -62,35 +60,31 @@ func TestOpenFile(t *testing.T) {
xlsx.SetCellStr("Sheet10", "b230", "10")
// Test set cell string value with illegal row number.
- assert.Panics(t, func() {
- xlsx.SetCellStr("Sheet10", "A", "10")
- })
+ assert.EqualError(t, xlsx.SetCellStr("Sheet10", "A", "10"), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
xlsx.SetActiveSheet(2)
// Test get cell formula with given rows number.
- xlsx.GetCellFormula("Sheet1", "B19")
+ _, err = xlsx.GetCellFormula("Sheet1", "B19")
+ assert.NoError(t, err)
// Test get cell formula with illegal worksheet name.
- xlsx.GetCellFormula("Sheet2", "B20")
- xlsx.GetCellFormula("Sheet1", "B20")
+ _, err = xlsx.GetCellFormula("Sheet2", "B20")
+ assert.NoError(t, err)
+ _, err = xlsx.GetCellFormula("Sheet1", "B20")
+ assert.NoError(t, err)
// Test get cell formula with illegal rows number.
- assert.Panics(t, func() {
- xlsx.GetCellFormula("Sheet1", "B")
- })
-
+ _, err = xlsx.GetCellFormula("Sheet1", "B")
+ assert.EqualError(t, err, `cannot convert cell "B" to coordinates: invalid cell name "B"`)
// Test get shared cell formula
xlsx.GetCellFormula("Sheet2", "H11")
xlsx.GetCellFormula("Sheet2", "I11")
getSharedForumula(&xlsxWorksheet{}, "")
// Test read cell value with given illegal rows number.
- assert.Panics(t, func() {
- xlsx.GetCellValue("Sheet2", "a-1")
- })
-
- assert.Panics(t, func() {
- xlsx.GetCellValue("Sheet2", "A")
- })
+ _, err = xlsx.GetCellValue("Sheet2", "a-1")
+ assert.EqualError(t, err, `cannot convert cell "A-1" to coordinates: invalid cell name "A-1"`)
+ _, err = xlsx.GetCellValue("Sheet2", "A")
+ assert.EqualError(t, err, `cannot convert cell "A" to coordinates: invalid cell name "A"`)
// Test read cell value with given lowercase column number.
xlsx.GetCellValue("Sheet2", "a5")
@@ -127,14 +121,14 @@ func TestOpenFile(t *testing.T) {
}
for _, test := range booltest {
xlsx.SetCellValue("Sheet2", "F16", test.value)
- assert.Equal(t, test.expected, xlsx.GetCellValue("Sheet2", "F16"))
+ val, err := xlsx.GetCellValue("Sheet2", "F16")
+ assert.NoError(t, err)
+ assert.Equal(t, test.expected, val)
}
xlsx.SetCellValue("Sheet2", "G2", nil)
- assert.Panics(t, func() {
- xlsx.SetCellValue("Sheet2", "G4", time.Now())
- })
+ assert.EqualError(t, xlsx.SetCellValue("Sheet2", "G4", time.Now()), "only UTC time expected")
xlsx.SetCellValue("Sheet2", "G4", time.Now().UTC())
// 02:46:40
@@ -320,19 +314,15 @@ func TestSetCellHyperLink(t *testing.T) {
t.Log(err)
}
// Test set cell hyperlink in a work sheet already have hyperlinks.
- xlsx.SetCellHyperLink("Sheet1", "B19", "https://github.com/360EntSecGroup-Skylar/excelize", "External")
+ assert.NoError(t, xlsx.SetCellHyperLink("Sheet1", "B19", "https://github.com/360EntSecGroup-Skylar/excelize", "External"))
// Test add first hyperlink in a work sheet.
- xlsx.SetCellHyperLink("Sheet2", "C1", "https://github.com/360EntSecGroup-Skylar/excelize", "External")
+ assert.NoError(t, xlsx.SetCellHyperLink("Sheet2", "C1", "https://github.com/360EntSecGroup-Skylar/excelize", "External"))
// Test add Location hyperlink in a work sheet.
- xlsx.SetCellHyperLink("Sheet2", "D6", "Sheet1!D8", "Location")
+ assert.NoError(t, xlsx.SetCellHyperLink("Sheet2", "D6", "Sheet1!D8", "Location"))
- assert.Panics(t, func() {
- xlsx.SetCellHyperLink("Sheet2", "C3", "Sheet1!D8", "")
- })
+ assert.EqualError(t, xlsx.SetCellHyperLink("Sheet2", "C3", "Sheet1!D8", ""), `invalid link type ""`)
- assert.Panics(t, func() {
- xlsx.SetCellHyperLink("Sheet2", "", "Sheet1!D60", "Location")
- })
+ assert.EqualError(t, xlsx.SetCellHyperLink("Sheet2", "", "Sheet1!D60", "Location"), `invalid cell name ""`)
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestSetCellHyperLink.xlsx")))
}
@@ -343,15 +333,17 @@ func TestGetCellHyperLink(t *testing.T) {
t.FailNow()
}
- assert.Panics(t, func() {
- xlsx.GetCellHyperLink("Sheet1", "")
- })
+ link, target, err := xlsx.GetCellHyperLink("Sheet1", "")
+ assert.EqualError(t, err, `invalid cell name ""`)
- link, target := xlsx.GetCellHyperLink("Sheet1", "A22")
+ link, target, err = xlsx.GetCellHyperLink("Sheet1", "A22")
+ assert.NoError(t, err)
t.Log(link, target)
- link, target = xlsx.GetCellHyperLink("Sheet2", "D6")
+ link, target, err = xlsx.GetCellHyperLink("Sheet2", "D6")
+ assert.NoError(t, err)
t.Log(link, target)
- link, target = xlsx.GetCellHyperLink("Sheet3", "H3")
+ link, target, err = xlsx.GetCellHyperLink("Sheet3", "H3")
+ assert.NoError(t, err)
t.Log(link, target)
}
@@ -365,9 +357,7 @@ func TestSetCellFormula(t *testing.T) {
xlsx.SetCellFormula("Sheet1", "C19", "SUM(Sheet2!D2,Sheet2!D9)")
// Test set cell formula with illegal rows number.
- assert.Panics(t, func() {
- xlsx.SetCellFormula("Sheet1", "C", "SUM(Sheet2!D2,Sheet2!D9)")
- })
+ assert.EqualError(t, xlsx.SetCellFormula("Sheet1", "C", "SUM(Sheet2!D2,Sheet2!D9)"), `cannot convert cell "C" to coordinates: invalid cell name "C"`)
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestSetCellFormula1.xlsx")))
@@ -496,21 +486,16 @@ func TestSetCellStyleAlignment(t *testing.T) {
t.FailNow()
}
- xlsx.SetCellStyle("Sheet1", "A22", "A22", style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet1", "A22", "A22", style))
// Test set cell style with given illegal rows number.
- assert.Panics(t, func() {
- xlsx.SetCellStyle("Sheet1", "A", "A22", style)
- })
-
- assert.Panics(t, func() {
- xlsx.SetCellStyle("Sheet1", "A22", "A", style)
- })
+ assert.EqualError(t, xlsx.SetCellStyle("Sheet1", "A", "A22", style), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
+ assert.EqualError(t, xlsx.SetCellStyle("Sheet1", "A22", "A", style), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
// Test get cell style with given illegal rows number.
- assert.Panics(t, func() {
- xlsx.GetCellStyle("Sheet1", "A")
- })
+ index, err := xlsx.GetCellStyle("Sheet1", "A")
+ assert.Equal(t, 0, index)
+ assert.EqualError(t, err, `cannot convert cell "A" to coordinates: invalid cell name "A"`)
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestSetCellStyleAlignment.xlsx")))
}
@@ -528,19 +513,19 @@ func TestSetCellStyleBorder(t *testing.T) {
if !assert.NoError(t, err) {
t.FailNow()
}
- xlsx.SetCellStyle("Sheet1", "J21", "L25", style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet1", "J21", "L25", style))
style, err = xlsx.NewStyle(`{"border":[{"type":"left","color":"0000FF","style":2},{"type":"top","color":"00FF00","style":3},{"type":"bottom","color":"FFFF00","style":4},{"type":"right","color":"FF0000","style":5},{"type":"diagonalDown","color":"A020F0","style":6},{"type":"diagonalUp","color":"A020F0","style":7}],"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":1}}`)
if !assert.NoError(t, err) {
t.FailNow()
}
- xlsx.SetCellStyle("Sheet1", "M28", "K24", style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet1", "M28", "K24", style))
style, err = xlsx.NewStyle(`{"border":[{"type":"left","color":"0000FF","style":2},{"type":"top","color":"00FF00","style":3},{"type":"bottom","color":"FFFF00","style":4},{"type":"right","color":"FF0000","style":5},{"type":"diagonalDown","color":"A020F0","style":6},{"type":"diagonalUp","color":"A020F0","style":7}],"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":4}}`)
if !assert.NoError(t, err) {
t.FailNow()
}
- xlsx.SetCellStyle("Sheet1", "M28", "K24", style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet1", "M28", "K24", style))
// Test set border and solid style pattern fill for a single cell.
style, err = xlsx.NewStyle(`{"border":[{"type":"left","color":"0000FF","style":8},{"type":"top","color":"00FF00","style":9},{"type":"bottom","color":"FFFF00","style":10},{"type":"right","color":"FF0000","style":11},{"type":"diagonalDown","color":"A020F0","style":12},{"type":"diagonalUp","color":"A020F0","style":13}],"fill":{"type":"pattern","color":["#E0EBF5"],"pattern":1}}`)
@@ -548,7 +533,7 @@ func TestSetCellStyleBorder(t *testing.T) {
t.FailNow()
}
- xlsx.SetCellStyle("Sheet1", "O22", "O22", style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet1", "O22", "O22", style))
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestSetCellStyleBorder.xlsx")))
}
@@ -596,7 +581,7 @@ func TestSetCellStyleNumberFormat(t *testing.T) {
if !assert.NoError(t, err) {
t.FailNow()
}
- xlsx.SetCellStyle("Sheet2", c, c, style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet2", c, c, style))
t.Log(xlsx.GetCellValue("Sheet2", c))
}
}
@@ -605,7 +590,7 @@ func TestSetCellStyleNumberFormat(t *testing.T) {
if !assert.NoError(t, err) {
t.FailNow()
}
- xlsx.SetCellStyle("Sheet2", "L33", "L33", style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet2", "L33", "L33", style))
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestSetCellStyleNumberFormat.xlsx")))
}
@@ -625,13 +610,13 @@ func TestSetCellStyleCurrencyNumberFormat(t *testing.T) {
t.FailNow()
}
- xlsx.SetCellStyle("Sheet1", "A1", "A1", style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet1", "A1", "A1", style))
style, err = xlsx.NewStyle(`{"number_format": 188, "decimal_places": 31, "negred": true}`)
if !assert.NoError(t, err) {
t.FailNow()
}
- xlsx.SetCellStyle("Sheet1", "A2", "A2", style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet1", "A2", "A2", style))
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestSetCellStyleCurrencyNumberFormat.TestBook3.xlsx")))
})
@@ -654,19 +639,19 @@ func TestSetCellStyleCurrencyNumberFormat(t *testing.T) {
t.FailNow()
}
- xlsx.SetCellStyle("Sheet1", "A1", "A1", style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet1", "A1", "A1", style))
style, err = xlsx.NewStyle(`{"number_format": 31, "lang": "ko-kr"}`)
if !assert.NoError(t, err) {
t.FailNow()
}
- xlsx.SetCellStyle("Sheet1", "A2", "A2", style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet1", "A2", "A2", style))
style, err = xlsx.NewStyle(`{"number_format": 71, "lang": "th-th"}`)
if !assert.NoError(t, err) {
t.FailNow()
}
- xlsx.SetCellStyle("Sheet1", "A2", "A2", style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet1", "A2", "A2", style))
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestSetCellStyleCurrencyNumberFormat.TestBook4.xlsx")))
})
@@ -680,12 +665,12 @@ func TestSetCellStyleCustomNumberFormat(t *testing.T) {
if err != nil {
t.Log(err)
}
- xlsx.SetCellStyle("Sheet1", "A1", "A1", style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet1", "A1", "A1", style))
style, err = xlsx.NewStyle(`{"custom_number_format": "[$-380A]dddd\\,\\ dd\" de \"mmmm\" de \"yyyy;@"}`)
if err != nil {
t.Log(err)
}
- xlsx.SetCellStyle("Sheet1", "A2", "A2", style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet1", "A2", "A2", style))
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestSetCellStyleCustomNumberFormat.xlsx")))
}
@@ -702,25 +687,25 @@ func TestSetCellStyleFill(t *testing.T) {
if !assert.NoError(t, err) {
t.FailNow()
}
- xlsx.SetCellStyle("Sheet1", "O23", "O23", style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet1", "O23", "O23", style))
style, err = xlsx.NewStyle(`{"fill":{"type":"gradient","color":["#FFFFFF"],"shading":1}}`)
if !assert.NoError(t, err) {
t.FailNow()
}
- xlsx.SetCellStyle("Sheet1", "O23", "O23", style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet1", "O23", "O23", style))
style, err = xlsx.NewStyle(`{"fill":{"type":"pattern","color":[],"pattern":1}}`)
if !assert.NoError(t, err) {
t.FailNow()
}
- xlsx.SetCellStyle("Sheet1", "O23", "O23", style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet1", "O23", "O23", style))
style, err = xlsx.NewStyle(`{"fill":{"type":"pattern","color":["#E0EBF5"],"pattern":19}}`)
if !assert.NoError(t, err) {
t.FailNow()
}
- xlsx.SetCellStyle("Sheet1", "O23", "O23", style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet1", "O23", "O23", style))
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestSetCellStyleFill.xlsx")))
}
@@ -737,35 +722,35 @@ func TestSetCellStyleFont(t *testing.T) {
t.FailNow()
}
- xlsx.SetCellStyle("Sheet2", "A1", "A1", style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet2", "A1", "A1", style))
style, err = xlsx.NewStyle(`{"font":{"italic":true,"underline":"double"}}`)
if !assert.NoError(t, err) {
t.FailNow()
}
- xlsx.SetCellStyle("Sheet2", "A2", "A2", style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet2", "A2", "A2", style))
style, err = xlsx.NewStyle(`{"font":{"bold":true}}`)
if !assert.NoError(t, err) {
t.FailNow()
}
- xlsx.SetCellStyle("Sheet2", "A3", "A3", style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet2", "A3", "A3", style))
style, err = xlsx.NewStyle(`{"font":{"bold":true,"family":"","size":0,"color":"","underline":""}}`)
if !assert.NoError(t, err) {
t.FailNow()
}
- xlsx.SetCellStyle("Sheet2", "A4", "A4", style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet2", "A4", "A4", style))
style, err = xlsx.NewStyle(`{"font":{"color":"#777777"}}`)
if !assert.NoError(t, err) {
t.FailNow()
}
- xlsx.SetCellStyle("Sheet2", "A5", "A5", style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet2", "A5", "A5", style))
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestSetCellStyleFont.xlsx")))
}
@@ -782,7 +767,7 @@ func TestSetCellStyleProtection(t *testing.T) {
t.FailNow()
}
- xlsx.SetCellStyle("Sheet2", "A6", "A6", style)
+ assert.NoError(t, xlsx.SetCellStyle("Sheet2", "A6", "A6", style))
err = xlsx.SaveAs(filepath.Join("test", "TestSetCellStyleProtection.xlsx"))
if !assert.NoError(t, err) {
t.FailNow()
@@ -818,7 +803,8 @@ func TestGetPicture(t *testing.T) {
t.FailNow()
}
- file, raw := xlsx.GetPicture("Sheet1", "F21")
+ file, raw, err := xlsx.GetPicture("Sheet1", "F21")
+ assert.NoError(t, err)
if !assert.NotEmpty(t, filepath.Join("test", file)) || !assert.NotEmpty(t, raw) ||
!assert.NoError(t, ioutil.WriteFile(filepath.Join("test", file), raw, 0644)) {
@@ -826,12 +812,14 @@ func TestGetPicture(t *testing.T) {
}
// Try to get picture from a worksheet that doesn't contain any images.
- file, raw = xlsx.GetPicture("Sheet3", "I9")
+ file, raw, err = xlsx.GetPicture("Sheet3", "I9")
+ assert.NoError(t, err)
assert.Empty(t, file)
assert.Empty(t, raw)
// Try to get picture from a cell that doesn't contain an image.
- file, raw = xlsx.GetPicture("Sheet2", "A2")
+ file, raw, err = xlsx.GetPicture("Sheet2", "A2")
+ assert.NoError(t, err)
assert.Empty(t, file)
assert.Empty(t, raw)
@@ -850,7 +838,8 @@ func TestGetPicture(t *testing.T) {
t.FailNow()
}
- file, raw = xlsx.GetPicture("Sheet1", "F21")
+ file, raw, err = xlsx.GetPicture("Sheet1", "F21")
+ assert.NoError(t, err)
if !assert.NotEmpty(t, filepath.Join("test", file)) || !assert.NotEmpty(t, raw) ||
!assert.NoError(t, ioutil.WriteFile(filepath.Join("test", file), raw, 0644)) {
@@ -858,7 +847,8 @@ func TestGetPicture(t *testing.T) {
}
// Try to get picture from a local storage file that doesn't contain an image.
- file, raw = xlsx.GetPicture("Sheet1", "F22")
+ file, raw, err = xlsx.GetPicture("Sheet1", "F22")
+ assert.NoError(t, err)
assert.Empty(t, file)
assert.Empty(t, raw)
}
@@ -913,7 +903,9 @@ func TestCopySheet(t *testing.T) {
}
xlsx.SetCellValue("Sheet4", "F1", "Hello")
- assert.NotEqual(t, "Hello", xlsx.GetCellValue("Sheet1", "F1"))
+ val, err := xlsx.GetCellValue("Sheet1", "F1")
+ assert.NoError(t, err)
+ assert.NotEqual(t, "Hello", val)
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestCopySheet.xlsx")))
}
@@ -1101,7 +1093,7 @@ func TestInsertCol(t *testing.T) {
t.FailNow()
}
- xlsx.InsertCol(sheet1, "A")
+ assert.NoError(t, xlsx.InsertCol(sheet1, "A"))
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestInsertCol.xlsx")))
}
@@ -1118,8 +1110,8 @@ func TestRemoveCol(t *testing.T) {
xlsx.MergeCell(sheet1, "A1", "B1")
xlsx.MergeCell(sheet1, "A2", "B2")
- xlsx.RemoveCol(sheet1, "A")
- xlsx.RemoveCol(sheet1, "A")
+ assert.NoError(t, xlsx.RemoveCol(sheet1, "A"))
+ assert.NoError(t, xlsx.RemoveCol(sheet1, "A"))
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestRemoveCol.xlsx")))
}
@@ -1242,18 +1234,11 @@ func TestSetSheetRow(t *testing.T) {
xlsx.SetSheetRow("Sheet1", "B27", &[]interface{}{"cell", nil, int32(42), float64(42), time.Now().UTC()})
- assert.Panics(t, func() {
- xlsx.SetSheetRow("Sheet1", "", &[]interface{}{"cell", nil, 2})
- })
-
- assert.Panics(t, func() {
- xlsx.SetSheetRow("Sheet1", "B27", []interface{}{})
- })
-
- assert.Panics(t, func() {
- xlsx.SetSheetRow("Sheet1", "B27", &xlsx)
- })
+ assert.EqualError(t, xlsx.SetSheetRow("Sheet1", "", &[]interface{}{"cell", nil, 2}),
+ `cannot convert cell "" to coordinates: invalid cell name ""`)
+ assert.EqualError(t, xlsx.SetSheetRow("Sheet1", "B27", []interface{}{}), `pointer to slice expected`)
+ assert.EqualError(t, xlsx.SetSheetRow("Sheet1", "B27", &xlsx), `pointer to slice expected`)
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestSetSheetRow.xlsx")))
}
@@ -1267,16 +1252,15 @@ func TestOutlineLevel(t *testing.T) {
xlsx.SetColOutlineLevel("Sheet2", "B", 2)
xlsx.SetRowOutlineLevel("Sheet1", 2, 250)
- assert.Panics(t, func() {
- xlsx.SetRowOutlineLevel("Sheet1", 0, 1)
- })
+ assert.EqualError(t, xlsx.SetRowOutlineLevel("Sheet1", 0, 1), "invalid row number 0")
+ level, err := xlsx.GetRowOutlineLevel("Sheet1", 2)
+ assert.NoError(t, err)
+ assert.Equal(t, uint8(250), level)
- assert.Equal(t, uint8(250), xlsx.GetRowOutlineLevel("Sheet1", 2))
+ _, err = xlsx.GetRowOutlineLevel("Sheet1", 0)
+ assert.EqualError(t, err, `invalid row number 0`)
- assert.Panics(t, func() {
- xlsx.GetRowOutlineLevel("Sheet1", 0)
- })
- err := xlsx.SaveAs(filepath.Join("test", "TestOutlineLevel.xlsx"))
+ err = xlsx.SaveAs(filepath.Join("test", "TestOutlineLevel.xlsx"))
if !assert.NoError(t, err) {
t.FailNow()
}
@@ -1418,7 +1402,7 @@ func prepareTestBook4() (*File, error) {
func fillCells(xlsx *File, sheet string, colCount, rowCount int) {
for col := 1; col <= colCount; col++ {
for row := 1; row <= rowCount; row++ {
- cell := MustCoordinatesToCellName(col, row)
+ cell, _ := CoordinatesToCellName(col, row)
xlsx.SetCellStr(sheet, cell, cell)
}
}
diff --git a/lib.go b/lib.go
index 809a16b..ad4f79a 100644
--- a/lib.go
+++ b/lib.go
@@ -135,22 +135,6 @@ func ColumnNameToNumber(name string) (int, error) {
return col, nil
}
-// MustColumnNameToNumber provides a function to convert Excel sheet column
-// name to int. Column name case insencitive.
-// Function returns error if column name incorrect.
-//
-// Example:
-//
-// excelize.MustColumnNameToNumber("AK") // returns 37
-//
-func MustColumnNameToNumber(name string) int {
- n, err := ColumnNameToNumber(name)
- if err != nil {
- panic(err)
- }
- return n
-}
-
// ColumnNumberToName provides a function to convert integer
// to Excel sheet column title.
//
@@ -174,8 +158,9 @@ func ColumnNumberToName(num int) (string, error) {
// to [X, Y] coordinates or retrusn an error.
//
// Example:
-// CellCoordinates("A1") // returns 1, 1, nil
-// CellCoordinates("Z3") // returns 26, 3, nil
+//
+// CellCoordinates("A1") // returns 1, 1, nil
+// CellCoordinates("Z3") // returns 26, 3, nil
//
func CellNameToCoordinates(cell string) (int, int, error) {
const msg = "cannot convert cell %q to coordinates: %v"
@@ -193,25 +178,12 @@ func CellNameToCoordinates(cell string) (int, int, error) {
return col, row, nil
}
-// MustCellNameToCoordinates converts alpha-numeric cell name
-// to [X, Y] coordinates or panics.
+// CoordinatesToCellName converts [X, Y] coordinates to alpha-numeric cell
+// name or returns an error.
//
// Example:
-// MustCellNameToCoordinates("A1") // returns 1, 1
-// MustCellNameToCoordinates("Z3") // returns 26, 3
//
-func MustCellNameToCoordinates(cell string) (int, int) {
- c, r, err := CellNameToCoordinates(cell)
- if err != nil {
- panic(err)
- }
- return c, r
-}
-
-// CoordinatesToCellName converts [X, Y] coordinates to alpha-numeric cell name or returns an error.
-//
-// Example:
-// CoordinatesToCellName(1, 1) // returns "A1", nil
+// CoordinatesToCellName(1, 1) // returns "A1", nil
//
func CoordinatesToCellName(col, row int) (string, error) {
if col < 1 || row < 1 {
@@ -224,19 +196,6 @@ func CoordinatesToCellName(col, row int) (string, error) {
return fmt.Sprintf("%s%d", colname, row), nil
}
-// MustCoordinatesToCellName converts [X, Y] coordinates to alpha-numeric cell name or panics.
-//
-// Example:
-// MustCoordinatesToCellName(1, 1) // returns "A1"
-//
-func MustCoordinatesToCellName(col, row int) string {
- n, err := CoordinatesToCellName(col, row)
- if err != nil {
- panic(err)
- }
- return n
-}
-
// boolPtr returns a pointer to a bool with the given value.
func boolPtr(b bool) *bool { return &b }
diff --git a/lib_test.go b/lib_test.go
index 4c19f73..1c30c0e 100644
--- a/lib_test.go
+++ b/lib_test.go
@@ -71,9 +71,6 @@ func TestColumnNameToNumber_Error(t *testing.T) {
if assert.Errorf(t, err, msg, col.Name) {
assert.Equalf(t, col.Num, out, msg, col.Name)
}
- assert.Panicsf(t, func() {
- MustColumnNameToNumber(col.Name)
- }, msg, col.Name)
}
}
@@ -174,9 +171,6 @@ func TestCellNameToCoordinates_Error(t *testing.T) {
assert.Equalf(t, -1, c, msg, cell)
assert.Equalf(t, -1, r, msg, cell)
}
- assert.Panicsf(t, func() {
- MustCellNameToCoordinates(cell)
- }, msg, cell)
}
}
@@ -199,9 +193,6 @@ func TestCoordinatesToCellName_Error(t *testing.T) {
if assert.Errorf(t, err, msg, col, row) {
assert.Equalf(t, "", cell, msg, col, row)
}
- assert.Panicsf(t, func() {
- MustCoordinatesToCellName(col, row)
- }, msg, col, row)
}
for _, col := range invalidIndexes {
diff --git a/picture.go b/picture.go
index d78bcdf..9a9ff09 100644
--- a/picture.go
+++ b/picture.go
@@ -162,7 +162,10 @@ func (f *File) AddPictureFromBytes(sheet, cell, format, name, extension string,
}
drawingHyperlinkRID = f.addDrawingRelationships(drawingID, SourceRelationshipHyperLink, formatSet.Hyperlink, hyperlinkType)
}
- f.addDrawingPicture(sheet, drawingXML, cell, name, img.Width, img.Height, drawingRID, drawingHyperlinkRID, formatSet)
+ err = f.addDrawingPicture(sheet, drawingXML, cell, name, img.Width, img.Height, drawingRID, drawingHyperlinkRID, formatSet)
+ if err != nil {
+ return err
+ }
f.addMedia(file, ext)
f.addContentTypePart(drawingID, "drawings")
return err
@@ -270,8 +273,11 @@ func (f *File) countDrawings() int {
// addDrawingPicture provides a function to add picture by given sheet,
// drawingXML, cell, file name, width, height relationship index and format
// sets.
-func (f *File) addDrawingPicture(sheet, drawingXML, cell, file string, width, height, rID, hyperlinkRID int, formatSet *formatPicture) {
- col, row := MustCellNameToCoordinates(cell)
+func (f *File) addDrawingPicture(sheet, drawingXML, cell, file string, width, height, rID, hyperlinkRID int, formatSet *formatPicture) error {
+ col, row, err := CellNameToCoordinates(cell)
+ if err != nil {
+ return err
+ }
width = int(float64(width) * formatSet.XScale)
height = int(float64(height) * formatSet.YScale)
col--
@@ -315,6 +321,7 @@ func (f *File) addDrawingPicture(sheet, drawingXML, cell, file string, width, he
}
content.TwoCellAnchor = append(content.TwoCellAnchor, &twoCellAnchor)
f.Drawings[drawingXML] = content
+ return err
}
// addDrawingRelationships provides a function to add image part relationships
@@ -468,7 +475,7 @@ func (f *File) getSheetRelationshipsTargetByID(sheet, rID string) string {
// fmt.Println(err)
// return
// }
-// file, raw := xlsx.GetPicture("Sheet1", "A2")
+// file, raw, err := xlsx.GetPicture("Sheet1", "A2")
// if file == "" {
// return
// }
@@ -477,13 +484,16 @@ func (f *File) getSheetRelationshipsTargetByID(sheet, rID string) string {
// fmt.Println(err)
// }
//
-func (f *File) GetPicture(sheet, cell string) (string, []byte) {
- col, row := MustCellNameToCoordinates(cell)
+func (f *File) GetPicture(sheet, cell string) (string, []byte, error) {
+ col, row, err := CellNameToCoordinates(cell)
+ if err != nil {
+ return "", []byte{}, err
+ }
col--
row--
xlsx := f.workSheetReader(sheet)
if xlsx.Drawing == nil {
- return "", []byte{}
+ return "", []byte{}, err
}
target := f.getSheetRelationshipsTargetByID(sheet, xlsx.Drawing.RID)
@@ -503,7 +513,7 @@ func (f *File) GetPicture(sheet, cell string) (string, []byte) {
if ok {
return filepath.Base(xlsxWorkbookRelation.Target),
[]byte(f.XLSX[strings.Replace(xlsxWorkbookRelation.Target,
- "..", "xl", -1)])
+ "..", "xl", -1)]), err
}
}
}
@@ -511,7 +521,7 @@ func (f *File) GetPicture(sheet, cell string) (string, []byte) {
_, ok := f.XLSX[drawingXML]
if !ok {
- return "", nil
+ return "", nil, err
}
decodeWsDr := decodeWsDr{}
_ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML(drawingXML)), &decodeWsDr)
@@ -523,12 +533,12 @@ func (f *File) GetPicture(sheet, cell string) (string, []byte) {
xlsxWorkbookRelation := f.getDrawingRelationships(drawingRelationships, decodeTwoCellAnchor.Pic.BlipFill.Blip.Embed)
_, ok := supportImageTypes[filepath.Ext(xlsxWorkbookRelation.Target)]
if ok {
- return filepath.Base(xlsxWorkbookRelation.Target), []byte(f.XLSX[strings.Replace(xlsxWorkbookRelation.Target, "..", "xl", -1)])
+ return filepath.Base(xlsxWorkbookRelation.Target), []byte(f.XLSX[strings.Replace(xlsxWorkbookRelation.Target, "..", "xl", -1)]), err
}
}
}
}
- return "", []byte{}
+ return "", []byte{}, err
}
// getDrawingRelationships provides a function to get drawing relationships
diff --git a/picture_test.go b/picture_test.go
index 97d3cd9..8c8d2e4 100644
--- a/picture_test.go
+++ b/picture_test.go
@@ -4,17 +4,18 @@ import (
"fmt"
_ "image/png"
"io/ioutil"
+ "path/filepath"
"testing"
)
func BenchmarkAddPictureFromBytes(b *testing.B) {
f := NewFile()
- imgFile, err := ioutil.ReadFile("logo.png")
+ imgFile, err := ioutil.ReadFile(filepath.Join("test", "images", "excel.png"))
if err != nil {
- panic("unable to load image for benchmark")
+ b.Error("unable to load image for benchmark")
}
b.ResetTimer()
for i := 1; i <= b.N; i++ {
- f.AddPictureFromBytes("Sheet1", fmt.Sprint("A", i), "", "logo", ".png", imgFile)
+ f.AddPictureFromBytes("Sheet1", fmt.Sprint("A", i), "", "excel", ".png", imgFile)
}
}
diff --git a/rows.go b/rows.go
index 54c2046..5b8d7d8 100644
--- a/rows.go
+++ b/rows.go
@@ -21,17 +21,18 @@ import (
// GetRows return all the rows in a sheet by given worksheet name (case
// sensitive). For example:
//
-// for _, row := range xlsx.GetRows("Sheet1") {
+// rows, err := xlsx.GetRows("Sheet1")
+// for _, row := range rows {
// for _, colCell := range row {
// fmt.Print(colCell, "\t")
// }
// fmt.Println()
// }
//
-func (f *File) GetRows(sheet string) [][]string {
+func (f *File) GetRows(sheet string) ([][]string, error) {
name, ok := f.sheetMap[trimSheetName(sheet)]
if !ok {
- return nil
+ return nil, nil
}
xlsx := f.workSheetReader(sheet)
@@ -47,7 +48,10 @@ func (f *File) GetRows(sheet string) [][]string {
rowData xlsxRow
)
- rowCount, colCount := f.getTotalRowsCols(name)
+ rowCount, colCount, err := f.getTotalRowsCols(name)
+ if err != nil {
+ return nil, nil
+ }
rows := make([][]string, rowCount)
for i := range rows {
rows[i] = make([]string, colCount+1)
@@ -68,7 +72,10 @@ func (f *File) GetRows(sheet string) [][]string {
_ = decoder.DecodeElement(&rowData, &startElement)
cr := rowData.R - 1
for _, colCell := range rowData.C {
- col, _ := MustCellNameToCoordinates(colCell.R)
+ col, _, err := CellNameToCoordinates(colCell.R)
+ if err != nil {
+ return nil, err
+ }
val, _ := colCell.getValueFrom(f, d)
rows[cr][col-1] = val
if val != "" {
@@ -79,7 +86,7 @@ func (f *File) GetRows(sheet string) [][]string {
default:
}
}
- return rows[:row]
+ return rows[:row], nil
}
// Rows defines an iterator to a sheet
@@ -117,9 +124,9 @@ func (rows *Rows) Error() error {
}
// Columns return the current row's column values
-func (rows *Rows) Columns() []string {
+func (rows *Rows) Columns() ([]string, error) {
if rows.token == nil {
- return []string{}
+ return []string{}, nil
}
startElement := rows.token.(xml.StartElement)
r := xlsxRow{}
@@ -127,11 +134,14 @@ func (rows *Rows) Columns() []string {
d := rows.f.sharedStringsReader()
columns := make([]string, len(r.C))
for _, colCell := range r.C {
- col, _ := MustCellNameToCoordinates(colCell.R)
+ col, _, err := CellNameToCoordinates(colCell.R)
+ if err != nil {
+ return columns, err
+ }
val, _ := colCell.getValueFrom(rows.f, d)
columns[col-1] = val
}
- return columns
+ return columns, nil
}
// ErrSheetNotExist defines an error of sheet is not exist
@@ -147,7 +157,8 @@ func (err ErrSheetNotExist) Error() string {
//
// rows, err := xlsx.Rows("Sheet1")
// for rows.Next() {
-// for _, colCell := range rows.Columns() {
+// row, err := rows.Columns()
+// for _, colCell := range row {
// fmt.Print(colCell, "\t")
// }
// fmt.Println()
@@ -171,7 +182,7 @@ func (f *File) Rows(sheet string) (*Rows, error) {
// getTotalRowsCols provides a function to get total columns and rows in a
// worksheet.
-func (f *File) getTotalRowsCols(name string) (int, int) {
+func (f *File) getTotalRowsCols(name string) (int, int, error) {
decoder := xml.NewDecoder(bytes.NewReader(f.readXML(name)))
var inElement string
var r xlsxRow
@@ -189,7 +200,10 @@ func (f *File) getTotalRowsCols(name string) (int, int) {
_ = decoder.DecodeElement(&r, &startElement)
tr = r.R
for _, colCell := range r.C {
- col, _ := MustCellNameToCoordinates(colCell.R)
+ col, _, err := CellNameToCoordinates(colCell.R)
+ if err != nil {
+ return tr, tc, err
+ }
if col > tc {
tc = col
}
@@ -198,17 +212,17 @@ func (f *File) getTotalRowsCols(name string) (int, int) {
default:
}
}
- return tr, tc
+ return tr, tc, nil
}
// SetRowHeight provides a function to set the height of a single row. For
// example, set the height of the first row in Sheet1:
//
-// xlsx.SetRowHeight("Sheet1", 1, 50)
+// err := xlsx.SetRowHeight("Sheet1", 1, 50)
//
-func (f *File) SetRowHeight(sheet string, row int, height float64) {
+func (f *File) SetRowHeight(sheet string, row int, height float64) error {
if row < 1 {
- panic(newInvalidRowNumberError(row)) // Fail fast to avoid possible future side effects!
+ return newInvalidRowNumberError(row)
}
xlsx := f.workSheetReader(sheet)
@@ -218,6 +232,7 @@ func (f *File) SetRowHeight(sheet string, row int, height float64) {
rowIdx := row - 1
xlsx.SheetData.Row[rowIdx].Ht = height
xlsx.SheetData.Row[rowIdx].CustomHeight = true
+ return nil
}
// getRowHeight provides a function to get row height in pixels by given sheet
@@ -236,24 +251,24 @@ func (f *File) getRowHeight(sheet string, row int) int {
// GetRowHeight provides a function to get row height by given worksheet name
// and row index. For example, get the height of the first row in Sheet1:
//
-// xlsx.GetRowHeight("Sheet1", 1)
+// height, err := xlsx.GetRowHeight("Sheet1", 1)
//
-func (f *File) GetRowHeight(sheet string, row int) float64 {
+func (f *File) GetRowHeight(sheet string, row int) (float64, error) {
if row < 1 {
- panic(newInvalidRowNumberError(row)) // Fail fast to avoid possible future side effects!
+ return defaultRowHeightPixels, newInvalidRowNumberError(row)
}
xlsx := f.workSheetReader(sheet)
if row > len(xlsx.SheetData.Row) {
- return defaultRowHeightPixels // it will be better to use 0, but we take care with BC
+ return defaultRowHeightPixels, nil // it will be better to use 0, but we take care with BC
}
for _, v := range xlsx.SheetData.Row {
if v.R == row && v.Ht != 0 {
- return v.Ht
+ return v.Ht, nil
}
}
// Optimisation for when the row heights haven't changed.
- return defaultRowHeightPixels
+ return defaultRowHeightPixels, nil
}
// sharedStringsReader provides a function to get the pointer to the structure
@@ -299,138 +314,140 @@ func (xlsx *xlsxC) getValueFrom(f *File, d *xlsxSST) (string, error) {
// SetRowVisible provides a function to set visible of a single row by given
// worksheet name and Excel row number. For example, hide row 2 in Sheet1:
//
-// xlsx.SetRowVisible("Sheet1", 2, false)
+// err := xlsx.SetRowVisible("Sheet1", 2, false)
//
-func (f *File) SetRowVisible(sheet string, row int, visible bool) {
+func (f *File) SetRowVisible(sheet string, row int, visible bool) error {
if row < 1 {
- panic(newInvalidRowNumberError(row)) // Fail fast to avoid possible future side effects!
+ return newInvalidRowNumberError(row)
}
xlsx := f.workSheetReader(sheet)
prepareSheetXML(xlsx, 0, row)
xlsx.SheetData.Row[row-1].Hidden = !visible
+ return nil
}
// GetRowVisible provides a function to get visible of a single row by given
// worksheet name and Excel row number. For example, get visible state of row
// 2 in Sheet1:
//
-// xlsx.GetRowVisible("Sheet1", 2)
+// visible, err := xlsx.GetRowVisible("Sheet1", 2)
//
-func (f *File) GetRowVisible(sheet string, row int) bool {
+func (f *File) GetRowVisible(sheet string, row int) (bool, error) {
if row < 1 {
- panic(newInvalidRowNumberError(row)) // Fail fast to avoid possible future side effects!
+ return false, newInvalidRowNumberError(row)
}
xlsx := f.workSheetReader(sheet)
if row > len(xlsx.SheetData.Row) {
- return false
+ return false, nil
}
- return !xlsx.SheetData.Row[row-1].Hidden
+ return !xlsx.SheetData.Row[row-1].Hidden, nil
}
// SetRowOutlineLevel provides a function to set outline level number of a
// single row by given worksheet name and Excel row number. For example,
// outline row 2 in Sheet1 to level 1:
//
-// xlsx.SetRowOutlineLevel("Sheet1", 2, 1)
+// err := xlsx.SetRowOutlineLevel("Sheet1", 2, 1)
//
-func (f *File) SetRowOutlineLevel(sheet string, row int, level uint8) {
+func (f *File) SetRowOutlineLevel(sheet string, row int, level uint8) error {
if row < 1 {
- panic(newInvalidRowNumberError(row)) // Fail fast to avoid possible future side effects!
+ return newInvalidRowNumberError(row)
}
xlsx := f.workSheetReader(sheet)
prepareSheetXML(xlsx, 0, row)
xlsx.SheetData.Row[row-1].OutlineLevel = level
+ return nil
}
// GetRowOutlineLevel provides a function to get outline level number of a
// single row by given worksheet name and Excel row number. For example, get
// outline number of row 2 in Sheet1:
//
-// xlsx.GetRowOutlineLevel("Sheet1", 2)
+// level, err := xlsx.GetRowOutlineLevel("Sheet1", 2)
//
-func (f *File) GetRowOutlineLevel(sheet string, row int) uint8 {
+func (f *File) GetRowOutlineLevel(sheet string, row int) (uint8, error) {
if row < 1 {
- panic(newInvalidRowNumberError(row)) // Fail fast to avoid possible future side effects!
+ return 0, newInvalidRowNumberError(row)
}
xlsx := f.workSheetReader(sheet)
if row > len(xlsx.SheetData.Row) {
- return 0
+ return 0, nil
}
- return xlsx.SheetData.Row[row-1].OutlineLevel
+ return xlsx.SheetData.Row[row-1].OutlineLevel, nil
}
// RemoveRow provides a function to remove single row by given worksheet name
// and Excel row number. For example, remove row 3 in Sheet1:
//
-// xlsx.RemoveRow("Sheet1", 3)
+// err := xlsx.RemoveRow("Sheet1", 3)
//
// 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
// worksheet, it will cause a file error when you open it. The excelize only
// partially updates these references currently.
-func (f *File) RemoveRow(sheet string, row int) {
+func (f *File) RemoveRow(sheet string, row int) error {
if row < 1 {
- panic(newInvalidRowNumberError(row)) // Fail fast to avoid possible future side effects!
+ return newInvalidRowNumberError(row)
}
xlsx := f.workSheetReader(sheet)
if row > len(xlsx.SheetData.Row) {
- return
+ return nil
}
for rowIdx := range xlsx.SheetData.Row {
if xlsx.SheetData.Row[rowIdx].R == row {
xlsx.SheetData.Row = append(xlsx.SheetData.Row[:rowIdx],
xlsx.SheetData.Row[rowIdx+1:]...)[:len(xlsx.SheetData.Row)-1]
- f.adjustHelper(sheet, rows, row, -1)
- return
+ return f.adjustHelper(sheet, rows, row, -1)
}
}
+ return nil
}
// InsertRow provides a function to insert a new row after given Excel row
// number starting from 1. For example, create a new row before row 3 in
// Sheet1:
//
-// xlsx.InsertRow("Sheet1", 3)
+// err := elsx.InsertRow("Sheet1", 3)
//
-func (f *File) InsertRow(sheet string, row int) {
+func (f *File) InsertRow(sheet string, row int) error {
if row < 1 {
- panic(newInvalidRowNumberError(row)) // Fail fast to avoid possible future side effects!
+ return newInvalidRowNumberError(row)
}
- f.adjustHelper(sheet, rows, row, 1)
+ return f.adjustHelper(sheet, rows, row, 1)
}
// DuplicateRow inserts a copy of specified row (by it Excel row number) below
//
-// xlsx.DuplicateRow("Sheet1", 2)
+// err := xlsx.DuplicateRow("Sheet1", 2)
//
// 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
// worksheet, it will cause a file error when you open it. The excelize only
// partially updates these references currently.
-func (f *File) DuplicateRow(sheet string, row int) {
- f.DuplicateRowTo(sheet, row, row+1)
+func (f *File) DuplicateRow(sheet string, row int) error {
+ return f.DuplicateRowTo(sheet, row, row+1)
}
// DuplicateRowTo inserts a copy of specified row by it Excel number
// to specified row position moving down exists rows after target position
//
-// xlsx.DuplicateRowTo("Sheet1", 2, 7)
+// err := xlsx.DuplicateRowTo("Sheet1", 2, 7)
//
// 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
// worksheet, it will cause a file error when you open it. The excelize only
// partially updates these references currently.
-func (f *File) DuplicateRowTo(sheet string, row, row2 int) {
+func (f *File) DuplicateRowTo(sheet string, row, row2 int) error {
if row < 1 {
- panic(newInvalidRowNumberError(row)) // Fail fast to avoid possible future side effects!
+ return newInvalidRowNumberError(row)
}
xlsx := f.workSheetReader(sheet)
if row > len(xlsx.SheetData.Row) || row2 < 1 || row == row2 {
- return
+ return nil
}
var ok bool
@@ -444,10 +461,12 @@ func (f *File) DuplicateRowTo(sheet string, row, row2 int) {
}
}
if !ok {
- return
+ return nil
}
- f.adjustHelper(sheet, rows, row2, 1)
+ if err := f.adjustHelper(sheet, rows, row2, 1); err != nil {
+ return err
+ }
idx2 := -1
for i, r := range xlsx.SheetData.Row {
@@ -457,7 +476,7 @@ func (f *File) DuplicateRowTo(sheet string, row, row2 int) {
}
}
if idx2 == -1 && len(xlsx.SheetData.Row) >= row2 {
- return
+ return nil
}
rowCopy.C = append(make([]xlsxC, 0, len(rowCopy.C)), rowCopy.C...)
@@ -468,6 +487,7 @@ func (f *File) DuplicateRowTo(sheet string, row, row2 int) {
} else {
xlsx.SheetData.Row = append(xlsx.SheetData.Row, rowCopy)
}
+ return nil
}
// checkRow provides a function to check and fill each column element for all
@@ -494,7 +514,7 @@ func (f *File) DuplicateRowTo(sheet string, row, row2 int) {
//
// Noteice: this method could be very slow for large spreadsheets (more than
// 3000 rows one sheet).
-func checkRow(xlsx *xlsxWorksheet) {
+func checkRow(xlsx *xlsxWorksheet) error {
for rowIdx := range xlsx.SheetData.Row {
rowData := &xlsx.SheetData.Row[rowIdx]
@@ -502,7 +522,10 @@ func checkRow(xlsx *xlsxWorksheet) {
if colCount == 0 {
continue
}
- lastCol, _ := MustCellNameToCoordinates(rowData.C[colCount-1].R)
+ lastCol, _, err := CellNameToCoordinates(rowData.C[colCount-1].R)
+ if err != nil {
+ return err
+ }
if colCount < lastCol {
oldList := rowData.C
@@ -511,18 +534,26 @@ func checkRow(xlsx *xlsxWorksheet) {
rowData.C = xlsx.SheetData.Row[rowIdx].C[:0]
for colIdx := 0; colIdx < lastCol; colIdx++ {
- newlist = append(newlist, xlsxC{R: MustCoordinatesToCellName(colIdx+1, rowIdx+1)})
+ cellName, err := CoordinatesToCellName(colIdx+1, rowIdx+1)
+ if err != nil {
+ return err
+ }
+ newlist = append(newlist, xlsxC{R: cellName})
}
rowData.C = newlist
for colIdx := range oldList {
colData := &oldList[colIdx]
- colNum, _ := MustCellNameToCoordinates(colData.R)
+ colNum, _, err := CellNameToCoordinates(colData.R)
+ if err != nil {
+ return err
+ }
xlsx.SheetData.Row[rowIdx].C[colNum-1] = *colData
}
}
}
+ return nil
}
// convertRowHeightToPixels provides a function to convert the height of a
diff --git a/rows_test.go b/rows_test.go
index 50e26dd..53c0677 100644
--- a/rows_test.go
+++ b/rows_test.go
@@ -23,13 +23,16 @@ func TestRows(t *testing.T) {
collectedRows := make([][]string, 0)
for rows.Next() {
- collectedRows = append(collectedRows, trimSliceSpace(rows.Columns()))
+ columns, err := rows.Columns()
+ assert.NoError(t, err)
+ collectedRows = append(collectedRows, trimSliceSpace(columns))
}
if !assert.NoError(t, rows.Error()) {
t.FailNow()
}
- returnedRows := xlsx.GetRows(sheet2)
+ returnedRows, err := xlsx.GetRows(sheet2)
+ assert.NoError(t, err)
for i := range returnedRows {
returnedRows[i] = trimSliceSpace(returnedRows[i])
}
@@ -54,21 +57,22 @@ func TestRowHeight(t *testing.T) {
xlsx := NewFile()
sheet1 := xlsx.GetSheetName(1)
- assert.Panics(t, func() {
- xlsx.SetRowHeight(sheet1, 0, defaultRowHeightPixels+1.0)
- })
+ assert.EqualError(t, xlsx.SetRowHeight(sheet1, 0, defaultRowHeightPixels+1.0), "invalid row number 0")
- assert.Panics(t, func() {
- xlsx.GetRowHeight("Sheet1", 0)
- })
+ height, err := xlsx.GetRowHeight("Sheet1", 0)
+ assert.EqualError(t, err, "invalid row number 0")
- xlsx.SetRowHeight(sheet1, 1, 111.0)
- assert.Equal(t, 111.0, xlsx.GetRowHeight(sheet1, 1))
+ assert.NoError(t, xlsx.SetRowHeight(sheet1, 1, 111.0))
+ height, err = xlsx.GetRowHeight(sheet1, 1)
+ assert.NoError(t, err)
+ assert.Equal(t, 111.0, height)
- xlsx.SetRowHeight(sheet1, 4, 444.0)
- assert.Equal(t, 444.0, xlsx.GetRowHeight(sheet1, 4))
+ assert.NoError(t, xlsx.SetRowHeight(sheet1, 4, 444.0))
+ height, err = xlsx.GetRowHeight(sheet1, 4)
+ assert.NoError(t, err)
+ assert.Equal(t, 444.0, height)
- err := xlsx.SaveAs(filepath.Join("test", "TestRowHeight.xlsx"))
+ err = xlsx.SaveAs(filepath.Join("test", "TestRowHeight.xlsx"))
if !assert.NoError(t, err) {
t.FailNow()
}
@@ -86,13 +90,11 @@ func TestRowVisibility(t *testing.T) {
xlsx.SetRowVisible("Sheet3", 2, true)
xlsx.GetRowVisible("Sheet3", 2)
- assert.Panics(t, func() {
- xlsx.SetRowVisible("Sheet3", 0, true)
- })
+ assert.EqualError(t, xlsx.SetRowVisible("Sheet3", 0, true), "invalid row number 0")
- assert.Panics(t, func() {
- xlsx.GetRowVisible("Sheet3", 0)
- })
+ visible, err := xlsx.GetRowVisible("Sheet3", 0)
+ assert.Equal(t, false, visible)
+ assert.EqualError(t, err, "invalid row number 0")
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestRowVisibility.xlsx")))
}
@@ -110,27 +112,23 @@ func TestRemoveRow(t *testing.T) {
xlsx.SetCellHyperLink(sheet1, "A5", "https://github.com/360EntSecGroup-Skylar/excelize", "External")
- assert.Panics(t, func() {
- xlsx.RemoveRow(sheet1, -1)
- })
+ assert.EqualError(t, xlsx.RemoveRow(sheet1, -1), "invalid row number -1")
- assert.Panics(t, func() {
- xlsx.RemoveRow(sheet1, 0)
- })
+ assert.EqualError(t, xlsx.RemoveRow(sheet1, 0), "invalid row number 0")
- xlsx.RemoveRow(sheet1, 4)
+ assert.NoError(t, xlsx.RemoveRow(sheet1, 4))
if !assert.Len(t, r.SheetData.Row, rowCount-1) {
t.FailNow()
}
xlsx.MergeCell(sheet1, "B3", "B5")
- xlsx.RemoveRow(sheet1, 2)
+ assert.NoError(t, xlsx.RemoveRow(sheet1, 2))
if !assert.Len(t, r.SheetData.Row, rowCount-2) {
t.FailNow()
}
- xlsx.RemoveRow(sheet1, 4)
+ assert.NoError(t, xlsx.RemoveRow(sheet1, 4))
if !assert.Len(t, r.SheetData.Row, rowCount-3) {
t.FailNow()
}
@@ -140,17 +138,17 @@ func TestRemoveRow(t *testing.T) {
t.FailNow()
}
- xlsx.RemoveRow(sheet1, 1)
+ assert.NoError(t, xlsx.RemoveRow(sheet1, 1))
if !assert.Len(t, r.SheetData.Row, rowCount-4) {
t.FailNow()
}
- xlsx.RemoveRow(sheet1, 2)
+ assert.NoError(t, xlsx.RemoveRow(sheet1, 2))
if !assert.Len(t, r.SheetData.Row, rowCount-5) {
t.FailNow()
}
- xlsx.RemoveRow(sheet1, 1)
+ assert.NoError(t, xlsx.RemoveRow(sheet1, 1))
if !assert.Len(t, r.SheetData.Row, rowCount-6) {
t.FailNow()
}
@@ -171,20 +169,16 @@ func TestInsertRow(t *testing.T) {
xlsx.SetCellHyperLink(sheet1, "A5", "https://github.com/360EntSecGroup-Skylar/excelize", "External")
- assert.Panics(t, func() {
- xlsx.InsertRow(sheet1, -1)
- })
+ assert.EqualError(t, xlsx.InsertRow(sheet1, -1), "invalid row number -1")
- assert.Panics(t, func() {
- xlsx.InsertRow(sheet1, 0)
- })
+ assert.EqualError(t, xlsx.InsertRow(sheet1, 0), "invalid row number 0")
- xlsx.InsertRow(sheet1, 1)
+ assert.NoError(t, xlsx.InsertRow(sheet1, 1))
if !assert.Len(t, r.SheetData.Row, rowCount+1) {
t.FailNow()
}
- xlsx.InsertRow(sheet1, 4)
+ assert.NoError(t, xlsx.InsertRow(sheet1, 4))
if !assert.Len(t, r.SheetData.Row, rowCount+2) {
t.FailNow()
}
@@ -198,11 +192,11 @@ func TestInsertRowInEmptyFile(t *testing.T) {
xlsx := NewFile()
sheet1 := xlsx.GetSheetName(1)
r := xlsx.workSheetReader(sheet1)
- xlsx.InsertRow(sheet1, 1)
+ assert.NoError(t, xlsx.InsertRow(sheet1, 1))
assert.Len(t, r.SheetData.Row, 0)
- xlsx.InsertRow(sheet1, 2)
+ assert.NoError(t, xlsx.InsertRow(sheet1, 2))
assert.Len(t, r.SheetData.Row, 0)
- xlsx.InsertRow(sheet1, 99)
+ assert.NoError(t, xlsx.InsertRow(sheet1, 99))
assert.Len(t, r.SheetData.Row, 0)
assert.NoError(t, xlsx.SaveAs(filepath.Join("test", "TestInsertRowInEmptyFile.xlsx")))
}
@@ -234,7 +228,7 @@ func TestDuplicateRow(t *testing.T) {
xlsx.SetCellStr(sheet, "A1", cells["A1"])
xlsx.SetCellStr(sheet, "B1", cells["B1"])
- xlsx.DuplicateRow(sheet, 1)
+ assert.NoError(t, xlsx.DuplicateRow(sheet, 1))
if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.FromSingleRow_1"))) {
t.FailNow()
}
@@ -243,12 +237,14 @@ func TestDuplicateRow(t *testing.T) {
"A2": cells["A1"], "B2": cells["B1"],
}
for cell, val := range expect {
- if !assert.Equal(t, val, xlsx.GetCellValue(sheet, cell), cell) {
+ v, err := xlsx.GetCellValue(sheet, cell)
+ assert.NoError(t, err)
+ if !assert.Equal(t, val, v, cell) {
t.FailNow()
}
}
- xlsx.DuplicateRow(sheet, 2)
+ assert.NoError(t, xlsx.DuplicateRow(sheet, 2))
if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.FromSingleRow_2"))) {
t.FailNow()
}
@@ -258,7 +254,9 @@ func TestDuplicateRow(t *testing.T) {
"A3": cells["A1"], "B3": cells["B1"],
}
for cell, val := range expect {
- if !assert.Equal(t, val, xlsx.GetCellValue(sheet, cell), cell) {
+ v, err := xlsx.GetCellValue(sheet, cell)
+ assert.NoError(t, err)
+ if !assert.Equal(t, val, v, cell) {
t.FailNow()
}
}
@@ -269,7 +267,7 @@ func TestDuplicateRow(t *testing.T) {
xlsx.SetCellStr(sheet, "A1", cells["A1"])
xlsx.SetCellStr(sheet, "B1", cells["B1"])
- xlsx.DuplicateRow(sheet, 1)
+ assert.NoError(t, xlsx.DuplicateRow(sheet, 1))
xlsx.SetCellStr(sheet, "A2", cells["A2"])
xlsx.SetCellStr(sheet, "B2", cells["B2"])
@@ -282,7 +280,9 @@ func TestDuplicateRow(t *testing.T) {
"A2": cells["A2"], "B2": cells["B2"],
}
for cell, val := range expect {
- if !assert.Equal(t, val, xlsx.GetCellValue(sheet, cell), cell) {
+ v, err := xlsx.GetCellValue(sheet, cell)
+ assert.NoError(t, err)
+ if !assert.Equal(t, val, v, cell) {
t.FailNow()
}
}
@@ -291,7 +291,7 @@ func TestDuplicateRow(t *testing.T) {
t.Run("FirstOfMultipleRows", func(t *testing.T) {
xlsx := newFileWithDefaults()
- xlsx.DuplicateRow(sheet, 1)
+ assert.NoError(t, xlsx.DuplicateRow(sheet, 1))
if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.FirstOfMultipleRows"))) {
t.FailNow()
@@ -303,7 +303,9 @@ func TestDuplicateRow(t *testing.T) {
"A4": cells["A3"], "B4": cells["B3"],
}
for cell, val := range expect {
- if !assert.Equal(t, val, xlsx.GetCellValue(sheet, cell), cell) {
+ v, err := xlsx.GetCellValue(sheet, cell)
+ assert.NoError(t, err)
+ if !assert.Equal(t, val, v, cell) {
t.FailNow()
}
}
@@ -312,26 +314,35 @@ func TestDuplicateRow(t *testing.T) {
t.Run("ZeroWithNoRows", func(t *testing.T) {
xlsx := NewFile()
- assert.Panics(t, func() {
- xlsx.DuplicateRow(sheet, 0)
- })
+ assert.EqualError(t, xlsx.DuplicateRow(sheet, 0), "invalid row number 0")
if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.ZeroWithNoRows"))) {
t.FailNow()
}
- assert.Equal(t, "", xlsx.GetCellValue(sheet, "A1"))
- assert.Equal(t, "", xlsx.GetCellValue(sheet, "B1"))
- assert.Equal(t, "", xlsx.GetCellValue(sheet, "A2"))
- assert.Equal(t, "", xlsx.GetCellValue(sheet, "B2"))
-
+ val, err := xlsx.GetCellValue(sheet, "A1")
+ assert.NoError(t, err)
+ assert.Equal(t, "", val)
+ val, err = xlsx.GetCellValue(sheet, "B1")
+ assert.NoError(t, err)
+ assert.Equal(t, "", val)
+ val, err = xlsx.GetCellValue(sheet, "A2")
+ assert.NoError(t, err)
+ assert.Equal(t, "", val)
+ val, err = xlsx.GetCellValue(sheet, "B2")
+ assert.NoError(t, err)
+ assert.Equal(t, "", val)
+
+ assert.NoError(t, err)
expect := map[string]string{
"A1": "", "B1": "",
"A2": "", "B2": "",
}
for cell, val := range expect {
- if !assert.Equal(t, val, xlsx.GetCellValue(sheet, cell), cell) {
+ v, err := xlsx.GetCellValue(sheet, cell)
+ assert.NoError(t, err)
+ if !assert.Equal(t, val, v, cell) {
t.FailNow()
}
}
@@ -340,7 +351,7 @@ func TestDuplicateRow(t *testing.T) {
t.Run("MiddleRowOfEmptyFile", func(t *testing.T) {
xlsx := NewFile()
- xlsx.DuplicateRow(sheet, 99)
+ assert.NoError(t, xlsx.DuplicateRow(sheet, 99))
if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.MiddleRowOfEmptyFile"))) {
t.FailNow()
@@ -351,7 +362,9 @@ func TestDuplicateRow(t *testing.T) {
"A100": "",
}
for cell, val := range expect {
- if !assert.Equal(t, val, xlsx.GetCellValue(sheet, cell), cell) {
+ v, err := xlsx.GetCellValue(sheet, cell)
+ assert.NoError(t, err)
+ if !assert.Equal(t, val, v, cell) {
t.FailNow()
}
}
@@ -360,7 +373,7 @@ func TestDuplicateRow(t *testing.T) {
t.Run("WithLargeOffsetToMiddleOfData", func(t *testing.T) {
xlsx := newFileWithDefaults()
- xlsx.DuplicateRowTo(sheet, 1, 3)
+ assert.NoError(t, xlsx.DuplicateRowTo(sheet, 1, 3))
if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.WithLargeOffsetToMiddleOfData"))) {
t.FailNow()
@@ -372,7 +385,9 @@ func TestDuplicateRow(t *testing.T) {
"A4": cells["A3"], "B4": cells["B3"],
}
for cell, val := range expect {
- if !assert.Equal(t, val, xlsx.GetCellValue(sheet, cell), cell) {
+ v, err := xlsx.GetCellValue(sheet, cell)
+ assert.NoError(t, err)
+ if !assert.Equal(t, val, v, cell) {
t.FailNow()
}
}
@@ -381,7 +396,7 @@ func TestDuplicateRow(t *testing.T) {
t.Run("WithLargeOffsetToEmptyRows", func(t *testing.T) {
xlsx := newFileWithDefaults()
- xlsx.DuplicateRowTo(sheet, 1, 7)
+ assert.NoError(t, xlsx.DuplicateRowTo(sheet, 1, 7))
if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.WithLargeOffsetToEmptyRows"))) {
t.FailNow()
@@ -393,7 +408,9 @@ func TestDuplicateRow(t *testing.T) {
"A7": cells["A1"], "B7": cells["B1"],
}
for cell, val := range expect {
- if !assert.Equal(t, val, xlsx.GetCellValue(sheet, cell), cell) {
+ v, err := xlsx.GetCellValue(sheet, cell)
+ assert.NoError(t, err)
+ if !assert.Equal(t, val, v, cell) {
t.FailNow()
}
}
@@ -402,7 +419,7 @@ func TestDuplicateRow(t *testing.T) {
t.Run("InsertBefore", func(t *testing.T) {
xlsx := newFileWithDefaults()
- xlsx.DuplicateRowTo(sheet, 2, 1)
+ assert.NoError(t, xlsx.DuplicateRowTo(sheet, 2, 1))
if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.InsertBefore"))) {
t.FailNow()
@@ -415,7 +432,9 @@ func TestDuplicateRow(t *testing.T) {
"A4": cells["A3"], "B4": cells["B3"],
}
for cell, val := range expect {
- if !assert.Equal(t, val, xlsx.GetCellValue(sheet, cell), cell) {
+ v, err := xlsx.GetCellValue(sheet, cell)
+ assert.NoError(t, err)
+ if !assert.Equal(t, val, v, cell) {
t.FailNow()
}
}
@@ -424,7 +443,7 @@ func TestDuplicateRow(t *testing.T) {
t.Run("InsertBeforeWithLargeOffset", func(t *testing.T) {
xlsx := newFileWithDefaults()
- xlsx.DuplicateRowTo(sheet, 3, 1)
+ assert.NoError(t, xlsx.DuplicateRowTo(sheet, 3, 1))
if !assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(outFile, "TestDuplicateRow.InsertBeforeWithLargeOffset"))) {
t.FailNow()
@@ -437,7 +456,9 @@ func TestDuplicateRow(t *testing.T) {
"A4": cells["A3"], "B4": cells["B3"],
}
for cell, val := range expect {
- if !assert.Equal(t, val, xlsx.GetCellValue(sheet, cell)) {
+ v, err := xlsx.GetCellValue(sheet, cell)
+ assert.NoError(t, err)
+ if !assert.Equal(t, val, v) {
t.FailNow()
}
}
@@ -467,12 +488,12 @@ func TestDuplicateRowInvalidRownum(t *testing.T) {
xlsx.SetCellStr(sheet, col, val)
}
- assert.Panics(t, func() {
- xlsx.DuplicateRow(sheet, row)
- })
+ assert.EqualError(t, xlsx.DuplicateRow(sheet, row), fmt.Sprintf("invalid row number %d", row))
for col, val := range cells {
- if !assert.Equal(t, val, xlsx.GetCellValue(sheet, col)) {
+ v, err := xlsx.GetCellValue(sheet, col)
+ assert.NoError(t, err)
+ if !assert.Equal(t, val, v) {
t.FailNow()
}
}
@@ -489,12 +510,12 @@ func TestDuplicateRowInvalidRownum(t *testing.T) {
xlsx.SetCellStr(sheet, col, val)
}
- assert.Panics(t, func() {
- xlsx.DuplicateRowTo(sheet, row1, row2)
- })
+ assert.EqualError(t, xlsx.DuplicateRowTo(sheet, row1, row2), fmt.Sprintf("invalid row number %d", row1))
for col, val := range cells {
- if !assert.Equal(t, val, xlsx.GetCellValue(sheet, col)) {
+ v, err := xlsx.GetCellValue(sheet, col)
+ assert.NoError(t, err)
+ if !assert.Equal(t, val, v) {
t.FailNow()
}
}
diff --git a/shape.go b/shape.go
index c58038c..e6b0456 100644
--- a/shape.go
+++ b/shape.go
@@ -275,15 +275,21 @@ func (f *File) AddShape(sheet, cell, format string) error {
rID := f.addSheetRelationships(sheet, SourceRelationshipDrawingML, sheetRelationshipsDrawingXML, "")
f.addSheetDrawing(sheet, rID)
}
- f.addDrawingShape(sheet, drawingXML, cell, formatSet)
+ err = f.addDrawingShape(sheet, drawingXML, cell, formatSet)
+ if err != nil {
+ return err
+ }
f.addContentTypePart(drawingID, "drawings")
return err
}
// addDrawingShape provides a function to add preset geometry by given sheet,
// drawingXMLand format sets.
-func (f *File) addDrawingShape(sheet, drawingXML, cell string, formatSet *formatShape) {
- fromCol, fromRow := MustCellNameToCoordinates(cell)
+func (f *File) addDrawingShape(sheet, drawingXML, cell string, formatSet *formatShape) error {
+ fromCol, fromRow, err := CellNameToCoordinates(cell)
+ if err != nil {
+ return err
+ }
colIdx := fromCol - 1
rowIdx := fromRow - 1
@@ -421,6 +427,7 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, formatSet *format
}
content.TwoCellAnchor = append(content.TwoCellAnchor, &twoCellAnchor)
f.Drawings[drawingXML] = content
+ return err
}
// setShapeRef provides a function to set color with hex model by given actual
diff --git a/sheet.go b/sheet.go
index ce1f241..ec4df77 100644
--- a/sheet.go
+++ b/sheet.go
@@ -275,11 +275,11 @@ func (f *File) GetActiveSheetIndex() int {
return 0
}
-// 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
-// problem formula error or reference missing.
+// 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 problem formula error or reference missing.
func (f *File) SetSheetName(oldName, newName string) {
oldName = trimSheetName(oldName)
newName = trimSheetName(newName)
@@ -665,14 +665,14 @@ func (f *File) GetSheetVisible(name string) bool {
//
// An example of search the coordinates of the value of "100" on Sheet1:
//
-// xlsx.SearchSheet("Sheet1", "100")
+// result, err := xlsx.SearchSheet("Sheet1", "100")
//
// An example of search the coordinates where the numerical value in the range
// of "0-9" of Sheet1 is described:
//
-// xlsx.SearchSheet("Sheet1", "[0-9]", true)
+// result, err := xlsx.SearchSheet("Sheet1", "[0-9]", true)
//
-func (f *File) SearchSheet(sheet, value string, reg ...bool) []string {
+func (f *File) SearchSheet(sheet, value string, reg ...bool) ([]string, error) {
var regSearch bool
for _, r := range reg {
regSearch = r
@@ -683,7 +683,7 @@ func (f *File) SearchSheet(sheet, value string, reg ...bool) []string {
)
name, ok := f.sheetMap[trimSheetName(sheet)]
if !ok {
- return result
+ return result, nil
}
if xlsx != nil {
output, _ := xml.Marshal(f.Sheet[name])
@@ -718,14 +718,21 @@ func (f *File) SearchSheet(sheet, value string, reg ...bool) []string {
}
}
- cellCol, _ := MustCellNameToCoordinates(colCell.R)
- result = append(result, MustCoordinatesToCellName(cellCol, r.R))
+ cellCol, _, err := CellNameToCoordinates(colCell.R)
+ if err != nil {
+ return result, err
+ }
+ cellName, err := CoordinatesToCellName(cellCol, r.R)
+ if err != nil {
+ return result, err
+ }
+ result = append(result, cellName)
}
}
default:
}
}
- return result
+ return result, nil
}
// ProtectSheet provides a function to prevent other users from accidentally
diff --git a/styles.go b/styles.go
index 50b30b8..1cc025c 100644
--- a/styles.go
+++ b/styles.go
@@ -1880,8 +1880,8 @@ func parseFormatStyleSet(style string) (*formatStyle, error) {
//
// xlsx := excelize.NewFile()
// xlsx.SetCellValue("Sheet1", "A6", 42920.5)
-// style, _ := xlsx.NewStyle(`{"custom_number_format": "[$-380A]dddd\\,\\ dd\" de \"mmmm\" de \"yyyy;@"}`)
-// xlsx.SetCellStyle("Sheet1", "A6", "A6", style)
+// style, err := xlsx.NewStyle(`{"custom_number_format": "[$-380A]dddd\\,\\ dd\" de \"mmmm\" de \"yyyy;@"}`)
+// err = xlsx.SetCellStyle("Sheet1", "A6", "A6", style)
//
// Cell Sheet1!A6 in the Excel Application: martes, 04 de Julio de 2017
//
@@ -2265,10 +2265,13 @@ 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 {
+func (f *File) GetCellStyle(sheet, axis string) (int, error) {
xlsx := f.workSheetReader(sheet)
- cellData, col, _ := f.prepareCell(xlsx, sheet, axis)
- return f.prepareCellStyle(xlsx, col, cellData.S)
+ cellData, col, _, err := f.prepareCell(xlsx, sheet, axis)
+ if err != nil {
+ return 0, err
+ }
+ return f.prepareCellStyle(xlsx, col, cellData.S), err
}
// SetCellStyle provides a function to add style attribute for cells by given
@@ -2282,7 +2285,7 @@ func (f *File) GetCellStyle(sheet, axis string) int {
// if err != nil {
// fmt.Println(err)
// }
-// xlsx.SetCellStyle("Sheet1", "H9", "H9", style)
+// err = xlsx.SetCellStyle("Sheet1", "H9", "H9", style)
//
// Set gradient fill with vertical variants shading styles for cell H9 on
// Sheet1:
@@ -2291,7 +2294,7 @@ func (f *File) GetCellStyle(sheet, axis string) int {
// if err != nil {
// fmt.Println(err)
// }
-// xlsx.SetCellStyle("Sheet1", "H9", "H9", style)
+// err = xlsx.SetCellStyle("Sheet1", "H9", "H9", style)
//
// Set solid style pattern fill for cell H9 on Sheet1:
//
@@ -2299,7 +2302,7 @@ func (f *File) GetCellStyle(sheet, axis string) int {
// if err != nil {
// fmt.Println(err)
// }
-// xlsx.SetCellStyle("Sheet1", "H9", "H9", style)
+// err = xlsx.SetCellStyle("Sheet1", "H9", "H9", style)
//
// Set alignment style for cell H9 on Sheet1:
//
@@ -2307,7 +2310,7 @@ func (f *File) GetCellStyle(sheet, axis string) int {
// if err != nil {
// fmt.Println(err)
// }
-// xlsx.SetCellStyle("Sheet1", "H9", "H9", style)
+// err = xlsx.SetCellStyle("Sheet1", "H9", "H9", style)
//
// Dates and times in Excel are represented by real numbers, for example "Apr 7
// 2017 12:00 PM" is represented by the number 42920.5. Set date and time format
@@ -2318,7 +2321,7 @@ func (f *File) GetCellStyle(sheet, axis string) int {
// if err != nil {
// fmt.Println(err)
// }
-// xlsx.SetCellStyle("Sheet1", "H9", "H9", style)
+// err = xlsx.SetCellStyle("Sheet1", "H9", "H9", style)
//
// Set font style for cell H9 on Sheet1:
//
@@ -2326,7 +2329,7 @@ func (f *File) GetCellStyle(sheet, axis string) int {
// if err != nil {
// fmt.Println(err)
// }
-// xlsx.SetCellStyle("Sheet1", "H9", "H9", style)
+// err = xlsx.SetCellStyle("Sheet1", "H9", "H9", style)
//
// Hide and lock for cell H9 on Sheet1:
//
@@ -2334,17 +2337,17 @@ func (f *File) GetCellStyle(sheet, axis string) int {
// if err != nil {
// fmt.Println(err)
// }
-// xlsx.SetCellStyle("Sheet1", "H9", "H9", style)
+// err = xlsx.SetCellStyle("Sheet1", "H9", "H9", style)
//
-func (f *File) SetCellStyle(sheet, hcell, vcell string, styleID int) {
+func (f *File) SetCellStyle(sheet, hcell, vcell string, styleID int) error {
hcol, hrow, err := CellNameToCoordinates(hcell)
if err != nil {
- panic(err)
+ return err
}
vcol, vrow, err := CellNameToCoordinates(vcell)
if err != nil {
- panic(err)
+ return err
}
// Normalize the coordinate area, such correct C1:B3 to B1:C3.
@@ -2370,6 +2373,7 @@ func (f *File) SetCellStyle(sheet, hcell, vcell string, styleID int) {
xlsx.SheetData.Row[r].C[k].S = styleID
}
}
+ return nil
}
// SetConditionalFormat provides a function to create conditional formatting
diff --git a/table.go b/table.go
index e33264b..2ed8654 100644
--- a/table.go
+++ b/table.go
@@ -33,11 +33,11 @@ func parseFormatTableSet(formatSet string) (*formatTable, error) {
// name, coordinate area and format set. For example, create a table of A1:D5
// on Sheet1:
//
-// xlsx.AddTable("Sheet1", "A1", "D5", ``)
+// err := xlsx.AddTable("Sheet1", "A1", "D5", ``)
//
// Create a table of F2:H6 on Sheet2 with format set:
//
-// xlsx.AddTable("Sheet2", "F2", "H6", `{"table_name":"table","table_style":"TableStyleMedium2", "show_first_column":true,"show_last_column":true,"show_row_stripes":false,"show_column_stripes":true}`)
+// err := xlsx.AddTable("Sheet2", "F2", "H6", `{"table_name":"table","table_style":"TableStyleMedium2", "show_first_column":true,"show_last_column":true,"show_row_stripes":false,"show_column_stripes":true}`)
//
// Note that the table at least two lines include string type header. Multiple
// tables coordinate areas can't have an intersection.
@@ -56,8 +56,14 @@ func (f *File) AddTable(sheet, hcell, vcell, format string) error {
return err
}
// Coordinate conversion, convert C1:B3 to 2,0,1,2.
- hcol, hrow := MustCellNameToCoordinates(hcell)
- vcol, vrow := MustCellNameToCoordinates(vcell)
+ hcol, hrow, err := CellNameToCoordinates(hcell)
+ if err != nil {
+ return err
+ }
+ vcol, vrow, err := CellNameToCoordinates(vcell)
+ if err != nil {
+ return err
+ }
if vcol < hcol {
vcol, hcol = hcol, vcol
@@ -73,7 +79,10 @@ func (f *File) AddTable(sheet, hcell, vcell, format string) error {
// Add first table for given sheet.
rID := f.addSheetRelationships(sheet, SourceRelationshipTable, sheetRelationshipsTableXML, "")
f.addSheetTable(sheet, rID)
- f.addTable(sheet, tableXML, hcol, hrow, vcol, vrow, tableID, formatSet)
+ err = f.addTable(sheet, tableXML, hcol, hrow, vcol, vrow, tableID, formatSet)
+ if err != nil {
+ return err
+ }
f.addContentTypePart(tableID, "table")
return err
}
@@ -106,24 +115,33 @@ func (f *File) addSheetTable(sheet string, rID int) {
// addTable provides a function to add table by given worksheet name,
// coordinate area and format set.
-func (f *File) addTable(sheet, tableXML string, hcol, hrow, vcol, vrow, i int, formatSet *formatTable) {
+func (f *File) addTable(sheet, tableXML string, hcol, hrow, vcol, vrow, i int, formatSet *formatTable) error {
// Correct the minimum number of rows, the table at least two lines.
if hrow == vrow {
vrow++
}
// Correct table reference coordinate area, such correct C1:B3 to B1:C3.
- ref := MustCoordinatesToCellName(hcol, hrow) + ":" + MustCoordinatesToCellName(vcol, vrow)
+ hcell, err := CoordinatesToCellName(hcol, hrow)
+ if err != nil {
+ return err
+ }
+ vcell, err := CoordinatesToCellName(vcol, vrow)
+ if err != nil {
+ return err
+ }
+ ref := hcell + ":" + vcell
- var (
- tableColumn []*xlsxTableColumn
- )
+ var tableColumn []*xlsxTableColumn
idx := 0
for i := hcol; i <= vcol; i++ {
idx++
- cell := MustCoordinatesToCellName(i, hrow)
- name := f.GetCellValue(sheet, cell)
+ cell, err := CoordinatesToCellName(i, hrow)
+ if err != nil {
+ return err
+ }
+ name, _ := f.GetCellValue(sheet, cell)
if _, err := strconv.Atoi(name); err == nil {
f.SetCellStr(sheet, cell, name)
}
@@ -163,6 +181,7 @@ func (f *File) addTable(sheet, tableXML string, hcol, hrow, vcol, vrow, i int, f
}
table, _ := xml.Marshal(t)
f.saveFileList(tableXML, table)
+ return nil
}
// parseAutoFilterSet provides a function to parse the settings of the auto
@@ -244,8 +263,14 @@ func parseAutoFilterSet(formatSet string) (*formatAutoFilter, error) {
// Price < 2000
//
func (f *File) AutoFilter(sheet, hcell, vcell, format string) error {
- hcol, hrow := MustCellNameToCoordinates(hcell)
- vcol, vrow := MustCellNameToCoordinates(vcell)
+ hcol, hrow, err := CellNameToCoordinates(hcell)
+ if err != nil {
+ return err
+ }
+ vcol, vrow, err := CellNameToCoordinates(vcell)
+ if err != nil {
+ return err
+ }
if vcol < hcol {
vcol, hcol = hcol, vcol
@@ -256,7 +281,17 @@ func (f *File) AutoFilter(sheet, hcell, vcell, format string) error {
}
formatSet, _ := parseAutoFilterSet(format)
- ref := MustCoordinatesToCellName(hcol, hrow) + ":" + MustCoordinatesToCellName(vcol, vrow)
+
+ var cellStart, cellEnd string
+ cellStart, err = CoordinatesToCellName(hcol, hrow)
+ if err != nil {
+ return err
+ }
+ cellEnd, err = CoordinatesToCellName(vcol, vrow)
+ if err != nil {
+ return err
+ }
+ ref := cellStart + ":" + cellEnd
refRange := vcol - hcol
return f.autoFilter(sheet, ref, refRange, hcol, formatSet)
}
@@ -277,7 +312,10 @@ func (f *File) autoFilter(sheet, ref string, refRange, col int, formatSet *forma
return nil
}
- fsCol := MustColumnNameToNumber(formatSet.Column)
+ fsCol, err := ColumnNameToNumber(formatSet.Column)
+ if err != nil {
+ return err
+ }
offset := fsCol - col
if offset < 0 || offset > refRange {
return fmt.Errorf("incorrect index of column '%s'", formatSet.Column)