Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DRAFT: Handle and return more errors #1268

Draft
wants to merge 13 commits into
base: master
Choose a base branch
from
Draft
15 changes: 10 additions & 5 deletions adjust_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import (
)

func TestAdjustMergeCells(t *testing.T) {
f := NewFile()
f, err := NewFile()
assert.NoError(t, err)
// testing adjustAutoFilter with illegal cell coordinates.
assert.EqualError(t, f.adjustMergeCells(&xlsxWorksheet{
MergeCells: &xlsxMergeCells{
Expand Down Expand Up @@ -264,15 +265,17 @@ func TestAdjustMergeCells(t *testing.T) {
assert.Equal(t, 0, len(c.ws.MergeCells.Cells), c.label)
}

f = NewFile()
f, err = NewFile()
assert.NoError(t, err)
p1, p2 := f.adjustMergeCellsHelper(2, 1, 0, 0)
assert.Equal(t, 1, p1)
assert.Equal(t, 2, p2)
f.deleteMergeCell(nil, -1)
}

func TestAdjustAutoFilter(t *testing.T) {
f := NewFile()
f, err := NewFile()
assert.NoError(t, err)
assert.NoError(t, f.adjustAutoFilter(&xlsxWorksheet{
SheetData: xlsxSheetData{
Row: []xlsxRow{{Hidden: true, R: 2}},
Expand All @@ -295,7 +298,8 @@ func TestAdjustAutoFilter(t *testing.T) {
}

func TestAdjustHelper(t *testing.T) {
f := NewFile()
f, err := NewFile()
assert.NoError(t, err)
f.NewSheet("Sheet2")
f.Sheet.Store("xl/worksheets/sheet1.xml", &xlsxWorksheet{
MergeCells: &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: "A:B1"}}},
Expand All @@ -311,7 +315,8 @@ func TestAdjustHelper(t *testing.T) {
}

func TestAdjustCalcChain(t *testing.T) {
f := NewFile()
f, err := NewFile()
assert.NoError(t, err)
f.CalcChain = &xlsxCalcChain{
C: []xlsxCalcChainC{
{R: "B2", I: 2}, {R: "B2", I: 1},
Expand Down
30 changes: 21 additions & 9 deletions calc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ import (
)

func prepareCalcData(cellData [][]interface{}) *File {
f := NewFile()
f, err := NewFile()
if err != nil {
return nil
}
for r, row := range cellData {
for c, value := range row {
cell, _ := CoordinatesToCellName(c+1, r+1)
Expand Down Expand Up @@ -4673,7 +4676,9 @@ func TestCalcDatabase(t *testing.T) {
}

func TestCalcFORMULATEXT(t *testing.T) {
f, formulaText := NewFile(), "=SUM(B1:C1)"
f, err := NewFile()
assert.NoError(t, err)
formulaText := "=SUM(B1:C1)"
assert.NoError(t, f.SetCellFormula("Sheet1", "A1", formulaText))
for _, formula := range []string{"=FORMULATEXT(A1)", "=FORMULATEXT(A:A)", "=FORMULATEXT(A1:B1)"} {
assert.NoError(t, f.SetCellFormula("Sheet1", "D1", formula), formula)
Expand Down Expand Up @@ -4918,7 +4923,8 @@ func TestCalcIRR(t *testing.T) {
}

func TestCalcMAXMINIFS(t *testing.T) {
f := NewFile()
f, err := NewFile()
assert.NoError(t, err)
for cell, row := range map[string][]interface{}{
"A1": {1, -math.MaxFloat64 - 1},
"A2": {2, -math.MaxFloat64 - 2},
Expand Down Expand Up @@ -5202,7 +5208,8 @@ func TestCalcXNPV(t *testing.T) {
}

func TestCalcMATCH(t *testing.T) {
f := NewFile()
f, err := NewFile()
assert.NoError(t, err)
for cell, row := range map[string][]interface{}{
"A1": {"cccc", 7, 4, 16},
"A2": {"dddd", 2, 6, 11},
Expand Down Expand Up @@ -5244,7 +5251,8 @@ func TestCalcMATCH(t *testing.T) {
}

func TestCalcISFORMULA(t *testing.T) {
f := NewFile()
f, err := NewFile()
assert.NoError(t, err)
assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "=ISFORMULA(A1)"))
for _, formula := range []string{"=NA()", "=SUM(A1:A3)"} {
assert.NoError(t, f.SetCellFormula("Sheet1", "A1", formula))
Expand Down Expand Up @@ -5384,7 +5392,8 @@ func TestCalcSLOP(t *testing.T) {
}

func TestCalcSHEET(t *testing.T) {
f := NewFile()
f, err := NewFile()
assert.NoError(t, err)
f.NewSheet("Sheet2")
formulaList := map[string]string{
"=SHEET(\"Sheet2\")": "2",
Expand All @@ -5400,7 +5409,8 @@ func TestCalcSHEET(t *testing.T) {
}

func TestCalcSHEETS(t *testing.T) {
f := NewFile()
f, err := NewFile()
assert.NoError(t, err)
f.NewSheet("Sheet2")
formulaList := map[string]string{
"=SHEETS(Sheet1!A1:B1)": "1",
Expand Down Expand Up @@ -5629,7 +5639,8 @@ func TestCalcNETWORKDAYSandWORKDAY(t *testing.T) {
}

func TestCalcZTEST(t *testing.T) {
f := NewFile()
f, err := NewFile()
assert.NoError(t, err)
assert.NoError(t, f.SetSheetRow("Sheet1", "A1", &[]int{4, 5, 2, 5, 8, 9, 3, 2, 3, 8, 9, 5}))
formulaList := map[string]string{
"=Z.TEST(A1:L1,5)": "0.371103278558538",
Expand Down Expand Up @@ -5700,7 +5711,8 @@ func TestCalcBetainvProbIterator(t *testing.T) {
}

func TestNestedFunctionsWithOperators(t *testing.T) {
f := NewFile()
f, err := NewFile()
assert.NoError(t, err)
formulaList := map[string]string{
`=LEN("KEEP")`: "4",
`=LEN("REMOVEKEEP") - LEN("REMOVE")`: "4",
Expand Down
21 changes: 15 additions & 6 deletions calcchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,42 @@ package excelize
import (
"bytes"
"encoding/xml"
"fmt"
"io"
"log"
)

// calcChainReader provides a function to get the pointer to the structure
// NewCalcChainReader provides a function to get the pointer to the structure
// after deserialization of xl/calcChain.xml.
func (f *File) calcChainReader() *xlsxCalcChain {
func (f *File) NewCalcChainReader() (*xlsxCalcChain, error) {
var err error

if f.CalcChain == nil {
f.CalcChain = new(xlsxCalcChain)
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 nil, fmt.Errorf("xml decode error: %w", err)
}
}

return f.CalcChain, nil
}

// calcChainReader provides a function to get the CalcChain.
func (f *File) calcChainReader() *xlsxCalcChain {
return f.CalcChain
}

// calcChainWriter provides a function to save xl/calcChain.xml after
// serialize structure.
func (f *File) calcChainWriter() {
func (f *File) calcChainWriter() error {
if f.CalcChain != nil && f.CalcChain.C != nil {
output, _ := xml.Marshal(f.CalcChain)
output, err := xml.Marshal(f.CalcChain)
if err != nil {
return err
}
f.saveFileList(defaultXMLPathCalcChain, output)
}
return nil
}

// deleteCalcChain provides a function to remove cell reference on the
Expand Down
12 changes: 9 additions & 3 deletions calcchain_test.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
package excelize

import "testing"
import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestCalcChainReader(t *testing.T) {
f := NewFile()
f, err := NewFile()
assert.NoError(t, err)
f.CalcChain = nil
f.Pkg.Store(defaultXMLPathCalcChain, MacintoshCyrillicCharset)
f.calcChainReader()
}

func TestDeleteCalcChain(t *testing.T) {
f := NewFile()
f, err := NewFile()
assert.NoError(t, err)
f.CalcChain = &xlsxCalcChain{C: []xlsxCalcChainC{}}
f.ContentTypes.Overrides = append(f.ContentTypes.Overrides, xlsxOverride{
PartName: "/xl/calcChain.xml",
Expand Down
45 changes: 32 additions & 13 deletions cell.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,12 @@ var cellTypes = map[string]CellType{
// returned, along with the raw value of the cell. All cells' values will be
// the same in a merged range.
func (f *File) GetCellValue(sheet, axis string, opts ...Options) (string, error) {
sst, err := f.sharedStringsReader()
if err != nil {
return "", err
}
return f.getCellStringFunc(sheet, axis, func(x *xlsxWorksheet, c *xlsxC) (string, bool, error) {
val, err := c.getValueFrom(f, f.sharedStringsReader(), parseOptions(opts...).RawCellValue)
val, err := c.getValueFrom(f, sst, parseOptions(opts...).RawCellValue)
return val, true, err
})
}
Expand Down Expand Up @@ -404,7 +408,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 {
Expand Down Expand Up @@ -747,7 +754,10 @@ func (f *File) SetCellHyperLink(sheet, axis, link, linkType string, opts ...Hype
case "External":
sheetPath := f.sheetMap[trimSheetName(sheet)]
sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(sheetPath, "xl/worksheets/") + ".rels"
rID := f.setRels(linkData.RID, sheetRels, SourceRelationshipHyperLink, link, linkType)
rID, err := f.setRels(linkData.RID, sheetRels, SourceRelationshipHyperLink, link, linkType)
if err != nil {
return err
}
linkData = xlsxHyperlink{
Ref: axis,
}
Expand Down Expand Up @@ -826,7 +836,10 @@ func (f *File) GetCellRichText(sheet, cell string) (runs []RichTextRun, err erro
if err != nil || cellData.T != "s" {
return
}
sst := f.sharedStringsReader()
sst, err := f.sharedStringsReader()
if err != nil {
return
}
if len(sst.SI) <= siIdx || siIdx < 0 {
return
}
Expand Down Expand Up @@ -998,7 +1011,10 @@ func (f *File) SetCellRichText(sheet, cell string, runs []RichTextRun) error {
}
cellData.S = f.prepareCellStyle(ws, col, row, cellData.S)
si := xlsxSI{}
sst := f.sharedStringsReader()
sst, err := f.sharedStringsReader()
if err != nil {
return err
}
var textRuns []xlsxR
totalCellChars := 0
for _, textRun := range runs {
Expand Down Expand Up @@ -1133,16 +1149,17 @@ func (f *File) getCellStringFunc(sheet, axis 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) (formatted string) {
formatted = v
if raw {
return v
return
}
if s == 0 {
return v
return
}
styleSheet := f.stylesReader()
if s >= len(styleSheet.CellXfs.Xf) {
return v
return
}
var numFmtID int
if styleSheet.CellXfs.Xf[s].NumFmtID != nil {
Expand All @@ -1153,17 +1170,19 @@ 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)
formatted = ok(v, builtInNumFmt[numFmtID], date1904)
return
}
if styleSheet == nil || styleSheet.NumFmts == nil {
return v
return
}
for _, xlsxFmt := range styleSheet.NumFmts.NumFmt {
if xlsxFmt.NumFmtID == numFmtID {
return format(v, xlsxFmt.FormatCode, date1904)
formatted = format(v, xlsxFmt.FormatCode, date1904)
return
}
}
return v
return
}

// prepareCellStyle provides a function to prepare style index of cell in
Expand Down
Loading