Skip to content

Commit 3ca60f8

Browse files
committed
This closes #2033, support set gap width and overlap for column and bar chart
- Add new fields GapWidth and Overlap in the Chart data type - Update unit tests - Update dependencies modules
1 parent c936188 commit 3ca60f8

7 files changed

+97
-23
lines changed

chart.go

+45-1
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,42 @@ var (
486486
Line: "standard",
487487
Line3D: "standard",
488488
}
489+
barColChartTypes = []ChartType{
490+
Bar,
491+
BarStacked,
492+
BarPercentStacked,
493+
Bar3DClustered,
494+
Bar3DStacked,
495+
Bar3DPercentStacked,
496+
Bar3DConeClustered,
497+
Bar3DConeStacked,
498+
Bar3DConePercentStacked,
499+
Bar3DPyramidClustered,
500+
Bar3DPyramidStacked,
501+
Bar3DPyramidPercentStacked,
502+
Bar3DCylinderClustered,
503+
Bar3DCylinderStacked,
504+
Bar3DCylinderPercentStacked,
505+
Col,
506+
ColStacked,
507+
ColPercentStacked,
508+
Col3D,
509+
Col3DClustered,
510+
Col3DStacked,
511+
Col3DPercentStacked,
512+
Col3DCone,
513+
Col3DConeStacked,
514+
Col3DConeClustered,
515+
Col3DConePercentStacked,
516+
Col3DPyramid,
517+
Col3DPyramidClustered,
518+
Col3DPyramidStacked,
519+
Col3DPyramidPercentStacked,
520+
Col3DCylinder,
521+
Col3DCylinderClustered,
522+
Col3DCylinderStacked,
523+
Col3DCylinderPercentStacked,
524+
}
489525
orientation = map[bool]string{
490526
true: "maxMin",
491527
false: "minMax",
@@ -904,7 +940,7 @@ func (opts *Chart) parseTitle() {
904940
// TextRotation
905941
// Vertical
906942
//
907-
// The value of 'TextRotation' that can be set from -90 to 90:
943+
// The value of 'TextRotation' that can be set from -90 to 90.
908944
//
909945
// The value of 'Vertical' that can be set are:
910946
//
@@ -949,6 +985,14 @@ func (opts *Chart) parseTitle() {
949985
// 'HoleSize' property. The 'HoleSize' property is optional. The default width
950986
// is 75, and the value should be great than 0 and less or equal than 90.
951987
//
988+
// Set the gap with of the column and bar series chart by 'GapWidth' property.
989+
// The 'GapWidth' property is optional. The default width is 150, and the value
990+
// should be great or equal than 0 and less or equal than 500.
991+
//
992+
// Set series overlap of the column and bar series chart by 'Overlap' property.
993+
// The 'Overlap' property is optional. The default width is 0, and the value
994+
// should be great or equal than -100 and less or equal than 100.
995+
//
952996
// combo: Specifies the create a chart that combines two or more chart types in
953997
// a single chart. For example, create a clustered column - line chart with
954998
// data Sheet1!$E$1:$L$15:

chart_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ func TestAddChart(t *testing.T) {
215215
opts *Chart
216216
}{
217217
{sheetName: "Sheet1", cell: "P1", opts: &Chart{Type: Col, Series: series, Format: format, Legend: ChartLegend{Position: "none", ShowLegendKey: true}, Title: []RichTextRun{{Text: "2D Column Chart"}}, PlotArea: plotArea, Border: ChartLine{Type: ChartLineNone}, ShowBlanksAs: "zero", XAxis: ChartAxis{Font: Font{Bold: true, Italic: true, Underline: "dbl", Family: "Times New Roman", Size: 15, Strike: true, Color: "000000"}, Title: []RichTextRun{{Text: "Primary Horizontal Axis Title"}}}, YAxis: ChartAxis{Font: Font{Bold: false, Italic: false, Underline: "sng", Color: "777777"}, Title: []RichTextRun{{Text: "Primary Vertical Axis Title", Font: &Font{Color: "777777", Bold: true, Italic: true, Size: 12}}}}}},
218-
{sheetName: "Sheet1", cell: "X1", opts: &Chart{Type: ColStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "2D Stacked Column Chart"}}, PlotArea: plotArea, Fill: Fill{Type: "pattern", Pattern: 1}, Border: ChartLine{Type: ChartLineAutomatic}, ShowBlanksAs: "zero"}},
218+
{sheetName: "Sheet1", cell: "X1", opts: &Chart{Type: ColStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "2D Stacked Column Chart"}}, PlotArea: plotArea, Fill: Fill{Type: "pattern", Pattern: 1}, Border: ChartLine{Type: ChartLineAutomatic}, ShowBlanksAs: "zero", GapWidth: uintPtr(10), Overlap: intPtr(100)}},
219219
{sheetName: "Sheet1", cell: "P16", opts: &Chart{Type: ColPercentStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "100% Stacked Column Chart"}}, PlotArea: plotArea, Fill: Fill{Type: "pattern", Color: []string{"EEEEEE"}, Pattern: 1}, Border: ChartLine{Type: ChartLineSolid, Width: 2}, ShowBlanksAs: "zero", XAxis: ChartAxis{Alignment: Alignment{Vertical: "wordArtVertRtl", TextRotation: 0}}}},
220220
{sheetName: "Sheet1", cell: "X16", opts: &Chart{Type: Col3DClustered, Series: series, Format: format, Legend: ChartLegend{Position: "bottom", ShowLegendKey: false}, Title: []RichTextRun{{Text: "3D Clustered Column Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
221221
{sheetName: "Sheet1", cell: "P30", opts: &Chart{Type: Col3DStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "3D Stacked Column Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero", XAxis: ChartAxis{Alignment: Alignment{Vertical: "vert", TextRotation: 0}}}},

drawing.go

+35-8
Original file line numberDiff line numberDiff line change
@@ -210,20 +210,18 @@ func (f *File) drawBaseChart(pa *cPlotArea, opts *Chart) *cPlotArea {
210210
VaryColors: &attrValBool{
211211
Val: opts.VaryColors,
212212
},
213-
Ser: f.drawChartSeries(opts),
214-
Shape: f.drawChartShape(opts),
215-
DLbls: f.drawChartDLbls(opts),
216-
AxID: f.genAxID(opts),
217-
Overlap: &attrValInt{Val: intPtr(100)},
213+
Ser: f.drawChartSeries(opts),
214+
Shape: f.drawChartShape(opts),
215+
DLbls: f.drawChartDLbls(opts),
216+
GapWidth: f.drawChartGapWidth(opts),
217+
AxID: f.genAxID(opts),
218+
Overlap: f.drawChartOverlap(opts),
218219
},
219220
}
220221
var ok bool
221222
if *c[0].BarDir.Val, ok = plotAreaChartBarDir[opts.Type]; !ok {
222223
c[0].BarDir = nil
223224
}
224-
if *c[0].Overlap.Val, ok = plotAreaChartOverlap[opts.Type]; !ok {
225-
c[0].Overlap = nil
226-
}
227225
catAx := f.drawPlotAreaCatAx(pa, opts)
228226
valAx := f.drawPlotAreaValAx(pa, opts)
229227
charts := map[ChartType]*cPlotArea{
@@ -697,6 +695,35 @@ func (f *File) drawBubbleChart(pa *cPlotArea, opts *Chart) *cPlotArea {
697695
return plotArea
698696
}
699697

698+
// drawChartGapWidth provides a function to draw the c:gapWidth element by given
699+
// format sets.
700+
func (f *File) drawChartGapWidth(opts *Chart) *attrValInt {
701+
for _, t := range barColChartTypes {
702+
if t == opts.Type && opts.GapWidth != nil && *opts.GapWidth != 150 && *opts.GapWidth <= 500 {
703+
return &attrValInt{intPtr(int(*opts.GapWidth))}
704+
}
705+
}
706+
return nil
707+
}
708+
709+
// drawChartOverlap provides a function to draw the c:overlap element by given
710+
// format sets.
711+
func (f *File) drawChartOverlap(opts *Chart) *attrValInt {
712+
var val *attrValInt
713+
if _, ok := plotAreaChartOverlap[opts.Type]; ok {
714+
val = &attrValInt{intPtr(100)}
715+
}
716+
if opts.Overlap != nil && -100 <= *opts.Overlap && *opts.Overlap <= 100 {
717+
val = &attrValInt{intPtr(*opts.Overlap)}
718+
}
719+
for _, t := range barColChartTypes {
720+
if t == opts.Type {
721+
return val
722+
}
723+
}
724+
return nil
725+
}
726+
700727
// drawChartShape provides a function to draw the c:shape element by given
701728
// format sets.
702729
func (f *File) drawChartShape(opts *Chart) *attrValString {

go.mod

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ go 1.18
55
require (
66
github.com/richardlehane/mscfb v1.0.4
77
github.com/stretchr/testify v1.9.0
8-
github.com/tiendc/go-deepcopy v1.1.0
8+
github.com/tiendc/go-deepcopy v1.2.0
99
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d
1010
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7
11-
golang.org/x/crypto v0.29.0
11+
golang.org/x/crypto v0.30.0
1212
golang.org/x/image v0.18.0
13-
golang.org/x/net v0.31.0
14-
golang.org/x/text v0.20.0
13+
golang.org/x/net v0.32.0
14+
golang.org/x/text v0.21.0
1515
)
1616

1717
require (

go.sum

+8-8
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,20 @@ github.com/richardlehane/msoleps v1.0.4 h1:WuESlvhX3gH2IHcd8UqyCuFY5yiq/GR/yqaSM
99
github.com/richardlehane/msoleps v1.0.4/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
1010
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
1111
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
12-
github.com/tiendc/go-deepcopy v1.1.0 h1:rBHhm5vg7WYnGLwktbQouodWjBXDoStOL4S7v/K8S4A=
13-
github.com/tiendc/go-deepcopy v1.1.0/go.mod h1:toXoeQoUqXOOS/X4sKuiAoSk6elIdqc0pN7MTgOOo2I=
12+
github.com/tiendc/go-deepcopy v1.2.0 h1:6vCCs+qdLQHzFqY1fcPirsAWOmrLbuccilfp8UzD1Qo=
13+
github.com/tiendc/go-deepcopy v1.2.0/go.mod h1:toXoeQoUqXOOS/X4sKuiAoSk6elIdqc0pN7MTgOOo2I=
1414
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d h1:llb0neMWDQe87IzJLS4Ci7psK/lVsjIS2otl+1WyRyY=
1515
github.com/xuri/efp v0.0.0-20240408161823-9ad904a10d6d/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
1616
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7 h1:hPVCafDV85blFTabnqKgNhDCkJX25eik94Si9cTER4A=
1717
github.com/xuri/nfp v0.0.0-20240318013403-ab9948c2c4a7/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
18-
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
19-
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
18+
golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY=
19+
golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
2020
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
2121
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
22-
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
23-
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
24-
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
25-
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
22+
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
23+
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
24+
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
25+
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
2626
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
2727
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
2828
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

xmlChart.go

+3
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ type cCharts struct {
336336
SplitPos *attrValInt `xml:"splitPos"`
337337
SerLines *attrValString `xml:"serLines"`
338338
DLbls *cDLbls `xml:"dLbls"`
339+
GapWidth *attrValInt `xml:"gapWidth"`
339340
Shape *attrValString `xml:"shape"`
340341
HoleSize *attrValInt `xml:"holeSize"`
341342
Smooth *attrValBool `xml:"smooth"`
@@ -584,6 +585,8 @@ type Chart struct {
584585
ShowBlanksAs string
585586
BubbleSize int
586587
HoleSize int
588+
GapWidth *uint
589+
Overlap *int
587590
order int
588591
}
589592

xmlWorksheet.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1007,7 +1007,7 @@ type PageLayoutOptions struct {
10071007
// BlackAndWhite specified print black and white.
10081008
BlackAndWhite *bool
10091009
// PageOrder specifies the ordering of multiple pages. Values
1010-
// accepted: overThenDown, downThenOver
1010+
// accepted: overThenDown and downThenOver
10111011
PageOrder *string
10121012
}
10131013

0 commit comments

Comments
 (0)