- Support set and get built-in number format of the pivot table data filed cells - Update unit tests - Fixed ineffectual assignment issue
This commit is contained in:
parent
d21b598235
commit
9a38657515
4
calc.go
4
calc.go
|
@ -14459,7 +14459,7 @@ func (fn *formulaFuncs) VALUE(argsList *list.List) formulaArg {
|
||||||
value, _ := decimal.Float64()
|
value, _ := decimal.Float64()
|
||||||
return newNumberFormulaArg(value * percent)
|
return newNumberFormulaArg(value * percent)
|
||||||
}
|
}
|
||||||
dateValue, timeValue, errTime, errDate := 0.0, 0.0, false, false
|
dateValue, timeValue, errTime := 0.0, 0.0, false
|
||||||
if !isDateOnlyFmt(text) {
|
if !isDateOnlyFmt(text) {
|
||||||
h, m, s, _, _, err := strToTime(text)
|
h, m, s, _, _, err := strToTime(text)
|
||||||
errTime = err.Type == ArgError
|
errTime = err.Type == ArgError
|
||||||
|
@ -14468,7 +14468,7 @@ func (fn *formulaFuncs) VALUE(argsList *list.List) formulaArg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
y, m, d, _, err := strToDate(text)
|
y, m, d, _, err := strToDate(text)
|
||||||
errDate = err.Type == ArgError
|
errDate := err.Type == ArgError
|
||||||
if !errDate {
|
if !errDate {
|
||||||
dateValue = daysBetween(excelMinTime1900.Unix(), makeDate(y, time.Month(m), d)) + 1
|
dateValue = daysBetween(excelMinTime1900.Unix(), makeDate(y, time.Month(m), d)) + 1
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,10 @@ type PivotTableOptions struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// PivotTableField directly maps the field settings of the pivot table.
|
// PivotTableField directly maps the field settings of the pivot table.
|
||||||
|
//
|
||||||
|
// Name specifies the name of the data field. Maximum 255 characters
|
||||||
|
// are allowed in data field name, excess characters will be truncated.
|
||||||
|
//
|
||||||
// Subtotal specifies the aggregation function that applies to this data
|
// Subtotal specifies the aggregation function that applies to this data
|
||||||
// field. The default value is sum. The possible values for this attribute
|
// field. The default value is sum. The possible values for this attribute
|
||||||
// are:
|
// are:
|
||||||
|
@ -78,8 +82,9 @@ type PivotTableOptions struct {
|
||||||
// Var
|
// Var
|
||||||
// Varp
|
// Varp
|
||||||
//
|
//
|
||||||
// Name specifies the name of the data field. Maximum 255 characters
|
// NumFmt specifies the number format ID of the data field, this filed only
|
||||||
// are allowed in data field name, excess characters will be truncated.
|
// accepts built-in number format ID and does not support custom number format
|
||||||
|
// expression currently.
|
||||||
type PivotTableField struct {
|
type PivotTableField struct {
|
||||||
Compact bool
|
Compact bool
|
||||||
Data string
|
Data string
|
||||||
|
@ -87,6 +92,7 @@ type PivotTableField struct {
|
||||||
Outline bool
|
Outline bool
|
||||||
Subtotal string
|
Subtotal string
|
||||||
DefaultSubtotal bool
|
DefaultSubtotal bool
|
||||||
|
NumFmt int
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddPivotTable provides the method to add pivot table by given pivot table
|
// AddPivotTable provides the method to add pivot table by given pivot table
|
||||||
|
@ -452,6 +458,7 @@ func (f *File) addPivotDataFields(pt *xlsxPivotTableDefinition, opts *PivotTable
|
||||||
}
|
}
|
||||||
dataFieldsSubtotals := f.getPivotTableFieldsSubtotal(opts.Data)
|
dataFieldsSubtotals := f.getPivotTableFieldsSubtotal(opts.Data)
|
||||||
dataFieldsName := f.getPivotTableFieldsName(opts.Data)
|
dataFieldsName := f.getPivotTableFieldsName(opts.Data)
|
||||||
|
dataFieldsNumFmtID := f.getPivotTableFieldsNumFmtID(opts.Data)
|
||||||
for idx, dataField := range dataFieldsIndex {
|
for idx, dataField := range dataFieldsIndex {
|
||||||
if pt.DataFields == nil {
|
if pt.DataFields == nil {
|
||||||
pt.DataFields = &xlsxDataFields{}
|
pt.DataFields = &xlsxDataFields{}
|
||||||
|
@ -460,6 +467,7 @@ func (f *File) addPivotDataFields(pt *xlsxPivotTableDefinition, opts *PivotTable
|
||||||
Name: dataFieldsName[idx],
|
Name: dataFieldsName[idx],
|
||||||
Fld: dataField,
|
Fld: dataField,
|
||||||
Subtotal: dataFieldsSubtotals[idx],
|
Subtotal: dataFieldsSubtotals[idx],
|
||||||
|
NumFmtID: dataFieldsNumFmtID[idx],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -687,6 +695,22 @@ func (f *File) getPivotTableFieldName(name string, fields []PivotTableField) str
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getPivotTableFieldsNumFmtID prepare fields number format ID by given pivot
|
||||||
|
// table fields.
|
||||||
|
func (f *File) getPivotTableFieldsNumFmtID(fields []PivotTableField) []int {
|
||||||
|
field := make([]int, len(fields))
|
||||||
|
for idx, fld := range fields {
|
||||||
|
if _, ok := builtInNumFmt[fld.NumFmt]; ok {
|
||||||
|
field[idx] = fld.NumFmt
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (27 <= fld.NumFmt && fld.NumFmt <= 36) || (50 <= fld.NumFmt && fld.NumFmt <= 81) {
|
||||||
|
field[idx] = fld.NumFmt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return field
|
||||||
|
}
|
||||||
|
|
||||||
// getPivotTableFieldOptions return options for specific field by given field name.
|
// getPivotTableFieldOptions return options for specific field by given field name.
|
||||||
func (f *File) getPivotTableFieldOptions(name string, fields []PivotTableField) (options PivotTableField, ok bool) {
|
func (f *File) getPivotTableFieldOptions(name string, fields []PivotTableField) (options PivotTableField, ok bool) {
|
||||||
for _, field := range fields {
|
for _, field := range fields {
|
||||||
|
@ -891,6 +915,7 @@ func (f *File) extractPivotTableFields(order []string, pt *xlsxPivotTableDefinit
|
||||||
Data: order[field.Fld],
|
Data: order[field.Fld],
|
||||||
Name: field.Name,
|
Name: field.Name,
|
||||||
Subtotal: cases.Title(language.English).String(field.Subtotal),
|
Subtotal: cases.Title(language.English).String(field.Subtotal),
|
||||||
|
NumFmt: field.NumFmtID,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ func TestPivotTable(t *testing.T) {
|
||||||
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
|
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
|
||||||
Filter: []PivotTableField{{Data: "Region"}},
|
Filter: []PivotTableField{{Data: "Region"}},
|
||||||
Columns: []PivotTableField{{Data: "Type", DefaultSubtotal: true}},
|
Columns: []PivotTableField{{Data: "Type", DefaultSubtotal: true}},
|
||||||
Data: []PivotTableField{{Data: "Sales", Subtotal: "Sum", Name: "Summarize by Sum"}},
|
Data: []PivotTableField{{Data: "Sales", Subtotal: "Sum", Name: "Summarize by Sum", NumFmt: 38}},
|
||||||
RowGrandTotals: true,
|
RowGrandTotals: true,
|
||||||
ColGrandTotals: true,
|
ColGrandTotals: true,
|
||||||
ShowDrill: true,
|
ShowDrill: true,
|
||||||
|
@ -131,7 +131,7 @@ func TestPivotTable(t *testing.T) {
|
||||||
PivotTableRange: "Sheet2!A1:AN17",
|
PivotTableRange: "Sheet2!A1:AN17",
|
||||||
Rows: []PivotTableField{{Data: "Month"}},
|
Rows: []PivotTableField{{Data: "Month"}},
|
||||||
Columns: []PivotTableField{{Data: "Region", DefaultSubtotal: true}, {Data: "Type", DefaultSubtotal: true}, {Data: "Year"}},
|
Columns: []PivotTableField{{Data: "Region", DefaultSubtotal: true}, {Data: "Type", DefaultSubtotal: true}, {Data: "Year"}},
|
||||||
Data: []PivotTableField{{Data: "Sales", Subtotal: "Min", Name: "Summarize by Min"}},
|
Data: []PivotTableField{{Data: "Sales", Subtotal: "Min", Name: "Summarize by Min", NumFmt: 32}},
|
||||||
RowGrandTotals: true,
|
RowGrandTotals: true,
|
||||||
ColGrandTotals: true,
|
ColGrandTotals: true,
|
||||||
ShowDrill: true,
|
ShowDrill: true,
|
||||||
|
@ -151,7 +151,7 @@ func TestPivotTable(t *testing.T) {
|
||||||
PivotTableRange: "Sheet2!A20:AR60",
|
PivotTableRange: "Sheet2!A20:AR60",
|
||||||
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Type"}},
|
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Type"}},
|
||||||
Columns: []PivotTableField{{Data: "Region", DefaultSubtotal: true}, {Data: "Year"}},
|
Columns: []PivotTableField{{Data: "Region", DefaultSubtotal: true}, {Data: "Year"}},
|
||||||
Data: []PivotTableField{{Data: "Sales", Subtotal: "Product", Name: "Summarize by Product"}},
|
Data: []PivotTableField{{Data: "Sales", Subtotal: "Product", Name: "Summarize by Product", NumFmt: 32}},
|
||||||
RowGrandTotals: true,
|
RowGrandTotals: true,
|
||||||
ColGrandTotals: true,
|
ColGrandTotals: true,
|
||||||
ShowDrill: true,
|
ShowDrill: true,
|
||||||
|
@ -171,7 +171,7 @@ func TestPivotTable(t *testing.T) {
|
||||||
PivotTableRange: "Sheet2!A65:AJ100",
|
PivotTableRange: "Sheet2!A65:AJ100",
|
||||||
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
|
Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
|
||||||
Columns: []PivotTableField{{Data: "Region", DefaultSubtotal: true}, {Data: "Type"}},
|
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"}},
|
Data: []PivotTableField{{Data: "Sales", Subtotal: "Sum", Name: "Sum of Sales", NumFmt: -1}, {Data: "Sales", Subtotal: "Average", Name: "Average of Sales", NumFmt: 38}},
|
||||||
RowGrandTotals: true,
|
RowGrandTotals: true,
|
||||||
ColGrandTotals: true,
|
ColGrandTotals: true,
|
||||||
ShowDrill: true,
|
ShowDrill: true,
|
||||||
|
|
12
styles.go
12
styles.go
|
@ -1902,27 +1902,25 @@ func (f *File) newFont(style *Style) (*xlsxFont, error) {
|
||||||
|
|
||||||
// getNumFmtID provides a function to get number format code ID.
|
// getNumFmtID provides a function to get number format code ID.
|
||||||
// If given number format code does not exist, will return -1.
|
// If given number format code does not exist, will return -1.
|
||||||
func getNumFmtID(styleSheet *xlsxStyleSheet, style *Style) (numFmtID int) {
|
func getNumFmtID(styleSheet *xlsxStyleSheet, style *Style) int {
|
||||||
numFmtID = -1
|
numFmtID := -1
|
||||||
if _, ok := builtInNumFmt[style.NumFmt]; ok {
|
if _, ok := builtInNumFmt[style.NumFmt]; ok {
|
||||||
return style.NumFmt
|
return style.NumFmt
|
||||||
}
|
}
|
||||||
if (27 <= style.NumFmt && style.NumFmt <= 36) || (50 <= style.NumFmt && style.NumFmt <= 81) {
|
if (27 <= style.NumFmt && style.NumFmt <= 36) || (50 <= style.NumFmt && style.NumFmt <= 81) {
|
||||||
numFmtID = style.NumFmt
|
return style.NumFmt
|
||||||
return
|
|
||||||
}
|
}
|
||||||
if fmtCode, ok := currencyNumFmt[style.NumFmt]; ok {
|
if fmtCode, ok := currencyNumFmt[style.NumFmt]; ok {
|
||||||
numFmtID = style.NumFmt
|
numFmtID = style.NumFmt
|
||||||
if styleSheet.NumFmts != nil {
|
if styleSheet.NumFmts != nil {
|
||||||
for _, numFmt := range styleSheet.NumFmts.NumFmt {
|
for _, numFmt := range styleSheet.NumFmts.NumFmt {
|
||||||
if numFmt.FormatCode == fmtCode {
|
if numFmt.FormatCode == fmtCode {
|
||||||
numFmtID = numFmt.NumFmtID
|
return numFmt.NumFmtID
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return numFmtID
|
||||||
}
|
}
|
||||||
|
|
||||||
// newNumFmt provides a function to check if number format code in the range
|
// newNumFmt provides a function to check if number format code in the range
|
||||||
|
|
|
@ -273,7 +273,7 @@ type xlsxDataField struct {
|
||||||
ShowDataAs string `xml:"showDataAs,attr,omitempty"`
|
ShowDataAs string `xml:"showDataAs,attr,omitempty"`
|
||||||
BaseField int `xml:"baseField,attr,omitempty"`
|
BaseField int `xml:"baseField,attr,omitempty"`
|
||||||
BaseItem int64 `xml:"baseItem,attr,omitempty"`
|
BaseItem int64 `xml:"baseItem,attr,omitempty"`
|
||||||
NumFmtID string `xml:"numFmtId,attr,omitempty"`
|
NumFmtID int `xml:"numFmtId,attr,omitempty"`
|
||||||
ExtLst *xlsxExtLst `xml:"extLst"`
|
ExtLst *xlsxExtLst `xml:"extLst"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue