Resolve #582, support to set date field subtotal and names for pivot table

- typo fixed and update do.dev badge in the README.
This commit is contained in:
xuri 2020-02-21 23:07:43 +08:00
parent ad883caa0f
commit 6dcb7013ee
No known key found for this signature in database
GPG Key ID: BA5E5BB1C948EDF7
4 changed files with 77 additions and 10 deletions

View File

@ -4,7 +4,7 @@
<a href="https://travis-ci.org/360EntSecGroup-Skylar/excelize"><img src="https://travis-ci.org/360EntSecGroup-Skylar/excelize.svg?branch=master" alt="Build Status"></a>
<a href="https://codecov.io/gh/360EntSecGroup-Skylar/excelize"><img src="https://codecov.io/gh/360EntSecGroup-Skylar/excelize/branch/master/graph/badge.svg" alt="Code Coverage"></a>
<a href="https://goreportcard.com/report/github.com/360EntSecGroup-Skylar/excelize"><img src="https://goreportcard.com/badge/github.com/360EntSecGroup-Skylar/excelize" alt="Go Report Card"></a>
<a href="https://godoc.org/github.com/360EntSecGroup-Skylar/excelize"><img src="https://godoc.org/github.com/360EntSecGroup-Skylar/excelize?status.svg" alt="GoDoc"></a>
<a href="https://pkg.go.dev/github.com/360EntSecGroup-Skylar/excelize/v2?tab=doc"><img src="https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white" alt="go.dev"></a>
<a href="https://opensource.org/licenses/BSD-3-Clause"><img src="https://img.shields.io/badge/license-bsd-orange.svg" alt="Licenses"></a>
<a href="https://www.paypal.me/xuri"><img src="https://img.shields.io/badge/Donate-PayPal-green.svg" alt="Donate"></a>
</p>

View File

@ -4,7 +4,7 @@
<a href="https://travis-ci.org/360EntSecGroup-Skylar/excelize"><img src="https://travis-ci.org/360EntSecGroup-Skylar/excelize.svg?branch=master" alt="Build Status"></a>
<a href="https://codecov.io/gh/360EntSecGroup-Skylar/excelize"><img src="https://codecov.io/gh/360EntSecGroup-Skylar/excelize/branch/master/graph/badge.svg" alt="Code Coverage"></a>
<a href="https://goreportcard.com/report/github.com/360EntSecGroup-Skylar/excelize"><img src="https://goreportcard.com/badge/github.com/360EntSecGroup-Skylar/excelize" alt="Go Report Card"></a>
<a href="https://godoc.org/github.com/360EntSecGroup-Skylar/excelize"><img src="https://godoc.org/github.com/360EntSecGroup-Skylar/excelize?status.svg" alt="GoDoc"></a>
<a href="https://pkg.go.dev/github.com/360EntSecGroup-Skylar/excelize/v2?tab=doc"><img src="https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white" alt="go.dev"></a>
<a href="https://opensource.org/licenses/BSD-3-Clause"><img src="https://img.shields.io/badge/license-bsd-orange.svg" alt="Licenses"></a>
<a href="https://www.paypal.me/xuri"><img src="https://img.shields.io/badge/Donate-PayPal-green.svg" alt="Donate"></a>
</p>

View File

@ -20,6 +20,8 @@ import (
// PivotTableOption directly maps the format settings of the pivot table.
type PivotTableOption struct {
DataRange string
DataSubtotal string
DataFieldName string
PivotTableRange string
Rows []string
Columns []string
@ -28,9 +30,29 @@ type PivotTableOption struct {
}
// AddPivotTable provides the method to add pivot table by given pivot table
// options. For example, create a pivot table on the Sheet1!$G$2:$M$34 area
// with the region Sheet1!$A$1:$E$31 as the data source, summarize by sum for
// sales:
// options.
//
// DataSubtotal specifies the aggregation function that applies to this data
// field. The default value is sum. The possible values for this attribute
// are:
//
// Average
// Count
// CountNums
// Max
// Min
// Product
// StdDev
// StdDevp
// Sum
// Var
// Varp
//
// DataFieldName specifies the name of the data field. Maximum 255 characters
// are allowed in data field name, excess characters will be truncated.
//
// For example, create a pivot table on the Sheet1!$G$2:$M$34 area with the
// region Sheet1!$A$1:$E$31 as the data source, summarize by sum for sales:
//
// package main
//
@ -62,6 +84,8 @@ type PivotTableOption struct {
// Rows: []string{"Month", "Year"},
// Columns: []string{"Type"},
// Data: []string{"Sales"},
// DataSubtotal: "Sum",
// DataFieldName: "Summarize as Sum",
// }); err != nil {
// fmt.Println(err)
// }
@ -278,9 +302,9 @@ func (f *File) addPivotTable(cacheID, pivotTableID int, pivotTableXML string, op
if err != nil {
return err
}
for _, filedIdx := range rowFieldsIndex {
for _, fieldIdx := range rowFieldsIndex {
pt.RowFields.Field = append(pt.RowFields.Field, &xlsxField{
X: filedIdx,
X: fieldIdx,
})
}
@ -297,9 +321,15 @@ func (f *File) addPivotTable(cacheID, pivotTableID int, pivotTableXML string, op
if err != nil {
return err
}
dataFieldName := opt.DataFieldName
if len(dataFieldName) > 255 {
dataFieldName = dataFieldName[0:255]
}
for _, dataField := range dataFieldsIndex {
pt.DataFields.DataField = append(pt.DataFields.DataField, &xlsxDataField{
Fld: dataField,
Name: dataFieldName,
Fld: dataField,
Subtotal: f.getFieldsSubtotal(opt),
})
}
@ -336,9 +366,9 @@ func (f *File) addPivotColFields(pt *xlsxPivotTableDefinition, opt *PivotTableOp
if err != nil {
return err
}
for _, filedIdx := range colFieldsIndex {
for _, fieldIdx := range colFieldsIndex {
pt.ColFields.Field = append(pt.ColFields.Field, &xlsxField{
X: filedIdx,
X: fieldIdx,
})
}
@ -430,6 +460,18 @@ func (f *File) getPivotFieldsIndex(fields []string, opt *PivotTableOption) ([]in
return pivotFieldsIndex, nil
}
// getFieldsSubtotal prepare data subtotal by given fields and pivot option.
func (f *File) getFieldsSubtotal(opt *PivotTableOption) (subtotal string) {
subtotal = "sum"
for _, enum := range []string{"average", "count", "countNums", "max", "min", "product", "stdDev", "stdDevp", "sum", "var", "varp"} {
if strings.ToLower(enum) == strings.ToLower(opt.DataSubtotal) {
subtotal = enum
return
}
}
return
}
// addWorkbookPivotCache add the association ID of the pivot cache in xl/workbook.xml.
func (f *File) addWorkbookPivotCache(RID int) int {
wb := f.workbookReader()

View File

@ -4,6 +4,7 @@ import (
"fmt"
"math/rand"
"path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/assert"
@ -30,6 +31,8 @@ func TestAddPivotTable(t *testing.T) {
Rows: []string{"Month", "Year"},
Columns: []string{"Type"},
Data: []string{"Sales"},
DataSubtotal: "Sum",
DataFieldName: "Summarize by Sum",
}))
// Use different order of coordinate tests
assert.NoError(t, f.AddPivotTable(&PivotTableOption{
@ -38,6 +41,8 @@ func TestAddPivotTable(t *testing.T) {
Rows: []string{"Month", "Year"},
Columns: []string{"Type"},
Data: []string{"Sales"},
DataSubtotal: "Average",
DataFieldName: "Summarize by Average",
}))
assert.NoError(t, f.AddPivotTable(&PivotTableOption{
@ -46,6 +51,8 @@ func TestAddPivotTable(t *testing.T) {
Rows: []string{"Month", "Year"},
Columns: []string{"Region"},
Data: []string{"Sales"},
DataSubtotal: "Count",
DataFieldName: "Summarize by Count",
}))
assert.NoError(t, f.AddPivotTable(&PivotTableOption{
DataRange: "Sheet1!$A$1:$E$31",
@ -53,12 +60,16 @@ func TestAddPivotTable(t *testing.T) {
Rows: []string{"Month"},
Columns: []string{"Region", "Year"},
Data: []string{"Sales"},
DataSubtotal: "CountNums",
DataFieldName: "Summarize by CountNums",
}))
assert.NoError(t, f.AddPivotTable(&PivotTableOption{
DataRange: "Sheet1!$A$1:$E$31",
PivotTableRange: "Sheet1!$AE$2:$AG$33",
Rows: []string{"Month", "Year"},
Data: []string{"Sales"},
DataSubtotal: "Max",
DataFieldName: "Summarize by Max",
}))
f.NewSheet("Sheet2")
assert.NoError(t, f.AddPivotTable(&PivotTableOption{
@ -67,6 +78,8 @@ func TestAddPivotTable(t *testing.T) {
Rows: []string{"Month"},
Columns: []string{"Region", "Type", "Year"},
Data: []string{"Sales"},
DataSubtotal: "Min",
DataFieldName: "Summarize by Min",
}))
assert.NoError(t, f.AddPivotTable(&PivotTableOption{
DataRange: "Sheet1!$A$1:$E$31",
@ -74,6 +87,8 @@ func TestAddPivotTable(t *testing.T) {
Rows: []string{"Month", "Type"},
Columns: []string{"Region", "Year"},
Data: []string{"Sales"},
DataSubtotal: "Product",
DataFieldName: "Summarize by Product",
}))
// Test empty pivot table options
@ -135,6 +150,16 @@ func TestAddPivotTable(t *testing.T) {
Data: []string{"Sales"},
}), `parameter 'DataRange' parsing error: cannot convert cell "A0" to coordinates: invalid cell name "A0"`)
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddPivotTable1.xlsx")))
// Test with field names that exceed the length limit and invalid subtotal
assert.NoError(t, f.AddPivotTable(&PivotTableOption{
DataRange: "Sheet1!$A$1:$E$31",
PivotTableRange: "Sheet1!$G$2:$M$34",
Rows: []string{"Month", "Year"},
Columns: []string{"Type"},
Data: []string{"Sales"},
DataSubtotal: "-",
DataFieldName: strings.Repeat("s", 256),
}))
// Test adjust range with invalid range
_, _, err := f.adjustRange("")