Skip to content

Commit 9ddb52e

Browse files
committed
Fix qax-os#554, init combo chart support, new chart pie of pie, bar of pie chart support
1 parent 5ca7231 commit 9ddb52e

File tree

3 files changed

+136
-12
lines changed

3 files changed

+136
-12
lines changed

chart.go

+102-7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"errors"
1717
"io"
1818
"log"
19+
"reflect"
1920
"strconv"
2021
"strings"
2122
)
@@ -66,6 +67,8 @@ const (
6667
Line = "line"
6768
Pie = "pie"
6869
Pie3D = "pie3D"
70+
PieOfPieChart = "pieOfPie"
71+
BarOfPieChart = "barOfPie"
6972
Radar = "radar"
7073
Scatter = "scatter"
7174
Surface3D = "surface3D"
@@ -123,6 +126,8 @@ var (
123126
Line: 0,
124127
Pie: 0,
125128
Pie3D: 30,
129+
PieOfPieChart: 0,
130+
BarOfPieChart: 0,
126131
Radar: 0,
127132
Scatter: 0,
128133
Surface3D: 15,
@@ -175,6 +180,8 @@ var (
175180
Line: 0,
176181
Pie: 0,
177182
Pie3D: 0,
183+
PieOfPieChart: 0,
184+
BarOfPieChart: 0,
178185
Radar: 0,
179186
Scatter: 0,
180187
Surface3D: 20,
@@ -237,6 +244,8 @@ var (
237244
Line: 0,
238245
Pie: 0,
239246
Pie3D: 0,
247+
PieOfPieChart: 0,
248+
BarOfPieChart: 0,
240249
Radar: 0,
241250
Scatter: 0,
242251
Surface3D: 0,
@@ -297,6 +306,8 @@ var (
297306
Line: "General",
298307
Pie: "General",
299308
Pie3D: "General",
309+
PieOfPieChart: "General",
310+
BarOfPieChart: "General",
300311
Radar: "General",
301312
Scatter: "General",
302313
Surface3D: "General",
@@ -351,6 +362,8 @@ var (
351362
Line: "between",
352363
Pie: "between",
353364
Pie3D: "between",
365+
PieOfPieChart: "between",
366+
BarOfPieChart: "between",
354367
Radar: "between",
355368
Scatter: "between",
356369
Surface3D: "midCat",
@@ -491,7 +504,7 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) {
491504
// AddChart provides the method to add chart in a sheet by given chart format
492505
// set (such as offset, scale, aspect ratio setting and print settings) and
493506
// properties set. For example, create 3D clustered column chart with data
494-
// Sheet1!$A$29:$D$32:
507+
// Sheet1!$E$1:$L$15:
495508
//
496509
// package main
497510
//
@@ -507,12 +520,12 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) {
507520
// for k, v := range values {
508521
// f.SetCellValue("Sheet1", k, v)
509522
// }
510-
// if err := f.AddChart("Sheet1", "E1", `{"type":"col3DClustered","dimension":{"width":640,"height":480},"series":[{"name":"Sheet1!$A$2","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$2:$D$2"},{"name":"Sheet1!$A$3","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$3:$D$3"},{"name":"Sheet1!$A$4","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$4:$D$4"}],"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":"bottom","show_legend_key":false},"title":{"name":"Fruit 3D Clustered Column 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":{"reverse_order":true},"y_axis":{"maximum":7.5,"minimum":0.5}}`); err != nil {
523+
// if err := f.AddChart("Sheet1", "E1", `{"type":"col3DClustered","series":[{"name":"Sheet1!$A$2","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$2:$D$2"},{"name":"Sheet1!$A$3","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$3:$D$3"},{"name":"Sheet1!$A$4","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$4:$D$4"}],"title":{"name":"Fruit 3D Clustered Column 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":{"reverse_order":true},"y_axis":{"maximum":7.5,"minimum":0.5}}`); err != nil {
511524
// println(err.Error())
512525
// return
513526
// }
514527
// // Save xlsx file by the given path.
515-
// if err := xlsx.SaveAs("Book1.xlsx"); err != nil {
528+
// if err := f.SaveAs("Book1.xlsx"); err != nil {
516529
// println(err.Error())
517530
// }
518531
// }
@@ -565,6 +578,8 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) {
565578
// line | line chart
566579
// pie | pie chart
567580
// pie3D | 3D pie chart
581+
// pieOfPie | pie of pie chart
582+
// barOfPie | bar of pie chart
568583
// radar | radar chart
569584
// scatter | scatter chart
570585
// surface3D | 3D surface chart
@@ -681,6 +696,34 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) {
681696
//
682697
// Set chart size by dimension property. The dimension property is optional. The default width is 480, and height is 290.
683698
//
699+
// combo: Specifies tha create a chart that combines two art types in a single
700+
// chart. For example, create a clustered column - line chart with data
701+
// Sheet1!$E$1:$L$15:
702+
//
703+
// package main
704+
//
705+
// import "github.com/360EntSecGroup-Skylar/excelize"
706+
//
707+
// func main() {
708+
// categories := map[string]string{"A2": "Small", "A3": "Normal", "A4": "Large", "B1": "Apple", "C1": "Orange", "D1": "Pear"}
709+
// values := map[string]int{"B2": 2, "C2": 3, "D2": 3, "B3": 5, "C3": 2, "D3": 4, "B4": 6, "C4": 7, "D4": 8}
710+
// f := excelize.NewFile()
711+
// for k, v := range categories {
712+
// f.SetCellValue("Sheet1", k, v)
713+
// }
714+
// for k, v := range values {
715+
// f.SetCellValue("Sheet1", k, v)
716+
// }
717+
// if err := f.AddChart("Sheet1", "E1", `{"type":"col","series":[{"name":"Sheet1!$A$2","categories":"","values":"Sheet1!$B$2:$D$2"},{"name":"Sheet1!$A$3","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$3:$D$3"}],"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":"Clustered Column - Line Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"combo":{"type":"line","series":[{"name":"Sheet1!$A$4","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$4:$D$4"}],"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},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true}}}`); err != nil {
718+
// println(err.Error())
719+
// return
720+
// }
721+
// // Save xlsx file by the given path.
722+
// if err := f.SaveAs("Book1.xlsx"); err != nil {
723+
// println(err.Error())
724+
// }
725+
// }
726+
//
684727
func (f *File) AddChart(sheet, cell, format string) error {
685728
formatSet, err := parseFormatChartSet(format)
686729
if err != nil {
@@ -915,6 +958,8 @@ func (f *File) addChart(formatSet *formatChart) {
915958
Line: f.drawLineChart,
916959
Pie3D: f.drawPie3DChart,
917960
Pie: f.drawPieChart,
961+
PieOfPieChart: f.drawPieOfPieChart,
962+
BarOfPieChart: f.drawBarOfPieChart,
918963
Radar: f.drawRadarChart,
919964
Scatter: f.drawScatterChart,
920965
Surface3D: f.drawSurface3DChart,
@@ -924,8 +969,20 @@ func (f *File) addChart(formatSet *formatChart) {
924969
Bubble: f.drawBaseChart,
925970
Bubble3D: f.drawBaseChart,
926971
}
927-
xlsxChartSpace.Chart.PlotArea = plotAreaFunc[formatSet.Type](formatSet)
928-
972+
addChart := func(c, p *cPlotArea) {
973+
immutable, mutable := reflect.ValueOf(c).Elem(), reflect.ValueOf(p).Elem()
974+
for i := 0; i < mutable.NumField(); i++ {
975+
field := mutable.Field(i)
976+
if field.IsNil() {
977+
continue
978+
}
979+
immutable.FieldByName(mutable.Type().Field(i).Name).Set(field)
980+
}
981+
}
982+
addChart(xlsxChartSpace.Chart.PlotArea, plotAreaFunc[formatSet.Type](formatSet))
983+
if formatSet.Combo != nil {
984+
addChart(xlsxChartSpace.Chart.PlotArea, plotAreaFunc[formatSet.Combo.Type](formatSet.Combo))
985+
}
929986
chart, _ := xml.Marshal(xlsxChartSpace)
930987
media := "xl/charts/chart" + strconv.Itoa(count+1) + ".xml"
931988
f.saveFileList(media, chart)
@@ -1246,6 +1303,40 @@ func (f *File) drawPie3DChart(formatSet *formatChart) *cPlotArea {
12461303
}
12471304
}
12481305

1306+
// drawPieOfPieChart provides a function to draw the c:plotArea element for
1307+
// pie chart by given format sets.
1308+
func (f *File) drawPieOfPieChart(formatSet *formatChart) *cPlotArea {
1309+
return &cPlotArea{
1310+
PieChart: &cCharts{
1311+
OfPieType: &attrValString{
1312+
Val: stringPtr("pie"),
1313+
},
1314+
VaryColors: &attrValBool{
1315+
Val: boolPtr(true),
1316+
},
1317+
Ser: f.drawChartSeries(formatSet),
1318+
SerLines: &attrValString{},
1319+
},
1320+
}
1321+
}
1322+
1323+
// drawBarOfPieChart provides a function to draw the c:plotArea element for
1324+
// pie chart by given format sets.
1325+
func (f *File) drawBarOfPieChart(formatSet *formatChart) *cPlotArea {
1326+
return &cPlotArea{
1327+
PieChart: &cCharts{
1328+
OfPieType: &attrValString{
1329+
Val: stringPtr("bar"),
1330+
},
1331+
VaryColors: &attrValBool{
1332+
Val: boolPtr(true),
1333+
},
1334+
Ser: f.drawChartSeries(formatSet),
1335+
SerLines: &attrValString{},
1336+
},
1337+
}
1338+
}
1339+
12491340
// drawRadarChart provides a function to draw the c:plotArea element for radar
12501341
// chart by given format sets.
12511342
func (f *File) drawRadarChart(formatSet *formatChart) *cPlotArea {
@@ -1371,11 +1462,15 @@ func (f *File) drawChartShape(formatSet *formatChart) *attrValString {
13711462
// drawChartSeries provides a function to draw the c:ser element by given
13721463
// format sets.
13731464
func (f *File) drawChartSeries(formatSet *formatChart) *[]cSer {
1465+
var baseIdx int
1466+
if formatSet.Combo != nil {
1467+
baseIdx = len(formatSet.Combo.Series)
1468+
}
13741469
ser := []cSer{}
13751470
for k := range formatSet.Series {
13761471
ser = append(ser, cSer{
1377-
IDx: &attrValInt{Val: intPtr(k)},
1378-
Order: &attrValInt{Val: intPtr(k)},
1472+
IDx: &attrValInt{Val: intPtr(k + baseIdx)},
1473+
Order: &attrValInt{Val: intPtr(k + baseIdx)},
13791474
Tx: &cTx{
13801475
StrRef: &cStrRef{
13811476
F: formatSet.Series[k].Name,

chart_test.go

+26-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package excelize
33
import (
44
"bytes"
55
"encoding/xml"
6+
"fmt"
67
"path/filepath"
78
"testing"
89

@@ -172,7 +173,31 @@ func TestAddChart(t *testing.T) {
172173
// bubble chart
173174
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"}`))
174175
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}}`))
176+
// pie of pie chart
177+
assert.NoError(t, f.AddChart("Sheet2", "BD48", `{"type":"pieOfPie","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$A$30:$D$37","values":"Sheet1!$B$30:$B$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":"Pie of Pie 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}}`))
178+
// bar of pie chart
179+
assert.NoError(t, f.AddChart("Sheet2", "BD64", `{"type":"barOfPie","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$A$30:$D$37","values":"Sheet1!$B$30:$B$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":"Bar of Pie 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}}`))
180+
// combo chart
181+
f.NewSheet("Combo Charts")
182+
clusteredColumnCombo := map[string][]string{
183+
"A1": {"line", "Clustered Column - Line Chart"},
184+
"I1": {"bubble", "Clustered Column - Bubble Chart"},
185+
"Q1": {"bubble3D", "Clustered Column - Bubble 3D Chart"},
186+
"Y1": {"doughnut", "Clustered Column - Doughnut Chart"},
187+
}
188+
for axis, props := range clusteredColumnCombo {
189+
assert.NoError(t, f.AddChart("Combo Charts", axis, fmt.Sprintf(`{"type":"col","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"}],"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":"%s"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"combo":{"type":"%s","series":[{"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},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true}}}`, props[1], props[0])))
190+
}
191+
stackedAreaCombo := map[string][]string{
192+
"A16": {"line", "Stacked Area - Line Chart"},
193+
"I16": {"bubble", "Stacked Area - Bubble Chart"},
194+
"Q16": {"bubble3D", "Stacked Area - Bubble 3D Chart"},
195+
"Y16": {"doughnut", "Stacked Area - Doughnut Chart"},
196+
}
197+
for axis, props := range stackedAreaCombo {
198+
assert.NoError(t, f.AddChart("Combo Charts", axis, fmt.Sprintf(`{"type":"areaStacked","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"}],"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":"%s"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"combo":{"type":"%s","series":[{"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},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true}}}`, props[1], props[0])))
199+
}
175200
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddChart.xlsx")))
176-
201+
// Test with unsupported chart type
177202
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")
178203
}

0 commit comments

Comments
 (0)