Skip to content

Commit

Permalink
- Resolve #611, fix failure BenchmarkSetCellValue
Browse files Browse the repository at this point in the history
- Allow empty filter, data, and rows in the pivot table
- Add more test case for pivot table
  • Loading branch information
xuri committed Apr 9, 2020
1 parent e36650f commit 10115b5
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 24 deletions.
5 changes: 3 additions & 2 deletions cell_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package excelize
import (
"fmt"
"path/filepath"
"strconv"
"testing"
"time"

Expand Down Expand Up @@ -122,9 +123,9 @@ func BenchmarkSetCellValue(b *testing.B) {
cols := []string{"A", "B", "C", "D", "E", "F"}
f := NewFile()
b.ResetTimer()
for i := 0; i < b.N; i++ {
for i := 1; i <= b.N; i++ {
for j := 0; j < len(values); j++ {
if err := f.SetCellValue("Sheet1", fmt.Sprint(cols[j], i), values[j]); err != nil {
if err := f.SetCellValue("Sheet1", cols[j]+strconv.Itoa(i), values[j]); err != nil {
b.Error(err)
}
}
Expand Down
68 changes: 46 additions & 22 deletions pivotTable.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
type PivotTableOption struct {
DataRange string
PivotTableRange string
Page []PivotTableField
Rows []PivotTableField
Columns []PivotTableField
Data []PivotTableField
Expand Down Expand Up @@ -194,7 +193,6 @@ func (f *File) adjustRange(rangeStr string) (string, []int, error) {
// fields.
func (f *File) getPivotFieldsOrder(dataRange string) ([]string, error) {
order := []string{}
// data range has been checked
dataSheet, coordinates, err := f.adjustRange(dataRange)
if err != nil {
return order, fmt.Errorf("parameter 'DataRange' parsing error: %s", err.Error())
Expand All @@ -217,10 +215,8 @@ func (f *File) addPivotCache(pivotCacheID int, pivotCacheXML string, opt *PivotT
if err != nil {
return fmt.Errorf("parameter 'DataRange' parsing error: %s", err.Error())
}
order, err := f.getPivotFieldsOrder(opt.DataRange)
if err != nil {
return err
}
// data range has been checked
order, _ := f.getPivotFieldsOrder(opt.DataRange)
hcell, _ := CoordinatesToCellName(coordinates[0], coordinates[1])
vcell, _ := CoordinatesToCellName(coordinates[2], coordinates[3])
pc := xlsxPivotCacheDefinition{
Expand Down Expand Up @@ -272,7 +268,6 @@ func (f *File) addPivotTable(cacheID, pivotTableID int, pivotTableXML string, op
FirstHeaderRow: 1,
},
PivotFields: &xlsxPivotFields{},
RowFields: &xlsxRowFields{},
RowItems: &xlsxRowItems{
Count: 1,
I: []*xlsxI{
Expand All @@ -285,8 +280,6 @@ func (f *File) addPivotTable(cacheID, pivotTableID int, pivotTableXML string, op
Count: 1,
I: []*xlsxI{{}},
},
PageFields: &xlsxPageFields{},
DataFields: &xlsxDataFields{},
PivotTableStyleInfo: &xlsxPivotTableStyleInfo{
Name: "PivotStyleLight16",
ShowRowHeaders: true,
Expand All @@ -296,46 +289,75 @@ func (f *File) addPivotTable(cacheID, pivotTableID int, pivotTableXML string, op
}

// pivot fields
err = f.addPivotFields(&pt, opt)
if err != nil {
return err
}
_ = f.addPivotFields(&pt, opt)

// count pivot fields
pt.PivotFields.Count = len(pt.PivotFields.PivotField)

// data range has been checked
_ = f.addPivotRowFields(&pt, opt)
_ = f.addPivotColFields(&pt, opt)
_ = f.addPivotPageFields(&pt, opt)
_ = f.addPivotDataFields(&pt, opt)

pivotTable, err := xml.Marshal(pt)
f.saveFileList(pivotTableXML, pivotTable)
return err
}

// addPivotRowFields provides a method to add row fields for pivot table by
// given pivot table options.
func (f *File) addPivotRowFields(pt *xlsxPivotTableDefinition, opt *PivotTableOption) error {
// row fields
rowFieldsIndex, err := f.getPivotFieldsIndex(opt.Rows, opt)
if err != nil {
return err
}
for _, fieldIdx := range rowFieldsIndex {
if pt.RowFields == nil {
pt.RowFields = &xlsxRowFields{}
}
pt.RowFields.Field = append(pt.RowFields.Field, &xlsxField{
X: fieldIdx,
})
}

// count row fields
pt.RowFields.Count = len(pt.RowFields.Field)

err = f.addPivotColFields(&pt, opt)
if err != nil {
return err
if pt.RowFields != nil {
pt.RowFields.Count = len(pt.RowFields.Field)
}
return err
}

// addPivotPageFields provides a method to add page fields for pivot table by
// given pivot table options.
func (f *File) addPivotPageFields(pt *xlsxPivotTableDefinition, opt *PivotTableOption) error {
// page fields
pageFieldsIndex, err := f.getPivotFieldsIndex(opt.Filter, opt)
if err != nil {
return err
}
pageFieldsName := f.getPivotTableFieldsName(opt.Filter)
for idx, pageField := range pageFieldsIndex {
if pt.PageFields == nil {
pt.PageFields = &xlsxPageFields{}
}
pt.PageFields.PageField = append(pt.PageFields.PageField, &xlsxPageField{
Name: pageFieldsName[idx],
Fld: pageField,
})
}

// count page fields
if pt.PageFields != nil {
pt.PageFields.Count = len(pt.PageFields.PageField)
}
return err
}

// addPivotDataFields provides a method to add data fields for pivot table by
// given pivot table options.
func (f *File) addPivotDataFields(pt *xlsxPivotTableDefinition, opt *PivotTableOption) error {
// data fields
dataFieldsIndex, err := f.getPivotFieldsIndex(opt.Data, opt)
if err != nil {
Expand All @@ -344,6 +366,9 @@ func (f *File) addPivotTable(cacheID, pivotTableID int, pivotTableXML string, op
dataFieldsSubtotals := f.getPivotTableFieldsSubtotal(opt.Data)
dataFieldsName := f.getPivotTableFieldsName(opt.Data)
for idx, dataField := range dataFieldsIndex {
if pt.DataFields == nil {
pt.DataFields = &xlsxDataFields{}
}
pt.DataFields.DataField = append(pt.DataFields.DataField, &xlsxDataField{
Name: dataFieldsName[idx],
Fld: dataField,
Expand All @@ -352,10 +377,9 @@ func (f *File) addPivotTable(cacheID, pivotTableID int, pivotTableXML string, op
}

// count data fields
pt.DataFields.Count = len(pt.DataFields.DataField)

pivotTable, err := xml.Marshal(pt)
f.saveFileList(pivotTableXML, pivotTable)
if pt.DataFields != nil {
pt.DataFields.Count = len(pt.DataFields.DataField)
}
return err
}

Expand Down
40 changes: 40 additions & 0 deletions pivotTable_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,46 @@ func TestAddPivotTable(t *testing.T) {
assert.EqualError(t, err, `parameter 'DataRange' parsing error: parameter is required`)
}

func TestAddPivotRowFields(t *testing.T) {
f := NewFile()
// Test invalid data range
assert.EqualError(t, f.addPivotRowFields(&xlsxPivotTableDefinition{}, &PivotTableOption{
DataRange: "Sheet1!$A$1:$A$1",
}), `parameter 'DataRange' parsing error: parameter is invalid`)
}

func TestAddPivotPageFields(t *testing.T) {
f := NewFile()
// Test invalid data range
assert.EqualError(t, f.addPivotPageFields(&xlsxPivotTableDefinition{}, &PivotTableOption{
DataRange: "Sheet1!$A$1:$A$1",
}), `parameter 'DataRange' parsing error: parameter is invalid`)
}

func TestAddPivotDataFields(t *testing.T) {
f := NewFile()
// Test invalid data range
assert.EqualError(t, f.addPivotDataFields(&xlsxPivotTableDefinition{}, &PivotTableOption{
DataRange: "Sheet1!$A$1:$A$1",
}), `parameter 'DataRange' parsing error: parameter is invalid`)
}

func TestAddPivotColFields(t *testing.T) {
f := NewFile()
// Test invalid data range
assert.EqualError(t, f.addPivotColFields(&xlsxPivotTableDefinition{}, &PivotTableOption{
DataRange: "Sheet1!$A$1:$A$1",
Columns: []PivotTableField{{Data: "Type"}},
}), `parameter 'DataRange' parsing error: parameter is invalid`)
}

func TestGetPivotFieldsOrder(t *testing.T) {
f := NewFile()
// Test get pivot fields order with not exist worksheet
_, err := f.getPivotFieldsOrder("SheetN!$A$1:$E$31")
assert.EqualError(t, err, "sheet SheetN is not exist")
}

func TestInStrSlice(t *testing.T) {
assert.EqualValues(t, -1, inStrSlice([]string{}, ""))
}
Expand Down

0 comments on commit 10115b5

Please sign in to comment.