fpspreadsheet: xlsx chart reader with limited support of image fills.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9177 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
parent
555cab8fa2
commit
9f5ceb3297
@ -158,7 +158,7 @@ type
|
|||||||
Image: TFPCustomImage;
|
Image: TFPCustomImage;
|
||||||
Width, Height: Double; // mm
|
Width, Height: Double; // mm
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
procedure Copyfrom(ASource: TsChartImage);
|
procedure CopyFrom(ASource: TsChartImage);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TsChartImagelist = class(TFPObjectList)
|
TsChartImagelist = class(TFPObjectList)
|
||||||
|
@ -50,6 +50,24 @@ uses
|
|||||||
fpsxmlcommon, xlsCommon;
|
fpsxmlcommon, xlsCommon;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
TXlsxRelationship = class
|
||||||
|
RelID: String;
|
||||||
|
Target: String;
|
||||||
|
Schema: String;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TXlsxRelationshipList = class(TFPList)
|
||||||
|
private
|
||||||
|
function GetItem(AIndex: Integer): TXlsxRelationship;
|
||||||
|
procedure SetItem(AIndex: Integer; AValue: TXlsxRelationship);
|
||||||
|
public
|
||||||
|
destructor Destroy; override;
|
||||||
|
function Add(ARelID, ASchema, ATarget: String): TXlsxRelationship;
|
||||||
|
procedure Clear;
|
||||||
|
procedure Delete(AIndex: Integer);
|
||||||
|
function FindTarget(ARelID: String): String;
|
||||||
|
property Items[AIndex: Integer]: TXlsxRelationship read GetItem write SetItem; default;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TsSpreadOOXMLReader }
|
{ TsSpreadOOXMLReader }
|
||||||
|
|
||||||
@ -128,7 +146,6 @@ type
|
|||||||
procedure ReadPageSetup(ANode: TDOMNode; AWorksheet: TsBasicWorksheet);
|
procedure ReadPageSetup(ANode: TDOMNode; AWorksheet: TsBasicWorksheet);
|
||||||
procedure ReadPalette(ANode: TDOMNode);
|
procedure ReadPalette(ANode: TDOMNode);
|
||||||
procedure ReadPrintOptions(ANode: TDOMNode; AWorksheet: TsBasicWorksheet);
|
procedure ReadPrintOptions(ANode: TDOMNode; AWorksheet: TsBasicWorksheet);
|
||||||
procedure ReadRels(AStream: TStream; ARelsFile: String; ARelsList: TFPList);
|
|
||||||
procedure ReadRow(ANode: TDOMNode; AWorksheet: TsBasicWorksheet; var ARowIndex: Cardinal);
|
procedure ReadRow(ANode: TDOMNode; AWorksheet: TsBasicWorksheet; var ARowIndex: Cardinal);
|
||||||
procedure ReadSharedStrings(ANode: TDOMNode);
|
procedure ReadSharedStrings(ANode: TDOMNode);
|
||||||
procedure ReadSheetFormatPr(ANode: TDOMNode; AWorksheet: TsBasicWorksheet);
|
procedure ReadSheetFormatPr(ANode: TDOMNode; AWorksheet: TsBasicWorksheet);
|
||||||
@ -155,6 +172,7 @@ type
|
|||||||
function CreateXMLStream: TStream;
|
function CreateXMLStream: TStream;
|
||||||
procedure ReadFromStream(AStream: TStream; APassword: String = '';
|
procedure ReadFromStream(AStream: TStream; APassword: String = '';
|
||||||
AParams: TsStreamParams = []); override;
|
AParams: TsStreamParams = []); override;
|
||||||
|
procedure ReadRels(AStream: TStream; ARelsFile: String; ARelsList: TFPList);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TsSpreadOOXMLWriter }
|
{ TsSpreadOOXMLWriter }
|
||||||
@ -311,6 +329,7 @@ var
|
|||||||
sfidOOXML: TsSpreadFormatID;
|
sfidOOXML: TsSpreadFormatID;
|
||||||
|
|
||||||
procedure InitOOXMLLimitations(out ALimitations: TsSpreadsheetFormatLimitations);
|
procedure InitOOXMLLimitations(out ALimitations: TsSpreadsheetFormatLimitations);
|
||||||
|
function MakeXLPath(AFileName: String): String;
|
||||||
|
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -460,25 +479,6 @@ type
|
|||||||
Formula: String;
|
Formula: String;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TRelationship = class
|
|
||||||
RelID: String;
|
|
||||||
Target: String;
|
|
||||||
Schema: String;
|
|
||||||
end;
|
|
||||||
|
|
||||||
TRelationshipList = class(TFPList)
|
|
||||||
private
|
|
||||||
function GetItem(AIndex: Integer): TRelationship;
|
|
||||||
procedure SetItem(AIndex: Integer; AValue: TRelationship);
|
|
||||||
public
|
|
||||||
destructor Destroy; override;
|
|
||||||
function Add(ARelID, ASchema, ATarget: String): TRelationship;
|
|
||||||
procedure Clear;
|
|
||||||
procedure Delete(AIndex: Integer);
|
|
||||||
function FindTarget(ARelID: String): String;
|
|
||||||
property Items[AIndex: Integer]: TRelationship read GetItem write SetItem; default;
|
|
||||||
end;
|
|
||||||
|
|
||||||
TSheetData = class
|
TSheetData = class
|
||||||
Name: String;
|
Name: String;
|
||||||
ID: String;
|
ID: String;
|
||||||
@ -488,10 +488,10 @@ type
|
|||||||
SheetRels: TFPList;
|
SheetRels: TFPList;
|
||||||
SheetRelsFile: String;
|
SheetRelsFile: String;
|
||||||
Drawing_File: String;
|
Drawing_File: String;
|
||||||
DrawingRels: TRelationshipList;
|
DrawingRels: TXlsxRelationshipList;
|
||||||
VmlDrawing_File: String;
|
VmlDrawing_File: String;
|
||||||
VmlDrawingRels: TRelationshipList;
|
VmlDrawingRels: TXlsxRelationshipList;
|
||||||
HyperlinkRels: TRelationshipList;
|
HyperlinkRels: TXlsxRelationshipList;
|
||||||
Comments_File: String;
|
Comments_File: String;
|
||||||
constructor Create;
|
constructor Create;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
@ -754,20 +754,20 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
{ TRelationshipList }
|
{ TXlsxRelationshipList }
|
||||||
|
|
||||||
destructor TRelationshipList.Destroy;
|
destructor TXlsxRelationshipList.Destroy;
|
||||||
begin
|
begin
|
||||||
Clear;
|
Clear;
|
||||||
inherited;
|
inherited;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TRelationshipList.Add(ARelID, ASchema, ATarget: String): TRelationship;
|
function TXlsxRelationshipList.Add(ARelID, ASchema, ATarget: String): TXlsxRelationship;
|
||||||
var
|
var
|
||||||
rel: TRelationship;
|
rel: TXlsxRelationship;
|
||||||
idx: Integer;
|
idx: Integer;
|
||||||
begin
|
begin
|
||||||
rel := TRelationship.Create;
|
rel := TXlsxRelationship.Create;
|
||||||
rel.RelID := ARelID;
|
rel.RelID := ARelID;
|
||||||
rel.Schema := ASchema;
|
rel.Schema := ASchema;
|
||||||
rel.Target := ATarget;
|
rel.Target := ATarget;
|
||||||
@ -775,7 +775,7 @@ begin
|
|||||||
Result := Items[idx];
|
Result := Items[idx];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TRelationshipList.Clear;
|
procedure TXlsxRelationshipList.Clear;
|
||||||
var
|
var
|
||||||
j: Integer;
|
j: Integer;
|
||||||
begin
|
begin
|
||||||
@ -783,16 +783,16 @@ begin
|
|||||||
inherited;
|
inherited;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TRelationshipList.Delete(AIndex: Integer);
|
procedure TXlsxRelationshipList.Delete(AIndex: Integer);
|
||||||
begin
|
begin
|
||||||
Items[AIndex].Free;
|
Items[AIndex].Free;
|
||||||
inherited;
|
inherited;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TRelationshipList.FindTarget(ARelID: String): String;
|
function TXlsxRelationshipList.FindTarget(ARelID: String): String;
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
rel: TRelationship;
|
rel: TXlsxRelationship;
|
||||||
begin
|
begin
|
||||||
for i := 0 to Count-1 do
|
for i := 0 to Count-1 do
|
||||||
begin
|
begin
|
||||||
@ -806,12 +806,12 @@ begin
|
|||||||
Result := '';
|
Result := '';
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TRelationshipList.GetItem(AIndex: Integer): TRelationship;
|
function TXlsxRelationshipList.GetItem(AIndex: Integer): TXlsxRelationship;
|
||||||
begin
|
begin
|
||||||
Result := TRelationship(inherited Items[AIndex]);
|
Result := TXlsxRelationship(inherited Items[AIndex]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TRelationshipList.SetItem(AIndex: Integer; AValue: TRelationship);
|
procedure TXlsxRelationshipList.SetItem(AIndex: Integer; AValue: TXlsxRelationship);
|
||||||
begin
|
begin
|
||||||
inherited Items[AIndex] := AValue;
|
inherited Items[AIndex] := AValue;
|
||||||
end;
|
end;
|
||||||
@ -822,10 +822,10 @@ end;
|
|||||||
constructor TSheetData.Create;
|
constructor TSheetData.Create;
|
||||||
begin
|
begin
|
||||||
inherited;
|
inherited;
|
||||||
SheetRels := TRelationshipList.Create;
|
SheetRels := TXlsxRelationshipList.Create;
|
||||||
DrawingRels := TRelationshipList.Create;
|
DrawingRels := TXlsxRelationshipList.Create;
|
||||||
VmlDrawingRels := TRelationshipList.Create;
|
VmlDrawingRels := TXlsxRelationshipList.Create;
|
||||||
HyperlinkRels := TRelationshipList.Create;
|
HyperlinkRels := TXlsxRelationshipList.Create;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TSheetData.Destroy;
|
destructor TSheetData.Destroy;
|
||||||
@ -853,7 +853,7 @@ begin
|
|||||||
|
|
||||||
FSharedStrings := TStringList.Create;
|
FSharedStrings := TStringList.Create;
|
||||||
FSheetList := TFPList.Create;
|
FSheetList := TFPList.Create;
|
||||||
FWorkbookRels := TRelationshipList.Create;
|
FWorkbookRels := TXlsxRelationshipList.Create;
|
||||||
FFillList := TFPList.Create;
|
FFillList := TFPList.Create;
|
||||||
FBorderList := TFPList.Create;
|
FBorderList := TFPList.Create;
|
||||||
FHyperlinkList := TFPList.Create;
|
FHyperlinkList := TFPList.Create;
|
||||||
@ -3771,7 +3771,7 @@ begin
|
|||||||
relSchema := GetAttrValue(node, 'Type');
|
relSchema := GetAttrValue(node, 'Type');
|
||||||
relTarget := GetAttrValue(node, 'Target');
|
relTarget := GetAttrValue(node, 'Target');
|
||||||
if (relID <> '') and (relTarget <> '') then
|
if (relID <> '') and (relTarget <> '') then
|
||||||
(ARelsList as TRelationshipList).Add(relID, relSchema, relTarget);
|
(ARelsList as TXlsxRelationshipList).Add(relID, relSchema, relTarget);
|
||||||
end;
|
end;
|
||||||
node := node.NextSibling;
|
node := node.NextSibling;
|
||||||
end;
|
end;
|
||||||
@ -4153,7 +4153,7 @@ begin
|
|||||||
for i := 0 to FSheetList.Count-1 do
|
for i := 0 to FSheetList.Count-1 do
|
||||||
begin
|
begin
|
||||||
sheetData := TSheetData(FSheetList[i]);
|
sheetData := TSheetData(FSheetList[i]);
|
||||||
sheetData.Target := TRelationshipList(FWorkbookRels).FindTarget(sheetData.RelID);
|
sheetData.Target := TXlsxRelationshipList(FWorkbookRels).FindTarget(sheetData.RelID);
|
||||||
sheetData.SheetRelsFile := OOXML_PATH_XL_WORKSHEETS + '_rels/' + ExtractFileName(sheetData.Target) + '.rels';
|
sheetData.SheetRelsFile := OOXML_PATH_XL_WORKSHEETS + '_rels/' + ExtractFileName(sheetData.Target) + '.rels';
|
||||||
ReadRels(AStream, sheetData.SheetRelsFile, sheetData.SheetRels);
|
ReadRels(AStream, sheetData.SheetRelsFile, sheetData.SheetRels);
|
||||||
end;
|
end;
|
||||||
@ -4169,7 +4169,7 @@ var
|
|||||||
sheetIndex: Integer;
|
sheetIndex: Integer;
|
||||||
relID: String;
|
relID: String;
|
||||||
sheetRelsFile: String;
|
sheetRelsFile: String;
|
||||||
rels: TRelationshipList;
|
rels: TXlsxRelationshipList;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
sheetIndex := TsWorksheet(AWorksheet).Index;
|
sheetIndex := TsWorksheet(AWorksheet).Index;
|
||||||
@ -4184,7 +4184,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
// This node points to the drawing.xml file with parameters for embedded
|
// This node points to the drawing.xml file with parameters for embedded
|
||||||
// images.
|
// images.
|
||||||
rels := TRelationshipList.Create;
|
rels := TXlsxRelationshipList.Create;
|
||||||
try
|
try
|
||||||
ReadRels(AStream, sheetRelsFile, rels);
|
ReadRels(AStream, sheetRelsFile, rels);
|
||||||
relID := GetAttrValue(ANode, 'r:id');
|
relID := GetAttrValue(ANode, 'r:id');
|
||||||
@ -4197,7 +4197,7 @@ begin
|
|||||||
if nodeName = 'legacyDrawingHF' then
|
if nodeName = 'legacyDrawingHF' then
|
||||||
begin
|
begin
|
||||||
// This is the node pointer to parameters for heater/footer images.
|
// This is the node pointer to parameters for heater/footer images.
|
||||||
rels := TRelationshipList.Create;
|
rels := TXlsxRelationshipList.Create;
|
||||||
try
|
try
|
||||||
ReadRels(AStream, sheetRelsFile, rels);
|
ReadRels(AStream, sheetRelsFile, rels);
|
||||||
relID := GetAttrValue(ANode, 'r:id');
|
relID := GetAttrValue(ANode, 'r:id');
|
||||||
@ -4212,7 +4212,7 @@ begin
|
|||||||
// This node is for comment size & position. We do not support this.
|
// This node is for comment size & position. We do not support this.
|
||||||
// But it indicates the presence of comments and extract the name of the
|
// But it indicates the presence of comments and extract the name of the
|
||||||
// comments.xml file from the sheet<n>.xml.rels file
|
// comments.xml file from the sheet<n>.xml.rels file
|
||||||
rels := TRelationshipList.Create;
|
rels := TXlsxRelationshipList.Create;
|
||||||
try
|
try
|
||||||
ReadRels(AStream, sheetRelsFile, rels);
|
ReadRels(AStream, sheetRelsFile, rels);
|
||||||
for i := 0 to rels.Count-1 do
|
for i := 0 to rels.Count-1 do
|
||||||
@ -4231,7 +4231,7 @@ begin
|
|||||||
// It contains also the relationship ids to external files listed in
|
// It contains also the relationship ids to external files listed in
|
||||||
// the sheet<n>.xml.rels file. We read these relationships here and store
|
// the sheet<n>.xml.rels file. We read these relationships here and store
|
||||||
// them in the HyperlinkRels of the sheetdata.
|
// them in the HyperlinkRels of the sheetdata.
|
||||||
rels := TRelationshipList.Create;
|
rels := TXlsxRelationshipList.Create;
|
||||||
try
|
try
|
||||||
ReadRels(AStream, sheetRelsfile, rels);
|
ReadRels(AStream, sheetRelsfile, rels);
|
||||||
for i := 0 to rels.Count-1 do
|
for i := 0 to rels.Count-1 do
|
||||||
@ -4699,7 +4699,7 @@ begin
|
|||||||
// unzip sheet file
|
// unzip sheet file
|
||||||
XMLStream := CreateXMLStream;
|
XMLStream := CreateXMLStream;
|
||||||
try
|
try
|
||||||
fn := TRelationshipList(FWorkbookRels).FindTarget(sheetData.RelID);
|
fn := TXlsxRelationshipList(FWorkbookRels).FindTarget(sheetData.RelID);
|
||||||
if fn = '' then
|
if fn = '' then
|
||||||
fn := OOXML_PATH_XL_WORKSHEETS + Format('sheet%d.xml', [i+1])
|
fn := OOXML_PATH_XL_WORKSHEETS + Format('sheet%d.xml', [i+1])
|
||||||
else
|
else
|
||||||
|
@ -41,7 +41,7 @@ type
|
|||||||
function ReadChartAxisTickMarks(ANode: TDOMNode): TsChartAxisTicks;
|
function ReadChartAxisTickMarks(ANode: TDOMNode): TsChartAxisTicks;
|
||||||
procedure ReadChartBarSeries(ANode: TDOMNode; AChart: TsChart);
|
procedure ReadChartBarSeries(ANode: TDOMNode; AChart: TsChart);
|
||||||
procedure ReadChartBubbleSeries(ANode: TDOMNode; AChart: TsChart);
|
procedure ReadChartBubbleSeries(ANode: TDOMNode; AChart: TsChart);
|
||||||
procedure ReadChartSeriesDataPointStyles(ANode: TDOMNode; ASeries: TsChartSeries);
|
procedure ReadChartImages(AStream: TStream; AChart: TsChart; ARelsList: TFPList);
|
||||||
procedure ReadChartLegend(ANode: TDOMNode; AChartLegend: TsChartLegend);
|
procedure ReadChartLegend(ANode: TDOMNode; AChartLegend: TsChartLegend);
|
||||||
procedure ReadChartLineSeries(ANode: TDOMNode; AChart: TsChart);
|
procedure ReadChartLineSeries(ANode: TDOMNode; AChart: TsChart);
|
||||||
procedure ReadChartPieSeries(ANode: TDOMNode; AChart: TsChart; RingMode: Boolean);
|
procedure ReadChartPieSeries(ANode: TDOMNode; AChart: TsChart; RingMode: Boolean);
|
||||||
@ -49,6 +49,7 @@ type
|
|||||||
procedure ReadChartRadarSeries(ANode: TDOMNode; AChart: TsChart);
|
procedure ReadChartRadarSeries(ANode: TDOMNode; AChart: TsChart);
|
||||||
procedure ReadChartScatterSeries(ANode: TDOMNode; AChart: TsChart);
|
procedure ReadChartScatterSeries(ANode: TDOMNode; AChart: TsChart);
|
||||||
procedure ReadChartSeriesAxis(ANode: TDOMNode; ASeries: TsChartSeries);
|
procedure ReadChartSeriesAxis(ANode: TDOMNode; ASeries: TsChartSeries);
|
||||||
|
procedure ReadChartSeriesDataPointStyles(ANode: TDOMNode; ASeries: TsChartSeries);
|
||||||
procedure ReadChartSeriesErrorBars(ANode: TDOMNode; ASeries: TsChartSeries);
|
procedure ReadChartSeriesErrorBars(ANode: TDOMNode; ASeries: TsChartSeries);
|
||||||
procedure ReadChartSeriesLabels(ANode: TDOMNode; ASeries: TsChartSeries);
|
procedure ReadChartSeriesLabels(ANode: TDOMNode; ASeries: TsChartSeries);
|
||||||
procedure ReadChartSeriesMarker(ANode: TDOMNode; ASeries: TsCustomLineSeries);
|
procedure ReadChartSeriesMarker(ANode: TDOMNode; ASeries: TsCustomLineSeries);
|
||||||
@ -59,11 +60,10 @@ type
|
|||||||
procedure ReadChartStockSeries(ANode: TDOMNode; AChart: TsChart);
|
procedure ReadChartStockSeries(ANode: TDOMNode; AChart: TsChart);
|
||||||
procedure ReadChartStockSeriesUpDownBars(ANode: TDOMNode; ASeries: TsStockSeries);
|
procedure ReadChartStockSeriesUpDownBars(ANode: TDOMNode; ASeries: TsStockSeries);
|
||||||
procedure ReadChartTitle(ANode: TDOMNode; ATitle: TsChartText);
|
procedure ReadChartTitle(ANode: TDOMNode; ATitle: TsChartText);
|
||||||
|
|
||||||
public
|
public
|
||||||
constructor Create(AReader: TsBasicSpreadReader); override;
|
constructor Create(AReader: TsBasicSpreadReader); override;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
procedure ReadChartXML(AStream: TStream; AChart: TsChart; AChartXML: String);
|
procedure ReadChartXML(AStream: TStream; AChart: TsChart; AChartXMLFile: String);
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -545,6 +545,8 @@ var
|
|||||||
gradient: TsChartGradient;
|
gradient: TsChartGradient;
|
||||||
color: TsColor;
|
color: TsColor;
|
||||||
hatch: string;
|
hatch: string;
|
||||||
|
relID: String;
|
||||||
|
imgWidth, imgHeight: Double;
|
||||||
begin
|
begin
|
||||||
if ANode = nil then
|
if ANode = nil then
|
||||||
exit;
|
exit;
|
||||||
@ -723,6 +725,27 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Image fill
|
||||||
|
// to do: only partially supported since TAChart cannot display this and we cannot write it back.
|
||||||
|
'a:blipFill':
|
||||||
|
begin
|
||||||
|
AFill.Style := cfsImage;
|
||||||
|
child1 := ANode.FirstChild;
|
||||||
|
while Assigned(child1) do
|
||||||
|
begin
|
||||||
|
nodeName := child1.NodeName;
|
||||||
|
case nodeName of
|
||||||
|
'a:blip':
|
||||||
|
relID := GetAttrValue(child1, 'r:embed');
|
||||||
|
'a:tile':
|
||||||
|
// contains x/y scaling factor and image offset.
|
||||||
|
;
|
||||||
|
end;
|
||||||
|
child1 := child1.NextSibling;
|
||||||
|
end;
|
||||||
|
AFill.Image := AChart.Images.IndexOf(relID);
|
||||||
|
end;
|
||||||
|
|
||||||
// Line style
|
// Line style
|
||||||
'a:ln':
|
'a:ln':
|
||||||
ReadChartLineProps(ANode, AChart, ALine);
|
ReadChartLineProps(ANode, AChart, ALine);
|
||||||
@ -809,13 +832,54 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TsSpreadOOXMLChartReader.ReadChartImages(AStream: TStream;
|
||||||
|
AChart: TsChart; ARelsList: TFPList);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
rel: TXlsxRelationship;
|
||||||
|
img: TFPCustomImage;
|
||||||
|
imgFileName: string;
|
||||||
|
memStream: TMemoryStream;
|
||||||
|
unzip: TStreamUnzipper;
|
||||||
|
begin
|
||||||
|
for i := 0 to ARelsList.Count-1 do
|
||||||
|
begin
|
||||||
|
rel := TXlsxRelationshipList(ARelsList)[i];
|
||||||
|
if rel.Schema = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image' then
|
||||||
|
begin
|
||||||
|
imgFileName := MakeXLPath(rel.Target);
|
||||||
|
if imgFileName = '' then
|
||||||
|
Continue;
|
||||||
|
unzip := TStreamUnzipper.Create(AStream);
|
||||||
|
try
|
||||||
|
unzip.Examine;
|
||||||
|
memStream := TMemoryStream.Create;
|
||||||
|
try
|
||||||
|
unzip.UnzipFile(imgFileName, memStream);
|
||||||
|
memStream.Position := 0;
|
||||||
|
if memStream.Size > 0 then
|
||||||
|
begin
|
||||||
|
img := TFPMemoryImage.Create(0, 0); // do not destroy this image here!
|
||||||
|
img.LoadFromStream(memStream);
|
||||||
|
AChart.Images.AddImage(rel.RelID, img);
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
memStream.Free;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
unzip.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
Reads the individual data point styles of a series.
|
Reads the individual data point styles of a series.
|
||||||
|
|
||||||
@param ANode First child of the <c:dPt> node
|
@param ANode First child of the <c:dPt> node
|
||||||
@param ASeries Series to which these data points belong
|
@param ASeries Series to which these data points belong
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
procedure TsSpreadOOXMLChartreader.ReadChartSeriesDataPointStyles(ANode: TDOMNode;
|
procedure TsSpreadOOXMLChartReader.ReadChartSeriesDataPointStyles(ANode: TDOMNode;
|
||||||
ASeries: TsChartSeries);
|
ASeries: TsChartSeries);
|
||||||
var
|
var
|
||||||
nodename, s: String;
|
nodename, s: String;
|
||||||
@ -1997,23 +2061,44 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{@@ ----------------------------------------------------------------------------
|
||||||
|
Reads the main xml file of a chart (and the associated rels file)
|
||||||
|
|
||||||
|
@param AStream Stream of the xlsx file
|
||||||
|
@param AChart Chart instance, already created, but empty
|
||||||
|
@param AChartXMLFile Name of the xml file with the chart data, usually 'xl/charts/chart1.xml'
|
||||||
|
-------------------------------------------------------------------------------}
|
||||||
procedure TsSpreadOOXMLChartReader.ReadChartXML(AStream: TStream; AChart: TsChart;
|
procedure TsSpreadOOXMLChartReader.ReadChartXML(AStream: TStream; AChart: TsChart;
|
||||||
AChartXML: String);
|
AChartXMLFile: String);
|
||||||
var
|
var
|
||||||
lReader: TsSpreadOOXMLReader;
|
lReader: TsSpreadOOXMLReader;
|
||||||
xmlStream: TStream;
|
xmlStream: TStream;
|
||||||
doc: TXMLDocument = nil;
|
doc: TXMLDocument = nil;
|
||||||
node: TDOMNode;
|
node: TDOMNode;
|
||||||
nodeName: String;
|
nodeName: String;
|
||||||
|
relsFileName: String;
|
||||||
|
relsList: TXlsxRelationshipList;
|
||||||
begin
|
begin
|
||||||
lReader := TsSpreadOOXMLReader(Reader);
|
lReader := TsSpreadOOXMLReader(Reader);
|
||||||
|
|
||||||
|
// Read the rels file of the chart. The items go into the FRelsList.
|
||||||
|
relsFileName := ExtractFilePath(AChartXMLFile) + '_rels/' + ExtractFileName(AChartXMLFile) + '.rels';
|
||||||
|
relsList := TXlsxRelationshipList.Create;
|
||||||
|
try
|
||||||
|
lReader.ReadRels(AStream, relsFileName, relsList);
|
||||||
|
// Read the images mentioned in the rels file.
|
||||||
|
ReadChartImages(AStream, AChart, relsList);
|
||||||
|
finally
|
||||||
|
relsList.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Read the xml file of the chart
|
||||||
xmlStream := lReader.CreateXMLStream;
|
xmlStream := lReader.CreateXMLStream;
|
||||||
try
|
try
|
||||||
if UnzipToStream(AStream, AChartXML, xmlStream) then
|
if UnzipToStream(AStream, AChartXMLFile, xmlStream) then
|
||||||
begin
|
begin
|
||||||
lReader.ReadXMLStream(doc, xmlStream);
|
lReader.ReadXMLStream(doc, xmlStream);
|
||||||
node := doc.DocumentElement.FirstChild; //FindNode('c:chart');
|
node := doc.DocumentElement.FirstChild;
|
||||||
while Assigned(node) do
|
while Assigned(node) do
|
||||||
begin
|
begin
|
||||||
nodeName := node.NodeName;
|
nodeName := node.NodeName;
|
||||||
|
Loading…
Reference in New Issue
Block a user