From 234c5541567e721c33cf433846619ed7aece12d8 Mon Sep 17 00:00:00 2001 From: Thomas Charbonnel Date: Mon, 25 Jul 2022 15:18:03 +0800 Subject: [PATCH] #1284 WIP --- cell_test.go | 78 ++++++++++++++++++++++++------------------------ excelize_test.go | 4 +-- rows.go | 73 +++++++++++++++++++++++++++++++++++++++----- rows_test.go | 7 ++--- 4 files changed, 108 insertions(+), 54 deletions(-) diff --git a/cell_test.go b/cell_test.go index fb1e8ef585..48a1c2fb77 100644 --- a/cell_test.go +++ b/cell_test.go @@ -224,7 +224,7 @@ func TestGetCellValue(t *testing.T) { f.checked = nil cells := []string{"A3", "A4", "B4", "A7", "B7"} rows, err := f.GetRows("Sheet1") - assert.Equal(t, [][]string{nil, nil, {"A3"}, {"A4", "B4"}, nil, nil, {"A7", "B7"}, {"A8", "B8"}}, rows) + assert.Equal(t, [][]Cell{nil, nil, {Cell{Value: "A3"}}, {Cell{Value: "A4"}, Cell{Value: "B4"}}, nil, nil, {Cell{Value: "A7"}, Cell{Value: "B7"}}, {Cell{Value: "A8"}, Cell{Value: "B8"}}}, rows) assert.NoError(t, err) for _, cell := range cells { value, err := f.GetCellValue("Sheet1", cell) @@ -246,21 +246,21 @@ func TestGetCellValue(t *testing.T) { f.Pkg.Store("xl/worksheets/sheet1.xml", []byte(fmt.Sprintf(sheetData, `A2B2`))) f.checked = nil rows, err = f.GetRows("Sheet1") - assert.Equal(t, [][]string{nil, {"A2", "B2"}}, rows) + assert.Equal(t, [][]Cell{nil, {Cell{Value: "A2"}, Cell{Value: "B2"}}}, rows) assert.NoError(t, err) f.Sheet.Delete("xl/worksheets/sheet1.xml") f.Pkg.Store("xl/worksheets/sheet1.xml", []byte(fmt.Sprintf(sheetData, `A1B1`))) f.checked = nil rows, err = f.GetRows("Sheet1") - assert.Equal(t, [][]string{{"A1", "B1"}}, rows) + assert.Equal(t, [][]Cell{{Cell{Value: "A1"}, Cell{Value: "B1"}}}, rows) assert.NoError(t, err) f.Sheet.Delete("xl/worksheets/sheet1.xml") f.Pkg.Store("xl/worksheets/sheet1.xml", []byte(fmt.Sprintf(sheetData, `A3A4B4A7B7A8B8`))) f.checked = nil rows, err = f.GetRows("Sheet1") - assert.Equal(t, [][]string{{"A3"}, {"A4", "B4"}, nil, nil, nil, nil, {"A7", "B7"}, {"A8", "B8"}}, rows) + assert.Equal(t, [][]Cell{{Cell{Value: "A3"}}, {Cell{Value: "A4"}, Cell{Value: "B4"}}, nil, nil, nil, nil, {Cell{Value: "A7"}, Cell{Value: "B7"}}, {Cell{Value: "A8"}, Cell{Value: "B8"}}}, rows) assert.NoError(t, err) f.Sheet.Delete("xl/worksheets/sheet1.xml") @@ -270,13 +270,13 @@ func TestGetCellValue(t *testing.T) { assert.Equal(t, "H6", cell) assert.NoError(t, err) rows, err = f.GetRows("Sheet1") - assert.Equal(t, [][]string{ - {"A6", "B6", "C6"}, + assert.Equal(t, [][]Cell{ + {Cell{Value: "A6"}, Cell{Value: "B6"}, Cell{Value: "C6"}}, nil, - {"100", "B3"}, - {"", "", "", "", "", "F4"}, + {Cell{Value: int64(100)}, Cell{Value: "B3"}}, + {Cell{}, Cell{}, Cell{}, Cell{}, Cell{}, Cell{Value: "F4"}}, nil, - {"", "", "", "", "", "", "", "H6"}, + {Cell{}, Cell{}, Cell{}, Cell{}, Cell{}, Cell{}, Cell{}, Cell{Value: "H6"}}, }, rows) assert.NoError(t, err) @@ -314,36 +314,36 @@ func TestGetCellValue(t *testing.T) { `))) f.checked = nil rows, err = f.GetRows("Sheet1") - assert.Equal(t, [][]string{{ - "2422.3", - "2422.3", - "12.4", - "964", - "1101.6", - "275.4", - "68.9", - "44385.2083333333", - "5.1", - "5.11", - "5.1", - "5.111", - "5.1111", - "2422.012345678", - "2422.0123456789", - "12.012345678901", - "964", - "1101.6", - "275.4", - "68.9", - "0.08888", - "0.00004", - "2422.3", - "1101.6", - "275.4", - "68.9", - "1.1", - "1234567890123_4", - "123456789_0123_4", + assert.Equal(t, [][]Cell{{ + Cell{Value: 2422.3}, + Cell{Value: 2422.3}, + Cell{Value: 12.4}, + Cell{Value: int64(964)}, + Cell{Value: 1101.6}, + Cell{Value: 275.4}, + Cell{Value: 68.9}, + Cell{Value: 44385.2083333333}, + Cell{Value: 5.1}, + Cell{Value: 5.11}, + Cell{Value: 5.1}, + Cell{Value: 5.111}, + Cell{Value: 5.1111}, + Cell{Value: 2422.012345678}, + Cell{Value: 2422.0123456789}, + Cell{Value: 12.012345678901}, + Cell{Value: int64(964)}, + Cell{Value: 1101.6}, + Cell{Value: 275.4}, + Cell{Value: 68.9}, + Cell{Value: 0.08888}, + Cell{Value: 0.00004}, + Cell{Value: 2422.3}, + Cell{Value: 1101.6}, + Cell{Value: 275.4}, + Cell{Value: 68.9}, + Cell{Value: 1.1}, + Cell{Value: "1234567890123_4"}, + Cell{Value: "123456789_0123_4"}, }}, rows) assert.NoError(t, err) } diff --git a/excelize_test.go b/excelize_test.go index f1b9903cbb..20368d0275 100644 --- a/excelize_test.go +++ b/excelize_test.go @@ -1114,12 +1114,12 @@ func TestSharedStrings(t *testing.T) { if !assert.NoError(t, err) { t.FailNow() } - assert.Equal(t, "A", rows[0][0]) + assert.Equal(t, Cell{Value: "A"}, rows[0][0]) rows, err = f.GetRows("Sheet2") if !assert.NoError(t, err) { t.FailNow() } - assert.Equal(t, "Test Weight (Kgs)", rows[0][0]) + assert.Equal(t, Cell{Value: "Test Weight (Kgs)"}, rows[0][0]) assert.NoError(t, f.Close()) } diff --git a/rows.go b/rows.go index 9ef52cadd4..4f29f34cee 100644 --- a/rows.go +++ b/rows.go @@ -49,12 +49,12 @@ import ( // fmt.Println() // } // -func (f *File) GetRows(sheet string, opts ...Options) ([][]string, error) { +func (f *File) GetRows(sheet string, opts ...Options) ([][]Cell, error) { rows, err := f.Rows(sheet) if err != nil { return nil, err } - results, cur, max := make([][]string, 0, 64), 0, 0 + results, cur, max := make([][]Cell, 0, 64), 0, 0 for rows.Next() { cur++ row, err := rows.Columns(opts...) @@ -147,7 +147,7 @@ func (rows *Rows) Close() error { // Columns return the current row's column values. This fetches the worksheet // data as a stream, returns each cell in a row as is, and will not skip empty // rows in the tail of the worksheet. -func (rows *Rows) Columns(opts ...Options) ([]string, error) { +func (rows *Rows) Columns(opts ...Options) ([]Cell, error) { if rows.curRow > rows.seekRow { return nil, nil } @@ -190,9 +190,9 @@ func (rows *Rows) Columns(opts ...Options) ([]string, error) { } // appendSpace append blank characters to slice by given length and source slice. -func appendSpace(l int, s []string) []string { +func appendSpace(l int, s []Cell) []Cell { for i := 1; i < l; i++ { - s = append(s, "") + s = append(s, Cell{}) } return s } @@ -211,7 +211,7 @@ type rowXMLIterator struct { err error inElement string cellCol int - columns []string + columns []Cell } // rowXMLHandler parse the row XML element of the worksheet. @@ -225,9 +225,13 @@ func (rows *Rows) rowXMLHandler(rowIterator *rowXMLIterator, xmlElement *xml.Sta return } } + //blank := rowIterator.cellCol - len(rowIterator.columns) + //if val, _ := colCell.getValueFrom(rows.f, rows.sst, raw); val != "" || colCell.F != nil { + // rowIterator.columns = append(appendSpace(blank, rowIterator.columns), val) + //} blank := rowIterator.cellCol - len(rowIterator.columns) - if val, _ := colCell.getValueFrom(rows.f, rows.sst, raw); val != "" || colCell.F != nil { - rowIterator.columns = append(appendSpace(blank, rowIterator.columns), val) + 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}) } } } @@ -494,6 +498,59 @@ func (c *xlsxC) getValueFrom(f *File, d *xlsxSST, raw bool) (string, error) { } } +func (c *xlsxC) getTypedValueFrom(f *File, d *xlsxSST) (interface{}, error) { + f.Lock() + defer f.Unlock() + switch c.T { + case "b": + if c.V == "1" { + return true, nil + } else if c.V == "0" { + return false, nil + } + case "s": + if c.V != "" { + xlsxSI := 0 + xlsxSI, _ = strconv.Atoi(c.V) + if _, ok := f.tempFiles.Load(defaultXMLPathSharedStrings); ok { + return f.getFromStringItem(xlsxSI), nil + } + if len(d.SI) > xlsxSI { + return d.SI[xlsxSI].String(), nil + } + } + case "str": + return c.V, nil + case "inlineStr": + if c.IS != nil { + return c.IS.String(), nil + } + return c.V, nil + default: + if isNum, precision := isNumeric(c.V); isNum { + var precisionV string + if precision == 0 { + precisionV = roundPrecision(c.V, 15) + } else { + precisionV = roundPrecision(c.V, -1) + } + + vi, erri := strconv.ParseInt(precisionV, 10, 64) + vf, errf := strconv.ParseFloat(precisionV, 64) + if erri == nil { + return vi, nil + } else if errf == nil { + return vf, nil + } else { + return precisionV, nil + } + } + // TODO: add support for other possible values of T (https://stackoverflow.com/questions/18334314/what-do-excel-xml-cell-attribute-values-mean) + } + + return c.V, nil +} + // roundPrecision provides a function to format floating-point number text // with precision, if the given text couldn't be parsed to float, this will // return the original string. diff --git a/rows_test.go b/rows_test.go index ec25bd938a..019fd360d2 100644 --- a/rows_test.go +++ b/rows_test.go @@ -24,11 +24,11 @@ func TestRows(t *testing.T) { t.FailNow() } - var collectedRows [][]string + var collectedRows [][]Cell for rows.Next() { columns, err := rows.Columns() assert.NoError(t, err) - collectedRows = append(collectedRows, trimSliceSpace(columns)) + collectedRows = append(collectedRows, columns) } if !assert.NoError(t, rows.Error()) { t.FailNow() @@ -37,9 +37,6 @@ func TestRows(t *testing.T) { returnedRows, err := f.GetRows(sheet2) assert.NoError(t, err) - for i := range returnedRows { - returnedRows[i] = trimSliceSpace(returnedRows[i]) - } if !assert.Equal(t, collectedRows, returnedRows) { t.FailNow() }