diff --git a/cell_test.go b/cell_test.go index f46b4b9..45e2f24 100644 --- a/cell_test.go +++ b/cell_test.go @@ -3,6 +3,7 @@ package excelize import ( "fmt" "path/filepath" + "strconv" "testing" "time" @@ -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) } } diff --git a/pivotTable.go b/pivotTable.go index 7061bfe..cf04381 100644 --- a/pivotTable.go +++ b/pivotTable.go @@ -21,7 +21,6 @@ import ( type PivotTableOption struct { DataRange string PivotTableRange string - Page []PivotTableField Rows []PivotTableField Columns []PivotTableField Data []PivotTableField @@ -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()) @@ -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{ @@ -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{ @@ -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, @@ -296,33 +289,49 @@ 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 { @@ -330,12 +339,25 @@ func (f *File) addPivotTable(cacheID, pivotTableID int, pivotTableXML string, op } 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 { @@ -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, @@ -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 } diff --git a/pivotTable_test.go b/pivotTable_test.go index 767206b..cc80835 100644 --- a/pivotTable_test.go +++ b/pivotTable_test.go @@ -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{}, "")) }