summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chart.go79
-rw-r--r--chart_test.go7
-rw-r--r--xmlChart.go4
3 files changed, 74 insertions, 16 deletions
diff --git a/chart.go b/chart.go
index c0060c9..b9439ca 100644
--- a/chart.go
+++ b/chart.go
@@ -69,6 +69,8 @@ const (
WireframeSurface3D = "wireframeSurface3D"
Contour = "contour"
WireframeContour = "wireframeContour"
+ Bubble = "bubble"
+ Bubble3D = "bubble3D"
)
// This section defines the default value of chart properties.
@@ -228,6 +230,8 @@ var (
WireframeSurface3D: 100,
Contour: 100,
WireframeContour: 100,
+ Bubble: 100,
+ Bubble3D: 100,
}
chartView3DPerspective = map[string]int{
Contour: 0,
@@ -283,6 +287,8 @@ var (
Surface3D: 0,
WireframeSurface3D: 0,
Contour: 0,
+ Bubble: 0,
+ Bubble3D: 0,
}
chartLegendPosition = map[string]string{
"bottom": "b",
@@ -342,6 +348,8 @@ var (
WireframeSurface3D: "General",
Contour: "General",
WireframeContour: "General",
+ Bubble: "General",
+ Bubble3D: "General",
}
chartValAxCrossBetween = map[string]string{
Area: "midCat",
@@ -394,6 +402,8 @@ var (
WireframeSurface3D: "midCat",
Contour: "midCat",
WireframeContour: "midCat",
+ Bubble: "midCat",
+ Bubble3D: "midCat",
}
plotAreaChartGrouping = map[string]string{
Area: "standard",
@@ -611,7 +621,9 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) {
// surface3D | 3D surface chart
// wireframeSurface3D | 3D wireframe surface chart
// contour | contour chart
-// wireframeContour | wireframe contour
+// wireframeContour | wireframe contour chart
+// bubble | bubble chart
+// bubble3D | 3D bubble chart
//
// In Excel a chart series is a collection of information that defines which data is plotted such as values, axis labels and formatting.
//
@@ -935,6 +947,8 @@ func (f *File) addChart(formatSet *formatChart) {
WireframeSurface3D: f.drawSurface3DChart,
Contour: f.drawSurfaceChart,
WireframeContour: f.drawSurfaceChart,
+ Bubble: f.drawBaseChart,
+ Bubble3D: f.drawBaseChart,
}
xlsxChartSpace.Chart.PlotArea = plotAreaFunc[formatSet.Type](formatSet)
@@ -965,12 +979,13 @@ func (f *File) drawBaseChart(formatSet *formatChart) *cPlotArea {
},
}
var ok bool
- c.BarDir.Val, ok = plotAreaChartBarDir[formatSet.Type]
- if !ok {
+ if c.BarDir.Val, ok = plotAreaChartBarDir[formatSet.Type]; !ok {
c.BarDir = nil
}
- c.Grouping.Val = plotAreaChartGrouping[formatSet.Type]
- if formatSet.Type == "colStacked" || formatSet.Type == "barStacked" || formatSet.Type == "barPercentStacked" || formatSet.Type == "colPercentStacked" || formatSet.Type == "areaPercentStacked" {
+ if c.Grouping.Val, ok = plotAreaChartGrouping[formatSet.Type]; !ok {
+ c.Grouping = nil
+ }
+ if strings.HasSuffix(formatSet.Type, "Stacked") {
c.Overlap = &attrValInt{Val: 100}
}
catAx := f.drawPlotAreaCatAx(formatSet)
@@ -1176,6 +1191,16 @@ func (f *File) drawBaseChart(formatSet *formatChart) *cPlotArea {
CatAx: catAx,
ValAx: valAx,
},
+ "bubble": {
+ BubbleChart: &c,
+ CatAx: catAx,
+ ValAx: valAx,
+ },
+ "bubble3D": {
+ BubbleChart: &c,
+ CatAx: catAx,
+ ValAx: valAx,
+ },
}
return charts[formatSet.Type]
}
@@ -1381,14 +1406,16 @@ func (f *File) drawChartSeries(formatSet *formatChart) *[]cSer {
F: formatSet.Series[k].Name,
},
},
- SpPr: f.drawChartSeriesSpPr(k, formatSet),
- Marker: f.drawChartSeriesMarker(k, formatSet),
- DPt: f.drawChartSeriesDPt(k, formatSet),
- DLbls: f.drawChartSeriesDLbls(formatSet),
- Cat: f.drawChartSeriesCat(formatSet.Series[k], formatSet),
- Val: f.drawChartSeriesVal(formatSet.Series[k], formatSet),
- XVal: f.drawChartSeriesXVal(formatSet.Series[k], formatSet),
- YVal: f.drawChartSeriesYVal(formatSet.Series[k], formatSet),
+ SpPr: f.drawChartSeriesSpPr(k, formatSet),
+ Marker: f.drawChartSeriesMarker(k, formatSet),
+ DPt: f.drawChartSeriesDPt(k, formatSet),
+ DLbls: f.drawChartSeriesDLbls(formatSet),
+ Cat: f.drawChartSeriesCat(formatSet.Series[k], formatSet),
+ Val: f.drawChartSeriesVal(formatSet.Series[k], formatSet),
+ XVal: f.drawChartSeriesXVal(formatSet.Series[k], formatSet),
+ YVal: f.drawChartSeriesYVal(formatSet.Series[k], formatSet),
+ BubbleSize: f.drawCharSeriesBubbleSize(formatSet.Series[k], formatSet),
+ Bubble3D: f.drawCharSeriesBubble3D(formatSet),
})
}
return &ser
@@ -1525,10 +1552,32 @@ func (f *File) drawChartSeriesYVal(v formatChartSeries, formatSet *formatChart)
F: v.Values,
},
}
- chartSeriesYVal := map[string]*cVal{Scatter: val}
+ chartSeriesYVal := map[string]*cVal{Scatter: val, Bubble: val, Bubble3D: val}
return chartSeriesYVal[formatSet.Type]
}
+// drawCharSeriesBubbleSize provides a function to draw the c:bubbleSize
+// element by given chart series and format sets.
+func (f *File) drawCharSeriesBubbleSize(v formatChartSeries, formatSet *formatChart) *cVal {
+ if _, ok := map[string]bool{Bubble: true, Bubble3D: true}[formatSet.Type]; !ok {
+ return nil
+ }
+ return &cVal{
+ NumRef: &cNumRef{
+ F: v.Values,
+ },
+ }
+}
+
+// drawCharSeriesBubble3D provides a function to draw the c:bubble3D element
+// by given format sets.
+func (f *File) drawCharSeriesBubble3D(formatSet *formatChart) *attrValBool {
+ if _, ok := map[string]bool{Bubble3D: true}[formatSet.Type]; !ok {
+ return nil
+ }
+ return &attrValBool{Val: true}
+}
+
// drawChartDLbls provides a function to draw the c:dLbls element by given
// format sets.
func (f *File) drawChartDLbls(formatSet *formatChart) *cDLbls {
@@ -1547,7 +1596,7 @@ func (f *File) drawChartDLbls(formatSet *formatChart) *cDLbls {
// given format sets.
func (f *File) drawChartSeriesDLbls(formatSet *formatChart) *cDLbls {
dLbls := f.drawChartDLbls(formatSet)
- chartSeriesDLbls := map[string]*cDLbls{Scatter: nil, Surface3D: nil, WireframeSurface3D: nil, Contour: nil, WireframeContour: nil}
+ chartSeriesDLbls := map[string]*cDLbls{Scatter: nil, Surface3D: nil, WireframeSurface3D: nil, Contour: nil, WireframeContour: nil, Bubble: nil, Bubble3D: nil}
if _, ok := chartSeriesDLbls[formatSet.Type]; ok {
return nil
}
diff --git a/chart_test.go b/chart_test.go
index 326354a..c0bae33 100644
--- a/chart_test.go
+++ b/chart_test.go
@@ -174,7 +174,12 @@ func TestAddChart(t *testing.T) {
// surface series chart
assert.NoError(t, f.AddChart("Sheet2", "AV1", `{"type":"surface3D","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"},{"name":"Sheet1!$A$33","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$33:$D$33"},{"name":"Sheet1!$A$34","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$34:$D$34"},{"name":"Sheet1!$A$35","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$35:$D$35"},{"name":"Sheet1!$A$36","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$36:$D$36"},{"name":"Sheet1!$A$37","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$37:$D$37"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"3D Surface Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero","y_axis":{"major_grid_lines":true}}`))
assert.NoError(t, f.AddChart("Sheet2", "AV16", `{"type":"wireframeSurface3D","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"},{"name":"Sheet1!$A$33","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$33:$D$33"},{"name":"Sheet1!$A$34","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$34:$D$34"},{"name":"Sheet1!$A$35","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$35:$D$35"},{"name":"Sheet1!$A$36","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$36:$D$36"},{"name":"Sheet1!$A$37","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$37:$D$37"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"3D Wireframe Surface Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero","y_axis":{"major_grid_lines":true}}`))
- assert.NoError(t, f.AddChart("Sheet2", "AV30", `{"type":"contour","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"},{"name":"Sheet1!$A$33","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$33:$D$33"},{"name":"Sheet1!$A$34","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$34:$D$34"},{"name":"Sheet1!$A$35","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$35:$D$35"},{"name":"Sheet1!$A$36","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$36:$D$36"},{"name":"Sheet1!$A$37","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$37:$D$37"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Contour Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`))
+ assert.NoError(t, f.AddChart("Sheet2", "AV32", `{"type":"contour","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"},{"name":"Sheet1!$A$33","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$33:$D$33"},{"name":"Sheet1!$A$34","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$34:$D$34"},{"name":"Sheet1!$A$35","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$35:$D$35"},{"name":"Sheet1!$A$36","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$36:$D$36"},{"name":"Sheet1!$A$37","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$37:$D$37"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Contour Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`))
assert.NoError(t, f.AddChart("Sheet2", "BD1", `{"type":"wireframeContour","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"},{"name":"Sheet1!$A$33","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$33:$D$33"},{"name":"Sheet1!$A$34","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$34:$D$34"},{"name":"Sheet1!$A$35","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$35:$D$35"},{"name":"Sheet1!$A$36","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$36:$D$36"},{"name":"Sheet1!$A$37","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$37:$D$37"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Wireframe Contour Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`))
+ // bubble chart
+ assert.NoError(t, f.AddChart("Sheet2", "BD16", `{"type":"bubble","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"},{"name":"Sheet1!$A$33","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$33:$D$33"},{"name":"Sheet1!$A$34","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$34:$D$34"},{"name":"Sheet1!$A$35","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$35:$D$35"},{"name":"Sheet1!$A$36","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$36:$D$36"},{"name":"Sheet1!$A$37","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$37:$D$37"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Bubble Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`))
+ assert.NoError(t, f.AddChart("Sheet2", "BD32", `{"type":"bubble3D","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"},{"name":"Sheet1!$A$33","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$33:$D$33"},{"name":"Sheet1!$A$34","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$34:$D$34"},{"name":"Sheet1!$A$35","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$35:$D$35"},{"name":"Sheet1!$A$36","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$36:$D$36"},{"name":"Sheet1!$A$37","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$37:$D$37"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Bubble 3D Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero","x_axis":{"major_grid_lines":true},"y_axis":{"major_grid_lines":true}}`))
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddChart.xlsx")))
+
+ assert.EqualError(t, f.AddChart("Sheet2", "BD32", `{"type":"unknown","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"},{"name":"Sheet1!$A$33","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$33:$D$33"},{"name":"Sheet1!$A$34","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$34:$D$34"},{"name":"Sheet1!$A$35","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$35:$D$35"},{"name":"Sheet1!$A$36","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$36:$D$36"},{"name":"Sheet1!$A$37","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$37:$D$37"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"Bubble 3D Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero"}`), "unsupported chart type unknown")
}
diff --git a/xmlChart.go b/xmlChart.go
index ff28bd3..8a3a680 100644
--- a/xmlChart.go
+++ b/xmlChart.go
@@ -306,6 +306,7 @@ type cPlotArea struct {
Area3DChart *cCharts `xml:"area3DChart"`
BarChart *cCharts `xml:"barChart"`
Bar3DChart *cCharts `xml:"bar3DChart"`
+ BubbleChart *cCharts `xml:"bubbleChart"`
DoughnutChart *cCharts `xml:"doughnutChart"`
LineChart *cCharts `xml:"lineChart"`
PieChart *cCharts `xml:"pieChart"`
@@ -323,6 +324,7 @@ type cPlotArea struct {
// cCharts specifies the common element of the chart.
type cCharts struct {
BarDir *attrValString `xml:"barDir"`
+ BubbleScale *attrValFloat `xml:"bubbleScale"`
Grouping *attrValString `xml:"grouping"`
RadarStyle *attrValString `xml:"radarStyle"`
ScatterStyle *attrValString `xml:"scatterStyle"`
@@ -395,6 +397,8 @@ type cSer struct {
XVal *cCat `xml:"xVal"`
YVal *cVal `xml:"yVal"`
Smooth *attrValBool `xml:"smooth"`
+ BubbleSize *cVal `xml:"bubbleSize"`
+ Bubble3D *attrValBool `xml:"bubble3D"`
}
// cMarker (Marker) directly maps the marker element. This element specifies a