From 4db31efb5618c7bb6779ba95de8b42538d8f4a28 Mon Sep 17 00:00:00 2001 From: Thomas Charbonnel Date: Wed, 27 Jul 2022 14:42:50 +0800 Subject: [PATCH] #1284 WIP add formula --- lib.go | 3 +++ rows.go | 15 +++++++++++---- rows_test.go | 18 ++++++++++++++++++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/lib.go b/lib.go index 99118ff079..75d24a30c4 100644 --- a/lib.go +++ b/lib.go @@ -698,6 +698,9 @@ func (f *File) addSheetNameSpace(sheet string, ns xml.Attr) { // the precision for the numeric. func isNumeric(s string) (bool, int) { dot, e, n, p := false, false, false, 0 + if s == "" { + return false, 0 + } for i, v := range s { if v == '.' { if dot { diff --git a/rows.go b/rows.go index 4f29f34cee..e661670615 100644 --- a/rows.go +++ b/rows.go @@ -74,7 +74,8 @@ type Rows struct { err error curRow, seekRow int needClose, rawCellValue bool - sheet string + sheetPath string + sheetName string f *File tempFile *os.File sst *xlsxSST @@ -230,9 +231,13 @@ func (rows *Rows) rowXMLHandler(rowIterator *rowXMLIterator, xmlElement *xml.Sta // rowIterator.columns = append(appendSpace(blank, rowIterator.columns), val) //} blank := rowIterator.cellCol - len(rowIterator.columns) - if val, _ := colCell.getTypedValueFrom(rows.f, rows.sst); val != "" || colCell.F != nil { - rowIterator.columns = append(appendSpace(blank, rowIterator.columns), Cell{Value: val, StyleID: colCell.S}) + var formula string + if colCell.F != nil { + formula, _ = rows.f.GetCellFormula(rows.sheetName, colCell.R) } + //if val, _ := colCell.getTypedValueFrom(rows.f, rows.sst); val != "" || colCell.F != nil { + val, _ := colCell.getTypedValueFrom(rows.f, rows.sst) + rowIterator.columns = append(appendSpace(blank, rowIterator.columns), Cell{Value: val, StyleID: colCell.S, Formula: formula}) } } @@ -272,7 +277,7 @@ func (f *File) Rows(sheet string) (*Rows, error) { f.saveFileList(name, f.replaceNameSpaceBytes(name, output)) } var err error - rows := Rows{f: f, sheet: name} + rows := Rows{f: f, sheetPath: name, sheetName: sheet} rows.needClose, rows.decoder, rows.tempFile, err = f.xmlDecoder(name) return &rows, err } @@ -544,6 +549,8 @@ func (c *xlsxC) getTypedValueFrom(f *File, d *xlsxSST) (interface{}, error) { } else { return precisionV, nil } + } else { + return nil, nil } // TODO: add support for other possible values of T (https://stackoverflow.com/questions/18334314/what-do-excel-xml-cell-attribute-values-mean) } diff --git a/rows_test.go b/rows_test.go index 019fd360d2..fbff60441e 100644 --- a/rows_test.go +++ b/rows_test.go @@ -69,12 +69,30 @@ func TestRowsIterator(t *testing.T) { rows, err := f.Rows(sheetName) require.NoError(t, err) + expectedCells := [][]Cell{ + {Cell{Value: "Monitor", StyleID: 1}, Cell{StyleID: 1}, Cell{Value: "Brand", StyleID: 2}, Cell{StyleID: 2}, Cell{Value: "inlineStr"}}, + {Cell{Value: "> 23 Inch", StyleID: 1}, Cell{Value: int64(19), StyleID: 1}, Cell{Value: "HP", StyleID: 3}, Cell{Value: int64(200), StyleID: 4}}, + {Cell{Value: "20-23 Inch", StyleID: 1}, Cell{Value: int64(24), StyleID: 1}, Cell{Value: "DELL", StyleID: 3}, Cell{Value: int64(450), StyleID: 4}}, + {Cell{Value: "17-20 Inch", StyleID: 1}, Cell{Value: int64(56), StyleID: 1}, Cell{Value: "Lenove", StyleID: 3}, Cell{Value: int64(200), StyleID: 4}}, + {Cell{Value: "< 17 Inch", StyleID: 5}, Cell{Value: int64(21), StyleID: 1}, Cell{Value: "SONY", StyleID: 3}, Cell{Value: int64(510), StyleID: 4}}, + {Cell{}, Cell{}, Cell{Value: "Acer", StyleID: 3}, Cell{Value: int64(315), StyleID: 4}}, + {Cell{}, Cell{}, Cell{Value: "IBM", StyleID: 3}, Cell{Value: int64(127), StyleID: 4}}, + {Cell{}, Cell{}, Cell{Value: "ASUS", StyleID: 4}, Cell{Value: int64(89), StyleID: 4}}, + {Cell{}, Cell{}, Cell{Value: "Apple", StyleID: 4}, Cell{Value: int64(348), StyleID: 4}}, + {Cell{}, Cell{}, Cell{Value: "SAMSUNG", StyleID: 4}, Cell{Value: int64(53), StyleID: 4}}, + {Cell{}, Cell{}, Cell{Value: "Other", StyleID: 4}, Cell{Value: int64(37), StyleID: 4}, Cell{Formula: "B2+B3", StyleID: 4}, Cell{Formula: "IF(B2>0, (D2/B2)*100, 0)", StyleID: 4}, Cell{Formula: "IF(B2>0, (D2/B2)*100, 0)", StyleID: 4}, Cell{Formula: "IF(D2>0, (F2/D2)*100, 0)", StyleID: 4}, Cell{Formula: "IF(D2>0, (F2/D2)*100, 0)", StyleID: 4}}, + } + gotCells := [][]Cell{} for rows.Next() { rowCount++ require.True(t, rowCount <= expectedNumRow, "rowCount is greater than expected") + cols, err := rows.Columns() + require.NoError(t, err) + gotCells = append(gotCells, cols) } assert.Equal(t, expectedNumRow, rowCount) + assert.Equal(t, expectedCells, gotCells) assert.NoError(t, rows.Close()) assert.NoError(t, f.Close())