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
|
||||
// length.
|
||||
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 = errors.New("no path defined for file, consider File.WriteTo or File.Write")
|
||||
// ErrSheetIdx defined the error message on receive the invalid worksheet
|
||||
|
|
|
@ -51,6 +51,7 @@ type PivotTableOptions struct {
|
|||
UseAutoFormatting bool
|
||||
PageOverThenDown bool
|
||||
MergeItem bool
|
||||
ClassicLayout bool
|
||||
CompactData bool
|
||||
ShowError bool
|
||||
ShowRowHeaders bool
|
||||
|
@ -220,6 +221,9 @@ func (f *File) parseFormatPivotTableSet(opts *PivotTableOptions) (*xlsxWorksheet
|
|||
if !ok {
|
||||
return dataSheet, pivotTableSheetPath, ErrSheetNotExist{pivotTableSheetName}
|
||||
}
|
||||
if opts.CompactData && opts.ClassicLayout {
|
||||
return nil, "", ErrPivotTableClassicLayout
|
||||
}
|
||||
return dataSheet, pivotTableSheetPath, err
|
||||
}
|
||||
|
||||
|
@ -352,6 +356,7 @@ func (f *File) addPivotTable(cacheID, pivotTableID int, opts *PivotTableOptions)
|
|||
MergeItem: &opts.MergeItem,
|
||||
CreatedVersion: pivotTableVersion,
|
||||
CompactData: &opts.CompactData,
|
||||
GridDropZones: opts.ClassicLayout,
|
||||
ShowError: &opts.ShowError,
|
||||
FieldPrintTitles: opts.FieldPrintTitles,
|
||||
ItemPrintTitles: opts.ItemPrintTitles,
|
||||
|
@ -387,6 +392,12 @@ func (f *File) addPivotTable(cacheID, pivotTableID int, opts *PivotTableOptions)
|
|||
if pt.Name == "" {
|
||||
pt.Name = fmt.Sprintf("PivotTable%d", pivotTableID)
|
||||
}
|
||||
|
||||
// set classic layout
|
||||
if opts.ClassicLayout {
|
||||
pt.Compact, pt.CompactData = boolPtr(false), boolPtr(false)
|
||||
}
|
||||
|
||||
// pivot fields
|
||||
_ = f.addPivotFields(&pt, opts)
|
||||
|
||||
|
@ -537,6 +548,14 @@ func (f *File) addPivotColFields(pt *xlsxPivotTableDefinition, opts *PivotTableO
|
|||
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
|
||||
// row in the data region by given pivot table definition and option.
|
||||
func (f *File) addPivotFields(pt *xlsxPivotTableDefinition, opts *PivotTableOptions) error {
|
||||
|
@ -554,8 +573,7 @@ func (f *File) addPivotFields(pt *xlsxPivotTableDefinition, opts *PivotTableOpti
|
|||
} else {
|
||||
items = append(items, &xlsxItem{T: "default"})
|
||||
}
|
||||
|
||||
pt.PivotFields.PivotField = append(pt.PivotFields.PivotField, &xlsxPivotField{
|
||||
fld := &xlsxPivotField{
|
||||
Name: f.getPivotTableFieldName(name, opts.Rows),
|
||||
Axis: "axisRow",
|
||||
DataField: inPivotTableField(opts.Data, name) != -1,
|
||||
|
@ -568,11 +586,13 @@ func (f *File) addPivotFields(pt *xlsxPivotTableDefinition, opts *PivotTableOpti
|
|||
Count: len(items),
|
||||
Item: items,
|
||||
},
|
||||
})
|
||||
}
|
||||
fld.setClassicLayout(opts.ClassicLayout)
|
||||
pt.PivotFields.PivotField = append(pt.PivotFields.PivotField, fld)
|
||||
continue
|
||||
}
|
||||
if inPivotTableField(opts.Filter, name) != -1 {
|
||||
pt.PivotFields.PivotField = append(pt.PivotFields.PivotField, &xlsxPivotField{
|
||||
fld := &xlsxPivotField{
|
||||
Axis: "axisPage",
|
||||
DataField: inPivotTableField(opts.Data, name) != -1,
|
||||
Name: f.getPivotTableFieldName(name, opts.Columns),
|
||||
|
@ -582,7 +602,9 @@ func (f *File) addPivotFields(pt *xlsxPivotTableDefinition, opts *PivotTableOpti
|
|||
{T: "default"},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
fld.setClassicLayout(opts.ClassicLayout)
|
||||
pt.PivotFields.PivotField = append(pt.PivotFields.PivotField, fld)
|
||||
continue
|
||||
}
|
||||
if inPivotTableField(opts.Columns, name) != -1 {
|
||||
|
@ -593,7 +615,7 @@ func (f *File) addPivotFields(pt *xlsxPivotTableDefinition, opts *PivotTableOpti
|
|||
} else {
|
||||
items = append(items, &xlsxItem{T: "default"})
|
||||
}
|
||||
pt.PivotFields.PivotField = append(pt.PivotFields.PivotField, &xlsxPivotField{
|
||||
fld := &xlsxPivotField{
|
||||
Name: f.getPivotTableFieldName(name, opts.Columns),
|
||||
Axis: "axisCol",
|
||||
DataField: inPivotTableField(opts.Data, name) != -1,
|
||||
|
@ -606,16 +628,22 @@ func (f *File) addPivotFields(pt *xlsxPivotTableDefinition, opts *PivotTableOpti
|
|||
Count: len(items),
|
||||
Item: items,
|
||||
},
|
||||
})
|
||||
}
|
||||
fld.setClassicLayout(opts.ClassicLayout)
|
||||
pt.PivotFields.PivotField = append(pt.PivotFields.PivotField, fld)
|
||||
continue
|
||||
}
|
||||
if inPivotTableField(opts.Data, name) != -1 {
|
||||
pt.PivotFields.PivotField = append(pt.PivotFields.PivotField, &xlsxPivotField{
|
||||
fld := &xlsxPivotField{
|
||||
DataField: true,
|
||||
})
|
||||
}
|
||||
fld.setClassicLayout(opts.ClassicLayout)
|
||||
pt.PivotFields.PivotField = append(pt.PivotFields.PivotField, fld)
|
||||
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
|
||||
}
|
||||
|
@ -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),
|
||||
PivotTableRange: fmt.Sprintf("%s!%s", sheet, pt.Location.Ref),
|
||||
Name: pt.Name,
|
||||
ClassicLayout: pt.GridDropZones,
|
||||
FieldPrintTitles: pt.FieldPrintTitles,
|
||||
ItemPrintTitles: pt.ItemPrintTitles,
|
||||
}
|
||||
|
|
|
@ -38,12 +38,13 @@ func TestPivotTable(t *testing.T) {
|
|||
RowGrandTotals: true,
|
||||
ColGrandTotals: true,
|
||||
ShowDrill: true,
|
||||
ClassicLayout: true,
|
||||
ShowError: true,
|
||||
ShowRowHeaders: true,
|
||||
ShowColHeaders: true,
|
||||
ShowLastColumn: true,
|
||||
ShowError: true,
|
||||
ItemPrintTitles: true,
|
||||
FieldPrintTitles: true,
|
||||
ItemPrintTitles: true,
|
||||
PivotTableStyleName: "PivotStyleLight16",
|
||||
}
|
||||
assert.NoError(t, f.AddPivotTable(expected))
|
||||
|
@ -265,18 +266,25 @@ func TestPivotTable(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// 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",
|
||||
PivotTableRange: "Sheet:1!G2:M34",
|
||||
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
|
||||
assert.EqualError(t, f.DeletePivotTable("SheetN", "PivotTable1"), "sheet SheetN does not exist")
|
||||
// Test delete pivot table with not exists pivot table name
|
||||
assert.EqualError(t, f.DeletePivotTable("Sheet1", "PivotTableN"), "table PivotTableN does not exist")
|
||||
// Test adjust range with invalid range
|
||||
_, _, err = f.adjustRange("")
|
||||
assert.EqualError(t, err, ErrParameterRequired.Error())
|
||||
assert.Error(t, err, ErrParameterRequired)
|
||||
// Test adjust range with incorrect range
|
||||
_, _, err = f.adjustRange("sheet1!")
|
||||
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",
|
||||
// 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 {
|
||||
if definedName.Name == "" || definedName.RefersTo == "" {
|
||||
return ErrParameterInvalid
|
||||
|
|
Loading…
Reference in New Issue