Skip to content

Commit

Permalink
This closes #1706 and closes #1708
Browse files Browse the repository at this point in the history
- Add export ChartLineType enumeration to specify the chart line type
- Add new Border field in the Chart type to set the chart area border
- Add new Type field in the ChartLine type to set the line type
- Fix some format missing on get style definition
- Update the unit tests
  • Loading branch information
xuri committed Nov 2, 2023
1 parent 7291e78 commit 4e936da
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 47 deletions.
32 changes: 25 additions & 7 deletions chart.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@ const (
Bubble3D
)

// ChartLineType is the type of supported chart line types.
type ChartLineType byte

// This section defines the currently supported chart line types enumeration.
const (
ChartLineSolid ChartLineType = iota
ChartLineNone
ChartLineAutomatic
)

// This section defines the default value of chart properties.
var (
chartView3DRotX = map[ChartType]int{
Expand Down Expand Up @@ -507,6 +517,21 @@ func parseChartOptions(opts *Chart) (*Chart, error) {
if opts.Legend.Position == "" {
opts.Legend.Position = defaultChartLegendPosition
}
opts.parseTitle()
if opts.VaryColors == nil {
opts.VaryColors = boolPtr(true)
}
if opts.Border.Width == 0 {
opts.Border.Width = 0.75
}
if opts.ShowBlanksAs == "" {
opts.ShowBlanksAs = defaultChartShowBlanksAs
}
return opts, nil
}

// parseTitle parse the title settings of the chart with default value.
func (opts *Chart) parseTitle() {
for i := range opts.Title {
if opts.Title[i].Font == nil {
opts.Title[i].Font = &Font{}
Expand All @@ -518,13 +543,6 @@ func parseChartOptions(opts *Chart) (*Chart, error) {
opts.Title[i].Font.Size = 14
}
}
if opts.VaryColors == nil {
opts.VaryColors = boolPtr(true)
}
if opts.ShowBlanksAs == "" {
opts.ShowBlanksAs = defaultChartShowBlanksAs
}
return opts, nil
}

// AddChart provides the method to add chart in a sheet by given chart format
Expand Down
6 changes: 3 additions & 3 deletions chart_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,9 @@ func TestAddChart(t *testing.T) {
sheetName, cell string
opts *Chart
}{
{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, ShowBlanksAs: "zero", XAxis: ChartAxis{Font: Font{Bold: true, Italic: true, Underline: "dbl", 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}}}}}},
{sheetName: "Sheet1", cell: "X1", opts: &Chart{Type: ColStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "2D Stacked Column Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
{sheetName: "Sheet1", cell: "P16", opts: &Chart{Type: ColPercentStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "100% Stacked Column Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
{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", 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}}}}}},
{sheetName: "Sheet1", cell: "X1", opts: &Chart{Type: ColStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "2D Stacked Column Chart"}}, PlotArea: plotArea, Border: ChartLine{Type: ChartLineAutomatic}, ShowBlanksAs: "zero"}},
{sheetName: "Sheet1", cell: "P16", opts: &Chart{Type: ColPercentStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "100% Stacked Column Chart"}}, PlotArea: plotArea, Border: ChartLine{Type: ChartLineSolid, Width: 2}, ShowBlanksAs: "zero"}},
{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"}},
{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"}},
{sheetName: "Sheet1", cell: "X30", opts: &Chart{Type: Col3DPercentStacked, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "3D 100% Stacked Column Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}},
Expand Down
50 changes: 32 additions & 18 deletions drawing.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,23 +94,7 @@ func (f *File) addChart(opts *Chart, comboCharts []*Chart) {
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),
},
},
},
},
Ln: f.drawChartLn(&opts.Border),
},
PrintSettings: &cPrintSettings{
PageMargins: &cPageMargins{
Expand Down Expand Up @@ -756,7 +740,7 @@ func (f *File) drawChartSeriesSpPr(i int, opts *Chart) *cSpPr {
spPrScatter := &cSpPr{
Ln: &aLn{
W: 25400,
NoFill: " ",
NoFill: &attrValString{},
},
}
spPrLine := &cSpPr{
Expand Down Expand Up @@ -1237,6 +1221,36 @@ func (f *File) drawPlotAreaTxPr(opts *ChartAxis) *cTxPr {
return cTxPr
}

// drawChartLn provides a function to draw the a:ln element.
func (f *File) drawChartLn(opts *ChartLine) *aLn {
ln := &aLn{
W: f.ptToEMUs(opts.Width),
Cap: "flat",
Cmpd: "sng",
Algn: "ctr",
}
switch opts.Type {
case ChartLineSolid:
ln.SolidFill = &aSolidFill{
SchemeClr: &aSchemeClr{
Val: "tx1",
LumMod: &attrValInt{
Val: intPtr(15000),
},
LumOff: &attrValInt{
Val: intPtr(85000),
},
},
}
return ln
case ChartLineNone:
ln.NoFill = &attrValString{}
return ln
default:
return nil
}
}

// 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
Expand Down
14 changes: 8 additions & 6 deletions styles.go
Original file line number Diff line number Diff line change
Expand Up @@ -1201,25 +1201,25 @@ var (
// extract style definition by given style.
extractStyleCondFuncs = map[string]func(xlsxXf, *xlsxStyleSheet) bool{
"fill": func(xf xlsxXf, s *xlsxStyleSheet) bool {
return xf.ApplyFill != nil && *xf.ApplyFill &&
return (xf.ApplyFill == nil || (xf.ApplyFill != nil && *xf.ApplyFill)) &&
xf.FillID != nil && s.Fills != nil &&
*xf.FillID < len(s.Fills.Fill)
},
"border": func(xf xlsxXf, s *xlsxStyleSheet) bool {
return xf.ApplyBorder != nil && *xf.ApplyBorder &&
return (xf.ApplyBorder == nil || (xf.ApplyBorder != nil && *xf.ApplyBorder)) &&
xf.BorderID != nil && s.Borders != nil &&
*xf.BorderID < len(s.Borders.Border)
},
"font": func(xf xlsxXf, s *xlsxStyleSheet) bool {
return xf.ApplyFont != nil && *xf.ApplyFont &&
return (xf.ApplyFont == nil || (xf.ApplyFont != nil && *xf.ApplyFont)) &&
xf.FontID != nil && s.Fonts != nil &&
*xf.FontID < len(s.Fonts.Font)
},
"alignment": func(xf xlsxXf, s *xlsxStyleSheet) bool {
return xf.ApplyAlignment != nil && *xf.ApplyAlignment
return xf.ApplyAlignment == nil || (xf.ApplyAlignment != nil && *xf.ApplyAlignment)
},
"protection": func(xf xlsxXf, s *xlsxStyleSheet) bool {
return xf.ApplyProtection != nil && *xf.ApplyProtection
return xf.ApplyProtection == nil || (xf.ApplyProtection != nil && *xf.ApplyProtection)
},
}
// drawContFmtFunc defines functions to create conditional formats.
Expand Down Expand Up @@ -1366,7 +1366,9 @@ func (f *File) extractFont(fnt *xlsxFont, s *xlsxStyleSheet, style *Style) {
font.Italic = fnt.I.Value()
}
if fnt.U != nil {
font.Underline = fnt.U.Value()
if font.Underline = fnt.U.Value(); font.Underline == "" {
font.Underline = "single"
}
}
if fnt.Name != nil {
font.Family = fnt.Name.Value()
Expand Down
6 changes: 6 additions & 0 deletions styles_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,12 @@ func TestGetStyle(t *testing.T) {
}
assert.Equal(t, "012345", f.getThemeColor(&xlsxColor{Indexed: 0}))

f.Styles.Fonts.Font[0].U = &attrValString{}
f.Styles.CellXfs.Xf[0].FontID = intPtr(0)
style, err = f.GetStyle(styleID)
assert.NoError(t, err)
assert.Equal(t, "single", style.Font.Underline)

// Test get style with invalid style index
style, err = f.GetStyle(-1)
assert.Nil(t, style)
Expand Down
7 changes: 1 addition & 6 deletions xmlCalcChain.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,11 @@

package excelize

import (
"encoding/xml"
"sync"
)
import "encoding/xml"

// xlsxCalcChain directly maps the calcChain element. This element represents
// the root of the calculation chain.
type xlsxCalcChain struct {
mu sync.Mutex
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/spreadsheetml/2006/main calcChain"`
C []xlsxCalcChainC `xml:"c"`
}
Expand Down Expand Up @@ -91,7 +87,6 @@ type xlsxCalcChainC struct {
// xlsxVolTypes maps the volatileDependencies part provides a cache of data that
// supports Real Time Data (RTD) and CUBE functions in the workbook.
type xlsxVolTypes struct {
mu sync.Mutex
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/spreadsheetml/2006/main volTypes"`
VolType []xlsxVolType `xml:"volType"`
ExtLst *xlsxExtLst `xml:"extLst"`
Expand Down
16 changes: 9 additions & 7 deletions xmlChart.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,13 +248,13 @@ type aContourClr struct {
// shapes and text. The line allows for the specifying of many different types
// of outlines including even line dashes and bevels.
type aLn struct {
Algn string `xml:"algn,attr,omitempty"`
Cap string `xml:"cap,attr,omitempty"`
Cmpd string `xml:"cmpd,attr,omitempty"`
W int `xml:"w,attr,omitempty"`
NoFill string `xml:"a:noFill,omitempty"`
Round string `xml:"a:round,omitempty"`
SolidFill *aSolidFill `xml:"a:solidFill"`
Algn string `xml:"algn,attr,omitempty"`
Cap string `xml:"cap,attr,omitempty"`
Cmpd string `xml:"cmpd,attr,omitempty"`
W int `xml:"w,attr,omitempty"`
NoFill *attrValString `xml:"a:noFill"`
Round string `xml:"a:round,omitempty"`
SolidFill *aSolidFill `xml:"a:solidFill"`
}

// cTxPr (Text Properties) directly maps the txPr element. This element
Expand Down Expand Up @@ -575,6 +575,7 @@ type Chart struct {
XAxis ChartAxis
YAxis ChartAxis
PlotArea ChartPlotArea
Border ChartLine
ShowBlanksAs string
HoleSize int
order int
Expand All @@ -594,6 +595,7 @@ type ChartMarker struct {

// ChartLine directly maps the format settings of the chart line.
type ChartLine struct {
Type ChartLineType
Smooth bool
Width float64
}
Expand Down

0 comments on commit 4e936da

Please sign in to comment.