This closes #1993, support to set and get pivot table classic layout
- Add new field `ClassicLayout` in the `PivotTableOptions` - Add a new exported error variable `ErrPivotTableClassicLayout` - Update unit tests - Add documentation for the SetDefinedName function, ref #1015
This commit is contained in:
parent
02189fb016
commit
41c7dd30ce
|
@ -97,6 +97,8 @@ var (
|
||||||
// ErrPasswordLengthInvalid defined the error message on invalid password
|
// ErrPasswordLengthInvalid defined the error message on invalid password
|
||||||
// length.
|
// length.
|
||||||
ErrPasswordLengthInvalid = errors.New("password length invalid")
|
ErrPasswordLengthInvalid = errors.New("password length invalid")
|
||||||
|
// ErrPivotTableClassicLayout
|
||||||
|
ErrPivotTableClassicLayout = errors.New("cannot enable ClassicLayout and CompactData in the same time")
|
||||||
// ErrSave defined the error message for saving file.
|
// ErrSave defined the error message for saving file.
|
||||||
ErrSave = errors.New("no path defined for file, consider File.WriteTo or File.Write")
|
ErrSave = errors.New("no path defined for file, consider File.WriteTo or File.Write")
|
||||||
// ErrSheetIdx defined the error message on receive the invalid worksheet
|
// ErrSheetIdx defined the error message on receive the invalid worksheet
|
||||||
|
|
|
@ -51,6 +51,7 @@ type PivotTableOptions struct {
|
||||||
UseAutoFormatting bool
|
UseAutoFormatting bool
|
||||||
PageOverThenDown bool
|
PageOverThenDown bool
|
||||||
MergeItem bool
|
MergeItem bool
|
||||||
|
ClassicLayout bool
|
||||||
CompactData bool
|
CompactData bool
|
||||||
ShowError bool
|
ShowError bool
|
||||||
ShowRowHeaders bool
|
ShowRowHeaders bool
|
||||||
|
@ -220,6 +221,9 @@ func (f *File) parseFormatPivotTableSet(opts *PivotTableOptions) (*xlsxWorksheet
|
||||||
if !ok {
|
if !ok {
|
||||||
return dataSheet, pivotTableSheetPath, ErrSheetNotExist{pivotTableSheetName}
|
return dataSheet, pivotTableSheetPath, ErrSheetNotExist{pivotTableSheetName}
|
||||||
}
|
}
|
||||||
|
if opts.CompactData && opts.ClassicLayout {
|
||||||
|
return nil, "", ErrPivotTableClassicLayout
|
||||||
|
}
|
||||||
return dataSheet, pivotTableSheetPath, err
|
return dataSheet, pivotTableSheetPath, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,6 +356,7 @@ func (f *File) addPivotTable(cacheID, pivotTableID int, opts *PivotTableOptions)
|
||||||
MergeItem: &opts.MergeItem,
|
MergeItem: &opts.MergeItem,
|
||||||
CreatedVersion: pivotTableVersion,
|
CreatedVersion: pivotTableVersion,
|
||||||
CompactData: &opts.CompactData,
|
CompactData: &opts.CompactData,
|
||||||
|
GridDropZones: opts.ClassicLayout,
|
||||||
ShowError: &opts.ShowError,
|
ShowError: &opts.ShowError,
|
||||||
FieldPrintTitles: opts.FieldPrintTitles,
|
FieldPrintTitles: opts.FieldPrintTitles,
|
||||||
ItemPrintTitles: opts.ItemPrintTitles,
|
ItemPrintTitles: opts.ItemPrintTitles,
|
||||||
|
@ -387,6 +392,12 @@ func (f *File) addPivotTable(cacheID, pivotTableID int, opts *PivotTableOptions)
|
||||||
if pt.Name == "" {
|
if pt.Name == "" {
|
||||||
pt.Name = fmt.Sprintf("PivotTable%d", pivotTableID)
|
pt.Name = fmt.Sprintf("PivotTable%d", pivotTableID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set classic layout
|
||||||
|
if opts.ClassicLayout {
|
||||||
|
pt.Compact, pt.CompactData = boolPtr(false), boolPtr(false)
|
||||||
|
}
|
||||||
|
|
||||||
// pivot fields
|
// pivot fields
|
||||||
_ = f.addPivotFields(&pt, opts)
|
_ = f.addPivotFields(&pt, opts)
|
||||||
|
|
||||||
|
@ -537,6 +548,14 @@ func (f *File) addPivotColFields(pt *xlsxPivotTableDefinition, opts *PivotTableO
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setClassicLayout provides a method to set classic layout for pivot table by
|
||||||
|
// setting Compact and Outline to false.
|
||||||
|
func (fld *xlsxPivotField) setClassicLayout(classicLayout bool) {
|
||||||
|
if classicLayout {
|
||||||
|
fld.Compact, fld.Outline = boolPtr(false), boolPtr(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// addPivotFields create pivot fields based on the column order of the first
|
// addPivotFields create pivot fields based on the column order of the first
|
||||||
// row in the data region by given pivot table definition and option.
|
// row in the data region by given pivot table definition and option.
|
||||||
func (f *File) addPivotFields(pt *xlsxPivotTableDefinition, opts *PivotTableOptions) error {
|
func (f *File) addPivotFields(pt *xlsxPivotTableDefinition, opts *PivotTableOptions) error {
|
||||||
|
@ -554,8 +573,7 @@ func (f *File) addPivotFields(pt *xlsxPivotTableDefinition, opts *PivotTableOpti
|
||||||
} else {
|
} else {
|
||||||
items = append(items, &xlsxItem{T: "default"})
|
items = append(items, &xlsxItem{T: "default"})
|
||||||
}
|
}
|
||||||
|
fld := &xlsxPivotField{
|
||||||
pt.PivotFields.PivotField = append(pt.PivotFields.PivotField, &xlsxPivotField{
|
|
||||||
Name: f.getPivotTableFieldName(name, opts.Rows),
|
Name: f.getPivotTableFieldName(name, opts.Rows),
|
||||||
Axis: "axisRow",
|
Axis: "axisRow",
|
||||||
DataField: inPivotTableField(opts.Data, name) != -1,
|
DataField: inPivotTableField(opts.Data, name) != -1,
|
||||||
|
@ -568,11 +586,13 @@ func (f *File) addPivotFields(pt *xlsxPivotTableDefinition, opts *PivotTableOpti
|
||||||
Count: len(items),
|
Count: len(items),
|
||||||
Item: items,
|
Item: items,
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
|
fld.setClassicLayout(opts.ClassicLayout)
|
||||||
|
pt.PivotFields.PivotField = append(pt.PivotFields.PivotField, fld)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if inPivotTableField(opts.Filter, name) != -1 {
|
if inPivotTableField(opts.Filter, name) != -1 {
|
||||||
pt.PivotFields.PivotField = append(pt.PivotFields.PivotField, &xlsxPivotField{
|
fld := &xlsxPivotField{
|
||||||
Axis: "axisPage",
|
Axis: "axisPage",
|
||||||
DataField: inPivotTableField(opts.Data, name) != -1,
|
DataField: inPivotTableField(opts.Data, name) != -1,
|
||||||
Name: f.getPivotTableFieldName(name, opts.Columns),
|
Name: f.getPivotTableFieldName(name, opts.Columns),
|
||||||
|
@ -582,7 +602,9 @@ func (f *File) addPivotFields(pt *xlsxPivotTableDefinition, opts *PivotTableOpti
|
||||||
{T: "default"},
|
{T: "default"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
|
fld.setClassicLayout(opts.ClassicLayout)
|
||||||
|
pt.PivotFields.PivotField = append(pt.PivotFields.PivotField, fld)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if inPivotTableField(opts.Columns, name) != -1 {
|
if inPivotTableField(opts.Columns, name) != -1 {
|
||||||
|
@ -593,7 +615,7 @@ func (f *File) addPivotFields(pt *xlsxPivotTableDefinition, opts *PivotTableOpti
|
||||||
} else {
|
} else {
|
||||||
items = append(items, &xlsxItem{T: "default"})
|
items = append(items, &xlsxItem{T: "default"})
|
||||||
}
|
}
|
||||||
pt.PivotFields.PivotField = append(pt.PivotFields.PivotField, &xlsxPivotField{
|
fld := &xlsxPivotField{
|
||||||
Name: f.getPivotTableFieldName(name, opts.Columns),
|
Name: f.getPivotTableFieldName(name, opts.Columns),
|
||||||
Axis: "axisCol",
|
Axis: "axisCol",
|
||||||
DataField: inPivotTableField(opts.Data, name) != -1,
|
DataField: inPivotTableField(opts.Data, name) != -1,
|
||||||
|
@ -606,16 +628,22 @@ func (f *File) addPivotFields(pt *xlsxPivotTableDefinition, opts *PivotTableOpti
|
||||||
Count: len(items),
|
Count: len(items),
|
||||||
Item: items,
|
Item: items,
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
|
fld.setClassicLayout(opts.ClassicLayout)
|
||||||
|
pt.PivotFields.PivotField = append(pt.PivotFields.PivotField, fld)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if inPivotTableField(opts.Data, name) != -1 {
|
if inPivotTableField(opts.Data, name) != -1 {
|
||||||
pt.PivotFields.PivotField = append(pt.PivotFields.PivotField, &xlsxPivotField{
|
fld := &xlsxPivotField{
|
||||||
DataField: true,
|
DataField: true,
|
||||||
})
|
}
|
||||||
|
fld.setClassicLayout(opts.ClassicLayout)
|
||||||
|
pt.PivotFields.PivotField = append(pt.PivotFields.PivotField, fld)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
pt.PivotFields.PivotField = append(pt.PivotFields.PivotField, &xlsxPivotField{})
|
fld := &xlsxPivotField{}
|
||||||
|
fld.setClassicLayout(opts.ClassicLayout)
|
||||||
|
pt.PivotFields.PivotField = append(pt.PivotFields.PivotField, fld)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -847,6 +875,7 @@ func (f *File) getPivotTable(sheet, pivotTableXML, pivotCacheRels string) (Pivot
|
||||||
DataRange: fmt.Sprintf("%s!%s", pc.CacheSource.WorksheetSource.Sheet, pc.CacheSource.WorksheetSource.Ref),
|
DataRange: fmt.Sprintf("%s!%s", pc.CacheSource.WorksheetSource.Sheet, pc.CacheSource.WorksheetSource.Ref),
|
||||||
PivotTableRange: fmt.Sprintf("%s!%s", sheet, pt.Location.Ref),
|
PivotTableRange: fmt.Sprintf("%s!%s", sheet, pt.Location.Ref),
|
||||||
Name: pt.Name,
|
Name: pt.Name,
|
||||||
|
ClassicLayout: pt.GridDropZones,
|
||||||
FieldPrintTitles: pt.FieldPrintTitles,
|
FieldPrintTitles: pt.FieldPrintTitles,
|
||||||
ItemPrintTitles: pt.ItemPrintTitles,
|
ItemPrintTitles: pt.ItemPrintTitles,
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,12 +38,13 @@ func TestPivotTable(t *testing.T) {
|
||||||
RowGrandTotals: true,
|
RowGrandTotals: true,
|
||||||
ColGrandTotals: true,
|
ColGrandTotals: true,
|
||||||
ShowDrill: true,
|
ShowDrill: true,
|
||||||
|
ClassicLayout: true,
|
||||||
|
ShowError: true,
|
||||||
ShowRowHeaders: true,
|
ShowRowHeaders: true,
|
||||||
ShowColHeaders: true,
|
ShowColHeaders: true,
|
||||||
ShowLastColumn: true,
|
ShowLastColumn: true,
|
||||||
ShowError: true,
|
|
||||||
ItemPrintTitles: true,
|
|
||||||
FieldPrintTitles: true,
|
FieldPrintTitles: true,
|
||||||
|
ItemPrintTitles: true,
|
||||||
PivotTableStyleName: "PivotStyleLight16",
|
PivotTableStyleName: "PivotStyleLight16",
|
||||||
}
|
}
|
||||||
assert.NoError(t, f.AddPivotTable(expected))
|
assert.NoError(t, f.AddPivotTable(expected))
|
||||||
|
@ -265,18 +266,25 @@ func TestPivotTable(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// Test add pivot table with invalid sheet name
|
// Test add pivot table with invalid sheet name
|
||||||
assert.EqualError(t, f.AddPivotTable(&PivotTableOptions{
|
assert.Error(t, f.AddPivotTable(&PivotTableOptions{
|
||||||
DataRange: "Sheet:1!A1:E31",
|
DataRange: "Sheet:1!A1:E31",
|
||||||
PivotTableRange: "Sheet:1!G2:M34",
|
PivotTableRange: "Sheet:1!G2:M34",
|
||||||
Rows: []PivotTableField{{Data: "Year"}},
|
Rows: []PivotTableField{{Data: "Year"}},
|
||||||
}), ErrSheetNameInvalid.Error())
|
}), ErrSheetNameInvalid)
|
||||||
|
// Test add pivot table with enable ClassicLayout and CompactData in the same time
|
||||||
|
assert.Error(t, f.AddPivotTable(&PivotTableOptions{
|
||||||
|
DataRange: "Sheet1!A1:E31",
|
||||||
|
PivotTableRange: "Sheet1!G2:M34",
|
||||||
|
CompactData: true,
|
||||||
|
ClassicLayout: true,
|
||||||
|
}), ErrPivotTableClassicLayout)
|
||||||
// Test delete pivot table with not exists worksheet
|
// Test delete pivot table with not exists worksheet
|
||||||
assert.EqualError(t, f.DeletePivotTable("SheetN", "PivotTable1"), "sheet SheetN does not exist")
|
assert.EqualError(t, f.DeletePivotTable("SheetN", "PivotTable1"), "sheet SheetN does not exist")
|
||||||
// Test delete pivot table with not exists pivot table name
|
// Test delete pivot table with not exists pivot table name
|
||||||
assert.EqualError(t, f.DeletePivotTable("Sheet1", "PivotTableN"), "table PivotTableN does not exist")
|
assert.EqualError(t, f.DeletePivotTable("Sheet1", "PivotTableN"), "table PivotTableN does not exist")
|
||||||
// Test adjust range with invalid range
|
// Test adjust range with invalid range
|
||||||
_, _, err = f.adjustRange("")
|
_, _, err = f.adjustRange("")
|
||||||
assert.EqualError(t, err, ErrParameterRequired.Error())
|
assert.Error(t, err, ErrParameterRequired)
|
||||||
// Test adjust range with incorrect range
|
// Test adjust range with incorrect range
|
||||||
_, _, err = f.adjustRange("sheet1!")
|
_, _, err = f.adjustRange("sheet1!")
|
||||||
assert.EqualError(t, err, "parameter is invalid")
|
assert.EqualError(t, err, "parameter is invalid")
|
||||||
|
|
18
sheet.go
18
sheet.go
|
@ -1657,6 +1657,24 @@ func (f *File) GetPageLayout(sheet string) (PageLayoutOptions, error) {
|
||||||
// Comment: "defined name comment",
|
// Comment: "defined name comment",
|
||||||
// Scope: "Sheet2",
|
// Scope: "Sheet2",
|
||||||
// })
|
// })
|
||||||
|
//
|
||||||
|
// If you fill the RefersTo property with only one columns range without a
|
||||||
|
// comma, it will work as "Columns to repeat at left" only. For example:
|
||||||
|
//
|
||||||
|
// err := f.SetDefinedName(&excelize.DefinedName{
|
||||||
|
// Name: "_xlnm.Print_Titles",
|
||||||
|
// RefersTo: "Sheet1!$A:$A",
|
||||||
|
// Scope: "Sheet1",
|
||||||
|
// })
|
||||||
|
//
|
||||||
|
// If you fill the RefersTo property with only one rows range without a comma,
|
||||||
|
// it will work as "Rows to repeat at top" only. For example:
|
||||||
|
//
|
||||||
|
// err := f.SetDefinedName(&excelize.DefinedName{
|
||||||
|
// Name: "_xlnm.Print_Titles",
|
||||||
|
// RefersTo: "Sheet1!$1:$1",
|
||||||
|
// Scope: "Sheet1",
|
||||||
|
// })
|
||||||
func (f *File) SetDefinedName(definedName *DefinedName) error {
|
func (f *File) SetDefinedName(definedName *DefinedName) error {
|
||||||
if definedName.Name == "" || definedName.RefersTo == "" {
|
if definedName.Name == "" || definedName.RefersTo == "" {
|
||||||
return ErrParameterInvalid
|
return ErrParameterInvalid
|
||||||
|
|
Loading…
Reference in New Issue