From 76c0221e9e2bc0dd8b2af2acbdaa7f9ef2e0ef47 Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Wed, 7 Feb 2024 17:36:41 +0000 Subject: [PATCH] fpspreadsheet: Radar series support in xlsx chart reader/writer. Fix some issues with radar series in ods. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9222 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../other/chart/radarchart_write_demo.lpi | 5 - .../other/chart/radarchart_write_demo.lpr | 31 +++-- .../visual/fpschart/fpschartlink/main.pas | 19 ++- .../fpspreadsheet/source/common/fpschart.pas | 75 +++++------ .../source/common/fpsopendocumentchart.pas | 39 +++--- .../source/common/xlsxooxmlchart.pas | 121 ++++++++++++++---- .../source/visual/fpspreadsheetchart.pas | 18 +-- 7 files changed, 196 insertions(+), 112 deletions(-) diff --git a/components/fpspreadsheet/examples/other/chart/radarchart_write_demo.lpi b/components/fpspreadsheet/examples/other/chart/radarchart_write_demo.lpi index 3f26de9a0..2a8959e14 100644 --- a/components/fpspreadsheet/examples/other/chart/radarchart_write_demo.lpi +++ b/components/fpspreadsheet/examples/other/chart/radarchart_write_demo.lpi @@ -51,11 +51,6 @@ - - - - - diff --git a/components/fpspreadsheet/examples/other/chart/radarchart_write_demo.lpr b/components/fpspreadsheet/examples/other/chart/radarchart_write_demo.lpr index fee21d33b..23195026c 100644 --- a/components/fpspreadsheet/examples/other/chart/radarchart_write_demo.lpr +++ b/components/fpspreadsheet/examples/other/chart/radarchart_write_demo.lpr @@ -12,8 +12,13 @@ var book: TsWorkbook; sheet: TsWorksheet; ch: TsChart; - ser: TsChartSeries; + ser: TsRadarSeries; + fn, dir: String; begin + dir := ExtractFilePath(ParamStr(0)) + 'files/'; + ForceDirectories(dir); + fn := dir + FILE_NAME; + book := TsWorkbook.Create; try // worksheet @@ -51,25 +56,29 @@ begin ser.SetLabelRange(3, 0, 10, 0); ser.SetYRange(3, 1, 10, 1); ser.Line.Color := scDarkRed; - ser.Fill.Color := scRed; - ser.Fill.Transparency := 0.35; + //ser.Fill.Style := cfsNoFill; // --> non-filled radar chrt + ser.ShowSymbols := true; + ser.Symbol := cssDiamond; + ser.SymbolFill.Style := cfsSolid; + ser.SymbolFill.Color := scYellow; + // in ods the symbol color is always equal to the line color + ser.SymbolWidth := 12; //3; + ser.SymbolHeight := 12; // 3; // Add 2nd radar series ("Student 2") - ser := TsRadarSeries.Create(ch); + ser := TsFilledRadarSeries.Create(ch); ser.SetTitleAddr(2, 2); ser.SetLabelRange(3, 0, 10, 0); ser.SetYRange(3, 2, 10, 2); ser.Line.Color := scDarkBlue; - ser.Fill.Color := scBlue; + ser.Fill.Color := $FFCC99; ser.Fill.Transparency := 0.35; - { - book.WriteToFile(FILE_NAME + '.xlsx', true); // Excel fails to open the file - WriteLn('Data saved with chart in ', FILE_NAME, '.xlsx'); - } + book.WriteToFile(fn + '.xlsx', true); + WriteLn('Data saved with chart in ', fn + '.xlsx'); - book.WriteToFile(FILE_NAME + '.ods', true); - WriteLn('Data saved with chart in ', FILE_NAME, '.ods'); + book.WriteToFile(fn + '.ods', true); + WriteLn('Data saved with chart in ', fn + '.ods'); finally book.Free; end; diff --git a/components/fpspreadsheet/examples/visual/fpschart/fpschartlink/main.pas b/components/fpspreadsheet/examples/visual/fpschart/fpschartlink/main.pas index 732f606a6..0b0c0fa0d 100644 --- a/components/fpspreadsheet/examples/visual/fpschart/fpschartlink/main.pas +++ b/components/fpspreadsheet/examples/visual/fpschart/fpschartlink/main.pas @@ -6,7 +6,7 @@ interface uses Classes, SysUtils, - LCLVersion, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls, + LCLVersion, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls, FileUtil, TAGraph, TASources, fpSpreadsheet, fpsTypes, fpsOpenDocument, xlsxOOXML, fpSpreadsheetCtrls, fpSpreadsheetGrid, fpSpreadsheetChart; @@ -35,6 +35,7 @@ type procedure FormCreate(Sender: TObject); procedure sWorkbookSource1Error(Sender: TObject; const AMsg: String); private + FDir: String; sChartLink: TsWorkbookChartLink; procedure LoadFile(AFileName: String); @@ -114,13 +115,27 @@ procedure TForm1.ComboBox1CloseUp(Sender: TObject); begin if ComboBox1.ItemIndex > -1 then begin - Combobox1.Text := Combobox1.Items[Combobox1.ItemIndex]; + Combobox1.Text := FDir + Combobox1.Items[Combobox1.ItemIndex]; LoadFile(Combobox1.Text); end; end; procedure TForm1.FormCreate(Sender: TObject); +var + L: TStrings; + i: Integer; begin + FDir := ExpandFileName(Application.Location + '../../../other/chart/files/'); + L := TStringList.Create; + try + FindAllFiles(L, FDir, '*.xlsx;*.ods', false); + for i := 0 to L.Count-1 do + L[i] := ExtractFileName(L[i]); + Combobox1.Items.Assign(L); + finally + L.Free; + end; + {$IF LCL_FullVersion >= 2020000} ComboBox1.TextHint := 'Enter or select file name'; {$IFEND} diff --git a/components/fpspreadsheet/source/common/fpschart.pas b/components/fpspreadsheet/source/common/fpschart.pas index f517654be..db77834cd 100644 --- a/components/fpspreadsheet/source/common/fpschart.pas +++ b/components/fpspreadsheet/source/common/fpschart.pas @@ -619,13 +619,12 @@ type FSymbolWidth: Double; // in mm FShowLines: Boolean; FShowSymbols: Boolean; - FBorder: TsChartLine; - function GetSymbolFill: TsChartFill; - procedure SetSymbolFill(Value: TsChartFill); + FSymbolBorder: TsChartLine; + FSymbolFill: TsChartFill; protected property Symbol: TsChartSeriesSymbol read FSymbol write FSymbol; - property SymbolBorder: TsChartLine read FBorder write FBorder; - property SymbolFill: TsChartFill read GetSymbolFill write SetSymbolFill; + property SymbolBorder: TsChartLine read FSymbolBorder write FSymbolBorder; + property SymbolFill: TsChartFill read FSymbolFill write FSymbolFill; property SymbolHeight: double read FSymbolHeight write FSymbolHeight; property SymbolWidth: double read FSymbolWidth write FSymbolWidth; property ShowLines: Boolean read FShowLines write FShowLines; @@ -666,18 +665,15 @@ type end; TsRadarSeries = class(TsLineSeries) - protected - function GetChartType: TsChartType; override; - end; - { - TsRingSeries = class(TsPieSeries) - private - FInnerRadiusPercent: Integer; public constructor Create(AChart: TsChart); override; - property InnerRadiusPercent: Integer read FInnerRadiusPercent write FInnerRadiusPercent; end; - } + + TsFilledRadarSeries = class(TsRadarSeries) + public + constructor Create(AChart: TsChart); override; + end; + TsCustomScatterSeries = class(TsCustomLineSeries) public constructor Create(AChart: TsChart); override; @@ -2490,27 +2486,22 @@ begin FShowSymbols := false; FShowLines := true; - FBorder := TsChartLine.Create; - FBorder.Style := clsSolid; - FBorder.Width := PtsToMM(DEFAULT_CHART_LINEWIDTH); - FBorder.Color := scBlack; + FSymbolBorder := TsChartLine.Create; + FSymbolBorder.Style := clsSolid; + FSymbolBorder.Width := PtsToMM(DEFAULT_CHART_LINEWIDTH); + FSymbolBorder.Color := scBlack; + + FSymbolFill := TsChartFill.Create; + FSymbolFill.Style := cfsNoFill; end; destructor TsCustomLineSeries.Destroy; begin - FBorder.Free; + FSymbolBorder.Free; + FSymbolFill.Free; inherited; end; -function TsCustomLineSeries.GetSymbolFill: TsChartFill; -begin - Result := FFill; -end; - -procedure TsCustomLineSeries.SetSymbolFill(Value: TsChartFill); -begin - FFill := Value; -end; { TsPieSeries } constructor TsPieSeries.Create(AChart: TsChart); @@ -2545,23 +2536,21 @@ end; { TsRadarSeries } -function TsRadarSeries.GetChartType: TsChartType; -begin - if Fill.Style <> cfsNoFill then - Result := ctFilledRadar - else - Result := ctRadar; -end; - - (* -{ TsRingSeries } -constructor TsRingSeries.Create(AChart: TsChart); +constructor TsRadarSeries.Create(AChart: TsChart); begin inherited Create(AChart); - FChartType := ctRing; - FLine.Color := scBlack; - FInnerRadiusPercent := 50; -end; *) + FChartType := ctRadar; + FFill.Style := cfsNoFill; // to make the series default to ctRadar rather than ctFilledRadar +end; + + +{ TsFilledRadarSeries } +constructor TsFilledRadarSeries.Create(AChart: TsChart); +begin + inherited Create(AChart); + FChartType := ctFilledRadar; + Fill.Style := cfsSolid; +end; { TsTrendlineEquation } diff --git a/components/fpspreadsheet/source/common/fpsopendocumentchart.pas b/components/fpspreadsheet/source/common/fpsopendocumentchart.pas index 0318315b2..f95322c01 100644 --- a/components/fpspreadsheet/source/common/fpsopendocumentchart.pas +++ b/components/fpspreadsheet/source/common/fpsopendocumentchart.pas @@ -1491,20 +1491,18 @@ begin series := TsBarSeries.Create(AChart); 'chart:bubble': series := TsBubbleSeries.Create(AChart); - // 'chart:circle': - // series := TsPieSeries.Create(AChart); - 'chart:filled-radar': - series := TsRadarSeries.Create(AChart); - 'chart:line': - series := TsLineSeries.Create(AChart); - 'chart:radar': - series := TsRadarSeries.Create(AChart); 'chart:circle': begin series := TsPieSeries.Create(AChart); if FChartType = ctRing then TsPieSeries(series).InnerRadiusPercent := 50; end; + 'chart:line': + series := TsLineSeries.Create(AChart); + 'chart:radar': + series := TsRadarSeries.Create(AChart); + 'chart:filled-radar': + series := TsFilledRadarSeries.Create(AChart); 'chart:scatter': series := TsScatterSeries.Create(AChart); // 'chart:stock': --- has already been created @@ -1650,7 +1648,14 @@ begin if ASeries.ChartType in [ctBar] then ASeries.Line.Style := clsSolid; GetChartLineProps(AStyleNode, AChart, ASeries.Line); - GetChartFillProps(AStyleNode, AChart, ASeries.Fill); + if ((ASeries is TsRadarSeries) and (ASeries.ChartType = ctRadar)) or (ASeries is TsCustomLineSeries) then + begin + // In ods, symbols and lines have the same color + TsRadarSeries(ASeries).SymbolFill.Style := cfsSolid; + TsRadarSeries(ASeries).SymbolFill.Color := ASeries.Line.Color; + TsRadarSeries(ASeries).SymbolBorder.Style := clsNoLine; + end else + GetChartFillProps(AStyleNode, AChart, ASeries.Fill); end; 'style:text-properties': GetChartTextProps(AStyleNode, ASeries.LabelFont); @@ -1739,10 +1744,10 @@ begin TsOpenedCustomLineSeries(ASeries).Symbol := css; break; end; - s := GetAttrValue(AStyleNode, 'symbol-width'); + s := GetAttrValue(AStyleNode, 'chart:symbol-width'); if (s <> '') and EvalLengthStr(s, value, rel) then TsOpenedCustomLineSeries(ASeries).SymbolWidth := value; - s := GetAttrValue(AStyleNode, 'symbol-height'); + s := GetAttrValue(AStyleNode, 'chart:symbol-height'); if (s <> '') and EvalLengthStr(s, value, rel) then TsOpenedCustomLineSeries(ASeries).SymbolHeight := value; end else @@ -2607,7 +2612,7 @@ begin ciStepCenterY: interpolationStr := 'chart:interpolation="step-center-y" '; end; - if not (AChart.GetChartType in [ctRadar, ctPie]) then + if not (AChart.GetChartType in [ctRadar, ctFilledRadar, ctPie]) then rightAngledAxes := 'chart:right-angled-axes="true" '; for i := 0 to AChart.Series.Count-1 do @@ -2784,7 +2789,7 @@ function TsSpreadOpenDocChartWriter.GetChartSeriesStyleAsXML(AChart: TsChart; ASeriesIndex, AIndent, AStyleID: Integer): String; var series: TsChartSeries; - lineser: TsLineSeries = nil; + lineser: TsOpenedCustomLineSeries = nil; indent: String; numStyle: String; forceNoLine: Boolean = false; @@ -2809,7 +2814,7 @@ begin if ((series is TsLineSeries) and (series.ChartType <> ctFilledRadar)) or (series is TsScatterSeries) then begin - lineser := TsLineSeries(series); + lineser := TsOpenedCustomLineSeries(series); if lineser.ShowSymbols then chartProps := Format( 'chart:symbol-type="named-symbol" chart:symbol-name="%s" chart:symbol-width="%.1fmm" chart:symbol-height="%.1fmm" ', @@ -2870,9 +2875,10 @@ begin // Graphic properties lineProps := GetChartLineStyleGraphicPropsAsXML(AChart, series.Line, forceNoLine); - fillProps := GetChartFillStyleGraphicPropsAsXML(AChart, series.Fill); if (series is TsLineSeries) and (series.ChartType <> ctFilledRadar) then begin + lineSer := TsOpenedCustomLineSeries(series); + fillProps := GetChartFillStyleGraphicPropsAsXML(AChart, lineser.SymbolFill); if lineSer.ShowSymbols then graphProps := graphProps + fillProps; if lineSer.ShowLines and (lineser.Line.Style <> clsNoLine) then @@ -2880,7 +2886,10 @@ begin else graphProps := graphProps + 'draw:stroke="none" '; end else + begin + fillProps := GetChartFillStyleGraphicPropsAsXML(AChart, series.Fill); graphProps := fillProps + lineProps; + end; // Text properties textProps := TsSpreadOpenDocWriter(Writer).WriteFontStyleXMLAsString(series.LabelFont); diff --git a/components/fpspreadsheet/source/common/xlsxooxmlchart.pas b/components/fpspreadsheet/source/common/xlsxooxmlchart.pas index 0e57c5ccd..af78ab913 100644 --- a/components/fpspreadsheet/source/common/xlsxooxmlchart.pas +++ b/components/fpspreadsheet/source/common/xlsxooxmlchart.pas @@ -102,7 +102,7 @@ type procedure WriteChartAxisTitle(AStream: TStream; AIndent: Integer; Axis: TsChartAxis); procedure WriteChartLegendNode(AStream: TStream; AIndent: Integer; ALegend: TsChartLegend); procedure WriteChartPlotAreaNode(AStream: TStream; AIndent: Integer; AChart: TsChart); - procedure WriteChartRegression(AStream: TStream; AIndent: Integer; ASeries: TsChartSeries); + procedure WriteChartTrendline(AStream: TStream; AIndent: Integer; ASeries: TsChartSeries); procedure WriteChartSeriesDatapointLabels(AStream: TStream; AIndent: Integer; ASeries: TsChartSeries); procedure WriteChartSeriesDatapointStyles(AStream: TStream; AIndent: Integer; ASeries: TsChartSeries); procedure WriteChartSeriesNode(AStream: TStream; AIndent: Integer; ASeries: TsChartSeries; ASeriesIndex: Integer); @@ -114,6 +114,7 @@ type procedure WriteBarSeries(AStream: TStream; AIndent: Integer; ASeries: TsBarSeries; ASeriesIndex: Integer); procedure WriteBubbleSeries(AStream: TStream; AIndent: Integer; ASeries: TsBubbleSeries; ASeriesIndex: Integer); procedure WritePieSeries(AStream: TStream; AIndent: Integer; ASeries: TsPieSeries; ASeriesIndex: Integer); + procedure WriteRadarSeries(AStream: TStream; AIndent: Integer; ASeries: TsRadarSeries; ASeriesIndex: Integer); procedure WriteScatterSeries(AStream: TStream; AIndent: Integer; ASeries: TsScatterSeries; ASeriesIndex: Integer); procedure WriteChartLabels(AStream: TStream; AIndent: Integer; AFont: TsFont); @@ -1395,7 +1396,7 @@ begin if TryStrToInt(s, n) then with TsOpenedCustomLineSeries(ASeries) do begin - SymbolWidth := PtsToMM(n div 2); + SymbolWidth := PtsToMM(n); SymbolHeight := SymbolWidth; end; @@ -1550,28 +1551,47 @@ end; -------------------------------------------------------------------------------} procedure TsSpreadOOXMLChartReader.ReadChartRadarSeries(ANode: TDOMNode; AChart: TsChart); var - nodeName: String; + node: TDOMNode; + nodeName, s: String; ser: TsRadarSeries; - radarStyle: String = ''; + filled: Boolean = false; begin if ANode = nil then exit; - while Assigned(ANode) do + // At first, we need the value of c:radarStyle because it determines the + // series class to be created. + node := ANode; + while Assigned(node) do begin - nodeName := ANode.NodeName; + nodeName := node.NodeName; case nodeName of 'c:radarStyle': - radarStyle := GetAttrValue(ANode, 'val'); - 'c:ser': begin - ser := TsRadarSeries.Create(AChart); - ReadChartSeriesProps(ANode.FirstChild, ser); - if radarStyle <> 'filled' then - ser.Fill.Style := cfsNoFill; + s := GetAttrValue(node, 'val'); + filled := s = 'filled'; end; end; - ANode := ANode.NextSibling; + node := node.NextSibling; + end; + + // Search the series node. Then create the series and read its properties + // from the subnodes. + node := ANode; + while Assigned(node) do + begin + nodeName := node.NodeName; + case nodeName of + 'c:ser': + begin + if filled then + ser := TsFilledRadarSeries.Create(AChart) + else + ser := TsRadarSeries.Create(AChart); + ReadChartSeriesProps(node.FirstChild, ser); + end; + end; + node := node.NextSibling; end; end; @@ -3827,6 +3847,7 @@ var markerStr: String; chart: TsChart; ser: TsOpenedCustomLineSeries; + symbolSizePts: Integer; begin indent := DupeString(' ', AIndent); chart := ASeries.Chart; @@ -3835,7 +3856,7 @@ begin if ser.ShowSymbols then case ser.Symbol of cssRect: markerStr := 'square'; - cssDiamond: markerStr := 'diamong'; + cssDiamond: markerStr := 'diamond'; cssTriangle: markerStr := 'triangle'; cssTriangleDown: markerStr := 'triangle'; // !!!! cssTriangleLeft: markerStr := 'triangle'; // !!!! @@ -3852,13 +3873,16 @@ begin else markerStr := 'none'; + symbolSizePts := round(mmToPts((ser.SymbolWidth + ser.SymbolHeight)/2)); + if symbolSizePts > 72 then symbolSizePts := 72; + Result := Format( indent + '' + LE + - indent + '' + LE + + indent + '' + LE + indent + '' + LE + GetChartFillAndLineXML(AIndent + 2, chart, ser.SymbolFill, ser.SymbolBorder) + LE + indent + '', - [ markerStr, mmToPts(ser.SymbolWidth + ser.SymbolHeight) ] + [ markerStr, symbolSizePts ] ); end; @@ -3903,6 +3927,8 @@ begin end; ctPie, ctRing: WritePieSeries(AStream, AIndent + 2, TsPieSeries(ser), i); + ctRadar, ctFilledRadar: + WriteRadarSeries(AStream, AIndent + 2, TsRadarSeries(ser), i); ctScatter: begin WriteScatterSeries(AStream, AIndent + 2, TsScatterSeries(ser), i); @@ -3972,6 +3998,39 @@ begin ); end; +procedure TsSpreadOOXMLChartWriter.WriteRadarSeries(AStream: TStream; + AIndent: Integer; ASeries: TsRadarSeries; ASeriesIndex: Integer); +var + indent: String; + chart: TsChart; + radarStyle: String; +begin + indent := DupeString(' ', AIndent); + chart := ASeries.Chart; + + if ASeries.ChartType = ctFilledRadar then + radarStyle := 'filled' + else + radarStyle := 'marker'; + + AppendToStream(AStream, + indent + '' + LE + + indent + ' ' + LE + ); + + WriteChartSeriesNode(AStream, AIndent + 4, ASeries, ASeriesIndex); + + AppendToStream(AStream, Format( + indent + ' ' + LE + + indent + ' ' + LE + + indent + '' + LE, + [ + FAxisID[chart.XAxis.Alignment], // + FAxisID[chart.YAxis.Alignment] // + ] + )); +end; + procedure TsSpreadOOXMLChartWriter.WriteScatterSeries(AStream: TStream; AIndent: Integer; ASeries: TsScatterSeries; ASeriesIndex: Integer); var @@ -4015,7 +4074,7 @@ end; Writes the node for the specified chart series if a trendline is activated. -------------------------------------------------------------------------------} -procedure TsSpreadOOXMLChartWriter.WriteChartRegression(AStream: TStream; +procedure TsSpreadOOXMLChartWriter.WriteChartTrendline(AStream: TStream; AIndent: Integer; ASeries: TsChartSeries); var indent: String; @@ -4182,9 +4241,6 @@ var xRng, yRng: TsChartRange; forceNoLine: Boolean; xValName, yValName, xRefName, yRefName: String; - explosionStr: String = ''; - dps: TsChartDataPointStyle; - i: Integer; begin indent := DupeString(' ', AIndent); chart := ASeries.Chart; @@ -4217,15 +4273,24 @@ begin indent + ' ' + LE ); end else - // Line & scatter series: symbol markers + // Line & scatter & radar series: symbol markers if (ASeries is TsCustomLineSeries) then begin - forceNoLine := not TsOpenedCustomLineSeries(ASeries).ShowLines; - AppendToStream(AStream, - indent + ' ' + LE + - GetChartLineXML(AIndent + 4, chart, ASeries.Line, forceNoLine) + LE + - indent + ' ' + LE - ); + if (ASeries.ChartType = ctFilledRadar) then + AppendToStream(AStream, + indent + ' ' + LE + + GetChartFillAndLineXML(AIndent + 4, chart, ASeries.Fill, ASeries.Line) + LE + + indent + ' ' + LE + ) + else + begin + forceNoLine := not TsOpenedCustomLineSeries(ASeries).ShowLines; + AppendToStream(AStream, + indent + ' ' + LE + + GetChartLineXML(AIndent + 4, chart, ASeries.Line, forceNoLine) + LE + + indent + ' ' + LE + ); + end; if TsOpenedCustomLineSeries(ASeries).ShowSymbols then AppendToStream(AStream, indent + ' ' + LE + @@ -4242,7 +4307,7 @@ begin // Trend line if ASeries.SupportsTrendline then - WriteChartRegression(AStream, AIndent + 2, ASeries); + WriteChartTrendline(AStream, AIndent + 2, ASeries); // Data point labels WriteChartSeriesDatapointLabels(AStream, AIndent + 2, ASeries); diff --git a/components/fpspreadsheet/source/visual/fpspreadsheetchart.pas b/components/fpspreadsheet/source/visual/fpspreadsheetchart.pas index d60b9d329..538a4f72b 100644 --- a/components/fpspreadsheet/source/visual/fpspreadsheetchart.pas +++ b/components/fpspreadsheet/source/visual/fpspreadsheetchart.pas @@ -550,10 +550,11 @@ begin if FIntegerX then value := trunc(value); end else - if FCyclicX then - value := AIndex / FPointsNumber * TWO_PI - else value := AIndex; + // For polar series we rescale the x values to a full circle. + // And the angle begins at the 90° position. + if FCyclicX then + value := value / FPointsNumber * TWO_PI + pi/2; FCurItem.SetX(i, value); end; @@ -2651,8 +2652,8 @@ begin UpdateChartBrush(AWorkbookSeries.Chart, openedWorkbookSeries.SymbolFill, seriesPointer.Brush); UpdateChartPen(AWorkbookSeries.Chart, openedWorkbookSeries.SymbolBorder, seriesPointer.Pen); seriesPointer.Style := POINTER_STYLES[openedWorkbookSeries.Symbol]; - seriesPointer.HorizSize := mmToPx(openedWorkbookSeries.SymbolWidth, ppi); - seriesPointer.VertSize := mmToPx(openedWorkbookSeries.SymbolHeight, ppi); + seriesPointer.HorizSize := mmToPx(openedWorkbookSeries.SymbolWidth / 2, ppi); + seriesPointer.VertSize := mmToPx(openedWorkbookSeries.SymbolHeight / 2, ppi); // Error bars UpdateChartErrorBars(AWorkbookSeries, AChartSeries); @@ -2694,14 +2695,15 @@ begin (AChartSeries.Source as TsWorkbookChartSource).CyclicX := true; UpdateChartPen(AWorkbookSeries.Chart, AWorkbookSeries.Line, AChartSeries.LinePen); - UpdateChartBrush(AWorkbookSeries.Chart, AWorkbookSeries.Fill, AChartSeries.Brush); + if AWorkbookSeries.ChartType = ctFilledRadar then + UpdateChartBrush(AWorkbookSeries.Chart, AWorkbookSeries.Fill, AChartSeries.Brush); if AWorkbookSeries.ShowSymbols then begin UpdateChartBrush(AWorkbookSeries.Chart, AWorkbookSeries.SymbolFill, AChartSeries.Pointer.Brush); UpdateChartPen(AWorkbookSeries.Chart, AWorkbookSeries.SymbolBorder, AChartSeries.Pointer.Pen); AChartSeries.Pointer.Style := POINTER_STYLES[AWorkbookSeries.Symbol]; - AChartSeries.Pointer.HorizSize := mmToPx(AWorkbookSeries.SymbolWidth, ppi); - AChartSeries.Pointer.VertSize := mmToPx(AWorkbookSeries.SymbolHeight, ppi); + AChartSeries.Pointer.HorizSize := mmToPx(AWorkbookSeries.SymbolWidth / 2, ppi); + AChartSeries.Pointer.VertSize := mmToPx(AWorkbookSeries.SymbolHeight / 2, ppi); end; FChart.LeftAxis.Minors.Clear;