Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion chart.go
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,7 @@ func (opts *Chart) parseTitle() {
// Categories
// Values
// Fill
// Legend
// Line
// Marker
// DataLabel
Expand All @@ -787,7 +788,10 @@ func (opts *Chart) parseTitle() {
// optional and the default value was same with 'Values'.
//
// Fill: This set the format for the data series fill. The 'Fill' property is
// optional
// optional.
//
// Legend: This set the font of legend text for a data series. The 'Legend'
// property is optional.
//
// Line: This sets the line format of the line chart. The 'Line' property is
// optional and if it isn't supplied it will default style. The options that
Expand Down Expand Up @@ -819,6 +823,7 @@ func (opts *Chart) parseTitle() {
//
// Position
// ShowLegendKey
// Font
//
// Position: Set the position of the chart legend. The default legend position
// is bottom. The available positions are:
Expand All @@ -833,6 +838,11 @@ func (opts *Chart) parseTitle() {
// ShowLegendKey: Set the legend keys shall be shown in data labels. The default
// value is false.
//
// Font: Set the font properties of the chart legend text. The properties that
// can be set are the same as the font object that is used for cell formatting.
// The font family, size, color, bold, italic, underline, and strike properties
// can be set.
//
// Set properties of the chart title. The properties that can be set are:
//
// Title
Expand Down Expand Up @@ -1008,6 +1018,9 @@ func (opts *Chart) parseTitle() {
// Set chart size by 'Dimension' property. The 'Dimension' property is optional.
// The default width is 480, and height is 260.
//
// Set chart legend for all data series by 'Legend' property. The 'Legend'
// property is optional.
//
// Set the bubble size in all data series for the bubble chart or 3D bubble
// chart by 'BubbleSizes' property. The 'BubbleSizes' property is optional. The
// default width is 100, and the value should be great than 0 and less or equal
Expand Down
3 changes: 2 additions & 1 deletion chart_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ func TestAddChart(t *testing.T) {
Width: 1,
},
},
Legend: ChartLegend{Font: &Font{Family: "Arial", Size: 11, Strike: true, Color: "777777"}},
},
}
series2 := []ChartSeries{
Expand Down Expand Up @@ -225,7 +226,7 @@ func TestAddChart(t *testing.T) {
{sheetName: "Sheet1", cell: "P1", opts: &Chart{Type: Col, Series: series, Format: format, Legend: ChartLegend{Position: "none", ShowLegendKey: true}, Title: []RichTextRun{{Text: "2D Column Chart", Font: &Font{Size: 11, Family: "Calibri"}}}, PlotArea: plotArea, Border: ChartLine{Type: ChartLineNone}, ShowBlanksAs: "zero", XAxis: ChartAxis{Font: Font{Bold: true, Italic: true, Underline: "dbl", Family: "Times New Roman", Size: 15, Strike: true, Color: "000000"}, Title: []RichTextRun{{Text: "Primary Horizontal Axis Title"}}}, YAxis: ChartAxis{Font: Font{Bold: false, Italic: false, Underline: "sng", Color: "777777"}, Title: []RichTextRun{{Text: "Primary Vertical Axis Title", Font: &Font{Color: "777777", Bold: true, Italic: true, Size: 12}}}}}},
{sheetName: "Sheet1", cell: "X1", opts: &Chart{Type: ColStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "2D Stacked Column Chart"}}, PlotArea: plotArea, Fill: Fill{Type: "pattern", Pattern: 1}, Border: ChartLine{Type: ChartLineAutomatic}, ShowBlanksAs: "zero", GapWidth: uintPtr(10), Overlap: intPtr(100)}},
{sheetName: "Sheet1", cell: "P16", opts: &Chart{Type: ColPercentStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "100% Stacked Column Chart"}}, PlotArea: plotArea, Fill: Fill{Type: "pattern", Color: []string{"EEEEEE"}, Pattern: 1}, Border: ChartLine{Type: ChartLineSolid, Width: 2}, ShowBlanksAs: "zero", XAxis: ChartAxis{Alignment: Alignment{Vertical: "wordArtVertRtl", TextRotation: 0}}}},
{sheetName: "Sheet1", cell: "X16", opts: &Chart{Type: Col3DClustered, Series: series, Format: format, Legend: ChartLegend{Position: "bottom", ShowLegendKey: false}, Title: []RichTextRun{{Text: "3D Clustered Column Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
{sheetName: "Sheet1", cell: "X16", opts: &Chart{Type: Col3DClustered, Series: series, Format: format, Legend: ChartLegend{Position: "bottom", ShowLegendKey: false, Font: &Font{Size: 10}}, Title: []RichTextRun{{Text: "3D Clustered Column Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
{sheetName: "Sheet1", cell: "P30", opts: &Chart{Type: Col3DStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "3D Stacked Column Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero", XAxis: ChartAxis{Alignment: Alignment{Vertical: "vert", TextRotation: 0}}}},
{sheetName: "Sheet1", cell: "X30", opts: &Chart{Type: Col3DPercentStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "3D 100% Stacked Column Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
{sheetName: "Sheet1", cell: "X45", opts: &Chart{Type: Radar, Series: series, Format: format, Legend: ChartLegend{Position: "top_right", ShowLegendKey: false}, Title: []RichTextRun{{Text: "Radar Chart"}}, PlotArea: plotArea, ShowBlanksAs: "span"}},
Expand Down
50 changes: 38 additions & 12 deletions drawing.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,7 @@ func (f *File) addChart(opts *Chart, comboCharts []*Chart) {
BackWall: &cThicknessSpPr{
Thickness: &attrValInt{Val: intPtr(0)},
},
PlotArea: &cPlotArea{},
Legend: &cLegend{
LegendPos: &attrValString{Val: stringPtr(chartLegendPosition[opts.Legend.Position])},
Overlay: &attrValBool{Val: boolPtr(false)},
},

PlotArea: &cPlotArea{},
PlotVisOnly: &attrValBool{Val: boolPtr(false)},
DispBlanksAs: &attrValString{Val: stringPtr(opts.ShowBlanksAs)},
ShowDLblsOverMax: &attrValBool{Val: boolPtr(false)},
Expand Down Expand Up @@ -165,9 +160,7 @@ func (f *File) addChart(opts *Chart, comboCharts []*Chart) {
Bubble: f.drawBubbleChart,
Bubble3D: f.drawBubbleChart,
}
if opts.Legend.Position == "none" {
xlsxChartSpace.Chart.Legend = nil
}
xlsxChartSpace.Chart.drawChartLegend(opts)
xlsxChartSpace.Chart.PlotArea.SpPr = f.drawShapeFill(opts.PlotArea.Fill, xlsxChartSpace.Chart.PlotArea.SpPr)
xlsxChartSpace.Chart.PlotArea.DTable = f.drawPlotAreaDTable(opts)
addChart := func(c, p *cPlotArea) {
Expand Down Expand Up @@ -881,7 +874,8 @@ func (f *File) drawChartSeriesCat(v ChartSeries, opts *Chart) *cCat {
func (f *File) drawChartSeriesVal(v ChartSeries, opts *Chart) *cVal {
val := &cVal{
NumRef: &cNumRef{
F: v.Values,
F: v.Values,
NumCache: &cNumCache{},
},
}
chartSeriesVal := map[ChartType]*cVal{Scatter: nil, Bubble: nil, Bubble3D: nil}
Expand Down Expand Up @@ -935,7 +929,8 @@ func (f *File) drawChartSeriesXVal(v ChartSeries, opts *Chart) *cCat {
func (f *File) drawChartSeriesYVal(v ChartSeries, opts *Chart) *cVal {
val := &cVal{
NumRef: &cNumRef{
F: v.Values,
F: v.Values,
NumCache: &cNumCache{},
},
}
chartSeriesYVal := map[ChartType]*cVal{Scatter: val, Bubble: val, Bubble3D: val}
Expand All @@ -954,7 +949,8 @@ func (f *File) drawCharSeriesBubbleSize(v ChartSeries, opts *Chart) *cVal {
}
return &cVal{
NumRef: &cNumRef{
F: fVal,
F: fVal,
NumCache: &cNumCache{},
},
}
}
Expand Down Expand Up @@ -1343,6 +1339,36 @@ func (f *File) drawChartLn(opts *ChartLine) *aLn {
}
}

// drawChartLegend provides a function to draw the c:legend element.
func (c *cChart) drawChartLegend(opts *Chart) {
if opts.Legend.Position == "none" {
c.Legend = nil
return
}
if c.Legend == nil {
c.Legend = &cLegend{
LegendPos: &attrValString{Val: stringPtr(chartLegendPosition[opts.Legend.Position])},
Overlay: &attrValBool{Val: boolPtr(false)},
}
}
if opts.Legend.Font != nil {
c.Legend.TxPr = &cTxPr{P: aP{PPr: &aPPr{}}}
drawChartFont(opts.Legend.Font, &c.Legend.TxPr.P.PPr.DefRPr)
}
for k := range opts.Series {
font := opts.Series[k].Legend.Font
if font == nil {
continue
}
legendEntry := cLegendEntry{
IDx: &attrValInt{Val: intPtr(k + opts.order)},
TxPr: &cTxPr{P: aP{PPr: &aPPr{}}},
}
drawChartFont(font, &legendEntry.TxPr.P.PPr.DefRPr)
c.Legend.LegendEntry = append(c.Legend.LegendEntry, legendEntry)
}
}

// drawingParser provides a function to parse drawingXML. In order to solve
// the problem that the label structure is changed after serialization and
// deserialization, two different structures: decodeWsDr and encodeWsDr are
Expand Down
20 changes: 15 additions & 5 deletions xmlChart.go
Original file line number Diff line number Diff line change
Expand Up @@ -509,14 +509,22 @@ type cDLbls struct {
ShowLeaderLines *attrValBool `xml:"showLeaderLines"`
}

// cLegendEntry (Legend Entry) directly maps the legendEntry element. This
// element specifies the legend entry.
type cLegendEntry struct {
IDx *attrValInt `xml:"idx"`
TxPr *cTxPr `xml:"txPr"`
}

// cLegend (Legend) directly maps the legend element. This element specifies
// the legend.
type cLegend struct {
Layout *string `xml:"layout"`
LegendPos *attrValString `xml:"legendPos"`
Overlay *attrValBool `xml:"overlay"`
SpPr *cSpPr `xml:"spPr"`
TxPr *cTxPr `xml:"txPr"`
Layout *string `xml:"layout"`
LegendPos *attrValString `xml:"legendPos"`
LegendEntry []cLegendEntry `xml:"legendEntry"`
Overlay *attrValBool `xml:"overlay"`
SpPr *cSpPr `xml:"spPr"`
TxPr *cTxPr `xml:"txPr"`
}

// cPrintSettings directly maps the printSettings element. This element
Expand Down Expand Up @@ -611,6 +619,7 @@ type Chart struct {
type ChartLegend struct {
Position string
ShowLegendKey bool
Font *Font
}

// ChartMarker directly maps the format settings of the chart marker.
Expand Down Expand Up @@ -644,6 +653,7 @@ type ChartSeries struct {
Values string
Sizes string
Fill Fill
Legend ChartLegend
Line ChartLine
Marker ChartMarker
DataLabel ChartDataLabel
Expand Down