From b1f632d4084130628f10906ff6a7bb55022e4c08 Mon Sep 17 00:00:00 2001 From: xuri Date: Tue, 30 Apr 2019 18:39:27 +0800 Subject: Resolve #393, upgrade Go module to v2 --- chart.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index d669a47..88f48b2 100644 --- a/chart.go +++ b/chart.go @@ -308,7 +308,7 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // import ( // "fmt" // -// "github.com/360EntSecGroup-Skylar/excelize" +// "github.com/360EntSecGroup-Skylar/excelize/v2" // ) // // func main() { -- cgit v1.2.1 From 46a3632ee0f441c8990a7205445dfdb00823a6ad Mon Sep 17 00:00:00 2001 From: xuri Date: Sun, 9 Jun 2019 09:53:02 +0800 Subject: Fix #422, avoid accent theme color index overflow --- chart.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index 88f48b2..73c4728 100644 --- a/chart.go +++ b/chart.go @@ -946,11 +946,13 @@ func (f *File) drawChartSeriesSpPr(i int, formatSet *formatChart) *cSpPr { Ln: &aLn{ W: 25400, Cap: "rnd", // rnd, sq, flat - SolidFill: &aSolidFill{ - SchemeClr: &aSchemeClr{Val: "accent" + strconv.Itoa(i+1)}, - }, }, } + if i < 6 { + spPrLine.Ln.SolidFill = &aSolidFill{ + SchemeClr: &aSchemeClr{Val: "accent" + strconv.Itoa(i+1)}, + } + } chartSeriesSpPr := map[string]*cSpPr{Area: nil, AreaStacked: nil, AreaPercentStacked: nil, Area3D: nil, Area3DStacked: nil, Area3DPercentStacked: nil, Bar: nil, BarStacked: nil, BarPercentStacked: nil, Bar3DClustered: nil, Bar3DStacked: nil, Bar3DPercentStacked: nil, Col: nil, ColStacked: nil, ColPercentStacked: nil, Col3DClustered: nil, Col3D: nil, Col3DStacked: nil, Col3DPercentStacked: nil, Doughnut: nil, Line: spPrLine, Pie: nil, Pie3D: nil, Radar: nil, Scatter: spPrScatter} return chartSeriesSpPr[formatSet.Type] } @@ -1014,7 +1016,9 @@ func (f *File) drawChartSeriesMarker(i int, formatSet *formatChart) *cMarker { marker := &cMarker{ Symbol: &attrValString{Val: "circle"}, Size: &attrValInt{Val: 5}, - SpPr: &cSpPr{ + } + if i < 6 { + marker.SpPr = &cSpPr{ SolidFill: &aSolidFill{ SchemeClr: &aSchemeClr{ Val: "accent" + strconv.Itoa(i+1), @@ -1028,7 +1032,7 @@ func (f *File) drawChartSeriesMarker(i int, formatSet *formatChart) *cMarker { }, }, }, - }, + } } chartSeriesMarker := map[string]*cMarker{Area: nil, AreaStacked: nil, AreaPercentStacked: nil, Area3D: nil, Area3DStacked: nil, Area3DPercentStacked: nil, Bar: nil, BarStacked: nil, BarPercentStacked: nil, Bar3DClustered: nil, Bar3DStacked: nil, Bar3DPercentStacked: nil, Col: nil, ColStacked: nil, ColPercentStacked: nil, Col3DClustered: nil, Col3D: nil, Col3DStacked: nil, Col3DPercentStacked: nil, Doughnut: nil, Line: nil, Pie: nil, Pie3D: nil, Radar: nil, Scatter: marker} return chartSeriesMarker[formatSet.Type] -- cgit v1.2.1 From dc0869fde3a717009eb4aeff6a26387f0495b655 Mon Sep 17 00:00:00 2001 From: xuri Date: Fri, 14 Jun 2019 00:05:10 +0800 Subject: support to create cone, pyramid and cylinder series chart for column and bar types --- chart.go | 930 ++++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 656 insertions(+), 274 deletions(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index 73c4728..8ecd8c7 100644 --- a/chart.go +++ b/chart.go @@ -12,148 +12,254 @@ package excelize import ( "encoding/json" "encoding/xml" + "errors" "strconv" "strings" ) // This section defines the currently supported chart types. const ( - Area = "area" - AreaStacked = "areaStacked" - AreaPercentStacked = "areaPercentStacked" - Area3D = "area3D" - Area3DStacked = "area3DStacked" - Area3DPercentStacked = "area3DPercentStacked" - Bar = "bar" - BarStacked = "barStacked" - BarPercentStacked = "barPercentStacked" - Bar3DClustered = "bar3DClustered" - Bar3DStacked = "bar3DStacked" - Bar3DPercentStacked = "bar3DPercentStacked" - Col = "col" - ColStacked = "colStacked" - ColPercentStacked = "colPercentStacked" - Col3DClustered = "col3DClustered" - Col3D = "col3D" - Col3DStacked = "col3DStacked" - Col3DPercentStacked = "col3DPercentStacked" - Doughnut = "doughnut" - Line = "line" - Pie = "pie" - Pie3D = "pie3D" - Radar = "radar" - Scatter = "scatter" + Area = "area" + AreaStacked = "areaStacked" + AreaPercentStacked = "areaPercentStacked" + Area3D = "area3D" + Area3DStacked = "area3DStacked" + Area3DPercentStacked = "area3DPercentStacked" + Bar = "bar" + BarStacked = "barStacked" + BarPercentStacked = "barPercentStacked" + Bar3DClustered = "bar3DClustered" + Bar3DStacked = "bar3DStacked" + Bar3DPercentStacked = "bar3DPercentStacked" + Bar3DConeClustered = "bar3DConeClustered" + Bar3DConeStacked = "bar3DConeStacked" + Bar3DConePercentStacked = "bar3DConePercentStacked" + Bar3DPyramidClustered = "bar3DPyramidClustered" + Bar3DPyramidStacked = "bar3DPyramidStacked" + Bar3DPyramidPercentStacked = "bar3DPyramidPercentStacked" + Bar3DCylinderClustered = "bar3DCylinderClustered" + Bar3DCylinderStacked = "bar3DCylinderStacked" + Bar3DCylinderPercentStacked = "bar3DCylinderPercentStacked" + Col = "col" + ColStacked = "colStacked" + ColPercentStacked = "colPercentStacked" + Col3D = "col3D" + Col3DClustered = "col3DClustered" + Col3DStacked = "col3DStacked" + Col3DPercentStacked = "col3DPercentStacked" + Col3DCone = "col3DCone" + Col3DConeClustered = "col3DConeClustered" + Col3DConeStacked = "col3DConeStacked" + Col3DConePercentStacked = "col3DConePercentStacked" + Col3DPyramid = "col3DPyramid" + Col3DPyramidClustered = "col3DPyramidClustered" + Col3DPyramidStacked = "col3DPyramidStacked" + Col3DPyramidPercentStacked = "col3DPyramidPercentStacked" + Col3DCylinder = "col3DCylinder" + Col3DCylinderClustered = "col3DCylinderClustered" + Col3DCylinderStacked = "col3DCylinderStacked" + Col3DCylinderPercentStacked = "col3DCylinderPercentStacked" + Doughnut = "doughnut" + Line = "line" + Pie = "pie" + Pie3D = "pie3D" + Radar = "radar" + Scatter = "scatter" ) // This section defines the default value of chart properties. var ( chartView3DRotX = map[string]int{ - Area: 0, - AreaStacked: 0, - AreaPercentStacked: 0, - Area3D: 15, - Area3DStacked: 15, - Area3DPercentStacked: 15, - Bar: 0, - BarStacked: 0, - BarPercentStacked: 0, - Bar3DClustered: 15, - Bar3DStacked: 15, - Bar3DPercentStacked: 15, - Col: 0, - ColStacked: 0, - ColPercentStacked: 0, - Col3DClustered: 15, - Col3D: 15, - Col3DStacked: 15, - Col3DPercentStacked: 15, - Doughnut: 0, - Line: 0, - Pie: 0, - Pie3D: 30, - Radar: 0, - Scatter: 0, + Area: 0, + AreaStacked: 0, + AreaPercentStacked: 0, + Area3D: 15, + Area3DStacked: 15, + Area3DPercentStacked: 15, + Bar: 0, + BarStacked: 0, + BarPercentStacked: 0, + Bar3DClustered: 15, + Bar3DStacked: 15, + Bar3DPercentStacked: 15, + Bar3DConeClustered: 15, + Bar3DConeStacked: 15, + Bar3DConePercentStacked: 15, + Bar3DPyramidClustered: 15, + Bar3DPyramidStacked: 15, + Bar3DPyramidPercentStacked: 15, + Bar3DCylinderClustered: 15, + Bar3DCylinderStacked: 15, + Bar3DCylinderPercentStacked: 15, + Col: 0, + ColStacked: 0, + ColPercentStacked: 0, + Col3D: 15, + Col3DClustered: 15, + Col3DStacked: 15, + Col3DPercentStacked: 15, + Col3DCone: 15, + Col3DConeClustered: 15, + Col3DConeStacked: 15, + Col3DConePercentStacked: 15, + Col3DPyramid: 15, + Col3DPyramidClustered: 15, + Col3DPyramidStacked: 15, + Col3DPyramidPercentStacked: 15, + Col3DCylinder: 15, + Col3DCylinderClustered: 15, + Col3DCylinderStacked: 15, + Col3DCylinderPercentStacked: 15, + Doughnut: 0, + Line: 0, + Pie: 0, + Pie3D: 30, + Radar: 0, + Scatter: 0, } chartView3DRotY = map[string]int{ - Area: 0, - AreaStacked: 0, - AreaPercentStacked: 0, - Area3D: 20, - Area3DStacked: 20, - Area3DPercentStacked: 20, - Bar: 0, - BarStacked: 0, - BarPercentStacked: 0, - Bar3DClustered: 20, - Bar3DStacked: 20, - Bar3DPercentStacked: 20, - Col: 0, - ColStacked: 0, - ColPercentStacked: 0, - Col3DClustered: 20, - Col3D: 20, - Col3DStacked: 20, - Col3DPercentStacked: 20, - Doughnut: 0, - Line: 0, - Pie: 0, - Pie3D: 0, - Radar: 0, - Scatter: 0, + Area: 0, + AreaStacked: 0, + AreaPercentStacked: 0, + Area3D: 20, + Area3DStacked: 20, + Area3DPercentStacked: 20, + Bar: 0, + BarStacked: 0, + BarPercentStacked: 0, + Bar3DClustered: 20, + Bar3DStacked: 20, + Bar3DPercentStacked: 20, + Bar3DConeClustered: 20, + Bar3DConeStacked: 20, + Bar3DConePercentStacked: 20, + Bar3DPyramidClustered: 20, + Bar3DPyramidStacked: 20, + Bar3DPyramidPercentStacked: 20, + Bar3DCylinderClustered: 20, + Bar3DCylinderStacked: 20, + Bar3DCylinderPercentStacked: 20, + Col: 0, + ColStacked: 0, + ColPercentStacked: 0, + Col3D: 20, + Col3DClustered: 20, + Col3DStacked: 20, + Col3DPercentStacked: 20, + Col3DCone: 20, + Col3DConeClustered: 20, + Col3DConeStacked: 20, + Col3DConePercentStacked: 20, + Col3DPyramid: 20, + Col3DPyramidClustered: 20, + Col3DPyramidStacked: 20, + Col3DPyramidPercentStacked: 20, + Col3DCylinder: 20, + Col3DCylinderClustered: 20, + Col3DCylinderStacked: 20, + Col3DCylinderPercentStacked: 20, + Doughnut: 0, + Line: 0, + Pie: 0, + Pie3D: 0, + Radar: 0, + Scatter: 0, } chartView3DDepthPercent = map[string]int{ - Area: 100, - AreaStacked: 100, - AreaPercentStacked: 100, - Area3D: 100, - Area3DStacked: 100, - Area3DPercentStacked: 100, - Bar: 100, - BarStacked: 100, - BarPercentStacked: 100, - Bar3DClustered: 100, - Bar3DStacked: 100, - Bar3DPercentStacked: 100, - Col: 100, - ColStacked: 100, - ColPercentStacked: 100, - Col3DClustered: 100, - Col3D: 100, - Col3DStacked: 100, - Col3DPercentStacked: 100, - Doughnut: 100, - Line: 100, - Pie: 100, - Pie3D: 100, - Radar: 100, - Scatter: 100, + Area: 100, + AreaStacked: 100, + AreaPercentStacked: 100, + Area3D: 100, + Area3DStacked: 100, + Area3DPercentStacked: 100, + Bar: 100, + BarStacked: 100, + BarPercentStacked: 100, + Bar3DClustered: 100, + Bar3DStacked: 100, + Bar3DPercentStacked: 100, + Bar3DConeClustered: 100, + Bar3DConeStacked: 100, + Bar3DConePercentStacked: 100, + Bar3DPyramidClustered: 100, + Bar3DPyramidStacked: 100, + Bar3DPyramidPercentStacked: 100, + Bar3DCylinderClustered: 100, + Bar3DCylinderStacked: 100, + Bar3DCylinderPercentStacked: 100, + Col: 100, + ColStacked: 100, + ColPercentStacked: 100, + Col3D: 100, + Col3DClustered: 100, + Col3DStacked: 100, + Col3DPercentStacked: 100, + Col3DCone: 100, + Col3DConeClustered: 100, + Col3DConeStacked: 100, + Col3DConePercentStacked: 100, + Col3DPyramid: 100, + Col3DPyramidClustered: 100, + Col3DPyramidStacked: 100, + Col3DPyramidPercentStacked: 100, + Col3DCylinder: 100, + Col3DCylinderClustered: 100, + Col3DCylinderStacked: 100, + Col3DCylinderPercentStacked: 100, + Doughnut: 100, + Line: 100, + Pie: 100, + Pie3D: 100, + Radar: 100, + Scatter: 100, } chartView3DRAngAx = map[string]int{ - Area: 0, - AreaStacked: 0, - AreaPercentStacked: 0, - Area3D: 1, - Area3DStacked: 1, - Area3DPercentStacked: 1, - Bar: 0, - BarStacked: 0, - BarPercentStacked: 0, - Bar3DClustered: 1, - Bar3DStacked: 1, - Bar3DPercentStacked: 1, - Col: 0, - ColStacked: 0, - ColPercentStacked: 0, - Col3DClustered: 1, - Col3D: 1, - Col3DStacked: 1, - Col3DPercentStacked: 1, - Doughnut: 0, - Line: 0, - Pie: 0, - Pie3D: 0, - Radar: 0, - Scatter: 0, + Area: 0, + AreaStacked: 0, + AreaPercentStacked: 0, + Area3D: 1, + Area3DStacked: 1, + Area3DPercentStacked: 1, + Bar: 0, + BarStacked: 0, + BarPercentStacked: 0, + Bar3DClustered: 1, + Bar3DStacked: 1, + Bar3DPercentStacked: 1, + Bar3DConeClustered: 1, + Bar3DConeStacked: 1, + Bar3DConePercentStacked: 1, + Bar3DPyramidClustered: 1, + Bar3DPyramidStacked: 1, + Bar3DPyramidPercentStacked: 1, + Bar3DCylinderClustered: 1, + Bar3DCylinderStacked: 1, + Bar3DCylinderPercentStacked: 1, + Col: 0, + ColStacked: 0, + ColPercentStacked: 0, + Col3D: 1, + Col3DClustered: 1, + Col3DStacked: 1, + Col3DPercentStacked: 1, + Col3DCone: 1, + Col3DConeClustered: 1, + Col3DConeStacked: 1, + Col3DConePercentStacked: 1, + Col3DPyramid: 1, + Col3DPyramidClustered: 1, + Col3DPyramidStacked: 1, + Col3DPyramidPercentStacked: 1, + Col3DCylinder: 1, + Col3DCylinderClustered: 1, + Col3DCylinderStacked: 1, + Col3DCylinderPercentStacked: 1, + Doughnut: 0, + Line: 0, + Pie: 0, + Pie3D: 0, + Radar: 0, + Scatter: 0, } chartLegendPosition = map[string]string{ "bottom": "b", @@ -163,96 +269,180 @@ var ( "top_right": "tr", } chartValAxNumFmtFormatCode = map[string]string{ - Area: "General", - AreaStacked: "General", - AreaPercentStacked: "0%", - Area3D: "General", - Area3DStacked: "General", - Area3DPercentStacked: "0%", - Bar: "General", - BarStacked: "General", - BarPercentStacked: "0%", - Bar3DClustered: "General", - Bar3DStacked: "General", - Bar3DPercentStacked: "0%", - Col: "General", - ColStacked: "General", - ColPercentStacked: "0%", - Col3DClustered: "General", - Col3D: "General", - Col3DStacked: "General", - Col3DPercentStacked: "0%", - Doughnut: "General", - Line: "General", - Pie: "General", - Pie3D: "General", - Radar: "General", - Scatter: "General", + Area: "General", + AreaStacked: "General", + AreaPercentStacked: "0%", + Area3D: "General", + Area3DStacked: "General", + Area3DPercentStacked: "0%", + Bar: "General", + BarStacked: "General", + BarPercentStacked: "0%", + Bar3DClustered: "General", + Bar3DStacked: "General", + Bar3DPercentStacked: "0%", + Bar3DConeClustered: "General", + Bar3DConeStacked: "General", + Bar3DConePercentStacked: "0%", + Bar3DPyramidClustered: "General", + Bar3DPyramidStacked: "General", + Bar3DPyramidPercentStacked: "0%", + Bar3DCylinderClustered: "General", + Bar3DCylinderStacked: "General", + Bar3DCylinderPercentStacked: "0%", + Col: "General", + ColStacked: "General", + ColPercentStacked: "0%", + Col3D: "General", + Col3DClustered: "General", + Col3DStacked: "General", + Col3DPercentStacked: "0%", + Col3DCone: "General", + Col3DConeClustered: "General", + Col3DConeStacked: "General", + Col3DConePercentStacked: "0%", + Col3DPyramid: "General", + Col3DPyramidClustered: "General", + Col3DPyramidStacked: "General", + Col3DPyramidPercentStacked: "0%", + Col3DCylinder: "General", + Col3DCylinderClustered: "General", + Col3DCylinderStacked: "General", + Col3DCylinderPercentStacked: "0%", + Doughnut: "General", + Line: "General", + Pie: "General", + Pie3D: "General", + Radar: "General", + Scatter: "General", } chartValAxCrossBetween = map[string]string{ - Area: "midCat", - AreaStacked: "midCat", - AreaPercentStacked: "midCat", - Area3D: "midCat", - Area3DStacked: "midCat", - Area3DPercentStacked: "midCat", - Bar: "between", - BarStacked: "between", - BarPercentStacked: "between", - Bar3DClustered: "between", - Bar3DStacked: "between", - Bar3DPercentStacked: "between", - Col: "between", - ColStacked: "between", - ColPercentStacked: "between", - Col3DClustered: "between", - Col3D: "between", - Col3DStacked: "between", - Col3DPercentStacked: "between", - Doughnut: "between", - Line: "between", - Pie: "between", - Pie3D: "between", - Radar: "between", - Scatter: "between", + Area: "midCat", + AreaStacked: "midCat", + AreaPercentStacked: "midCat", + Area3D: "midCat", + Area3DStacked: "midCat", + Area3DPercentStacked: "midCat", + Bar: "between", + BarStacked: "between", + BarPercentStacked: "between", + Bar3DClustered: "between", + Bar3DStacked: "between", + Bar3DPercentStacked: "between", + Bar3DConeClustered: "between", + Bar3DConeStacked: "between", + Bar3DConePercentStacked: "between", + Bar3DPyramidClustered: "between", + Bar3DPyramidStacked: "between", + Bar3DPyramidPercentStacked: "between", + Bar3DCylinderClustered: "between", + Bar3DCylinderStacked: "between", + Bar3DCylinderPercentStacked: "between", + Col: "between", + ColStacked: "between", + ColPercentStacked: "between", + Col3D: "between", + Col3DClustered: "between", + Col3DStacked: "between", + Col3DPercentStacked: "between", + Col3DCone: "between", + Col3DConeClustered: "between", + Col3DConeStacked: "between", + Col3DConePercentStacked: "between", + Col3DPyramid: "between", + Col3DPyramidClustered: "between", + Col3DPyramidStacked: "between", + Col3DPyramidPercentStacked: "between", + Col3DCylinder: "between", + Col3DCylinderClustered: "between", + Col3DCylinderStacked: "between", + Col3DCylinderPercentStacked: "between", + Doughnut: "between", + Line: "between", + Pie: "between", + Pie3D: "between", + Radar: "between", + Scatter: "between", } plotAreaChartGrouping = map[string]string{ - Area: "standard", - AreaStacked: "stacked", - AreaPercentStacked: "percentStacked", - Area3D: "standard", - Area3DStacked: "stacked", - Area3DPercentStacked: "percentStacked", - Bar: "clustered", - BarStacked: "stacked", - BarPercentStacked: "percentStacked", - Bar3DClustered: "clustered", - Bar3DStacked: "stacked", - Bar3DPercentStacked: "percentStacked", - Col: "clustered", - ColStacked: "stacked", - ColPercentStacked: "percentStacked", - Col3DClustered: "clustered", - Col3D: "standard", - Col3DStacked: "stacked", - Col3DPercentStacked: "percentStacked", - Line: "standard", + Area: "standard", + AreaStacked: "stacked", + AreaPercentStacked: "percentStacked", + Area3D: "standard", + Area3DStacked: "stacked", + Area3DPercentStacked: "percentStacked", + Bar: "clustered", + BarStacked: "stacked", + BarPercentStacked: "percentStacked", + Bar3DClustered: "clustered", + Bar3DStacked: "stacked", + Bar3DPercentStacked: "percentStacked", + Bar3DConeClustered: "clustered", + Bar3DConeStacked: "stacked", + Bar3DConePercentStacked: "percentStacked", + Bar3DPyramidClustered: "clustered", + Bar3DPyramidStacked: "stacked", + Bar3DPyramidPercentStacked: "percentStacked", + Bar3DCylinderClustered: "clustered", + Bar3DCylinderStacked: "stacked", + Bar3DCylinderPercentStacked: "percentStacked", + Col: "clustered", + ColStacked: "stacked", + ColPercentStacked: "percentStacked", + Col3D: "standard", + Col3DClustered: "clustered", + Col3DStacked: "stacked", + Col3DPercentStacked: "percentStacked", + Col3DCone: "standard", + Col3DConeClustered: "clustered", + Col3DConeStacked: "stacked", + Col3DConePercentStacked: "percentStacked", + Col3DPyramid: "standard", + Col3DPyramidClustered: "clustered", + Col3DPyramidStacked: "stacked", + Col3DPyramidPercentStacked: "percentStacked", + Col3DCylinder: "standard", + Col3DCylinderClustered: "clustered", + Col3DCylinderStacked: "stacked", + Col3DCylinderPercentStacked: "percentStacked", + Line: "standard", } plotAreaChartBarDir = map[string]string{ - Bar: "bar", - BarStacked: "bar", - BarPercentStacked: "bar", - Bar3DClustered: "bar", - Bar3DStacked: "bar", - Bar3DPercentStacked: "bar", - Col: "col", - ColStacked: "col", - ColPercentStacked: "col", - Col3DClustered: "col", - Col3D: "col", - Col3DStacked: "col", - Col3DPercentStacked: "col", - Line: "standard", + Bar: "bar", + BarStacked: "bar", + BarPercentStacked: "bar", + Bar3DClustered: "bar", + Bar3DStacked: "bar", + Bar3DPercentStacked: "bar", + Bar3DConeClustered: "bar", + Bar3DConeStacked: "bar", + Bar3DConePercentStacked: "bar", + Bar3DPyramidClustered: "bar", + Bar3DPyramidStacked: "bar", + Bar3DPyramidPercentStacked: "bar", + Bar3DCylinderClustered: "bar", + Bar3DCylinderStacked: "bar", + Bar3DCylinderPercentStacked: "bar", + Col: "col", + ColStacked: "col", + ColPercentStacked: "col", + Col3D: "col", + Col3DClustered: "col", + Col3DStacked: "col", + Col3DPercentStacked: "col", + Col3DCone: "col", + Col3DConeStacked: "col", + Col3DConeClustered: "col", + Col3DConePercentStacked: "col", + Col3DPyramid: "col", + Col3DPyramidClustered: "col", + Col3DPyramidStacked: "col", + Col3DPyramidPercentStacked: "col", + Col3DCylinder: "col", + Col3DCylinderClustered: "col", + Col3DCylinderStacked: "col", + Col3DCylinderPercentStacked: "col", + Line: "standard", } orientation = map[bool]string{ true: "maxMin", @@ -335,33 +525,54 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // // The following shows the type of chart supported by excelize: // -// Type | Chart -// ----------------------+------------------------------ -// area | 2D area chart -// areaStacked | 2D stacked area chart -// areaPercentStacked | 2D 100% stacked area chart -// area3D | 3D area chart -// area3DStacked | 3D stacked area chart -// area3DPercentStacked | 3D 100% stacked area chart -// bar | 2D clustered bar chart -// barStacked | 2D stacked bar chart -// barPercentStacked | 2D 100% stacked bar chart -// bar3DClustered | 3D clustered bar chart -// bar3DStacked | 3D stacked bar chart -// bar3DPercentStacked | 3D 100% stacked bar chart -// col | 2D clustered column chart -// colStacked | 2D stacked column chart -// colPercentStacked | 2D 100% stacked column chart -// col3DClustered | 3D clustered column chart -// col3D | 3D column chart -// col3DStacked | 3D stacked column chart -// col3DPercentStacked | 3D 100% stacked column chart -// doughnut | doughnut chart -// line | line chart -// pie | pie chart -// pie3D | 3D pie chart -// radar | radar chart -// scatter | scatter chart +// Type | Chart +// -----------------------------+------------------------------ +// area | 2D area chart +// areaStacked | 2D stacked area chart +// areaPercentStacked | 2D 100% stacked area chart +// area3D | 3D area chart +// area3DStacked | 3D stacked area chart +// area3DPercentStacked | 3D 100% stacked area chart +// bar | 2D clustered bar chart +// barStacked | 2D stacked bar chart +// barPercentStacked | 2D 100% stacked bar chart +// bar3DClustered | 3D clustered bar chart +// bar3DStacked | 3D stacked bar chart +// bar3DPercentStacked | 3D 100% stacked bar chart +// bar3DConeClustered | 3D cone clustered bar chart +// bar3DConeStacked | 3D cone stacked bar chart +// bar3DConePercentStacked | 3D cone percent bar chart +// bar3DPyramidClustered | 3D pyramid clustered bar chart +// bar3DPyramidStacked | 3D pyramid stacked bar chart +// bar3DPyramidPercentStacked | 3D pyramid percent stacked bar chart +// bar3DCylinderClustered | 3D cylinder clustered bar chart +// bar3DCylinderStacked | 3D cylinder stacked bar chart +// bar3DCylinderPercentStacked | 3D cylinder percent stacked bar chart +// col | 2D clustered column chart +// colStacked | 2D stacked column chart +// colPercentStacked | 2D 100% stacked column chart +// col3DClustered | 3D clustered column chart +// col3D | 3D column chart +// col3DStacked | 3D stacked column chart +// col3DPercentStacked | 3D 100% stacked column chart +// col3DCone | 3D cone column chart +// col3DConeClustered | 3D cone clustered column chart +// col3DConeStacked | 3D cone stacked column chart +// col3DConePercentStacked | 3D cone percent stacked column chart +// col3DPyramid | 3D pyramid column chart +// col3DPyramidClustered | 3D pyramid clustered column chart +// col3DPyramidStacked | 3D pyramid stacked column chart +// col3DPyramidPercentStacked | 3D pyramid percent stacked column chart +// col3DCylinder | 3D cylinder column chart +// col3DCylinderClustered | 3D cylinder clustered column chart +// col3DCylinderStacked | 3D cylinder stacked column chart +// col3DCylinderPercentStacked | 3D cylinder percent stacked column chart +// doughnut | doughnut chart +// line | line chart +// pie | pie chart +// pie3D | 3D pie chart +// radar | radar chart +// scatter | scatter chart // // In Excel a chart series is a collection of information that defines which data is plotted such as values, axis labels and formatting. // @@ -457,6 +668,9 @@ func (f *File) AddChart(sheet, cell, format string) error { if err != nil { return err } + if _, ok := chartValAxNumFmtFormatCode[formatSet.Type]; !ok { + return errors.New("unsupported chart type " + formatSet.Type) + } // Add first picture for given sheet, create xl/drawings/ and xl/drawings/_rels/ folder. drawingID := f.countDrawings() + 1 chartID := f.countCharts() + 1 @@ -631,31 +845,52 @@ func (f *File) addChart(formatSet *formatChart) { }, } plotAreaFunc := map[string]func(*formatChart) *cPlotArea{ - Area: f.drawBaseChart, - AreaStacked: f.drawBaseChart, - AreaPercentStacked: f.drawBaseChart, - Area3D: f.drawBaseChart, - Area3DStacked: f.drawBaseChart, - Area3DPercentStacked: f.drawBaseChart, - Bar: f.drawBaseChart, - BarStacked: f.drawBaseChart, - BarPercentStacked: f.drawBaseChart, - Bar3DClustered: f.drawBaseChart, - Bar3DStacked: f.drawBaseChart, - Bar3DPercentStacked: f.drawBaseChart, - Col: f.drawBaseChart, - ColStacked: f.drawBaseChart, - ColPercentStacked: f.drawBaseChart, - Col3DClustered: f.drawBaseChart, - Col3D: f.drawBaseChart, - Col3DStacked: f.drawBaseChart, - Col3DPercentStacked: f.drawBaseChart, - Doughnut: f.drawDoughnutChart, - Line: f.drawLineChart, - Pie3D: f.drawPie3DChart, - Pie: f.drawPieChart, - Radar: f.drawRadarChart, - Scatter: f.drawScatterChart, + Area: f.drawBaseChart, + AreaStacked: f.drawBaseChart, + AreaPercentStacked: f.drawBaseChart, + Area3D: f.drawBaseChart, + Area3DStacked: f.drawBaseChart, + Area3DPercentStacked: f.drawBaseChart, + Bar: f.drawBaseChart, + BarStacked: f.drawBaseChart, + BarPercentStacked: f.drawBaseChart, + Bar3DClustered: f.drawBaseChart, + Bar3DStacked: f.drawBaseChart, + Bar3DPercentStacked: f.drawBaseChart, + Bar3DConeClustered: f.drawBaseChart, + Bar3DConeStacked: f.drawBaseChart, + Bar3DConePercentStacked: f.drawBaseChart, + Bar3DPyramidClustered: f.drawBaseChart, + Bar3DPyramidStacked: f.drawBaseChart, + Bar3DPyramidPercentStacked: f.drawBaseChart, + Bar3DCylinderClustered: f.drawBaseChart, + Bar3DCylinderStacked: f.drawBaseChart, + Bar3DCylinderPercentStacked: f.drawBaseChart, + Col: f.drawBaseChart, + ColStacked: f.drawBaseChart, + ColPercentStacked: f.drawBaseChart, + Col3D: f.drawBaseChart, + Col3DClustered: f.drawBaseChart, + Col3DStacked: f.drawBaseChart, + Col3DPercentStacked: f.drawBaseChart, + Col3DCone: f.drawBaseChart, + Col3DConeClustered: f.drawBaseChart, + Col3DConeStacked: f.drawBaseChart, + Col3DConePercentStacked: f.drawBaseChart, + Col3DPyramid: f.drawBaseChart, + Col3DPyramidClustered: f.drawBaseChart, + Col3DPyramidStacked: f.drawBaseChart, + Col3DPyramidPercentStacked: f.drawBaseChart, + Col3DCylinder: f.drawBaseChart, + Col3DCylinderClustered: f.drawBaseChart, + Col3DCylinderStacked: f.drawBaseChart, + Col3DCylinderPercentStacked: f.drawBaseChart, + Doughnut: f.drawDoughnutChart, + Line: f.drawLineChart, + Pie3D: f.drawPie3DChart, + Pie: f.drawPieChart, + Radar: f.drawRadarChart, + Scatter: f.drawScatterChart, } xlsxChartSpace.Chart.PlotArea = plotAreaFunc[formatSet.Type](formatSet) @@ -678,6 +913,7 @@ func (f *File) drawBaseChart(formatSet *formatChart) *cPlotArea { Val: true, }, Ser: f.drawChartSeries(formatSet), + Shape: f.drawChartShape(formatSet), DLbls: f.drawChartDLbls(formatSet), AxID: []*attrValInt{ {Val: 754001152}, @@ -756,6 +992,51 @@ func (f *File) drawBaseChart(formatSet *formatChart) *cPlotArea { CatAx: catAx, ValAx: valAx, }, + "bar3DConeClustered": { + Bar3DChart: &c, + CatAx: catAx, + ValAx: valAx, + }, + "bar3DConeStacked": { + Bar3DChart: &c, + CatAx: catAx, + ValAx: valAx, + }, + "bar3DConePercentStacked": { + Bar3DChart: &c, + CatAx: catAx, + ValAx: valAx, + }, + "bar3DPyramidClustered": { + Bar3DChart: &c, + CatAx: catAx, + ValAx: valAx, + }, + "bar3DPyramidStacked": { + Bar3DChart: &c, + CatAx: catAx, + ValAx: valAx, + }, + "bar3DPyramidPercentStacked": { + Bar3DChart: &c, + CatAx: catAx, + ValAx: valAx, + }, + "bar3DCylinderClustered": { + Bar3DChart: &c, + CatAx: catAx, + ValAx: valAx, + }, + "bar3DCylinderStacked": { + Bar3DChart: &c, + CatAx: catAx, + ValAx: valAx, + }, + "bar3DCylinderPercentStacked": { + Bar3DChart: &c, + CatAx: catAx, + ValAx: valAx, + }, "col": { BarChart: &c, CatAx: catAx, @@ -771,12 +1052,12 @@ func (f *File) drawBaseChart(formatSet *formatChart) *cPlotArea { CatAx: catAx, ValAx: valAx, }, - "col3DClustered": { + "col3D": { Bar3DChart: &c, CatAx: catAx, ValAx: valAx, }, - "col3D": { + "col3DClustered": { Bar3DChart: &c, CatAx: catAx, ValAx: valAx, @@ -791,6 +1072,66 @@ func (f *File) drawBaseChart(formatSet *formatChart) *cPlotArea { CatAx: catAx, ValAx: valAx, }, + "col3DCone": { + Bar3DChart: &c, + CatAx: catAx, + ValAx: valAx, + }, + "col3DConeClustered": { + Bar3DChart: &c, + CatAx: catAx, + ValAx: valAx, + }, + "col3DConeStacked": { + Bar3DChart: &c, + CatAx: catAx, + ValAx: valAx, + }, + "col3DConePercentStacked": { + Bar3DChart: &c, + CatAx: catAx, + ValAx: valAx, + }, + "col3DPyramid": { + Bar3DChart: &c, + CatAx: catAx, + ValAx: valAx, + }, + "col3DPyramidClustered": { + Bar3DChart: &c, + CatAx: catAx, + ValAx: valAx, + }, + "col3DPyramidStacked": { + Bar3DChart: &c, + CatAx: catAx, + ValAx: valAx, + }, + "col3DPyramidPercentStacked": { + Bar3DChart: &c, + CatAx: catAx, + ValAx: valAx, + }, + "col3DCylinder": { + Bar3DChart: &c, + CatAx: catAx, + ValAx: valAx, + }, + "col3DCylinderClustered": { + Bar3DChart: &c, + CatAx: catAx, + ValAx: valAx, + }, + "col3DCylinderStacked": { + Bar3DChart: &c, + CatAx: catAx, + ValAx: valAx, + }, + "col3DCylinderPercentStacked": { + Bar3DChart: &c, + CatAx: catAx, + ValAx: valAx, + }, } return charts[formatSet.Type] } @@ -907,6 +1248,38 @@ func (f *File) drawScatterChart(formatSet *formatChart) *cPlotArea { } } +func (f *File) drawChartShape(formatSet *formatChart) *attrValString { + shapes := map[string]string{ + Bar3DConeClustered: "cone", + Bar3DConeStacked: "cone", + Bar3DConePercentStacked: "cone", + Bar3DPyramidClustered: "pyramid", + Bar3DPyramidStacked: "pyramid", + Bar3DPyramidPercentStacked: "pyramid", + Bar3DCylinderClustered: "cylinder", + Bar3DCylinderStacked: "cylinder", + Bar3DCylinderPercentStacked: "cylinder", + Col3DCone: "cone", + Col3DConeClustered: "cone", + Col3DConeStacked: "cone", + Col3DConePercentStacked: "cone", + Col3DPyramid: "pyramid", + Col3DPyramidClustered: "pyramid", + Col3DPyramidStacked: "pyramid", + Col3DPyramidPercentStacked: "pyramid", + Col3DCylinder: "cylinder", + Col3DCylinderClustered: "cylinder", + Col3DCylinderStacked: "cylinder", + Col3DCylinderPercentStacked: "cylinder", + } + if shape, ok := shapes[formatSet.Type]; ok { + return &attrValString{ + Val: shape, + } + } + return nil +} + // drawChartSeries provides a function to draw the c:ser element by given // format sets. func (f *File) drawChartSeries(formatSet *formatChart) *[]cSer { @@ -953,7 +1326,7 @@ func (f *File) drawChartSeriesSpPr(i int, formatSet *formatChart) *cSpPr { SchemeClr: &aSchemeClr{Val: "accent" + strconv.Itoa(i+1)}, } } - chartSeriesSpPr := map[string]*cSpPr{Area: nil, AreaStacked: nil, AreaPercentStacked: nil, Area3D: nil, Area3DStacked: nil, Area3DPercentStacked: nil, Bar: nil, BarStacked: nil, BarPercentStacked: nil, Bar3DClustered: nil, Bar3DStacked: nil, Bar3DPercentStacked: nil, Col: nil, ColStacked: nil, ColPercentStacked: nil, Col3DClustered: nil, Col3D: nil, Col3DStacked: nil, Col3DPercentStacked: nil, Doughnut: nil, Line: spPrLine, Pie: nil, Pie3D: nil, Radar: nil, Scatter: spPrScatter} + chartSeriesSpPr := map[string]*cSpPr{Line: spPrLine, Scatter: spPrScatter} return chartSeriesSpPr[formatSet.Type] } @@ -982,7 +1355,7 @@ func (f *File) drawChartSeriesDPt(i int, formatSet *formatChart) []*cDPt { }, }, }} - chartSeriesDPt := map[string][]*cDPt{Area: nil, AreaStacked: nil, AreaPercentStacked: nil, Area3D: nil, Area3DStacked: nil, Area3DPercentStacked: nil, Bar: nil, BarStacked: nil, BarPercentStacked: nil, Bar3DClustered: nil, Bar3DStacked: nil, Bar3DPercentStacked: nil, Col: nil, ColStacked: nil, ColPercentStacked: nil, Col3DClustered: nil, Col3D: nil, Col3DStacked: nil, Col3DPercentStacked: nil, Doughnut: nil, Line: nil, Pie: dpt, Pie3D: dpt, Radar: nil, Scatter: nil} + chartSeriesDPt := map[string][]*cDPt{Pie: dpt, Pie3D: dpt} return chartSeriesDPt[formatSet.Type] } @@ -994,8 +1367,11 @@ func (f *File) drawChartSeriesCat(v formatChartSeries, formatSet *formatChart) * F: v.Categories, }, } - chartSeriesCat := map[string]*cCat{Area: cat, AreaStacked: cat, AreaPercentStacked: cat, Area3D: cat, Area3DStacked: cat, Area3DPercentStacked: cat, Bar: cat, BarStacked: cat, BarPercentStacked: cat, Bar3DClustered: cat, Bar3DStacked: cat, Bar3DPercentStacked: cat, Col: cat, ColStacked: cat, ColPercentStacked: cat, Col3DClustered: cat, Col3D: cat, Col3DStacked: cat, Col3DPercentStacked: cat, Doughnut: cat, Line: cat, Pie: cat, Pie3D: cat, Radar: cat, Scatter: nil} - return chartSeriesCat[formatSet.Type] + chartSeriesCat := map[string]*cCat{Scatter: nil} + if _, ok := chartSeriesCat[formatSet.Type]; ok { + return nil + } + return cat } // drawChartSeriesVal provides a function to draw the c:val element by given @@ -1006,8 +1382,11 @@ func (f *File) drawChartSeriesVal(v formatChartSeries, formatSet *formatChart) * F: v.Values, }, } - chartSeriesVal := map[string]*cVal{Area: val, AreaStacked: val, AreaPercentStacked: val, Area3D: val, Area3DStacked: val, Area3DPercentStacked: val, Bar: val, BarStacked: val, BarPercentStacked: val, Bar3DClustered: val, Bar3DStacked: val, Bar3DPercentStacked: val, Col: val, ColStacked: val, ColPercentStacked: val, Col3DClustered: val, Col3D: val, Col3DStacked: val, Col3DPercentStacked: val, Doughnut: val, Line: val, Pie: val, Pie3D: val, Radar: val, Scatter: nil} - return chartSeriesVal[formatSet.Type] + chartSeriesVal := map[string]*cVal{Scatter: nil} + if _, ok := chartSeriesVal[formatSet.Type]; ok { + return nil + } + return val } // drawChartSeriesMarker provides a function to draw the c:marker element by @@ -1034,7 +1413,7 @@ func (f *File) drawChartSeriesMarker(i int, formatSet *formatChart) *cMarker { }, } } - chartSeriesMarker := map[string]*cMarker{Area: nil, AreaStacked: nil, AreaPercentStacked: nil, Area3D: nil, Area3DStacked: nil, Area3DPercentStacked: nil, Bar: nil, BarStacked: nil, BarPercentStacked: nil, Bar3DClustered: nil, Bar3DStacked: nil, Bar3DPercentStacked: nil, Col: nil, ColStacked: nil, ColPercentStacked: nil, Col3DClustered: nil, Col3D: nil, Col3DStacked: nil, Col3DPercentStacked: nil, Doughnut: nil, Line: nil, Pie: nil, Pie3D: nil, Radar: nil, Scatter: marker} + chartSeriesMarker := map[string]*cMarker{Scatter: marker} return chartSeriesMarker[formatSet.Type] } @@ -1046,7 +1425,7 @@ func (f *File) drawChartSeriesXVal(v formatChartSeries, formatSet *formatChart) F: v.Categories, }, } - chartSeriesXVal := map[string]*cCat{Area: nil, AreaStacked: nil, AreaPercentStacked: nil, Area3D: nil, Area3DStacked: nil, Area3DPercentStacked: nil, Bar: nil, BarStacked: nil, BarPercentStacked: nil, Bar3DClustered: nil, Bar3DStacked: nil, Bar3DPercentStacked: nil, Col: nil, ColStacked: nil, ColPercentStacked: nil, Col3DClustered: nil, Col3D: nil, Col3DStacked: nil, Col3DPercentStacked: nil, Doughnut: nil, Line: nil, Pie: nil, Pie3D: nil, Radar: nil, Scatter: cat} + chartSeriesXVal := map[string]*cCat{Scatter: cat} return chartSeriesXVal[formatSet.Type] } @@ -1058,7 +1437,7 @@ func (f *File) drawChartSeriesYVal(v formatChartSeries, formatSet *formatChart) F: v.Values, }, } - chartSeriesYVal := map[string]*cVal{Area: nil, AreaStacked: nil, AreaPercentStacked: nil, Area3D: nil, Area3DStacked: nil, Area3DPercentStacked: nil, Bar: nil, BarStacked: nil, BarPercentStacked: nil, Bar3DClustered: nil, Bar3DStacked: nil, Bar3DPercentStacked: nil, Col: nil, ColStacked: nil, ColPercentStacked: nil, Col3DClustered: nil, Col3D: nil, Col3DStacked: nil, Col3DPercentStacked: nil, Doughnut: nil, Line: nil, Pie: nil, Pie3D: nil, Radar: nil, Scatter: val} + chartSeriesYVal := map[string]*cVal{Scatter: val} return chartSeriesYVal[formatSet.Type] } @@ -1080,8 +1459,11 @@ 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{Area: dLbls, AreaStacked: dLbls, AreaPercentStacked: dLbls, Area3D: dLbls, Area3DStacked: dLbls, Area3DPercentStacked: dLbls, Bar: dLbls, BarStacked: dLbls, BarPercentStacked: dLbls, Bar3DClustered: dLbls, Bar3DStacked: dLbls, Bar3DPercentStacked: dLbls, Col: dLbls, ColStacked: dLbls, ColPercentStacked: dLbls, Col3DClustered: dLbls, Col3D: dLbls, Col3DStacked: dLbls, Col3DPercentStacked: dLbls, Doughnut: dLbls, Line: dLbls, Pie: dLbls, Pie3D: dLbls, Radar: dLbls, Scatter: nil} - return chartSeriesDLbls[formatSet.Type] + chartSeriesDLbls := map[string]*cDLbls{Scatter: nil} + if _, ok := chartSeriesDLbls[formatSet.Type]; ok { + return nil + } + return dLbls } // drawPlotAreaCatAx provides a function to draw the c:catAx element. -- cgit v1.2.1 From 5cf1c05ed48ad92b6c58d3dfe7d3598526b77b01 Mon Sep 17 00:00:00 2001 From: xuri Date: Sat, 15 Jun 2019 20:55:56 +0800 Subject: Add surface 3D, wireframe Surface 3D, contour, and wireframe contour chart support --- chart.go | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 133 insertions(+), 6 deletions(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index 8ecd8c7..c0060c9 100644 --- a/chart.go +++ b/chart.go @@ -65,6 +65,10 @@ const ( Pie3D = "pie3D" Radar = "radar" Scatter = "scatter" + Surface3D = "surface3D" + WireframeSurface3D = "wireframeSurface3D" + Contour = "contour" + WireframeContour = "wireframeContour" ) // This section defines the default value of chart properties. @@ -116,6 +120,10 @@ var ( Pie3D: 30, Radar: 0, Scatter: 0, + Surface3D: 15, + WireframeSurface3D: 15, + Contour: 90, + WireframeContour: 90, } chartView3DRotY = map[string]int{ Area: 0, @@ -164,6 +172,10 @@ var ( Pie3D: 0, Radar: 0, Scatter: 0, + Surface3D: 20, + WireframeSurface3D: 20, + Contour: 0, + WireframeContour: 0, } chartView3DDepthPercent = map[string]int{ Area: 100, @@ -212,6 +224,14 @@ var ( Pie3D: 100, Radar: 100, Scatter: 100, + Surface3D: 100, + WireframeSurface3D: 100, + Contour: 100, + WireframeContour: 100, + } + chartView3DPerspective = map[string]int{ + Contour: 0, + WireframeContour: 0, } chartView3DRAngAx = map[string]int{ Area: 0, @@ -260,6 +280,9 @@ var ( Pie3D: 0, Radar: 0, Scatter: 0, + Surface3D: 0, + WireframeSurface3D: 0, + Contour: 0, } chartLegendPosition = map[string]string{ "bottom": "b", @@ -315,6 +338,10 @@ var ( Pie3D: "General", Radar: "General", Scatter: "General", + Surface3D: "General", + WireframeSurface3D: "General", + Contour: "General", + WireframeContour: "General", } chartValAxCrossBetween = map[string]string{ Area: "midCat", @@ -363,6 +390,10 @@ var ( Pie3D: "between", Radar: "between", Scatter: "between", + Surface3D: "midCat", + WireframeSurface3D: "midCat", + Contour: "midCat", + WireframeContour: "midCat", } plotAreaChartGrouping = map[string]string{ Area: "standard", @@ -456,6 +487,10 @@ var ( true: "r", false: "l", } + valTickLblPos = map[string]string{ + Contour: "none", + WireframeContour: "none", + } ) // parseFormatChartSet provides a function to parse the format settings of the @@ -573,6 +608,10 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // pie3D | 3D pie chart // radar | radar chart // scatter | scatter chart +// surface3D | 3D surface chart +// wireframeSurface3D | 3D wireframe surface chart +// contour | contour chart +// wireframeContour | wireframe contour // // In Excel a chart series is a collection of information that defines which data is plotted such as values, axis labels and formatting. // @@ -791,6 +830,7 @@ func (f *File) addChart(formatSet *formatChart) { RotX: &attrValInt{Val: chartView3DRotX[formatSet.Type]}, RotY: &attrValInt{Val: chartView3DRotY[formatSet.Type]}, DepthPercent: &attrValInt{Val: chartView3DDepthPercent[formatSet.Type]}, + Perspective: &attrValInt{Val: chartView3DPerspective[formatSet.Type]}, RAngAx: &attrValInt{Val: chartView3DRAngAx[formatSet.Type]}, }, Floor: &cThicknessSpPr{ @@ -891,6 +931,10 @@ func (f *File) addChart(formatSet *formatChart) { Pie: f.drawPieChart, Radar: f.drawRadarChart, Scatter: f.drawScatterChart, + Surface3D: f.drawSurface3DChart, + WireframeSurface3D: f.drawSurface3DChart, + Contour: f.drawSurfaceChart, + WireframeContour: f.drawSurfaceChart, } xlsxChartSpace.Chart.PlotArea = plotAreaFunc[formatSet.Type](formatSet) @@ -1248,6 +1292,52 @@ func (f *File) drawScatterChart(formatSet *formatChart) *cPlotArea { } } +// drawSurface3DChart provides a function to draw the c:surface3DChart element by +// given format sets. +func (f *File) drawSurface3DChart(formatSet *formatChart) *cPlotArea { + plotArea := &cPlotArea{ + Surface3DChart: &cCharts{ + Ser: f.drawChartSeries(formatSet), + AxID: []*attrValInt{ + {Val: 754001152}, + {Val: 753999904}, + {Val: 832256642}, + }, + }, + CatAx: f.drawPlotAreaCatAx(formatSet), + ValAx: f.drawPlotAreaValAx(formatSet), + SerAx: f.drawPlotAreaSerAx(formatSet), + } + if formatSet.Type == WireframeSurface3D { + plotArea.Surface3DChart.Wireframe = &attrValBool{Val: true} + } + return plotArea +} + +// drawSurfaceChart provides a function to draw the c:surfaceChart element by +// given format sets. +func (f *File) drawSurfaceChart(formatSet *formatChart) *cPlotArea { + plotArea := &cPlotArea{ + SurfaceChart: &cCharts{ + Ser: f.drawChartSeries(formatSet), + AxID: []*attrValInt{ + {Val: 754001152}, + {Val: 753999904}, + {Val: 832256642}, + }, + }, + CatAx: f.drawPlotAreaCatAx(formatSet), + ValAx: f.drawPlotAreaValAx(formatSet), + SerAx: f.drawPlotAreaSerAx(formatSet), + } + if formatSet.Type == WireframeContour { + plotArea.SurfaceChart.Wireframe = &attrValBool{Val: true} + } + return plotArea +} + +// drawChartShape provides a function to draw the c:shape element by given +// format sets. func (f *File) drawChartShape(formatSet *formatChart) *attrValString { shapes := map[string]string{ Bar3DConeClustered: "cone", @@ -1273,9 +1363,7 @@ func (f *File) drawChartShape(formatSet *formatChart) *attrValString { Col3DCylinderPercentStacked: "cylinder", } if shape, ok := shapes[formatSet.Type]; ok { - return &attrValString{ - Val: shape, - } + return &attrValString{Val: shape} } return nil } @@ -1459,7 +1547,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} + chartSeriesDLbls := map[string]*cDLbls{Scatter: nil, Surface3D: nil, WireframeSurface3D: nil, Contour: nil, WireframeContour: nil} if _, ok := chartSeriesDLbls[formatSet.Type]; ok { return nil } @@ -1476,7 +1564,7 @@ func (f *File) drawPlotAreaCatAx(formatSet *formatChart) []*cAxs { if formatSet.XAxis.Maximum == 0 { max = nil } - return []*cAxs{ + axs := []*cAxs{ { AxID: &attrValInt{Val: 754001152}, Scaling: &cScaling{ @@ -1503,6 +1591,10 @@ func (f *File) drawPlotAreaCatAx(formatSet *formatChart) []*cAxs { NoMultiLvlLbl: &attrValBool{Val: false}, }, } + if formatSet.XAxis.MajorGridlines { + axs[0].MajorGridlines = &cChartLines{SpPr: f.drawPlotAreaSpPr()} + } + return axs } // drawPlotAreaValAx provides a function to draw the c:valAx element. @@ -1515,7 +1607,7 @@ func (f *File) drawPlotAreaValAx(formatSet *formatChart) []*cAxs { if formatSet.YAxis.Maximum == 0 { max = nil } - return []*cAxs{ + axs := []*cAxs{ { AxID: &attrValInt{Val: 753999904}, Scaling: &cScaling{ @@ -1539,6 +1631,41 @@ func (f *File) drawPlotAreaValAx(formatSet *formatChart) []*cAxs { CrossBetween: &attrValString{Val: chartValAxCrossBetween[formatSet.Type]}, }, } + if formatSet.YAxis.MajorGridlines { + axs[0].MajorGridlines = &cChartLines{SpPr: f.drawPlotAreaSpPr()} + } + if pos, ok := valTickLblPos[formatSet.Type]; ok { + axs[0].TickLblPos.Val = pos + } + return axs +} + +// drawPlotAreaSerAx provides a function to draw the c:serAx element. +func (f *File) drawPlotAreaSerAx(formatSet *formatChart) []*cAxs { + min := &attrValFloat{Val: formatSet.YAxis.Minimum} + max := &attrValFloat{Val: formatSet.YAxis.Maximum} + if formatSet.YAxis.Minimum == 0 { + min = nil + } + if formatSet.YAxis.Maximum == 0 { + max = nil + } + return []*cAxs{ + { + AxID: &attrValInt{Val: 832256642}, + Scaling: &cScaling{ + Orientation: &attrValString{Val: orientation[formatSet.YAxis.ReverseOrder]}, + Max: max, + Min: min, + }, + Delete: &attrValBool{Val: false}, + AxPos: &attrValString{Val: catAxPos[formatSet.XAxis.ReverseOrder]}, + TickLblPos: &attrValString{Val: "nextTo"}, + SpPr: f.drawPlotAreaSpPr(), + TxPr: f.drawPlotAreaTxPr(), + CrossAx: &attrValInt{Val: 753999904}, + }, + } } // drawPlotAreaSpPr provides a function to draw the c:spPr element. -- cgit v1.2.1 From e77c462d3f1c29b009186d42832e6d5f42ac069f Mon Sep 17 00:00:00 2001 From: xuri Date: Wed, 19 Jun 2019 00:01:18 +0800 Subject: Support to create bubble and 3D bubble chart --- chart.go | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 64 insertions(+), 15 deletions(-) (limited to 'chart.go') 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 } -- cgit v1.2.1 From 9c70d0ac868f66badf2663cc7b4b3c46d5411131 Mon Sep 17 00:00:00 2001 From: xuri Date: Sun, 11 Aug 2019 00:36:14 +0800 Subject: Documentation updated, Go 1.10+ required --- chart.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index b9439ca..6a106f0 100644 --- a/chart.go +++ b/chart.go @@ -5,7 +5,7 @@ // Package excelize providing a set of functions that allow you to write to // and read from XLSX files. Support reads and writes XLSX file generated by // Microsoft Excelâ„¢ 2007 and later. Support save file without losing original -// charts of XLSX. This library needs Go version 1.8 or later. +// charts of XLSX. This library needs Go version 1.10 or later. package excelize -- cgit v1.2.1 From 0acb3ef9685e80d51dfda5ab9a9db870af7e1614 Mon Sep 17 00:00:00 2001 From: xuri Date: Mon, 2 Sep 2019 21:52:55 +0800 Subject: Testing files updated --- chart.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index 6a106f0..e1eb81f 100644 --- a/chart.go +++ b/chart.go @@ -543,7 +543,7 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // import ( // "fmt" // -// "github.com/360EntSecGroup-Skylar/excelize/v2" +// "github.com/360EntSecGroup-Skylar/excelize" // ) // // func main() { -- cgit v1.2.1 From 8922f659788187afa6d0a5d3248e999c2c1bb846 Mon Sep 17 00:00:00 2001 From: xuri Date: Mon, 16 Sep 2019 01:17:35 +0800 Subject: Combine functions: workBookRelsWriter, drawingRelsWriter into relsWriter; drawingRelsReader, workbookRelsReader, workSheetRelsReader into relsReader; addDrawingRelationships, addSheetRelationships into addRels --- chart.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index e1eb81f..db2df1e 100644 --- a/chart.go +++ b/chart.go @@ -727,7 +727,8 @@ func (f *File) AddChart(sheet, cell, format string) error { chartID := f.countCharts() + 1 drawingXML := "xl/drawings/drawing" + strconv.Itoa(drawingID) + ".xml" drawingID, drawingXML = f.prepareDrawing(xlsx, drawingID, sheet, drawingXML) - drawingRID := f.addDrawingRelationships(drawingID, SourceRelationshipChart, "../charts/chart"+strconv.Itoa(chartID)+".xml", "") + drawingRels := "xl/drawings/_rels/drawing" + strconv.Itoa(drawingID) + ".xml.rels" + drawingRID := f.addRels(drawingRels, SourceRelationshipChart, "../charts/chart"+strconv.Itoa(chartID)+".xml", "") err = f.addDrawingChart(sheet, drawingXML, cell, formatSet.Dimension.Width, formatSet.Dimension.Height, drawingRID, &formatSet.Format) if err != nil { return err @@ -761,7 +762,9 @@ func (f *File) prepareDrawing(xlsx *xlsxWorksheet, drawingID int, sheet, drawing drawingXML = strings.Replace(sheetRelationshipsDrawingXML, "..", "xl", -1) } else { // Add first picture for given sheet. - rID := f.addSheetRelationships(sheet, SourceRelationshipDrawingML, sheetRelationshipsDrawingXML, "") + sheetPath, _ := f.sheetMap[trimSheetName(sheet)] + sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(sheetPath, "xl/worksheets/") + ".rels" + rID := f.addRels(sheetRels, SourceRelationshipDrawingML, sheetRelationshipsDrawingXML, "") f.addSheetDrawing(sheet, rID) } return drawingID, drawingXML -- cgit v1.2.1 From a34d3b8c86d67d3ad0bc0dbedb69d3b4ebbc210f Mon Sep 17 00:00:00 2001 From: xuri Date: Tue, 24 Sep 2019 21:53:19 +0800 Subject: Compatibility improvement --- chart.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index db2df1e..7db7eee 100644 --- a/chart.go +++ b/chart.go @@ -1845,7 +1845,7 @@ func (f *File) addDrawingChart(sheet, drawingXML, cell string, width, height, rI graphicFrame := xlsxGraphicFrame{ NvGraphicFramePr: xlsxNvGraphicFramePr{ CNvPr: &xlsxCNvPr{ - ID: f.countCharts() + f.countMedia() + 1, + ID: len(content.OneCellAnchor) + len(content.TwoCellAnchor) + 2, Name: "Chart " + strconv.Itoa(cNvPrID), }, }, -- cgit v1.2.1 From eb520ae27757d4bca276fa2894bf461d75df9b37 Mon Sep 17 00:00:00 2001 From: xuri Date: Thu, 26 Sep 2019 22:28:14 +0800 Subject: Improve compatibility for charts --- chart.go | 83 +++++++++++++--------------------------------------------------- 1 file changed, 17 insertions(+), 66 deletions(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index 7db7eee..7d40405 100644 --- a/chart.go +++ b/chart.go @@ -179,59 +179,11 @@ var ( Contour: 0, WireframeContour: 0, } - chartView3DDepthPercent = map[string]int{ - Area: 100, - AreaStacked: 100, - AreaPercentStacked: 100, - Area3D: 100, - Area3DStacked: 100, - Area3DPercentStacked: 100, - Bar: 100, - BarStacked: 100, - BarPercentStacked: 100, - Bar3DClustered: 100, - Bar3DStacked: 100, - Bar3DPercentStacked: 100, - Bar3DConeClustered: 100, - Bar3DConeStacked: 100, - Bar3DConePercentStacked: 100, - Bar3DPyramidClustered: 100, - Bar3DPyramidStacked: 100, - Bar3DPyramidPercentStacked: 100, - Bar3DCylinderClustered: 100, - Bar3DCylinderStacked: 100, - Bar3DCylinderPercentStacked: 100, - Col: 100, - ColStacked: 100, - ColPercentStacked: 100, - Col3D: 100, - Col3DClustered: 100, - Col3DStacked: 100, - Col3DPercentStacked: 100, - Col3DCone: 100, - Col3DConeClustered: 100, - Col3DConeStacked: 100, - Col3DConePercentStacked: 100, - Col3DPyramid: 100, - Col3DPyramidClustered: 100, - Col3DPyramidStacked: 100, - Col3DPyramidPercentStacked: 100, - Col3DCylinder: 100, - Col3DCylinderClustered: 100, - Col3DCylinderStacked: 100, - Col3DCylinderPercentStacked: 100, - Doughnut: 100, - Line: 100, - Pie: 100, - Pie3D: 100, - Radar: 100, - Scatter: 100, - Surface3D: 100, - WireframeSurface3D: 100, - Contour: 100, - WireframeContour: 100, - Bubble: 100, - Bubble3D: 100, + plotAreaChartOverlap = map[string]int{ + BarStacked: 100, + BarPercentStacked: 100, + ColStacked: 100, + ColPercentStacked: 100, } chartView3DPerspective = map[string]int{ Contour: 0, @@ -842,11 +794,10 @@ func (f *File) addChart(formatSet *formatChart) { }, }, View3D: &cView3D{ - RotX: &attrValInt{Val: chartView3DRotX[formatSet.Type]}, - RotY: &attrValInt{Val: chartView3DRotY[formatSet.Type]}, - DepthPercent: &attrValInt{Val: chartView3DDepthPercent[formatSet.Type]}, - Perspective: &attrValInt{Val: chartView3DPerspective[formatSet.Type]}, - RAngAx: &attrValInt{Val: chartView3DRAngAx[formatSet.Type]}, + RotX: &attrValInt{Val: chartView3DRotX[formatSet.Type]}, + RotY: &attrValInt{Val: chartView3DRotY[formatSet.Type]}, + Perspective: &attrValInt{Val: chartView3DPerspective[formatSet.Type]}, + RAngAx: &attrValInt{Val: chartView3DRAngAx[formatSet.Type]}, }, Floor: &cThicknessSpPr{ Thickness: &attrValInt{Val: 0}, @@ -980,6 +931,7 @@ func (f *File) drawBaseChart(formatSet *formatChart) *cPlotArea { {Val: 754001152}, {Val: 753999904}, }, + Overlap: &attrValInt{Val: 100}, } var ok bool if c.BarDir.Val, ok = plotAreaChartBarDir[formatSet.Type]; !ok { @@ -988,8 +940,8 @@ func (f *File) drawBaseChart(formatSet *formatChart) *cPlotArea { if c.Grouping.Val, ok = plotAreaChartGrouping[formatSet.Type]; !ok { c.Grouping = nil } - if strings.HasSuffix(formatSet.Type, "Stacked") { - c.Overlap = &attrValInt{Val: 100} + if c.Overlap.Val, ok = plotAreaChartOverlap[formatSet.Type]; !ok { + c.Overlap = nil } catAx := f.drawPlotAreaCatAx(formatSet) valAx := f.drawPlotAreaValAx(formatSet) @@ -1485,7 +1437,7 @@ func (f *File) drawChartSeriesCat(v formatChartSeries, formatSet *formatChart) * F: v.Categories, }, } - chartSeriesCat := map[string]*cCat{Scatter: nil} + chartSeriesCat := map[string]*cCat{Scatter: nil, Bubble: nil, Bubble3D: nil} if _, ok := chartSeriesCat[formatSet.Type]; ok { return nil } @@ -1500,7 +1452,7 @@ func (f *File) drawChartSeriesVal(v formatChartSeries, formatSet *formatChart) * F: v.Values, }, } - chartSeriesVal := map[string]*cVal{Scatter: nil} + chartSeriesVal := map[string]*cVal{Scatter: nil, Bubble: nil, Bubble3D: nil} if _, ok := chartSeriesVal[formatSet.Type]; ok { return nil } @@ -1783,7 +1735,6 @@ func (f *File) drawPlotAreaTxPr() *cTxPr { // deserialization, two different structures: decodeWsDr and encodeWsDr are // defined. func (f *File) drawingParser(path string) (*xlsxWsDr, int) { - cNvPrID := 1 if f.Drawings[path] == nil { content := xlsxWsDr{} content.A = NameSpaceDrawingML @@ -1793,7 +1744,6 @@ func (f *File) drawingParser(path string) (*xlsxWsDr, int) { decodeWsDr := decodeWsDr{} _ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML(path)), &decodeWsDr) content.R = decodeWsDr.R - cNvPrID = len(decodeWsDr.OneCellAnchor) + len(decodeWsDr.TwoCellAnchor) + 1 for _, v := range decodeWsDr.OneCellAnchor { content.OneCellAnchor = append(content.OneCellAnchor, &xdrCellAnchor{ EditAs: v.EditAs, @@ -1809,7 +1759,8 @@ func (f *File) drawingParser(path string) (*xlsxWsDr, int) { } f.Drawings[path] = &content } - return f.Drawings[path], cNvPrID + wsDr := f.Drawings[path] + return wsDr, len(wsDr.OneCellAnchor) + len(wsDr.TwoCellAnchor) + 2 } // addDrawingChart provides a function to add chart graphic frame by given @@ -1845,7 +1796,7 @@ func (f *File) addDrawingChart(sheet, drawingXML, cell string, width, height, rI graphicFrame := xlsxGraphicFrame{ NvGraphicFramePr: xlsxNvGraphicFramePr{ CNvPr: &xlsxCNvPr{ - ID: len(content.OneCellAnchor) + len(content.TwoCellAnchor) + 2, + ID: cNvPrID, Name: "Chart " + strconv.Itoa(cNvPrID), }, }, -- cgit v1.2.1 From 7716968abc1d330492e311504af8951c34fb7520 Mon Sep 17 00:00:00 2001 From: xuri Date: Mon, 21 Oct 2019 00:04:18 +0800 Subject: Fix #505, support set line width of the line chart --- chart.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index 7d40405..289903e 100644 --- a/chart.go +++ b/chart.go @@ -584,6 +584,7 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // name // categories // values +// line // // name: Set the name for the series. The name is displayed in the chart legend and in the formula bar. The name property is optional and if it isn't supplied it will default to Series 1..n. The name can also be a formula such as Sheet1!$A$1 // @@ -591,6 +592,8 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // // values: This is the most important property of a series and is the only mandatory option for every chart object. This option links the chart with the worksheet data that it displays. // +// 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 can be set is width. The range of width is 0.25pt - 999pt. If the value of width is outside the range, the default width of the line is 2pt. +// // Set properties of the chart legend. The options that can be set are: // // position @@ -1387,7 +1390,7 @@ func (f *File) drawChartSeriesSpPr(i int, formatSet *formatChart) *cSpPr { } spPrLine := &cSpPr{ Ln: &aLn{ - W: 25400, + W: f.ptToEMUs(formatSet.Series[i].Line.Width), Cap: "rnd", // rnd, sq, flat }, } @@ -1438,7 +1441,7 @@ func (f *File) drawChartSeriesCat(v formatChartSeries, formatSet *formatChart) * }, } chartSeriesCat := map[string]*cCat{Scatter: nil, Bubble: nil, Bubble3D: nil} - if _, ok := chartSeriesCat[formatSet.Type]; ok { + if _, ok := chartSeriesCat[formatSet.Type]; ok || v.Categories == "" { return nil } return cat @@ -1821,3 +1824,13 @@ func (f *File) addDrawingChart(sheet, drawingXML, cell string, width, height, rI f.Drawings[drawingXML] = content return err } + +// ptToEMUs provides a function to convert pt to EMUs, 1 pt = 12700 EMUs. The +// range of pt is 0.25pt - 999pt. If the value of pt is outside the range, the +// default EMUs will be returned. +func (f *File) ptToEMUs(pt float64) int { + if 0.25 > pt || pt > 999 { + return 25400 + } + return int(12700 * pt) +} -- cgit v1.2.1 From 6abf8bf9723512086f009ca574bde1d6682fc83d Mon Sep 17 00:00:00 2001 From: xuri Date: Sun, 27 Oct 2019 14:16:02 +0800 Subject: Resolve #501, support set minor grid lines for the chart --- chart.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'chart.go') diff --git a/chart.go b/chart.go index 289903e..bbd71d6 100644 --- a/chart.go +++ b/chart.go @@ -652,10 +652,16 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // // Set the primary horizontal and vertical axis options by x_axis and y_axis. The properties that can be set are: // +// major_grid_lines +// minor_grid_lines // reverse_order // maximum // minimum // +// major_grid_lines: Specifies major gridlines. +// +// minor_grid_lines: Specifies minor gridlines. +// // reverse_order: Specifies that the categories or values on reverse order (orientation of the chart). The reverse_order property is optional. The default value is false. // // maximum: Specifies that the fixed maximum, 0 is auto. The maximum property is optional. The default value is auto. @@ -1601,6 +1607,9 @@ func (f *File) drawPlotAreaCatAx(formatSet *formatChart) []*cAxs { if formatSet.XAxis.MajorGridlines { axs[0].MajorGridlines = &cChartLines{SpPr: f.drawPlotAreaSpPr()} } + if formatSet.XAxis.MinorGridlines { + axs[0].MinorGridlines = &cChartLines{SpPr: f.drawPlotAreaSpPr()} + } return axs } @@ -1641,6 +1650,9 @@ func (f *File) drawPlotAreaValAx(formatSet *formatChart) []*cAxs { if formatSet.YAxis.MajorGridlines { axs[0].MajorGridlines = &cChartLines{SpPr: f.drawPlotAreaSpPr()} } + if formatSet.YAxis.MinorGridlines { + axs[0].MinorGridlines = &cChartLines{SpPr: f.drawPlotAreaSpPr()} + } if pos, ok := valTickLblPos[formatSet.Type]; ok { axs[0].TickLblPos.Val = pos } -- cgit v1.2.1 From b1b3c0d15158abc71267da5893de020f047c3872 Mon Sep 17 00:00:00 2001 From: Alex Geer Date: Thu, 19 Dec 2019 19:30:48 +0300 Subject: =?UTF-8?q?Fix=20#539=20Fixed=20error=20opening=20excel=20file=20c?= =?UTF-8?q?reated=20in=20encoding=20d=E2=80=A6=20(#540)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fixed issue #539 Fixed error opening excel file created in encoding different from UTF-8, added logging of possible errors when decoding XML if the function does not provide exit with an error * Added test for CharsetReader * Fixed #discussion_r359397878 Discussion: https://github.com/360EntSecGroup-Skylar/excelize/pull/540#discussion_r359397878 * Fixed go fmt * go mod tidy and removed unused imports * The code has been refactored --- chart.go | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index 7d40405..aaa7cd6 100644 --- a/chart.go +++ b/chart.go @@ -10,9 +10,12 @@ package excelize import ( + "bytes" "encoding/json" "encoding/xml" "errors" + "io" + "log" "strconv" "strings" ) @@ -1735,14 +1738,21 @@ func (f *File) drawPlotAreaTxPr() *cTxPr { // deserialization, two different structures: decodeWsDr and encodeWsDr are // defined. func (f *File) drawingParser(path string) (*xlsxWsDr, int) { + var ( + err error + ok bool + ) + if f.Drawings[path] == nil { content := xlsxWsDr{} content.A = NameSpaceDrawingML content.Xdr = NameSpaceDrawingMLSpreadSheet - _, ok := f.XLSX[path] - if ok { // Append Model + if _, ok = f.XLSX[path]; ok { // Append Model decodeWsDr := decodeWsDr{} - _ = xml.Unmarshal(namespaceStrictToTransitional(f.readXML(path)), &decodeWsDr) + if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(path)))). + Decode(&decodeWsDr); err != nil && err != io.EOF { + log.Printf("xml decode error: %s", err) + } content.R = decodeWsDr.R for _, v := range decodeWsDr.OneCellAnchor { content.OneCellAnchor = append(content.OneCellAnchor, &xdrCellAnchor{ -- cgit v1.2.1 From 4e4a5b9b3e052d1694442515492792fb1aa74c5a Mon Sep 17 00:00:00 2001 From: xuri Date: Mon, 23 Dec 2019 00:07:40 +0800 Subject: Improve compatibility, fix workbook's rels ID calc error --- chart.go | 219 +++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 109 insertions(+), 110 deletions(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index bf8155a..5a42c5b 100644 --- a/chart.go +++ b/chart.go @@ -726,8 +726,7 @@ func (f *File) prepareDrawing(xlsx *xlsxWorksheet, drawingID int, sheet, drawing drawingXML = strings.Replace(sheetRelationshipsDrawingXML, "..", "xl", -1) } else { // Add first picture for given sheet. - sheetPath, _ := f.sheetMap[trimSheetName(sheet)] - sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(sheetPath, "xl/worksheets/") + ".rels" + sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(f.sheetMap[trimSheetName(sheet)], "xl/worksheets/") + ".rels" rID := f.addRels(sheetRels, SourceRelationshipDrawingML, sheetRelationshipsDrawingXML, "") f.addSheetDrawing(sheet, rID) } @@ -743,9 +742,9 @@ func (f *File) addChart(formatSet *formatChart) { XMLNSa: NameSpaceDrawingML, XMLNSr: SourceRelationship, XMLNSc16r2: SourceRelationshipChart201506, - Date1904: &attrValBool{Val: false}, - Lang: &attrValString{Val: "en-US"}, - RoundedCorners: &attrValBool{Val: false}, + Date1904: &attrValBool{Val: boolPtr(false)}, + Lang: &attrValString{Val: stringPtr("en-US")}, + RoundedCorners: &attrValBool{Val: boolPtr(false)}, Chart: cChart{ Title: &cTitle{ Tx: cTx{ @@ -761,10 +760,10 @@ func (f *File) addChart(formatSet *formatChart) { SchemeClr: &aSchemeClr{ Val: "tx1", LumMod: &attrValInt{ - Val: 65000, + Val: intPtr(65000), }, LumOff: &attrValInt{ - Val: 35000, + Val: intPtr(35000), }, }, }, @@ -806,29 +805,29 @@ func (f *File) addChart(formatSet *formatChart) { }, }, View3D: &cView3D{ - RotX: &attrValInt{Val: chartView3DRotX[formatSet.Type]}, - RotY: &attrValInt{Val: chartView3DRotY[formatSet.Type]}, - Perspective: &attrValInt{Val: chartView3DPerspective[formatSet.Type]}, - RAngAx: &attrValInt{Val: chartView3DRAngAx[formatSet.Type]}, + RotX: &attrValInt{Val: intPtr(chartView3DRotX[formatSet.Type])}, + RotY: &attrValInt{Val: intPtr(chartView3DRotY[formatSet.Type])}, + Perspective: &attrValInt{Val: intPtr(chartView3DPerspective[formatSet.Type])}, + RAngAx: &attrValInt{Val: intPtr(chartView3DRAngAx[formatSet.Type])}, }, Floor: &cThicknessSpPr{ - Thickness: &attrValInt{Val: 0}, + Thickness: &attrValInt{Val: intPtr(0)}, }, SideWall: &cThicknessSpPr{ - Thickness: &attrValInt{Val: 0}, + Thickness: &attrValInt{Val: intPtr(0)}, }, BackWall: &cThicknessSpPr{ - Thickness: &attrValInt{Val: 0}, + Thickness: &attrValInt{Val: intPtr(0)}, }, PlotArea: &cPlotArea{}, Legend: &cLegend{ - LegendPos: &attrValString{Val: chartLegendPosition[formatSet.Legend.Position]}, - Overlay: &attrValBool{Val: false}, + LegendPos: &attrValString{Val: stringPtr(chartLegendPosition[formatSet.Legend.Position])}, + Overlay: &attrValBool{Val: boolPtr(false)}, }, - PlotVisOnly: &attrValBool{Val: false}, - DispBlanksAs: &attrValString{Val: formatSet.ShowBlanksAs}, - ShowDLblsOverMax: &attrValBool{Val: false}, + PlotVisOnly: &attrValBool{Val: boolPtr(false)}, + DispBlanksAs: &attrValString{Val: stringPtr(formatSet.ShowBlanksAs)}, + ShowDLblsOverMax: &attrValBool{Val: boolPtr(false)}, }, SpPr: &cSpPr{ SolidFill: &aSolidFill{ @@ -842,10 +841,10 @@ func (f *File) addChart(formatSet *formatChart) { SolidFill: &aSolidFill{ SchemeClr: &aSchemeClr{Val: "tx1", LumMod: &attrValInt{ - Val: 15000, + Val: intPtr(15000), }, LumOff: &attrValInt{ - Val: 85000, + Val: intPtr(85000), }, }, }, @@ -928,31 +927,31 @@ func (f *File) addChart(formatSet *formatChart) { func (f *File) drawBaseChart(formatSet *formatChart) *cPlotArea { c := cCharts{ BarDir: &attrValString{ - Val: "col", + Val: stringPtr("col"), }, Grouping: &attrValString{ - Val: "clustered", + Val: stringPtr("clustered"), }, VaryColors: &attrValBool{ - Val: true, + Val: boolPtr(true), }, Ser: f.drawChartSeries(formatSet), Shape: f.drawChartShape(formatSet), DLbls: f.drawChartDLbls(formatSet), AxID: []*attrValInt{ - {Val: 754001152}, - {Val: 753999904}, + {Val: intPtr(754001152)}, + {Val: intPtr(753999904)}, }, - Overlap: &attrValInt{Val: 100}, + Overlap: &attrValInt{Val: intPtr(100)}, } var ok bool - if c.BarDir.Val, ok = plotAreaChartBarDir[formatSet.Type]; !ok { + if *c.BarDir.Val, ok = plotAreaChartBarDir[formatSet.Type]; !ok { c.BarDir = nil } - if c.Grouping.Val, ok = plotAreaChartGrouping[formatSet.Type]; !ok { + if *c.Grouping.Val, ok = plotAreaChartGrouping[formatSet.Type]; !ok { c.Grouping = nil } - if c.Overlap.Val, ok = plotAreaChartOverlap[formatSet.Type]; !ok { + if *c.Overlap.Val, ok = plotAreaChartOverlap[formatSet.Type]; !ok { c.Overlap = nil } catAx := f.drawPlotAreaCatAx(formatSet) @@ -1178,10 +1177,10 @@ func (f *File) drawDoughnutChart(formatSet *formatChart) *cPlotArea { return &cPlotArea{ DoughnutChart: &cCharts{ VaryColors: &attrValBool{ - Val: true, + Val: boolPtr(true), }, Ser: f.drawChartSeries(formatSet), - HoleSize: &attrValInt{Val: 75}, + HoleSize: &attrValInt{Val: intPtr(75)}, }, } } @@ -1192,19 +1191,19 @@ func (f *File) drawLineChart(formatSet *formatChart) *cPlotArea { return &cPlotArea{ LineChart: &cCharts{ Grouping: &attrValString{ - Val: plotAreaChartGrouping[formatSet.Type], + Val: stringPtr(plotAreaChartGrouping[formatSet.Type]), }, VaryColors: &attrValBool{ - Val: false, + Val: boolPtr(false), }, Ser: f.drawChartSeries(formatSet), DLbls: f.drawChartDLbls(formatSet), Smooth: &attrValBool{ - Val: false, + Val: boolPtr(false), }, AxID: []*attrValInt{ - {Val: 754001152}, - {Val: 753999904}, + {Val: intPtr(754001152)}, + {Val: intPtr(753999904)}, }, }, CatAx: f.drawPlotAreaCatAx(formatSet), @@ -1218,7 +1217,7 @@ func (f *File) drawPieChart(formatSet *formatChart) *cPlotArea { return &cPlotArea{ PieChart: &cCharts{ VaryColors: &attrValBool{ - Val: true, + Val: boolPtr(true), }, Ser: f.drawChartSeries(formatSet), }, @@ -1231,7 +1230,7 @@ func (f *File) drawPie3DChart(formatSet *formatChart) *cPlotArea { return &cPlotArea{ Pie3DChart: &cCharts{ VaryColors: &attrValBool{ - Val: true, + Val: boolPtr(true), }, Ser: f.drawChartSeries(formatSet), }, @@ -1244,16 +1243,16 @@ func (f *File) drawRadarChart(formatSet *formatChart) *cPlotArea { return &cPlotArea{ RadarChart: &cCharts{ RadarStyle: &attrValString{ - Val: "marker", + Val: stringPtr("marker"), }, VaryColors: &attrValBool{ - Val: false, + Val: boolPtr(false), }, Ser: f.drawChartSeries(formatSet), DLbls: f.drawChartDLbls(formatSet), AxID: []*attrValInt{ - {Val: 754001152}, - {Val: 753999904}, + {Val: intPtr(754001152)}, + {Val: intPtr(753999904)}, }, }, CatAx: f.drawPlotAreaCatAx(formatSet), @@ -1267,16 +1266,16 @@ func (f *File) drawScatterChart(formatSet *formatChart) *cPlotArea { return &cPlotArea{ ScatterChart: &cCharts{ ScatterStyle: &attrValString{ - Val: "smoothMarker", // line,lineMarker,marker,none,smooth,smoothMarker + Val: stringPtr("smoothMarker"), // line,lineMarker,marker,none,smooth,smoothMarker }, VaryColors: &attrValBool{ - Val: false, + Val: boolPtr(false), }, Ser: f.drawChartSeries(formatSet), DLbls: f.drawChartDLbls(formatSet), AxID: []*attrValInt{ - {Val: 754001152}, - {Val: 753999904}, + {Val: intPtr(754001152)}, + {Val: intPtr(753999904)}, }, }, CatAx: f.drawPlotAreaCatAx(formatSet), @@ -1291,9 +1290,9 @@ func (f *File) drawSurface3DChart(formatSet *formatChart) *cPlotArea { Surface3DChart: &cCharts{ Ser: f.drawChartSeries(formatSet), AxID: []*attrValInt{ - {Val: 754001152}, - {Val: 753999904}, - {Val: 832256642}, + {Val: intPtr(754001152)}, + {Val: intPtr(753999904)}, + {Val: intPtr(832256642)}, }, }, CatAx: f.drawPlotAreaCatAx(formatSet), @@ -1301,7 +1300,7 @@ func (f *File) drawSurface3DChart(formatSet *formatChart) *cPlotArea { SerAx: f.drawPlotAreaSerAx(formatSet), } if formatSet.Type == WireframeSurface3D { - plotArea.Surface3DChart.Wireframe = &attrValBool{Val: true} + plotArea.Surface3DChart.Wireframe = &attrValBool{Val: boolPtr(true)} } return plotArea } @@ -1313,9 +1312,9 @@ func (f *File) drawSurfaceChart(formatSet *formatChart) *cPlotArea { SurfaceChart: &cCharts{ Ser: f.drawChartSeries(formatSet), AxID: []*attrValInt{ - {Val: 754001152}, - {Val: 753999904}, - {Val: 832256642}, + {Val: intPtr(754001152)}, + {Val: intPtr(753999904)}, + {Val: intPtr(832256642)}, }, }, CatAx: f.drawPlotAreaCatAx(formatSet), @@ -1323,7 +1322,7 @@ func (f *File) drawSurfaceChart(formatSet *formatChart) *cPlotArea { SerAx: f.drawPlotAreaSerAx(formatSet), } if formatSet.Type == WireframeContour { - plotArea.SurfaceChart.Wireframe = &attrValBool{Val: true} + plotArea.SurfaceChart.Wireframe = &attrValBool{Val: boolPtr(true)} } return plotArea } @@ -1355,7 +1354,7 @@ func (f *File) drawChartShape(formatSet *formatChart) *attrValString { Col3DCylinderPercentStacked: "cylinder", } if shape, ok := shapes[formatSet.Type]; ok { - return &attrValString{Val: shape} + return &attrValString{Val: stringPtr(shape)} } return nil } @@ -1366,8 +1365,8 @@ func (f *File) drawChartSeries(formatSet *formatChart) *[]cSer { ser := []cSer{} for k := range formatSet.Series { ser = append(ser, cSer{ - IDx: &attrValInt{Val: k}, - Order: &attrValInt{Val: k}, + IDx: &attrValInt{Val: intPtr(k)}, + Order: &attrValInt{Val: intPtr(k)}, Tx: &cTx{ StrRef: &cStrRef{ F: formatSet.Series[k].Name, @@ -1416,8 +1415,8 @@ func (f *File) drawChartSeriesSpPr(i int, formatSet *formatChart) *cSpPr { // data index and format sets. func (f *File) drawChartSeriesDPt(i int, formatSet *formatChart) []*cDPt { dpt := []*cDPt{{ - IDx: &attrValInt{Val: i}, - Bubble3D: &attrValBool{Val: false}, + IDx: &attrValInt{Val: intPtr(i)}, + Bubble3D: &attrValBool{Val: boolPtr(false)}, SpPr: &cSpPr{ SolidFill: &aSolidFill{ SchemeClr: &aSchemeClr{Val: "accent" + strconv.Itoa(i+1)}, @@ -1475,8 +1474,8 @@ func (f *File) drawChartSeriesVal(v formatChartSeries, formatSet *formatChart) * // given data index and format sets. func (f *File) drawChartSeriesMarker(i int, formatSet *formatChart) *cMarker { marker := &cMarker{ - Symbol: &attrValString{Val: "circle"}, - Size: &attrValInt{Val: 5}, + Symbol: &attrValString{Val: stringPtr("circle")}, + Size: &attrValInt{Val: intPtr(5)}, } if i < 6 { marker.SpPr = &cSpPr{ @@ -1542,20 +1541,20 @@ func (f *File) drawCharSeriesBubble3D(formatSet *formatChart) *attrValBool { if _, ok := map[string]bool{Bubble3D: true}[formatSet.Type]; !ok { return nil } - return &attrValBool{Val: true} + return &attrValBool{Val: boolPtr(true)} } // drawChartDLbls provides a function to draw the c:dLbls element by given // format sets. func (f *File) drawChartDLbls(formatSet *formatChart) *cDLbls { return &cDLbls{ - ShowLegendKey: &attrValBool{Val: formatSet.Legend.ShowLegendKey}, - ShowVal: &attrValBool{Val: formatSet.Plotarea.ShowVal}, - ShowCatName: &attrValBool{Val: formatSet.Plotarea.ShowCatName}, - ShowSerName: &attrValBool{Val: formatSet.Plotarea.ShowSerName}, - ShowBubbleSize: &attrValBool{Val: formatSet.Plotarea.ShowBubbleSize}, - ShowPercent: &attrValBool{Val: formatSet.Plotarea.ShowPercent}, - ShowLeaderLines: &attrValBool{Val: formatSet.Plotarea.ShowLeaderLines}, + ShowLegendKey: &attrValBool{Val: boolPtr(formatSet.Legend.ShowLegendKey)}, + ShowVal: &attrValBool{Val: boolPtr(formatSet.Plotarea.ShowVal)}, + ShowCatName: &attrValBool{Val: boolPtr(formatSet.Plotarea.ShowCatName)}, + ShowSerName: &attrValBool{Val: boolPtr(formatSet.Plotarea.ShowSerName)}, + ShowBubbleSize: &attrValBool{Val: boolPtr(formatSet.Plotarea.ShowBubbleSize)}, + ShowPercent: &attrValBool{Val: boolPtr(formatSet.Plotarea.ShowPercent)}, + ShowLeaderLines: &attrValBool{Val: boolPtr(formatSet.Plotarea.ShowLeaderLines)}, } } @@ -1572,8 +1571,8 @@ func (f *File) drawChartSeriesDLbls(formatSet *formatChart) *cDLbls { // drawPlotAreaCatAx provides a function to draw the c:catAx element. func (f *File) drawPlotAreaCatAx(formatSet *formatChart) []*cAxs { - min := &attrValFloat{Val: formatSet.XAxis.Minimum} - max := &attrValFloat{Val: formatSet.XAxis.Maximum} + min := &attrValFloat{Val: float64Ptr(formatSet.XAxis.Minimum)} + max := &attrValFloat{Val: float64Ptr(formatSet.XAxis.Maximum)} if formatSet.XAxis.Minimum == 0 { min = nil } @@ -1582,29 +1581,29 @@ func (f *File) drawPlotAreaCatAx(formatSet *formatChart) []*cAxs { } axs := []*cAxs{ { - AxID: &attrValInt{Val: 754001152}, + AxID: &attrValInt{Val: intPtr(754001152)}, Scaling: &cScaling{ - Orientation: &attrValString{Val: orientation[formatSet.XAxis.ReverseOrder]}, + Orientation: &attrValString{Val: stringPtr(orientation[formatSet.XAxis.ReverseOrder])}, Max: max, Min: min, }, - Delete: &attrValBool{Val: false}, - AxPos: &attrValString{Val: catAxPos[formatSet.XAxis.ReverseOrder]}, + Delete: &attrValBool{Val: boolPtr(false)}, + AxPos: &attrValString{Val: stringPtr(catAxPos[formatSet.XAxis.ReverseOrder])}, NumFmt: &cNumFmt{ FormatCode: "General", SourceLinked: true, }, - MajorTickMark: &attrValString{Val: "none"}, - MinorTickMark: &attrValString{Val: "none"}, - TickLblPos: &attrValString{Val: "nextTo"}, + MajorTickMark: &attrValString{Val: stringPtr("none")}, + MinorTickMark: &attrValString{Val: stringPtr("none")}, + TickLblPos: &attrValString{Val: stringPtr("nextTo")}, SpPr: f.drawPlotAreaSpPr(), TxPr: f.drawPlotAreaTxPr(), - CrossAx: &attrValInt{Val: 753999904}, - Crosses: &attrValString{Val: "autoZero"}, - Auto: &attrValBool{Val: true}, - LblAlgn: &attrValString{Val: "ctr"}, - LblOffset: &attrValInt{Val: 100}, - NoMultiLvlLbl: &attrValBool{Val: false}, + CrossAx: &attrValInt{Val: intPtr(753999904)}, + Crosses: &attrValString{Val: stringPtr("autoZero")}, + Auto: &attrValBool{Val: boolPtr(true)}, + LblAlgn: &attrValString{Val: stringPtr("ctr")}, + LblOffset: &attrValInt{Val: intPtr(100)}, + NoMultiLvlLbl: &attrValBool{Val: boolPtr(false)}, }, } if formatSet.XAxis.MajorGridlines { @@ -1618,8 +1617,8 @@ func (f *File) drawPlotAreaCatAx(formatSet *formatChart) []*cAxs { // drawPlotAreaValAx provides a function to draw the c:valAx element. func (f *File) drawPlotAreaValAx(formatSet *formatChart) []*cAxs { - min := &attrValFloat{Val: formatSet.YAxis.Minimum} - max := &attrValFloat{Val: formatSet.YAxis.Maximum} + min := &attrValFloat{Val: float64Ptr(formatSet.YAxis.Minimum)} + max := &attrValFloat{Val: float64Ptr(formatSet.YAxis.Maximum)} if formatSet.YAxis.Minimum == 0 { min = nil } @@ -1628,26 +1627,26 @@ func (f *File) drawPlotAreaValAx(formatSet *formatChart) []*cAxs { } axs := []*cAxs{ { - AxID: &attrValInt{Val: 753999904}, + AxID: &attrValInt{Val: intPtr(753999904)}, Scaling: &cScaling{ - Orientation: &attrValString{Val: orientation[formatSet.YAxis.ReverseOrder]}, + Orientation: &attrValString{Val: stringPtr(orientation[formatSet.YAxis.ReverseOrder])}, Max: max, Min: min, }, - Delete: &attrValBool{Val: false}, - AxPos: &attrValString{Val: valAxPos[formatSet.YAxis.ReverseOrder]}, + Delete: &attrValBool{Val: boolPtr(false)}, + AxPos: &attrValString{Val: stringPtr(valAxPos[formatSet.YAxis.ReverseOrder])}, NumFmt: &cNumFmt{ FormatCode: chartValAxNumFmtFormatCode[formatSet.Type], SourceLinked: true, }, - MajorTickMark: &attrValString{Val: "none"}, - MinorTickMark: &attrValString{Val: "none"}, - TickLblPos: &attrValString{Val: "nextTo"}, + MajorTickMark: &attrValString{Val: stringPtr("none")}, + MinorTickMark: &attrValString{Val: stringPtr("none")}, + TickLblPos: &attrValString{Val: stringPtr("nextTo")}, SpPr: f.drawPlotAreaSpPr(), TxPr: f.drawPlotAreaTxPr(), - CrossAx: &attrValInt{Val: 754001152}, - Crosses: &attrValString{Val: "autoZero"}, - CrossBetween: &attrValString{Val: chartValAxCrossBetween[formatSet.Type]}, + CrossAx: &attrValInt{Val: intPtr(754001152)}, + Crosses: &attrValString{Val: stringPtr("autoZero")}, + CrossBetween: &attrValString{Val: stringPtr(chartValAxCrossBetween[formatSet.Type])}, }, } if formatSet.YAxis.MajorGridlines { @@ -1657,15 +1656,15 @@ func (f *File) drawPlotAreaValAx(formatSet *formatChart) []*cAxs { axs[0].MinorGridlines = &cChartLines{SpPr: f.drawPlotAreaSpPr()} } if pos, ok := valTickLblPos[formatSet.Type]; ok { - axs[0].TickLblPos.Val = pos + axs[0].TickLblPos.Val = stringPtr(pos) } return axs } // drawPlotAreaSerAx provides a function to draw the c:serAx element. func (f *File) drawPlotAreaSerAx(formatSet *formatChart) []*cAxs { - min := &attrValFloat{Val: formatSet.YAxis.Minimum} - max := &attrValFloat{Val: formatSet.YAxis.Maximum} + min := &attrValFloat{Val: float64Ptr(formatSet.YAxis.Minimum)} + max := &attrValFloat{Val: float64Ptr(formatSet.YAxis.Maximum)} if formatSet.YAxis.Minimum == 0 { min = nil } @@ -1674,18 +1673,18 @@ func (f *File) drawPlotAreaSerAx(formatSet *formatChart) []*cAxs { } return []*cAxs{ { - AxID: &attrValInt{Val: 832256642}, + AxID: &attrValInt{Val: intPtr(832256642)}, Scaling: &cScaling{ - Orientation: &attrValString{Val: orientation[formatSet.YAxis.ReverseOrder]}, + Orientation: &attrValString{Val: stringPtr(orientation[formatSet.YAxis.ReverseOrder])}, Max: max, Min: min, }, - Delete: &attrValBool{Val: false}, - AxPos: &attrValString{Val: catAxPos[formatSet.XAxis.ReverseOrder]}, - TickLblPos: &attrValString{Val: "nextTo"}, + Delete: &attrValBool{Val: boolPtr(false)}, + AxPos: &attrValString{Val: stringPtr(catAxPos[formatSet.XAxis.ReverseOrder])}, + TickLblPos: &attrValString{Val: stringPtr("nextTo")}, SpPr: f.drawPlotAreaSpPr(), TxPr: f.drawPlotAreaTxPr(), - CrossAx: &attrValInt{Val: 753999904}, + CrossAx: &attrValInt{Val: intPtr(753999904)}, }, } } @@ -1701,8 +1700,8 @@ func (f *File) drawPlotAreaSpPr() *cSpPr { SolidFill: &aSolidFill{ SchemeClr: &aSchemeClr{ Val: "tx1", - LumMod: &attrValInt{Val: 15000}, - LumOff: &attrValInt{Val: 85000}, + LumMod: &attrValInt{Val: intPtr(15000)}, + LumOff: &attrValInt{Val: intPtr(85000)}, }, }, }, @@ -1734,8 +1733,8 @@ func (f *File) drawPlotAreaTxPr() *cTxPr { SolidFill: &aSolidFill{ SchemeClr: &aSchemeClr{ Val: "tx1", - LumMod: &attrValInt{Val: 15000}, - LumOff: &attrValInt{Val: 85000}, + LumMod: &attrValInt{Val: intPtr(15000)}, + LumOff: &attrValInt{Val: intPtr(85000)}, }, }, Latin: &aLatin{Typeface: "+mn-lt"}, -- cgit v1.2.1 From 5f3a4bc39f9cf2987104ffe57242a0526cdd9158 Mon Sep 17 00:00:00 2001 From: xuri Date: Wed, 25 Dec 2019 00:00:50 +0800 Subject: Fix #538, added setting a major unit and tick label skip support for the chart --- chart.go | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index 5a42c5b..b1446fb 100644 --- a/chart.go +++ b/chart.go @@ -653,10 +653,21 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // // show_val: Specifies that the value shall be shown in a data label. The show_val property is optional. The default value is false. // -// Set the primary horizontal and vertical axis options by x_axis and y_axis. The properties that can be set are: +// Set the primary horizontal and vertical axis options by x_axis and y_axis. The properties of x_axis that can be set are: // // major_grid_lines // minor_grid_lines +// major_unit +// reverse_order +// maximum +// minimum +// +// The properties of y_axis that can be set are: +// +// major_grid_lines +// minor_grid_lines +// major_unit +// tick_label_skip // reverse_order // maximum // minimum @@ -665,6 +676,10 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // // minor_grid_lines: Specifies minor gridlines. // +// major_unit: Specifies the distance between major ticks. Shall contain a positive floating-point number. The major_unit property is optional. The default value is auto. +// +// tick_label_skip: Specifies how many tick labels to skip between label that is drawn. The tick_label_skip property is optional. The default value is auto. +// // reverse_order: Specifies that the categories or values on reverse order (orientation of the chart). The reverse_order property is optional. The default value is false. // // maximum: Specifies that the fixed maximum, 0 is auto. The maximum property is optional. The default value is auto. @@ -1612,6 +1627,12 @@ func (f *File) drawPlotAreaCatAx(formatSet *formatChart) []*cAxs { if formatSet.XAxis.MinorGridlines { axs[0].MinorGridlines = &cChartLines{SpPr: f.drawPlotAreaSpPr()} } + if formatSet.XAxis.MajorUnit != 0 { + axs[0].MajorUnit = &attrValFloat{Val: float64Ptr(formatSet.XAxis.MajorUnit)} + } + if formatSet.XAxis.TickLabelSkip != 0 { + axs[0].TickLblSkip = &attrValInt{Val: intPtr(formatSet.XAxis.TickLabelSkip)} + } return axs } @@ -1658,6 +1679,9 @@ func (f *File) drawPlotAreaValAx(formatSet *formatChart) []*cAxs { if pos, ok := valTickLblPos[formatSet.Type]; ok { axs[0].TickLblPos.Val = stringPtr(pos) } + if formatSet.YAxis.MajorUnit != 0 { + axs[0].MajorUnit = &attrValFloat{Val: float64Ptr(formatSet.YAxis.MajorUnit)} + } return axs } -- cgit v1.2.1 From 8b960ee1e624bd2776a351a4a3b2ad04c29bae9a Mon Sep 17 00:00:00 2001 From: xuri Date: Sat, 28 Dec 2019 15:05:44 +0800 Subject: Fix #547 and #546, add default overlay element for the chart --- chart.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index b1446fb..8b38d22 100644 --- a/chart.go +++ b/chart.go @@ -657,7 +657,6 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // // major_grid_lines // minor_grid_lines -// major_unit // reverse_order // maximum // minimum @@ -818,6 +817,7 @@ func (f *File) addChart(formatSet *formatChart) { }, }, }, + Overlay: &attrValBool{Val: boolPtr(false)}, }, View3D: &cView3D{ RotX: &attrValInt{Val: intPtr(chartView3DRotX[formatSet.Type])}, @@ -1627,9 +1627,6 @@ func (f *File) drawPlotAreaCatAx(formatSet *formatChart) []*cAxs { if formatSet.XAxis.MinorGridlines { axs[0].MinorGridlines = &cChartLines{SpPr: f.drawPlotAreaSpPr()} } - if formatSet.XAxis.MajorUnit != 0 { - axs[0].MajorUnit = &attrValFloat{Val: float64Ptr(formatSet.XAxis.MajorUnit)} - } if formatSet.XAxis.TickLabelSkip != 0 { axs[0].TickLblSkip = &attrValInt{Val: intPtr(formatSet.XAxis.TickLabelSkip)} } -- cgit v1.2.1 From 09485b3f9f0aefc58d51462aed65c2416205c591 Mon Sep 17 00:00:00 2001 From: xuri Date: Sun, 29 Dec 2019 16:02:31 +0800 Subject: Improve code coverage unit tests --- chart.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index 8b38d22..b5ff3d1 100644 --- a/chart.go +++ b/chart.go @@ -1,4 +1,4 @@ -// Copyright 2016 - 2019 The excelize Authors. All rights reserved. Use of +// Copyright 2016 - 2020 The excelize Authors. All rights reserved. Use of // this source code is governed by a BSD-style license that can be found in // the LICENSE file. // @@ -657,6 +657,7 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // // major_grid_lines // minor_grid_lines +// tick_label_skip // reverse_order // maximum // minimum @@ -666,7 +667,6 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // major_grid_lines // minor_grid_lines // major_unit -// tick_label_skip // reverse_order // maximum // minimum -- cgit v1.2.1 From 5f5ec76740704a8362e5a120b4a3582b409a5fdd Mon Sep 17 00:00:00 2001 From: xuri Date: Tue, 31 Dec 2019 01:01:16 +0800 Subject: Fix #551, handle empty rows in streaming reading --- chart.go | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index b5ff3d1..a8fcaf5 100644 --- a/chart.go +++ b/chart.go @@ -495,11 +495,7 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // // package main // -// import ( -// "fmt" -// -// "github.com/360EntSecGroup-Skylar/excelize" -// ) +// import "github.com/360EntSecGroup-Skylar/excelize" // // func main() { // categories := map[string]string{"A2": "Small", "A3": "Normal", "A4": "Large", "B1": "Apple", "C1": "Orange", "D1": "Pear"} @@ -511,15 +507,13 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // for k, v := range values { // f.SetCellValue("Sheet1", k, v) // } -// 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}}`) -// if err != nil { -// fmt.Println(err) +// 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 { +// println(err.Error()) // return // } // // Save xlsx file by the given path. -// err = xlsx.SaveAs("./Book1.xlsx") -// if err != nil { -// fmt.Println(err) +// if err := xlsx.SaveAs("Book1.xlsx"); err != nil { +// println(err.Error()) // } // } // -- cgit v1.2.1 From 9ddb52eac4e451f676dabe4eed45ee95fce38eef Mon Sep 17 00:00:00 2001 From: xuri Date: Tue, 14 Jan 2020 00:33:36 +0800 Subject: Fix #554, init combo chart support, new chart pie of pie, bar of pie chart support --- chart.go | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 102 insertions(+), 7 deletions(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index a8fcaf5..f3b1cd8 100644 --- a/chart.go +++ b/chart.go @@ -16,6 +16,7 @@ import ( "errors" "io" "log" + "reflect" "strconv" "strings" ) @@ -66,6 +67,8 @@ const ( Line = "line" Pie = "pie" Pie3D = "pie3D" + PieOfPieChart = "pieOfPie" + BarOfPieChart = "barOfPie" Radar = "radar" Scatter = "scatter" Surface3D = "surface3D" @@ -123,6 +126,8 @@ var ( Line: 0, Pie: 0, Pie3D: 30, + PieOfPieChart: 0, + BarOfPieChart: 0, Radar: 0, Scatter: 0, Surface3D: 15, @@ -175,6 +180,8 @@ var ( Line: 0, Pie: 0, Pie3D: 0, + PieOfPieChart: 0, + BarOfPieChart: 0, Radar: 0, Scatter: 0, Surface3D: 20, @@ -237,6 +244,8 @@ var ( Line: 0, Pie: 0, Pie3D: 0, + PieOfPieChart: 0, + BarOfPieChart: 0, Radar: 0, Scatter: 0, Surface3D: 0, @@ -297,6 +306,8 @@ var ( Line: "General", Pie: "General", Pie3D: "General", + PieOfPieChart: "General", + BarOfPieChart: "General", Radar: "General", Scatter: "General", Surface3D: "General", @@ -351,6 +362,8 @@ var ( Line: "between", Pie: "between", Pie3D: "between", + PieOfPieChart: "between", + BarOfPieChart: "between", Radar: "between", Scatter: "between", Surface3D: "midCat", @@ -491,7 +504,7 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // AddChart provides the method to add chart in a sheet by given chart format // set (such as offset, scale, aspect ratio setting and print settings) and // properties set. For example, create 3D clustered column chart with data -// Sheet1!$A$29:$D$32: +// Sheet1!$E$1:$L$15: // // package main // @@ -507,12 +520,12 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // for k, v := range values { // f.SetCellValue("Sheet1", k, v) // } -// 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 { +// 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 { // println(err.Error()) // return // } // // Save xlsx file by the given path. -// if err := xlsx.SaveAs("Book1.xlsx"); err != nil { +// if err := f.SaveAs("Book1.xlsx"); err != nil { // println(err.Error()) // } // } @@ -565,6 +578,8 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // line | line chart // pie | pie chart // pie3D | 3D pie chart +// pieOfPie | pie of pie chart +// barOfPie | bar of pie chart // radar | radar chart // scatter | scatter chart // surface3D | 3D surface chart @@ -681,6 +696,34 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // // Set chart size by dimension property. The dimension property is optional. The default width is 480, and height is 290. // +// combo: Specifies tha create a chart that combines two art types in a single +// chart. For example, create a clustered column - line chart with data +// Sheet1!$E$1:$L$15: +// +// package main +// +// import "github.com/360EntSecGroup-Skylar/excelize" +// +// func main() { +// categories := map[string]string{"A2": "Small", "A3": "Normal", "A4": "Large", "B1": "Apple", "C1": "Orange", "D1": "Pear"} +// values := map[string]int{"B2": 2, "C2": 3, "D2": 3, "B3": 5, "C3": 2, "D3": 4, "B4": 6, "C4": 7, "D4": 8} +// f := excelize.NewFile() +// for k, v := range categories { +// f.SetCellValue("Sheet1", k, v) +// } +// for k, v := range values { +// f.SetCellValue("Sheet1", k, v) +// } +// 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 { +// println(err.Error()) +// return +// } +// // Save xlsx file by the given path. +// if err := f.SaveAs("Book1.xlsx"); err != nil { +// println(err.Error()) +// } +// } +// func (f *File) AddChart(sheet, cell, format string) error { formatSet, err := parseFormatChartSet(format) if err != nil { @@ -915,6 +958,8 @@ func (f *File) addChart(formatSet *formatChart) { Line: f.drawLineChart, Pie3D: f.drawPie3DChart, Pie: f.drawPieChart, + PieOfPieChart: f.drawPieOfPieChart, + BarOfPieChart: f.drawBarOfPieChart, Radar: f.drawRadarChart, Scatter: f.drawScatterChart, Surface3D: f.drawSurface3DChart, @@ -924,8 +969,20 @@ func (f *File) addChart(formatSet *formatChart) { Bubble: f.drawBaseChart, Bubble3D: f.drawBaseChart, } - xlsxChartSpace.Chart.PlotArea = plotAreaFunc[formatSet.Type](formatSet) - + addChart := func(c, p *cPlotArea) { + immutable, mutable := reflect.ValueOf(c).Elem(), reflect.ValueOf(p).Elem() + for i := 0; i < mutable.NumField(); i++ { + field := mutable.Field(i) + if field.IsNil() { + continue + } + immutable.FieldByName(mutable.Type().Field(i).Name).Set(field) + } + } + addChart(xlsxChartSpace.Chart.PlotArea, plotAreaFunc[formatSet.Type](formatSet)) + if formatSet.Combo != nil { + addChart(xlsxChartSpace.Chart.PlotArea, plotAreaFunc[formatSet.Combo.Type](formatSet.Combo)) + } chart, _ := xml.Marshal(xlsxChartSpace) media := "xl/charts/chart" + strconv.Itoa(count+1) + ".xml" f.saveFileList(media, chart) @@ -1246,6 +1303,40 @@ func (f *File) drawPie3DChart(formatSet *formatChart) *cPlotArea { } } +// drawPieOfPieChart provides a function to draw the c:plotArea element for +// pie chart by given format sets. +func (f *File) drawPieOfPieChart(formatSet *formatChart) *cPlotArea { + return &cPlotArea{ + PieChart: &cCharts{ + OfPieType: &attrValString{ + Val: stringPtr("pie"), + }, + VaryColors: &attrValBool{ + Val: boolPtr(true), + }, + Ser: f.drawChartSeries(formatSet), + SerLines: &attrValString{}, + }, + } +} + +// drawBarOfPieChart provides a function to draw the c:plotArea element for +// pie chart by given format sets. +func (f *File) drawBarOfPieChart(formatSet *formatChart) *cPlotArea { + return &cPlotArea{ + PieChart: &cCharts{ + OfPieType: &attrValString{ + Val: stringPtr("bar"), + }, + VaryColors: &attrValBool{ + Val: boolPtr(true), + }, + Ser: f.drawChartSeries(formatSet), + SerLines: &attrValString{}, + }, + } +} + // drawRadarChart provides a function to draw the c:plotArea element for radar // chart by given format sets. func (f *File) drawRadarChart(formatSet *formatChart) *cPlotArea { @@ -1371,11 +1462,15 @@ func (f *File) drawChartShape(formatSet *formatChart) *attrValString { // drawChartSeries provides a function to draw the c:ser element by given // format sets. func (f *File) drawChartSeries(formatSet *formatChart) *[]cSer { + var baseIdx int + if formatSet.Combo != nil { + baseIdx = len(formatSet.Combo.Series) + } ser := []cSer{} for k := range formatSet.Series { ser = append(ser, cSer{ - IDx: &attrValInt{Val: intPtr(k)}, - Order: &attrValInt{Val: intPtr(k)}, + IDx: &attrValInt{Val: intPtr(k + baseIdx)}, + Order: &attrValInt{Val: intPtr(k + baseIdx)}, Tx: &cTx{ StrRef: &cStrRef{ F: formatSet.Series[k].Name, -- cgit v1.2.1 From fa7078f06c82ed30f9573caf3c4d24d49f45df5a Mon Sep 17 00:00:00 2001 From: xuri Date: Thu, 16 Jan 2020 01:05:22 +0800 Subject: Specified combo chart as variadic parameters --- chart.go | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index f3b1cd8..738ed4b 100644 --- a/chart.go +++ b/chart.go @@ -696,7 +696,7 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // // Set chart size by dimension property. The dimension property is optional. The default width is 480, and height is 290. // -// combo: Specifies tha create a chart that combines two art types in a single +// combo: Specifies the create a chart that combines two art types in a single // chart. For example, create a clustered column - line chart with data // Sheet1!$E$1:$L$15: // @@ -714,7 +714,7 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // for k, v := range values { // f.SetCellValue("Sheet1", k, v) // } -// 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 { +// 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}}`, `{"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 { // println(err.Error()) // return // } @@ -724,11 +724,22 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // } // } // -func (f *File) AddChart(sheet, cell, format string) error { +func (f *File) AddChart(sheet, cell, format string, combo ...string) error { formatSet, err := parseFormatChartSet(format) if err != nil { return err } + comboCharts := []*formatChart{} + for _, comboFormat := range combo { + comboChart, err := parseFormatChartSet(comboFormat) + if err != nil { + return err + } + if _, ok := chartValAxNumFmtFormatCode[comboChart.Type]; !ok { + return errors.New("unsupported chart type " + comboChart.Type) + } + comboCharts = append(comboCharts, comboChart) + } // Read sheet data. xlsx, err := f.workSheetReader(sheet) if err != nil { @@ -748,7 +759,7 @@ func (f *File) AddChart(sheet, cell, format string) error { if err != nil { return err } - f.addChart(formatSet) + f.addChart(formatSet, comboCharts) f.addContentTypePart(chartID, "chart") f.addContentTypePart(drawingID, "drawings") return err @@ -786,7 +797,7 @@ func (f *File) prepareDrawing(xlsx *xlsxWorksheet, drawingID int, sheet, drawing // addChart provides a function to create chart as xl/charts/chart%d.xml by // given format sets. -func (f *File) addChart(formatSet *formatChart) { +func (f *File) addChart(formatSet *formatChart, comboCharts []*formatChart) { count := f.countCharts() xlsxChartSpace := xlsxChartSpace{ XMLNSc: NameSpaceDrawingMLChart, @@ -980,8 +991,11 @@ func (f *File) addChart(formatSet *formatChart) { } } addChart(xlsxChartSpace.Chart.PlotArea, plotAreaFunc[formatSet.Type](formatSet)) - if formatSet.Combo != nil { - addChart(xlsxChartSpace.Chart.PlotArea, plotAreaFunc[formatSet.Combo.Type](formatSet.Combo)) + order := len(formatSet.Series) + for idx := range comboCharts { + comboCharts[idx].order = order + addChart(xlsxChartSpace.Chart.PlotArea, plotAreaFunc[comboCharts[idx].Type](comboCharts[idx])) + order += len(comboCharts[idx].Series) } chart, _ := xml.Marshal(xlsxChartSpace) media := "xl/charts/chart" + strconv.Itoa(count+1) + ".xml" @@ -1462,15 +1476,11 @@ func (f *File) drawChartShape(formatSet *formatChart) *attrValString { // drawChartSeries provides a function to draw the c:ser element by given // format sets. func (f *File) drawChartSeries(formatSet *formatChart) *[]cSer { - var baseIdx int - if formatSet.Combo != nil { - baseIdx = len(formatSet.Combo.Series) - } ser := []cSer{} for k := range formatSet.Series { ser = append(ser, cSer{ - IDx: &attrValInt{Val: intPtr(k + baseIdx)}, - Order: &attrValInt{Val: intPtr(k + baseIdx)}, + IDx: &attrValInt{Val: intPtr(k + formatSet.order)}, + Order: &attrValInt{Val: intPtr(k + formatSet.order)}, Tx: &cTx{ StrRef: &cStrRef{ F: formatSet.Series[k].Name, @@ -1506,9 +1516,9 @@ func (f *File) drawChartSeriesSpPr(i int, formatSet *formatChart) *cSpPr { Cap: "rnd", // rnd, sq, flat }, } - if i < 6 { + if i+formatSet.order < 6 { spPrLine.Ln.SolidFill = &aSolidFill{ - SchemeClr: &aSchemeClr{Val: "accent" + strconv.Itoa(i+1)}, + SchemeClr: &aSchemeClr{Val: "accent" + strconv.Itoa(i+formatSet.order+1)}, } } chartSeriesSpPr := map[string]*cSpPr{Line: spPrLine, Scatter: spPrScatter} -- cgit v1.2.1 From 0bb245523aada34c7b3d30f0f6e9b16d9f78e7b8 Mon Sep 17 00:00:00 2001 From: xuri Date: Sun, 19 Jan 2020 00:23:00 +0800 Subject: Resolve #557, init delete chart support --- chart.go | 1240 +++----------------------------------------------------------- 1 file changed, 54 insertions(+), 1186 deletions(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index 738ed4b..5f06c55 100644 --- a/chart.go +++ b/chart.go @@ -12,11 +12,9 @@ package excelize import ( "bytes" "encoding/json" - "encoding/xml" "errors" + "fmt" "io" - "log" - "reflect" "strconv" "strings" ) @@ -765,1205 +763,75 @@ func (f *File) AddChart(sheet, cell, format string, combo ...string) error { return err } -// countCharts provides a function to get chart files count storage in the -// folder xl/charts. -func (f *File) countCharts() int { - count := 0 - for k := range f.XLSX { - if strings.Contains(k, "xl/charts/chart") { - count++ - } - } - return count -} - -// prepareDrawing provides a function to prepare drawing ID and XML by given -// drawingID, worksheet name and default drawingXML. -func (f *File) prepareDrawing(xlsx *xlsxWorksheet, drawingID int, sheet, drawingXML string) (int, string) { - sheetRelationshipsDrawingXML := "../drawings/drawing" + strconv.Itoa(drawingID) + ".xml" - if xlsx.Drawing != nil { - // The worksheet already has a picture or chart relationships, use the relationships drawing ../drawings/drawing%d.xml. - sheetRelationshipsDrawingXML = f.getSheetRelationshipsTargetByID(sheet, xlsx.Drawing.RID) - drawingID, _ = strconv.Atoi(strings.TrimSuffix(strings.TrimPrefix(sheetRelationshipsDrawingXML, "../drawings/drawing"), ".xml")) - drawingXML = strings.Replace(sheetRelationshipsDrawingXML, "..", "xl", -1) - } else { - // Add first picture for given sheet. - sheetRels := "xl/worksheets/_rels/" + strings.TrimPrefix(f.sheetMap[trimSheetName(sheet)], "xl/worksheets/") + ".rels" - rID := f.addRels(sheetRels, SourceRelationshipDrawingML, sheetRelationshipsDrawingXML, "") - f.addSheetDrawing(sheet, rID) +// DeleteChart provides a function to delete chart in XLSX by given worksheet +// and cell name. +func (f *File) DeleteChart(sheet, cell string) (err error) { + var wsDr *xlsxWsDr + col, row, err := CellNameToCoordinates(cell) + if err != nil { + return } - return drawingID, drawingXML -} - -// addChart provides a function to create chart as xl/charts/chart%d.xml by -// given format sets. -func (f *File) addChart(formatSet *formatChart, comboCharts []*formatChart) { - count := f.countCharts() - xlsxChartSpace := xlsxChartSpace{ - XMLNSc: NameSpaceDrawingMLChart, - XMLNSa: NameSpaceDrawingML, - XMLNSr: SourceRelationship, - XMLNSc16r2: SourceRelationshipChart201506, - Date1904: &attrValBool{Val: boolPtr(false)}, - Lang: &attrValString{Val: stringPtr("en-US")}, - RoundedCorners: &attrValBool{Val: boolPtr(false)}, - Chart: cChart{ - Title: &cTitle{ - Tx: cTx{ - Rich: &cRich{ - P: aP{ - PPr: &aPPr{ - DefRPr: aRPr{ - Kern: 1200, - Strike: "noStrike", - U: "none", - Sz: 1400, - SolidFill: &aSolidFill{ - SchemeClr: &aSchemeClr{ - Val: "tx1", - LumMod: &attrValInt{ - Val: intPtr(65000), - }, - LumOff: &attrValInt{ - Val: intPtr(35000), - }, - }, - }, - Ea: &aEa{ - Typeface: "+mn-ea", - }, - Cs: &aCs{ - Typeface: "+mn-cs", - }, - Latin: &aLatin{ - Typeface: "+mn-lt", - }, - }, - }, - R: &aR{ - RPr: aRPr{ - Lang: "en-US", - AltLang: "en-US", - }, - T: formatSet.Title.Name, - }, - }, - }, - }, - TxPr: cTxPr{ - P: aP{ - PPr: &aPPr{ - DefRPr: aRPr{ - Kern: 1200, - U: "none", - Sz: 14000, - Strike: "noStrike", - }, - }, - EndParaRPr: &aEndParaRPr{ - Lang: "en-US", - }, - }, - }, - Overlay: &attrValBool{Val: boolPtr(false)}, - }, - View3D: &cView3D{ - RotX: &attrValInt{Val: intPtr(chartView3DRotX[formatSet.Type])}, - RotY: &attrValInt{Val: intPtr(chartView3DRotY[formatSet.Type])}, - Perspective: &attrValInt{Val: intPtr(chartView3DPerspective[formatSet.Type])}, - RAngAx: &attrValInt{Val: intPtr(chartView3DRAngAx[formatSet.Type])}, - }, - Floor: &cThicknessSpPr{ - Thickness: &attrValInt{Val: intPtr(0)}, - }, - SideWall: &cThicknessSpPr{ - Thickness: &attrValInt{Val: intPtr(0)}, - }, - BackWall: &cThicknessSpPr{ - Thickness: &attrValInt{Val: intPtr(0)}, - }, - PlotArea: &cPlotArea{}, - Legend: &cLegend{ - LegendPos: &attrValString{Val: stringPtr(chartLegendPosition[formatSet.Legend.Position])}, - Overlay: &attrValBool{Val: boolPtr(false)}, - }, - - PlotVisOnly: &attrValBool{Val: boolPtr(false)}, - DispBlanksAs: &attrValString{Val: stringPtr(formatSet.ShowBlanksAs)}, - ShowDLblsOverMax: &attrValBool{Val: boolPtr(false)}, - }, - SpPr: &cSpPr{ - SolidFill: &aSolidFill{ - SchemeClr: &aSchemeClr{Val: "bg1"}, - }, - Ln: &aLn{ - W: 9525, - Cap: "flat", - Cmpd: "sng", - Algn: "ctr", - SolidFill: &aSolidFill{ - SchemeClr: &aSchemeClr{Val: "tx1", - LumMod: &attrValInt{ - Val: intPtr(15000), - }, - LumOff: &attrValInt{ - Val: intPtr(85000), - }, - }, - }, - }, - }, - PrintSettings: &cPrintSettings{ - PageMargins: &cPageMargins{ - B: 0.75, - L: 0.7, - R: 0.7, - T: 0.7, - Header: 0.3, - Footer: 0.3, - }, - }, + col-- + row-- + ws, err := f.workSheetReader(sheet) + if err != nil { + return } - plotAreaFunc := map[string]func(*formatChart) *cPlotArea{ - Area: f.drawBaseChart, - AreaStacked: f.drawBaseChart, - AreaPercentStacked: f.drawBaseChart, - Area3D: f.drawBaseChart, - Area3DStacked: f.drawBaseChart, - Area3DPercentStacked: f.drawBaseChart, - Bar: f.drawBaseChart, - BarStacked: f.drawBaseChart, - BarPercentStacked: f.drawBaseChart, - Bar3DClustered: f.drawBaseChart, - Bar3DStacked: f.drawBaseChart, - Bar3DPercentStacked: f.drawBaseChart, - Bar3DConeClustered: f.drawBaseChart, - Bar3DConeStacked: f.drawBaseChart, - Bar3DConePercentStacked: f.drawBaseChart, - Bar3DPyramidClustered: f.drawBaseChart, - Bar3DPyramidStacked: f.drawBaseChart, - Bar3DPyramidPercentStacked: f.drawBaseChart, - Bar3DCylinderClustered: f.drawBaseChart, - Bar3DCylinderStacked: f.drawBaseChart, - Bar3DCylinderPercentStacked: f.drawBaseChart, - Col: f.drawBaseChart, - ColStacked: f.drawBaseChart, - ColPercentStacked: f.drawBaseChart, - Col3D: f.drawBaseChart, - Col3DClustered: f.drawBaseChart, - Col3DStacked: f.drawBaseChart, - Col3DPercentStacked: f.drawBaseChart, - Col3DCone: f.drawBaseChart, - Col3DConeClustered: f.drawBaseChart, - Col3DConeStacked: f.drawBaseChart, - Col3DConePercentStacked: f.drawBaseChart, - Col3DPyramid: f.drawBaseChart, - Col3DPyramidClustered: f.drawBaseChart, - Col3DPyramidStacked: f.drawBaseChart, - Col3DPyramidPercentStacked: f.drawBaseChart, - Col3DCylinder: f.drawBaseChart, - Col3DCylinderClustered: f.drawBaseChart, - Col3DCylinderStacked: f.drawBaseChart, - Col3DCylinderPercentStacked: f.drawBaseChart, - Doughnut: f.drawDoughnutChart, - Line: f.drawLineChart, - Pie3D: f.drawPie3DChart, - Pie: f.drawPieChart, - PieOfPieChart: f.drawPieOfPieChart, - BarOfPieChart: f.drawBarOfPieChart, - Radar: f.drawRadarChart, - Scatter: f.drawScatterChart, - Surface3D: f.drawSurface3DChart, - WireframeSurface3D: f.drawSurface3DChart, - Contour: f.drawSurfaceChart, - WireframeContour: f.drawSurfaceChart, - Bubble: f.drawBaseChart, - Bubble3D: f.drawBaseChart, + if ws.Drawing == nil { + return } - addChart := func(c, p *cPlotArea) { - immutable, mutable := reflect.ValueOf(c).Elem(), reflect.ValueOf(p).Elem() - for i := 0; i < mutable.NumField(); i++ { - field := mutable.Field(i) - if field.IsNil() { - continue + drawingXML := strings.Replace(f.getSheetRelationshipsTargetByID(sheet, ws.Drawing.RID), "..", "xl", -1) + wsDr, _ = f.drawingParser(drawingXML) + for idx, anchor := range wsDr.TwoCellAnchor { + if err = nil; anchor.From != nil && anchor.Pic == nil { + if anchor.From.Col == col && anchor.From.Row == row { + wsDr.TwoCellAnchor = append(wsDr.TwoCellAnchor[:idx], wsDr.TwoCellAnchor[idx+1:]...) } - immutable.FieldByName(mutable.Type().Field(i).Name).Set(field) - } - } - addChart(xlsxChartSpace.Chart.PlotArea, plotAreaFunc[formatSet.Type](formatSet)) - order := len(formatSet.Series) - for idx := range comboCharts { - comboCharts[idx].order = order - addChart(xlsxChartSpace.Chart.PlotArea, plotAreaFunc[comboCharts[idx].Type](comboCharts[idx])) - order += len(comboCharts[idx].Series) - } - chart, _ := xml.Marshal(xlsxChartSpace) - media := "xl/charts/chart" + strconv.Itoa(count+1) + ".xml" - f.saveFileList(media, chart) -} - -// drawBaseChart provides a function to draw the c:plotArea element for bar, -// and column series charts by given format sets. -func (f *File) drawBaseChart(formatSet *formatChart) *cPlotArea { - c := cCharts{ - BarDir: &attrValString{ - Val: stringPtr("col"), - }, - Grouping: &attrValString{ - Val: stringPtr("clustered"), - }, - VaryColors: &attrValBool{ - Val: boolPtr(true), - }, - Ser: f.drawChartSeries(formatSet), - Shape: f.drawChartShape(formatSet), - DLbls: f.drawChartDLbls(formatSet), - AxID: []*attrValInt{ - {Val: intPtr(754001152)}, - {Val: intPtr(753999904)}, - }, - Overlap: &attrValInt{Val: intPtr(100)}, - } - var ok bool - if *c.BarDir.Val, ok = plotAreaChartBarDir[formatSet.Type]; !ok { - c.BarDir = nil - } - if *c.Grouping.Val, ok = plotAreaChartGrouping[formatSet.Type]; !ok { - c.Grouping = nil - } - if *c.Overlap.Val, ok = plotAreaChartOverlap[formatSet.Type]; !ok { - c.Overlap = nil - } - catAx := f.drawPlotAreaCatAx(formatSet) - valAx := f.drawPlotAreaValAx(formatSet) - charts := map[string]*cPlotArea{ - "area": { - AreaChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "areaStacked": { - AreaChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "areaPercentStacked": { - AreaChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "area3D": { - Area3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "area3DStacked": { - Area3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "area3DPercentStacked": { - Area3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "bar": { - BarChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "barStacked": { - BarChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "barPercentStacked": { - BarChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "bar3DClustered": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "bar3DStacked": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "bar3DPercentStacked": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "bar3DConeClustered": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "bar3DConeStacked": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "bar3DConePercentStacked": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "bar3DPyramidClustered": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "bar3DPyramidStacked": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "bar3DPyramidPercentStacked": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "bar3DCylinderClustered": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "bar3DCylinderStacked": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "bar3DCylinderPercentStacked": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "col": { - BarChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "colStacked": { - BarChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "colPercentStacked": { - BarChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "col3D": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "col3DClustered": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "col3DStacked": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "col3DPercentStacked": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "col3DCone": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "col3DConeClustered": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "col3DConeStacked": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "col3DConePercentStacked": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "col3DPyramid": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "col3DPyramidClustered": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "col3DPyramidStacked": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "col3DPyramidPercentStacked": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "col3DCylinder": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "col3DCylinderClustered": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "col3DCylinderStacked": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "col3DCylinderPercentStacked": { - Bar3DChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "bubble": { - BubbleChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - "bubble3D": { - BubbleChart: &c, - CatAx: catAx, - ValAx: valAx, - }, - } - return charts[formatSet.Type] -} - -// drawDoughnutChart provides a function to draw the c:plotArea element for -// doughnut chart by given format sets. -func (f *File) drawDoughnutChart(formatSet *formatChart) *cPlotArea { - return &cPlotArea{ - DoughnutChart: &cCharts{ - VaryColors: &attrValBool{ - Val: boolPtr(true), - }, - Ser: f.drawChartSeries(formatSet), - HoleSize: &attrValInt{Val: intPtr(75)}, - }, - } -} - -// drawLineChart provides a function to draw the c:plotArea element for line -// chart by given format sets. -func (f *File) drawLineChart(formatSet *formatChart) *cPlotArea { - return &cPlotArea{ - LineChart: &cCharts{ - Grouping: &attrValString{ - Val: stringPtr(plotAreaChartGrouping[formatSet.Type]), - }, - VaryColors: &attrValBool{ - Val: boolPtr(false), - }, - Ser: f.drawChartSeries(formatSet), - DLbls: f.drawChartDLbls(formatSet), - Smooth: &attrValBool{ - Val: boolPtr(false), - }, - AxID: []*attrValInt{ - {Val: intPtr(754001152)}, - {Val: intPtr(753999904)}, - }, - }, - CatAx: f.drawPlotAreaCatAx(formatSet), - ValAx: f.drawPlotAreaValAx(formatSet), - } -} - -// drawPieChart provides a function to draw the c:plotArea element for pie -// chart by given format sets. -func (f *File) drawPieChart(formatSet *formatChart) *cPlotArea { - return &cPlotArea{ - PieChart: &cCharts{ - VaryColors: &attrValBool{ - Val: boolPtr(true), - }, - Ser: f.drawChartSeries(formatSet), - }, - } -} - -// drawPie3DChart provides a function to draw the c:plotArea element for 3D -// pie chart by given format sets. -func (f *File) drawPie3DChart(formatSet *formatChart) *cPlotArea { - return &cPlotArea{ - Pie3DChart: &cCharts{ - VaryColors: &attrValBool{ - Val: boolPtr(true), - }, - Ser: f.drawChartSeries(formatSet), - }, - } -} - -// drawPieOfPieChart provides a function to draw the c:plotArea element for -// pie chart by given format sets. -func (f *File) drawPieOfPieChart(formatSet *formatChart) *cPlotArea { - return &cPlotArea{ - PieChart: &cCharts{ - OfPieType: &attrValString{ - Val: stringPtr("pie"), - }, - VaryColors: &attrValBool{ - Val: boolPtr(true), - }, - Ser: f.drawChartSeries(formatSet), - SerLines: &attrValString{}, - }, - } -} - -// drawBarOfPieChart provides a function to draw the c:plotArea element for -// pie chart by given format sets. -func (f *File) drawBarOfPieChart(formatSet *formatChart) *cPlotArea { - return &cPlotArea{ - PieChart: &cCharts{ - OfPieType: &attrValString{ - Val: stringPtr("bar"), - }, - VaryColors: &attrValBool{ - Val: boolPtr(true), - }, - Ser: f.drawChartSeries(formatSet), - SerLines: &attrValString{}, - }, - } -} - -// drawRadarChart provides a function to draw the c:plotArea element for radar -// chart by given format sets. -func (f *File) drawRadarChart(formatSet *formatChart) *cPlotArea { - return &cPlotArea{ - RadarChart: &cCharts{ - RadarStyle: &attrValString{ - Val: stringPtr("marker"), - }, - VaryColors: &attrValBool{ - Val: boolPtr(false), - }, - Ser: f.drawChartSeries(formatSet), - DLbls: f.drawChartDLbls(formatSet), - AxID: []*attrValInt{ - {Val: intPtr(754001152)}, - {Val: intPtr(753999904)}, - }, - }, - CatAx: f.drawPlotAreaCatAx(formatSet), - ValAx: f.drawPlotAreaValAx(formatSet), - } -} - -// drawScatterChart provides a function to draw the c:plotArea element for -// scatter chart by given format sets. -func (f *File) drawScatterChart(formatSet *formatChart) *cPlotArea { - return &cPlotArea{ - ScatterChart: &cCharts{ - ScatterStyle: &attrValString{ - Val: stringPtr("smoothMarker"), // line,lineMarker,marker,none,smooth,smoothMarker - }, - VaryColors: &attrValBool{ - Val: boolPtr(false), - }, - Ser: f.drawChartSeries(formatSet), - DLbls: f.drawChartDLbls(formatSet), - AxID: []*attrValInt{ - {Val: intPtr(754001152)}, - {Val: intPtr(753999904)}, - }, - }, - CatAx: f.drawPlotAreaCatAx(formatSet), - ValAx: f.drawPlotAreaValAx(formatSet), - } -} - -// drawSurface3DChart provides a function to draw the c:surface3DChart element by -// given format sets. -func (f *File) drawSurface3DChart(formatSet *formatChart) *cPlotArea { - plotArea := &cPlotArea{ - Surface3DChart: &cCharts{ - Ser: f.drawChartSeries(formatSet), - AxID: []*attrValInt{ - {Val: intPtr(754001152)}, - {Val: intPtr(753999904)}, - {Val: intPtr(832256642)}, - }, - }, - CatAx: f.drawPlotAreaCatAx(formatSet), - ValAx: f.drawPlotAreaValAx(formatSet), - SerAx: f.drawPlotAreaSerAx(formatSet), - } - if formatSet.Type == WireframeSurface3D { - plotArea.Surface3DChart.Wireframe = &attrValBool{Val: boolPtr(true)} - } - return plotArea -} - -// drawSurfaceChart provides a function to draw the c:surfaceChart element by -// given format sets. -func (f *File) drawSurfaceChart(formatSet *formatChart) *cPlotArea { - plotArea := &cPlotArea{ - SurfaceChart: &cCharts{ - Ser: f.drawChartSeries(formatSet), - AxID: []*attrValInt{ - {Val: intPtr(754001152)}, - {Val: intPtr(753999904)}, - {Val: intPtr(832256642)}, - }, - }, - CatAx: f.drawPlotAreaCatAx(formatSet), - ValAx: f.drawPlotAreaValAx(formatSet), - SerAx: f.drawPlotAreaSerAx(formatSet), - } - if formatSet.Type == WireframeContour { - plotArea.SurfaceChart.Wireframe = &attrValBool{Val: boolPtr(true)} - } - return plotArea -} - -// drawChartShape provides a function to draw the c:shape element by given -// format sets. -func (f *File) drawChartShape(formatSet *formatChart) *attrValString { - shapes := map[string]string{ - Bar3DConeClustered: "cone", - Bar3DConeStacked: "cone", - Bar3DConePercentStacked: "cone", - Bar3DPyramidClustered: "pyramid", - Bar3DPyramidStacked: "pyramid", - Bar3DPyramidPercentStacked: "pyramid", - Bar3DCylinderClustered: "cylinder", - Bar3DCylinderStacked: "cylinder", - Bar3DCylinderPercentStacked: "cylinder", - Col3DCone: "cone", - Col3DConeClustered: "cone", - Col3DConeStacked: "cone", - Col3DConePercentStacked: "cone", - Col3DPyramid: "pyramid", - Col3DPyramidClustered: "pyramid", - Col3DPyramidStacked: "pyramid", - Col3DPyramidPercentStacked: "pyramid", - Col3DCylinder: "cylinder", - Col3DCylinderClustered: "cylinder", - Col3DCylinderStacked: "cylinder", - Col3DCylinderPercentStacked: "cylinder", - } - if shape, ok := shapes[formatSet.Type]; ok { - return &attrValString{Val: stringPtr(shape)} - } - return nil -} - -// drawChartSeries provides a function to draw the c:ser element by given -// format sets. -func (f *File) drawChartSeries(formatSet *formatChart) *[]cSer { - ser := []cSer{} - for k := range formatSet.Series { - ser = append(ser, cSer{ - IDx: &attrValInt{Val: intPtr(k + formatSet.order)}, - Order: &attrValInt{Val: intPtr(k + formatSet.order)}, - Tx: &cTx{ - StrRef: &cStrRef{ - 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), - BubbleSize: f.drawCharSeriesBubbleSize(formatSet.Series[k], formatSet), - Bubble3D: f.drawCharSeriesBubble3D(formatSet), - }) - } - return &ser -} - -// drawChartSeriesSpPr provides a function to draw the c:spPr element by given -// format sets. -func (f *File) drawChartSeriesSpPr(i int, formatSet *formatChart) *cSpPr { - spPrScatter := &cSpPr{ - Ln: &aLn{ - W: 25400, - NoFill: " ", - }, - } - spPrLine := &cSpPr{ - Ln: &aLn{ - W: f.ptToEMUs(formatSet.Series[i].Line.Width), - Cap: "rnd", // rnd, sq, flat - }, - } - if i+formatSet.order < 6 { - spPrLine.Ln.SolidFill = &aSolidFill{ - SchemeClr: &aSchemeClr{Val: "accent" + strconv.Itoa(i+formatSet.order+1)}, - } - } - chartSeriesSpPr := map[string]*cSpPr{Line: spPrLine, Scatter: spPrScatter} - return chartSeriesSpPr[formatSet.Type] -} - -// drawChartSeriesDPt provides a function to draw the c:dPt element by given -// data index and format sets. -func (f *File) drawChartSeriesDPt(i int, formatSet *formatChart) []*cDPt { - dpt := []*cDPt{{ - IDx: &attrValInt{Val: intPtr(i)}, - Bubble3D: &attrValBool{Val: boolPtr(false)}, - SpPr: &cSpPr{ - SolidFill: &aSolidFill{ - SchemeClr: &aSchemeClr{Val: "accent" + strconv.Itoa(i+1)}, - }, - Ln: &aLn{ - W: 25400, - Cap: "rnd", - SolidFill: &aSolidFill{ - SchemeClr: &aSchemeClr{Val: "lt" + strconv.Itoa(i+1)}, - }, - }, - Sp3D: &aSp3D{ - ContourW: 25400, - ContourClr: &aContourClr{ - SchemeClr: &aSchemeClr{Val: "lt" + strconv.Itoa(i+1)}, - }, - }, - }, - }} - chartSeriesDPt := map[string][]*cDPt{Pie: dpt, Pie3D: dpt} - return chartSeriesDPt[formatSet.Type] -} - -// drawChartSeriesCat provides a function to draw the c:cat element by given -// chart series and format sets. -func (f *File) drawChartSeriesCat(v formatChartSeries, formatSet *formatChart) *cCat { - cat := &cCat{ - StrRef: &cStrRef{ - F: v.Categories, - }, - } - chartSeriesCat := map[string]*cCat{Scatter: nil, Bubble: nil, Bubble3D: nil} - if _, ok := chartSeriesCat[formatSet.Type]; ok || v.Categories == "" { - return nil - } - return cat -} - -// drawChartSeriesVal provides a function to draw the c:val element by given -// chart series and format sets. -func (f *File) drawChartSeriesVal(v formatChartSeries, formatSet *formatChart) *cVal { - val := &cVal{ - NumRef: &cNumRef{ - F: v.Values, - }, - } - chartSeriesVal := map[string]*cVal{Scatter: nil, Bubble: nil, Bubble3D: nil} - if _, ok := chartSeriesVal[formatSet.Type]; ok { - return nil - } - return val -} - -// drawChartSeriesMarker provides a function to draw the c:marker element by -// given data index and format sets. -func (f *File) drawChartSeriesMarker(i int, formatSet *formatChart) *cMarker { - marker := &cMarker{ - Symbol: &attrValString{Val: stringPtr("circle")}, - Size: &attrValInt{Val: intPtr(5)}, - } - if i < 6 { - marker.SpPr = &cSpPr{ - SolidFill: &aSolidFill{ - SchemeClr: &aSchemeClr{ - Val: "accent" + strconv.Itoa(i+1), - }, - }, - Ln: &aLn{ - W: 9252, - SolidFill: &aSolidFill{ - SchemeClr: &aSchemeClr{ - Val: "accent" + strconv.Itoa(i+1), - }, - }, - }, } } - chartSeriesMarker := map[string]*cMarker{Scatter: marker} - return chartSeriesMarker[formatSet.Type] + return f.deleteChart(col, row, drawingXML, wsDr) } -// drawChartSeriesXVal provides a function to draw the c:xVal element by given -// chart series and format sets. -func (f *File) drawChartSeriesXVal(v formatChartSeries, formatSet *formatChart) *cCat { - cat := &cCat{ - StrRef: &cStrRef{ - F: v.Categories, - }, - } - chartSeriesXVal := map[string]*cCat{Scatter: cat} - return chartSeriesXVal[formatSet.Type] -} - -// drawChartSeriesYVal provides a function to draw the c:yVal element by given -// chart series and format sets. -func (f *File) drawChartSeriesYVal(v formatChartSeries, formatSet *formatChart) *cVal { - val := &cVal{ - NumRef: &cNumRef{ - F: v.Values, - }, - } - 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: boolPtr(true)} -} - -// drawChartDLbls provides a function to draw the c:dLbls element by given -// format sets. -func (f *File) drawChartDLbls(formatSet *formatChart) *cDLbls { - return &cDLbls{ - ShowLegendKey: &attrValBool{Val: boolPtr(formatSet.Legend.ShowLegendKey)}, - ShowVal: &attrValBool{Val: boolPtr(formatSet.Plotarea.ShowVal)}, - ShowCatName: &attrValBool{Val: boolPtr(formatSet.Plotarea.ShowCatName)}, - ShowSerName: &attrValBool{Val: boolPtr(formatSet.Plotarea.ShowSerName)}, - ShowBubbleSize: &attrValBool{Val: boolPtr(formatSet.Plotarea.ShowBubbleSize)}, - ShowPercent: &attrValBool{Val: boolPtr(formatSet.Plotarea.ShowPercent)}, - ShowLeaderLines: &attrValBool{Val: boolPtr(formatSet.Plotarea.ShowLeaderLines)}, - } -} - -// drawChartSeriesDLbls provides a function to draw the c:dLbls element by -// 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, Bubble: nil, Bubble3D: nil} - if _, ok := chartSeriesDLbls[formatSet.Type]; ok { - return nil - } - return dLbls -} - -// drawPlotAreaCatAx provides a function to draw the c:catAx element. -func (f *File) drawPlotAreaCatAx(formatSet *formatChart) []*cAxs { - min := &attrValFloat{Val: float64Ptr(formatSet.XAxis.Minimum)} - max := &attrValFloat{Val: float64Ptr(formatSet.XAxis.Maximum)} - if formatSet.XAxis.Minimum == 0 { - min = nil - } - if formatSet.XAxis.Maximum == 0 { - max = nil - } - axs := []*cAxs{ - { - AxID: &attrValInt{Val: intPtr(754001152)}, - Scaling: &cScaling{ - Orientation: &attrValString{Val: stringPtr(orientation[formatSet.XAxis.ReverseOrder])}, - Max: max, - Min: min, - }, - Delete: &attrValBool{Val: boolPtr(false)}, - AxPos: &attrValString{Val: stringPtr(catAxPos[formatSet.XAxis.ReverseOrder])}, - NumFmt: &cNumFmt{ - FormatCode: "General", - SourceLinked: true, - }, - MajorTickMark: &attrValString{Val: stringPtr("none")}, - MinorTickMark: &attrValString{Val: stringPtr("none")}, - TickLblPos: &attrValString{Val: stringPtr("nextTo")}, - SpPr: f.drawPlotAreaSpPr(), - TxPr: f.drawPlotAreaTxPr(), - CrossAx: &attrValInt{Val: intPtr(753999904)}, - Crosses: &attrValString{Val: stringPtr("autoZero")}, - Auto: &attrValBool{Val: boolPtr(true)}, - LblAlgn: &attrValString{Val: stringPtr("ctr")}, - LblOffset: &attrValInt{Val: intPtr(100)}, - NoMultiLvlLbl: &attrValBool{Val: boolPtr(false)}, - }, - } - if formatSet.XAxis.MajorGridlines { - axs[0].MajorGridlines = &cChartLines{SpPr: f.drawPlotAreaSpPr()} - } - if formatSet.XAxis.MinorGridlines { - axs[0].MinorGridlines = &cChartLines{SpPr: f.drawPlotAreaSpPr()} - } - if formatSet.XAxis.TickLabelSkip != 0 { - axs[0].TickLblSkip = &attrValInt{Val: intPtr(formatSet.XAxis.TickLabelSkip)} - } - return axs -} - -// drawPlotAreaValAx provides a function to draw the c:valAx element. -func (f *File) drawPlotAreaValAx(formatSet *formatChart) []*cAxs { - min := &attrValFloat{Val: float64Ptr(formatSet.YAxis.Minimum)} - max := &attrValFloat{Val: float64Ptr(formatSet.YAxis.Maximum)} - if formatSet.YAxis.Minimum == 0 { - min = nil - } - if formatSet.YAxis.Maximum == 0 { - max = nil - } - axs := []*cAxs{ - { - AxID: &attrValInt{Val: intPtr(753999904)}, - Scaling: &cScaling{ - Orientation: &attrValString{Val: stringPtr(orientation[formatSet.YAxis.ReverseOrder])}, - Max: max, - Min: min, - }, - Delete: &attrValBool{Val: boolPtr(false)}, - AxPos: &attrValString{Val: stringPtr(valAxPos[formatSet.YAxis.ReverseOrder])}, - NumFmt: &cNumFmt{ - FormatCode: chartValAxNumFmtFormatCode[formatSet.Type], - SourceLinked: true, - }, - MajorTickMark: &attrValString{Val: stringPtr("none")}, - MinorTickMark: &attrValString{Val: stringPtr("none")}, - TickLblPos: &attrValString{Val: stringPtr("nextTo")}, - SpPr: f.drawPlotAreaSpPr(), - TxPr: f.drawPlotAreaTxPr(), - CrossAx: &attrValInt{Val: intPtr(754001152)}, - Crosses: &attrValString{Val: stringPtr("autoZero")}, - CrossBetween: &attrValString{Val: stringPtr(chartValAxCrossBetween[formatSet.Type])}, - }, - } - if formatSet.YAxis.MajorGridlines { - axs[0].MajorGridlines = &cChartLines{SpPr: f.drawPlotAreaSpPr()} - } - if formatSet.YAxis.MinorGridlines { - axs[0].MinorGridlines = &cChartLines{SpPr: f.drawPlotAreaSpPr()} - } - if pos, ok := valTickLblPos[formatSet.Type]; ok { - axs[0].TickLblPos.Val = stringPtr(pos) - } - if formatSet.YAxis.MajorUnit != 0 { - axs[0].MajorUnit = &attrValFloat{Val: float64Ptr(formatSet.YAxis.MajorUnit)} - } - return axs -} - -// drawPlotAreaSerAx provides a function to draw the c:serAx element. -func (f *File) drawPlotAreaSerAx(formatSet *formatChart) []*cAxs { - min := &attrValFloat{Val: float64Ptr(formatSet.YAxis.Minimum)} - max := &attrValFloat{Val: float64Ptr(formatSet.YAxis.Maximum)} - if formatSet.YAxis.Minimum == 0 { - min = nil - } - if formatSet.YAxis.Maximum == 0 { - max = nil - } - return []*cAxs{ - { - AxID: &attrValInt{Val: intPtr(832256642)}, - Scaling: &cScaling{ - Orientation: &attrValString{Val: stringPtr(orientation[formatSet.YAxis.ReverseOrder])}, - Max: max, - Min: min, - }, - Delete: &attrValBool{Val: boolPtr(false)}, - AxPos: &attrValString{Val: stringPtr(catAxPos[formatSet.XAxis.ReverseOrder])}, - TickLblPos: &attrValString{Val: stringPtr("nextTo")}, - SpPr: f.drawPlotAreaSpPr(), - TxPr: f.drawPlotAreaTxPr(), - CrossAx: &attrValInt{Val: intPtr(753999904)}, - }, - } -} - -// drawPlotAreaSpPr provides a function to draw the c:spPr element. -func (f *File) drawPlotAreaSpPr() *cSpPr { - return &cSpPr{ - Ln: &aLn{ - W: 9525, - Cap: "flat", - Cmpd: "sng", - Algn: "ctr", - SolidFill: &aSolidFill{ - SchemeClr: &aSchemeClr{ - Val: "tx1", - LumMod: &attrValInt{Val: intPtr(15000)}, - LumOff: &attrValInt{Val: intPtr(85000)}, - }, - }, - }, - } -} - -// drawPlotAreaTxPr provides a function to draw the c:txPr element. -func (f *File) drawPlotAreaTxPr() *cTxPr { - return &cTxPr{ - BodyPr: aBodyPr{ - Rot: -60000000, - SpcFirstLastPara: true, - VertOverflow: "ellipsis", - Vert: "horz", - Wrap: "square", - Anchor: "ctr", - AnchorCtr: true, - }, - P: aP{ - PPr: &aPPr{ - DefRPr: aRPr{ - Sz: 900, - B: false, - I: false, - U: "none", - Strike: "noStrike", - Kern: 1200, - Baseline: 0, - SolidFill: &aSolidFill{ - SchemeClr: &aSchemeClr{ - Val: "tx1", - LumMod: &attrValInt{Val: intPtr(15000)}, - LumOff: &attrValInt{Val: intPtr(85000)}, - }, - }, - Latin: &aLatin{Typeface: "+mn-lt"}, - Ea: &aEa{Typeface: "+mn-ea"}, - Cs: &aCs{Typeface: "+mn-cs"}, - }, - }, - EndParaRPr: &aEndParaRPr{Lang: "en-US"}, - }, - } -} - -// 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 -// defined. -func (f *File) drawingParser(path string) (*xlsxWsDr, int) { +// deleteChart provides a function to delete chart graphic frame by given by +// given coordinates. +func (f *File) deleteChart(col, row int, drawingXML string, wsDr *xlsxWsDr) (err error) { var ( - err error - ok bool + deWsDr *decodeWsDr + deTwoCellAnchor *decodeTwoCellAnchor ) - - if f.Drawings[path] == nil { - content := xlsxWsDr{} - content.A = NameSpaceDrawingML - content.Xdr = NameSpaceDrawingMLSpreadSheet - if _, ok = f.XLSX[path]; ok { // Append Model - decodeWsDr := decodeWsDr{} - if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(path)))). - Decode(&decodeWsDr); err != nil && err != io.EOF { - log.Printf("xml decode error: %s", err) - } - content.R = decodeWsDr.R - for _, v := range decodeWsDr.OneCellAnchor { - content.OneCellAnchor = append(content.OneCellAnchor, &xdrCellAnchor{ - EditAs: v.EditAs, - GraphicFrame: v.Content, - }) - } - for _, v := range decodeWsDr.TwoCellAnchor { - content.TwoCellAnchor = append(content.TwoCellAnchor, &xdrCellAnchor{ - EditAs: v.EditAs, - GraphicFrame: v.Content, - }) + deWsDr = new(decodeWsDr) + if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(drawingXML)))). + Decode(deWsDr); err != nil && err != io.EOF { + err = fmt.Errorf("xml decode error: %s", err) + return + } + for idx, anchor := range deWsDr.TwoCellAnchor { + deTwoCellAnchor = new(decodeTwoCellAnchor) + if err = f.xmlNewDecoder(bytes.NewReader([]byte("" + anchor.Content + ""))). + Decode(deTwoCellAnchor); err != nil && err != io.EOF { + err = fmt.Errorf("xml decode error: %s", err) + return + } + if err = nil; deTwoCellAnchor.From != nil && deTwoCellAnchor.Pic == nil { + if anchor.From.Col == col && anchor.From.Row == row { + wsDr.TwoCellAnchor = append(wsDr.TwoCellAnchor[:idx], wsDr.TwoCellAnchor[idx+1:]...) } } - f.Drawings[path] = &content } - wsDr := f.Drawings[path] - return wsDr, len(wsDr.OneCellAnchor) + len(wsDr.TwoCellAnchor) + 2 + f.Drawings[drawingXML] = wsDr + return err } -// addDrawingChart provides a function to add chart graphic frame by given -// sheet, drawingXML, cell, width, height, relationship index and format sets. -func (f *File) addDrawingChart(sheet, drawingXML, cell string, width, height, rID int, formatSet *formatPicture) error { - col, row, err := CellNameToCoordinates(cell) - if err != nil { - return err - } - colIdx := col - 1 - rowIdx := row - 1 - - width = int(float64(width) * formatSet.XScale) - height = int(float64(height) * formatSet.YScale) - colStart, rowStart, _, _, colEnd, rowEnd, x2, y2 := - f.positionObjectPixels(sheet, colIdx, rowIdx, formatSet.OffsetX, formatSet.OffsetY, width, height) - content, cNvPrID := f.drawingParser(drawingXML) - twoCellAnchor := xdrCellAnchor{} - twoCellAnchor.EditAs = formatSet.Positioning - from := xlsxFrom{} - from.Col = colStart - from.ColOff = formatSet.OffsetX * EMU - from.Row = rowStart - from.RowOff = formatSet.OffsetY * EMU - to := xlsxTo{} - to.Col = colEnd - to.ColOff = x2 * EMU - to.Row = rowEnd - to.RowOff = y2 * EMU - twoCellAnchor.From = &from - twoCellAnchor.To = &to - - graphicFrame := xlsxGraphicFrame{ - NvGraphicFramePr: xlsxNvGraphicFramePr{ - CNvPr: &xlsxCNvPr{ - ID: cNvPrID, - Name: "Chart " + strconv.Itoa(cNvPrID), - }, - }, - Graphic: &xlsxGraphic{ - GraphicData: &xlsxGraphicData{ - URI: NameSpaceDrawingMLChart, - Chart: &xlsxChart{ - C: NameSpaceDrawingMLChart, - R: SourceRelationship, - RID: "rId" + strconv.Itoa(rID), - }, - }, - }, - } - graphic, _ := xml.Marshal(graphicFrame) - twoCellAnchor.GraphicFrame = string(graphic) - twoCellAnchor.ClientData = &xdrClientData{ - FLocksWithSheet: formatSet.FLocksWithSheet, - FPrintsWithSheet: formatSet.FPrintsWithSheet, +// countCharts provides a function to get chart files count storage in the +// folder xl/charts. +func (f *File) countCharts() int { + count := 0 + for k := range f.XLSX { + if strings.Contains(k, "xl/charts/chart") { + count++ + } } - content.TwoCellAnchor = append(content.TwoCellAnchor, &twoCellAnchor) - f.Drawings[drawingXML] = content - return err + return count } // ptToEMUs provides a function to convert pt to EMUs, 1 pt = 12700 EMUs. The -- cgit v1.2.1 From e2bd08c9111b0141c66adf232edb2fd729afa63f Mon Sep 17 00:00:00 2001 From: xuri Date: Tue, 21 Jan 2020 23:29:56 +0800 Subject: Make DeleteChart delete multiple charts located on the same cell --- chart.go | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index 5f06c55..2629f0b 100644 --- a/chart.go +++ b/chart.go @@ -694,9 +694,9 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // // Set chart size by dimension property. The dimension property is optional. The default width is 480, and height is 290. // -// combo: Specifies the create a chart that combines two art types in a single -// chart. For example, create a clustered column - line chart with data -// Sheet1!$E$1:$L$15: +// combo: Specifies the create a chart that combines two or more chart types +// in a single chart. For example, create a clustered column - line chart with +// data Sheet1!$E$1:$L$15: // // package main // @@ -782,10 +782,11 @@ func (f *File) DeleteChart(sheet, cell string) (err error) { } drawingXML := strings.Replace(f.getSheetRelationshipsTargetByID(sheet, ws.Drawing.RID), "..", "xl", -1) wsDr, _ = f.drawingParser(drawingXML) - for idx, anchor := range wsDr.TwoCellAnchor { - if err = nil; anchor.From != nil && anchor.Pic == nil { - if anchor.From.Col == col && anchor.From.Row == row { + for idx := 0; idx < len(wsDr.TwoCellAnchor); idx++ { + if err = nil; wsDr.TwoCellAnchor[idx].From != nil && wsDr.TwoCellAnchor[idx].Pic == nil { + if wsDr.TwoCellAnchor[idx].From.Col == col && wsDr.TwoCellAnchor[idx].From.Row == row { wsDr.TwoCellAnchor = append(wsDr.TwoCellAnchor[:idx], wsDr.TwoCellAnchor[idx+1:]...) + idx-- } } } @@ -795,26 +796,18 @@ func (f *File) DeleteChart(sheet, cell string) (err error) { // deleteChart provides a function to delete chart graphic frame by given by // given coordinates. func (f *File) deleteChart(col, row int, drawingXML string, wsDr *xlsxWsDr) (err error) { - var ( - deWsDr *decodeWsDr - deTwoCellAnchor *decodeTwoCellAnchor - ) - deWsDr = new(decodeWsDr) - if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(drawingXML)))). - Decode(deWsDr); err != nil && err != io.EOF { - err = fmt.Errorf("xml decode error: %s", err) - return - } - for idx, anchor := range deWsDr.TwoCellAnchor { + var deTwoCellAnchor *decodeTwoCellAnchor + for idx := 0; idx < len(wsDr.TwoCellAnchor); idx++ { deTwoCellAnchor = new(decodeTwoCellAnchor) - if err = f.xmlNewDecoder(bytes.NewReader([]byte("" + anchor.Content + ""))). + if err = f.xmlNewDecoder(bytes.NewReader([]byte("" + wsDr.TwoCellAnchor[idx].GraphicFrame + ""))). Decode(deTwoCellAnchor); err != nil && err != io.EOF { err = fmt.Errorf("xml decode error: %s", err) return } if err = nil; deTwoCellAnchor.From != nil && deTwoCellAnchor.Pic == nil { - if anchor.From.Col == col && anchor.From.Row == row { + if deTwoCellAnchor.From.Col == col && deTwoCellAnchor.From.Row == row { wsDr.TwoCellAnchor = append(wsDr.TwoCellAnchor[:idx], wsDr.TwoCellAnchor[idx+1:]...) + idx-- } } } -- cgit v1.2.1 From cbc3fd21b79fbb819c1c341fc825701c04a0b473 Mon Sep 17 00:00:00 2001 From: xuri Date: Wed, 22 Jan 2020 01:08:18 +0800 Subject: Resolve #455, init delete picture from spreadsheet support --- chart.go | 37 +------------------------------------ 1 file changed, 1 insertion(+), 36 deletions(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index 2629f0b..227cdee 100644 --- a/chart.go +++ b/chart.go @@ -10,11 +10,8 @@ package excelize import ( - "bytes" "encoding/json" "errors" - "fmt" - "io" "strconv" "strings" ) @@ -766,7 +763,6 @@ func (f *File) AddChart(sheet, cell, format string, combo ...string) error { // DeleteChart provides a function to delete chart in XLSX by given worksheet // and cell name. func (f *File) DeleteChart(sheet, cell string) (err error) { - var wsDr *xlsxWsDr col, row, err := CellNameToCoordinates(cell) if err != nil { return @@ -781,38 +777,7 @@ func (f *File) DeleteChart(sheet, cell string) (err error) { return } drawingXML := strings.Replace(f.getSheetRelationshipsTargetByID(sheet, ws.Drawing.RID), "..", "xl", -1) - wsDr, _ = f.drawingParser(drawingXML) - for idx := 0; idx < len(wsDr.TwoCellAnchor); idx++ { - if err = nil; wsDr.TwoCellAnchor[idx].From != nil && wsDr.TwoCellAnchor[idx].Pic == nil { - if wsDr.TwoCellAnchor[idx].From.Col == col && wsDr.TwoCellAnchor[idx].From.Row == row { - wsDr.TwoCellAnchor = append(wsDr.TwoCellAnchor[:idx], wsDr.TwoCellAnchor[idx+1:]...) - idx-- - } - } - } - return f.deleteChart(col, row, drawingXML, wsDr) -} - -// deleteChart provides a function to delete chart graphic frame by given by -// given coordinates. -func (f *File) deleteChart(col, row int, drawingXML string, wsDr *xlsxWsDr) (err error) { - var deTwoCellAnchor *decodeTwoCellAnchor - for idx := 0; idx < len(wsDr.TwoCellAnchor); idx++ { - deTwoCellAnchor = new(decodeTwoCellAnchor) - if err = f.xmlNewDecoder(bytes.NewReader([]byte("" + wsDr.TwoCellAnchor[idx].GraphicFrame + ""))). - Decode(deTwoCellAnchor); err != nil && err != io.EOF { - err = fmt.Errorf("xml decode error: %s", err) - return - } - if err = nil; deTwoCellAnchor.From != nil && deTwoCellAnchor.Pic == nil { - if deTwoCellAnchor.From.Col == col && deTwoCellAnchor.From.Row == row { - wsDr.TwoCellAnchor = append(wsDr.TwoCellAnchor[:idx], wsDr.TwoCellAnchor[idx+1:]...) - idx-- - } - } - } - f.Drawings[drawingXML] = wsDr - return err + return f.deleteDrawing(col, row, drawingXML, "Chart") } // countCharts provides a function to get chart files count storage in the -- cgit v1.2.1 From ad883caa0f77dfc016ae99bd5fbb606953eb99a0 Mon Sep 17 00:00:00 2001 From: xuri Date: Wed, 19 Feb 2020 00:08:10 +0800 Subject: Resolve #580, revert commit https://github.com/360EntSecGroup-Skylar/excelize/commit/5ca7231ed408ac264f509ff52b5d28ff4fbda757 --- chart.go | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index 227cdee..69c2c95 100644 --- a/chart.go +++ b/chart.go @@ -503,7 +503,11 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // // package main // -// import "github.com/360EntSecGroup-Skylar/excelize" +// import ( +// "fmt" +// +// "github.com/360EntSecGroup-Skylar/excelize" +// ) // // func main() { // categories := map[string]string{"A2": "Small", "A3": "Normal", "A4": "Large", "B1": "Apple", "C1": "Orange", "D1": "Pear"} @@ -516,12 +520,12 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // f.SetCellValue("Sheet1", k, v) // } // 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 { -// println(err.Error()) +// fmt.Println(err) // return // } // // Save xlsx file by the given path. // if err := f.SaveAs("Book1.xlsx"); err != nil { -// println(err.Error()) +// fmt.Println(err) // } // } // @@ -697,7 +701,11 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // // package main // -// import "github.com/360EntSecGroup-Skylar/excelize" +// import ( +// "fmt" +// +// "github.com/360EntSecGroup-Skylar/excelize" +// ) // // func main() { // categories := map[string]string{"A2": "Small", "A3": "Normal", "A4": "Large", "B1": "Apple", "C1": "Orange", "D1": "Pear"} @@ -710,12 +718,12 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // f.SetCellValue("Sheet1", k, v) // } // 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}}`, `{"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 { -// println(err.Error()) +// fmt.Println(err) // return // } // // Save xlsx file by the given path. // if err := f.SaveAs("Book1.xlsx"); err != nil { -// println(err.Error()) +// fmt.Println(err) // } // } // -- cgit v1.2.1 From 6afc468a025984aa1b265b0228f032c5ed881a3b Mon Sep 17 00:00:00 2001 From: xuri Date: Sat, 28 Mar 2020 23:47:26 +0800 Subject: Resolve #451, support create chart sheet --- chart.go | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) (limited to 'chart.go') diff --git a/chart.go b/chart.go index 69c2c95..df196e9 100644 --- a/chart.go +++ b/chart.go @@ -11,7 +11,9 @@ package excelize import ( "encoding/json" + "encoding/xml" "errors" + "fmt" "strconv" "strings" ) @@ -768,6 +770,72 @@ func (f *File) AddChart(sheet, cell, format string, combo ...string) error { return err } +// AddChartSheet provides the method to create a chartsheet by given chart +// format set (such as offset, scale, aspect ratio setting and print settings) +// and properties set. In Excel a chartsheet is a worksheet that only contains +// a chart. +func (f *File) AddChartSheet(sheet, format string, combo ...string) error { + // Check if the worksheet already exists + if f.GetSheetIndex(sheet) != 0 { + return errors.New("already existing name worksheet") + } + formatSet, err := parseFormatChartSet(format) + if err != nil { + return err + } + comboCharts := []*formatChart{} + for _, comboFormat := range combo { + comboChart, err := parseFormatChartSet(comboFormat) + if err != nil { + return err + } + if _, ok := chartValAxNumFmtFormatCode[comboChart.Type]; !ok { + return errors.New("unsupported chart type " + comboChart.Type) + } + comboCharts = append(comboCharts, comboChart) + } + if _, ok := chartValAxNumFmtFormatCode[formatSet.Type]; !ok { + return errors.New("unsupported chart type " + formatSet.Type) + } + cs := xlsxChartsheet{ + SheetViews: []*xlsxChartsheetViews{{ + SheetView: []*xlsxChartsheetView{{ZoomScaleAttr: 100, ZoomToFitAttr: true}}}, + }, + } + wb := f.workbookReader() + sheetID := 0 + for _, v := range wb.Sheets.Sheet { + if v.SheetID > sheetID { + sheetID = v.SheetID + } + } + sheetID++ + path := "xl/chartsheets/sheet" + strconv.Itoa(sheetID) + ".xml" + f.sheetMap[trimSheetName(sheet)] = path + f.Sheet[path] = nil + drawingID := f.countDrawings() + 1 + chartID := f.countCharts() + 1 + drawingXML := "xl/drawings/drawing" + strconv.Itoa(drawingID) + ".xml" + drawingID, drawingXML = f.prepareChartSheetDrawing(&cs, drawingID, sheet, drawingXML) + drawingRels := "xl/drawings/_rels/drawing" + strconv.Itoa(drawingID) + ".xml.rels" + drawingRID := f.addRels(drawingRels, SourceRelationshipChart, "../charts/chart"+strconv.Itoa(chartID)+".xml", "") + err = f.addSheetDrawingChart(sheet, drawingXML, formatSet.Dimension.Width, formatSet.Dimension.Height, drawingRID, &formatSet.Format) + if err != nil { + return err + } + f.addChart(formatSet, comboCharts) + f.addContentTypePart(chartID, "chart") + f.addContentTypePart(sheetID, "chartsheet") + f.addContentTypePart(drawingID, "drawings") + // Update xl/_rels/workbook.xml.rels + rID := f.addRels("xl/_rels/workbook.xml.rels", SourceRelationshipChartsheet, fmt.Sprintf("chartsheets/sheet%d.xml", sheetID), "") + // Update xl/workbook.xml + f.setWorkbook(sheet, sheetID, rID) + v, _ := xml.Marshal(cs) + f.saveFileList(path, replaceRelationshipsBytes(replaceWorkSheetsRelationshipsNameSpaceBytes(v))) + return err +} + // DeleteChart provides a function to delete chart in XLSX by given worksheet // and cell name. func (f *File) DeleteChart(sheet, cell string) (err error) { -- cgit v1.2.1 From 3f89c6e9799c9c82af1305f080416c53d19e64c1 Mon Sep 17 00:00:00 2001 From: xuri Date: Sun, 29 Mar 2020 18:44:24 +0800 Subject: remove ineffectual variable assignments and simplify code --- chart.go | 72 +++++++++++++++++++++++++++++----------------------------------- 1 file changed, 33 insertions(+), 39 deletions(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index df196e9..cae833d 100644 --- a/chart.go +++ b/chart.go @@ -730,28 +730,14 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // } // func (f *File) AddChart(sheet, cell, format string, combo ...string) error { - formatSet, err := parseFormatChartSet(format) - if err != nil { - return err - } - comboCharts := []*formatChart{} - for _, comboFormat := range combo { - comboChart, err := parseFormatChartSet(comboFormat) - if err != nil { - return err - } - if _, ok := chartValAxNumFmtFormatCode[comboChart.Type]; !ok { - return errors.New("unsupported chart type " + comboChart.Type) - } - comboCharts = append(comboCharts, comboChart) - } // Read sheet data. xlsx, err := f.workSheetReader(sheet) if err != nil { return err } - if _, ok := chartValAxNumFmtFormatCode[formatSet.Type]; !ok { - return errors.New("unsupported chart type " + formatSet.Type) + formatSet, comboCharts, err := f.getFormatChart(format, combo) + if err != nil { + return err } // Add first picture for given sheet, create xl/drawings/ and xl/drawings/_rels/ folder. drawingID := f.countDrawings() + 1 @@ -777,31 +763,18 @@ func (f *File) AddChart(sheet, cell, format string, combo ...string) error { func (f *File) AddChartSheet(sheet, format string, combo ...string) error { // Check if the worksheet already exists if f.GetSheetIndex(sheet) != 0 { - return errors.New("already existing name worksheet") + return errors.New("the same name worksheet already exists") } - formatSet, err := parseFormatChartSet(format) + formatSet, comboCharts, err := f.getFormatChart(format, combo) if err != nil { return err } - comboCharts := []*formatChart{} - for _, comboFormat := range combo { - comboChart, err := parseFormatChartSet(comboFormat) - if err != nil { - return err - } - if _, ok := chartValAxNumFmtFormatCode[comboChart.Type]; !ok { - return errors.New("unsupported chart type " + comboChart.Type) - } - comboCharts = append(comboCharts, comboChart) - } - if _, ok := chartValAxNumFmtFormatCode[formatSet.Type]; !ok { - return errors.New("unsupported chart type " + formatSet.Type) - } cs := xlsxChartsheet{ SheetViews: []*xlsxChartsheetViews{{ SheetView: []*xlsxChartsheetView{{ZoomScaleAttr: 100, ZoomToFitAttr: true}}}, }, } + f.SheetCount++ wb := f.workbookReader() sheetID := 0 for _, v := range wb.Sheets.Sheet { @@ -819,10 +792,7 @@ func (f *File) AddChartSheet(sheet, format string, combo ...string) error { drawingID, drawingXML = f.prepareChartSheetDrawing(&cs, drawingID, sheet, drawingXML) drawingRels := "xl/drawings/_rels/drawing" + strconv.Itoa(drawingID) + ".xml.rels" drawingRID := f.addRels(drawingRels, SourceRelationshipChart, "../charts/chart"+strconv.Itoa(chartID)+".xml", "") - err = f.addSheetDrawingChart(sheet, drawingXML, formatSet.Dimension.Width, formatSet.Dimension.Height, drawingRID, &formatSet.Format) - if err != nil { - return err - } + f.addSheetDrawingChart(drawingXML, drawingRID, &formatSet.Format) f.addChart(formatSet, comboCharts) f.addContentTypePart(chartID, "chart") f.addContentTypePart(sheetID, "chartsheet") @@ -831,11 +801,35 @@ func (f *File) AddChartSheet(sheet, format string, combo ...string) error { rID := f.addRels("xl/_rels/workbook.xml.rels", SourceRelationshipChartsheet, fmt.Sprintf("chartsheets/sheet%d.xml", sheetID), "") // Update xl/workbook.xml f.setWorkbook(sheet, sheetID, rID) - v, _ := xml.Marshal(cs) - f.saveFileList(path, replaceRelationshipsBytes(replaceWorkSheetsRelationshipsNameSpaceBytes(v))) + chartsheet, _ := xml.Marshal(cs) + f.saveFileList(path, replaceRelationshipsBytes(replaceRelationshipsNameSpaceBytes(chartsheet))) return err } +// getFormatChart provides a function to check format set of the chart and +// create chart format. +func (f *File) getFormatChart(format string, combo []string) (*formatChart, []*formatChart, error) { + comboCharts := []*formatChart{} + formatSet, err := parseFormatChartSet(format) + if err != nil { + return formatSet, comboCharts, err + } + for _, comboFormat := range combo { + comboChart, err := parseFormatChartSet(comboFormat) + if err != nil { + return formatSet, comboCharts, err + } + if _, ok := chartValAxNumFmtFormatCode[comboChart.Type]; !ok { + return formatSet, comboCharts, errors.New("unsupported chart type " + comboChart.Type) + } + comboCharts = append(comboCharts, comboChart) + } + if _, ok := chartValAxNumFmtFormatCode[formatSet.Type]; !ok { + return formatSet, comboCharts, errors.New("unsupported chart type " + formatSet.Type) + } + return formatSet, comboCharts, err +} + // DeleteChart provides a function to delete chart in XLSX by given worksheet // and cell name. func (f *File) DeleteChart(sheet, cell string) (err error) { -- cgit v1.2.1 From 3ce4b91be96589847823b6c1b6c123ba7880310f Mon Sep 17 00:00:00 2001 From: xuri Date: Tue, 31 Mar 2020 00:02:00 +0800 Subject: Resolve #345, fix missing comments by GetComments --- chart.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index cae833d..2c802ee 100644 --- a/chart.go +++ b/chart.go @@ -789,7 +789,7 @@ func (f *File) AddChartSheet(sheet, format string, combo ...string) error { drawingID := f.countDrawings() + 1 chartID := f.countCharts() + 1 drawingXML := "xl/drawings/drawing" + strconv.Itoa(drawingID) + ".xml" - drawingID, drawingXML = f.prepareChartSheetDrawing(&cs, drawingID, sheet, drawingXML) + f.prepareChartSheetDrawing(&cs, drawingID, sheet) drawingRels := "xl/drawings/_rels/drawing" + strconv.Itoa(drawingID) + ".xml.rels" drawingRID := f.addRels(drawingRels, SourceRelationshipChart, "../charts/chart"+strconv.Itoa(chartID)+".xml", "") f.addSheetDrawingChart(drawingXML, drawingRID, &formatSet.Format) -- cgit v1.2.1 From 1fe660df648422a53eef0c735657cb2f5237ef7b Mon Sep 17 00:00:00 2001 From: xuri Date: Thu, 23 Apr 2020 02:01:14 +0800 Subject: - Resolve #485 use sheet index instead of ID - added 3 internal function: getSheetID, getActiveSheetID, getSheetNameByID --- chart.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'chart.go') diff --git a/chart.go b/chart.go index 2c802ee..8fa0b5d 100644 --- a/chart.go +++ b/chart.go @@ -762,7 +762,7 @@ func (f *File) AddChart(sheet, cell, format string, combo ...string) error { // a chart. func (f *File) AddChartSheet(sheet, format string, combo ...string) error { // Check if the worksheet already exists - if f.GetSheetIndex(sheet) != 0 { + if f.GetSheetIndex(sheet) != -1 { return errors.New("the same name worksheet already exists") } formatSet, comboCharts, err := f.getFormatChart(format, combo) -- cgit v1.2.1