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:
wp_xxyyzz
2023-11-10 16:19:22 +00:00
parent d4f01977aa
commit 0a956f3056
7 changed files with 295 additions and 74 deletions

View File

@ -7,7 +7,7 @@ uses
fpspreadsheet, fpstypes, fpsUtils, fpschart, xlsxooxml, fpsopendocument;
const
FILE_NAME = 'world-population';
FILE_NAME = 'pie';
var
book: TsWorkbook;
sheet: TsWorksheet;

View File

@ -7,7 +7,7 @@ uses
fpspreadsheet, fpstypes, fpsUtils, fpschart, xlsxooxml, fpsopendocument;
const
FILE_NAME = 'school-grades';
FILE_NAME = 'radar';
var
book: TsWorkbook;
sheet: TsWorksheet;

View File

@ -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)),

View File

@ -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;

View File

@ -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'

View File

@ -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;

View File

@ -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