fpspreadsheet: Fix width of bar series
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9200 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
parent
5c17dcf97e
commit
5afa428929
@ -60,6 +60,7 @@ begin
|
||||
ch.RotatedAxes := true;
|
||||
fn := fn + '-rotated';
|
||||
end;
|
||||
ch.BarGapWidthPercent := 75;
|
||||
|
||||
// Add 1st bar series ("Student 1")
|
||||
ser := TsBarSeries.Create(ch);
|
||||
|
@ -514,6 +514,7 @@ type
|
||||
FSupportsRegression: Boolean;
|
||||
FXErrorBars: TsChartErrorBars;
|
||||
FYErrorBars: TsChartErrorBars;
|
||||
FGroupIndex: Integer; // series with the same GroupIndex can be stacked
|
||||
procedure SetXErrorBars(AValue: TsChartErrorBars);
|
||||
procedure SetYErrorBars(AValue: TsChartErrorBars);
|
||||
protected
|
||||
@ -552,6 +553,7 @@ type
|
||||
property DataLabelCalloutShape: TsChartLabelCalloutShape read FDataLabelCalloutShape write FDataLabelCalloutShape;
|
||||
property DataPointStyles: TsChartDatapointStyleList read FDataPointStyles;
|
||||
property FillColorRange: TsChartRange read FFillColorRange write FFillColorRange;
|
||||
property GroupIndex: Integer read FGroupIndex write FGroupIndex;
|
||||
property LabelBackground: TsChartFill read FLabelBackground write FLabelBackground;
|
||||
property LabelBorder: TsChartLine read FLabelBorder write FLabelBorder;
|
||||
property LabelFont: TsFont read FLabelFont write FLabelFont;
|
||||
@ -582,13 +584,8 @@ type
|
||||
end;
|
||||
|
||||
TsBarSeries = class(TsChartSeries)
|
||||
private
|
||||
FBarWidthPercent: Integer;
|
||||
FBarOffsetPercent: Integer;
|
||||
public
|
||||
constructor Create(AChart: TsChart); override;
|
||||
property BarWidthPercent: Integer read FBarWidthPercent write FBarWidthPercent;
|
||||
property BarOffsetPercent: Integer read FBarOffsetPercent write FBarOffsetPercent;
|
||||
property Regression;
|
||||
end;
|
||||
|
||||
@ -757,6 +754,8 @@ type
|
||||
FRotatedAxes: Boolean; // For bar series: vertical columns <--> horizontal bars
|
||||
FStackMode: TsChartStackMode; // For bar and area series
|
||||
FInterpolation: TsChartInterpolation; // For line/scatter series: data connection lines
|
||||
FBarGapWidthPercent: Integer; // For bar series: distance between bars (relative to single bar width)
|
||||
FBarOverlapPercent: Integer; // For bar series: overlap between bars
|
||||
|
||||
FTitle: TsChartText;
|
||||
FSubTitle: TsChartText;
|
||||
@ -834,6 +833,11 @@ type
|
||||
{ Attributes of the plot's secondary y axis (right) }
|
||||
property Y2Axis: TsChartAxis read FY2Axis write FY2Axis;
|
||||
|
||||
{ Gap between bars/bar groups, as percentage of single bar width }
|
||||
property BarGapWidthPercent: Integer read FBarGapWidthPercent write FBarGapWidthPercent;
|
||||
{ Overlapping of bars, as percentage of single bar width }
|
||||
property BarOverlapPercent: Integer read FBarOverlapPercent write FBarOverlapPercent;
|
||||
|
||||
{ Connecting line between data points (for line and scatter series) }
|
||||
property Interpolation: TsChartInterpolation read FInterpolation write FInterpolation;
|
||||
{ x and y axes exchanged (mainly for bar series, but works also for scatter and bubble series) }
|
||||
@ -2039,6 +2043,7 @@ begin
|
||||
FLineColorRange := TsChartRange.Create(AChart);
|
||||
FLabelRange := TsChartRange.Create(AChart);
|
||||
FTitleAddr := TsChartCellAddr.Create(AChart);
|
||||
FGroupIndex := -1;
|
||||
|
||||
FFill := TsChartFill.Create;
|
||||
FFill.Style := cfsSolid;
|
||||
@ -2284,6 +2289,7 @@ begin
|
||||
inherited Create(AChart);
|
||||
FChartType := ctArea;
|
||||
FSupportsRegression := true;
|
||||
FGroupIndex := 0;
|
||||
end;
|
||||
|
||||
|
||||
@ -2292,10 +2298,9 @@ end;
|
||||
constructor TsBarSeries.Create(AChart: TsChart);
|
||||
begin
|
||||
inherited Create(AChart);
|
||||
FBarWidthPercent := 80;
|
||||
FBarOffsetPercent := 0;
|
||||
FChartType := ctBar;
|
||||
FSupportsRegression := true;
|
||||
FGroupIndex := 0;
|
||||
end;
|
||||
|
||||
|
||||
@ -2314,7 +2319,7 @@ begin
|
||||
inherited;
|
||||
end;
|
||||
|
||||
{ Empty sheet name will be replace by name of the sheet containing the chart. }
|
||||
{ Empty sheet name will be replaced by the name of the sheet containing the chart. }
|
||||
procedure TsBubbleSeries.SetBubbleRange(ARow1, ACol1, ARow2, ACol2: Cardinal);
|
||||
begin
|
||||
SetBubbleRange('', ARow1, ACol1, '', ARow2, ACol2);
|
||||
@ -2620,7 +2625,6 @@ begin
|
||||
FHatches := TsChartHatchList.Create;
|
||||
FImages := TsChartImageList.Create;
|
||||
|
||||
|
||||
fgradients.AddLinearGradient('g1', scRed, scBlue, 0, 0, 1, 1, 0, 0);
|
||||
|
||||
FWorksheet := nil;
|
||||
@ -2678,6 +2682,9 @@ begin
|
||||
FY2Axis.Position := capEnd;
|
||||
|
||||
FSeriesList := TsChartSeriesList.Create;
|
||||
|
||||
FBarGapWidthPercent := 50;
|
||||
FBarOverlapPercent := 0;
|
||||
end;
|
||||
|
||||
destructor TsChart.Destroy;
|
||||
|
@ -836,6 +836,14 @@ begin
|
||||
s := GetAttrValue(AStyleNode, 'style:rotation-angle');
|
||||
if (s <> '') and TryStrToFloat(s, value, FPointSeparatorSettings) then
|
||||
Axis.LabelRotation := Round(value);
|
||||
|
||||
s := GetAttrValue(AStyleNode, 'chart:gap-width'); // why did they put this here ???
|
||||
if TryStrToFloat(s, value, FPointSeparatorSettings) then
|
||||
AChart.BarGapWidthPercent := round(value);
|
||||
|
||||
s := GetAttrValue(AStyleNode, 'chart:overlap'); // why did they put this here ???
|
||||
if TryStrToFloat(s, value, FPointSeparatorSettings) then
|
||||
AChart.BarOverlapPercent := round(value);
|
||||
end;
|
||||
end;
|
||||
AStyleNode := AStyleNode.NextSibling;
|
||||
@ -2220,6 +2228,11 @@ begin
|
||||
angle := Axis.LabelRotation;
|
||||
chartProps := chartProps + Format('style:rotation-angle="%.1f" ', [angle], FPointSeparatorSettings);
|
||||
|
||||
// Bar series gap distance and over lap -- why did they put it here?
|
||||
if (chart.GetChartType = ctBar) and (Axis = chart.YAxis) then
|
||||
chartProps := chartProps + Format(
|
||||
'chart:gap-width="%d" chart:overlap="%d" ', [chart.BarGapWidthPercent, chart.BarOverlapPercent]);
|
||||
|
||||
// Label orientation
|
||||
graphProps := 'svg:stroke-color="' + ColorToHTMLColorStr(Axis.AxisLine.Color) + '" ';
|
||||
|
||||
|
@ -156,6 +156,8 @@ const
|
||||
|
||||
FALSE_TRUE: Array[boolean] of String = ('0', '1');
|
||||
LEGEND_POS: Array[TsChartLegendPosition] of string = ('r', 't', 'b', 'l');
|
||||
GROUPING: Array[TsChartStackMode] of string = ('clustered', 'stacked', 'percentStacked');
|
||||
|
||||
|
||||
{$INCLUDE xlsxooxmlchart_hatch.inc}
|
||||
|
||||
@ -454,6 +456,7 @@ begin
|
||||
while Assigned(ANode) do
|
||||
begin
|
||||
nodeName := ANode.NodeName;
|
||||
s := GetAttrValue(ANode, 'val');
|
||||
case nodeName of
|
||||
'c:ser':
|
||||
begin
|
||||
@ -461,27 +464,23 @@ begin
|
||||
ReadChartSeriesProps(ANode.FirstChild, ser);
|
||||
end;
|
||||
'c:barDir':
|
||||
begin
|
||||
s := GetAttrValue(ANode, 'val');
|
||||
case s of
|
||||
'col': AChart.RotatedAxes := false;
|
||||
'bar': AChart.RotatedAxes := true;
|
||||
end;
|
||||
case s of
|
||||
'col': AChart.RotatedAxes := false;
|
||||
'bar': AChart.RotatedAxes := true;
|
||||
end;
|
||||
'c:grouping':
|
||||
begin
|
||||
s := GetAttrValue(ANode, 'val');
|
||||
case s of
|
||||
'stacked': AChart.StackMode := csmStacked;
|
||||
'percentStacked': AChart.StackMode := csmStackedPercentage;
|
||||
end;
|
||||
case s of
|
||||
'stacked': AChart.StackMode := csmStacked;
|
||||
'percentStacked': AChart.StackMode := csmStackedPercentage;
|
||||
end;
|
||||
'c:varyColors':
|
||||
;
|
||||
'c:dLbls':
|
||||
s := '';
|
||||
'c:gapWidth':
|
||||
;
|
||||
; // see BarSeries
|
||||
'c:overlap':
|
||||
; // see BarSeries
|
||||
'c:axId':
|
||||
ReadChartSeriesAxis(ANode, ser);
|
||||
end;
|
||||
@ -499,11 +498,19 @@ begin
|
||||
s := GetAttrValue(ANode, 'val');
|
||||
case nodeName of
|
||||
'c:gapWidth':
|
||||
if TryStrToFloat(s, n, FPointSeparatorSettings) then
|
||||
AChart.BarGapWidthPercent := round(n);
|
||||
{
|
||||
if TryStrToFloat(s, n, FPointSeparatorSettings) then
|
||||
ser.BarWidthPercent := round(100 / (1 + n/100));
|
||||
}
|
||||
'c:overlap':
|
||||
if TryStrToFloat(s, n, FPointSeparatorSettings) then
|
||||
AChart.BarOverlapPercent := round(n);
|
||||
{
|
||||
if TryStrToFloat(s, n, FPointSeparatorSettings) then
|
||||
ser.BarOffsetPercent := round(n);
|
||||
}
|
||||
end;
|
||||
ANode := ANode.NextSibling;
|
||||
end;
|
||||
@ -3349,27 +3356,69 @@ procedure TsSpreadOOXMLChartWriter.WriteBarSeries(AStream: TStream;
|
||||
var
|
||||
indent: String;
|
||||
chart: TsChart;
|
||||
gapWidth: Integer = 0;
|
||||
overlap: Integer = 999;
|
||||
isFirstOfGroup: Boolean = true;
|
||||
isLastOfGroup: Boolean = true;
|
||||
{
|
||||
function GroupWidth: Integer;
|
||||
var
|
||||
i: Integer;
|
||||
ser: TsChartSeries;
|
||||
begin
|
||||
Result := 1;
|
||||
if chart.StackMode = csmSideBySide then
|
||||
for i := ASeriesIndex-1 downto 0 do
|
||||
begin
|
||||
ser := chart.Series[i];
|
||||
if (ser is TsBarseries) and (ser.GroupIndex = ASeries.GroupIndex) then
|
||||
inc(Result);
|
||||
end;
|
||||
end;
|
||||
}
|
||||
begin
|
||||
indent := DupeString(' ', AIndent);
|
||||
chart := ASeries.Chart;
|
||||
|
||||
AppendToStream(AStream,
|
||||
indent + '<c:barChart>' + LE +
|
||||
indent + ' <c:barDir val="col"/>' + LE +
|
||||
indent + ' <c:grouping val="clustered"/>' + LE
|
||||
);
|
||||
if ASeries.GroupIndex > -1 then
|
||||
begin
|
||||
if (ASeriesIndex > 0) and (chart.Series[ASeriesIndex-1].GroupIndex = ASeries.GroupIndex) then
|
||||
isfirstOfGroup := false;
|
||||
if (ASeriesIndex < chart.Series.Count-1) and (chart.Series[ASeriesIndex+1].GroupIndex = ASeries.GroupIndex) then
|
||||
isLastOfGroup := false;
|
||||
if chart.StackMode <> csmSideBySide then
|
||||
overlap := 100
|
||||
end;
|
||||
|
||||
if isFirstOfGroup then
|
||||
AppendToStream(AStream, Format(
|
||||
indent + '<c:barChart>' + LE +
|
||||
indent + ' <c:barDir val="col"/>' + LE +
|
||||
indent + ' <c:grouping val="%s"/>' + LE,
|
||||
[ GROUPING[chart.StackMode] ]
|
||||
));
|
||||
|
||||
WriteChartSeriesNode(AStream, AIndent + 2, ASeries, ASeriesIndex);
|
||||
|
||||
AppendToStream(AStream, Format(
|
||||
indent + ' <c:axId val="%d"/>' + LE +
|
||||
indent + ' <c:axId val="%d"/>' + LE +
|
||||
indent + '</c:barChart>' + LE,
|
||||
[
|
||||
FAxisID[ASeries.Chart.XAxis.Alignment], // <c:axId>
|
||||
FAxisID[ASeries.Chart.YAxis.Alignment] // <c:axId>
|
||||
]
|
||||
));
|
||||
if isLastOfGroup then
|
||||
begin
|
||||
if overlap = 999 then
|
||||
overlap := chart.BarOverlapPercent;
|
||||
gapWidth := chart.BarGapWidthPercent;
|
||||
AppendToStream(AStream, Format(
|
||||
indent + ' <c:gapWidth val="%d"/>' + LE +
|
||||
indent + ' <c:overlap val="%d"/>' + LE +
|
||||
indent + ' <c:axId val="%d"/>' + LE +
|
||||
indent + ' <c:axId val="%d"/>' + LE +
|
||||
indent + '</c:barChart>' + LE,
|
||||
[
|
||||
gapWidth, // <c:gapWidth>
|
||||
overlap, // <c:overlap>
|
||||
FAxisID[ASeries.Chart.XAxis.Alignment], // <c:axId>
|
||||
FAxisID[ASeries.Chart.YAxis.Alignment] // <c:axId>
|
||||
]
|
||||
));
|
||||
end;
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
|
@ -142,7 +142,6 @@ type
|
||||
function ActiveChartSeries(ASeries: TsChartSeries): TChartSeries;
|
||||
procedure AddSeries(ASeries: TsChartSeries);
|
||||
procedure FixAreaSeries({%H-}AWorkbookChart: TsChart);
|
||||
procedure FixBarSeries(AWorkbookChart: TsChart);
|
||||
procedure FixSource(AChartSeries: TBasicPointSeries);
|
||||
procedure ClearChart;
|
||||
procedure ConstructHatchPattern(AWorkbookChart: TsChart; AFill: TsChartFill; ABrush: TBrush);
|
||||
@ -1638,38 +1637,6 @@ begin
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Adjusts bar widths and offsets for side-by-side bar charts.
|
||||
-------------------------------------------------------------------------------}
|
||||
procedure TsWorkbookChartLink.FixBarSeries(AWorkbookChart: TsChart);
|
||||
const
|
||||
TOTAL_BARWIDTH = 75;
|
||||
var
|
||||
i, n: Integer;
|
||||
wBar: Integer;
|
||||
offs: Integer;
|
||||
ser: TBarSeries;
|
||||
begin
|
||||
if AWorkbookChart.GetChartType <> ctBar then
|
||||
exit;
|
||||
|
||||
// Count number of bar series
|
||||
n := 0;
|
||||
for i := 0 to FChart.SeriesCount - 1 do
|
||||
if FChart.Series[i] is TBarSeries then inc(n);
|
||||
|
||||
// Calc bar width and adjust offset of each series within group
|
||||
wBar := TOTAL_BARWIDTH div n;
|
||||
offs := (wBar - TOTAL_BARWIDTH) div 2;
|
||||
for i := 0 to FChart.SeriesCount - 1 do
|
||||
if FChart.Series[i] is TBarSeries then
|
||||
begin
|
||||
ser := TBarSeries(FChart.Series[i]);
|
||||
ser.BarWidthPercent := wBar;
|
||||
ser.BarOffsetPercent := offs + wBar * i;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsWorkbookChartLink.FixSource(AChartSeries: TBasicPointSeries);
|
||||
var
|
||||
i, j, nx, ny: Integer;
|
||||
@ -1901,12 +1868,31 @@ end;
|
||||
|
||||
procedure TsWorkbookChartLink.UpdateBarSeries(AWorkbookSeries: TsBarSeries;
|
||||
AChartSeries: TBarSeries);
|
||||
|
||||
function CalcBarWidthPercent: Integer;
|
||||
var
|
||||
ser: TsChartSeries;
|
||||
gapwidth: Integer;
|
||||
i, n: Integer;
|
||||
begin
|
||||
n := 1;
|
||||
if (AWorkbookSeries.Chart.GetChartType = ctBar) and (AWorkbookSeries.Chart.StackMode = csmSideBySide) then
|
||||
for i := 0 to AWorkbookSeries.Chart.Series.Count-1 do
|
||||
begin
|
||||
ser := AWorkbookSeries.Chart.Series[i];
|
||||
if (ser <> AWorkbookSeries) and (ser.GroupIndex = AWorkbookSeries.GroupIndex) then
|
||||
inc(n);
|
||||
end;
|
||||
gapWidth := AWorkbookSeries.Chart.BarGapWidthPercent;
|
||||
Result := round(100/(n + gapWidth/100) * n);
|
||||
end;
|
||||
|
||||
begin
|
||||
UpdateChartBrush(AWorkbookSeries.Chart, AWorkbookSeries.Fill, AChartSeries.BarBrush);
|
||||
UpdateChartPen(AWorkbookSeries.Chart, AWorkbookSeries.Line, AChartSeries.BarPen);
|
||||
AChartSeries.Transparency := round(AWorkbookSeries.Fill.Transparency * 255);
|
||||
AChartSeries.BarWidthPercent := AWorkbookSeries.BarWidthPercent;
|
||||
AChartSeries.BarOffsetPercent := AWorkbookSeries.BarOffsetPercent;
|
||||
AChartSeries.BarWidthPercent := CalcBarWidthPercent; //AWorkbookSeries.BarWidthPercent;
|
||||
AChartSeries.BarOffsetPercent := 0; //AWorkbookSeries.BarOffsetPercent;
|
||||
AChartSeries.BarWidthStyle := bwPercentMin;
|
||||
AChartSeries.Stacked := AWorkbookSeries.Chart.StackMode <> csmSideBySide;
|
||||
if AChartSeries.Source is TCalculatedChartSource then
|
||||
@ -1973,7 +1959,6 @@ begin
|
||||
FChart.Prepare;
|
||||
UpdateChartAxisLabels(ch);
|
||||
FixAreaSeries(ch);
|
||||
FixBarSeries(ch);
|
||||
end;
|
||||
|
||||
procedure TsWorkbookChartLink.UpdateChartAxis(AWorkbookAxis: TsChartAxis);
|
||||
|
Loading…
Reference in New Issue
Block a user