You've already forked lazarus-ccr
fpspreadsheet: No longer ignore worksheets in chart cell ranges.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9020 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -7,7 +7,7 @@ uses
|
||||
fpspreadsheet, fpstypes, fpsUtils, fpschart, xlsxooxml, fpsopendocument;
|
||||
|
||||
const
|
||||
FILE_NAME = 'world-population';
|
||||
FILE_NAME = 'pie';
|
||||
var
|
||||
book: TsWorkbook;
|
||||
sheet: TsWorksheet;
|
||||
|
@ -7,7 +7,7 @@ uses
|
||||
fpspreadsheet, fpstypes, fpsUtils, fpschart, xlsxooxml, fpsopendocument;
|
||||
|
||||
const
|
||||
FILE_NAME = 'school-grades';
|
||||
FILE_NAME = 'radar';
|
||||
var
|
||||
book: TsWorkbook;
|
||||
sheet: TsWorksheet;
|
||||
|
@ -2,17 +2,22 @@ program read_chart_demo;
|
||||
|
||||
uses
|
||||
SysUtils, TypInfo,
|
||||
fpSpreadsheet, fpsTypes, fpsChart, fpsOpenDocument;
|
||||
fpSpreadsheet, fpsTypes, fpsUtils, fpsChart, fpsOpenDocument;
|
||||
|
||||
const
|
||||
FILE_NAME = 'test.ods';
|
||||
// FILE_NAME = 'test.ods';
|
||||
// FILE_NAME = 'area.ods';
|
||||
FILE_NAME = 'bars.ods';
|
||||
var
|
||||
book: TsWorkbook;
|
||||
sheet: TsWorksheet;
|
||||
chart: TsChart;
|
||||
i, j: Integer;
|
||||
s: String;
|
||||
isODS: Boolean;
|
||||
begin
|
||||
isODS := ExtractFileExt(FILE_NAME) = '.ods';
|
||||
|
||||
book := TsWorkbook.Create;
|
||||
try
|
||||
book.ReadFromFile(FILE_NAME);
|
||||
@ -129,6 +134,11 @@ begin
|
||||
' Font: "', chart.XAxis.Title.Font.FontName, '" Size:', chart.XAxis.Title.Font.Size:0:0,
|
||||
' Style:', SetToString(PTypeInfo(TypeInfo(TsFontStyles)), integer(chart.XAxis.Title.Font.Style), True),
|
||||
' Color:', IntToHex(chart.XAxis.Title.Font.Color, 6));
|
||||
with chart.XAxis.CategoryRange do
|
||||
if isODS then
|
||||
WriteLn(' CATEGORIES: ', GetSheetCellRangeString_ODS(Sheet1, Sheet2, Row1, Col1, Row2, Col2))
|
||||
else
|
||||
WriteLn(' CATEGORIES: ', GetCellRangeString(Sheet1, Sheet2, Row1, Col1, Row2, Col2));
|
||||
WriteLn(' RANGE: AutomaticMin:', chart.XAxis.AutomaticMin, ' Minimum: ', chart.XAxis.Min:0:3,
|
||||
' AutomaticMax:', chart.XAxis.AutomaticMax, ' Maximum: ', chart.XAxis.Max:0:3);
|
||||
WriteLn(' POSITION: ', GetEnumName(TypeInfo(TsChartAxisPosition), ord(chart.XAXis.Position)),
|
||||
@ -159,6 +169,11 @@ begin
|
||||
' Font: "', chart.YAxis.Title.Font.FontName, '" Size:', chart.YAxis.Title.Font.Size:0:0,
|
||||
' Style:', SetToString(PTypeInfo(TypeInfo(TsFontStyles)), integer(chart.YAxis.Title.Font.Style), True),
|
||||
' Color:', IntToHex(chart.YAxis.Title.Font.Color, 6));
|
||||
with chart.YAxis.CategoryRange do
|
||||
if isODS then
|
||||
WriteLn(' CATEGORIES: ', GetSheetCellRangeString_ODS(Sheet1, Sheet2, Row1, Col1, Row2, Col2))
|
||||
else
|
||||
WriteLn(' CATEGORIES: ', GetCellRangeString(Sheet1, Sheet2, Row1, Col1, Row2, Col2));
|
||||
WriteLn(' RANGE: AutomaticMin:', chart.YAxis.AutomaticMin, ' Minimum: ', chart.YAxis.Min:0:3,
|
||||
' AutomaticMax:', chart.YAxis.AutomaticMax, ' Maximum: ', chart.YAxis.Max:0:3);
|
||||
WriteLn(' POSITION: ', GetEnumName(TypeInfo(TsChartAxisPosition), ord(chart.YAXis.Position)),
|
||||
|
@ -144,6 +144,30 @@ type
|
||||
property Items[AIndex: Integer]: TsChartLineStyle read GetItem write SetItem; default;
|
||||
end;
|
||||
|
||||
TsChartCellAddr = class
|
||||
private
|
||||
FChart: TsChart;
|
||||
public
|
||||
Sheet: String;
|
||||
Row, Col: Cardinal;
|
||||
constructor Create(AChart: TsChart);
|
||||
function GetSheetName: String;
|
||||
function IsUsed: Boolean;
|
||||
end;
|
||||
|
||||
TsChartRange = class
|
||||
private
|
||||
FChart: TsChart;
|
||||
public
|
||||
Sheet1, Sheet2: String;
|
||||
Row1, Col1, Row2, Col2: Cardinal;
|
||||
constructor Create(AChart: TsChart);
|
||||
procedure Assign(ASource: TsChartRange);
|
||||
function GetSheet1Name: String;
|
||||
function GetSheet2Name: String;
|
||||
function IsUsed: Boolean;
|
||||
end;
|
||||
|
||||
TsChartElement = class
|
||||
private
|
||||
FChart: TsChart;
|
||||
@ -195,7 +219,7 @@ type
|
||||
FAutomaticMajorInterval: Boolean;
|
||||
FAutomaticMinorSteps: Boolean;
|
||||
FAxisLine: TsChartLine;
|
||||
FCategoryRange: TsCellRange;
|
||||
FCategoryRange: TsChartRange;
|
||||
FMajorGridLines: TsChartLine;
|
||||
FMinorGridLines: TsChartline;
|
||||
FInverted: Boolean;
|
||||
@ -222,7 +246,7 @@ type
|
||||
property AutomaticMajorInterval: Boolean read FAutomaticMajorInterval write FAutomaticMajorInterval;
|
||||
property AutomaticMinorSteps: Boolean read FAutomaticMinorSteps write FAutomaticMinorSteps;
|
||||
property AxisLine: TsChartLine read FAxisLine write FAxisLine;
|
||||
property CategoryRange: TsCellRange read FCategoryRange write FCategoryRange;
|
||||
property CategoryRange: TsChartRange read FCategoryRange write FCategoryRange;
|
||||
property Inverted: Boolean read FInverted write FInverted;
|
||||
property LabelFont: TsFont read FLabelFont write FLabelFont;
|
||||
property LabelFormat: String read FLabelFormat write FLabelFormat;
|
||||
@ -271,15 +295,15 @@ type
|
||||
TsChartSeries = class(TsChartElement)
|
||||
private
|
||||
FChartType: TsChartType;
|
||||
FXRange: TsCellRange; // cell range containing the x data
|
||||
FYRange: TsCellRange;
|
||||
FLabelRange: TsCellRange;
|
||||
FXRange: TsChartRange; // cell range containing the x data
|
||||
FYRange: TsChartRange;
|
||||
FFillColorRange: TsChartRange;
|
||||
FLabelRange: TsChartRange;
|
||||
FLabelFont: TsFont;
|
||||
FLabelPosition: TsChartLabelPosition;
|
||||
FLabelSeparator: string;
|
||||
FFillColorRange: TsCellRange;
|
||||
FYAxis: TsChartAxisLink;
|
||||
FTitleAddr: TsCellCoord;
|
||||
FTitleAddr: TsChartCellAddr;
|
||||
FLabelFormat: String;
|
||||
FLine: TsChartLine;
|
||||
FFill: TsChartFill;
|
||||
@ -296,10 +320,15 @@ type
|
||||
function HasXValues: Boolean;
|
||||
function HasYValues: Boolean;
|
||||
procedure SetTitleAddr(ARow, ACol: Cardinal);
|
||||
procedure SetTitleAddr(ASheet: String; ARow, ACol: Cardinal);
|
||||
procedure SetLabelRange(ARow1, ACol1, ARow2, ACol2: Cardinal);
|
||||
procedure SetLabelRange(ASheet1: String; ARow1, ACol1: Cardinal; ASheet2: String; ARow2, ACol2: Cardinal);
|
||||
procedure SetXRange(ARow1, ACol1, ARow2, ACol2: Cardinal);
|
||||
procedure SetXRange(ASheet1: String; ARow1, ACol1: Cardinal; ASheet2: String; ARow2, ACol2: Cardinal);
|
||||
procedure SetYRange(ARow1, ACol1, ARow2, ACol2: Cardinal);
|
||||
procedure SetYRange(ASheet1: String; ARow1, ACol1: Cardinal; ASheet2: String; ARow2, ACol2: Cardinal);
|
||||
procedure SetFillColorRange(ARow1, ACol1, ARow2, ACol2: Cardinal);
|
||||
procedure SetFillColorRange(ASheet1: String; ARow1, ACol1: Cardinal; ASheet2: String; ARow2, ACol2: Cardinal);
|
||||
function LabelsInCol: Boolean;
|
||||
function XValuesInCol: Boolean;
|
||||
function YValuesInCol: Boolean;
|
||||
@ -307,15 +336,15 @@ type
|
||||
property ChartType: TsChartType read GetChartType;
|
||||
property Count: Integer read GetCount;
|
||||
property DataLabels: TsChartDataLabels read FDataLabels write FDataLabels;
|
||||
property FillColorRange: TsCellRange read FFillColorRange;
|
||||
property FillColorRange: TsChartRange read FFillColorRange;
|
||||
property LabelFont: TsFont read FLabelFont write FLabelFont;
|
||||
property LabelFormat: String read FLabelFormat write FLabelFormat; // Number format in Excel notation, e.g. '0.00'
|
||||
property LabelPosition: TsChartLabelPosition read FLabelPosition write FLabelPosition;
|
||||
property LabelRange: TsCellRange read FLabelRange;
|
||||
property LabelRange: TsChartRange read FLabelRange;
|
||||
property LabelSeparator: string read FLabelSeparator write FLabelSeparator;
|
||||
property TitleAddr: TsCellCoord read FTitleAddr write FTitleAddr; // use '\n' for line-break
|
||||
property XRange: TsCellRange read FXRange;
|
||||
property YRange: TsCellRange read FYRange;
|
||||
property TitleAddr: TsChartCellAddr read FTitleAddr write FTitleAddr; // use '\n' for line-break
|
||||
property XRange: TsChartRange read FXRange;
|
||||
property YRange: TsChartRange read FYRange;
|
||||
property YAxis: TsChartAxisLink read FYAxis write FYAxis;
|
||||
|
||||
property Fill: TsChartFill read FFill write FFill;
|
||||
@ -335,11 +364,13 @@ type
|
||||
|
||||
TsBubbleSeries = class(TsChartSeries)
|
||||
private
|
||||
FBubbleRange: TsCellRange;
|
||||
FBubbleRange: TsChartRange;
|
||||
public
|
||||
constructor Create(AChart: TsChart); override;
|
||||
destructor Destroy; override;
|
||||
procedure SetBubbleRange(ARow1, ACol1, ARow2, ACol2: Cardinal);
|
||||
property BubbleRange: TsCellRange read FBubbleRange;
|
||||
procedure SetBubbleRange(ASheet1: String; ARow1, ACol1: Cardinal; ASheet2: String; ARow2, ACol2: Cardinal);
|
||||
property BubbleRange: TsChartRange read FBubbleRange;
|
||||
end;
|
||||
|
||||
TsChartSeriesSymbol = (
|
||||
@ -449,6 +480,7 @@ type
|
||||
private
|
||||
FName: String;
|
||||
FIndex: Integer; // Index in workbook's chart list
|
||||
FWorkbook: TsBasicWorkbook;
|
||||
FSheetIndex: Integer;
|
||||
FRow, FCol: Cardinal;
|
||||
FOffsetX, FOffsetY: Double;
|
||||
@ -473,11 +505,13 @@ type
|
||||
FLineStyles: TsChartLineStyleList;
|
||||
FGradients: TsChartGradientList;
|
||||
FHatches: TsChartHatchList;
|
||||
function GetCategoryLabelRange: TsCellRange;
|
||||
function GetCategoryLabelRange: TsChartRange;
|
||||
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
function GetWorksheet: TsBasicWorksheet;
|
||||
|
||||
function AddSeries(ASeries: TsChartSeries): Integer;
|
||||
procedure DeleteSeries(AIndex: Integer);
|
||||
|
||||
@ -504,6 +538,8 @@ type
|
||||
property Width: double read FWidth write FWidth;
|
||||
{ Height of the chart, in mm }
|
||||
property Height: double read FHeight write FHeight;
|
||||
{ Workbook to which the chart belongs }
|
||||
property Workbook: TsBasicWorkbook read FWorkbook write FWorkbook;
|
||||
|
||||
{ Attributes of the entire chart background }
|
||||
property Background: TsChartFill read FBackground write FBackground;
|
||||
@ -537,7 +573,7 @@ type
|
||||
{ Stacking of series (for bar and area series ) }
|
||||
property StackMode: TsChartStackMode read FStackMode write FStackMode;
|
||||
|
||||
property CategoryLabelRange: TsCellRange read GetCategoryLabelRange;
|
||||
property CategoryLabelRange: TsChartRange read GetCategoryLabelRange;
|
||||
|
||||
{ Attributes of the series }
|
||||
property Series: TsChartSeriesList read FSeriesList write FSeriesList;
|
||||
@ -559,6 +595,9 @@ type
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
fpSpreadsheet;
|
||||
|
||||
{ TsChartGradient }
|
||||
|
||||
constructor TsChartGradient.Create;
|
||||
@ -796,6 +835,77 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
{ TsChartCellAddr }
|
||||
|
||||
constructor TsChartCellAddr.Create(AChart: TsChart);
|
||||
begin
|
||||
FChart := AChart;
|
||||
Sheet := '';
|
||||
Row := UNASSIGNED_ROW_COL_INDEX;
|
||||
Col := UNASSIGNED_ROW_COL_INDEX;
|
||||
end;
|
||||
|
||||
function TsChartCellAddr.GetSheetName: String;
|
||||
begin
|
||||
if Sheet <> '' then
|
||||
Result := Sheet
|
||||
else
|
||||
Result := FChart.GetWorksheet.Name;
|
||||
end;
|
||||
|
||||
function TsChartCellAddr.IsUsed: Boolean;
|
||||
begin
|
||||
Result := (Row <> UNASSIGNED_ROW_COL_INDEX) and (Col <> UNASSIGNED_ROW_COL_INDEX);
|
||||
end;
|
||||
|
||||
|
||||
{ TsChartRange }
|
||||
|
||||
constructor TsChartRange.Create(AChart: TsChart);
|
||||
begin
|
||||
FChart := AChart;
|
||||
Sheet1 := '';
|
||||
Sheet2 := '';
|
||||
Row1 := UNASSIGNED_ROW_COL_INDEX;
|
||||
Col1 := UNASSIGNED_ROW_COL_INDEX;
|
||||
Row2 := UNASSIGNED_ROW_COL_INDEX;
|
||||
Col2 := UNASSIGNED_ROW_COL_INDEX;
|
||||
end;
|
||||
|
||||
procedure TsChartRange.Assign(ASource: TsChartRange);
|
||||
begin
|
||||
Sheet1 := ASource.Sheet1;
|
||||
Sheet2 := ASource.Sheet2;
|
||||
Row1 := ASource.Row1;
|
||||
Col1 := ASource.Col1;
|
||||
Row2 := ASource.Row2;
|
||||
Col2 := ASource.Col2;
|
||||
end;
|
||||
|
||||
function TsChartRange.GetSheet1Name: String;
|
||||
begin
|
||||
if Sheet1 <> '' then
|
||||
Result := Sheet1
|
||||
else
|
||||
Result := FChart.GetWorksheet.Name;
|
||||
end;
|
||||
|
||||
function TsChartRange.GetSheet2Name: String;
|
||||
begin
|
||||
if Sheet2 <> '' then
|
||||
Result := Sheet2
|
||||
else
|
||||
Result := FChart.GetWorksheet.Name;
|
||||
end;
|
||||
|
||||
function TsChartRange.IsUsed: Boolean;
|
||||
begin
|
||||
Result :=
|
||||
(Row1 <> UNASSIGNED_ROW_COL_INDEX) and (Col1 <> UNASSIGNED_ROW_COL_INDEX) and
|
||||
(Row2 <> UNASSIGNED_ROW_COL_INDEX) and (Col2 <> UNASSIGNED_ROW_COL_INDEX);
|
||||
end;
|
||||
|
||||
|
||||
{ TsChartElement }
|
||||
|
||||
constructor TsChartElement.Create(AChart: TsChart);
|
||||
@ -860,6 +970,8 @@ begin
|
||||
FAutomaticMajorInterval := true;
|
||||
FAutomaticMinorSteps := true;
|
||||
|
||||
FCategoryRange := TsChartRange.Create(AChart);
|
||||
|
||||
FTitle := TsChartText.Create(AChart);
|
||||
|
||||
FLabelFont := TsFont.Create;
|
||||
@ -897,6 +1009,7 @@ begin
|
||||
FAxisLine.Free;
|
||||
FLabelFont.Free;
|
||||
FTitle.Free;
|
||||
FCategoryRange.Free;
|
||||
inherited;
|
||||
end;
|
||||
|
||||
@ -928,6 +1041,12 @@ begin
|
||||
|
||||
idx := AChart.AddSeries(self);
|
||||
|
||||
FXRange := TsChartRange.Create(AChart);
|
||||
FYRange := TsChartRange.Create(AChart);
|
||||
FFillColorRange := TsChartRange.Create(AChart);
|
||||
FLabelRange := TsChartRange.Create(AChart);
|
||||
FTitleAddr := TsChartCellAddr.Create(AChart);
|
||||
|
||||
FFill := TsChartFill.Create;
|
||||
FFill.Style := cfsSolid;
|
||||
FFill.Color := DEFAULT_SERIES_COLORS[idx mod Length(DEFAULT_SERIES_COLORS)];
|
||||
@ -949,6 +1068,11 @@ begin
|
||||
FLabelFont.Free;
|
||||
FLine.Free;
|
||||
FFill.Free;
|
||||
FTitleAddr.Free;
|
||||
FLabelRange.Free;
|
||||
FFillColorRange.Free;
|
||||
FYRange.Free;
|
||||
FXRange.Free;
|
||||
inherited;
|
||||
end;
|
||||
|
||||
@ -1003,46 +1127,84 @@ end;
|
||||
|
||||
procedure TsChartSeries.SetTitleAddr(ARow, ACol: Cardinal);
|
||||
begin
|
||||
SetTitleAddr('', ARow, ACol);
|
||||
end;
|
||||
|
||||
procedure TsChartSeries.SetTitleAddr(ASheet: String; ARow, ACol: Cardinal);
|
||||
begin
|
||||
FTitleAddr.Sheet := ASheet;
|
||||
FTitleAddr.Row := ARow;
|
||||
FTitleAddr.Col := ACol;
|
||||
end;
|
||||
|
||||
procedure TsChartSeries.SetFillColorRange(ARow1, ACol1, ARow2, ACol2: Cardinal);
|
||||
begin
|
||||
SetFillColorRange('', ARow1, ACol1, '', ARow2, ACol2);
|
||||
end;
|
||||
|
||||
procedure TsChartSeries.SetFillColorRange(ASheet1: String; ARow1, ACol1: Cardinal;
|
||||
ASheet2: String; ARow2, ACol2: Cardinal);
|
||||
begin
|
||||
if (ARow1 <> ARow2) and (ACol1 <> ACol2) then
|
||||
raise Exception.Create('Series fill color values can only be located in a single column or row.');
|
||||
FFillColorRange.Sheet1 := ASHeet1;
|
||||
FFillColorRange.Row1 := ARow1;
|
||||
FFillColorRange.Col1 := ACol1;
|
||||
FFillColorRange.Sheet2 := ASheet2;
|
||||
FFillColorRange.Row2 := ARow2;
|
||||
FFillColorRange.Col2 := ACol2;
|
||||
end;
|
||||
|
||||
procedure TsChartSeries.SetLabelRange(ARow1, ACol1, ARow2, ACol2: Cardinal);
|
||||
begin
|
||||
SetLabelRange('', ARow1, ACol1, '', ARow2, ACol2);
|
||||
end;
|
||||
|
||||
procedure TsChartSeries.SetLabelRange(ASheet1: String; ARow1, ACol1: Cardinal;
|
||||
ASheet2: String; ARow2, ACol2: Cardinal);
|
||||
begin
|
||||
if (ARow1 <> ARow2) and (ACol1 <> ACol2) then
|
||||
raise Exception.Create('Series labels can only be located in a single column or row.');
|
||||
FLabelRange.Sheet1 := ASheet1;
|
||||
FLabelRange.Row1 := ARow1;
|
||||
FLabelRange.Col1 := ACol1;
|
||||
FLabelRange.Sheet2 := ASheet2;
|
||||
FLabelRange.Row2 := ARow2;
|
||||
FLabelRange.Col2 := ACol2;
|
||||
end;
|
||||
|
||||
procedure TsChartSeries.SetXRange(ARow1, ACol1, ARow2, ACol2: Cardinal);
|
||||
begin
|
||||
SetXRange('', ARow1, ACol1, '', ARow2, ACol2);
|
||||
end;
|
||||
|
||||
procedure TsChartSeries.SetXRange(ASheet1: String; ARow1, ACol1: Cardinal;
|
||||
ASheet2: String; ARow2, ACol2: Cardinal);
|
||||
begin
|
||||
if (ARow1 <> ARow2) and (ACol1 <> ACol2) then
|
||||
raise Exception.Create('Series x values can only be located in a single column or row.');
|
||||
FXRange.Sheet1 := ASheet1;
|
||||
FXRange.Row1 := ARow1;
|
||||
FXRange.Col1 := ACol1;
|
||||
FXRange.Sheet2 := ASheet2;
|
||||
FXRange.Row2 := ARow2;
|
||||
FXRange.Col2 := ACol2;
|
||||
end;
|
||||
|
||||
procedure TsChartSeries.SetYRange(ARow1, ACol1, ARow2, ACol2: Cardinal);
|
||||
begin
|
||||
SetYRange('', ARow1, ACol1, '', ARow2, ACol2);
|
||||
end;
|
||||
|
||||
procedure TsChartSeries.SetYRange(ASheet1: String; ARow1, ACol1: Cardinal;
|
||||
ASheet2: String; ARow2, ACol2: Cardinal);
|
||||
begin
|
||||
if (ARow1 <> ARow2) and (ACol1 <> ACol2) then
|
||||
raise Exception.Create('Series y values can only be located in a single column or row.');
|
||||
FYRange.Sheet1 := ASheet1;
|
||||
FYRange.Row1 := ARow1;
|
||||
FYRange.Col1 := ACol1;
|
||||
FYRange.Sheet2 := ASheet2;
|
||||
FYRange.Row2 := ARow2;
|
||||
FYRange.Col2 := ACol2;
|
||||
end;
|
||||
@ -1094,15 +1256,31 @@ end;
|
||||
constructor TsBubbleSeries.Create(AChart: TsChart);
|
||||
begin
|
||||
inherited;
|
||||
FBubbleRange := TsChartRange.Create(AChart);
|
||||
FChartType := ctBubble;
|
||||
end;
|
||||
|
||||
destructor TsBubbleSeries.Destroy;
|
||||
begin
|
||||
FBubbleRange.Free;
|
||||
inherited;
|
||||
end;
|
||||
|
||||
{ Empty sheet name will be replace by name of the sheet containing the chart. }
|
||||
procedure TsBubbleSeries.SetBubbleRange(ARow1, ACol1, ARow2, ACol2: Cardinal);
|
||||
begin
|
||||
SetBubbleRange('', ARow1, ACol1, '', ARow2, ACol2);
|
||||
end;
|
||||
|
||||
procedure TsBubbleSeries.SetBubbleRange(ASheet1: String; ARow1, ACol1: Cardinal;
|
||||
ASheet2: String; ARow2, ACol2: Cardinal);
|
||||
begin
|
||||
if (ARow1 <> ARow2) and (ACol1 <> ACol2) then
|
||||
raise Exception.Create('Bubble series values can only be located in a single column or row.');
|
||||
FBubbleRange.Sheet1 := ASheet1;
|
||||
FBubbleRange.Row1 := ARow1;
|
||||
FBubbleRange.Col1 := ACol1;
|
||||
FBubbleRange.Sheet2 := ASheet2;
|
||||
FBubbleRange.Row2 := ARow2;
|
||||
FBubbleRange.Col2 := ACol2;
|
||||
end;
|
||||
@ -1367,17 +1545,9 @@ begin
|
||||
FSeriesList.Delete(AIndex);
|
||||
end;
|
||||
|
||||
function TsChart.GetCategoryLabelRange: TsCellRange;
|
||||
function TsChart.GetCategoryLabelRange: TsChartRange;
|
||||
begin
|
||||
if FSeriesList.Count > 0 then
|
||||
Result := Series[0].LabelRange
|
||||
else
|
||||
begin
|
||||
Result.Row1 := 0;
|
||||
Result.Col1 := 0;
|
||||
Result.Row2 := 0;
|
||||
Result.Col2 := 0;
|
||||
end;
|
||||
Result := XAxis.CategoryRange;
|
||||
end;
|
||||
|
||||
function TsChart.GetChartType: TsChartType;
|
||||
@ -1396,6 +1566,11 @@ begin
|
||||
Result := nil;
|
||||
end;
|
||||
|
||||
function TsChart.GetWorksheet: TsBasicWorksheet;
|
||||
begin
|
||||
Result := TsWorkbook(FWorkbook).GetWorksheetByIndex(FSheetIndex);
|
||||
end;
|
||||
|
||||
function TsChart.IsScatterChart: Boolean;
|
||||
begin
|
||||
Result := GetChartType = ctScatter;
|
||||
|
@ -27,7 +27,7 @@ type
|
||||
procedure ReadChartAxisProps(ANode, AStyleNode: TDOMNode; AChart: TsChart);
|
||||
procedure ReadChartAxisStyle(AStyleNode: TDOMNode; AChart: TsChart; Axis: TsChartAxis);
|
||||
procedure ReadChartBackgroundStyle(AStyleNode: TDOMNode; AChart: TsChart);
|
||||
procedure ReadChartCellRange(ANode: TDOMNode; AChart: TsChart; var ARange: TsCellRange);
|
||||
procedure ReadChartCellRange(ANode: TDOMNode; ANodeName: String; ARange: TsChartRange);
|
||||
procedure ReadChartProps(AChartNode, AStyleNode: TDOMNode; AChart: TsChart);
|
||||
procedure ReadChartPlotAreaProps(ANode, AStyleNode: TDOMNode; AChart: TsChart);
|
||||
procedure ReadChartPlotAreaStyle(AStyleNode: TDOMNode; AChart: TsChart);
|
||||
@ -430,29 +430,41 @@ procedure TsSpreadOpenDocChartReader.ReadChart(AChartNode, AStyleNode: TDOMNode;
|
||||
AChart: TsChart);
|
||||
var
|
||||
nodeName: String;
|
||||
node: TDOMNode;
|
||||
officeChartNode: TDOMNode;
|
||||
chartChartNode: TDOMNode;
|
||||
chartElementNode: TDOMNode;
|
||||
begin
|
||||
AChartNode := AChartNode.FirstChild.FirstChild; // --> chart:chart
|
||||
while (AChartNode <> nil) do
|
||||
nodeName := AChartNode.NodeName;
|
||||
officeChartNode := AChartNode.FirstChild;
|
||||
while officeChartNode <> nil do
|
||||
begin
|
||||
nodeName := AChartNode.NodeName;
|
||||
if nodeName = 'chart:chart' then
|
||||
nodeName := officeChartNode.NodeName;
|
||||
if nodeName = 'office:chart' then
|
||||
begin
|
||||
ReadChartProps(AChartNode, AStyleNode, AChart);
|
||||
node := AChartNode.FirstChild;
|
||||
while (node <> nil) do
|
||||
chartChartNode := officeChartNode.FirstChild;
|
||||
while chartChartNode <> nil do
|
||||
begin
|
||||
nodeName := node.NodeName;
|
||||
case nodeName of
|
||||
'chart:plot-area': ReadChartPlotAreaProps(node, AStyleNode, AChart);
|
||||
'chart:legend': ReadChartLegendProps(node, AStyleNode, AChart);
|
||||
'chart:title': ReadChartTitleProps(node, AStyleNode, AChart, AChart.Title);
|
||||
'chart:subtitle': ReadChartTitleProps(node, AStyleNode, AChart, AChart.Subtitle);
|
||||
nodeName := chartChartNode.NodeName;
|
||||
if nodeName = 'chart:chart' then
|
||||
begin
|
||||
ReadChartProps(chartChartNode, AStyleNode, AChart);
|
||||
chartElementNode := chartChartNode.FirstChild;
|
||||
while (chartElementNode <> nil) do
|
||||
begin
|
||||
nodeName := chartElementNode.NodeName;
|
||||
case nodeName of
|
||||
'chart:plot-area': ReadChartPlotAreaProps(chartElementNode, AStyleNode, AChart);
|
||||
'chart:legend': ReadChartLegendProps(chartElementNode, AStyleNode, AChart);
|
||||
'chart:title': ReadChartTitleProps(chartElementNode, AStyleNode, AChart, AChart.Title);
|
||||
'chart:subtitle': ReadChartTitleProps(chartElementNode, AStyleNode, AChart, AChart.Subtitle);
|
||||
end;
|
||||
chartElementNode := chartElementNode.NextSibling;
|
||||
end;
|
||||
end;
|
||||
node := node.NextSibling;
|
||||
chartChartNode := chartChartNode.NextSibling;
|
||||
end;
|
||||
end;
|
||||
AChartNode := AChartNode.NextSibling;
|
||||
officeChartNode := officeChartNode.NextSibling;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -481,7 +493,6 @@ var
|
||||
s, styleName, nodeName: String;
|
||||
styleNode, subNode: TDOMNode;
|
||||
axis: TsChartAxis;
|
||||
rng: TsCellRange;
|
||||
begin
|
||||
s := GetAttrValue(ANode, 'chart:name');
|
||||
case s of
|
||||
@ -504,11 +515,7 @@ begin
|
||||
'chart:title':
|
||||
ReadChartTitleProps(subNode, AStyleNode, AChart, axis.Title);
|
||||
'chart:categories':
|
||||
begin
|
||||
rng := axis.CategoryRange;
|
||||
ReadChartCellRange(subNode, AChart, rng);
|
||||
axis.CategoryRange := rng;
|
||||
end;
|
||||
ReadChartCellRange(subNode, 'table:cell-range-address', axis.CategoryRange);
|
||||
'chart:grid':
|
||||
ReadChartAxisGrid(subNode, AStyleNode, AChart, axis);
|
||||
end;
|
||||
@ -627,17 +634,23 @@ begin
|
||||
end;
|
||||
|
||||
procedure TsSpreadOpenDocChartReader.ReadChartCellRange(ANode: TDOMNode;
|
||||
AChart: TsChart; var ARange: TsCellRange);
|
||||
ANodeName: String; ARange: TsChartRange);
|
||||
var
|
||||
s: String;
|
||||
rng: TsCellRange;
|
||||
sh1, sh2: String;
|
||||
r1, c1, r2, c2: Cardinal;
|
||||
relFlags: TsRelFlags;
|
||||
begin
|
||||
s := GetAttrValue(ANode, 'table:cell-range-address');
|
||||
if (s <> '') and TryStrToCellRange_ODS(s, sh1, sh2, rng.Row1, rng.Col1, rng.Row2, rng.Col2, relFlags) then
|
||||
// TO DO: sheets are ignored here !!!
|
||||
ARange := rng;
|
||||
s := GetAttrValue(ANode, ANodeName);
|
||||
if (s <> '') and TryStrToCellRange_ODS(s, sh1, sh2, r1, c1, r2, c2, relFlags) then
|
||||
begin
|
||||
ARange.Sheet1 := sh1;
|
||||
ARange.Sheet2 := sh2;
|
||||
ARange.Row1 := r1;
|
||||
ARange.Col1 := c1;
|
||||
ARange.Row2 := r2;
|
||||
ARange.Col2 := c2;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsSpreadOpenDocChartReader.ReadChartFiles(AStream: TStream;
|
||||
@ -678,6 +691,7 @@ begin
|
||||
if chart = nil then
|
||||
raise Exception.Create('Chart in "' + contentfile + '" not found.');
|
||||
|
||||
// Read the Object/styles.xml file
|
||||
if stylesFile <> '' then
|
||||
begin
|
||||
XMLStream := lReader.CreateXMLStream;
|
||||
@ -699,6 +713,7 @@ begin
|
||||
FreeAndNil(doc);
|
||||
end;
|
||||
|
||||
// Read the Object/content.xml file
|
||||
XMLStream := lReader.CreateXMLStream;
|
||||
try
|
||||
ok := UnzipToStream(AStream, contentFile, XMLStream);
|
||||
@ -2574,7 +2589,6 @@ procedure TsSpreadOpenDocChartWriter.WriteChartSeries(
|
||||
var AStyleID: Integer);
|
||||
var
|
||||
indent: String;
|
||||
sheet: TsWorksheet;
|
||||
series: TsChartSeries;
|
||||
valuesRange: String = '';
|
||||
domainRangeX: String = '';
|
||||
@ -2591,13 +2605,12 @@ begin
|
||||
indent := DupeString(' ', AChartIndent);
|
||||
|
||||
series := AChart.Series[ASeriesIndex];
|
||||
sheet := TsWorkbook(Writer.Workbook).GetWorksheetByIndex(AChart.sheetIndex);
|
||||
|
||||
// These are the x values of a scatter or bubble plot.
|
||||
if (series is TsScatterSeries) or (series is TsBubbleSeries) then
|
||||
begin
|
||||
domainRangeX := GetSheetCellRangeString_ODS(
|
||||
sheet.Name, sheet.Name,
|
||||
series.XRange.GetSheet1Name, series.XRange.GetSheet2Name,
|
||||
series.XRange.Row1, series.XRange.Col1,
|
||||
series.XRange.Row2, series.XRange.Col2,
|
||||
rfAllRel, false
|
||||
@ -2606,23 +2619,27 @@ begin
|
||||
|
||||
if series is TsBubbleSeries then
|
||||
begin
|
||||
// These are the y values of the in-plane coordinates of each bubble position.
|
||||
domainRangeY := GetSheetCellRangeString_ODS(
|
||||
sheet.Name, sheet.Name,
|
||||
series.YRange.GetSheet1Name, series.YRange.GetSheet2Name,
|
||||
series.YRange.Row1, series.YRange.Col1,
|
||||
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
|
||||
);
|
||||
with TsBubbleSeries(series) do
|
||||
begin
|
||||
valuesRange := GetSheetCellRangeString_ODS(
|
||||
BubbleRange.GetSheet1Name, BubbleRange.GetSheet2Name,
|
||||
BubbleRange.Row1, BubbleRange.Col1,
|
||||
BubbleRange.Row2, BubbleRange.Col2,
|
||||
rfAllRel, false
|
||||
);
|
||||
end
|
||||
end else
|
||||
// These are the y values of the non-bubble series
|
||||
valuesRange := GetSheetCellRangeString_ODS(
|
||||
sheet.Name, sheet.Name,
|
||||
series.YRange.GetSheet1Name, series.YRange.GetSheet2Name,
|
||||
series.YRange.Row1, series.YRange.Col1,
|
||||
series.YRange.Row2, series.YRange.Col2,
|
||||
rfAllRel, false
|
||||
@ -2633,20 +2650,25 @@ begin
|
||||
(series.FillColorRange.Col1 <> series.FillColorRange.Col2)
|
||||
then
|
||||
fillColorRange := GetSheetCellRangeString_ODS(
|
||||
sheet.Name, sheet.Name,
|
||||
series.FillColorRange.GetSheet1Name, series.FillColorRange.GetSheet2Name,
|
||||
series.FillColorRange.Row1, series.FillColorRange.Col1,
|
||||
series.FillColorRange.Row2, series.FillColorRange.Col2,
|
||||
rfAllRel, false
|
||||
);
|
||||
|
||||
// And these are the data point labels.
|
||||
// And this is the title of the series for the legend
|
||||
titleAddr := GetSheetCellRangeString_ODS(
|
||||
sheet.Name, sheet.Name,
|
||||
series.TitleAddr.GetSheetName, series.TitleAddr.GetSheetName,
|
||||
series.TitleAddr.Row, series.TitleAddr.Col,
|
||||
series.TitleAddr.Row, series.TitleAddr.Col,
|
||||
rfAllRel, false
|
||||
);
|
||||
count := series.YRange.Row2 - series.YRange.Row1 + 1;
|
||||
|
||||
// Number of data points
|
||||
if series.YValuesInCol then
|
||||
count := series.YRange.Row2 - series.YRange.Row1 + 1
|
||||
else
|
||||
count := series.YRange.Col2 - series.YRange.Col1 + 1;
|
||||
|
||||
if series is TsRingSeries then
|
||||
chartClass := 'circle'
|
||||
|
@ -14,6 +14,7 @@ begin
|
||||
Result := TsChart.Create;
|
||||
if (ASheet = nil) then
|
||||
raise Exception.Create('To do: Insert chart as new ChartSheet');
|
||||
Result.Workbook := self;
|
||||
Result.SheetIndex := GetWorksheetIndex(ASheet);
|
||||
Result.Row := ARow;
|
||||
Result.Col := ACol;
|
||||
|
@ -1466,6 +1466,14 @@ function GetSheetCellRangeString_ODS(ASheet1, ASheet2: String;
|
||||
ARow1, ACol1, ARow2, ACol2: Cardinal; AFlags: TsRelFlags = rfAllRel;
|
||||
WithBrackets: Boolean = true): String;
|
||||
begin
|
||||
if (ASheet1 = '') and (ASheet2 = '') and
|
||||
(ARow1 = UNASSIGNED_ROW_COL_INDEX) and (ACol1 = UNASSIGNED_ROW_COL_INDEX) and
|
||||
(ARow2 = UNASSIGNED_ROW_COL_INDEX) and (ACol2 = UNASSIGNED_ROW_COL_INDEX) then
|
||||
begin
|
||||
Result := '';
|
||||
exit;
|
||||
end;
|
||||
|
||||
Result := Format('%s.%s%s%s%d:%s.%s%s%s%d', [
|
||||
ASheet1, RELCHAR[rfRelCol in AFlags], GetColString(ACol1), RELCHAR[rfRelRow in AFlags], ARow1 + 1,
|
||||
ASheet2, RELCHAR[rfRelCol2 in AFlags], GetColString(ACol2), RELCHAR[rfRelRow2 in AFlags], ARow2 + 1
|
||||
|
Reference in New Issue
Block a user