From d7b7d410a5c386f5f5a5a55a2777148c5ec73c16 Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Mon, 29 Jan 2024 00:43:05 +0000 Subject: [PATCH] fpspreadsheet: Move xlsx chart writing code to chartwriter unit. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@9181 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../other/chart/barchart_write_demo.lpr | 4 +- .../source/common/fpsopendocumentchart.pas | 2 + .../fpspreadsheet/source/common/xlsxooxml.pas | 880 +------------ .../source/common/xlsxooxmlchart.pas | 1126 ++++++++++++++++- 4 files changed, 1159 insertions(+), 853 deletions(-) diff --git a/components/fpspreadsheet/examples/other/chart/barchart_write_demo.lpr b/components/fpspreadsheet/examples/other/chart/barchart_write_demo.lpr index 203bd96fe..f08d19a77 100644 --- a/components/fpspreadsheet/examples/other/chart/barchart_write_demo.lpr +++ b/components/fpspreadsheet/examples/other/chart/barchart_write_demo.lpr @@ -81,10 +81,8 @@ begin ser.Fill.Hatch := ch.Hatches.AddLineHatch('Forward', chsSingle, scWhite, 1.5, 0.1, 45); ser.Fill.Color := scBlue; - { - book.WriteToFile(fn + '.xlsx', true); // Excel fails to open the file + book.WriteToFile(fn + '.xlsx', true); WriteLn('Data saved with chart in ', fn, '.xlsx'); - } book.WriteToFile(fn + '.ods', true); WriteLn('Data saved with chart in ', fn, '.ods'); diff --git a/components/fpspreadsheet/source/common/fpsopendocumentchart.pas b/components/fpspreadsheet/source/common/fpsopendocumentchart.pas index 65892d627..dd8b6641a 100644 --- a/components/fpspreadsheet/source/common/fpsopendocumentchart.pas +++ b/components/fpspreadsheet/source/common/fpsopendocumentchart.pas @@ -151,8 +151,10 @@ type public constructor Create(AWriter: TsBasicSpreadWriter); override; destructor Destroy; override; + procedure AddChartsToZip(AZip: TZipper); procedure AddToMetaInfManifest(AStream: TStream); + procedure CreateStreams; override; procedure DestroyStreams; override; procedure ResetStreams; override; diff --git a/components/fpspreadsheet/source/common/xlsxooxml.pas b/components/fpspreadsheet/source/common/xlsxooxml.pas index bf8773836..d5b945f08 100644 --- a/components/fpspreadsheet/source/common/xlsxooxml.pas +++ b/components/fpspreadsheet/source/common/xlsxooxml.pas @@ -211,13 +211,6 @@ type procedure WriteCFColorRangeRule(AStream: TStream; ARule: TsCFColorRangeRule; APriority: Integer); procedure WriteCFDataBarRule(AStream: TStream; ARule: TsCFDatabarRule; APriority: Integer); procedure WriteCFIconSetRule(AStream: TStream; ARule: TsCFIconSetRule; APriority: Integer); - {$ifdef FPS_CHARTS} - procedure WriteChart(AStream: TStream; AChartIndex: Integer); - procedure WriteChartColors; - procedure WriteChartRels; - procedure WriteCharts; - procedure WriteChartStyles; - {$endif} procedure WriteColBreaks(AStream: TStream; AWorksheet: TsBasicWorksheet); procedure WriteCols(AStream: TStream; AWorksheet: TsBasicWorksheet); procedure WriteComments(AWorksheet: TsBasicWorksheet); @@ -275,10 +268,6 @@ type FSMedia: array of TStream; FSSheets: array of TStream; FSSheetRels: array of TStream; - FSCharts: array of TStream; - FSChartRels: array of TStream; - FSChartStyles: array of TStream; - FSChartColors: array of TStream; FSComments: array of TStream; FSDrawings: array of TStream; FSDrawingsRels: array of TStream; @@ -389,8 +378,6 @@ const SCHEMAS_SPREADML = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'; SCHEMAS_CORE = 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties'; SCHEMAS_DRAWINGML_CHART= 'http://schemas.openxmlformats.org/drawingml/2006/chart'; - SCHEMAS_CHART_COLORS = 'http://schemas.microsoft.com/office/2011/relationships/chartColorStyle'; - SCHEMAS_CHART_STYLE = 'http://schemas.microsoft.com/office/2011/relationships/chartStyle'; { OOXML mime types constants } MIME_XML = 'application/xml'; @@ -404,8 +391,7 @@ const MIME_STYLES = MIME_SPREADML + '.styles+xml'; MIME_STRINGS = MIME_SPREADML + '.sharedStrings+xml'; MIME_COMMENTS = MIME_SPREADML + '.comments+xml'; - MIME_DRAWING = MIME_OFFICEDOCUMENT + '.drawing+xml'; // 'application/vnd.openxmlformats-officedocument.drawing+xml - MIME_DRAWINGML_CHART = MIME_OFFICEDOCUMENT + '.drawingml.chart+xml'; + MIME_DRAWING = MIME_OFFICEDOCUMENT + '.drawing+xml'; MIME_VMLDRAWING = MIME_OFFICEDOCUMENT + '.vmlDrawing'; LAST_PALETTE_INDEX = 63; @@ -2783,7 +2769,7 @@ procedure TsSpreadOOXMLReader.ReadDrawing(ANode: TDOMNode; end; var - node, child, child2, child3: TDOMNode; + node: TDOMNode; nodeName: String = ''; rID, fileName: String; xPos, yPos, horExt, vertExt: Double; @@ -4878,7 +4864,7 @@ begin Result := -1; end; -{ Calculates the rIds for comments, hyperlinks, image, and +{ Calculates the rIds for comments, hyperlinks, image, charts and header/footer images of the specified worksheet } procedure TsSpreadOOXMLWriter.Get_rId(AWorksheet: TsBasicWorksheet; out AComment_rId, AFirstHyperlink_rId, ADrawing_rId, ADrawingHF_rId: Integer); @@ -5323,772 +5309,6 @@ begin ''); end; -{$ifdef FPS_CHARTS} -procedure TsSpreadOOXMLWriter.WriteChart(AStream: TStream; - AChartIndex: Integer); - - function GetChartAxisXML(Indent: Integer; AChart: TsChart; - AxisID, OtherAxisID: Integer; NodeName, AxPos: String): String; - var - ind: String; - begin - ind := DupeString(' ', Indent); - Result := Format( - ind + '<%s>' + LE + // 1 - ind + ' ' + LE + // 2 - ind + ' ' + LE + - ind + ' ' + LE + - ind + ' ' + LE + - ind + ' ' + LE + // 3 - ind + ' ' + LE + - IfThen(AxPos='l', ind + ' ' + LE, '') + - ind + ' ' + LE + // 4 - ind + ' ' + LE + - IfThen(AxPos='l', ind + ' ' + LE, '') + - IfThen(AxPos='b', ind + ' ' + LE, '') + - IfThen(AxPos='b', ind + ' ' + LE, '') + - IfThen(AxPos='b', ind + ' ' + LE, '') + - ind + '', [ // 5 - NodeName, // 1 - AxisID, // 2 - AxPos, // 3 - OtherAxisID, // 4 - NodeName // 5 - ]); - end; - - function GetBarChartXML(Indent: Integer; AChart: TsChart; CatAxID, ValAxID: Integer): String; - var - ind: String; - begin - ind := DupeString(' ', Indent); - Result := Format( - ind + '' + LE + - ind + ' ' + LE + - ind + ' ' + LE + - ind + ' ' + LE + // categories axis (x) - ind + ' ' + LE + // values axis (y) - ind + '', [ - CatAxID, - ValAxID - ]); - end; - - function GetLegendXML(Indent: Integer; AChart: TsChart): string; - var - ind: String; - begin - ind := DupeString(' ', Indent); - Result := - ind + '' + LE + - ind + ' ' + LE + - ind + ' ' + LE + - ind + ''; - end; - -var - chart: TsChart; - xAxID, yAxID: Integer; -begin - chart := TsWorkbook(FWorkbook).GetChartByIndex(AChartIndex); - AppendToStream(AStream, - XML_HEADER + LE); - - AppendToStream(AStream, - '' + LE -// ' xmlns:c16r2="http://schemas.microsoft.com/office/drawing/2015/06/chart">' + LE - ); - - xAxID := Random(MaxInt); - yAxID := Random(MaxInt); - - AppendToStream(AStream, - ' ' + LE + // to do: get correct value - ' ' + LE + - // ' ' + LE + - // ' ' + LE + - ' ' + LE + - ' ' + LE + - GetBarChartXML(6, chart, xAxID, yAxID) + LE + // to be replaced by real series - GetChartAxisXML(6, chart, xAxID, yAxID, 'c:catAx', 'b') + LE + - GetChartAxisXML(6, chart, yAxID, xAxID, 'c:valAx', 'l') + LE + - ' ' + LE + - GetLegendXML(4, chart) + LE + - ' ' + LE + - ' ' + LE - ); - - AppendToStream(AStream, - '' + LE - ); -end; -{$endif} - -{$ifdef FPS_CHARTS} -procedure TsSpreadOOXMLWriter.WriteChartColors; -var - i, n: Integer; -begin - n := TsWorkbook(FWorkbook).GetChartCount; - SetLength(FSChartColors, n); - - for i := 0 to n - 1 do - begin - FSChartColors[i] := CreateTempStream(FWorkbook, Format('fpsChCol%d', [i])); - - AppendToStream(FSChartColors[i], - XML_Header); - - AppendToStream(FSChartColors[i], - '' + LE + - '' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' '+ LE + - ' ' + LE + - ' '+ LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' '+ LE + - '' + LE - ); - end; -end; -{$endif} - -{$ifdef FPS_CHARTS} -{ Write the relationship file for all workbook's chart. The file defines which - xml files contain the ChartStyles and Colors needed by each chart. } -procedure TsSpreadOOXMLWriter.WriteChartRels; -var - i, n: Integer; -begin - n := TsWorkbook(FWorkbook).GetChartCount; - SetLength(FSChartRels, n); - - for i := 0 to n-1 do - begin - FSChartRels[i] := CreateTempStream(FWorkbook, Format('fpsChRels%d', [i])); - AppendToStream(FSChartRels[i], - XML_HEADER); - AppendToStream(FSChartRels[i], Format( - '' + LE + - ' ' + LE + - ' ' + LE + - '' + LE, [ - SCHEMAS_RELS, - i+1, SCHEMAS_CHART_STYLE, - i+1, SCHEMAS_CHART_COLORS - ])); - end; -end; -{$endif} - -{$ifdef FPS_CHARTS} -procedure TsSpreadOOXMLWriter.WriteCharts; -var - i, n: Integer; - chart: TsChart; -begin - n := TsWorkbook(FWorkbook).GetChartCount; - SetLength(FSCharts, n); - - for i := 0 to n - 1 do - begin - FSCharts[i] := CreateTempStream(FWorkbook, Format('fpsCh%d', [i])); - WriteChart(FSCharts[i], i); - end; -end; -{$endif} - -{$ifdef FPS_CHARTS} -procedure TsSpreadOOXMLWriter.WriteChartStyles; -var - i, n: Integer; -begin - n := TsWorkbook(FWorkbook).GetChartCount; - SetLength(FSChartStyles, n); - - for i := 0 to n - 1 do - begin - FSChartStyles[i] := CreateTempStream(FWorkbook, Format('fpsChSty%d', [i])); - - AppendToStream(FSChartStyles[i], - XML_Header); - - AppendToStream(FSChartStyles[i], - '' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' '+ LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE+ - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + lE+ - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + lE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE+ - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE+ - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE+ - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE+ - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + - - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE+ - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - ' ' + LE + - - '' + LE - ); - end; -end; -{$endif} - procedure TsSpreadOOXMLWriter.WriteColBreaks(AStream: TStream; AWorksheet: TsBasicWorksheet); var @@ -7373,7 +6593,14 @@ procedure TsSpreadOOXMLWriter.WriteDrawings(AWorksheet: TsBasicWorksheet); AppendToStream(AStream, Format( ' ' + LE + ' ' + LE + - ' ' + LE + // line 1 + ' ' + LE + // line 1 + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + ' ' + LE + ' ' + LE + ' ' + LE + @@ -7401,7 +6628,9 @@ var i, j: Integer; rId: Integer; sheet: TsWorksheet absolute AWorksheet; + {$ifdef FPS_CHARTS} chart: TsChart; + {$endif} begin if (sheet.GetImageCount = 0) {$ifdef FPS_CHARTS}and (sheet.GetChartCount = 0){$endif} then exit; @@ -7444,9 +6673,9 @@ begin ''); end; -// For each sheet, writes a "drawingX.xml.rels" file to +// For each sheet, writes a "drawingN.xml.rels" file to // folder "../drawings/_rels". -// X is a sequential number (starting 1), not neccessarily identical with the +// N is a sequential number (starting 1), not neccessarily identical with the // sheet index. // See also: WriteVmlDrawingRels procedure TsSpreadOOXMLWriter.WriteDrawingRels(AWorksheet: TsBasicWorksheet); @@ -7935,8 +7164,8 @@ begin end; // Relationships for charts or embedded images - // relationship with to the ../drawings/drawingX.xml file containing all - // chart/image infos. X is the 1-based sheet index + // relationship with to the ../drawings/drawingN.xml file containing all + // chart/image infos. N is the 1-based sheet index if (sheet.GetImageCount > 0) {$ifdef FPS_CHARTS}or (sheet.GetChartCount > 0){$endif} then AppendToStream(FSSheetRels[FCurSheetNum], Format( ' ' + LineEnding, @@ -8199,10 +7428,7 @@ begin {$ifdef FPS_CHARTS} { Write all charts } - WriteChartRels; - WriteChartStyles; - WriteChartColors; - WriteCharts; + FChartWriter.WriteCharts; {$endif} { Workbook relations - Mark relation to all sheets } @@ -8254,18 +7480,7 @@ begin '' + LineEnding); {$ifdef FPS_CHARTS} - n := 1; - for i:=0 to book.GetWorksheetCount-1 do - begin - sheet := book.GetWorksheetByIndex(i); - for j:=0 to sheet.GetChartCount-1 do - begin - AppendToStream(FSContentTypes, Format( - '' + LE, - [n, MIME_DRAWINGML_CHART])); - inc(n); - end; - end; + TsSpreadOOXMLChartWriter(FChartWriter).WriteChartContentTypes(FSContentTypes); {$endif} for i:=1 to book.GetWorksheetCount do @@ -8675,9 +7890,9 @@ begin WriteHeaderFooter(FSSheets[FCurSheetNum], AWorksheet); { This item is required for all embedded images and charts. - There must be a matching file in "drawingX.xml" file in "../drawings" + There must be a matching file in "drawingN.xml" file in "../drawings" which contains the image/chart-related data of all images/charts in this sheet. - The file in turn requires an entry "drawingX.xml.rels" in the drawings rels + The file in turn requires an entry "drawingN.xml.rels" in the drawings rels folder } if (worksheet.GetImageCount > 0) {$ifdef FPS_CHARTS}or (worksheet.GetChartCount > 0){$endif} then AppendToStream(FSSheets[FCurSheetNum], Format( @@ -8730,6 +7945,9 @@ begin FSSharedStrings_complete := CreateTempStream(FWorkbook, 'fpsSSC'); FSMetaData := CreateTempStream(FWorkbook, 'fpsMETA'); FSCustomMetaData := CreateTempStream(FWorkbook, 'fpsCM'); + {$IFDEF FPS_CHARTS} + FChartWriter.CreateStreams; + {$ENDIF} { if boFileStream in FWorkbook.Options then begin @@ -8781,14 +7999,9 @@ begin DestroyTempStream(FSSharedStrings_complete); for stream in FSSheets do DestroyTempStream(stream); SetLength(FSSheets, 0); - for stream in FSCharts do DestroyTempStream(stream); - SetLength(FSCharts, 0); - for stream in FSChartRels do DestroyTempStream(stream); - SetLength(FSChartRels, 0); - for stream in FSChartStyles do DestroyTempStream(stream); - SetLength(FSChartStyles, 0); - for stream in FSChartColors do DestroyTempStream(stream); - SetLength(FSChartColors, 0); + {$ifdef FPS_CHARTS} + FChartWriter.DestroyStreams; + {$endif} for stream in FSComments do DestroyTempStream(stream); SetLength(FSComments, 0); for stream in FSSheetRels do DestroyTempStream(stream); @@ -8922,41 +8135,10 @@ begin FZip.Entries.AddFileEntry(FSSheetRels[i], OOXML_PATH_XL_WORKSHEETS_RELS + Format('sheet%d.xml.rels', [i+1])); end; - { not used by Excel 2007 - // Write chart styles - for i:=0 to High(FSChartStyles) do - begin - if (FSChartStyles[i] = nil) or (FSChartStyles[i].Size = 0) then Continue; - FSChartStyles[i].Position := 0; - FZip.Entries.AddFileEntry(FSChartStyles[i], OOXML_PATH_XL_CHARTS + Format('style%d.xml', [i+1])); - end; - - // Write chart colors - for i:=0 to High(FSChartColors) do - begin - if (FSChartColors[i] = nil) or (FSChartColors[i].Size = 0) then Continue; - FSChartColors[i].Position := 0; - FZip.Entries.AddFileEntry(FSChartColors[i], OOXML_PATH_XL_CHARTS + Format('colors%d.xml', [i+1])); - end; - } - - // Write charts - for i:=0 to High(FSCharts) do - begin - if (FSCharts[i] = nil) or (FSCharts[i].Size = 0) then Continue; - FSCharts[i].Position := 0; - FZip.Entries.AddFileEntry(FSCharts[i], OOXML_PATH_XL_CHARTS + Format('chart%d.xml', [i+1])); - end; - - { not used by Excel 2007 - // Write chart relationships - for i := 0 to High(FSChartRels) do - begin - if (FSChartRels[i] = nil) or (FSChartRels[i].Size = 0) then Continue; - FSChartRels[i].Position := 0; - FZip.Entries.AddFileEntry(FSChartRels[i], OOXML_PATH_XL_CHARTS_RELS + Format('chart%d.xml.rels', [i+1])); - end; - } + {$ifdef FPS_CHARTS} + // Write charts + TsSpreadOOXMLChartWriter(FChartWriter).AddChartsToZip(FZip); + {$endif} // Write drawings for i:=0 to High(FSDrawings) do begin diff --git a/components/fpspreadsheet/source/common/xlsxooxmlchart.pas b/components/fpspreadsheet/source/common/xlsxooxmlchart.pas index 50a2d491d..be0695a49 100644 --- a/components/fpspreadsheet/source/common/xlsxooxmlchart.pas +++ b/components/fpspreadsheet/source/common/xlsxooxmlchart.pas @@ -68,19 +68,41 @@ type constructor Create(AReader: TsBasicSpreadReader); override; destructor Destroy; override; procedure ReadChartXML(AStream: TStream; AChart: TsChart; AChartXMLFile: String); - end; + { TsSpreadOOXMLChartWriter } + TsSpreadOOXMLChartWriter = class(TsBasicSpreadChartWriter) private + FSCharts: array of TStream; + FSChartRels: array of TStream; + FSChartStyles: array of TStream; + FSChartColors: array of TStream; FPointSeparatorSettings: TFormatSettings; + function GetChartFillAndLineXML(AIndent: Integer; AFill: TsChartFill; ALine: TsChartLine): String; protected + procedure WriteChartLegend(AStream: TStream; AIndent: Integer; ALegend: TsChartLegend); + procedure WriteChartPlotArea(AStream: TStream; AIndent: Integer; AChart: TsChart); + procedure WriteChartTitle(AStream: TStream; AIndent: Integer; ATitle: TsChartText); + + // Called by the public functions + procedure WriteChartColorsXML(AStream: TStream; AChartIndex: Integer); + procedure WriteChartRelsXML(AStream: TStream; AChartIndex: Integer); + procedure WriteChartStylesXML(AStream: TStream; AChartIndex: Integer); + procedure WriteChartXML(AStream: TStream; AChartIndex: Integer); public constructor Create(AWriter: TsBasicSpreadWriter); override; destructor Destroy; override; + // Public functions called by the main writer + procedure AddChartsToZip(AZip: TZipper); + procedure CreateStreams; override; + procedure DestroyStreams; override; + procedure ResetStreams; override; + procedure WriteChartContentTypes(AStream: TStream); + procedure WriteCharts; override; end; {$ENDIF} @@ -93,6 +115,19 @@ uses xlsxooxml; const + MIME_DRAWINGML_CHART = 'application/vnd.openxmlformats-officedocument.drawingml.chart+xml'; + MIME_DRAWINGML_CHART_STYLE = 'application/vnd.ms-office.chartstyle+xml'; + MIME_DRAWINGML_CHART_COLORS = 'application/vnd.ms-office.chartcolorstyle+xml'; + + SCHEMAS_RELS = 'http://schemas.openxmlformats.org/package/2006/relationships'; + SCHEMAS_CHART_COLORS = 'http://schemas.microsoft.com/office/2011/relationships/chartColorStyle'; + SCHEMAS_CHART_STYLE = 'http://schemas.microsoft.com/office/2011/relationships/chartStyle'; + + OOXML_PATH_XL_CHARTS = 'xl/charts/'; + OOXML_PATH_XL_CHARTS_RELS = 'xl/charts/_rels/'; + + LE = LineEnding; + PTS_MULTIPLIER = 12700; ANGLE_MULTIPLIER = 60000; PERCENT_MULTIPLIER = 1000; @@ -2266,6 +2301,1095 @@ begin inherited; end; +procedure TsSpreadOOXMLChartWriter.AddChartsToZip(AZip: TZipper); +var + i: Integer; +begin + // Add chart relationships to zip + for i := 0 to High(FSChartRels) do + begin + if (FSChartRels[i] = nil) or (FSChartRels[i].Size = 0) then Continue; + FSChartRels[i].Position := 0; + AZip.Entries.AddFileEntry(FSChartRels[i], OOXML_PATH_XL_CHARTS_RELS + Format('chart%d.xml.rels', [i+1])); + end; + + // Add chart styles to zip + for i:=0 to High(FSChartStyles) do + begin + if (FSChartStyles[i] = nil) or (FSChartStyles[i].Size = 0) then Continue; + FSChartStyles[i].Position := 0; + AZip.Entries.AddFileEntry(FSChartStyles[i], OOXML_PATH_XL_CHARTS + Format('style%d.xml', [i+1])); + end; + + // Add chart colors to zip + for i:=0 to High(FSChartColors) do + begin + if (FSChartColors[i] = nil) or (FSChartColors[i].Size = 0) then Continue; + FSChartColors[i].Position := 0; + AZip.Entries.AddFileEntry(FSChartColors[i], OOXML_PATH_XL_CHARTS + Format('colors%d.xml', [i+1])); + end; + + // Add charts top zip + for i:=0 to High(FSCharts) do + begin + if (FSCharts[i] = nil) or (FSCharts[i].Size = 0) then Continue; + FSCharts[i].Position := 0; + AZip.Entries.AddFileEntry(FSCharts[i], OOXML_PATH_XL_CHARTS + Format('chart%d.xml', [i+1])); + end; +end; + +procedure TsSpreadOOXMLChartWriter.CreateStreams; +var + n, i: Integer; + workbook: TsWorkbook; +begin + workbook := TsWorkbook(Writer.Workbook); + n := workbook.GetChartCount; + SetLength(FSCharts, n); + SetLength(FSChartRels, n); + SetLength(FSChartStyles, n); + SetLength(FSChartColors, n); + + for i := 0 to n - 1 do + begin + FSCharts[i] := CreateTempStream(workbook, Format('fpsCh%d', [i])); + FSChartRels[i] := CreateTempStream(workbook, Format('fpsChRels%d', [i])); + FSChartStyles[i] := CreateTempStream(workbook, Format('fpsChSty%d', [i])); + FSChartColors[i] := CreateTempStream(workbook, Format('fpsChCol%d', [i])); + end; +end; + +procedure TsSpreadOOXMLChartWriter.DestroyStreams; +var + stream: TStream; +begin + for stream in FSCharts do DestroyTempStream(stream); + SetLength(FSCharts, 0); + + for stream in FSChartRels do DestroyTempStream(stream); + SetLength(FSChartRels, 0); + + for stream in FSChartStyles do DestroyTempStream(stream); + SetLength(FSChartStyles, 0); + + for stream in FSChartColors do DestroyTempStream(stream); + SetLength(FSChartColors, 0); +end; + +procedure TsSpreadOOXMLChartWriter.ResetStreams; +var + stream: TStream; +begin + for stream in FSCharts do stream.Position := 0; + for stream in FSChartRels do stream.Position := 0; + for stream in FSChartStyles do stream.Position := 0; + for stream in FSChartColors do stream.Position := 0; +end; + +{@@ ---------------------------------------------------------------------------- + Writes the xl/charts/colorsN.xml file where N is the number AChartIndex. + + So far, the code is just copied from a file writen by Excel. + + @param AStream Stream to which the xml text is written +-------------------------------------------------------------------------------} +procedure TsSpreadOOXMLChartWriter.WriteChartColorsXML(AStream: TStream; + AChartIndex: Integer); +begin + AppendToStream(AStream, + XML_Header); + + AppendToStream(AStream, + '' + LE + + + '' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' '+ LE + + ' ' + LE + + ' '+ LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' '+ LE + + + '' + LE + ); +end; + +{ Write the relationship file for the chart with the given index. + The file defines which xml files contain the ChartStyles and Colors, as well + as images needed by each chart. } +procedure TsSpreadOOXMLChartWriter.WriteChartRelsXML(AStream: TStream; + AChartIndex: Integer); +begin + AppendToStream(AStream, + XML_HEADER); + AppendToStream(AStream, Format( + '' + LE + + ' ' + LE + + ' ' + LE + + '' + LE, [ + SCHEMAS_RELS, + AChartIndex + 1, SCHEMAS_CHART_STYLE, + AChartIndex + 1, SCHEMAS_CHART_COLORS + ])); +end; + +{@@ ---------------------------------------------------------------------------- + Writes the xl/charts/stylesN.xml file where N is the number AChartIndex. + + So far, the code is just copied from a file written by Excel. + + @param AStream Stream to which the xml text is written. +-------------------------------------------------------------------------------} +procedure TsSpreadOOXMLChartWriter.WriteChartStylesXML(AStream: TStream; + AChartIndex: Integer); +begin + AppendToStream(AStream, + XML_Header); + + AppendToStream(AStream, + '' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' '+ LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE+ + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + lE+ + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + lE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE+ + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE+ + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE+ + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE+ + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE+ + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + ' ' + LE + + + '' + LE + ); +end; + +procedure TsSpreadOOXMLChartWriter.WriteChartXML(AStream: TStream; AChartIndex: Integer); + + function GetChartAxisXML(AIndent: Integer; AChart: TsChart; + AxisID, OtherAxisID: Integer; NodeName, AxPos: String): String; + var + ind: String; + begin + ind := DupeString(' ', AIndent); + Result := Format( + ind + '<%s>' + LE + // 1 + ind + ' ' + LE + // 2 + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + // 3 + ind + ' ' + LE + + IfThen(AxPos='l', ind + ' ' + LE, '') + + ind + ' ' + LE + // 4 + ind + ' ' + LE + + IfThen(AxPos='l', ind + ' ' + LE, '') + + IfThen(AxPos='b', ind + ' ' + LE, '') + + IfThen(AxPos='b', ind + ' ' + LE, '') + + IfThen(AxPos='b', ind + ' ' + LE, '') + + ind + '', [ // 5 + NodeName, // 1 + AxisID, // 2 + AxPos, // 3 + OtherAxisID, // 4 + NodeName // 5 + ]); + end; + + function GetBarChartXML(Indent: Integer; AChart: TsChart; CatAxID, ValAxID: Integer): String; + var + ind: String; + begin + ind := DupeString(' ', Indent); + Result := Format( + ind + '' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + // categories axis (x) + ind + ' ' + LE + // values axis (y) + ind + '', [ + CatAxID, + ValAxID + ]); + end; + + function GetLegendXML(Indent: Integer; AChart: TsChart): string; + var + ind: String; + begin + ind := DupeString(' ', Indent); + Result := + ind + '' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ''; + end; + +var + chart: TsChart; + xAxID, yAxID: Integer; +begin + chart := TsWorkbook(Writer.Workbook).GetChartByIndex(AChartIndex); + AppendToStream(AStream, + XML_HEADER + LE); + + AppendToStream(AStream, + '' + LE +// ' xmlns:c16r2="http://schemas.microsoft.com/office/drawing/2015/06/chart">' + LE + ); + + xAxID := Random(MaxInt); + yAxID := Random(MaxInt); + + AppendToStream(AStream, + ' ' + LE + // to do: get correct value + ' '); + + WriteChartTitle(AStream, 4, chart.Title); + WriteChartPlotArea(AStream, 4, chart); + WriteChartLegend(AStream, 4, chart.Legend); + + AppendToStream(AStream, + ' ' + LE + + ' ' + LE + ); + + AppendToStream(AStream, + '' + LE + ); +end; + +function TsSpreadOOXMLChartWriter.GetChartFillAndLineXML(AIndent: Integer; + AFill: TsChartFill; ALine: TsChartLine): String; +var + ind: String; +begin + ind := DupeString(' ', AIndent); + + Result := + ind + '' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' '+ LE + + ind + '' + LE +end; + +{@@ ---------------------------------------------------------------------------- + Writes the chart-related entries to the [Content_Types].xml file + + @param AStream Stream holding the other content types +-------------------------------------------------------------------------------} +procedure TsSpreadOOXMLChartWriter.WriteChartContentTypes(AStream: TStream); +var + i, j, n: Integer; + workbook: TsWorkbook; + sheet: TsWorksheet; +begin + workbook := TsWorkbook(Writer.Workbook); + n := 1; + for i:=0 to workbook.GetWorksheetCount-1 do + begin + sheet := workbook.GetWorksheetByIndex(i); + for j:=0 to sheet.GetChartCount-1 do + begin + AppendToStream(AStream, Format( + '' + LE, + [n, MIME_DRAWINGML_CHART])); + AppendToStream(AStream, Format( + '' + LE, + [n, MIME_DRAWINGML_CHART_STYLE])); + AppendToStream(AStream, Format( + '' + LE, + [n, MIME_DRAWINGML_CHART_COLORS])); + inc(n); + end; + end; +end; + +procedure TsSpreadOOXMLChartWriter.WriteChartLegend(AStream: TStream; + AIndent: Integer; ALegend: TsChartLegend); +var + ind: String; +begin + if not ALegend.Visible then + exit; + + ind := DupeString(' ', AIndent); + + AppendToStream(AStream, + ind + '' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + '' + LE + ); +end; + +procedure TsSpreadOOXMLChartWriter.WriteChartPlotArea(AStream: TStream; + AIndent: Integer; AChart: TsChart); +var + ind: String; +begin + ind := DupeString(' ', AIndent); + + AppendToStream(AStream, + ind + '' + LE + + ind + ' ' + LE + + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE+ + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' '+ LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + '' + LE + ); +end; + +procedure TsSpreadOOXMLChartWriter.WriteCharts; +var + i: Integer; +begin + for i := 0 to TsWorkbook(Writer.Workbook).GetChartCount - 1 do + begin + WriteChartRelsXML(FSChartRels[i], i); + WriteChartStylesXML(FSChartStyles[i], i); + WriteChartColorsXML(FSChartColors[i], i); + WriteChartXML(FSCharts[i], i); + end; +end; + +procedure TsSpreadOOXMLChartWriter.WriteChartTitle(AStream: TStream; + AIndent: Integer; ATitle: TsChartText); +var + ind: String; +begin + ind := DupeString(' ', AIndent); + + AppendToStream(AStream, + ind + '' + LE + + ind + ' ' + LE + ); + + AppendToStream(AStream, + GetChartFillAndLineXML(AIndent + 2, ATitle.Background, ATitle.Border) + ); + + AppendToStream(AStream, + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' '+ LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + + ind + ' ' + LE + ); + + AppendToStream(AStream, + ind + '' + LE + ); +end; + {$ENDIF} end.