forked from p30928647/excelize
This closes #866, support use the defined name to reference the data range in pivot table options
- Fix incorrect scope when getting defined name - Update docs: use column number instead of index on get column width
This commit is contained in:
parent
24967a5c25
commit
f27624acdd
13
calc.go
13
calc.go
|
@ -955,16 +955,23 @@ func isOperatorPrefixToken(token efp.Token) bool {
|
|||
|
||||
// getDefinedNameRefTo convert defined name to reference range.
|
||||
func (f *File) getDefinedNameRefTo(definedNameName string, currentSheet string) (refTo string) {
|
||||
var workbookRefTo, worksheetRefTo string
|
||||
for _, definedName := range f.GetDefinedName() {
|
||||
if definedName.Name == definedNameName {
|
||||
refTo = definedName.RefersTo
|
||||
// worksheet scope takes precedence over scope workbook when both definedNames exist
|
||||
if definedName.Scope == "Workbook" {
|
||||
workbookRefTo = definedName.RefersTo
|
||||
}
|
||||
if definedName.Scope == currentSheet {
|
||||
break
|
||||
worksheetRefTo = definedName.RefersTo
|
||||
}
|
||||
}
|
||||
}
|
||||
return refTo
|
||||
refTo = workbookRefTo
|
||||
if worksheetRefTo != "" {
|
||||
refTo = worksheetRefTo
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// parseToken parse basic arithmetic operator priority and evaluate based on
|
||||
|
|
4
col.go
4
col.go
|
@ -604,7 +604,7 @@ func (f *File) positionObjectPixels(sheet string, col, row, x1, y1, width, heigh
|
|||
}
|
||||
|
||||
// getColWidth provides a function to get column width in pixels by given
|
||||
// sheet name and column index.
|
||||
// sheet name and column number.
|
||||
func (f *File) getColWidth(sheet string, col int) int {
|
||||
xlsx, _ := f.workSheetReader(sheet)
|
||||
if xlsx.Cols != nil {
|
||||
|
@ -623,7 +623,7 @@ func (f *File) getColWidth(sheet string, col int) int {
|
|||
}
|
||||
|
||||
// GetColWidth provides a function to get column width by given worksheet name
|
||||
// and column index.
|
||||
// and column name.
|
||||
func (f *File) GetColWidth(sheet, col string) (float64, error) {
|
||||
colNum, err := ColumnNameToNumber(col)
|
||||
if err != nil {
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
|
||||
// PivotTableOption directly maps the format settings of the pivot table.
|
||||
type PivotTableOption struct {
|
||||
pivotTableSheetName string
|
||||
DataRange string
|
||||
PivotTableRange string
|
||||
Rows []PivotTableField
|
||||
|
@ -164,14 +165,19 @@ func (f *File) parseFormatPivotTableSet(opt *PivotTableOption) (*xlsxWorksheet,
|
|||
if opt == nil {
|
||||
return nil, "", errors.New("parameter is required")
|
||||
}
|
||||
dataSheetName, _, err := f.adjustRange(opt.DataRange)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("parameter 'DataRange' parsing error: %s", err.Error())
|
||||
}
|
||||
pivotTableSheetName, _, err := f.adjustRange(opt.PivotTableRange)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("parameter 'PivotTableRange' parsing error: %s", err.Error())
|
||||
}
|
||||
opt.pivotTableSheetName = pivotTableSheetName
|
||||
dataRange := f.getDefinedNameRefTo(opt.DataRange, pivotTableSheetName)
|
||||
if dataRange == "" {
|
||||
dataRange = opt.DataRange
|
||||
}
|
||||
dataSheetName, _, err := f.adjustRange(dataRange)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("parameter 'DataRange' parsing error: %s", err.Error())
|
||||
}
|
||||
dataSheet, err := f.workSheetReader(dataSheetName)
|
||||
if err != nil {
|
||||
return dataSheet, "", err
|
||||
|
@ -215,8 +221,12 @@ func (f *File) adjustRange(rangeStr string) (string, []int, error) {
|
|||
|
||||
// getPivotFieldsOrder provides a function to get order list of pivot table
|
||||
// fields.
|
||||
func (f *File) getPivotFieldsOrder(dataRange string) ([]string, error) {
|
||||
func (f *File) getPivotFieldsOrder(opt *PivotTableOption) ([]string, error) {
|
||||
order := []string{}
|
||||
dataRange := f.getDefinedNameRefTo(opt.DataRange, opt.pivotTableSheetName)
|
||||
if dataRange == "" {
|
||||
dataRange = opt.DataRange
|
||||
}
|
||||
dataSheet, coordinates, err := f.adjustRange(dataRange)
|
||||
if err != nil {
|
||||
return order, fmt.Errorf("parameter 'DataRange' parsing error: %s", err.Error())
|
||||
|
@ -235,12 +245,18 @@ func (f *File) getPivotFieldsOrder(dataRange string) ([]string, error) {
|
|||
// addPivotCache provides a function to create a pivot cache by given properties.
|
||||
func (f *File) addPivotCache(pivotCacheID int, pivotCacheXML string, opt *PivotTableOption, ws *xlsxWorksheet) error {
|
||||
// validate data range
|
||||
dataSheet, coordinates, err := f.adjustRange(opt.DataRange)
|
||||
definedNameRef := true
|
||||
dataRange := f.getDefinedNameRefTo(opt.DataRange, opt.pivotTableSheetName)
|
||||
if dataRange == "" {
|
||||
definedNameRef = false
|
||||
dataRange = opt.DataRange
|
||||
}
|
||||
dataSheet, coordinates, err := f.adjustRange(dataRange)
|
||||
if err != nil {
|
||||
return fmt.Errorf("parameter 'DataRange' parsing error: %s", err.Error())
|
||||
}
|
||||
// data range has been checked
|
||||
order, _ := f.getPivotFieldsOrder(opt.DataRange)
|
||||
order, _ := f.getPivotFieldsOrder(opt)
|
||||
hcell, _ := CoordinatesToCellName(coordinates[0], coordinates[1])
|
||||
vcell, _ := CoordinatesToCellName(coordinates[2], coordinates[3])
|
||||
pc := xlsxPivotCacheDefinition{
|
||||
|
@ -258,7 +274,9 @@ func (f *File) addPivotCache(pivotCacheID int, pivotCacheXML string, opt *PivotT
|
|||
},
|
||||
CacheFields: &xlsxCacheFields{},
|
||||
}
|
||||
|
||||
if definedNameRef {
|
||||
pc.CacheSource.WorksheetSource = &xlsxWorksheetSource{Name: opt.DataRange}
|
||||
}
|
||||
for _, name := range order {
|
||||
defaultRowsSubtotal, rowOk := f.getPivotTableFieldNameDefaultSubtotal(name, opt.Rows)
|
||||
defaultColumnsSubtotal, colOk := f.getPivotTableFieldNameDefaultSubtotal(name, opt.Columns)
|
||||
|
@ -509,7 +527,7 @@ func (f *File) addPivotColFields(pt *xlsxPivotTableDefinition, opt *PivotTableOp
|
|||
// addPivotFields create pivot fields based on the column order of the first
|
||||
// row in the data region by given pivot table definition and option.
|
||||
func (f *File) addPivotFields(pt *xlsxPivotTableDefinition, opt *PivotTableOption) error {
|
||||
order, err := f.getPivotFieldsOrder(opt.DataRange)
|
||||
order, err := f.getPivotFieldsOrder(opt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -606,7 +624,7 @@ func (f *File) countPivotCache() int {
|
|||
// to a sequential index by given fields and pivot option.
|
||||
func (f *File) getPivotFieldsIndex(fields []PivotTableField, opt *PivotTableOption) ([]int, error) {
|
||||
pivotFieldsIndex := []int{}
|
||||
orders, err := f.getPivotFieldsOrder(opt.DataRange)
|
||||
orders, err := f.getPivotFieldsOrder(opt)
|
||||
if err != nil {
|
||||
return pivotFieldsIndex, err
|
||||
}
|
||||
|
|
|
@ -136,10 +136,16 @@ func TestAddPivotTable(t *testing.T) {
|
|||
ShowColHeaders: true,
|
||||
ShowLastColumn: true,
|
||||
}))
|
||||
//Test Pivot table with many data, many rows, many cols
|
||||
// Create pivot table with many data, many rows, many cols and defined name
|
||||
f.SetDefinedName(&DefinedName{
|
||||
Name: "dataRange",
|
||||
RefersTo: "Sheet1!$A$1:$E$31",
|
||||
Comment: "Pivot Table Data Range",
|
||||
Scope: "Sheet2",
|
||||
})
|
||||
assert.NoError(t, f.AddPivotTable(&PivotTableOption{
|
||||
DataRange: "Sheet1!$A$1:$E$31",
|
||||
PivotTableRange: "Sheet2!$A$56:$AG$90",
|
||||
DataRange: "dataRange",
|
||||
PivotTableRange: "Sheet2!$A$57:$AJ$91",
|
||||
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
|
||||
Columns: []PivotTableField{{Data: "Region", DefaultSubtotal: true}, {Data: "Type"}},
|
||||
Data: []PivotTableField{{Data: "Sales", Subtotal: "Sum", Name: "Sum of Sales"}, {Data: "Sales", Subtotal: "Average", Name: "Average of Sales"}},
|
||||
|
@ -223,7 +229,7 @@ func TestAddPivotTable(t *testing.T) {
|
|||
_, _, err := f.adjustRange("")
|
||||
assert.EqualError(t, err, "parameter is required")
|
||||
// Test get pivot fields order with empty data range
|
||||
_, err = f.getPivotFieldsOrder("")
|
||||
_, err = f.getPivotFieldsOrder(&PivotTableOption{})
|
||||
assert.EqualError(t, err, `parameter 'DataRange' parsing error: parameter is required`)
|
||||
// Test add pivot cache with empty data range
|
||||
assert.EqualError(t, f.addPivotCache(0, "", &PivotTableOption{}, nil), "parameter 'DataRange' parsing error: parameter is required")
|
||||
|
@ -288,7 +294,7 @@ func TestAddPivotColFields(t *testing.T) {
|
|||
func TestGetPivotFieldsOrder(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test get pivot fields order with not exist worksheet
|
||||
_, err := f.getPivotFieldsOrder("SheetN!$A$1:$E$31")
|
||||
_, err := f.getPivotFieldsOrder(&PivotTableOption{DataRange: "SheetN!$A$1:$E$31"})
|
||||
assert.EqualError(t, err, "sheet SheetN is not exist")
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue