fpspreadsheet: Add ods writer demo for TsBubbleSeries. Chart link supports reading TsBubbleSeries (but: size issues to be fixed in TAChart).

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9052 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2023-11-28 21:22:46 +00:00
parent 97d7919d6a
commit 8b51f30e14
5 changed files with 193 additions and 7 deletions

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="12"/>
<PathDelim Value="\"/>
<General>
<Flags>
<MainUnitHasCreateFormStatements Value="False"/>
<MainUnitHasTitleStatement Value="False"/>
<MainUnitHasScaledStatement Value="False"/>
</Flags>
<SessionStorage Value="InProjectDir"/>
<Title Value="bubblechart_write_demo"/>
<UseAppBundle Value="False"/>
<ResourceType Value="res"/>
</General>
<BuildModes>
<Item Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
<UseFileFilters Value="True"/>
</PublishOptions>
<RunParams>
<FormatVersion Value="2"/>
</RunParams>
<RequiredPackages>
<Item>
<PackageName Value="laz_fpspreadsheet"/>
</Item>
</RequiredPackages>
<Units>
<Unit>
<Filename Value="bubblechart_write_demo.lpr"/>
<IsPartOfProject Value="True"/>
</Unit>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<PathDelim Value="\"/>
<Target>
<Filename Value="bubblechart_write_demo"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Debugging>
<DebugInfoType Value="dsDwarf3"/>
</Debugging>
</Linking>
<Other>
<ConfigFile>
<WriteConfigFilePath Value=""/>
</ConfigFile>
</Other>
</CompilerOptions>
<Debugging>
<Exceptions>
<Item>
<Name Value="EAbort"/>
</Item>
<Item>
<Name Value="ECodetoolError"/>
</Item>
<Item>
<Name Value="EFOpenError"/>
</Item>
</Exceptions>
</Debugging>
</CONFIG>

View File

@ -0,0 +1,84 @@
program bubblechart_write_demo;
{.$DEFINE DARK_MODE}
uses
SysUtils,
fpspreadsheet, fpstypes, fpsUtils, fpschart, xlsxooxml, fpsopendocument;
const
FILE_NAME = 'bubble';
sDISTANCE = 'Distance from Sun' + LineEnding + '(relative to Earth)';
sPERIOD = 'Orbital period' + LineEnding + '(relative to Earth)';
sDIAMETER = 'Diameter (km)';
var
book: TsWorkbook;
sheet: TsWorksheet;
ch: TsChart;
ser: TsBubbleSeries;
begin
book := TsWorkbook.Create;
try
// worksheet
sheet := book.AddWorksheet('bubble_series');
// Enter data
sheet.WriteText( 0,0, 'Solar System');
sheet.WriteFont( 0,0, '', 12, [fssBold], scBlack);
sheet.WriteText( 2,0, 'Planet' ); sheet.WriteText ( 2,1, sDistance); sheet.WriteText ( 2,2, sPERIOD); sheet.WriteText (2, 3, sDIAMETER);
sheet.WriteText( 3,0, 'Mercury'); sheet.WriteNumber( 3,1, 0.387); sheet.WriteNumber( 3,2, 0.241); sheet.WriteNumber( 3,3, 4.879E3);
sheet.WriteText( 4,0, 'Venus' ); sheet.WriteNumber( 4,1, 0.723); sheet.WriteNumber( 4,2, 0.615); sheet.WriteNumber( 4,3, 1.210E4);
sheet.WriteText( 5,0, 'Earth' ); sheet.WriteNumber( 5,1, 1.000); sheet.WriteNumber( 5,2, 1.000); sheet.WriteNumber( 5,3, 1.276E4);
sheet.WriteText( 6,0, 'Mars' ); sheet.WriteNumber( 6,1, 1.524); sheet.WriteNumber( 6,2, 1.881); sheet.WriteNumber( 6,3, 6.792E3);
sheet.WriteText( 7,0, 'Jupiter'); sheet.WriteNumber( 7,1, 5.204); sheet.WriteNumber( 7,2, 11.862); sheet.WriteNumber( 7,3, 1.430E5);
sheet.WriteText( 8,0, 'Saturn' ); sheet.WriteNumber( 8,1, 9.582); sheet.WriteNumber( 8,2, 29.445); sheet.WriteNumber( 8,3, 1.205E5);
sheet.WriteText( 9,0, 'Uranus' ); sheet.WriteNumber( 9,1,19.201); sheet.WriteNumber( 9,2, 84.011); sheet.WriteNumber( 9,3, 5.112E4);
sheet.WriteText(10,0, 'Neptune'); sheet.WriteNumber(10,1,30.047); sheet.WriteNumber(10,2,164.79); sheet.WriteNumber(10,3, 4.953E4);
sheet.WriteText(12,0, 'Source: wikipedia');
sheet.WriteFont(12,0, '', 8, [], scBlack);
sheet.WriteColWidth(1, 40.0, suMillimeters);
sheet.WriteColWidth(2, 40.0, suMillimeters);
// Create chart: left/top in cell D4, 150 mm x 150 mm
ch := book.AddChart(sheet, 2, 4, 150, 150);
// Chart properties
ch.Border.Style := clsNoLine;
ch.Title.Caption := 'Solar System';
ch.Title.Font.Style := [fssBold];
ch.Legend.Visible := false;
ch.XAxis.Title.Caption := 'Distance from Sun (relative to Earth)';
ch.XAxis.MinorGridLines.Style := clsNoLine;
ch.XAxis.Logarithmic := true;
ch.YAxis.Title.Caption := 'Orbital period (relative to Earth)';
ch.YAxis.AxisLine.Color := scSilver;
ch.YAxis.MinorGridLines.Style := clsNoLine;
ch.YAxis.Logarithmic := true;
// Add data as bubble series
ser := TsBubbleSeries.Create(ch);
ser.SetLabelRange(3, 0, 10, 0);
ser.SetXRange(3, 1, 10, 1);
ser.SetYRange(3, 2, 10, 2);
ser.SetBubbleRange(3, 3, 10, 3);
ser.Line.Style := clsNoLine;
ser.Fill.Color := $c47244; //72c4 scBlue;
ser.Fill.Transparency := 0.25;
ser.DataLabels := [cdlCategory];
ch.AddSeries(ser);
{
book.WriteToFile(FILE_NAME + '.xlsx', true); // Excel fails to open the file
WriteLn('Data saved with chart in ', FILENAME, '.xlsx');
}
book.WriteToFile(FILE_NAME + '.ods', true);
WriteLn('Data saved with chart in ', FILE_NAME, '.ods');
finally
book.Free;
end;
end.

View File

@ -35,7 +35,8 @@ implementation
{$R *.lfm} {$R *.lfm}
const const
FILE_NAME = '../../../other/chart/bars.ods'; // FILE_NAME = '../../../other/chart/bars.ods';
FILE_NAME = '../../../other/chart/bubble.ods';
// FILE_NAME = '../../../other/chart/area.ods'; // FILE_NAME = '../../../other/chart/area.ods';
// FILE_NAME = '../../../other/chart/area-sameImg.ods'; // FILE_NAME = '../../../other/chart/area-sameImg.ods';
// FILE_NAME = '../../../other/chart/pie.ods'; // FILE_NAME = '../../../other/chart/pie.ods';

View File

@ -391,6 +391,7 @@ type
end; end;
TsBubbleSeries = class(TsChartSeries) TsBubbleSeries = class(TsChartSeries)
// to do: inherited from ScatterSeries, but without symbols
private private
FBubbleRange: TsChartRange; FBubbleRange: TsChartRange;
public public
@ -1629,6 +1630,7 @@ begin
FSubTitle.Font.Size := 12; FSubTitle.Font.Size := 12;
FLegend := TsChartLegend.Create(self); FLegend := TsChartLegend.Create(self);
FLegend.Visible := false;
FXAxis := TsChartAxis.Create(self); FXAxis := TsChartAxis.Create(self);
FXAxis.Title.Caption := 'x axis'; FXAxis.Title.Caption := 'x axis';

View File

@ -23,7 +23,7 @@ uses
LCLVersion, Forms, Controls, Graphics, GraphUtil, Dialogs, LCLVersion, Forms, Controls, Graphics, GraphUtil, Dialogs,
// TAChart // TAChart
TATypes, TATextElements, TAChartUtils, TALegend, TACustomSource, TASources, TATypes, TATextElements, TAChartUtils, TALegend, TACustomSource, TASources,
TACustomSeries, TASeries, TARadialSeries, TAFitUtils, TAFuncSeries, TACustomSeries, TASeries, TARadialSeries, TAFitUtils, TAFuncSeries, TAMultiSeries,
TAChartAxisUtils, TAChartAxis, TAStyles, TAGraph, TAChartAxisUtils, TAChartAxis, TAStyles, TAGraph,
// FPSpreadsheet // FPSpreadsheet
fpsTypes, fpSpreadsheet, fpsUtils, fpsChart, fpsTypes, fpSpreadsheet, fpsUtils, fpsChart,
@ -140,6 +140,7 @@ type
procedure UpdateAreaSeries(AWorkbookSeries: TsAreaSeries; AChartSeries: TAreaSeries); procedure UpdateAreaSeries(AWorkbookSeries: TsAreaSeries; AChartSeries: TAreaSeries);
procedure UpdateBarSeries(AWorkbookSeries: TsBarSeries; AChartSeries: TBarSeries); procedure UpdateBarSeries(AWorkbookSeries: TsBarSeries; AChartSeries: TBarSeries);
procedure UpdateBubbleSeries(AWorkbookSeries: TsBubbleSeries; AChartSeries: TBubbleSeries);
procedure UpdateLineSeries(AWorkbookSeries: TsLineSeries; AChartSeries: TLineSeries); procedure UpdateLineSeries(AWorkbookSeries: TsLineSeries; AChartSeries: TLineSeries);
procedure UpdatePieSeries(AWorkbookSeries: TsPieSeries; AChartSeries: TPieSeries); procedure UpdatePieSeries(AWorkbookSeries: TsPieSeries; AChartSeries: TPieSeries);
procedure UpdatePolarSeries(AWorkbookSeries: TsRadarSeries; AChartSeries: TPolarSeries); procedure UpdatePolarSeries(AWorkbookSeries: TsRadarSeries; AChartSeries: TPolarSeries);
@ -830,8 +831,8 @@ begin
SetLength(FWorksheets[ARangeIndex], Length(FWorksheets[ARangeIndex]) + 1); SetLength(FWorksheets[ARangeIndex], Length(FWorksheets[ARangeIndex]) + 1);
case ARangeIndex of case ARangeIndex of
rngX: XCount := Length(FRanges[ARangeIndex]); rngX: XCount := Max(XCount, Length(FRanges[ARangeIndex]));
rngY: YCount := Length(FRanges[ARangeIndex]); rngY: YCount := Max(YCount, Length(FRanges[ARangeIndex]));
end; end;
SetLength(FRanges[ARangeIndex, AListIndex], 1); // FIXME: Assuming here single-block range !!! SetLength(FRanges[ARangeIndex, AListIndex], 1); // FIXME: Assuming here single-block range !!!
@ -968,7 +969,7 @@ begin
if (calcSrc.Origin is TsWorkbookChartSource) then if (calcSrc.Origin is TsWorkbookChartSource) then
src := TsWorkbookChartSource(calcSrc.Origin); src := TsWorkbookChartSource(calcSrc.Origin);
end else end else
// ... otherwise we use the workbook chartsource directly. // ... otherwise we use the workbook chart source directly.
if (firstSeries.Source is TsWorkbookChartSource) then if (firstSeries.Source is TsWorkbookChartSource) then
begin begin
src := (firstSeries.Source as TsWorkbookChartSource); src := (firstSeries.Source as TsWorkbookChartSource);
@ -978,12 +979,14 @@ begin
src.SetYRange(src.YCount, ASeries.YRange); // <--- This updates also the YCount src.SetYRange(src.YCount, ASeries.YRange); // <--- This updates also the YCount
src.FRangeStr[rngY] := src.BuildRangeStr(rngY); src.FRangeStr[rngY] := src.BuildRangeStr(rngY);
if Result is TBarSeries then if Result is TBarSeries then
TBarSeries(Result).Styles := FChartStyles TBarSeries(Result).Styles := FChartStyles
else if Result is TLineSeries then else if Result is TLineSeries then
TLineSeries(Result).Styles := FChartStyles TLineSeries(Result).Styles := FChartStyles
else if Result is TAreaSeries then else if Result is TAreaSeries then
TAreaSeries(Result).Styles := FChartStyles; TAreaSeries(Result).Styles := FChartStyles;
Result.Legend.Multiplicity := lmStyle; Result.Legend.Multiplicity := lmStyle;
src.SetTitleAddr(ASeries.TitleAddr); src.SetTitleAddr(ASeries.TitleAddr);
@ -997,6 +1000,9 @@ begin
else else
begin begin
// This is either for a non-stackable or the first stackable series. // This is either for a non-stackable or the first stackable series.
src := TsWorkbookChartSource.Create(self);
src.WorkbookSource := FWorkbookSource;
case ASeries.ChartType of case ASeries.ChartType of
ctBar: ctBar:
Result := TBarSeries.Create(FChart); Result := TBarSeries.Create(FChart);
@ -1006,10 +1012,15 @@ begin
Result := TAreaSeries.Create(FChart); Result := TAreaSeries.Create(FChart);
ctRadar, ctFilledRadar: ctRadar, ctFilledRadar:
Result := TPolarSeries.Create(FChart); Result := TPolarSeries.Create(FChart);
ctBubble:
begin
Result := TBubbleSeries.Create(FChart);
src.SetYRange(1, TsBubbleSeries(ASeries).BubbleRange);
end;
else
exit(nil);
end; end;
src := TsWorkbookChartSource.Create(self);
src.WorkbookSource := FWorkbookSource;
if not ASeries.LabelRange.IsEmpty then src.SetLabelRange(ASeries.LabelRange); if not ASeries.LabelRange.IsEmpty then src.SetLabelRange(ASeries.LabelRange);
if not ASeries.XRange.IsEmpty then src.SetXRange(0, ASeries.XRange); if not ASeries.XRange.IsEmpty then src.SetXRange(0, ASeries.XRange);
if not ASeries.YRange.IsEmpty then src.SetYRange(0, ASeries.YRange); if not ASeries.YRange.IsEmpty then src.SetYRange(0, ASeries.YRange);
@ -1039,6 +1050,12 @@ var
axis: TsChartAxis; axis: TsChartAxis;
begin begin
ser := ActiveChartSeries(ASeries); ser := ActiveChartSeries(ASeries);
if ser = nil then
begin
FWorkbook.AddErrorMsg('Series could not be loaded.');
exit;
end;
ser.Transparency := round(ASeries.Fill.Transparency); ser.Transparency := round(ASeries.Fill.Transparency);
axis := ASeries.Chart.YAxis; axis := ASeries.Chart.YAxis;
UpdateChartSeriesMarks(ASeries, ser); UpdateChartSeriesMarks(ASeries, ser);
@ -1059,6 +1076,8 @@ begin
UpdateAreaSeries(TsAreaSeries(ASeries), TAreaSeries(ser)); UpdateAreaSeries(TsAreaSeries(ASeries), TAreaSeries(ser));
ctBar: ctBar:
UpdateBarSeries(TsBarSeries(ASeries), TBarSeries(ser)); UpdateBarSeries(TsBarSeries(ASeries), TBarSeries(ser));
ctBubble:
UpdateBubbleSeries(TsBubbleSeries(ASeries), TBubbleSeries(ser));
ctLine: ctLine:
UpdateLineSeries(TsLineSeries(ASeries), TLineSeries(ser)); UpdateLineSeries(TsLineSeries(ASeries), TLineSeries(ser));
ctScatter: ctScatter:
@ -1403,6 +1422,13 @@ begin
TCalculatedChartSource(AChartSeries.Source).Percentage := (AWorkbookSeries.Chart.StackMode = csmStackedPercentage); TCalculatedChartSource(AChartSeries.Source).Percentage := (AWorkbookSeries.Chart.StackMode = csmStackedPercentage);
end; end;
procedure TsWorkbookChartlink.UpdateBubbleSeries(AWorkbookSeries: TsBubbleSeries;
AChartSeries: TBubbleSeries);
begin
UpdateChartBrush(AWorkbookSeries.Chart, AWorkbookSeries.Fill, AChartSeries.BubbleBrush);
UpdateChartPen(AWorkbookSeries.Chart, AWorkbookSeries.Line, AChartSeries.BubblePen);
end;
procedure TsWorkbookChartLink.UpdateChart; procedure TsWorkbookChartLink.UpdateChart;
var var
ch: TsChart; ch: TsChart;