summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--adjust_test.go16
-rw-r--r--calcchain.go20
-rw-r--r--calcchain_test.go26
-rw-r--r--cell.go92
-rw-r--r--cell_test.go113
-rw-r--r--chart_test.go18
-rw-r--r--col.go78
-rw-r--r--col_test.go13
-rw-r--r--comment.go102
-rw-r--r--comment_test.go48
-rw-r--r--docProps.go4
-rw-r--r--docProps_test.go12
-rw-r--r--drawing.go25
-rw-r--r--drawing_test.go17
-rw-r--r--errors.go5
-rw-r--r--excelize.go9
-rw-r--r--excelize_test.go30
-rw-r--r--file.go4
-rw-r--r--merge_test.go6
-rw-r--r--picture.go11
-rw-r--r--picture_test.go16
-rw-r--r--rows.go39
-rw-r--r--rows_test.go17
-rw-r--r--shape.go14
-rw-r--r--shape_test.go11
-rw-r--r--sheet.go8
-rw-r--r--sheet_test.go6
-rw-r--r--stream_test.go4
-rw-r--r--styles.go112
-rw-r--r--styles_test.go76
30 files changed, 655 insertions, 297 deletions
diff --git a/adjust_test.go b/adjust_test.go
index 0325616..3ce1796 100644
--- a/adjust_test.go
+++ b/adjust_test.go
@@ -10,7 +10,7 @@ import (
func TestAdjustMergeCells(t *testing.T) {
f := NewFile()
- // testing adjustAutoFilter with illegal cell reference.
+ // Test adjustAutoFilter with illegal cell reference.
assert.EqualError(t, f.adjustMergeCells(&xlsxWorksheet{
MergeCells: &xlsxMergeCells{
Cells: []*xlsxMergeCell{
@@ -57,7 +57,7 @@ func TestAdjustMergeCells(t *testing.T) {
},
}, columns, 1, -1))
- // testing adjustMergeCells
+ // Test adjustMergeCells.
var cases []struct {
label string
ws *xlsxWorksheet
@@ -68,7 +68,7 @@ func TestAdjustMergeCells(t *testing.T) {
expectRect []int
}
- // testing insert
+ // Test insert.
cases = []struct {
label string
ws *xlsxWorksheet
@@ -139,7 +139,7 @@ func TestAdjustMergeCells(t *testing.T) {
assert.Equal(t, c.expectRect, c.ws.MergeCells.Cells[0].rect, c.label)
}
- // testing delete
+ // Test delete,
cases = []struct {
label string
ws *xlsxWorksheet
@@ -227,7 +227,7 @@ func TestAdjustMergeCells(t *testing.T) {
assert.Equal(t, c.expect, c.ws.MergeCells.Cells[0].Ref, c.label)
}
- // testing delete one row/column
+ // Test delete one row or column
cases = []struct {
label string
ws *xlsxWorksheet
@@ -324,13 +324,13 @@ func TestAdjustTable(t *testing.T) {
f = NewFile()
assert.NoError(t, f.AddTable(sheetName, "A1", "D5", ""))
- // Test adjust table with non-table part
+ // Test adjust table with non-table part.
f.Pkg.Delete("xl/tables/table1.xml")
assert.NoError(t, f.RemoveRow(sheetName, 1))
- // Test adjust table with unsupported charset
+ // Test adjust table with unsupported charset.
f.Pkg.Store("xl/tables/table1.xml", MacintoshCyrillicCharset)
assert.NoError(t, f.RemoveRow(sheetName, 1))
- // Test adjust table with invalid table range reference
+ // Test adjust table with invalid table range reference.
f.Pkg.Store("xl/tables/table1.xml", []byte(`<table ref="-" />`))
assert.NoError(t, f.RemoveRow(sheetName, 1))
}
diff --git a/calcchain.go b/calcchain.go
index 80928c2..3aa5d81 100644
--- a/calcchain.go
+++ b/calcchain.go
@@ -15,23 +15,19 @@ import (
"bytes"
"encoding/xml"
"io"
- "log"
)
// calcChainReader provides a function to get the pointer to the structure
// after deserialization of xl/calcChain.xml.
-func (f *File) calcChainReader() *xlsxCalcChain {
- var err error
-
+func (f *File) calcChainReader() (*xlsxCalcChain, error) {
if f.CalcChain == nil {
f.CalcChain = new(xlsxCalcChain)
- if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathCalcChain)))).
+ if err := f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathCalcChain)))).
Decode(f.CalcChain); err != nil && err != io.EOF {
- log.Printf("xml decode error: %s", err)
+ return f.CalcChain, err
}
}
-
- return f.CalcChain
+ return f.CalcChain, nil
}
// calcChainWriter provides a function to save xl/calcChain.xml after
@@ -45,8 +41,11 @@ func (f *File) calcChainWriter() {
// deleteCalcChain provides a function to remove cell reference on the
// calculation chain.
-func (f *File) deleteCalcChain(index int, cell string) {
- calc := f.calcChainReader()
+func (f *File) deleteCalcChain(index int, cell string) error {
+ calc, err := f.calcChainReader()
+ if err != nil {
+ return err
+ }
if calc != nil {
calc.C = xlsxCalcChainCollection(calc.C).Filter(func(c xlsxCalcChainC) bool {
return !((c.I == index && c.R == cell) || (c.I == index && cell == "") || (c.I == 0 && c.R == cell))
@@ -64,6 +63,7 @@ func (f *File) deleteCalcChain(index int, cell string) {
}
}
}
+ return err
}
type xlsxCalcChainCollection []xlsxCalcChainC
diff --git a/calcchain_test.go b/calcchain_test.go
index c36655b..fae3a51 100644
--- a/calcchain_test.go
+++ b/calcchain_test.go
@@ -1,12 +1,18 @@
package excelize
-import "testing"
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
func TestCalcChainReader(t *testing.T) {
f := NewFile()
+ // Test read calculation chain with unsupported charset.
f.CalcChain = nil
f.Pkg.Store(defaultXMLPathCalcChain, MacintoshCyrillicCharset)
- f.calcChainReader()
+ _, err := f.calcChainReader()
+ assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
}
func TestDeleteCalcChain(t *testing.T) {
@@ -15,5 +21,19 @@ func TestDeleteCalcChain(t *testing.T) {
f.ContentTypes.Overrides = append(f.ContentTypes.Overrides, xlsxOverride{
PartName: "/xl/calcChain.xml",
})
- f.deleteCalcChain(1, "A1")
+ assert.NoError(t, f.deleteCalcChain(1, "A1"))
+
+ f.CalcChain = nil
+ f.Pkg.Store(defaultXMLPathCalcChain, MacintoshCyrillicCharset)
+ assert.EqualError(t, f.deleteCalcChain(1, "A1"), "XML syntax error on line 1: invalid UTF-8")
+
+ f.CalcChain = nil
+ f.Pkg.Store(defaultXMLPathCalcChain, MacintoshCyrillicCharset)
+ assert.EqualError(t, f.SetCellFormula("Sheet1", "A1", ""), "XML syntax error on line 1: invalid UTF-8")
+
+ formulaType, ref := STCellFormulaTypeShared, "C1:C5"
+ assert.NoError(t, f.SetCellFormula("Sheet1", "C1", "=A1+B1", FormulaOpts{Ref: &ref, Type: &formulaType}))
+ f.CalcChain = nil
+ f.Pkg.Store(defaultXMLPathCalcChain, MacintoshCyrillicCharset)
+ assert.EqualError(t, f.SetCellValue("Sheet1", "C1", true), "XML syntax error on line 1: invalid UTF-8")
}
diff --git a/cell.go b/cell.go
index c8fa9b2..cbb7932 100644
--- a/cell.go
+++ b/cell.go
@@ -66,7 +66,11 @@ var cellTypes = map[string]CellType{
// values will be the same in a merged range.
func (f *File) GetCellValue(sheet, cell string, opts ...Options) (string, error) {
return f.getCellStringFunc(sheet, cell, func(x *xlsxWorksheet, c *xlsxC) (string, bool, error) {
- val, err := c.getValueFrom(f, f.sharedStringsReader(), parseOptions(opts...).RawCellValue)
+ sst, err := f.sharedStringsReader()
+ if err != nil {
+ return "", true, err
+ }
+ val, err := c.getValueFrom(f, sst, parseOptions(opts...).RawCellValue)
return val, true, err
})
}
@@ -173,23 +177,26 @@ func (c *xlsxC) hasValue() bool {
}
// removeFormula delete formula for the cell.
-func (f *File) removeFormula(c *xlsxC, ws *xlsxWorksheet, sheet string) {
+func (f *File) removeFormula(c *xlsxC, ws *xlsxWorksheet, sheet string) error {
if c.F != nil && c.Vm == nil {
sheetID := f.getSheetID(sheet)
- f.deleteCalcChain(sheetID, c.R)
+ if err := f.deleteCalcChain(sheetID, c.R); err != nil {
+ return err
+ }
if c.F.T == STCellFormulaTypeShared && c.F.Ref != "" {
si := c.F.Si
for r, row := range ws.SheetData.Row {
for col, cell := range row.C {
if cell.F != nil && cell.F.Si != nil && *cell.F.Si == *si {
ws.SheetData.Row[r].C[col].F = nil
- f.deleteCalcChain(sheetID, cell.R)
+ _ = f.deleteCalcChain(sheetID, cell.R)
}
}
}
}
c.F = nil
}
+ return nil
}
// setCellIntFunc is a wrapper of SetCellInt.
@@ -289,8 +296,7 @@ func (f *File) SetCellInt(sheet, cell string, value int) error {
c.S = f.prepareCellStyle(ws, col, row, c.S)
c.T, c.V = setCellInt(value)
c.IS = nil
- f.removeFormula(c, ws, sheet)
- return err
+ return f.removeFormula(c, ws, sheet)
}
// setCellInt prepares cell type and string type cell value by a given
@@ -316,8 +322,7 @@ func (f *File) SetCellBool(sheet, cell string, value bool) error {
c.S = f.prepareCellStyle(ws, col, row, c.S)
c.T, c.V = setCellBool(value)
c.IS = nil
- f.removeFormula(c, ws, sheet)
- return err
+ return f.removeFormula(c, ws, sheet)
}
// setCellBool prepares cell type and string type cell value by a given
@@ -354,8 +359,7 @@ func (f *File) SetCellFloat(sheet, cell string, value float64, precision, bitSiz
c.S = f.prepareCellStyle(ws, col, row, c.S)
c.T, c.V = setCellFloat(value, precision, bitSize)
c.IS = nil
- f.removeFormula(c, ws, sheet)
- return err
+ return f.removeFormula(c, ws, sheet)
}
// setCellFloat prepares cell type and string type cell value by a given
@@ -379,10 +383,11 @@ func (f *File) SetCellStr(sheet, cell, value string) error {
ws.Lock()
defer ws.Unlock()
c.S = f.prepareCellStyle(ws, col, row, c.S)
- c.T, c.V, err = f.setCellString(value)
+ if c.T, c.V, err = f.setCellString(value); err != nil {
+ return err
+ }
c.IS = nil
- f.removeFormula(c, ws, sheet)
- return err
+ return f.removeFormula(c, ws, sheet)
}
// setCellString provides a function to set string type to shared string
@@ -429,7 +434,10 @@ func (f *File) setSharedString(val string) (int, error) {
if err := f.sharedStringsLoader(); err != nil {
return 0, err
}
- sst := f.sharedStringsReader()
+ sst, err := f.sharedStringsReader()
+ if err != nil {
+ return 0, err
+ }
f.Lock()
defer f.Unlock()
if i, ok := f.sharedStringsMap[val]; ok {
@@ -498,7 +506,7 @@ func (c *xlsxC) getCellBool(f *File, raw bool) (string, error) {
return "FALSE", nil
}
}
- return f.formattedValue(c.S, c.V, raw), nil
+ return f.formattedValue(c.S, c.V, raw)
}
// setCellDefault prepares cell type and string type cell value by a given
@@ -529,7 +537,7 @@ func (c *xlsxC) getCellDate(f *File, raw bool) (string, error) {
c.V = strconv.FormatFloat(excelTime, 'G', 15, 64)
}
}
- return f.formattedValue(c.S, c.V, raw), nil
+ return f.formattedValue(c.S, c.V, raw)
}
// getValueFrom return a value from a column/row cell, this function is
@@ -548,18 +556,18 @@ func (c *xlsxC) getValueFrom(f *File, d *xlsxSST, raw bool) (string, error) {
xlsxSI := 0
xlsxSI, _ = strconv.Atoi(c.V)
if _, ok := f.tempFiles.Load(defaultXMLPathSharedStrings); ok {
- return f.formattedValue(c.S, f.getFromStringItem(xlsxSI), raw), nil
+ return f.formattedValue(c.S, f.getFromStringItem(xlsxSI), raw)
}
if len(d.SI) > xlsxSI {
- return f.formattedValue(c.S, d.SI[xlsxSI].String(), raw), nil
+ return f.formattedValue(c.S, d.SI[xlsxSI].String(), raw)
}
}
- return f.formattedValue(c.S, c.V, raw), nil
+ return f.formattedValue(c.S, c.V, raw)
case "inlineStr":
if c.IS != nil {
- return f.formattedValue(c.S, c.IS.String(), raw), nil
+ return f.formattedValue(c.S, c.IS.String(), raw)
}
- return f.formattedValue(c.S, c.V, raw), nil
+ return f.formattedValue(c.S, c.V, raw)
default:
if isNum, precision, decimal := isNumeric(c.V); isNum && !raw {
if precision > 15 {
@@ -568,7 +576,7 @@ func (c *xlsxC) getValueFrom(f *File, d *xlsxSST, raw bool) (string, error) {
c.V = strconv.FormatFloat(decimal, 'f', -1, 64)
}
}
- return f.formattedValue(c.S, c.V, raw), nil
+ return f.formattedValue(c.S, c.V, raw)
}
}
@@ -587,8 +595,7 @@ func (f *File) SetCellDefault(sheet, cell, value string) error {
defer ws.Unlock()
c.S = f.prepareCellStyle(ws, col, row, c.S)
c.setCellDefault(value)
- f.removeFormula(c, ws, sheet)
- return err
+ return f.removeFormula(c, ws, sheet)
}
// GetCellFormula provides a function to get formula from cell by given
@@ -698,8 +705,7 @@ func (f *File) SetCellFormula(sheet, cell, formula string, opts ...FormulaOpts)
}
if formula == "" {
c.F = nil
- f.deleteCalcChain(f.getSheetID(sheet), cell)
- return err
+ return f.deleteCalcChain(f.getSheetID(sheet), cell)
}
if c.F != nil {
@@ -926,7 +932,10 @@ func (f *File) GetCellRichText(sheet, cell string) (runs []RichTextRun, err erro
if err != nil || c.T != "s" {
return
}
- sst := f.sharedStringsReader()
+ sst, err := f.sharedStringsReader()
+ if err != nil {
+ return
+ }
if len(sst.SI) <= siIdx || siIdx < 0 {
return
}
@@ -1145,7 +1154,11 @@ func (f *File) SetCellRichText(sheet, cell string, runs []RichTextRun) error {
return err
}
c.S = f.prepareCellStyle(ws, col, row, c.S)
- si, sst := xlsxSI{}, f.sharedStringsReader()
+ si := xlsxSI{}
+ sst, err := f.sharedStringsReader()
+ if err != nil {
+ return err
+ }
if si.R, err = setRichText(runs); err != nil {
return err
}
@@ -1286,19 +1299,22 @@ func (f *File) getCellStringFunc(sheet, cell string, fn func(x *xlsxWorksheet, c
// formattedValue provides a function to returns a value after formatted. 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) formattedValue(s int, v string, raw bool) string {
+func (f *File) formattedValue(s int, v string, raw bool) (string, error) {
if raw {
- return v
+ return v, nil
}
if s == 0 {
- return v
+ return v, nil
+ }
+ styleSheet, err := f.stylesReader()
+ if err != nil {
+ return v, err
}
- styleSheet := f.stylesReader()
if styleSheet.CellXfs == nil {
- return v
+ return v, err
}
if s >= len(styleSheet.CellXfs.Xf) {
- return v
+ return v, err
}
var numFmtID int
if styleSheet.CellXfs.Xf[s].NumFmtID != nil {
@@ -1309,17 +1325,17 @@ func (f *File) formattedValue(s int, v string, raw bool) string {
date1904 = wb.WorkbookPr.Date1904
}
if ok := builtInNumFmtFunc[numFmtID]; ok != nil {
- return ok(v, builtInNumFmt[numFmtID], date1904)
+ return ok(v, builtInNumFmt[numFmtID], date1904), err
}
if styleSheet.NumFmts == nil {
- return v
+ return v, err
}
for _, xlsxFmt := range styleSheet.NumFmts.NumFmt {
if xlsxFmt.NumFmtID == numFmtID {
- return format(v, xlsxFmt.FormatCode, date1904)
+ return format(v, xlsxFmt.FormatCode, date1904), err
}
}
- return v
+ return v, err
}
// prepareCellStyle provides a function to prepare style index of cell in
diff --git a/cell_test.go b/cell_test.go
index 6689c36..18bc101 100644
--- a/cell_test.go
+++ b/cell_test.go
@@ -188,6 +188,11 @@ func TestSetCellValue(t *testing.T) {
B2, err := f.GetCellValue("Sheet1", "B2")
assert.NoError(t, err)
assert.Equal(t, "0.50", B2)
+
+ // Test set cell value with unsupported charset shared strings table
+ f.SharedStrings = nil
+ f.Pkg.Store(defaultXMLPathSharedStrings, MacintoshCyrillicCharset)
+ assert.EqualError(t, f.SetCellValue("Sheet1", "A1", "A1"), "XML syntax error on line 1: invalid UTF-8")
}
func TestSetCellValues(t *testing.T) {
@@ -199,7 +204,7 @@ func TestSetCellValues(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, v, "12/31/10 00:00")
- // test date value lower than min date supported by Excel
+ // Test date value lower than min date supported by Excel
err = f.SetCellValue("Sheet1", "A1", time.Date(1600, time.December, 31, 0, 0, 0, 0, time.UTC))
assert.NoError(t, err)
@@ -377,6 +382,12 @@ func TestGetCellValue(t *testing.T) {
"2020-07-10 15:00:00.000",
}, rows[0])
assert.NoError(t, err)
+
+ // Test get cell value with unsupported charset shared strings table.
+ f.SharedStrings = nil
+ f.Pkg.Store(defaultXMLPathSharedStrings, MacintoshCyrillicCharset)
+ _, value := f.GetCellValue("Sheet1", "A1")
+ assert.EqualError(t, value, "XML syntax error on line 1: invalid UTF-8")
}
func TestGetCellType(t *testing.T) {
@@ -395,7 +406,9 @@ func TestGetCellType(t *testing.T) {
func TestGetValueFrom(t *testing.T) {
f := NewFile()
c := xlsxC{T: "s"}
- value, err := c.getValueFrom(f, f.sharedStringsReader(), false)
+ sst, err := f.sharedStringsReader()
+ assert.NoError(t, err)
+ value, err := c.getValueFrom(f, sst, false)
assert.NoError(t, err)
assert.Equal(t, "", value)
}
@@ -566,36 +579,46 @@ func TestGetCellRichText(t *testing.T) {
runsSource[1].Font.Color = strings.ToUpper(runsSource[1].Font.Color)
assert.True(t, reflect.DeepEqual(runsSource[1].Font, runs[1].Font), "should get the same font")
- // Test get cell rich text when string item index overflow
+ // Test get cell rich text when string item index overflow.
ws, ok := f.Sheet.Load("xl/worksheets/sheet1.xml")
assert.True(t, ok)
ws.(*xlsxWorksheet).SheetData.Row[0].C[0].V = "2"
runs, err = f.GetCellRichText("Sheet1", "A1")
assert.NoError(t, err)
assert.Equal(t, 0, len(runs))
- // Test get cell rich text when string item index is negative
+ // Test get cell rich text when string item index is negative.
ws, ok = f.Sheet.Load("xl/worksheets/sheet1.xml")
assert.True(t, ok)
ws.(*xlsxWorksheet).SheetData.Row[0].C[0].V = "-1"
runs, err = f.GetCellRichText("Sheet1", "A1")
assert.NoError(t, err)
assert.Equal(t, 0, len(runs))
- // Test get cell rich text on invalid string item index
+ // Test get cell rich text on invalid string item index.
ws, ok = f.Sheet.Load("xl/worksheets/sheet1.xml")
assert.True(t, ok)
ws.(*xlsxWorksheet).SheetData.Row[0].C[0].V = "x"
_, err = f.GetCellRichText("Sheet1", "A1")
assert.EqualError(t, err, "strconv.Atoi: parsing \"x\": invalid syntax")
- // Test set cell rich text on not exists worksheet
+ // Test set cell rich text on not exists worksheet.
_, err = f.GetCellRichText("SheetN", "A1")
assert.EqualError(t, err, "sheet SheetN does not exist")
- // Test set cell rich text with illegal cell reference
+ // Test set cell rich text with illegal cell reference.
_, err = f.GetCellRichText("Sheet1", "A")
assert.EqualError(t, err, newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
- // Test set rich text color theme without tint
+ // Test set rich text color theme without tint.
assert.NoError(t, f.SetCellRichText("Sheet1", "A1", []RichTextRun{{Font: &Font{ColorTheme: &theme}}}))
- // Test set rich text color tint without theme
+ // Test set rich text color tint without theme.
assert.NoError(t, f.SetCellRichText("Sheet1", "A1", []RichTextRun{{Font: &Font{ColorTint: 0.5}}}))
+
+ // Test set cell rich text with unsupported charset shared strings table.
+ f.SharedStrings = nil
+ f.Pkg.Store(defaultXMLPathSharedStrings, MacintoshCyrillicCharset)
+ assert.EqualError(t, f.SetCellRichText("Sheet1", "A1", runsSource), "XML syntax error on line 1: invalid UTF-8")
+ // Test get cell rich text with unsupported charset shared strings table.
+ f.SharedStrings = nil
+ f.Pkg.Store(defaultXMLPathSharedStrings, MacintoshCyrillicCharset)
+ _, err = f.GetCellRichText("Sheet1", "A1")
+ assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
}
func TestSetCellRichText(t *testing.T) {
@@ -689,80 +712,108 @@ func TestSetCellRichText(t *testing.T) {
assert.NoError(t, err)
assert.NoError(t, f.SetCellStyle("Sheet1", "A1", "A1", style))
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetCellRichText.xlsx")))
- // Test set cell rich text on not exists worksheet
+ // Test set cell rich text on not exists worksheet.
assert.EqualError(t, f.SetCellRichText("SheetN", "A1", richTextRun), "sheet SheetN does not exist")
- // Test set cell rich text with illegal cell reference
+ // Test set cell rich text with illegal cell reference.
assert.EqualError(t, f.SetCellRichText("Sheet1", "A", richTextRun), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
richTextRun = []RichTextRun{{Text: strings.Repeat("s", TotalCellChars+1)}}
- // Test set cell rich text with characters over the maximum limit
+ // Test set cell rich text with characters over the maximum limit.
assert.EqualError(t, f.SetCellRichText("Sheet1", "A1", richTextRun), ErrCellCharsLength.Error())
}
-func TestFormattedValue2(t *testing.T) {
+func TestFormattedValue(t *testing.T) {
f := NewFile()
- assert.Equal(t, "43528", f.formattedValue(0, "43528", false))
+ result, err := f.formattedValue(0, "43528", false)
+ assert.NoError(t, err)
+ assert.Equal(t, "43528", result)
- assert.Equal(t, "43528", f.formattedValue(15, "43528", false))
+ result, err = f.formattedValue(15, "43528", false)
+ assert.NoError(t, err)
+ assert.Equal(t, "43528", result)
- assert.Equal(t, "43528", f.formattedValue(1, "43528", false))
+ result, err = f.formattedValue(1, "43528", false)
+ assert.NoError(t, err)
+ assert.Equal(t, "43528", result)
customNumFmt := "[$-409]MM/DD/YYYY"
- _, err := f.NewStyle(&Style{
+ _, err = f.NewStyle(&Style{
CustomNumFmt: &customNumFmt,
})
assert.NoError(t, err)
- assert.Equal(t, "03/04/2019", f.formattedValue(1, "43528", false))
+ result, err = f.formattedValue(1, "43528", false)
+ assert.NoError(t, err)
+ assert.Equal(t, "03/04/2019", result)
- // formatted value with no built-in number format ID
+ // Test format value with no built-in number format ID.
numFmtID := 5
f.Styles.CellXfs.Xf = append(f.Styles.CellXfs.Xf, xlsxXf{
NumFmtID: &numFmtID,
})
- assert.Equal(t, "43528", f.formattedValue(2, "43528", false))
+ result, err = f.formattedValue(2, "43528", false)
+ assert.NoError(t, err)
+ assert.Equal(t, "43528", result)
- // formatted value with invalid number format ID
+ // Test format value with invalid number format ID.
f.Styles.CellXfs.Xf = append(f.Styles.CellXfs.Xf, xlsxXf{
NumFmtID: nil,
})
- assert.Equal(t, "43528", f.formattedValue(3, "43528", false))
+ result, err = f.formattedValue(3, "43528", false)
+ assert.NoError(t, err)
+ assert.Equal(t, "43528", result)
- // formatted value with empty number format
+ // Test format value with empty number format.
f.Styles.NumFmts = nil
f.Styles.CellXfs.Xf = append(f.Styles.CellXfs.Xf, xlsxXf{
NumFmtID: &numFmtID,
})
- assert.Equal(t, "43528", f.formattedValue(1, "43528", false))
+ result, err = f.formattedValue(1, "43528", false)
+ assert.NoError(t, err)
+ assert.Equal(t, "43528", result)
- // formatted decimal value with build-in number format ID
+ // Test format decimal value with build-in number format ID.
styleID, err := f.NewStyle(&Style{
NumFmt: 1,
})
assert.NoError(t, err)
- assert.Equal(t, "311", f.formattedValue(styleID, "310.56", false))
+ result, err = f.formattedValue(styleID, "310.56", false)
+ assert.NoError(t, err)
+ assert.Equal(t, "311", result)
for _, fn := range builtInNumFmtFunc {
assert.Equal(t, "0_0", fn("0_0", "", false))
}
+
+ // Test format value with unsupported charset style sheet.
+ f.Styles = nil
+ f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
+ _, err = f.formattedValue(1, "43528", false)
+ assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
}
func TestFormattedValueNilXfs(t *testing.T) {
// Set the CellXfs to nil and verify that the formattedValue function does not crash.
f := NewFile()
f.Styles.CellXfs = nil
- assert.Equal(t, "43528", f.formattedValue(3, "43528", false))
+ result, err := f.formattedValue(3, "43528", false)
+ assert.NoError(t, err)
+ assert.Equal(t, "43528", result)
}
func TestFormattedValueNilNumFmts(t *testing.T) {
// Set the NumFmts value to nil and verify that the formattedValue function does not crash.
f := NewFile()
f.Styles.NumFmts = nil
- assert.Equal(t, "43528", f.formattedValue(3, "43528", false))
+ result, err := f.formattedValue(3, "43528", false)
+ assert.NoError(t, err)
+ assert.Equal(t, "43528", result)
}
func TestFormattedValueNilWorkbook(t *testing.T) {
// Set the Workbook value to nil and verify that the formattedValue function does not crash.
f := NewFile()
f.WorkBook = nil
- assert.Equal(t, "43528", f.formattedValue(3, "43528", false))
+ result, err := f.formattedValue(3, "43528", false)
+ assert.NoError(t, err)
+ assert.Equal(t, "43528", result)
}
func TestFormattedValueNilWorkbookPr(t *testing.T) {
@@ -770,7 +821,9 @@ func TestFormattedValueNilWorkbookPr(t *testing.T) {
// crash.
f := NewFile()
f.WorkBook.WorkbookPr = nil
- assert.Equal(t, "43528", f.formattedValue(3, "43528", false))
+ result, err := f.formattedValue(3, "43528", false)
+ assert.NoError(t, err)
+ assert.Equal(t, "43528", result)
}
func TestSharedStringsError(t *testing.T) {
diff --git a/chart_test.go b/chart_test.go
index 6d40b44..dac724a 100644
--- a/chart_test.go
+++ b/chart_test.go
@@ -95,6 +95,24 @@ func TestChartSize(t *testing.T) {
func TestAddDrawingChart(t *testing.T) {
f := NewFile()
assert.EqualError(t, f.addDrawingChart("SheetN", "", "", 0, 0, 0, nil), newCellNameToCoordinatesError("", newInvalidCellNameError("")).Error())
+
+ path := "xl/drawings/drawing1.xml"
+ f.Pkg.Store(path, MacintoshCyrillicCharset)
+ assert.EqualError(t, f.addDrawingChart("Sheet1", path, "A1", 0, 0, 0, &pictureOptions{}), "XML syntax error on line 1: invalid UTF-8")
+}
+
+func TestAddSheetDrawingChart(t *testing.T) {
+ f := NewFile()
+ path := "xl/drawings/drawing1.xml"
+ f.Pkg.Store(path, MacintoshCyrillicCharset)
+ assert.EqualError(t, f.addSheetDrawingChart(path, 0, &pictureOptions{}), "XML syntax error on line 1: invalid UTF-8")
+}
+
+func TestDeleteDrawing(t *testing.T) {
+ f := NewFile()
+ path := "xl/drawings/drawing1.xml"
+ f.Pkg.Store(path, MacintoshCyrillicCharset)
+ assert.EqualError(t, f.deleteDrawing(0, 0, path, "Chart"), "XML syntax error on line 1: invalid UTF-8")
}
func TestAddChart(t *testing.T) {
diff --git a/col.go b/col.go
index 8466797..b930877 100644
--- a/col.go
+++ b/col.go
@@ -38,6 +38,7 @@ type Cols struct {
sheet string
f *File
sheetXML []byte
+ sst *xlsxSST
}
// GetCols gets the value of all cells by columns on the worksheet based on the
@@ -87,17 +88,14 @@ func (cols *Cols) Error() error {
// Rows return the current column's row values.
func (cols *Cols) Rows(opts ...Options) ([]string, error) {
- var (
- err error
- inElement string
- cellCol, cellRow int
- rows []string
- )
+ var rowIterator rowXMLIterator
if cols.stashCol >= cols.curCol {
- return rows, err
+ return rowIterator.cells, rowIterator.err
}
cols.rawCellValue = parseOptions(opts...).RawCellValue
- d := cols.f.sharedStringsReader()
+ if cols.sst, rowIterator.err = cols.f.sharedStringsReader(); rowIterator.err != nil {
+ return rowIterator.cells, rowIterator.err
+ }
decoder := cols.f.xmlNewDecoder(bytes.NewReader(cols.sheetXML))
for {
token, _ := decoder.Token()
@@ -106,42 +104,25 @@ func (cols *Cols) Rows(opts ...Options) ([]string, error) {
}
switch xmlElement := token.(type) {
case xml.StartElement:
- inElement = xmlElement.Name.Local
- if inElement == "row" {
- cellCol = 0
- cellRow++
+ rowIterator.inElement = xmlElement.Name.Local
+ if rowIterator.inElement == "row" {
+ rowIterator.cellCol = 0
+ rowIterator.cellRow++
attrR, _ := attrValToInt("r", xmlElement.Attr)
if attrR != 0 {
- cellRow = attrR
+ rowIterator.cellRow = attrR
}
}
- if inElement == "c" {
- cellCol++
- for _, attr := range xmlElement.Attr {
- if attr.Name.Local == "r" {
- if cellCol, cellRow, err = CellNameToCoordinates(attr.Value); err != nil {
- return rows, err
- }
- }
- }
- blank := cellRow - len(rows)
- for i := 1; i < blank; i++ {
- rows = append(rows, "")
- }
- if cellCol == cols.curCol {
- colCell := xlsxC{}
- _ = decoder.DecodeElement(&colCell, &xmlElement)
- val, _ := colCell.getValueFrom(cols.f, d, cols.rawCellValue)
- rows = append(rows, val)
- }
+ if cols.rowXMLHandler(&rowIterator, &xmlElement, decoder); rowIterator.err != nil {
+ return rowIterator.cells, rowIterator.err
}
case xml.EndElement:
if xmlElement.Name.Local == "sheetData" {
- return rows, err
+ return rowIterator.cells, rowIterator.err
}
}
}
- return rows, err
+ return rowIterator.cells, rowIterator.err
}
// columnXMLIterator defined runtime use field for the worksheet column SAX parser.
@@ -183,6 +164,30 @@ func columnXMLHandler(colIterator *columnXMLIterator, xmlElement *xml.StartEleme
}
}
+// rowXMLHandler parse the row XML element of the worksheet.
+func (cols *Cols) rowXMLHandler(rowIterator *rowXMLIterator, xmlElement *xml.StartElement, decoder *xml.Decoder) {
+ if rowIterator.inElement == "c" {
+ rowIterator.cellCol++
+ for _, attr := range xmlElement.Attr {
+ if attr.Name.Local == "r" {
+ if rowIterator.cellCol, rowIterator.cellRow, rowIterator.err = CellNameToCoordinates(attr.Value); rowIterator.err != nil {
+ return
+ }
+ }
+ }
+ blank := rowIterator.cellRow - len(rowIterator.cells)
+ for i := 1; i < blank; i++ {
+ rowIterator.cells = append(rowIterator.cells, "")
+ }
+ if rowIterator.cellCol == cols.curCol {
+ colCell := xlsxC{}
+ _ = decoder.DecodeElement(&colCell, xmlElement)
+ val, _ := colCell.getValueFrom(cols.f, cols.sst, cols.rawCellValue)
+ rowIterator.cells = append(rowIterator.cells, val)
+ }
+ }
+}
+
// Cols returns a columns iterator, used for streaming reading data for a
// worksheet with a large data. This function is concurrency safe. For
// example:
@@ -420,7 +425,10 @@ func (f *File) SetColStyle(sheet, columns string, styleID int) error {
if err != nil {
return err
}
- s := f.stylesReader()
+ s, err := f.stylesReader()
+ if err != nil {
+ return err
+ }
s.Lock()
if styleID < 0 || s.CellXfs == nil || len(s.CellXfs.Xf) <= styleID {
s.Unlock()
diff --git a/col_test.go b/col_test.go
index f786335..0ed1906 100644
--- a/col_test.go
+++ b/col_test.go
@@ -56,6 +56,15 @@ func TestCols(t *testing.T) {
})
_, err = f.Rows("Sheet1")
assert.NoError(t, err)
+
+ // Test columns iterator with unsupported charset shared strings table.
+ f.SharedStrings = nil
+ f.Pkg.Store(defaultXMLPathSharedStrings, MacintoshCyrillicCharset)
+ cols, err = f.Cols("Sheet1")
+ assert.NoError(t, err)
+ cols.Next()
+ _, err = cols.Rows()
+ assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
}
func TestColumnsIterator(t *testing.T) {
@@ -316,6 +325,10 @@ func TestSetColStyle(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, styleID, cellStyleID)
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetColStyle.xlsx")))
+ // Test set column style with unsupported charset style sheet.
+ f.Styles = nil
+ f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
+ assert.EqualError(t, f.SetColStyle("Sheet1", "C:F", styleID), "XML syntax error on line 1: invalid UTF-8")
}
func TestColWidth(t *testing.T) {
diff --git a/comment.go b/comment.go
index 28c6cf8..eec5fa6 100644
--- a/comment.go
+++ b/comment.go
@@ -16,7 +16,6 @@ import (
"encoding/xml"
"fmt"
"io"
- "log"
"path/filepath"
"strconv"
"strings"
@@ -24,8 +23,8 @@ import (
// GetComments retrieves all comments and returns a map of worksheet name to
// the worksheet comments.
-func (f *File) GetComments() (comments map[string][]Comment) {
- comments = map[string][]Comment{}
+func (f *File) GetComments() (map[string][]Comment, error) {
+ comments := map[string][]Comment{}
for n, path := range f.sheetMap {
target := f.getSheetComments(filepath.Base(path))
if target == "" {
@@ -34,12 +33,16 @@ func (f *File) GetComments() (comments map[string][]Comment) {
if !strings.HasPrefix(target, "/") {
target = "xl" + strings.TrimPrefix(target, "..")
}
- if d := f.commentsReader(strings.TrimPrefix(target, "/")); d != nil {
+ cmts, err := f.commentsReader(strings.TrimPrefix(target, "/"))
+ if err != nil {
+ return comments, err
+ }
+ if cmts != nil {
var sheetComments []Comment
- for _, comment := range d.CommentList.Comment {
+ for _, comment := range cmts.CommentList.Comment {
sheetComment := Comment{}
- if comment.AuthorID < len(d.Authors.Author) {
- sheetComment.Author = d.Authors.Author[comment.AuthorID]
+ if comment.AuthorID < len(cmts.Authors.Author) {
+ sheetComment.Author = cmts.Authors.Author[comment.AuthorID]
}
sheetComment.Cell = comment.Ref
sheetComment.AuthorID = comment.AuthorID
@@ -60,7 +63,7 @@ func (f *File) GetComments() (comments map[string][]Comment) {
comments[n] = sheetComments
}
}
- return
+ return comments, nil
}
// getSheetComments provides the method to get the target comment reference by
@@ -129,7 +132,9 @@ func (f *File) AddComment(sheet string, comment Comment) error {
if err = f.addDrawingVML(commentID, drawingVML, comment.Cell, rows+1, cols); err != nil {
return err
}
- f.addComment(commentsXML, comment)
+ if err = f.addComment(commentsXML, comment); err != nil {
+ return err
+ }
f.addContentTypePart(commentID, "comments")
return err
}
@@ -139,34 +144,36 @@ func (f *File) AddComment(sheet string, comment Comment) error {
//
// err := f.DeleteComment("Sheet1", "A30")
func (f *File) DeleteComment(sheet, cell string) error {
- var err error
sheetXMLPath, ok := f.getSheetXMLPath(sheet)
if !ok {
- err = newNoExistSheetError(sheet)
- return err
+ return newNoExistSheetError(sheet)
}
commentsXML := f.getSheetComments(filepath.Base(sheetXMLPath))
if !strings.HasPrefix(commentsXML, "/") {
commentsXML = "xl" + strings.TrimPrefix(commentsXML, "..")
}
commentsXML = strings.TrimPrefix(commentsXML, "/")
- if comments := f.commentsReader(commentsXML); comments != nil {
- for i := 0; i < len(comments.CommentList.Comment); i++ {
- cmt := comments.CommentList.Comment[i]
+ cmts, err := f.commentsReader(commentsXML)
+ if err != nil {
+ return err
+ }
+ if cmts != nil {
+ for i := 0; i < len(cmts.CommentList.Comment); i++ {
+ cmt := cmts.CommentList.Comment[i]
if cmt.Ref != cell {
continue
}
- if len(comments.CommentList.Comment) > 1 {
- comments.CommentList.Comment = append(
- comments.CommentList.Comment[:i],
- comments.CommentList.Comment[i+1:]...,
+ if len(cmts.CommentList.Comment) > 1 {
+ cmts.CommentList.Comment = append(
+ cmts.CommentList.Comment[:i],
+ cmts.CommentList.Comment[i+1:]...,
)
i--
continue
}
- comments.CommentList.Comment = nil
+ cmts.CommentList.Comment = nil
}
- f.Comments[commentsXML] = comments
+ f.Comments[commentsXML] = cmts
}
return err
}
@@ -209,7 +216,10 @@ func (f *File) addDrawingVML(commentID int, drawingVML, cell string, lineCount,
},
}
// load exist comment shapes from xl/drawings/vmlDrawing%d.vml
- d := f.decodeVMLDrawingReader(drawingVML)
+ d, err := f.decodeVMLDrawingReader(drawingVML)
+ if err != nil {
+ return err
+ }
if d != nil {
for _, v := range d.Shape {
s := xlsxShape{
@@ -274,22 +284,30 @@ func (f *File) addDrawingVML(commentID int, drawingVML, cell string, lineCount,
// addComment provides a function to create chart as xl/comments%d.xml by
// given cell and format sets.
-func (f *File) addComment(commentsXML string, comment Comment) {
+func (f *File) addComment(commentsXML string, comment Comment) error {
if comment.Author == "" {
comment.Author = "Author"
}
if len(comment.Author) > MaxFieldLength {
comment.Author = comment.Author[:MaxFieldLength]
}
- comments, authorID := f.commentsReader(commentsXML), 0
- if comments == nil {
- comments = &xlsxComments{Authors: xlsxAuthor{Author: []string{comment.Author}}}
+ cmts, err := f.commentsReader(commentsXML)
+ if err != nil {
+ return err
+ }
+ var authorID int
+ if cmts == nil {
+ cmts = &xlsxComments{Authors: xlsxAuthor{Author: []string{comment.Author}}}
+ }
+ if inStrSlice(cmts.Authors.Author, comment.Author, true) == -1 {
+ cmts.Authors.Author = append(cmts.Authors.Author, comment.Author)
+ authorID = len(cmts.Authors.Author) - 1
}
- if inStrSlice(comments.Authors.Author, comment.Author, true) == -1 {
- comments.Authors.Author = append(comments.Authors.Author, comment.Author)
- authorID = len(comments.Authors.Author) - 1
+ defaultFont, err := f.GetDefaultFont()
+ if err != nil {
+ return err
}
- defaultFont, chars, cmt := f.GetDefaultFont(), 0, xlsxComment{
+ chars, cmt := 0, xlsxComment{
Ref: comment.Cell,
AuthorID: authorID,
Text: xlsxText{R: []xlsxR{}},
@@ -328,8 +346,9 @@ func (f *File) addComment(commentsXML string, comment Comment) {
}
cmt.Text.R = append(cmt.Text.R, r)
}
- comments.CommentList.Comment = append(comments.CommentList.Comment, cmt)
- f.Comments[commentsXML] = comments
+ cmts.CommentList.Comment = append(cmts.CommentList.Comment, cmt)
+ f.Comments[commentsXML] = cmts
+ return err
}
// countComments provides a function to get comments files count storage in
@@ -355,20 +374,18 @@ func (f *File) countComments() int {
// decodeVMLDrawingReader provides a function to get the pointer to the
// structure after deserialization of xl/drawings/vmlDrawing%d.xml.
-func (f *File) decodeVMLDrawingReader(path string) *decodeVmlDrawing {
- var err error
-
+func (f *File) decodeVMLDrawingReader(path string) (*decodeVmlDrawing, error) {
if f.DecodeVMLDrawing[path] == nil {
c, ok := f.Pkg.Load(path)
if ok && c != nil {
f.DecodeVMLDrawing[path] = new(decodeVmlDrawing)
- if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(c.([]byte)))).
+ if err := f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(c.([]byte)))).
Decode(f.DecodeVMLDrawing[path]); err != nil && err != io.EOF {
- log.Printf("xml decode error: %s", err)
+ return nil, err
}
}
}
- return f.DecodeVMLDrawing[path]
+ return f.DecodeVMLDrawing[path], nil
}
// vmlDrawingWriter provides a function to save xl/drawings/vmlDrawing%d.xml
@@ -384,19 +401,18 @@ func (f *File) vmlDrawingWriter() {
// commentsReader provides a function to get the pointer to the structure
// after deserialization of xl/comments%d.xml.
-func (f *File) commentsReader(path string) *xlsxComments {
- var err error
+func (f *File) commentsReader(path string) (*xlsxComments, error) {
if f.Comments[path] == nil {
content, ok := f.Pkg.Load(path)
if ok && content != nil {
f.Comments[path] = new(xlsxComments)
- if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(content.([]byte)))).
+ if err := f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(content.([]byte)))).
Decode(f.Comments[path]); err != nil && err != io.EOF {
- log.Printf("xml decode error: %s", err)
+ return nil, err
}
}
}
- return f.Comments[path]
+ return f.Comments[path], nil
}
// commentsWriter provides a function to save xl/comments%d.xml after
diff --git a/comment_test.go b/comment_test.go
index 019dc3b..ed44508 100644
--- a/comment_test.go
+++ b/comment_test.go
@@ -34,16 +34,37 @@ func TestAddComments(t *testing.T) {
assert.EqualError(t, f.AddComment("SheetN", Comment{Cell: "B7", Author: "Excelize", Runs: []RichTextRun{{Text: "Excelize: ", Font: &Font{Bold: true}}, {Text: "This is a comment."}}}), "sheet SheetN does not exist")
// Test add comment on with illegal cell reference
assert.EqualError(t, f.AddComment("Sheet1", Comment{Cell: "A", Author: "Excelize", Runs: []RichTextRun{{Text: "Excelize: ", Font: &Font{Bold: true}}, {Text: "This is a comment."}}}), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
+ comments, err := f.GetComments()
+ assert.NoError(t, err)
if assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddComments.xlsx"))) {
- assert.Len(t, f.GetComments(), 2)
+ assert.Len(t, comments, 2)
}
f.Comments["xl/comments2.xml"] = nil
f.Pkg.Store("xl/comments2.xml", []byte(xml.Header+`<comments xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><authors><author>Excelize: </author></authors><commentList><comment ref="B7" authorId="0"><text><t>Excelize: </t></text></comment></commentList></comments>`))
- comments := f.GetComments()
+ comments, err = f.GetComments()
+ assert.NoError(t, err)
assert.EqualValues(t, 2, len(comments["Sheet1"]))
assert.EqualValues(t, 1, len(comments["Sheet2"]))
- assert.EqualValues(t, len(NewFile().GetComments()), 0)
+ comments, err = NewFile().GetComments()
+ assert.NoError(t, err)
+ assert.EqualValues(t, len(comments), 0)
+
+ // Test add comments with unsupported charset.
+ f.Comments["xl/comments2.xml"] = nil
+ f.Pkg.Store("xl/comments2.xml", MacintoshCyrillicCharset)
+ _, err = f.GetComments()
+ assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
+
+ // Test add comments with unsupported charset.
+ f.Comments["xl/comments2.xml"] = nil
+ f.Pkg.Store("xl/comments2.xml", MacintoshCyrillicCharset)
+ assert.EqualError(t, f.AddComment("Sheet2", Comment{Cell: "A30", Text: "Comment"}), "XML syntax error on line 1: invalid UTF-8")
+
+ // Test add comments with unsupported charset style sheet.
+ f.Styles = nil
+ f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
+ assert.EqualError(t, f.AddComment("Sheet2", Comment{Cell: "A30", Text: "Comment"}), "XML syntax error on line 1: invalid UTF-8")
}
func TestDeleteComment(t *testing.T) {
@@ -61,19 +82,30 @@ func TestDeleteComment(t *testing.T) {
assert.NoError(t, f.DeleteComment("Sheet2", "A40"))
- assert.EqualValues(t, 5, len(f.GetComments()["Sheet2"]))
- assert.EqualValues(t, len(NewFile().GetComments()), 0)
+ comments, err := f.GetComments()
+ assert.NoError(t, err)
+ assert.EqualValues(t, 5, len(comments["Sheet2"]))
+
+ comments, err = NewFile().GetComments()
+ assert.NoError(t, err)
+ assert.EqualValues(t, len(comments), 0)
// Test delete all comments in a worksheet
assert.NoError(t, f.DeleteComment("Sheet2", "A41"))
assert.NoError(t, f.DeleteComment("Sheet2", "C41"))
assert.NoError(t, f.DeleteComment("Sheet2", "C42"))
- assert.EqualValues(t, 0, len(f.GetComments()["Sheet2"]))
+ comments, err = f.GetComments()
+ assert.NoError(t, err)
+ assert.EqualValues(t, 0, len(comments["Sheet2"]))
// Test delete comment on not exists worksheet
assert.EqualError(t, f.DeleteComment("SheetN", "A1"), "sheet SheetN does not exist")
// Test delete comment with worksheet part
f.Pkg.Delete("xl/worksheets/sheet1.xml")
assert.NoError(t, f.DeleteComment("Sheet1", "A22"))
+
+ f.Comments["xl/comments2.xml"] = nil
+ f.Pkg.Store("xl/comments2.xml", MacintoshCyrillicCharset)
+ assert.EqualError(t, f.DeleteComment("Sheet2", "A41"), "XML syntax error on line 1: invalid UTF-8")
}
func TestDecodeVMLDrawingReader(t *testing.T) {
@@ -85,9 +117,11 @@ func TestDecodeVMLDrawingReader(t *testing.T) {
func TestCommentsReader(t *testing.T) {
f := NewFile()
+ // Test read comments with unsupported charset.
path := "xl/comments1.xml"
f.Pkg.Store(path, MacintoshCyrillicCharset)
- f.commentsReader(path)
+ _, err := f.commentsReader(path)
+ assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
}
func TestCountComments(t *testing.T) {
diff --git a/docProps.go b/docProps.go
index 4ee46ad..ebe929b 100644
--- a/docProps.go
+++ b/docProps.go
@@ -76,7 +76,6 @@ func (f *File) SetAppProps(appProperties *AppProperties) error {
app = new(xlsxProperties)
if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathDocPropsApp)))).
Decode(app); err != nil && err != io.EOF {
- err = newDecodeXMLError(err)
return err
}
fields = []string{"Application", "ScaleCrop", "DocSecurity", "Company", "LinksUpToDate", "HyperlinksChanged", "AppVersion"}
@@ -103,7 +102,6 @@ func (f *File) GetAppProps() (ret *AppProperties, err error) {
app := new(xlsxProperties)
if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathDocPropsApp)))).
Decode(app); err != nil && err != io.EOF {
- err = newDecodeXMLError(err)
return
}
ret, err = &AppProperties{
@@ -182,7 +180,6 @@ func (f *File) SetDocProps(docProperties *DocProperties) error {
core = new(decodeCoreProperties)
if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathDocPropsCore)))).
Decode(core); err != nil && err != io.EOF {
- err = newDecodeXMLError(err)
return err
}
newProps = &xlsxCoreProperties{
@@ -237,7 +234,6 @@ func (f *File) GetDocProps() (ret *DocProperties, err error) {
if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathDocPropsCore)))).
Decode(core); err != nil && err != io.EOF {
- err = newDecodeXMLError(err)
return
}
ret, err = &DocProperties{
diff --git a/docProps_test.go b/docProps_test.go
index 545059d..64b690c 100644
--- a/docProps_test.go
+++ b/docProps_test.go
@@ -42,7 +42,7 @@ func TestSetAppProps(t *testing.T) {
// Test unsupported charset
f = NewFile()
f.Pkg.Store(defaultXMLPathDocPropsApp, MacintoshCyrillicCharset)
- assert.EqualError(t, f.SetAppProps(&AppProperties{}), "xml decode error: XML syntax error on line 1: invalid UTF-8")
+ assert.EqualError(t, f.SetAppProps(&AppProperties{}), "XML syntax error on line 1: invalid UTF-8")
}
func TestGetAppProps(t *testing.T) {
@@ -58,11 +58,11 @@ func TestGetAppProps(t *testing.T) {
assert.NoError(t, err)
assert.NoError(t, f.Close())
- // Test unsupported charset
+ // Test get application properties with unsupported charset.
f = NewFile()
f.Pkg.Store(defaultXMLPathDocPropsApp, MacintoshCyrillicCharset)
_, err = f.GetAppProps()
- assert.EqualError(t, err, "xml decode error: XML syntax error on line 1: invalid UTF-8")
+ assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
}
func TestSetDocProps(t *testing.T) {
@@ -94,7 +94,7 @@ func TestSetDocProps(t *testing.T) {
// Test unsupported charset
f = NewFile()
f.Pkg.Store(defaultXMLPathDocPropsCore, MacintoshCyrillicCharset)
- assert.EqualError(t, f.SetDocProps(&DocProperties{}), "xml decode error: XML syntax error on line 1: invalid UTF-8")
+ assert.EqualError(t, f.SetDocProps(&DocProperties{}), "XML syntax error on line 1: invalid UTF-8")
}
func TestGetDocProps(t *testing.T) {
@@ -110,9 +110,9 @@ func TestGetDocProps(t *testing.T) {
assert.NoError(t, err)
assert.NoError(t, f.Close())
- // Test unsupported charset
+ // Test get workbook properties with unsupported charset.
f = NewFile()
f.Pkg.Store(defaultXMLPathDocPropsCore, MacintoshCyrillicCharset)
_, err = f.GetDocProps()
- assert.EqualError(t, err, "xml decode error: XML syntax error on line 1: invalid UTF-8")
+ assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
}
diff --git a/drawing.go b/drawing.go
index 4fe575b..08b7aac 100644
--- a/drawing.go
+++ b/drawing.go
@@ -15,7 +15,6 @@ import (
"bytes"
"encoding/xml"
"io"
- "log"
"reflect"
"strconv"
"strings"
@@ -1194,7 +1193,7 @@ func (f *File) drawPlotAreaTxPr(opts *chartAxisOptions) *cTxPr {
// the problem that the label structure is changed after serialization and
// deserialization, two different structures: decodeWsDr and encodeWsDr are
// defined.
-func (f *File) drawingParser(path string) (*xlsxWsDr, int) {
+func (f *File) drawingParser(path string) (*xlsxWsDr, int, error) {
var (
err error
ok bool
@@ -1208,7 +1207,7 @@ func (f *File) drawingParser(path string) (*xlsxWsDr, int) {
decodeWsDr := decodeWsDr{}
if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(path)))).
Decode(&decodeWsDr); err != nil && err != io.EOF {
- log.Printf("xml decode error: %s", err)
+ return nil, 0, err
}
content.R = decodeWsDr.R
for _, v := range decodeWsDr.AlternateContent {
@@ -1238,7 +1237,7 @@ func (f *File) drawingParser(path string) (*xlsxWsDr, int) {
}
wsDr.Lock()
defer wsDr.Unlock()
- return wsDr, len(wsDr.OneCellAnchor) + len(wsDr.TwoCellAnchor) + 2
+ return wsDr, len(wsDr.OneCellAnchor) + len(wsDr.TwoCellAnchor) + 2, nil
}
// addDrawingChart provides a function to add chart graphic frame by given
@@ -1254,7 +1253,10 @@ func (f *File) addDrawingChart(sheet, drawingXML, cell string, width, height, rI
width = int(float64(width) * opts.XScale)
height = int(float64(height) * opts.YScale)
colStart, rowStart, colEnd, rowEnd, x2, y2 := f.positionObjectPixels(sheet, colIdx, rowIdx, opts.OffsetX, opts.OffsetY, width, height)
- content, cNvPrID := f.drawingParser(drawingXML)
+ content, cNvPrID, err := f.drawingParser(drawingXML)
+ if err != nil {
+ return err
+ }
twoCellAnchor := xdrCellAnchor{}
twoCellAnchor.EditAs = opts.Positioning
from := xlsxFrom{}
@@ -1302,8 +1304,11 @@ func (f *File) addDrawingChart(sheet, drawingXML, cell string, width, height, rI
// addSheetDrawingChart provides a function to add chart graphic frame for
// chartsheet by given sheet, drawingXML, width, height, relationship index
// and format sets.
-func (f *File) addSheetDrawingChart(drawingXML string, rID int, opts *pictureOptions) {
- content, cNvPrID := f.drawingParser(drawingXML)
+func (f *File) addSheetDrawingChart(drawingXML string, rID int, opts *pictureOptions) error {
+ content, cNvPrID, err := f.drawingParser(drawingXML)
+ if err != nil {
+ return err
+ }
absoluteAnchor := xdrCellAnchor{
EditAs: opts.Positioning,
Pos: &xlsxPoint2D{},
@@ -1336,6 +1341,7 @@ func (f *File) addSheetDrawingChart(drawingXML string, rID int, opts *pictureOpt
}
content.AbsoluteAnchor = append(content.AbsoluteAnchor, &absoluteAnchor)
f.Drawings.Store(drawingXML, content)
+ return err
}
// deleteDrawing provides a function to delete chart graphic frame by given by
@@ -1354,7 +1360,9 @@ func (f *File) deleteDrawing(col, row int, drawingXML, drawingType string) error
"Chart": func(anchor *decodeTwoCellAnchor) bool { return anchor.Pic == nil },
"Pic": func(anchor *decodeTwoCellAnchor) bool { return anchor.Pic != nil },
}
- wsDr, _ = f.drawingParser(drawingXML)
+ if wsDr, _, err = f.drawingParser(drawingXML); err != nil {
+ return err
+ }
for idx := 0; idx < len(wsDr.TwoCellAnchor); idx++ {
if err = nil; wsDr.TwoCellAnchor[idx].From != nil && xdrCellAnchorFuncs[drawingType](wsDr.TwoCellAnchor[idx]) {
if wsDr.TwoCellAnchor[idx].From.Col == col && wsDr.TwoCellAnchor[idx].From.Row == row {
@@ -1367,7 +1375,6 @@ func (f *File) deleteDrawing(col, row int, drawingXML, drawingType string) error
deTwoCellAnchor = new(decodeTwoCellAnchor)
if err = f.xmlNewDecoder(strings.NewReader("<decodeTwoCellAnchor>" + wsDr.TwoCellAnchor[idx].GraphicFrame + "</decodeTwoCellAnchor>")).
Decode(deTwoCellAnchor); err != nil && err != io.EOF {
- err = newDecodeXMLError(err)
return err
}
if err = nil; deTwoCellAnchor.From != nil && decodeTwoCellAnchorFuncs[drawingType](deTwoCellAnchor) {
diff --git a/drawing_test.go b/drawing_test.go
index e37b771..5c090eb 100644
--- a/drawing_test.go
+++ b/drawing_test.go
@@ -15,6 +15,8 @@ import (
"encoding/xml"
"sync"
"testing"
+
+ "github.com/stretchr/testify/assert"
)
func TestDrawingParser(t *testing.T) {
@@ -24,12 +26,15 @@ func TestDrawingParser(t *testing.T) {
}
f.Pkg.Store("charset", MacintoshCyrillicCharset)
f.Pkg.Store("wsDr", []byte(xml.Header+`<xdr:wsDr xmlns:xdr="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"><xdr:oneCellAnchor><xdr:graphicFrame/></xdr:oneCellAnchor></xdr:wsDr>`))
- // Test with one cell anchor
- f.drawingParser("wsDr")
- // Test with unsupported charset
- f.drawingParser("charset")
- // Test with alternate content
+ // Test with one cell anchor.
+ _, _, err := f.drawingParser("wsDr")
+ assert.NoError(t, err)
+ // Test with unsupported charset.
+ _, _, err = f.drawingParser("charset")
+ assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
+ // Test with alternate content.
f.Drawings = sync.Map{}
f.Pkg.Store("wsDr", []byte(xml.Header+`<xdr:wsDr xmlns:xdr="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"><mc:AlternateContent xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"><mc:Choice xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main" Requires="a14"><xdr:twoCellAnchor editAs="oneCell"></xdr:twoCellAnchor></mc:Choice><mc:Fallback/></mc:AlternateContent></xdr:wsDr>`))
- f.drawingParser("wsDr")
+ _, _, err = f.drawingParser("wsDr")
+ assert.NoError(t, err)
}
diff --git a/errors.go b/errors.go
index f486ad4..1f7c6f8 100644
--- a/errors.go
+++ b/errors.go
@@ -82,11 +82,6 @@ func newNotWorksheetError(name string) error {
return fmt.Errorf("sheet %s is not a worksheet", name)
}
-// newDecodeXMLError defined the error message on decode XML error.
-func newDecodeXMLError(err error) error {
- return fmt.Errorf("xml decode error: %s", err)
-}
-
// newStreamSetRowError defined the error message on the stream writer
// receiving the non-ascending row number.
func newStreamSetRowError(row int) error {
diff --git a/excelize.go b/excelize.go
index 987314b..256d427 100644
--- a/excelize.go
+++ b/excelize.go
@@ -177,11 +177,13 @@ func OpenReader(r io.Reader, opts ...Options) (*File, error) {
for k, v := range file {
f.Pkg.Store(k, v)
}
- f.CalcChain = f.calcChainReader()
+ if f.CalcChain, err = f.calcChainReader(); err != nil {
+ return f, err
+ }
f.sheetMap = f.getSheetMap()
- f.Styles = f.stylesReader()
+ f.Styles, err = f.stylesReader()
f.Theme = f.themeReader()
- return f, nil
+ return f, err
}
// parseOptions provides a function to parse the optional settings for open
@@ -250,7 +252,6 @@ func (f *File) workSheetReader(sheet string) (ws *xlsxWorksheet, err error) {
}
if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readBytes(name)))).
Decode(ws); err != nil && err != io.EOF {
- err = newDecodeXMLError(err)
return
}
err = nil
diff --git a/excelize_test.go b/excelize_test.go
index 74895f5..cab994f 100644
--- a/excelize_test.go
+++ b/excelize_test.go
@@ -10,6 +10,7 @@ import (
_ "image/gif"
_ "image/jpeg"
_ "image/png"
+ "io"
"math"
"os"
"path/filepath"
@@ -217,6 +218,28 @@ func TestOpenReader(t *testing.T) {
_, err = OpenReader(bytes.NewReader(oleIdentifier), Options{Password: "password", UnzipXMLSizeLimit: UnzipSizeLimit + 1})
assert.EqualError(t, err, ErrWorkbookFileFormat.Error())
+ // Test open workbook with unsupported charset internal calculation chain.
+ source, err := zip.OpenReader(filepath.Join("test", "Book1.xlsx"))
+ assert.NoError(t, err)
+ buf := new(bytes.Buffer)
+ zw := zip.NewWriter(buf)
+ for _, item := range source.File {
+ // The following statements can be simplified as zw.Copy(item) in go1.17
+ writer, err := zw.Create(item.Name)
+ assert.NoError(t, err)
+ readerCloser, err := item.Open()
+ assert.NoError(t, err)
+ _, err = io.Copy(writer, readerCloser)
+ assert.NoError(t, err)
+ }
+ fi, err := zw.Create(defaultXMLPathCalcChain)
+ assert.NoError(t, err)
+ _, err = fi.Write(MacintoshCyrillicCharset)
+ assert.NoError(t, err)
+ assert.NoError(t, zw.Close())
+ _, err = OpenReader(buf)
+ assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
+
// Test open spreadsheet with unzip size limit.
_, err = OpenFile(filepath.Join("test", "Book1.xlsx"), Options{UnzipSizeLimit: 100})
assert.EqualError(t, err, newUnzipSizeLimitError(100).Error())
@@ -338,6 +361,9 @@ func TestAddDrawingVML(t *testing.T) {
// Test addDrawingVML with illegal cell reference.
f := NewFile()
assert.EqualError(t, f.addDrawingVML(0, "", "*", 0, 0), newCellNameToCoordinatesError("*", newInvalidCellNameError("*")).Error())
+
+ f.Pkg.Store("xl/drawings/vmlDrawing1.vml", MacintoshCyrillicCharset)
+ assert.EqualError(t, f.addDrawingVML(0, "xl/drawings/vmlDrawing1.vml", "A1", 0, 0), "XML syntax error on line 1: invalid UTF-8")
}
func TestSetCellHyperLink(t *testing.T) {
@@ -1332,8 +1358,8 @@ func TestWorkSheetReader(t *testing.T) {
f.Sheet.Delete("xl/worksheets/sheet1.xml")
f.Pkg.Store("xl/worksheets/sheet1.xml", MacintoshCyrillicCharset)
_, err := f.workSheetReader("Sheet1")
- assert.EqualError(t, err, "xml decode error: XML syntax error on line 1: invalid UTF-8")
- assert.EqualError(t, f.UpdateLinkedValue(), "xml decode error: XML syntax error on line 1: invalid UTF-8")
+ assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
+ assert.EqualError(t, f.UpdateLinkedValue(), "XML syntax error on line 1: invalid UTF-8")
// Test on no checked worksheet.
f = NewFile()
diff --git a/file.go b/file.go
index fe5deca..31eaa3d 100644
--- a/file.go
+++ b/file.go
@@ -37,11 +37,11 @@ func NewFile() *File {
f.Pkg.Store(defaultXMLPathWorkbook, []byte(xml.Header+templateWorkbook))
f.Pkg.Store(defaultXMLPathContentTypes, []byte(xml.Header+templateContentTypes))
f.SheetCount = 1
- f.CalcChain = f.calcChainReader()
+ f.CalcChain, _ = f.calcChainReader()
f.Comments = make(map[string]*xlsxComments)
f.ContentTypes = f.contentTypesReader()
f.Drawings = sync.Map{}
- f.Styles = f.stylesReader()
+ f.Styles, _ = f.stylesReader()
f.DecodeVMLDrawing = make(map[string]*decodeVmlDrawing)
f.VMLDrawing = make(map[string]*vmlDrawing)
f.WorkBook = f.workbookReader()
diff --git a/merge_test.go b/merge_test.go
index e0b9210..31f2cf4 100644
--- a/merge_test.go
+++ b/merge_test.go
@@ -197,3 +197,9 @@ func TestFlatMergedCells(t *testing.T) {
ws := &xlsxWorksheet{MergeCells: &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: ""}}}}
assert.EqualError(t, flatMergedCells(ws, [][]*xlsxMergeCell{}), "cannot convert cell \"\" to coordinates: invalid cell name \"\"")
}
+
+func TestMergeCellsParser(t *testing.T) {
+ f := NewFile()
+ _, err := f.mergeCellsParser(&xlsxWorksheet{MergeCells: &xlsxMergeCells{Cells: []*xlsxMergeCell{nil}}}, "A1")
+ assert.NoError(t, err)
+}
diff --git a/picture.go b/picture.go
index a7c1edb..6cf1104 100644
--- a/picture.go
+++ b/picture.go
@@ -281,7 +281,10 @@ func (f *File) addDrawingPicture(sheet, drawingXML, cell, file, ext string, rID,
col--
row--
colStart, rowStart, colEnd, rowEnd, x2, y2 := f.positionObjectPixels(sheet, col, row, opts.OffsetX, opts.OffsetY, width, height)
- content, cNvPrID := f.drawingParser(drawingXML)
+ content, cNvPrID, err := f.drawingParser(drawingXML)
+ if err != nil {
+ return err
+ }
twoCellAnchor := xdrCellAnchor{}
twoCellAnchor.EditAs = opts.Positioning
from := xlsxFrom{}
@@ -559,14 +562,15 @@ func (f *File) getPicture(row, col int, drawingXML, drawingRelationships string)
deTwoCellAnchor *decodeTwoCellAnchor
)
- wsDr, _ = f.drawingParser(drawingXML)
+ if wsDr, _, err = f.drawingParser(drawingXML); err != nil {
+ return
+ }
if ret, buf = f.getPictureFromWsDr(row, col, drawingRelationships, wsDr); len(buf) > 0 {
return
}
deWsDr = new(decodeWsDr)
if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(drawingXML)))).
Decode(deWsDr); err != nil && err != io.EOF {
- err = newDecodeXMLError(err)
return
}
err = nil
@@ -574,7 +578,6 @@ func (f *File) getPicture(row, col int, drawingXML, drawingRelationships string)
deTwoCellAnchor = new(decodeTwoCellAnchor)
if err = f.xmlNewDecoder(strings.NewReader("<decodeTwoCellAnchor>" + anchor.Content + "</decodeTwoCellAnchor>")).
Decode(deTwoCellAnchor); err != nil && err != io.EOF {
- err = newDecodeXMLError(err)
return
}
if err = nil; deTwoCellAnchor.From != nil && deTwoCellAnchor.Pic != nil {
diff --git a/picture_test.go b/picture_test.go
index c34780f..65abf9e 100644
--- a/picture_test.go
+++ b/picture_test.go
@@ -169,15 +169,25 @@ func TestGetPicture(t *testing.T) {
assert.Empty(t, raw)
f, err = prepareTestBook1()
assert.NoError(t, err)
- f.Pkg.Store("xl/drawings/drawing1.xml", MacintoshCyrillicCharset)
- _, _, err = f.getPicture(20, 5, "xl/drawings/drawing1.xml", "xl/drawings/_rels/drawing2.xml.rels")
- assert.EqualError(t, err, "xml decode error: XML syntax error on line 1: invalid UTF-8")
+
+ // Test get pictures with unsupported charset.
+ path := "xl/drawings/drawing1.xml"
+ f.Pkg.Store(path, MacintoshCyrillicCharset)
+ _, _, err = f.getPicture(20, 5, path, "xl/drawings/_rels/drawing2.xml.rels")
+ assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
+ f.Drawings.Delete(path)
+ _, _, err = f.getPicture(20, 5, path, "xl/drawings/_rels/drawing2.xml.rels")
+ assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
}
func TestAddDrawingPicture(t *testing.T) {
// Test addDrawingPicture with illegal cell reference.
f := NewFile()
assert.EqualError(t, f.addDrawingPicture("sheet1", "", "A", "", "", 0, 0, image.Config{}, nil), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
+
+ path := "xl/drawings/drawing1.xml"
+ f.Pkg.Store(path, MacintoshCyrillicCharset)
+ assert.EqualError(t, f.addDrawingPicture("sheet1", path, "A1", "", "", 0, 0, image.Config{}, &pictureOptions{}), "XML syntax error on line 1: invalid UTF-8")
}
func TestAddPictureFromBytes(t *testing.T) {
diff --git a/rows.go b/rows.go
index bfea398..34a227f 100644
--- a/rows.go
+++ b/rows.go
@@ -16,7 +16,6 @@ import (
"encoding/xml"
"fmt"
"io"
- "log"
"math"
"os"
"strconv"
@@ -139,7 +138,10 @@ func (rows *Rows) Columns(opts ...Options) ([]string, error) {
}
var rowIterator rowXMLIterator
var token xml.Token
- rows.rawCellValue, rows.sst = parseOptions(opts...).RawCellValue, rows.f.sharedStringsReader()
+ rows.rawCellValue = parseOptions(opts...).RawCellValue
+ if rows.sst, rowIterator.err = rows.f.sharedStringsReader(); rowIterator.err != nil {
+ return rowIterator.cells, rowIterator.err
+ }
for {
if rows.token != nil {
token = rows.token
@@ -160,21 +162,21 @@ func (rows *Rows) Columns(opts ...Options) ([]string, error) {
rows.seekRowOpts = extractRowOpts(xmlElement.Attr)
if rows.curRow > rows.seekRow {
rows.token = nil
- return rowIterator.columns, rowIterator.err
+ return rowIterator.cells, rowIterator.err
}
}
if rows.rowXMLHandler(&rowIterator, &xmlElement, rows.rawCellValue); rowIterator.err != nil {
rows.token = nil
- return rowIterator.columns, rowIterator.err
+ return rowIterator.cells, rowIterator.err
}
rows.token = nil
case xml.EndElement:
if xmlElement.Name.Local == "sheetData" {
- return rowIterator.columns, rowIterator.err
+ return rowIterator.cells, rowIterator.err
}
}
}
- return rowIterator.columns, rowIterator.err
+ return rowIterator.cells, rowIterator.err
}
// extractRowOpts extract row element attributes.
@@ -211,10 +213,10 @@ func (err ErrSheetNotExist) Error() string {
// rowXMLIterator defined runtime use field for the worksheet row SAX parser.
type rowXMLIterator struct {
- err error
- inElement string
- cellCol int
- columns []string
+ err error
+ inElement string
+ cellCol, cellRow int
+ cells []string
}
// rowXMLHandler parse the row XML element of the worksheet.
@@ -228,9 +230,9 @@ func (rows *Rows) rowXMLHandler(rowIterator *rowXMLIterator, xmlElement *xml.Sta
return
}
}
- blank := rowIterator.cellCol - len(rowIterator.columns)
+ blank := rowIterator.cellCol - len(rowIterator.cells)
if val, _ := colCell.getValueFrom(rows.f, rows.sst, raw); val != "" || colCell.F != nil {
- rowIterator.columns = append(appendSpace(blank, rowIterator.columns), val)
+ rowIterator.cells = append(appendSpace(blank, rowIterator.cells), val)
}
}
}
@@ -409,7 +411,7 @@ func (f *File) GetRowHeight(sheet string, row int) (float64, error) {
// sharedStringsReader provides a function to get the pointer to the structure
// after deserialization of xl/sharedStrings.xml.
-func (f *File) sharedStringsReader() *xlsxSST {
+func (f *File) sharedStringsReader() (*xlsxSST, error) {
var err error
f.Lock()
defer f.Unlock()
@@ -419,7 +421,7 @@ func (f *File) sharedStringsReader() *xlsxSST {
ss := f.readXML(defaultXMLPathSharedStrings)
if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(ss))).
Decode(&sharedStrings); err != nil && err != io.EOF {
- log.Printf("xml decode error: %s", err)
+ return f.SharedStrings, err
}
if sharedStrings.Count == 0 {
sharedStrings.Count = len(sharedStrings.SI)
@@ -437,14 +439,14 @@ func (f *File) sharedStringsReader() *xlsxSST {
rels := f.relsReader(relPath)
for _, rel := range rels.Relationships {
if rel.Target == "/xl/sharedStrings.xml" {
- return f.SharedStrings
+ return f.SharedStrings, nil
}
}
// Update workbook.xml.rels
f.addRels(relPath, SourceRelationshipSharedStrings, "/xl/sharedStrings.xml", "")
}
- return f.SharedStrings
+ return f.SharedStrings, nil
}
// SetRowVisible provides a function to set visible of a single row by given
@@ -800,7 +802,10 @@ func (f *File) SetRowStyle(sheet string, start, end, styleID int) error {
if end > TotalRows {
return ErrMaxRows
}
- s := f.stylesReader()
+ s, err := f.stylesReader()
+ if err != nil {
+ return err
+ }
s.Lock()
defer s.Unlock()
if styleID < 0 || s.CellXfs == nil || len(s.CellXfs.Xf) <= styleID {
diff --git a/rows_test.go b/rows_test.go
index 81572e1..5317c22 100644
--- a/rows_test.go
+++ b/rows_test.go
@@ -55,7 +55,7 @@ func TestRows(t *testing.T) {
value, err := f.GetCellValue("Sheet1", "A19")
assert.NoError(t, err)
assert.Equal(t, "Total:", value)
- // Test load shared string table to memory
+ // Test load shared string table to memory.
err = f.SetCellValue("Sheet1", "A19", "A19")
assert.NoError(t, err)
value, err = f.GetCellValue("Sheet1", "A19")
@@ -63,6 +63,14 @@ func TestRows(t *testing.T) {
assert.Equal(t, "A19", value)
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetRow.xlsx")))
assert.NoError(t, f.Close())
+
+ // Test rows iterator with unsupported charset shared strings table.
+ f.SharedStrings = nil
+ f.Pkg.Store(defaultXMLPathSharedStrings, MacintoshCyrillicCharset)
+ rows, err = f.Rows(sheet2)
+ assert.NoError(t, err)
+ _, err = rows.Columns()
+ assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
}
func TestRowsIterator(t *testing.T) {
@@ -225,6 +233,7 @@ func TestColumns(t *testing.T) {
func TestSharedStringsReader(t *testing.T) {
f := NewFile()
+ // Test read shared string with unsupported charset.
f.Pkg.Store(defaultXMLPathSharedStrings, MacintoshCyrillicCharset)
f.sharedStringsReader()
si := xlsxSI{}
@@ -965,12 +974,16 @@ func TestSetRowStyle(t *testing.T) {
cellStyleID, err := f.GetCellStyle("Sheet1", "B2")
assert.NoError(t, err)
assert.Equal(t, style2, cellStyleID)
- // Test cell inheritance rows style
+ // Test cell inheritance rows style.
assert.NoError(t, f.SetCellValue("Sheet1", "C1", nil))
cellStyleID, err = f.GetCellStyle("Sheet1", "C1")
assert.NoError(t, err)
assert.Equal(t, style2, cellStyleID)
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestSetRowStyle.xlsx")))
+ // Test set row style with unsupported charset style sheet.
+ f.Styles = nil
+ f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
+ assert.EqualError(t, f.SetRowStyle("Sheet1", 1, 1, cellStyleID), "XML syntax error on line 1: invalid UTF-8")
}
func TestNumberFormats(t *testing.T) {
diff --git a/shape.go b/shape.go
index 9f250d7..6f7c8fd 100644
--- a/shape.go
+++ b/shape.go
@@ -305,8 +305,7 @@ func (f *File) AddShape(sheet, cell, opts string) error {
f.addSheetDrawing(sheet, rID)
f.addSheetNameSpace(sheet, SourceRelationship)
}
- err = f.addDrawingShape(sheet, drawingXML, cell, options)
- if err != nil {
+ if err = f.addDrawingShape(sheet, drawingXML, cell, options); err != nil {
return err
}
f.addContentTypePart(drawingID, "drawings")
@@ -328,7 +327,10 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, opts *shapeOption
colStart, rowStart, colEnd, rowEnd, x2, y2 := f.positionObjectPixels(sheet, colIdx, rowIdx, opts.Format.OffsetX, opts.Format.OffsetY,
width, height)
- content, cNvPrID := f.drawingParser(drawingXML)
+ content, cNvPrID, err := f.drawingParser(drawingXML)
+ if err != nil {
+ return err
+ }
twoCellAnchor := xdrCellAnchor{}
twoCellAnchor.EditAs = opts.Format.Positioning
from := xlsxFrom{}
@@ -385,6 +387,10 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, opts *shapeOption
W: f.ptToEMUs(opts.Line.Width),
}
}
+ defaultFont, err := f.GetDefaultFont()
+ if err != nil {
+ return err
+ }
if len(opts.Paragraph) < 1 {
opts.Paragraph = []shapeParagraphOptions{
{
@@ -392,7 +398,7 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, opts *shapeOption
Bold: false,
Italic: false,
Underline: "none",
- Family: f.GetDefaultFont(),
+ Family: defaultFont,
Size: 11,
Color: "#000000",
},
diff --git a/shape_test.go b/shape_test.go
index 829a9e5..9d1da8a 100644
--- a/shape_test.go
+++ b/shape_test.go
@@ -87,4 +87,15 @@ func TestAddShape(t *testing.T) {
}
}`))
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddShape2.xlsx")))
+ // Test set row style with unsupported charset style sheet.
+ f.Styles = nil
+ f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
+ assert.EqualError(t, f.AddShape("Sheet1", "B30", `{"type":"rect","paragraph":[{"text":"Rectangle"},{}]}`), "XML syntax error on line 1: invalid UTF-8")
+}
+
+func TestAddDrawingShape(t *testing.T) {
+ f := NewFile()
+ path := "xl/drawings/drawing1.xml"
+ f.Pkg.Store(path, MacintoshCyrillicCharset)
+ assert.EqualError(t, f.addDrawingShape("sheet1", path, "A1", &shapeOptions{}), "XML syntax error on line 1: invalid UTF-8")
}
diff --git a/sheet.go b/sheet.go
index 1346801..0616d95 100644
--- a/sheet.go
+++ b/sheet.go
@@ -881,10 +881,12 @@ func (f *File) searchSheet(name, value string, regSearch bool) (result []string,
var (
cellName, inElement string
cellCol, row int
- d *xlsxSST
+ sst *xlsxSST
)
- d = f.sharedStringsReader()
+ if sst, err = f.sharedStringsReader(); err != nil {
+ return
+ }
decoder := f.xmlNewDecoder(bytes.NewReader(f.readBytes(name)))
for {
var token xml.Token
@@ -907,7 +909,7 @@ func (f *File) searchSheet(name, value string, regSearch bool) (result []string,
if inElement == "c" {
colCell := xlsxC{}
_ = decoder.DecodeElement(&colCell, &xmlElement)
- val, _ := colCell.getValueFrom(f, d, false)
+ val, _ := colCell.getValueFrom(f, sst, false)
if regSearch {
regex := regexp.MustCompile(value)
if !regex.MatchString(val) {
diff --git a/sheet_test.go b/sheet_test.go
index 4e1e448..4b9d31e 100644
--- a/sheet_test.go
+++ b/sheet_test.go
@@ -91,6 +91,12 @@ func TestSearchSheet(t *testing.T) {
result, err = f.SearchSheet("Sheet1", "A")
assert.EqualError(t, err, "invalid cell reference [1, 0]")
assert.Equal(t, []string(nil), result)
+
+ // Test search sheet with unsupported charset shared strings table.
+ f.SharedStrings = nil
+ f.Pkg.Store(defaultXMLPathSharedStrings, MacintoshCyrillicCharset)
+ _, err = f.SearchSheet("Sheet1", "A")
+ assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
}
func TestSetPageLayout(t *testing.T) {
diff --git a/stream_test.go b/stream_test.go
index 040eee0..65af283 100644
--- a/stream_test.go
+++ b/stream_test.go
@@ -106,12 +106,12 @@ func TestStreamWriter(t *testing.T) {
assert.NoError(t, streamWriter.rawData.tmp.Close())
assert.NoError(t, os.Remove(streamWriter.rawData.tmp.Name()))
- // Test unsupported charset
+ // Test create stream writer with unsupported charset.
file = NewFile()
file.Sheet.Delete("xl/worksheets/sheet1.xml")
file.Pkg.Store("xl/worksheets/sheet1.xml", MacintoshCyrillicCharset)
_, err = file.NewStreamWriter("Sheet1")
- assert.EqualError(t, err, "xml decode error: XML syntax error on line 1: invalid UTF-8")
+ assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
assert.NoError(t, file.Close())
// Test read cell.
diff --git a/styles.go b/styles.go
index f7d00e1..08d6b0c 100644
--- a/styles.go
+++ b/styles.go
@@ -1037,15 +1037,15 @@ func formatToE(v, format string, date1904 bool) string {
// stylesReader provides a function to get the pointer to the structure after
// deserialization of xl/styles.xml.
-func (f *File) stylesReader() *xlsxStyleSheet {
+func (f *File) stylesReader() (*xlsxStyleSheet, error) {
if f.Styles == nil {
f.Styles = new(xlsxStyleSheet)
if err := f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathStyles)))).
Decode(f.Styles); err != nil && err != io.EOF {
- log.Printf("xml decode error: %s", err)
+ return f.Styles, err
}
}
- return f.Styles
+ return f.Styles, nil
}
// styleSheetWriter provides a function to save xl/styles.xml after serialize
@@ -1965,9 +1965,12 @@ func parseFormatStyleSet(style interface{}) (*Style, error) {
//
// Cell Sheet1!A6 in the Excel Application: martes, 04 de Julio de 2017
func (f *File) NewStyle(style interface{}) (int, error) {
- var fs *Style
- var err error
- var cellXfsID, fontID, borderID, fillID int
+ var (
+ fs *Style
+ font *xlsxFont
+ err error
+ cellXfsID, fontID, borderID, fillID int
+ )
fs, err = parseFormatStyleSet(style)
if err != nil {
return cellXfsID, err
@@ -1975,21 +1978,25 @@ func (f *File) NewStyle(style interface{}) (int, error) {
if fs.DecimalPlaces == 0 {
fs.DecimalPlaces = 2
}
- s := f.stylesReader()
+ s, err := f.stylesReader()
+ if err != nil {
+ return cellXfsID, err
+ }
s.Lock()
defer s.Unlock()
// check given style already exist.
- if cellXfsID = f.getStyleID(s, fs); cellXfsID != -1 {
+ if cellXfsID, err = f.getStyleID(s, fs); err != nil || cellXfsID != -1 {
return cellXfsID, err
}
numFmtID := newNumFmt(s, fs)
if fs.Font != nil {
- fontID = f.getFontID(s, fs)
+ fontID, _ = f.getFontID(s, fs)
if fontID == -1 {
s.Fonts.Count++
- s.Fonts.Font = append(s.Fonts.Font, f.newFont(fs))
+ font, _ = f.newFont(fs)
+ s.Fonts.Font = append(s.Fonts.Font, font)
fontID = s.Fonts.Count - 1
}
}
@@ -2065,12 +2072,19 @@ var getXfIDFuncs = map[string]func(int, xlsxXf, *Style) bool{
// getStyleID provides a function to get styleID by given style. If given
// style does not exist, will return -1.
-func (f *File) getStyleID(ss *xlsxStyleSheet, style *Style) (styleID int) {
- styleID = -1
+func (f *File) getStyleID(ss *xlsxStyleSheet, style *Style) (int, error) {
+ var (
+ err error
+ fontID int
+ styleID = -1
+ )
if ss.CellXfs == nil {
- return
+ return styleID, err
+ }
+ numFmtID, borderID, fillID := getNumFmtID(ss, style), getBorderID(ss, style), getFillID(ss, style)
+ if fontID, err = f.getFontID(ss, style); err != nil {
+ return styleID, err
}
- numFmtID, borderID, fillID, fontID := getNumFmtID(ss, style), getBorderID(ss, style), getFillID(ss, style), f.getFontID(ss, style)
if style.CustomNumFmt != nil {
numFmtID = getCustomNumFmtID(ss, style)
}
@@ -2082,10 +2096,10 @@ func (f *File) getStyleID(ss *xlsxStyleSheet, style *Style) (styleID int) {
getXfIDFuncs["alignment"](0, xf, style) &&
getXfIDFuncs["protection"](0, xf, style) {
styleID = xfID
- return
+ return styleID, err
}
}
- return
+ return styleID, err
}
// NewConditionalStyle provides a function to create style for conditional
@@ -2093,7 +2107,10 @@ func (f *File) getStyleID(ss *xlsxStyleSheet, style *Style) (styleID int) {
// function. Note that the color field uses RGB color code and only support to
// set font, fills, alignment and borders currently.
func (f *File) NewConditionalStyle(style string) (int, error) {
- s := f.stylesReader()
+ s, err := f.stylesReader()
+ if err != nil {
+ return 0, err
+ }
fs, err := parseFormatStyleSet(style)
if err != nil {
return 0, err
@@ -2108,7 +2125,7 @@ func (f *File) NewConditionalStyle(style string) (int, error) {
dxf.Border = newBorders(fs)
}
if fs.Font != nil {
- dxf.Font = f.newFont(fs)
+ dxf.Font, _ = f.newFont(fs)
}
dxfStr, _ := xml.Marshal(dxf)
if s.Dxfs == nil {
@@ -2123,41 +2140,56 @@ func (f *File) NewConditionalStyle(style string) (int, error) {
// GetDefaultFont provides the default font name currently set in the
// workbook. The spreadsheet generated by excelize default font is Calibri.
-func (f *File) GetDefaultFont() string {
- font := f.readDefaultFont()
- return *font.Name.Val
+func (f *File) GetDefaultFont() (string, error) {
+ font, err := f.readDefaultFont()
+ if err != nil {
+ return "", err
+ }
+ return *font.Name.Val, err
}
// SetDefaultFont changes the default font in the workbook.
-func (f *File) SetDefaultFont(fontName string) {
- font := f.readDefaultFont()
+func (f *File) SetDefaultFont(fontName string) error {
+ font, err := f.readDefaultFont()
+ if err != nil {
+ return err
+ }
font.Name.Val = stringPtr(fontName)
- s := f.stylesReader()
+ s, _ := f.stylesReader()
s.Fonts.Font[0] = font
custom := true
s.CellStyles.CellStyle[0].CustomBuiltIn = &custom
+ return err
}
// readDefaultFont provides an un-marshalled font value.
-func (f *File) readDefaultFont() *xlsxFont {
- s := f.stylesReader()
- return s.Fonts.Font[0]
+func (f *File) readDefaultFont() (*xlsxFont, error) {
+ s, err := f.stylesReader()
+ if err != nil {
+ return nil, err
+ }
+ return s.Fonts.Font[0], err
}
// getFontID provides a function to get font ID.
// If given font does not exist, will return -1.
-func (f *File) getFontID(styleSheet *xlsxStyleSheet, style *Style) (fontID int) {
- fontID = -1
+func (f *File) getFontID(styleSheet *xlsxStyleSheet, style *Style) (int, error) {
+ var err error
+ fontID := -1
if styleSheet.Fonts == nil || style.Font == nil {
- return
+ return fontID, err
}
for idx, fnt := range styleSheet.Fonts.Font {
- if reflect.DeepEqual(*fnt, *f.newFont(style)) {
+ font, err := f.newFont(style)
+ if err != nil {
+ return fontID, err
+ }
+ if reflect.DeepEqual(*fnt, *font) {
fontID = idx
- return
+ return fontID, err
}
}
- return
+ return fontID, err
}
// newFontColor set font color by given styles.
@@ -2190,7 +2222,8 @@ func newFontColor(font *Font) *xlsxColor {
// newFont provides a function to add font style by given cell format
// settings.
-func (f *File) newFont(style *Style) *xlsxFont {
+func (f *File) newFont(style *Style) (*xlsxFont, error) {
+ var err error
if style.Font.Size < MinFontSize {
style.Font.Size = 11
}
@@ -2207,7 +2240,9 @@ func (f *File) newFont(style *Style) *xlsxFont {
fnt.I = &attrValBool{Val: &style.Font.Italic}
}
if *fnt.Name.Val == "" {
- *fnt.Name.Val = f.GetDefaultFont()
+ if *fnt.Name.Val, err = f.GetDefaultFont(); err != nil {
+ return &fnt, err
+ }
}
if style.Font.Strike {
fnt.Strike = &attrValBool{Val: &style.Font.Strike}
@@ -2215,7 +2250,7 @@ func (f *File) newFont(style *Style) *xlsxFont {
if idx := inStrSlice(supportedUnderlineTypes, style.Font.Underline, true); idx != -1 {
fnt.U = &attrValString{Val: stringPtr(supportedUnderlineTypes[idx])}
}
- return &fnt
+ return &fnt, err
}
// getNumFmtID provides a function to get number format code ID.
@@ -2754,7 +2789,10 @@ func (f *File) SetCellStyle(sheet, hCell, vCell string, styleID int) error {
ws.Lock()
defer ws.Unlock()
- s := f.stylesReader()
+ s, err := f.stylesReader()
+ if err != nil {
+ return err
+ }
s.Lock()
defer s.Unlock()
if styleID < 0 || s.CellXfs == nil || len(s.CellXfs.Xf) <= styleID {
diff --git a/styles_test.go b/styles_test.go
index 487a6df..605ad07 100644
--- a/styles_test.go
+++ b/styles_test.go
@@ -30,7 +30,8 @@ func TestStyleFill(t *testing.T) {
styleID, err := xl.NewStyle(testCase.format)
assert.NoError(t, err)
- styles := xl.stylesReader()
+ styles, err := xl.stylesReader()
+ assert.NoError(t, err)
style := styles.CellXfs.Xf[styleID]
if testCase.expectFill {
assert.NotEqual(t, *style.FillID, 0, testCase.label)
@@ -220,7 +221,8 @@ func TestNewStyle(t *testing.T) {
f := NewFile()
styleID, err := f.NewStyle(`{"font":{"bold":true,"italic":true,"family":"Times New Roman","size":36,"color":"#777777"}}`)
assert.NoError(t, err)
- styles := f.stylesReader()
+ styles, err := f.stylesReader()
+ assert.NoError(t, err)
fontID := styles.CellXfs.Xf[styleID].FontID
font := styles.Fonts.Font[*fontID]
assert.Contains(t, *font.Name.Val, "Times New Roman", "Stored font should contain font name")
@@ -238,7 +240,7 @@ func TestNewStyle(t *testing.T) {
_, err = f.NewStyle(&Style{Font: &Font{Size: MaxFontSize + 1}})
assert.EqualError(t, err, ErrFontSize.Error())
- // new numeric custom style
+ // Test create numeric custom style.
numFmt := "####;####"
f.Styles.NumFmts = nil
styleID, err = f.NewStyle(&Style{
@@ -254,7 +256,7 @@ func TestNewStyle(t *testing.T) {
nf := f.Styles.CellXfs.Xf[styleID]
assert.Equal(t, 164, *nf.NumFmtID)
- // new currency custom style
+ // Test create currency custom style.
f.Styles.NumFmts = nil
styleID, err = f.NewStyle(&Style{
Lang: "ko-kr",
@@ -271,7 +273,7 @@ func TestNewStyle(t *testing.T) {
nf = f.Styles.CellXfs.Xf[styleID]
assert.Equal(t, 32, *nf.NumFmtID)
- // Test set build-in scientific number format
+ // Test set build-in scientific number format.
styleID, err = f.NewStyle(&Style{NumFmt: 11})
assert.NoError(t, err)
assert.NoError(t, f.SetCellStyle("Sheet1", "A1", "B1", styleID))
@@ -281,7 +283,7 @@ func TestNewStyle(t *testing.T) {
assert.Equal(t, [][]string{{"1.23E+00", "1.23E+00"}}, rows)
f = NewFile()
- // Test currency number format
+ // Test currency number format.
customNumFmt := "[$$-409]#,##0.00"
style1, err := f.NewStyle(&Style{CustomNumFmt: &customNumFmt})
assert.NoError(t, err)
@@ -306,21 +308,48 @@ func TestNewStyle(t *testing.T) {
style5, err := f.NewStyle(&Style{NumFmt: 160, Lang: "zh-cn"})
assert.NoError(t, err)
assert.Equal(t, 0, style5)
+
+ // Test create style with unsupported charset style sheet.
+ f.Styles = nil
+ f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
+ _, err = f.NewStyle(&Style{NumFmt: 165})
+ assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
+}
+
+func TestNewConditionalStyle(t *testing.T) {
+ f := NewFile()
+ // Test create conditional style with unsupported charset style sheet.
+ f.Styles = nil
+ f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
+ _, err := f.NewConditionalStyle(`{"font":{"color":"#9A0511"},"fill":{"type":"pattern","color":["#FEC7CE"],"pattern":1}}`)
+ assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
}
func TestGetDefaultFont(t *testing.T) {
f := NewFile()
- s := f.GetDefaultFont()
+ s, err := f.GetDefaultFont()
+ assert.NoError(t, err)
assert.Equal(t, s, "Calibri", "Default font should be Calibri")
+ // Test get default font with unsupported charset style sheet.
+ f.Styles = nil
+ f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
+ _, err = f.GetDefaultFont()
+ assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
}
func TestSetDefaultFont(t *testing.T) {
f := NewFile()
- f.SetDefaultFont("Arial")
- styles := f.stylesReader()
- s := f.GetDefaultFont()
+ assert.NoError(t, f.SetDefaultFont("Arial"))
+ styles, err := f.stylesReader()
+ assert.NoError(t, err)
+ s, err := f.GetDefaultFont()
+ assert.NoError(t, err)
assert.Equal(t, s, "Arial", "Default font should change to Arial")
assert.Equal(t, *styles.CellStyles.CellStyle[0].CustomBuiltIn, true)
+ // Test set default font with unsupported charset style sheet.
+ f.Styles = nil
+ f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
+ assert.EqualError(t, f.SetDefaultFont("Arial"), "XML syntax error on line 1: invalid UTF-8")
}
func TestStylesReader(t *testing.T) {
@@ -328,7 +357,9 @@ func TestStylesReader(t *testing.T) {
// Test read styles with unsupported charset.
f.Styles = nil
f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
- assert.EqualValues(t, new(xlsxStyleSheet), f.stylesReader())
+ styles, err := f.stylesReader()
+ assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
+ assert.EqualValues(t, new(xlsxStyleSheet), styles)
}
func TestThemeReader(t *testing.T) {
@@ -346,14 +377,33 @@ func TestSetCellStyle(t *testing.T) {
assert.EqualError(t, f.SetCellStyle("Sheet1", "A1", "A2", -1), newInvalidStyleID(-1).Error())
// Test set cell style with not exists style ID.
assert.EqualError(t, f.SetCellStyle("Sheet1", "A1", "A2", 10), newInvalidStyleID(10).Error())
+ // Test set cell style with unsupported charset style sheet.
+ f.Styles = nil
+ f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
+ assert.EqualError(t, f.SetCellStyle("Sheet1", "A1", "A2", 1), "XML syntax error on line 1: invalid UTF-8")
}
func TestGetStyleID(t *testing.T) {
- assert.Equal(t, -1, NewFile().getStyleID(&xlsxStyleSheet{}, nil))
+ f := NewFile()
+ styleID, err := f.getStyleID(&xlsxStyleSheet{}, nil)
+ assert.NoError(t, err)
+ assert.Equal(t, -1, styleID)
+ // Test get style ID with unsupported charset style sheet.
+ f.Styles = nil
+ f.Pkg.Store(defaultXMLPathStyles, MacintoshCyrillicCharset)
+ _, err = f.getStyleID(&xlsxStyleSheet{
+ CellXfs: &xlsxCellXfs{},
+ Fonts: &xlsxFonts{
+ Font: []*xlsxFont{{}},
+ },
+ }, &Style{NumFmt: 0, Font: &Font{}})
+ assert.EqualError(t, err, "XML syntax error on line 1: invalid UTF-8")
}
func TestGetFillID(t *testing.T) {
- assert.Equal(t, -1, getFillID(NewFile().stylesReader(), &Style{Fill: Fill{Type: "unknown"}}))
+ styles, err := NewFile().stylesReader()
+ assert.NoError(t, err)
+ assert.Equal(t, -1, getFillID(styles, &Style{Fill: Fill{Type: "unknown"}}))
}
func TestThemeColor(t *testing.T) {