Skip to content

Commit c2d6707

Browse files
committed
This closes qax-os#1474, support set the format for the data series fill (solid fill)
- Breaking changes: remove the `Color` field in the `ChartLine` structure - This support set the bubble size in a data series - Unit test update and correct the docs of the function `GetSheetDimension`
1 parent ad90cea commit c2d6707

File tree

5 files changed

+64
-27
lines changed

5 files changed

+64
-27
lines changed

chart.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,9 @@ func parseChartOptions(opts *Chart) (*Chart, error) {
657657
//
658658
// Name
659659
// Categories
660+
// Sizes
660661
// Values
662+
// Fill
661663
// Line
662664
// Marker
663665
//
@@ -670,16 +672,18 @@ func parseChartOptions(opts *Chart) (*Chart, error) {
670672
// the same as the X axis. In most chart types the 'Categories' property is
671673
// optional and the chart will just assume a sequential series from 1..n.
672674
//
675+
// Sizes: This sets the bubble size in a data series.
676+
//
673677
// Values: This is the most important property of a series and is the only
674678
// mandatory option for every chart object. This option links the chart with
675679
// the worksheet data that it displays.
676680
//
681+
// Fill: This set the format for the data series fill.
682+
//
677683
// Line: This sets the line format of the line chart. The 'Line' property is
678684
// optional and if it isn't supplied it will default style. The options that
679685
// can be set are width and color. The range of width is 0.25pt - 999pt. If the
680686
// value of width is outside the range, the default width of the line is 2pt.
681-
// The value for color should be represented in hex format
682-
// (e.g., #000000 - #FFFFFF)
683687
//
684688
// Marker: This sets the marker of the line chart and scatter chart. The range
685689
// of optional field 'Size' is 2-72 (default value is 5). The enumeration value

chart_test.go

+17-9
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,9 @@ func TestAddChart(t *testing.T) {
153153
{Name: "Sheet1!$A$37", Categories: "Sheet1!$B$29:$D$29", Values: "Sheet1!$B$37:$D$37"},
154154
}
155155
series2 := []ChartSeries{
156-
{Name: "Sheet1!$A$30", Categories: "Sheet1!$B$29:$D$29", Values: "Sheet1!$B$30:$D$30", Marker: ChartMarker{Symbol: "none", Size: 10}, Line: ChartLine{Color: "#000000"}},
156+
{Name: "Sheet1!$A$30", Categories: "Sheet1!$B$29:$D$29", Values: "Sheet1!$B$30:$D$30",
157+
Fill: Fill{Type: "pattern", Color: []string{"000000"}, Pattern: 1},
158+
Marker: ChartMarker{Symbol: "none", Size: 10}},
157159
{Name: "Sheet1!$A$31", Categories: "Sheet1!$B$29:$D$29", Values: "Sheet1!$B$31:$D$31"},
158160
{Name: "Sheet1!$A$32", Categories: "Sheet1!$B$29:$D$29", Values: "Sheet1!$B$32:$D$32"},
159161
{Name: "Sheet1!$A$33", Categories: "Sheet1!$B$29:$D$29", Values: "Sheet1!$B$33:$D$33"},
@@ -163,6 +165,16 @@ func TestAddChart(t *testing.T) {
163165
{Name: "Sheet1!$A$37", Categories: "Sheet1!$B$29:$D$29", Values: "Sheet1!$B$37:$D$37", Line: ChartLine{Width: 0.25}},
164166
}
165167
series3 := []ChartSeries{{Name: "Sheet1!$A$30", Categories: "Sheet1!$A$30:$D$37", Values: "Sheet1!$B$30:$B$37"}}
168+
series4 := []ChartSeries{
169+
{Name: "Sheet1!$A$30", Categories: "Sheet1!$B$29:$D$29", Values: "Sheet1!$B$30:$D$30", Sizes: "Sheet1!$B$30:$D$30"},
170+
{Name: "Sheet1!$A$31", Categories: "Sheet1!$B$29:$D$29", Values: "Sheet1!$B$31:$D$31", Sizes: "Sheet1!$B$31:$D$31"},
171+
{Name: "Sheet1!$A$32", Categories: "Sheet1!$B$29:$D$29", Values: "Sheet1!$B$32:$D$32", Sizes: "Sheet1!$B$32:$D$32"},
172+
{Name: "Sheet1!$A$33", Categories: "Sheet1!$B$29:$D$29", Values: "Sheet1!$B$33:$D$33", Sizes: "Sheet1!$B$33:$D$33"},
173+
{Name: "Sheet1!$A$34", Categories: "Sheet1!$B$29:$D$29", Values: "Sheet1!$B$34:$D$34", Sizes: "Sheet1!$B$34:$D$34"},
174+
{Name: "Sheet1!$A$35", Categories: "Sheet1!$B$29:$D$29", Values: "Sheet1!$B$35:$D$35", Sizes: "Sheet1!$B$35:$D$35"},
175+
{Name: "Sheet1!$A$36", Categories: "Sheet1!$B$29:$D$29", Values: "Sheet1!$B$36:$D$36", Sizes: "Sheet1!$B$36:$D$36"},
176+
{Name: "Sheet1!$A$37", Categories: "Sheet1!$B$29:$D$29", Values: "Sheet1!$B$37:$D$37", Sizes: "Sheet1!$B$37:$D$37"},
177+
}
166178
format := GraphicOptions{
167179
ScaleX: defaultPictureScale,
168180
ScaleY: defaultPictureScale,
@@ -242,8 +254,8 @@ func TestAddChart(t *testing.T) {
242254
{sheetName: "Sheet2", cell: "AV32", opts: &Chart{Type: "contour", Series: series, Format: format, Legend: legend, Title: ChartTitle{Name: "Contour Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
243255
{sheetName: "Sheet2", cell: "BD1", opts: &Chart{Type: "wireframeContour", Series: series, Format: format, Legend: legend, Title: ChartTitle{Name: "Wireframe Contour Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
244256
// bubble chart
245-
{sheetName: "Sheet2", cell: "BD16", opts: &Chart{Type: "bubble", Series: series, Format: format, Legend: legend, Title: ChartTitle{Name: "Bubble Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
246-
{sheetName: "Sheet2", cell: "BD32", opts: &Chart{Type: "bubble3D", Series: series, Format: format, Legend: legend, Title: ChartTitle{Name: "Bubble 3D Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero", XAxis: ChartAxis{MajorGridLines: true}, YAxis: ChartAxis{MajorGridLines: true}}},
257+
{sheetName: "Sheet2", cell: "BD16", opts: &Chart{Type: "bubble", Series: series4, Format: format, Legend: legend, Title: ChartTitle{Name: "Bubble Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
258+
{sheetName: "Sheet2", cell: "BD32", opts: &Chart{Type: "bubble3D", Series: series4, Format: format, Legend: legend, Title: ChartTitle{Name: "Bubble 3D Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero", XAxis: ChartAxis{MajorGridLines: true}, YAxis: ChartAxis{MajorGridLines: true}}},
247259
// pie of pie chart
248260
{sheetName: "Sheet2", cell: "BD48", opts: &Chart{Type: "pieOfPie", Series: series3, Format: format, Legend: legend, Title: ChartTitle{Name: "Pie of Pie Chart"}, PlotArea: plotArea, ShowBlanksAs: "zero", XAxis: ChartAxis{MajorGridLines: true}, YAxis: ChartAxis{MajorGridLines: true}}},
249261
// bar of pie chart
@@ -256,18 +268,14 @@ func TestAddChart(t *testing.T) {
256268
assert.NoError(t, err)
257269
clusteredColumnCombo := [][]string{
258270
{"A1", "line", "Clustered Column - Line Chart"},
259-
{"I1", "bubble", "Clustered Column - Bubble Chart"},
260-
{"Q1", "bubble3D", "Clustered Column - Bubble 3D Chart"},
261-
{"Y1", "doughnut", "Clustered Column - Doughnut Chart"},
271+
{"I1", "doughnut", "Clustered Column - Doughnut Chart"},
262272
}
263273
for _, props := range clusteredColumnCombo {
264274
assert.NoError(t, f.AddChart("Combo Charts", props[0], &Chart{Type: "col", Series: series[:4], Format: format, Legend: legend, Title: ChartTitle{Name: props[2]}, PlotArea: ChartPlotArea{ShowBubbleSize: true, ShowCatName: false, ShowLeaderLines: false, ShowPercent: true, ShowSerName: true, ShowVal: true}}, &Chart{Type: props[1], Series: series[4:], Format: format, Legend: legend, PlotArea: ChartPlotArea{ShowBubbleSize: true, ShowCatName: false, ShowLeaderLines: false, ShowPercent: true, ShowSerName: true, ShowVal: true}}))
265275
}
266276
stackedAreaCombo := map[string][]string{
267277
"A16": {"line", "Stacked Area - Line Chart"},
268-
"I16": {"bubble", "Stacked Area - Bubble Chart"},
269-
"Q16": {"bubble3D", "Stacked Area - Bubble 3D Chart"},
270-
"Y16": {"doughnut", "Stacked Area - Doughnut Chart"},
278+
"I16": {"doughnut", "Stacked Area - Doughnut Chart"},
271279
}
272280
for axis, props := range stackedAreaCombo {
273281
assert.NoError(t, f.AddChart("Combo Charts", axis, &Chart{Type: "areaStacked", Series: series[:4], Format: format, Legend: legend, Title: ChartTitle{Name: props[1]}, PlotArea: ChartPlotArea{ShowBubbleSize: true, ShowCatName: false, ShowLeaderLines: false, ShowPercent: true, ShowSerName: true, ShowVal: true}}, &Chart{Type: props[0], Series: series[4:], Format: format, Legend: legend, PlotArea: ChartPlotArea{ShowBubbleSize: true, ShowCatName: false, ShowLeaderLines: false, ShowPercent: true, ShowSerName: true, ShowVal: true}}))

drawing.go

+38-14
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,8 @@ func (f *File) addChart(opts *Chart, comboCharts []*Chart) {
234234
WireframeSurface3D: f.drawSurface3DChart,
235235
Contour: f.drawSurfaceChart,
236236
WireframeContour: f.drawSurfaceChart,
237-
Bubble: f.drawBaseChart,
238-
Bubble3D: f.drawBaseChart,
237+
Bubble: f.drawBubbleChart,
238+
Bubble3D: f.drawBubbleChart,
239239
}
240240
if opts.Legend.Position == "none" {
241241
xlsxChartSpace.Chart.Legend = nil
@@ -270,7 +270,7 @@ func (f *File) drawBaseChart(opts *Chart) *cPlotArea {
270270
Val: stringPtr("col"),
271271
},
272272
Grouping: &attrValString{
273-
Val: stringPtr("clustered"),
273+
Val: stringPtr(plotAreaChartGrouping[opts.Type]),
274274
},
275275
VaryColors: &attrValBool{
276276
Val: opts.VaryColors,
@@ -288,9 +288,6 @@ func (f *File) drawBaseChart(opts *Chart) *cPlotArea {
288288
if *c.BarDir.Val, ok = plotAreaChartBarDir[opts.Type]; !ok {
289289
c.BarDir = nil
290290
}
291-
if *c.Grouping.Val, ok = plotAreaChartGrouping[opts.Type]; !ok {
292-
c.Grouping = nil
293-
}
294291
if *c.Overlap.Val, ok = plotAreaChartOverlap[opts.Type]; !ok {
295292
c.Overlap = nil
296293
}
@@ -726,6 +723,26 @@ func (f *File) drawSurfaceChart(opts *Chart) *cPlotArea {
726723
return plotArea
727724
}
728725

726+
// drawBubbleChart provides a function to draw the c:bubbleChart element by
727+
// given format sets.
728+
func (f *File) drawBubbleChart(opts *Chart) *cPlotArea {
729+
plotArea := &cPlotArea{
730+
BubbleChart: &cCharts{
731+
VaryColors: &attrValBool{
732+
Val: opts.VaryColors,
733+
},
734+
Ser: f.drawChartSeries(opts),
735+
DLbls: f.drawChartDLbls(opts),
736+
AxID: []*attrValInt{
737+
{Val: intPtr(754001152)},
738+
{Val: intPtr(753999904)},
739+
},
740+
},
741+
ValAx: []*cAxs{f.drawPlotAreaCatAx(opts)[0], f.drawPlotAreaValAx(opts)[0]},
742+
}
743+
return plotArea
744+
}
745+
729746
// drawChartShape provides a function to draw the c:shape element by given
730747
// format sets.
731748
func (f *File) drawChartShape(opts *Chart) *attrValString {
@@ -794,13 +811,13 @@ func (f *File) drawChartSeriesSpPr(i int, opts *Chart) *cSpPr {
794811
var srgbClr *attrValString
795812
var schemeClr *aSchemeClr
796813

797-
if color := stringPtr(opts.Series[i].Line.Color); *color != "" {
798-
*color = strings.TrimPrefix(*color, "#")
799-
srgbClr = &attrValString{Val: color}
814+
if color := opts.Series[i].Fill.Color; len(color) == 1 {
815+
srgbClr = &attrValString{Val: stringPtr(strings.TrimPrefix(color[0], "#"))}
800816
} else {
801817
schemeClr = &aSchemeClr{Val: "accent" + strconv.Itoa((opts.order+i)%6+1)}
802818
}
803819

820+
spPr := &cSpPr{SolidFill: &aSolidFill{SchemeClr: schemeClr, SrgbClr: srgbClr}}
804821
spPrScatter := &cSpPr{
805822
Ln: &aLn{
806823
W: 25400,
@@ -817,8 +834,15 @@ func (f *File) drawChartSeriesSpPr(i int, opts *Chart) *cSpPr {
817834
},
818835
},
819836
}
820-
chartSeriesSpPr := map[string]*cSpPr{Line: spPrLine, Scatter: spPrScatter}
821-
return chartSeriesSpPr[opts.Type]
837+
if chartSeriesSpPr, ok := map[string]*cSpPr{
838+
Line: spPrLine, Scatter: spPrScatter,
839+
}[opts.Type]; ok {
840+
return chartSeriesSpPr
841+
}
842+
if srgbClr != nil {
843+
return spPr
844+
}
845+
return nil
822846
}
823847

824848
// drawChartSeriesDPt provides a function to draw the c:dPt element by given
@@ -923,7 +947,7 @@ func (f *File) drawChartSeriesXVal(v ChartSeries, opts *Chart) *cCat {
923947
F: v.Categories,
924948
},
925949
}
926-
chartSeriesXVal := map[string]*cCat{Scatter: cat}
950+
chartSeriesXVal := map[string]*cCat{Scatter: cat, Bubble: cat, Bubble3D: cat}
927951
return chartSeriesXVal[opts.Type]
928952
}
929953

@@ -942,12 +966,12 @@ func (f *File) drawChartSeriesYVal(v ChartSeries, opts *Chart) *cVal {
942966
// drawCharSeriesBubbleSize provides a function to draw the c:bubbleSize
943967
// element by given chart series and format sets.
944968
func (f *File) drawCharSeriesBubbleSize(v ChartSeries, opts *Chart) *cVal {
945-
if _, ok := map[string]bool{Bubble: true, Bubble3D: true}[opts.Type]; !ok {
969+
if _, ok := map[string]bool{Bubble: true, Bubble3D: true}[opts.Type]; !ok || v.Sizes == "" {
946970
return nil
947971
}
948972
return &cVal{
949973
NumRef: &cNumRef{
950-
F: v.Values,
974+
F: v.Sizes,
951975
},
952976
}
953977
}

sheet.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1920,7 +1920,7 @@ func (f *File) SetSheetDimension(sheet string, rangeRef string) error {
19201920
return err
19211921
}
19221922

1923-
// SetSheetDimension provides the method to get the used range of the worksheet.
1923+
// GetSheetDimension provides the method to get the used range of the worksheet.
19241924
func (f *File) GetSheetDimension(sheet string) (string, error) {
19251925
var ref string
19261926
ws, err := f.workSheetReader(sheet)

xmlChart.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,6 @@ type ChartMarker struct {
579579

580580
// ChartLine directly maps the format settings of the chart line.
581581
type ChartLine struct {
582-
Color string
583582
Smooth bool
584583
Width float64
585584
}
@@ -588,7 +587,9 @@ type ChartLine struct {
588587
type ChartSeries struct {
589588
Name string
590589
Categories string
590+
Sizes string
591591
Values string
592+
Fill Fill
592593
Line ChartLine
593594
Marker ChartMarker
594595
}

0 commit comments

Comments
 (0)