You've already forked lazarus-ccr
fpspreadsheet: Add support for bubble series.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@8991 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -5,7 +5,7 @@ program write_chart_demo;
|
|||||||
uses
|
uses
|
||||||
SysUtils, fpspreadsheet, fpstypes, fpschart, xlsxooxml, fpsopendocument;
|
SysUtils, fpspreadsheet, fpstypes, fpschart, xlsxooxml, fpsopendocument;
|
||||||
const
|
const
|
||||||
SERIES_CLASS: TsChartSeriesClass = TsScatterSeries;
|
SERIES_CLASS: TsChartSeriesClass = TsBubbleSeries; //TsScatterSeries;
|
||||||
r1 = 1;
|
r1 = 1;
|
||||||
r2 = 8;
|
r2 = 8;
|
||||||
var
|
var
|
||||||
@ -21,18 +21,21 @@ begin
|
|||||||
sheet1 := b.AddWorksheet('test1');
|
sheet1 := b.AddWorksheet('test1');
|
||||||
sheet1.WriteText(0, 1, '1+sin(x)');
|
sheet1.WriteText(0, 1, '1+sin(x)');
|
||||||
sheet1.WriteText(0, 2, '1+sin(x/2)');
|
sheet1.WriteText(0, 2, '1+sin(x/2)');
|
||||||
|
sheet1.WriteText(0, 3, 'Bubble');
|
||||||
for i := r1 to r2-1 do
|
for i := r1 to r2-1 do
|
||||||
begin
|
begin
|
||||||
sheet1.WriteNumber(i, 0, i-1);
|
sheet1.WriteNumber(i, 0, i-1);
|
||||||
sheet1.WriteNumber(i, 1, 1+sin(i-1));
|
sheet1.WriteNumber(i, 1, 1+sin(i-1));
|
||||||
sheet1.WriteNumber(i, 2, 1+sin((i-1)/2));
|
sheet1.WriteNumber(i, 2, 1+sin((i-1)/2));
|
||||||
|
sheet1.WriteNumber(i, 3, i*i); // Bubble series radii
|
||||||
end;
|
end;
|
||||||
sheet1.WriteNumber(r2, 0, 9);
|
sheet1.WriteNumber(r2, 0, 9);
|
||||||
sheet1.WriteNumber(r2, 1, 2);
|
sheet1.WriteNumber(r2, 1, 2);
|
||||||
sheet1.WriteNumber(r2, 2, 2.5);
|
sheet1.WriteNumber(r2, 2, 2.5);
|
||||||
|
sheet1.WriteNumber(r2, 3, r2*r2);
|
||||||
|
|
||||||
// Create chart
|
// Create chart
|
||||||
ch := b.AddChart(sheet1, 4, 4, 160, 100);
|
ch := b.AddChart(sheet1, 4, 6, 160, 100);
|
||||||
|
|
||||||
// Add first series (type depending on SERIES_CLASS)
|
// Add first series (type depending on SERIES_CLASS)
|
||||||
ser := SERIES_CLASS.Create(ch);
|
ser := SERIES_CLASS.Create(ch);
|
||||||
@ -47,16 +50,25 @@ begin
|
|||||||
TsLineSeries(ser).ShowSymbols := true;
|
TsLineSeries(ser).ShowSymbols := true;
|
||||||
TsLineSeries(ser).Symbol := cssCircle;
|
TsLineSeries(ser).Symbol := cssCircle;
|
||||||
end;
|
end;
|
||||||
|
if (ser is TsBubbleSeries) then
|
||||||
|
begin
|
||||||
|
TsBubbleSeries(ser).SetXRange(r1, 0, r2, 0);
|
||||||
|
TsBubbleSeries(ser).SetYRange(r1, 2, r2, 2);
|
||||||
|
TsBubbleSeries(ser).SetBubbleRange(r1, 3, r2, 3);
|
||||||
|
end;
|
||||||
|
|
||||||
// Add second series
|
if SERIES_CLASS <> TsBubbleSeries then
|
||||||
ser := SERIES_CLASS.Create(ch);
|
begin
|
||||||
// ser := TsBarSeries.Create(ch);
|
// Add second series
|
||||||
ser.SetTitleAddr(0, 2);
|
ser := SERIES_CLASS.Create(ch);
|
||||||
ser.SetLabelRange(r1, 0, r2, 0);
|
// ser := TsBarSeries.Create(ch);
|
||||||
ser.SetXRange(r1, 0, r2, 0);
|
ser.SetTitleAddr(0, 2);
|
||||||
ser.SetYRange(r1, 2, r2, 2);
|
ser.SetLabelRange(r1, 0, r2, 0);
|
||||||
ser.Line.Color := scRed;
|
ser.SetXRange(r1, 0, r2, 0);
|
||||||
ser.Fill.FgColor := scRed;
|
ser.SetYRange(r1, 2, r2, 2);
|
||||||
|
ser.Line.Color := scRed;
|
||||||
|
ser.Fill.FgColor := scRed;
|
||||||
|
end;
|
||||||
|
|
||||||
{$IFDEF DARK_MODE}
|
{$IFDEF DARK_MODE}
|
||||||
ch.Background.FgColor := scBlack;
|
ch.Background.FgColor := scBlack;
|
||||||
@ -71,7 +83,7 @@ begin
|
|||||||
ch.Background.Style := fsSolidFill;
|
ch.Background.Style := fsSolidFill;
|
||||||
ch.Border.Style := clsSolid;
|
ch.Border.Style := clsSolid;
|
||||||
ch.PlotArea.Background.Style := fsSolidFill;
|
ch.PlotArea.Background.Style := fsSolidFill;
|
||||||
//ch.RotatedAxes := true;
|
ch.RotatedAxes := true;
|
||||||
ch.StackMode := csmStackedPercentage;
|
ch.StackMode := csmStackedPercentage;
|
||||||
//ch.Interpolation := ciCubicSpline;
|
//ch.Interpolation := ciCubicSpline;
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ type
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
TsChartAxisPosition = (capStart, capEnd, capValue);
|
TsChartAxisPosition = (capStart, capEnd, capValue);
|
||||||
TsChartType = (ctEmpty, ctBar, ctLine, ctArea, ctBarLine, ctScatter);
|
TsChartType = (ctEmpty, ctBar, ctLine, ctArea, ctBarLine, ctScatter, ctBubble);
|
||||||
|
|
||||||
TsChartAxis = class(TsChartFillElement)
|
TsChartAxis = class(TsChartFillElement)
|
||||||
private
|
private
|
||||||
@ -239,6 +239,15 @@ type
|
|||||||
constructor Create(AChart: TsChart); override;
|
constructor Create(AChart: TsChart); override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
TsBubbleSeries = class(TsChartSeries)
|
||||||
|
private
|
||||||
|
FBubbleRange: TsCellRange;
|
||||||
|
public
|
||||||
|
constructor Create(AChart: TsChart); override;
|
||||||
|
procedure SetBubbleRange(ARow1, ACol1, ARow2, ACol2: Cardinal);
|
||||||
|
property BubbleRange: TsCellRange read FBubbleRange;
|
||||||
|
end;
|
||||||
|
|
||||||
TsChartSeriesSymbol = (
|
TsChartSeriesSymbol = (
|
||||||
cssRect, cssDiamond, cssTriangle, cssTriangleDown, cssTriangleLeft,
|
cssRect, cssDiamond, cssTriangle, cssTriangleDown, cssTriangleLeft,
|
||||||
cssTriangleRight, cssCircle, cssStar, cssX, cssPlus, cssAsterisk
|
cssTriangleRight, cssCircle, cssStar, cssX, cssPlus, cssAsterisk
|
||||||
@ -368,7 +377,7 @@ type
|
|||||||
|
|
||||||
{ Connecting line between data points (for line and scatter series) }
|
{ Connecting line between data points (for line and scatter series) }
|
||||||
property Interpolation: TsChartInterpolation read FInterpolation write FInterpolation;
|
property Interpolation: TsChartInterpolation read FInterpolation write FInterpolation;
|
||||||
{ x and y axes exchanged (for bar series) }
|
{ x and y axes exchanged (mainly for bar series, but works also for scatter and bubble series) }
|
||||||
property RotatedAxes: Boolean read FRotatedAxes write FRotatedAxes;
|
property RotatedAxes: Boolean read FRotatedAxes write FRotatedAxes;
|
||||||
{ Stacking of series (for bar and area series ) }
|
{ Stacking of series (for bar and area series ) }
|
||||||
property StackMode: TsChartStackMode read FStackMode write FStackMode;
|
property StackMode: TsChartStackMode read FStackMode write FStackMode;
|
||||||
@ -716,6 +725,23 @@ begin
|
|||||||
FChartType := ctBar;
|
FChartType := ctBar;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TsBubbleSeries }
|
||||||
|
|
||||||
|
constructor TsBubbleSeries.Create(AChart: TsChart);
|
||||||
|
begin
|
||||||
|
inherited;
|
||||||
|
FChartType := ctBubble;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TsBubbleSeries.SetBubbleRange(ARow1, ACol1, ARow2, ACol2: Cardinal);
|
||||||
|
begin
|
||||||
|
if (ARow1 <> ARow2) and (ACol1 <> ACol2) then
|
||||||
|
raise Exception.Create('Series bubble values can only be located in a single column or row.');
|
||||||
|
FBubbleRange.Row1 := ARow1;
|
||||||
|
FBubbleRange.Col1 := ACol1;
|
||||||
|
FBubbleRange.Row2 := ARow2;
|
||||||
|
FBubbleRange.Col2 := ACol2;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TsLineSeries }
|
{ TsLineSeries }
|
||||||
|
|
||||||
|
@ -538,7 +538,7 @@ const
|
|||||||
);
|
);
|
||||||
|
|
||||||
CHART_TYPE_NAMES: array[TsChartType] of string = (
|
CHART_TYPE_NAMES: array[TsChartType] of string = (
|
||||||
'', 'bar', 'line', 'area', 'barLine', 'scatter'
|
'', 'bar', 'line', 'area', 'barLine', 'scatter', 'bubble'
|
||||||
);
|
);
|
||||||
|
|
||||||
CHART_SYMBOL_NAMES: array[TsChartSeriesSymbol] of String = (
|
CHART_SYMBOL_NAMES: array[TsChartSeriesSymbol] of String = (
|
||||||
@ -7142,7 +7142,9 @@ var
|
|||||||
sheet: TsWorksheet;
|
sheet: TsWorksheet;
|
||||||
series: TsChartSeries;
|
series: TsChartSeries;
|
||||||
valuesRange: String;
|
valuesRange: String;
|
||||||
domainRange: String = '';
|
domainRangeX: String = '';
|
||||||
|
domainRangeY: String = '';
|
||||||
|
rangeStr: String = '';
|
||||||
titleAddr: String;
|
titleAddr: String;
|
||||||
count: Integer;
|
count: Integer;
|
||||||
begin
|
begin
|
||||||
@ -7151,10 +7153,10 @@ begin
|
|||||||
series := AChart.Series[ASeriesIndex];
|
series := AChart.Series[ASeriesIndex];
|
||||||
sheet := TsWorkbook(FWorkbook).GetWorksheetByIndex(AChart.sheetIndex);
|
sheet := TsWorkbook(FWorkbook).GetWorksheetByIndex(AChart.sheetIndex);
|
||||||
|
|
||||||
// These are the x values of a scatter plot.
|
// These are the x values of a scatter or bubble plot.
|
||||||
if series is TsScatterSeries then
|
if (series is TsScatterSeries) or (series is TsBubbleSeries) then
|
||||||
begin
|
begin
|
||||||
domainRange := GetSheetCellRangeString_ODS(
|
domainRangeX := GetSheetCellRangeString_ODS(
|
||||||
sheet.Name, sheet.Name,
|
sheet.Name, sheet.Name,
|
||||||
series.XRange.Row1, series.XRange.Col1,
|
series.XRange.Row1, series.XRange.Col1,
|
||||||
series.XRange.Row2, series.XRange.Col2,
|
series.XRange.Row2, series.XRange.Col2,
|
||||||
@ -7162,20 +7164,37 @@ begin
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// These are the y values
|
if series is TsBubbleSeries then
|
||||||
valuesRange := GetSheetCellRangeString_ODS(
|
begin
|
||||||
sheet.Name, sheet.Name,
|
domainRangeY := GetSheetCellRangeString_ODS(
|
||||||
series.YRange.Row1, series.YRange.Col1,
|
sheet.Name, sheet.Name,
|
||||||
series.YRange.Row2, series.YRange.Col2,
|
series.YRange.Row1, series.YRange.Col1,
|
||||||
rfAllRel, false
|
series.YRange.Row2, series.YRange.Col2,
|
||||||
);
|
rfAllRel, false
|
||||||
|
);
|
||||||
|
// These are the bubble radii
|
||||||
|
valuesRange := GetSheetCellRangeString_ODS(
|
||||||
|
sheet.Name, sheet.Name,
|
||||||
|
TsBubbleSeries(series).BubbleRange.Row1, TsBubbleSeries(series).BubbleRange.Col1,
|
||||||
|
TsBubbleSeries(series).BubbleRange.Row2, TsBubbleSeries(series).BubbleRange.Col2,
|
||||||
|
rfAllRel, false
|
||||||
|
);
|
||||||
|
end else
|
||||||
|
// These are the y values of the non-bubble series
|
||||||
|
valuesRange := GetSheetCellRangeString_ODS(
|
||||||
|
sheet.Name, sheet.Name,
|
||||||
|
series.YRange.Row1, series.YRange.Col1,
|
||||||
|
series.YRange.Row2, series.YRange.Col2,
|
||||||
|
rfAllRel, false
|
||||||
|
);
|
||||||
|
|
||||||
// And these are the data point labels.
|
// And these are the data point labels.
|
||||||
titleAddr := GetSheetCellRangeString_ODS(
|
titleAddr := GetSheetCellRangeString_ODS(
|
||||||
sheet.Name, sheet.Name,
|
sheet.Name, sheet.Name,
|
||||||
series.TitleAddr.Row, series.TitleAddr.Col,
|
series.TitleAddr.Row, series.TitleAddr.Col,
|
||||||
series.TitleAddr.Row, series.TitleAddr.Col,
|
series.TitleAddr.Row, series.TitleAddr.Col,
|
||||||
rfAllRel, false);
|
rfAllRel, false
|
||||||
|
);
|
||||||
count := series.YRange.Row2 - series.YRange.Row1 + 1;
|
count := series.YRange.Row2 - series.YRange.Row1 + 1;
|
||||||
|
|
||||||
// Store the series properties
|
// Store the series properties
|
||||||
@ -7186,11 +7205,17 @@ begin
|
|||||||
'chart:class="chart:%s">' + LE,
|
'chart:class="chart:%s">' + LE,
|
||||||
[ AStyleID, valuesRange, titleAddr, CHART_TYPE_NAMES[series.ChartType] ]
|
[ AStyleID, valuesRange, titleAddr, CHART_TYPE_NAMES[series.ChartType] ]
|
||||||
));
|
));
|
||||||
if domainRange <> '' then
|
if domainRangeY <> '' then
|
||||||
AppendToStream(AChartStream, Format(
|
AppendToStream(AChartStream, Format(
|
||||||
indent + '<chart:domain table:cell-range-address="%s"/>' + LE,
|
indent + '<chart:domain table:cell-range-address="%s"/>' + LE,
|
||||||
[ domainRange ]
|
[ domainRangeY ]
|
||||||
));
|
));
|
||||||
|
if domainRangeX <> '' then
|
||||||
|
AppendToStream(AChartStream, Format(
|
||||||
|
indent + '<chart:domain table:cell-range-address="%s"/>' + LE,
|
||||||
|
[ domainRangeX ]
|
||||||
|
));
|
||||||
|
|
||||||
AppendToStream(AChartStream, Format(
|
AppendToStream(AChartStream, Format(
|
||||||
indent + ' <chart:data-point chart:repeated="%d"/>' + LE,
|
indent + ' <chart:data-point chart:repeated="%d"/>' + LE,
|
||||||
[ count ]
|
[ count ]
|
||||||
@ -7478,7 +7503,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
Result := Format(
|
Result := Format(
|
||||||
indent + ' <style:style style:name="ch%d" style:family="chart">' + LE +
|
indent + ' <style:style style:name="ch%d" style:family="chart">', [ AStyleID ]) + LE +
|
||||||
indent + ' <style:chart-properties ' +
|
indent + ' <style:chart-properties ' +
|
||||||
interpolationStr +
|
interpolationStr +
|
||||||
verticalStr +
|
verticalStr +
|
||||||
@ -7489,9 +7514,7 @@ begin
|
|||||||
'chart:auto-size="true" ' +
|
'chart:auto-size="true" ' +
|
||||||
'chart:treat-empty-cells="leave-gap" ' +
|
'chart:treat-empty-cells="leave-gap" ' +
|
||||||
'chart:right-angled-axes="true"/>' + LE +
|
'chart:right-angled-axes="true"/>' + LE +
|
||||||
indent + ' </style:style>' + LE,
|
indent + ' </style:style>' + LE;
|
||||||
[ AStyleID ]
|
|
||||||
);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ <style:style style:name="ch1400" style:family="chart" style:data-style-name="N0">
|
{ <style:style style:name="ch1400" style:family="chart" style:data-style-name="N0">
|
||||||
|
Reference in New Issue
Block a user