Skip to content

Commit 3d02726

Browse files
committed
This closes qax-os#320, support custom chart axis font style
1 parent 7363c1e commit 3d02726

9 files changed

+78
-76
lines changed

chart.go

+16-3
Original file line numberDiff line numberDiff line change
@@ -750,22 +750,24 @@ func parseChartOptions(opts string) (*chartOptions, error) {
750750
// reverse_order
751751
// maximum
752752
// minimum
753+
// number_font
753754
//
754755
// The properties of y_axis that can be set are:
755756
//
756757
// none
757758
// major_grid_lines
758759
// minor_grid_lines
759-
// major_unit
760+
// tick_label_skip
760761
// reverse_order
761762
// maximum
762763
// minimum
764+
// number_font
763765
//
764766
// none: Disable axes.
765767
//
766-
// major_grid_lines: Specifies major gridlines.
768+
// major_grid_lines: Specifies major grid lines.
767769
//
768-
// minor_grid_lines: Specifies minor gridlines.
770+
// minor_grid_lines: Specifies minor grid lines.
769771
//
770772
// 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.
771773
//
@@ -777,6 +779,17 @@ func parseChartOptions(opts string) (*chartOptions, error) {
777779
//
778780
// minimum: Specifies that the fixed minimum, 0 is auto. The minimum property is optional. The default value is auto.
779781
//
782+
// number_font: Specifies that the font of the horizontal and vertical axis. The properties of number_font that can be set are:
783+
//
784+
// bold
785+
// italic
786+
// underline
787+
// family
788+
// size
789+
// strike
790+
// color
791+
// vertAlign
792+
//
780793
// Set chart size by dimension property. The dimension property is optional. The default width is 480, and height is 290.
781794
//
782795
// combo: Specifies the create a chart that combines two or more chart types

chart_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ func TestAddChart(t *testing.T) {
116116
// Test add chart on not exists worksheet.
117117
assert.EqualError(t, f.AddChart("SheetN", "P1", "{}"), "sheet SheetN does not exist")
118118

119-
assert.NoError(t, f.AddChart("Sheet1", "P1", `{"type":"col","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"},{"name":"Sheet1!$A$33","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$33:$D$33"},{"name":"Sheet1!$A$34","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$34:$D$34"},{"name":"Sheet1!$A$35","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$35:$D$35"},{"name":"Sheet1!$A$36","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$36:$D$36"},{"name":"Sheet1!$A$37","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$37:$D$37"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"none":true,"show_legend_key":true},"title":{"name":"2D 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"}`))
119+
assert.NoError(t, f.AddChart("Sheet1", "P1", `{"type":"col","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"},{"name":"Sheet1!$A$33","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$33:$D$33"},{"name":"Sheet1!$A$34","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$34:$D$34"},{"name":"Sheet1!$A$35","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$35:$D$35"},{"name":"Sheet1!$A$36","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$36:$D$36"},{"name":"Sheet1!$A$37","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$37:$D$37"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"none":true,"show_legend_key":true},"title":{"name":"2D 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":{"number_font":{"bold":true,"italic":true,"underline":"dbl","color":"#000000"}},"y_axis":{"number_font":{"bold":false,"italic":false,"underline":"sng","color":"#777777"}}}`))
120120
assert.NoError(t, f.AddChart("Sheet1", "X1", `{"type":"colStacked","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"},{"name":"Sheet1!$A$33","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$33:$D$33"},{"name":"Sheet1!$A$34","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$34:$D$34"},{"name":"Sheet1!$A$35","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$35:$D$35"},{"name":"Sheet1!$A$36","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$36:$D$36"},{"name":"Sheet1!$A$37","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$37:$D$37"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"2D Stacked 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"}`))
121121
assert.NoError(t, f.AddChart("Sheet1", "P16", `{"type":"colPercentStacked","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"},{"name":"Sheet1!$A$33","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$33:$D$33"},{"name":"Sheet1!$A$34","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$34:$D$34"},{"name":"Sheet1!$A$35","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$35:$D$35"},{"name":"Sheet1!$A$36","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$36:$D$36"},{"name":"Sheet1!$A$37","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$37:$D$37"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"left","show_legend_key":false},"title":{"name":"100% Stacked 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"}`))
122122
assert.NoError(t, f.AddChart("Sheet1", "X16", `{"type":"col3DClustered","series":[{"name":"Sheet1!$A$30","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$30:$D$30"},{"name":"Sheet1!$A$31","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$31:$D$31"},{"name":"Sheet1!$A$32","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$32:$D$32"},{"name":"Sheet1!$A$33","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$33:$D$33"},{"name":"Sheet1!$A$34","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$34:$D$34"},{"name":"Sheet1!$A$35","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$35:$D$35"},{"name":"Sheet1!$A$36","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$36:$D$36"},{"name":"Sheet1!$A$37","categories":"Sheet1!$B$29:$D$29","values":"Sheet1!$B$37:$D$37"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"bottom","show_legend_key":false},"title":{"name":"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"}`))

drawing.go

+17-5
Original file line numberDiff line numberDiff line change
@@ -1017,7 +1017,7 @@ func (f *File) drawPlotAreaCatAx(opts *chartOptions) []*cAxs {
10171017
MinorTickMark: &attrValString{Val: stringPtr("none")},
10181018
TickLblPos: &attrValString{Val: stringPtr("nextTo")},
10191019
SpPr: f.drawPlotAreaSpPr(),
1020-
TxPr: f.drawPlotAreaTxPr(),
1020+
TxPr: f.drawPlotAreaTxPr(&opts.YAxis),
10211021
CrossAx: &attrValInt{Val: intPtr(753999904)},
10221022
Crosses: &attrValString{Val: stringPtr("autoZero")},
10231023
Auto: &attrValBool{Val: boolPtr(true)},
@@ -1071,7 +1071,7 @@ func (f *File) drawPlotAreaValAx(opts *chartOptions) []*cAxs {
10711071
MinorTickMark: &attrValString{Val: stringPtr("none")},
10721072
TickLblPos: &attrValString{Val: stringPtr("nextTo")},
10731073
SpPr: f.drawPlotAreaSpPr(),
1074-
TxPr: f.drawPlotAreaTxPr(),
1074+
TxPr: f.drawPlotAreaTxPr(&opts.XAxis),
10751075
CrossAx: &attrValInt{Val: intPtr(754001152)},
10761076
Crosses: &attrValString{Val: stringPtr("autoZero")},
10771077
CrossBetween: &attrValString{Val: stringPtr(chartValAxCrossBetween[opts.Type])},
@@ -1114,7 +1114,7 @@ func (f *File) drawPlotAreaSerAx(opts *chartOptions) []*cAxs {
11141114
AxPos: &attrValString{Val: stringPtr(catAxPos[opts.XAxis.ReverseOrder])},
11151115
TickLblPos: &attrValString{Val: stringPtr("nextTo")},
11161116
SpPr: f.drawPlotAreaSpPr(),
1117-
TxPr: f.drawPlotAreaTxPr(),
1117+
TxPr: f.drawPlotAreaTxPr(nil),
11181118
CrossAx: &attrValInt{Val: intPtr(753999904)},
11191119
},
11201120
}
@@ -1140,8 +1140,8 @@ func (f *File) drawPlotAreaSpPr() *cSpPr {
11401140
}
11411141

11421142
// drawPlotAreaTxPr provides a function to draw the c:txPr element.
1143-
func (f *File) drawPlotAreaTxPr() *cTxPr {
1144-
return &cTxPr{
1143+
func (f *File) drawPlotAreaTxPr(opts *chartAxisOptions) *cTxPr {
1144+
cTxPr := &cTxPr{
11451145
BodyPr: aBodyPr{
11461146
Rot: -60000000,
11471147
SpcFirstLastPara: true,
@@ -1176,6 +1176,18 @@ func (f *File) drawPlotAreaTxPr() *cTxPr {
11761176
EndParaRPr: &aEndParaRPr{Lang: "en-US"},
11771177
},
11781178
}
1179+
if opts != nil {
1180+
cTxPr.P.PPr.DefRPr.B = opts.NumFont.Bold
1181+
cTxPr.P.PPr.DefRPr.I = opts.NumFont.Italic
1182+
if idx := inStrSlice(supportedDrawingUnderlineTypes, opts.NumFont.Underline, true); idx != -1 {
1183+
cTxPr.P.PPr.DefRPr.U = supportedDrawingUnderlineTypes[idx]
1184+
}
1185+
if opts.NumFont.Color != "" {
1186+
cTxPr.P.PPr.DefRPr.SolidFill.SchemeClr = nil
1187+
cTxPr.P.PPr.DefRPr.SolidFill.SrgbClr = &attrValString{Val: stringPtr(strings.ReplaceAll(strings.ToUpper(opts.NumFont.Color), "#", ""))}
1188+
}
1189+
}
1190+
return cTxPr
11791191
}
11801192

11811193
// drawingParser provides a function to parse drawingXML. In order to solve

file.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func (f *File) SaveAs(name string, opts ...Options) error {
7272
return ErrMaxFilePathLength
7373
}
7474
f.Path = name
75-
if _, ok := supportedContentType[filepath.Ext(f.Path)]; !ok {
75+
if _, ok := supportedContentTypes[filepath.Ext(f.Path)]; !ok {
7676
return ErrWorkbookFileFormat
7777
}
7878
file, err := os.OpenFile(filepath.Clean(name), os.O_WRONLY|os.O_TRUNC|os.O_CREATE, os.ModePerm)
@@ -112,7 +112,7 @@ func (f *File) WriteTo(w io.Writer, opts ...Options) (int64, error) {
112112
f.options = &opts[i]
113113
}
114114
if len(f.Path) != 0 {
115-
contentType, ok := supportedContentType[filepath.Ext(f.Path)]
115+
contentType, ok := supportedContentTypes[filepath.Ext(f.Path)]
116116
if !ok {
117117
return 0, ErrWorkbookFileFormat
118118
}

shape.go

+3-25
Original file line numberDiff line numberDiff line change
@@ -323,27 +323,6 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, opts *shapeOption
323323
colIdx := fromCol - 1
324324
rowIdx := fromRow - 1
325325

326-
textUnderlineType := map[string]bool{
327-
"none": true,
328-
"words": true,
329-
"sng": true,
330-
"dbl": true,
331-
"heavy": true,
332-
"dotted": true,
333-
"dottedHeavy": true,
334-
"dash": true,
335-
"dashHeavy": true,
336-
"dashLong": true,
337-
"dashLongHeavy": true,
338-
"dotDash": true,
339-
"dotDashHeavy": true,
340-
"dotDotDash": true,
341-
"dotDotDashHeavy": true,
342-
"wavy": true,
343-
"wavyHeavy": true,
344-
"wavyDbl": true,
345-
}
346-
347326
width := int(float64(opts.Width) * opts.Format.XScale)
348327
height := int(float64(opts.Height) * opts.Format.YScale)
349328

@@ -422,10 +401,9 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, opts *shapeOption
422401
}
423402
}
424403
for _, p := range opts.Paragraph {
425-
u := p.Font.Underline
426-
_, ok := textUnderlineType[u]
427-
if !ok {
428-
u = "none"
404+
u := "none"
405+
if idx := inStrSlice(supportedDrawingUnderlineTypes, p.Font.Underline, true); idx != -1 {
406+
u = supportedDrawingUnderlineTypes[idx]
429407
}
430408
text := p.Text
431409
if text == "" {

styles.go

+6-12
Original file line numberDiff line numberDiff line change
@@ -2087,7 +2087,6 @@ func (f *File) getFontID(styleSheet *xlsxStyleSheet, style *Style) (fontID int)
20872087
// newFont provides a function to add font style by given cell format
20882088
// settings.
20892089
func (f *File) newFont(style *Style) *xlsxFont {
2090-
fontUnderlineType := map[string]string{"single": "single", "double": "double"}
20912090
if style.Font.Size < MinFontSize {
20922091
style.Font.Size = 11
20932092
}
@@ -2112,9 +2111,8 @@ func (f *File) newFont(style *Style) *xlsxFont {
21122111
if style.Font.Strike {
21132112
fnt.Strike = &attrValBool{Val: &style.Font.Strike}
21142113
}
2115-
val, ok := fontUnderlineType[style.Font.Underline]
2116-
if ok {
2117-
fnt.U = &attrValString{Val: stringPtr(val)}
2114+
if idx := inStrSlice(supportedUnderlineTypes, style.Font.Underline, true); idx != -1 {
2115+
fnt.U = &attrValString{Val: stringPtr(supportedUnderlineTypes[idx])}
21182116
}
21192117
return &fnt
21202118
}
@@ -3100,13 +3098,10 @@ func drawCondFmtCellIs(p int, ct string, format *conditionalOptions) *xlsxCfRule
31003098
DxfID: &format.Format,
31013099
}
31023100
// "between" and "not between" criteria require 2 values.
3103-
_, ok := map[string]bool{"between": true, "notBetween": true}[ct]
3104-
if ok {
3105-
c.Formula = append(c.Formula, format.Minimum)
3106-
c.Formula = append(c.Formula, format.Maximum)
3101+
if ct == "between" || ct == "notBetween" {
3102+
c.Formula = append(c.Formula, []string{format.Minimum, format.Maximum}...)
31073103
}
3108-
_, ok = map[string]bool{"equal": true, "notEqual": true, "greaterThan": true, "lessThan": true, "greaterThanOrEqual": true, "lessThanOrEqual": true, "containsText": true, "notContains": true, "beginsWith": true, "endsWith": true}[ct]
3109-
if ok {
3104+
if idx := inStrSlice([]string{"equal", "notEqual", "greaterThan", "lessThan", "greaterThanOrEqual", "lessThanOrEqual", "containsText", "notContains", "beginsWith", "endsWith"}, ct, true); idx != -1 {
31103105
c.Formula = append(c.Formula, format.Value)
31113106
}
31123107
return c
@@ -3124,8 +3119,7 @@ func drawCondFmtTop10(p int, ct string, format *conditionalOptions) *xlsxCfRule
31243119
DxfID: &format.Format,
31253120
Percent: format.Percent,
31263121
}
3127-
rank, err := strconv.Atoi(format.Value)
3128-
if err == nil {
3122+
if rank, err := strconv.Atoi(format.Value); err == nil {
31293123
c.Rank = rank
31303124
}
31313125
return c

table.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ func (f *File) parseFilterTokens(expression string, tokens []string) ([]int, str
516516
}
517517
}
518518
}
519-
// if the string token contains an Excel match character then change the
519+
// If the string token contains an Excel match character then change the
520520
// operator type to indicate a non "simple" equality.
521521
re, _ = regexp.Match("[*?]", []byte(token))
522522
if operator == 2 && re {

xmlChart.go

+20-25
Original file line numberDiff line numberDiff line change
@@ -521,31 +521,26 @@ type cPageMargins struct {
521521

522522
// chartAxisOptions directly maps the format settings of the chart axis.
523523
type chartAxisOptions struct {
524-
None bool `json:"none"`
525-
Crossing string `json:"crossing"`
526-
MajorGridlines bool `json:"major_grid_lines"`
527-
MinorGridlines bool `json:"minor_grid_lines"`
528-
MajorTickMark string `json:"major_tick_mark"`
529-
MinorTickMark string `json:"minor_tick_mark"`
530-
MinorUnitType string `json:"minor_unit_type"`
531-
MajorUnit float64 `json:"major_unit"`
532-
MajorUnitType string `json:"major_unit_type"`
533-
TickLabelSkip int `json:"tick_label_skip"`
534-
DisplayUnits string `json:"display_units"`
535-
DisplayUnitsVisible bool `json:"display_units_visible"`
536-
DateAxis bool `json:"date_axis"`
537-
ReverseOrder bool `json:"reverse_order"`
538-
Maximum *float64 `json:"maximum"`
539-
Minimum *float64 `json:"minimum"`
540-
NumFormat string `json:"num_format"`
541-
NumFont struct {
542-
Color string `json:"color"`
543-
Bold bool `json:"bold"`
544-
Italic bool `json:"italic"`
545-
Underline bool `json:"underline"`
546-
} `json:"num_font"`
547-
LogBase float64 `json:"logbase"`
548-
NameLayout layoutOptions `json:"name_layout"`
524+
None bool `json:"none"`
525+
Crossing string `json:"crossing"`
526+
MajorGridlines bool `json:"major_grid_lines"`
527+
MinorGridlines bool `json:"minor_grid_lines"`
528+
MajorTickMark string `json:"major_tick_mark"`
529+
MinorTickMark string `json:"minor_tick_mark"`
530+
MinorUnitType string `json:"minor_unit_type"`
531+
MajorUnit float64 `json:"major_unit"`
532+
MajorUnitType string `json:"major_unit_type"`
533+
TickLabelSkip int `json:"tick_label_skip"`
534+
DisplayUnits string `json:"display_units"`
535+
DisplayUnitsVisible bool `json:"display_units_visible"`
536+
DateAxis bool `json:"date_axis"`
537+
ReverseOrder bool `json:"reverse_order"`
538+
Maximum *float64 `json:"maximum"`
539+
Minimum *float64 `json:"minimum"`
540+
NumFormat string `json:"number_format"`
541+
NumFont Font `json:"number_font"`
542+
LogBase float64 `json:"logbase"`
543+
NameLayout layoutOptions `json:"name_layout"`
549544
}
550545

551546
// chartDimensionOptions directly maps the dimension of the chart.

xmlDrawing.go

+12-2
Original file line numberDiff line numberDiff line change
@@ -144,15 +144,25 @@ const (
144144
// supportedImageTypes defined supported image types.
145145
var supportedImageTypes = map[string]string{".gif": ".gif", ".jpg": ".jpeg", ".jpeg": ".jpeg", ".png": ".png", ".tif": ".tiff", ".tiff": ".tiff", ".emf": ".emf", ".wmf": ".wmf", ".emz": ".emz", ".wmz": ".wmz"}
146146

147-
// supportedContentType defined supported file format types.
148-
var supportedContentType = map[string]string{
147+
// supportedContentTypes defined supported file format types.
148+
var supportedContentTypes = map[string]string{
149149
".xlam": ContentTypeAddinMacro,
150150
".xlsm": ContentTypeMacro,
151151
".xlsx": ContentTypeSheetML,
152152
".xltm": ContentTypeTemplateMacro,
153153
".xltx": ContentTypeTemplate,
154154
}
155155

156+
// supportedUnderlineTypes defined supported underline types.
157+
var supportedUnderlineTypes = []string{"none", "single", "double"}
158+
159+
// supportedDrawingUnderlineTypes defined supported underline types in drawing
160+
// markup language.
161+
var supportedDrawingUnderlineTypes = []string{
162+
"none", "words", "sng", "dbl", "heavy", "dotted", "dottedHeavy", "dash", "dashHeavy", "dashLong", "dashLongHeavy", "dotDash", "dotDashHeavy", "dotDotDash", "dotDotDashHeavy", "wavy", "wavyHeavy",
163+
"wavyDbl",
164+
}
165+
156166
// xlsxCNvPr directly maps the cNvPr (Non-Visual Drawing Properties). This
157167
// element specifies non-visual canvas properties. This allows for additional
158168
// information that does not affect the appearance of the picture to be stored.

0 commit comments

Comments
 (0)