Skip to content

Commit 7b80495

Browse files
authored
Merge branch 'qax-os:master' into formula
2 parents 07093cb + 9e0c94e commit 7b80495

15 files changed

+296
-45
lines changed

calc.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"sync"
3030
"time"
3131
"unicode"
32+
"unicode/utf16"
3233
"unicode/utf8"
3334
"unsafe"
3435

@@ -14507,7 +14508,7 @@ func (fn *formulaFuncs) TEXTJOIN(argsList *list.List) formulaArg {
1450714508
return ok
1450814509
}
1450914510
result := strings.Join(args, delimiter.Value())
14510-
if len(result) > TotalCellChars {
14511+
if len(utf16.Encode([]rune(result))) > TotalCellChars {
1451114512
return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("TEXTJOIN function exceeds %d characters", TotalCellChars))
1451214513
}
1451314514
return newStringFormulaArg(result)

calc_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3969,6 +3969,7 @@ func TestCalcCellValue(t *testing.T) {
39693969
"TEXTJOIN(\"\",TRUE,NA())": {"#N/A", "#N/A"},
39703970
"TEXTJOIN(\"\",TRUE," + strings.Repeat("0,", 250) + ",0)": {"#VALUE!", "TEXTJOIN accepts at most 252 arguments"},
39713971
"TEXTJOIN(\",\",FALSE,REPT(\"*\",32768))": {"#VALUE!", "TEXTJOIN function exceeds 32767 characters"},
3972+
"TEXTJOIN(\"\",FALSE,REPT(\"\U0001F600\",16384))": {"#VALUE!", "TEXTJOIN function exceeds 32767 characters"},
39723973
// TRIM
39733974
"TRIM()": {"#VALUE!", "TRIM requires 1 argument"},
39743975
"TRIM(1,2)": {"#VALUE!", "TRIM requires 1 argument"},

cell.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import (
2121
"strconv"
2222
"strings"
2323
"time"
24-
"unicode/utf8"
24+
"unicode/utf16"
2525

2626
"github.com/xuri/efp"
2727
)
@@ -447,8 +447,8 @@ func (f *File) SetCellStr(sheet, cell, value string) error {
447447

448448
// setCellString provides a function to set string type to shared string table.
449449
func (f *File) setCellString(value string) (t, v string, err error) {
450-
if utf8.RuneCountInString(value) > TotalCellChars {
451-
value = string([]rune(value)[:TotalCellChars])
450+
if len(utf16.Encode([]rune(value))) > TotalCellChars {
451+
value = truncateUTF16Units(value, TotalCellChars)
452452
}
453453
t = "s"
454454
var si int
@@ -510,8 +510,8 @@ func (f *File) setSharedString(val string) (int, error) {
510510

511511
// trimCellValue provides a function to set string type to cell.
512512
func trimCellValue(value string, escape bool) (v string, ns xml.Attr) {
513-
if utf8.RuneCountInString(value) > TotalCellChars {
514-
value = string([]rune(value)[:TotalCellChars])
513+
if len(utf16.Encode([]rune(value))) > TotalCellChars {
514+
value = truncateUTF16Units(value, TotalCellChars)
515515
}
516516
if value != "" {
517517
prefix, suffix := value[0], value[len(value)-1]
@@ -1211,7 +1211,7 @@ func setRichText(runs []RichTextRun) ([]xlsxR, error) {
12111211
totalCellChars int
12121212
)
12131213
for _, textRun := range runs {
1214-
totalCellChars += utf8.RuneCountInString(textRun.Text)
1214+
totalCellChars += len(utf16.Encode([]rune(textRun.Text)))
12151215
if totalCellChars > TotalCellChars {
12161216
return textRuns, ErrCellCharsLength
12171217
}

chart.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ const (
7878
WireframeContour
7979
Bubble
8080
Bubble3D
81+
StockHighLowClose
82+
StockOpenHighLowClose
8183
)
8284

8385
// ChartDashType is the type of supported chart dash types.
@@ -365,6 +367,8 @@ var (
365367
WireframeContour: "General",
366368
Bubble: "General",
367369
Bubble3D: "General",
370+
StockHighLowClose: "General",
371+
StockOpenHighLowClose: "General",
368372
}
369373
chartValAxCrossBetween = map[ChartType]string{
370374
Area: "midCat",
@@ -422,6 +426,8 @@ var (
422426
WireframeContour: "midCat",
423427
Bubble: "midCat",
424428
Bubble3D: "midCat",
429+
StockHighLowClose: "between",
430+
StockOpenHighLowClose: "between",
425431
}
426432
plotAreaChartGrouping = map[ChartType]string{
427433
Area: "standard",
@@ -768,6 +774,8 @@ func (opts *Chart) parseTitle() {
768774
// 52 | WireframeContour | wireframe contour chart
769775
// 53 | Bubble | bubble chart
770776
// 54 | Bubble3D | 3D bubble chart
777+
// 55 | StockHighLowClose | High-Low-Close stock chart
778+
// 56 | StockOpenHighLowClose | Open-High-Low-Close stock chart
771779
//
772780
// In Excel a chart series is a collection of information that defines which
773781
// data is plotted such as values, axis labels and formatting.

chart_test.go

Lines changed: 110 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -312,11 +312,11 @@ func TestAddChart(t *testing.T) {
312312
// Test with illegal cell reference
313313
assert.EqualError(t, f.AddChart("Sheet2", "A", &Chart{Type: Col, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "2D Column Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error())
314314
// Test with unsupported chart type
315-
assert.EqualError(t, f.AddChart("Sheet2", "BD32", &Chart{Type: 0x37, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "Bubble 3D Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}), newUnsupportedChartType(0x37).Error())
315+
assert.EqualError(t, f.AddChart("Sheet2", "BD32", &Chart{Type: 0x39, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "Bubble 3D Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}), newUnsupportedChartType(0x39).Error())
316316
// Test add combo chart with invalid format set
317317
assert.EqualError(t, f.AddChart("Sheet2", "BD32", &Chart{Type: Col, Series: series, Format: format, Legend: legend, Title: []RichTextRun{{Text: "2D Column Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero"}, nil), ErrParameterInvalid.Error())
318318
// Test add combo chart with unsupported chart type
319-
assert.EqualError(t, f.AddChart("Sheet2", "BD64", &Chart{Type: BarOfPie, Series: []ChartSeries{{Name: "Sheet1!$A$30", Categories: "Sheet1!$A$30:$D$37", Values: "Sheet1!$B$30:$B$37"}}, Format: format, Legend: legend, Title: []RichTextRun{{Text: "Bar of Pie Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero", XAxis: ChartAxis{MajorGridLines: true}, YAxis: ChartAxis{MajorGridLines: true}}, &Chart{Type: 0x37, Series: []ChartSeries{{Name: "Sheet1!$A$30", Categories: "Sheet1!$A$30:$D$37", Values: "Sheet1!$B$30:$B$37"}}, Format: format, Legend: legend, Title: []RichTextRun{{Text: "Bar of Pie Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero", XAxis: ChartAxis{MajorGridLines: true}, YAxis: ChartAxis{MajorGridLines: true}}), newUnsupportedChartType(0x37).Error())
319+
assert.EqualError(t, f.AddChart("Sheet2", "BD64", &Chart{Type: BarOfPie, Series: []ChartSeries{{Name: "Sheet1!$A$30", Categories: "Sheet1!$A$30:$D$37", Values: "Sheet1!$B$30:$B$37"}}, Format: format, Legend: legend, Title: []RichTextRun{{Text: "Bar of Pie Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero", XAxis: ChartAxis{MajorGridLines: true}, YAxis: ChartAxis{MajorGridLines: true}}, &Chart{Type: 0x39, Series: []ChartSeries{{Name: "Sheet1!$A$30", Categories: "Sheet1!$A$30:$D$37", Values: "Sheet1!$B$30:$B$37"}}, Format: format, Legend: legend, Title: []RichTextRun{{Text: "Bar of Pie Chart"}}, PlotArea: plotArea, ShowBlanksAs: "zero", XAxis: ChartAxis{MajorGridLines: true}, YAxis: ChartAxis{MajorGridLines: true}}), newUnsupportedChartType(0x39).Error())
320320
// Test add chart with series transparency value exceeds limit
321321
assert.Equal(t, ErrTransparency, f.AddChart("Sheet1", "BD64", &Chart{Type: Col, Series: []ChartSeries{{Name: "Sheet1!$A$30", Categories: "Sheet1!$B$29:$D$29", Values: "Sheet1!$B$30:$D$30", Fill: Fill{Transparency: 110}}}}))
322322
// Test add chart with transparency value exceeds limit
@@ -327,6 +327,113 @@ func TestAddChart(t *testing.T) {
327327
f.ContentTypes = nil
328328
f.Pkg.Store(defaultXMLPathContentTypes, MacintoshCyrillicCharset)
329329
assert.EqualError(t, f.AddChart("Sheet1", "P1", &Chart{Type: Col, Series: []ChartSeries{{Name: "Sheet1!$A$30", Categories: "Sheet1!$B$29:$D$29", Values: "Sheet1!$B$30:$D$30"}}, Title: []RichTextRun{{Text: "2D Column Chart"}}}), "XML syntax error on line 1: invalid UTF-8")
330+
331+
t.Run("for_create_stock_chart", func(t *testing.T) {
332+
f := NewFile()
333+
for i, row := range [][]interface{}{
334+
{"Date", "Volume", "Open", "High", "Low", "Close"},
335+
{45593, 14864000, 431.66, 431.94, 426.3, 426.59},
336+
{45590, 16899100, 426.76, 432.52, 426.57, 428.15},
337+
{45589, 13581600, 425.33, 425.98, 422.4, 424.73},
338+
{45588, 19654400, 430.86, 431.08, 422.53, 424.6},
339+
{45587, 25482200, 418.49, 430.58, 418.04, 427.51},
340+
{45586, 14206100, 416.12, 418.96, 413.75, 418.78},
341+
{45583, 17145300, 417.14, 419.65, 416.26, 418.16},
342+
{45582, 14820000, 422.36, 422.5, 415.59, 416.72},
343+
{45581, 15508900, 415.17, 416.36, 410.48, 416.12},
344+
{45580, 18900200, 422.18, 422.48, 415.26, 418.74},
345+
{45579, 16653100, 417.77, 424.04, 417.52, 419.14},
346+
{45576, 14144900, 416.14, 417.13, 413.25, 416.32},
347+
{45575, 13848400, 415.23, 417.35, 413.15, 415.84},
348+
{45574, 14974300, 415.86, 420.38, 414.3, 417.46},
349+
{45573, 19229300, 410.9, 415.66, 408.17, 414.71},
350+
{45572, 20919800, 416, 417.11, 409, 409.54},
351+
{45569, 19169700, 418.24, 419.75, 414.97, 416.06},
352+
{45568, 13686400, 417.63, 419.55, 414.29, 416.54},
353+
{45567, 16582300, 422.58, 422.82, 416.71, 417.13},
354+
{45566, 19092900, 428.45, 428.48, 418.81, 420.69},
355+
{45565, 16807300, 428.21, 430.42, 425.37, 430.3},
356+
} {
357+
cell, err := CoordinatesToCellName(1, i+1)
358+
assert.NoError(t, err)
359+
assert.NoError(t, f.SetSheetRow("Sheet1", cell, &row))
360+
}
361+
style, err := f.NewStyle(&Style{NumFmt: 15})
362+
assert.NoError(t, err)
363+
assert.NoError(t, f.SetColStyle("Sheet1", "A", style))
364+
365+
assert.NoError(t, f.AddChart("Sheet1", "G1", &Chart{
366+
Type: StockHighLowClose,
367+
Series: []ChartSeries{
368+
{Name: "Sheet1!$D$1", Categories: "Sheet1!$A$2:$A$22", Values: "Sheet1!$D$2:$D$22"},
369+
{Name: "Sheet1!$E$1", Categories: "Sheet1!$A$2:$A$22", Values: "Sheet1!$E$2:$E$22"},
370+
{Name: "Sheet1!$F$1", Categories: "Sheet1!$A$2:$A$22", Values: "Sheet1!$F$2:$F$22"},
371+
},
372+
Legend: ChartLegend{Position: "none"},
373+
Title: []RichTextRun{{Text: "High-Low-Close Stock Chart"}},
374+
XAxis: ChartAxis{NumFmt: ChartNumFmt{CustomNumFmt: "d-mmm-yy"}},
375+
}))
376+
assert.NoError(t, f.AddChart("Sheet1", "G16", &Chart{
377+
Type: StockOpenHighLowClose,
378+
Series: []ChartSeries{
379+
{Name: "Sheet1!$C$1", Categories: "Sheet1!$A$2:$A$22", Values: "Sheet1!$C$2:$C$22"},
380+
{Name: "Sheet1!$D$1", Categories: "Sheet1!$A$2:$A$22", Values: "Sheet1!$D$2:$D$22"},
381+
{Name: "Sheet1!$E$1", Categories: "Sheet1!$A$2:$A$22", Values: "Sheet1!$E$2:$E$22"},
382+
{Name: "Sheet1!$F$1", Categories: "Sheet1!$A$2:$A$22", Values: "Sheet1!$F$2:$F$22"},
383+
},
384+
Legend: ChartLegend{Position: "none"},
385+
Title: []RichTextRun{{Text: "Open-High-Low-Close Stock Chart"}},
386+
XAxis: ChartAxis{NumFmt: ChartNumFmt{CustomNumFmt: "d-mmm-yy"}},
387+
PlotArea: ChartPlotArea{
388+
UpBars: ChartUpDownBar{
389+
Border: ChartLine{Type: ChartLineNone},
390+
Fill: Fill{Type: "pattern", Color: []string{"00B050"}, Pattern: 1},
391+
},
392+
DownBars: ChartUpDownBar{
393+
Border: ChartLine{Type: ChartLineNone},
394+
Fill: Fill{Type: "pattern", Color: []string{"FF0000"}, Pattern: 1},
395+
},
396+
},
397+
}))
398+
assert.NoError(t, f.AddChart("Sheet1", "O1", &Chart{
399+
Type: Col,
400+
Series: []ChartSeries{
401+
{Name: "Sheet1!$B$1", Categories: "Sheet1!$A$2:$A$22", Values: "Sheet1!$B$2:$B$22"},
402+
},
403+
VaryColors: boolPtr(false),
404+
XAxis: ChartAxis{NumFmt: ChartNumFmt{CustomNumFmt: "d-mmm-yy"}},
405+
YAxis: ChartAxis{NumFmt: ChartNumFmt{CustomNumFmt: "#,##0"}},
406+
Title: []RichTextRun{{Text: "Volume-High-Low-Close Stock Chart"}},
407+
}, &Chart{
408+
Type: StockHighLowClose,
409+
Series: []ChartSeries{
410+
{Name: "Sheet1!$D$1", Categories: "Sheet1!$A$2:$A$22", Values: "Sheet1!$D$2:$D$22"},
411+
{Name: "Sheet1!$E$1", Categories: "Sheet1!$A$2:$A$22", Values: "Sheet1!$E$2:$E$22"},
412+
{Name: "Sheet1!$F$1", Categories: "Sheet1!$A$2:$A$22", Values: "Sheet1!$F$2:$F$22"},
413+
},
414+
YAxis: ChartAxis{Secondary: true},
415+
}))
416+
assert.NoError(t, f.AddChart("Sheet1", "O16", &Chart{
417+
Type: Col,
418+
Series: []ChartSeries{
419+
{Name: "Sheet1!$B$1", Categories: "Sheet1!$A$2:$A$22", Values: "Sheet1!$B$2:$B$22"},
420+
},
421+
VaryColors: boolPtr(false),
422+
XAxis: ChartAxis{NumFmt: ChartNumFmt{CustomNumFmt: "d-mmm-yy"}},
423+
YAxis: ChartAxis{NumFmt: ChartNumFmt{CustomNumFmt: "#,##0"}},
424+
Title: []RichTextRun{{Text: "Volume-Open-High-Low-Close Stock Chart"}},
425+
}, &Chart{
426+
Type: StockOpenHighLowClose,
427+
Series: []ChartSeries{
428+
{Name: "Sheet1!$C$1", Categories: "Sheet1!$A$2:$A$22", Values: "Sheet1!$C$2:$C$22"},
429+
{Name: "Sheet1!$D$1", Categories: "Sheet1!$A$2:$A$22", Values: "Sheet1!$D$2:$D$22"},
430+
{Name: "Sheet1!$E$1", Categories: "Sheet1!$A$2:$A$22", Values: "Sheet1!$E$2:$E$22"},
431+
{Name: "Sheet1!$F$1", Categories: "Sheet1!$A$2:$A$22", Values: "Sheet1!$F$2:$F$22"},
432+
},
433+
YAxis: ChartAxis{Secondary: true},
434+
}))
435+
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddChartStock.xlsx")))
436+
})
330437
}
331438

332439
func TestAddChartSheet(t *testing.T) {
@@ -363,7 +470,7 @@ func TestAddChartSheet(t *testing.T) {
363470
// Test add chartsheet with invalid sheet name
364471
assert.EqualError(t, f.AddChartSheet("Sheet:1", nil, &Chart{Type: Col3DClustered, Series: series, Title: []RichTextRun{{Text: "Fruit 3D Clustered Column Chart"}}}), ErrSheetNameInvalid.Error())
365472
// Test with unsupported chart type
366-
assert.EqualError(t, f.AddChartSheet("Chart2", &Chart{Type: 0x37, Series: series, Title: []RichTextRun{{Text: "Fruit 3D Clustered Column Chart"}}}), newUnsupportedChartType(0x37).Error())
473+
assert.EqualError(t, f.AddChartSheet("Chart2", &Chart{Type: 0x39, Series: series, Title: []RichTextRun{{Text: "Fruit 3D Clustered Column Chart"}}}), newUnsupportedChartType(0x39).Error())
367474

368475
assert.NoError(t, f.UpdateLinkedValue())
369476

drawing.go

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ func (f *File) addChart(opts *Chart, comboCharts []*Chart) {
159159
WireframeContour: f.drawSurfaceChart,
160160
Bubble: f.drawBubbleChart,
161161
Bubble3D: f.drawBubbleChart,
162+
StockHighLowClose: f.drawStockChart,
163+
StockOpenHighLowClose: f.drawStockChart,
162164
}
163165
xlsxChartSpace.Chart.drawChartLegend(opts)
164166
xlsxChartSpace.Chart.PlotArea.SpPr = f.drawShapeFill(opts.PlotArea.Fill, xlsxChartSpace.Chart.PlotArea.SpPr)
@@ -171,7 +173,7 @@ func (f *File) addChart(opts *Chart, comboCharts []*Chart) {
171173
continue
172174
}
173175
fld := immutable.FieldByName(mutable.Type().Field(i).Name)
174-
if field.Kind() == reflect.Slice && i < 16 { // All []*cCharts type fields
176+
if field.Kind() == reflect.Slice && i < 17 { // All []*cCharts type fields
175177
fld.Set(reflect.Append(fld, field.Index(0)))
176178
continue
177179
}
@@ -185,6 +187,10 @@ func (f *File) addChart(opts *Chart, comboCharts []*Chart) {
185187
addChart(xlsxChartSpace.Chart.PlotArea, plotAreaFunc[comboCharts[idx].Type](xlsxChartSpace.Chart.PlotArea, comboCharts[idx]))
186188
order += len(comboCharts[idx].Series)
187189
}
190+
// If the dateAx field exists, valAx field should be nil.
191+
if xlsxChartSpace.Chart.PlotArea != nil && xlsxChartSpace.Chart.PlotArea.DateAx != nil {
192+
xlsxChartSpace.Chart.PlotArea.CatAx = nil
193+
}
188194
chart, _ := xml.Marshal(xlsxChartSpace)
189195
media := "xl/charts/chart" + strconv.Itoa(count+1) + ".xml"
190196
f.saveFileList(media, chart)
@@ -689,6 +695,39 @@ func (f *File) drawBubbleChart(pa *cPlotArea, opts *Chart) *cPlotArea {
689695
return plotArea
690696
}
691697

698+
// drawStockChart provides a function to draw the c:stockChart element by
699+
// given format sets.
700+
func (f *File) drawStockChart(pa *cPlotArea, opts *Chart) *cPlotArea {
701+
plotArea := &cPlotArea{
702+
StockChart: []*cCharts{
703+
{
704+
VaryColors: &attrValBool{
705+
Val: opts.VaryColors,
706+
},
707+
Ser: f.drawChartSeries(opts),
708+
DLbls: f.drawChartDLbls(opts),
709+
AxID: f.genAxID(opts),
710+
},
711+
},
712+
ValAx: f.drawPlotAreaValAx(pa, opts),
713+
DateAx: f.drawPlotAreaCatAx(pa, opts),
714+
}
715+
if opts.Type == StockHighLowClose {
716+
plotArea.StockChart[0].HiLowLines = &cChartLines{}
717+
}
718+
if opts.Type == StockOpenHighLowClose {
719+
plotArea.StockChart[0].HiLowLines = &cChartLines{}
720+
plotArea.StockChart[0].UpDownBars = &cUpDownBars{
721+
GapWidth: &attrValString{Val: stringPtr("150")},
722+
UpBars: &cChartLines{f.drawShapeFill(opts.PlotArea.UpBars.Fill, &cSpPr{Ln: f.drawChartLn(&opts.PlotArea.UpBars.Border)})},
723+
DownBars: &cChartLines{f.drawShapeFill(opts.PlotArea.DownBars.Fill, &cSpPr{Ln: f.drawChartLn(&opts.PlotArea.UpBars.Border)})},
724+
}
725+
}
726+
ser := *plotArea.StockChart[0].Ser
727+
ser[0].Val.NumRef.NumCache = &cNumCache{}
728+
return plotArea
729+
}
730+
692731
// drawChartGapWidth provides a function to draw the c:gapWidth element by given
693732
// format sets.
694733
func (f *File) drawChartGapWidth(opts *Chart) *attrValInt {
@@ -818,8 +857,10 @@ func (f *File) drawChartSeriesSpPr(i int, opts *Chart) *cSpPr {
818857
}
819858
noLn := &cSpPr{Ln: &aLn{NoFill: &attrValString{}}}
820859
if chartSeriesSpPr, ok := map[ChartType]map[ChartLineType]*cSpPr{
821-
Line: {ChartLineUnset: solid, ChartLineSolid: solid, ChartLineNone: noLn, ChartLineAutomatic: solid},
822-
Scatter: {ChartLineUnset: noLn, ChartLineSolid: solid, ChartLineNone: noLn, ChartLineAutomatic: noLn},
860+
Line: {ChartLineUnset: solid, ChartLineSolid: solid, ChartLineNone: noLn, ChartLineAutomatic: solid},
861+
Scatter: {ChartLineUnset: noLn, ChartLineSolid: solid, ChartLineNone: noLn, ChartLineAutomatic: noLn},
862+
StockHighLowClose: {ChartLineUnset: noLn, ChartLineSolid: solid, ChartLineNone: noLn, ChartLineAutomatic: noLn},
863+
StockOpenHighLowClose: {ChartLineUnset: noLn, ChartLineSolid: solid, ChartLineNone: noLn, ChartLineAutomatic: noLn},
823864
}[opts.Type]; ok {
824865
return chartSeriesSpPr[opts.Series[i].Line.Type]
825866
}
@@ -892,7 +933,11 @@ func (f *File) drawChartSeriesVal(v ChartSeries, opts *Chart) *cVal {
892933
// drawChartSeriesMarker provides a function to draw the c:marker element by
893934
// given data index and format sets.
894935
func (f *File) drawChartSeriesMarker(i int, opts *Chart) *cMarker {
895-
defaultSymbol := map[ChartType]*attrValString{Scatter: {Val: stringPtr("circle")}}
936+
defaultSymbol := map[ChartType]*attrValString{
937+
Scatter: {Val: stringPtr("circle")},
938+
StockHighLowClose: {Val: stringPtr("dot")},
939+
StockOpenHighLowClose: {Val: stringPtr("none")},
940+
}
896941
marker := &cMarker{
897942
Symbol: defaultSymbol[opts.Type],
898943
Size: &attrValInt{Val: intPtr(5)},
@@ -912,7 +957,12 @@ func (f *File) drawChartSeriesMarker(i int, opts *Chart) *cMarker {
912957
if marker.SpPr != nil && marker.SpPr.Ln != nil {
913958
marker.SpPr.Ln = f.drawChartLn(&opts.Series[i].Marker.Border)
914959
}
915-
chartSeriesMarker := map[ChartType]*cMarker{Scatter: marker, Line: marker}
960+
chartSeriesMarker := map[ChartType]*cMarker{
961+
Scatter: marker,
962+
Line: marker,
963+
StockHighLowClose: marker,
964+
StockOpenHighLowClose: marker,
965+
}
916966
return chartSeriesMarker[opts.Type]
917967
}
918968

0 commit comments

Comments
 (0)