This closes #1499, support to set number format for chart data labels and axis

This commit is contained in:
xuri 2023-03-18 15:59:39 +08:00
parent e394f01a97
commit 7631fd08e1
No known key found for this signature in database
GPG Key ID: BA5E5BB1C948EDF7
3 changed files with 35 additions and 10 deletions

View File

@ -220,12 +220,12 @@ func TestAddChart(t *testing.T) {
{sheetName: "Sheet1", cell: "AV30", opts: &Chart{Type: "col3DCylinderPercentStacked", Series: series, Format: format, Legend: legend, Title: ChartTitle{Name: "3D Column Cylinder Percent Stacked Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero"}}, {sheetName: "Sheet1", cell: "AV30", opts: &Chart{Type: "col3DCylinderPercentStacked", Series: series, Format: format, Legend: legend, Title: ChartTitle{Name: "3D Column Cylinder Percent Stacked Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
{sheetName: "Sheet1", cell: "AV45", opts: &Chart{Type: "col3DCylinder", Series: series, Format: format, Legend: legend, Title: ChartTitle{Name: "3D Column Cylinder Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero"}}, {sheetName: "Sheet1", cell: "AV45", opts: &Chart{Type: "col3DCylinder", Series: series, Format: format, Legend: legend, Title: ChartTitle{Name: "3D Column Cylinder Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
{sheetName: "Sheet1", cell: "P45", opts: &Chart{Type: "col3D", Series: series, Format: format, Legend: legend, Title: ChartTitle{Name: "3D Column Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero"}}, {sheetName: "Sheet1", cell: "P45", opts: &Chart{Type: "col3D", Series: series, Format: format, Legend: legend, Title: ChartTitle{Name: "3D Column Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
{sheetName: "Sheet2", cell: "P1", opts: &Chart{Type: "line3D", Series: series2, Format: format, Legend: ChartLegend{Position: "top", ShowLegendKey: false}, Title: ChartTitle{Name: "3D Line Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero", XAxis: ChartAxis{MajorGridLines: true, MinorGridLines: true, TickLabelSkip: 1}, YAxis: ChartAxis{MajorGridLines: true, MinorGridLines: true, MajorUnit: 1}}}, {sheetName: "Sheet2", cell: "P1", opts: &Chart{Type: "line3D", Series: series2, Format: format, Legend: ChartLegend{Position: "top", ShowLegendKey: false}, Title: ChartTitle{Name: "3D Line Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero", XAxis: ChartAxis{MajorGridLines: true, MinorGridLines: true, TickLabelSkip: 1, NumFmt: ChartNumFmt{CustomNumFmt: "General"}}, YAxis: ChartAxis{MajorGridLines: true, MinorGridLines: true, MajorUnit: 1, NumFmt: ChartNumFmt{CustomNumFmt: "General"}}}},
{sheetName: "Sheet2", cell: "X1", opts: &Chart{Type: "scatter", Series: series, Format: format, Legend: ChartLegend{Position: "bottom", ShowLegendKey: false}, Title: ChartTitle{Name: "Scatter Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero"}}, {sheetName: "Sheet2", cell: "X1", opts: &Chart{Type: "scatter", Series: series, Format: format, Legend: ChartLegend{Position: "bottom", ShowLegendKey: false}, Title: ChartTitle{Name: "Scatter Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
{sheetName: "Sheet2", cell: "P16", opts: &Chart{Type: "doughnut", Series: series3, Format: format, Legend: ChartLegend{Position: "right", ShowLegendKey: false}, Title: ChartTitle{Name: "Doughnut Chart"}, PlotArea: ChartPlotArea{ShowBubbleSize: false, ShowCatName: false, ShowLeaderLines: false, ShowPercent: true, ShowSerName: false, ShowVal: false}, ShowBlanksAs: "zero", HoleSize: 30}}, {sheetName: "Sheet2", cell: "P16", opts: &Chart{Type: "doughnut", Series: series3, Format: format, Legend: ChartLegend{Position: "right", ShowLegendKey: false}, Title: ChartTitle{Name: "Doughnut Chart"}, PlotArea: ChartPlotArea{ShowBubbleSize: false, ShowCatName: false, ShowLeaderLines: false, ShowPercent: true, ShowSerName: false, ShowVal: false}, ShowBlanksAs: "zero", HoleSize: 30}},
{sheetName: "Sheet2", cell: "X16", opts: &Chart{Type: "line", Series: series2, Format: format, Legend: ChartLegend{Position: "top", ShowLegendKey: false}, Title: ChartTitle{Name: "Line Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero", XAxis: ChartAxis{MajorGridLines: true, MinorGridLines: true, TickLabelSkip: 1}, YAxis: ChartAxis{MajorGridLines: true, MinorGridLines: true, MajorUnit: 1}}}, {sheetName: "Sheet2", cell: "X16", opts: &Chart{Type: "line", Series: series2, Format: format, Legend: ChartLegend{Position: "top", ShowLegendKey: false}, Title: ChartTitle{Name: "Line Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero", XAxis: ChartAxis{MajorGridLines: true, MinorGridLines: true, TickLabelSkip: 1}, YAxis: ChartAxis{MajorGridLines: true, MinorGridLines: true, MajorUnit: 1}}},
{sheetName: "Sheet2", cell: "P32", opts: &Chart{Type: "pie3D", Series: series3, Format: format, Legend: ChartLegend{Position: "bottom", ShowLegendKey: false}, Title: ChartTitle{Name: "3D Column Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero"}}, {sheetName: "Sheet2", cell: "P32", opts: &Chart{Type: "pie3D", Series: series3, Format: format, Legend: ChartLegend{Position: "bottom", ShowLegendKey: false}, Title: ChartTitle{Name: "3D Column Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
{sheetName: "Sheet2", cell: "X32", opts: &Chart{Type: "pie", Series: series3, Format: format, Legend: ChartLegend{Position: "bottom", ShowLegendKey: false}, Title: ChartTitle{Name: "Pie Chart"}, PlotArea: ChartPlotArea{ShowBubbleSize: true, ShowCatName: false, ShowLeaderLines: false, ShowPercent: true, ShowSerName: false, ShowVal: false}, ShowBlanksAs: "gap"}}, {sheetName: "Sheet2", cell: "X32", opts: &Chart{Type: "pie", Series: series3, Format: format, Legend: ChartLegend{Position: "bottom", ShowLegendKey: false}, Title: ChartTitle{Name: "Pie Chart"}, PlotArea: ChartPlotArea{ShowBubbleSize: true, ShowCatName: false, ShowLeaderLines: false, ShowPercent: true, ShowSerName: false, ShowVal: false, NumFmt: ChartNumFmt{CustomNumFmt: "0.00%;0;;"}}, ShowBlanksAs: "gap"}},
// bar series chart // bar series chart
{sheetName: "Sheet2", cell: "P48", opts: &Chart{Type: "bar", Series: series, Format: format, Legend: legend, Title: ChartTitle{Name: "2D Clustered Bar Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero"}}, {sheetName: "Sheet2", cell: "P48", opts: &Chart{Type: "bar", Series: series, Format: format, Legend: legend, Title: ChartTitle{Name: "2D Clustered Bar Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
{sheetName: "Sheet2", cell: "X48", opts: &Chart{Type: "barStacked", Series: series, Format: format, Legend: legend, Title: ChartTitle{Name: "2D Stacked Bar Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero"}}, {sheetName: "Sheet2", cell: "X48", opts: &Chart{Type: "barStacked", Series: series, Format: format, Legend: legend, Title: ChartTitle{Name: "2D Stacked Bar Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero"}},

View File

@ -995,10 +995,24 @@ func (f *File) drawCharSeriesBubble3D(opts *Chart) *attrValBool {
return &attrValBool{Val: boolPtr(true)} return &attrValBool{Val: boolPtr(true)}
} }
// drawChartNumFmt provides a function to draw the c:numFmt element by given
// data labels format sets.
func (f *File) drawChartNumFmt(labels ChartNumFmt) *cNumFmt {
var numFmt *cNumFmt
if labels.CustomNumFmt != "" || labels.SourceLinked {
numFmt = &cNumFmt{
FormatCode: labels.CustomNumFmt,
SourceLinked: labels.SourceLinked,
}
}
return numFmt
}
// drawChartDLbls provides a function to draw the c:dLbls element by given // drawChartDLbls provides a function to draw the c:dLbls element by given
// format sets. // format sets.
func (f *File) drawChartDLbls(opts *Chart) *cDLbls { func (f *File) drawChartDLbls(opts *Chart) *cDLbls {
return &cDLbls{ return &cDLbls{
NumFmt: f.drawChartNumFmt(opts.PlotArea.NumFmt),
ShowLegendKey: &attrValBool{Val: boolPtr(opts.Legend.ShowLegendKey)}, ShowLegendKey: &attrValBool{Val: boolPtr(opts.Legend.ShowLegendKey)},
ShowVal: &attrValBool{Val: boolPtr(opts.PlotArea.ShowVal)}, ShowVal: &attrValBool{Val: boolPtr(opts.PlotArea.ShowVal)},
ShowCatName: &attrValBool{Val: boolPtr(opts.PlotArea.ShowCatName)}, ShowCatName: &attrValBool{Val: boolPtr(opts.PlotArea.ShowCatName)},
@ -1040,12 +1054,9 @@ func (f *File) drawPlotAreaCatAx(opts *Chart) []*cAxs {
Max: max, Max: max,
Min: min, Min: min,
}, },
Delete: &attrValBool{Val: boolPtr(opts.XAxis.None)}, Delete: &attrValBool{Val: boolPtr(opts.XAxis.None)},
AxPos: &attrValString{Val: stringPtr(catAxPos[opts.XAxis.ReverseOrder])}, AxPos: &attrValString{Val: stringPtr(catAxPos[opts.XAxis.ReverseOrder])},
NumFmt: &cNumFmt{ NumFmt: &cNumFmt{FormatCode: "General"},
FormatCode: "General",
SourceLinked: true,
},
MajorTickMark: &attrValString{Val: stringPtr("none")}, MajorTickMark: &attrValString{Val: stringPtr("none")},
MinorTickMark: &attrValString{Val: stringPtr("none")}, MinorTickMark: &attrValString{Val: stringPtr("none")},
TickLblPos: &attrValString{Val: stringPtr("nextTo")}, TickLblPos: &attrValString{Val: stringPtr("nextTo")},
@ -1059,6 +1070,9 @@ func (f *File) drawPlotAreaCatAx(opts *Chart) []*cAxs {
NoMultiLvlLbl: &attrValBool{Val: boolPtr(false)}, NoMultiLvlLbl: &attrValBool{Val: boolPtr(false)},
}, },
} }
if numFmt := f.drawChartNumFmt(opts.XAxis.NumFmt); numFmt != nil {
axs[0].NumFmt = numFmt
}
if opts.XAxis.MajorGridLines { if opts.XAxis.MajorGridLines {
axs[0].MajorGridlines = &cChartLines{SpPr: f.drawPlotAreaSpPr()} axs[0].MajorGridlines = &cChartLines{SpPr: f.drawPlotAreaSpPr()}
} }
@ -1097,8 +1111,7 @@ func (f *File) drawPlotAreaValAx(opts *Chart) []*cAxs {
Delete: &attrValBool{Val: boolPtr(opts.YAxis.None)}, Delete: &attrValBool{Val: boolPtr(opts.YAxis.None)},
AxPos: &attrValString{Val: stringPtr(valAxPos[opts.YAxis.ReverseOrder])}, AxPos: &attrValString{Val: stringPtr(valAxPos[opts.YAxis.ReverseOrder])},
NumFmt: &cNumFmt{ NumFmt: &cNumFmt{
FormatCode: chartValAxNumFmtFormatCode[opts.Type], FormatCode: chartValAxNumFmtFormatCode[opts.Type],
SourceLinked: true,
}, },
MajorTickMark: &attrValString{Val: stringPtr("none")}, MajorTickMark: &attrValString{Val: stringPtr("none")},
MinorTickMark: &attrValString{Val: stringPtr("none")}, MinorTickMark: &attrValString{Val: stringPtr("none")},
@ -1110,6 +1123,9 @@ func (f *File) drawPlotAreaValAx(opts *Chart) []*cAxs {
CrossBetween: &attrValString{Val: stringPtr(chartValAxCrossBetween[opts.Type])}, CrossBetween: &attrValString{Val: stringPtr(chartValAxCrossBetween[opts.Type])},
}, },
} }
if numFmt := f.drawChartNumFmt(opts.YAxis.NumFmt); numFmt != nil {
axs[0].NumFmt = numFmt
}
if opts.YAxis.MajorGridLines { if opts.YAxis.MajorGridLines {
axs[0].MajorGridlines = &cChartLines{SpPr: f.drawPlotAreaSpPr()} axs[0].MajorGridlines = &cChartLines{SpPr: f.drawPlotAreaSpPr()}
} }

View File

@ -481,6 +481,7 @@ type cNumCache struct {
// entire series or the entire chart. It contains child elements that specify // entire series or the entire chart. It contains child elements that specify
// the specific formatting and positioning settings. // the specific formatting and positioning settings.
type cDLbls struct { type cDLbls struct {
NumFmt *cNumFmt `xml:"numFmt"`
ShowLegendKey *attrValBool `xml:"showLegendKey"` ShowLegendKey *attrValBool `xml:"showLegendKey"`
ShowVal *attrValBool `xml:"showVal"` ShowVal *attrValBool `xml:"showVal"`
ShowCatName *attrValBool `xml:"showCatName"` ShowCatName *attrValBool `xml:"showCatName"`
@ -519,6 +520,12 @@ type cPageMargins struct {
T float64 `xml:"t,attr"` T float64 `xml:"t,attr"`
} }
// ChartNumFmt directly maps the number format settings of the chart.
type ChartNumFmt struct {
CustomNumFmt string
SourceLinked bool
}
// ChartAxis directly maps the format settings of the chart axis. // ChartAxis directly maps the format settings of the chart axis.
type ChartAxis struct { type ChartAxis struct {
None bool None bool
@ -531,6 +538,7 @@ type ChartAxis struct {
Minimum *float64 Minimum *float64
Font Font Font Font
LogBase float64 LogBase float64
NumFmt ChartNumFmt
} }
// ChartDimension directly maps the dimension of the chart. // ChartDimension directly maps the dimension of the chart.
@ -548,6 +556,7 @@ type ChartPlotArea struct {
ShowPercent bool ShowPercent bool
ShowSerName bool ShowSerName bool
ShowVal bool ShowVal bool
NumFmt ChartNumFmt
} }
// Chart directly maps the format settings of the chart. // Chart directly maps the format settings of the chart.