You've already forked lazarus-ccr
fpspreadsheet: Remove string-based writing code of ods files --> significant speed improvement particularly for large grids (20000x100 cells 120 sec (old) --> 7 sec (new)).
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3311 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -40,9 +40,10 @@ begin
|
|||||||
MyWorksheet := MyWorkbook.AddWorksheet('My Worksheet');
|
MyWorksheet := MyWorkbook.AddWorksheet('My Worksheet');
|
||||||
|
|
||||||
// Write some cells
|
// Write some cells
|
||||||
MyWorksheet.WriteNumber(0, 1, 2.0);// B1
|
MyWorksheet.WriteNumber(0, 0, 1.0); // A1
|
||||||
MyWorksheet.WriteNumber(0, 2, 3.0);// C1
|
MyWorksheet.WriteNumber(0, 1, 2.0); // B1
|
||||||
MyWorksheet.WriteNumber(0, 3, 4.0);// D1
|
MyWorksheet.WriteNumber(0, 2, 3.0); // C1
|
||||||
|
MyWorksheet.WriteNumber(0, 3, 4.0); // D1
|
||||||
MyWorksheet.WriteUTF8Text(4, 2, 'Total:');// C5
|
MyWorksheet.WriteUTF8Text(4, 2, 'Total:');// C5
|
||||||
MyWorksheet.WriteNumber(4, 3, 10); // D5
|
MyWorksheet.WriteNumber(4, 3, 10); // D5
|
||||||
MyWorksheet.WriteDateTime(5, 0, now);
|
MyWorksheet.WriteDateTime(5, 0, now);
|
||||||
|
@ -131,38 +131,36 @@ type
|
|||||||
FRowStyleList: TFPList;
|
FRowStyleList: TFPList;
|
||||||
|
|
||||||
// Routines to write parts of files
|
// Routines to write parts of files
|
||||||
function WriteCellStylesXMLAsString: string;
|
procedure WriteCellStyles(AStream: TStream);
|
||||||
function WriteColStylesXMLAsString: String;
|
procedure WriteColStyles(AStream: TStream);
|
||||||
function WriteNumFormatsXMLAsString: String;
|
procedure WriteColumns(AStream: TStream; ASheet: TsWorksheet);
|
||||||
function WriteRowStylesXMLAsString: String;
|
procedure WriteFontNames(AStream: TStream);
|
||||||
|
procedure WriteNumFormats(AStream: TStream);
|
||||||
function WriteColumnsXMLAsString(ASheet: TsWorksheet): String;
|
procedure WriteRowStyles(AStream: TStream);
|
||||||
function WriteRowsAndCellsXMLAsString(ASheet: TsWorksheet): String;
|
procedure WriteRowsAndCells(AStream: TStream; ASheet: TsWorksheet);
|
||||||
|
procedure WriteTableSettings(AStream: TStream);
|
||||||
|
|
||||||
function WriteBackgroundColorStyleXMLAsString(const AFormat: TCell): String;
|
function WriteBackgroundColorStyleXMLAsString(const AFormat: TCell): String;
|
||||||
function WriteBorderStyleXMLAsString(const AFormat: TCell): String;
|
function WriteBorderStyleXMLAsString(const AFormat: TCell): String;
|
||||||
function WriteDefaultFontXMLAsString: String;
|
function WriteDefaultFontXMLAsString: String;
|
||||||
function WriteFontNamesXMLAsString: String;
|
|
||||||
function WriteFontStyleXMLAsString(const AFormat: TCell): String;
|
function WriteFontStyleXMLAsString(const AFormat: TCell): String;
|
||||||
function WriteHorAlignmentStyleXMLAsString(const AFormat: TCell): String;
|
function WriteHorAlignmentStyleXMLAsString(const AFormat: TCell): String;
|
||||||
function WriteTextRotationStyleXMLAsString(const AFormat: TCell): String;
|
function WriteTextRotationStyleXMLAsString(const AFormat: TCell): String;
|
||||||
function WriteVertAlignmentStyleXMLAsString(const AFormat: TCell): String;
|
function WriteVertAlignmentStyleXMLAsString(const AFormat: TCell): String;
|
||||||
function WriteWordwrapStyleXMLAsString(const AFormat: TCell): String;
|
function WriteWordwrapStyleXMLAsString(const AFormat: TCell): String;
|
||||||
|
|
||||||
function WriteTableSettingsXMLAsString(AIndent: String): String;
|
|
||||||
protected
|
protected
|
||||||
FPointSeparatorSettings: TFormatSettings;
|
FPointSeparatorSettings: TFormatSettings;
|
||||||
// Strings with the contents of files
|
|
||||||
FMeta, FSettings, FStyles, FContent, FCellContent, FMimetype: string;
|
|
||||||
FMetaInfManifest: string;
|
|
||||||
// Streams with the contents of files
|
// Streams with the contents of files
|
||||||
FSMeta, FSSettings, FSStyles, FSContent, FSMimetype: TStringStream;
|
FSMeta, FSSettings, FSStyles, FSContent, FSMimeType, FSMetaInfManifest: TStream;
|
||||||
FSMetaInfManifest: TStringStream;
|
|
||||||
// Helpers
|
// Helpers
|
||||||
procedure CreateNumFormatList; override;
|
procedure CreateNumFormatList; override;
|
||||||
|
procedure CreateStreams;
|
||||||
|
procedure DestroyStreams;
|
||||||
procedure ListAllColumnStyles;
|
procedure ListAllColumnStyles;
|
||||||
procedure ListAllNumFormats; override;
|
procedure ListAllNumFormats; override;
|
||||||
procedure ListAllRowStyles;
|
procedure ListAllRowStyles;
|
||||||
|
procedure ResetStreams;
|
||||||
// Routines to write those files
|
// Routines to write those files
|
||||||
procedure WriteMimetype;
|
procedure WriteMimetype;
|
||||||
procedure WriteMetaInfManifest;
|
procedure WriteMetaInfManifest;
|
||||||
@ -170,7 +168,7 @@ type
|
|||||||
procedure WriteSettings;
|
procedure WriteSettings;
|
||||||
procedure WriteStyles;
|
procedure WriteStyles;
|
||||||
procedure WriteContent;
|
procedure WriteContent;
|
||||||
procedure WriteWorksheet(CurSheet: TsWorksheet);
|
procedure WriteWorksheet(AStream: TStream; CurSheet: TsWorksheet);
|
||||||
{ Record writing methods }
|
{ Record writing methods }
|
||||||
procedure WriteBlank(AStream: TStream; const ARow, ACol: Cardinal;
|
procedure WriteBlank(AStream: TStream; const ARow, ACol: Cardinal;
|
||||||
ACell: PCell); override;
|
ACell: PCell); override;
|
||||||
@ -2235,6 +2233,54 @@ begin
|
|||||||
FNumFormatList := TsSpreadOpenDocNumFormatList.Create(Workbook);
|
FNumFormatList := TsSpreadOpenDocNumFormatList.Create(Workbook);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ Creates the streams for the individual data files. Will be zipped into a
|
||||||
|
single xlsx file. }
|
||||||
|
procedure TsSpreadOpenDocWriter.CreateStreams;
|
||||||
|
var
|
||||||
|
dir: String;
|
||||||
|
begin
|
||||||
|
if (woSaveMemory in Workbook.WritingOptions) then begin
|
||||||
|
dir := IncludeTrailingPathDelimiter(GetTempDir);
|
||||||
|
FSMeta := TFileStream.Create(GetTempFileName(dir, 'fpsM'), fmCreate+fmOpenRead);
|
||||||
|
FSSettings := TFileStream.Create(GetTempFileName(dir, 'fpsS'), fmCreate+fmOpenRead);
|
||||||
|
FSStyles := TFileStream.Create(GetTempFileName(dir, 'fpsSTY'), fmCreate+fmOpenRead);
|
||||||
|
FSContent := TFileStream.Create(GetTempFileName(dir, 'fpsC'), fmCreate+fmOpenRead);
|
||||||
|
FSMimeType := TFileStream.Create(GetTempFileName(dir, 'fpsMT'), fmCreate+fmOpenRead);
|
||||||
|
FSMetaInfManifest := TFileStream.Create(GetTempFileName(dir, 'fpsMIM'), fmCreate+fmOpenRead);
|
||||||
|
end else begin;
|
||||||
|
FSMeta := TMemoryStream.Create;
|
||||||
|
FSSettings := TMemoryStream.Create;
|
||||||
|
FSStyles := TMemoryStream.Create;
|
||||||
|
FSContent := TMemoryStream.Create;
|
||||||
|
FSMimeType := TMemoryStream.Create;
|
||||||
|
FSMetaInfManifest := TMemoryStream.Create;
|
||||||
|
end;
|
||||||
|
// FSSheets will be created when needed.
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ Destroys the streams that were created by the writer }
|
||||||
|
procedure TsSpreadOpenDocWriter.DestroyStreams;
|
||||||
|
|
||||||
|
procedure DestroyStream(AStream: TStream);
|
||||||
|
var
|
||||||
|
fn: String;
|
||||||
|
begin
|
||||||
|
if AStream is TFileStream then begin
|
||||||
|
fn := TFileStream(AStream).Filename;
|
||||||
|
DeleteFile(fn);
|
||||||
|
end;
|
||||||
|
AStream.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
DestroyStream(FSMeta);
|
||||||
|
DestroyStream(FSSettings);
|
||||||
|
DestroyStream(FSStyles);
|
||||||
|
DestroyStream(FSContent);
|
||||||
|
DestroyStream(FSMimeType);
|
||||||
|
DestroyStream(FSMetaInfManifest);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TsSpreadOpenDocWriter.ListAllColumnStyles;
|
procedure TsSpreadOpenDocWriter.ListAllColumnStyles;
|
||||||
var
|
var
|
||||||
i, j, c: Integer;
|
i, j, c: Integer;
|
||||||
@ -2355,38 +2401,59 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ Is called before zipping the individual file parts. Rewinds the streams. }
|
||||||
|
procedure TsSpreadOpenDocWriter.ResetStreams;
|
||||||
|
begin
|
||||||
|
FSMeta.Position := 0;
|
||||||
|
FSSettings.Position := 0;
|
||||||
|
FSStyles.Position := 0;
|
||||||
|
FSContent.Position := 0;
|
||||||
|
FSMimeType.Position := 0;
|
||||||
|
FSMetaInfManifest.Position := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TsSpreadOpenDocWriter.WriteMimetype;
|
procedure TsSpreadOpenDocWriter.WriteMimetype;
|
||||||
begin
|
begin
|
||||||
FMimetype := 'application/vnd.oasis.opendocument.spreadsheet';
|
AppendToStream(FSMimeType,
|
||||||
|
'application/vnd.oasis.opendocument.spreadsheet'
|
||||||
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsSpreadOpenDocWriter.WriteMetaInfManifest;
|
procedure TsSpreadOpenDocWriter.WriteMetaInfManifest;
|
||||||
begin
|
begin
|
||||||
FMetaInfManifest :=
|
AppendToStream(FSMetaInfManifest,
|
||||||
XML_HEADER + LineEnding +
|
'<manifest:manifest xmlns:manifest="' + SCHEMAS_XMLNS_MANIFEST + '">');
|
||||||
'<manifest:manifest xmlns:manifest="' + SCHEMAS_XMLNS_MANIFEST + '">' + LineEnding +
|
AppendToStream(FSMetaInfManifest,
|
||||||
' <manifest:file-entry manifest:media-type="application/vnd.oasis.opendocument.spreadsheet" manifest:full-path="/" />' + LineEnding +
|
'<manifest:file-entry manifest:media-type="application/vnd.oasis.opendocument.spreadsheet" manifest:full-path="/" />');
|
||||||
' <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="content.xml" />' + LineEnding +
|
AppendToStream(FSMetaInfManifest,
|
||||||
' <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="styles.xml" />' + LineEnding +
|
'<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="content.xml" />');
|
||||||
' <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="meta.xml" />' + LineEnding +
|
AppendToStream(FSMetaInfManifest,
|
||||||
' <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="settings.xml" />' + LineEnding +
|
'<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="styles.xml" />');
|
||||||
'</manifest:manifest>';
|
AppendToStream(FSMetaInfManifest,
|
||||||
|
'<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="meta.xml" />');
|
||||||
|
AppendToStream(FSMetaInfManifest,
|
||||||
|
'<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="settings.xml" />');
|
||||||
|
AppendToStream(FSMetaInfManifest,
|
||||||
|
'</manifest:manifest>');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsSpreadOpenDocWriter.WriteMeta;
|
procedure TsSpreadOpenDocWriter.WriteMeta;
|
||||||
begin
|
begin
|
||||||
FMeta :=
|
AppendToStream(FSMeta,
|
||||||
XML_HEADER + LineEnding +
|
XML_HEADER);
|
||||||
|
AppendToStream(FSMeta,
|
||||||
'<office:document-meta xmlns:office="' + SCHEMAS_XMLNS_OFFICE +
|
'<office:document-meta xmlns:office="' + SCHEMAS_XMLNS_OFFICE +
|
||||||
'" xmlns:dcterms="' + SCHEMAS_XMLNS_DCTERMS +
|
'" xmlns:dcterms="' + SCHEMAS_XMLNS_DCTERMS +
|
||||||
'" xmlns:meta="' + SCHEMAS_XMLNS_META +
|
'" xmlns:meta="' + SCHEMAS_XMLNS_META +
|
||||||
'" xmlns="' + SCHEMAS_XMLNS +
|
'" xmlns="' + SCHEMAS_XMLNS +
|
||||||
'" xmlns:ex="' + SCHEMAS_XMLNS + '">' + LineEnding +
|
'" xmlns:ex="' + SCHEMAS_XMLNS + '">');
|
||||||
' <office:meta>' + LineEnding +
|
AppendToStream(FSMeta,
|
||||||
' <meta:generator>FPSpreadsheet Library</meta:generator>' + LineEnding +
|
'<office:meta>',
|
||||||
' <meta:document-statistic />' + LineEnding +
|
'<meta:generator>FPSpreadsheet Library</meta:generator>' +
|
||||||
' </office:meta>' + LineEnding +
|
'<meta:document-statistic />',
|
||||||
'</office:document-meta>';
|
'</office:meta>');
|
||||||
|
AppendToStream(FSMeta,
|
||||||
|
'</office:document-meta>');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsSpreadOpenDocWriter.WriteSettings;
|
procedure TsSpreadOpenDocWriter.WriteSettings;
|
||||||
@ -2406,71 +2473,115 @@ begin
|
|||||||
if not (soShowHeaders in sheet.Options) then showHeaders := false;
|
if not (soShowHeaders in sheet.Options) then showHeaders := false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
FSettings :=
|
AppendToStream(FSSettings,
|
||||||
XML_HEADER + LineEnding +
|
XML_HEADER);
|
||||||
|
AppendToStream(FSSettings,
|
||||||
'<office:document-settings xmlns:office="' + SCHEMAS_XMLNS_OFFICE +
|
'<office:document-settings xmlns:office="' + SCHEMAS_XMLNS_OFFICE +
|
||||||
'" xmlns:config="' + SCHEMAS_XMLNS_CONFIG +
|
'" xmlns:config="' + SCHEMAS_XMLNS_CONFIG +
|
||||||
'" xmlns:ooo="' + SCHEMAS_XMLNS_OOO + '">' + LineEnding +
|
'" xmlns:ooo="' + SCHEMAS_XMLNS_OOO + '">');
|
||||||
'<office:settings>' + LineEnding +
|
AppendToStream(FSSettings,
|
||||||
' <config:config-item-set config:name="ooo:view-settings">' + LineEnding +
|
'<office:settings>');
|
||||||
' <config:config-item-map-indexed config:name="Views">' + LineEnding +
|
AppendToStream(FSSettings,
|
||||||
' <config:config-item-map-entry>' + LineEnding +
|
'<config:config-item-set config:name="ooo:view-settings">');
|
||||||
' <config:config-item config:name="ActiveTable" config:type="string">Tabelle1</config:config-item>' + LineEnding +
|
AppendToStream(FSSettings,
|
||||||
' <config:config-item config:name="ZoomValue" config:type="int">100</config:config-item>' + LineEnding +
|
'<config:config-item-map-indexed config:name="Views">');
|
||||||
' <config:config-item config:name="PageViewZoomValue" config:type="int">100</config:config-item>' + LineEnding +
|
AppendToStream(FSSettings,
|
||||||
' <config:config-item config:name="ShowPageBreakPreview" config:type="boolean">false</config:config-item>' + LineEnding +
|
'<config:config-item-map-entry>');
|
||||||
' <config:config-item config:name="ShowGrid" config:type="boolean">'+FALSE_TRUE[showGrid]+'</config:config-item>' + LineEnding +
|
AppendToStream(FSSettings,
|
||||||
' <config:config-item config:name="HasColumnRowHeaders" config:type="boolean">'+FALSE_TRUE[showHeaders]+'</config:config-item>' + LineEnding +
|
'<config:config-item config:name="ActiveTable" config:type="string">Tabelle1</config:config-item>');
|
||||||
' <config:config-item-map-named config:name="Tables">' + LineEnding +
|
AppendToStream(FSSettings,
|
||||||
WriteTableSettingsXMLAsString(' ') +
|
'<config:config-item config:name="ZoomValue" config:type="int">100</config:config-item>');
|
||||||
' </config:config-item-map-named>' + LineEnding +
|
AppendToStream(FSSettings,
|
||||||
' </config:config-item-map-entry>' + LineEnding +
|
'<config:config-item config:name="PageViewZoomValue" config:type="int">100</config:config-item>');
|
||||||
' </config:config-item-map-indexed>' + LineEnding +
|
AppendToStream(FSSettings,
|
||||||
' </config:config-item-set>' + LineEnding +
|
'<config:config-item config:name="ShowPageBreakPreview" config:type="boolean">false</config:config-item>');
|
||||||
' </office:settings>' + LineEnding +
|
AppendToStream(FSSettings,
|
||||||
'</office:document-settings>';
|
'<config:config-item config:name="ShowGrid" config:type="boolean">'+FALSE_TRUE[showGrid]+'</config:config-item>');
|
||||||
|
AppendToStream(FSSettings,
|
||||||
|
'<config:config-item config:name="HasColumnRowHeaders" config:type="boolean">'+FALSE_TRUE[showHeaders]+'</config:config-item>');
|
||||||
|
AppendToStream(FSSettings,
|
||||||
|
'<config:config-item-map-named config:name="Tables">');
|
||||||
|
|
||||||
|
WriteTableSettings(FSSettings);
|
||||||
|
|
||||||
|
AppendToStream(FSSettings,
|
||||||
|
'</config:config-item-map-named>');
|
||||||
|
AppendToStream(FSSettings,
|
||||||
|
' </config:config-item-map-entry>');
|
||||||
|
AppendToStream(FSSettings,
|
||||||
|
' </config:config-item-map-indexed>');
|
||||||
|
AppendToStream(FSSettings,
|
||||||
|
' </config:config-item-set>');
|
||||||
|
AppendToStream(FSSettings,
|
||||||
|
' </office:settings>');
|
||||||
|
AppendToStream(FSSettings,
|
||||||
|
'</office:document-settings>');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsSpreadOpenDocWriter.WriteStyles;
|
procedure TsSpreadOpenDocWriter.WriteStyles;
|
||||||
begin
|
begin
|
||||||
FStyles :=
|
AppendToStream(FSStyles,
|
||||||
XML_HEADER + LineEnding +
|
XML_HEADER);
|
||||||
|
|
||||||
|
AppendToStream(FSStyles,
|
||||||
'<office:document-styles xmlns:office="' + SCHEMAS_XMLNS_OFFICE +
|
'<office:document-styles xmlns:office="' + SCHEMAS_XMLNS_OFFICE +
|
||||||
'" xmlns:fo="' + SCHEMAS_XMLNS_FO +
|
'" xmlns:fo="' + SCHEMAS_XMLNS_FO +
|
||||||
'" xmlns:style="' + SCHEMAS_XMLNS_STYLE +
|
'" xmlns:style="' + SCHEMAS_XMLNS_STYLE +
|
||||||
'" xmlns:svg="' + SCHEMAS_XMLNS_SVG +
|
'" xmlns:svg="' + SCHEMAS_XMLNS_SVG +
|
||||||
'" xmlns:table="' + SCHEMAS_XMLNS_TABLE +
|
'" xmlns:table="' + SCHEMAS_XMLNS_TABLE +
|
||||||
'" xmlns:text="' + SCHEMAS_XMLNS_TEXT +
|
'" xmlns:text="' + SCHEMAS_XMLNS_TEXT +
|
||||||
'" xmlns:v="' + SCHEMAS_XMLNS_V + '">' + LineEnding +
|
'" xmlns:v="' + SCHEMAS_XMLNS_V + '">');
|
||||||
'<office:font-face-decls>' + LineEnding +
|
|
||||||
' '+WriteFontNamesXMLAsString + LineEnding +
|
AppendToStream(FSStyles,
|
||||||
// ' <style:font-face style:name="Arial" svg:font-family="Arial" />' + LineEnding +
|
'<office:font-face-decls>');
|
||||||
'</office:font-face-decls>' + LineEnding +
|
WriteFontNames(FSStyles);
|
||||||
'<office:styles>' + LineEnding +
|
AppendToStream(FSStyles,
|
||||||
' <style:style style:name="Default" style:family="table-cell">' + LineEnding +
|
'</office:font-face-decls>');
|
||||||
' ' + WriteDefaultFontXMLAsString + LineEnding +
|
|
||||||
' </style:style>' + LineEnding +
|
AppendToStream(FSStyles,
|
||||||
'</office:styles>' + LineEnding +
|
'<office:styles>');
|
||||||
'<office:automatic-styles>' + LineEnding +
|
AppendToStream(FSStyles,
|
||||||
' <style:page-layout style:name="pm1">' + LineEnding +
|
'<style:style style:name="Default" style:family="table-cell">',
|
||||||
' <style:page-layout-properties fo:margin-top="1.25cm" fo:margin-bottom="1.25cm" fo:margin-left="1.905cm" fo:margin-right="1.905cm" />' + LineEnding +
|
WriteDefaultFontXMLAsString,
|
||||||
' <style:header-style>' + LineEnding +
|
'</style:style>');
|
||||||
' <style:header-footer-properties fo:min-height="0.751cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-bottom="0.25cm" fo:margin-top="0cm" />' + LineEnding +
|
AppendToStream(FSStyles,
|
||||||
' </style:header-style>' + LineEnding +
|
'</office:styles>');
|
||||||
' <style:footer-style>' + LineEnding +
|
|
||||||
' <style:header-footer-properties fo:min-height="0.751cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0.25cm" fo:margin-bottom="0cm" />' + LineEnding +
|
AppendToStream(FSStyles,
|
||||||
' </style:footer-style>' + LineEnding +
|
'<office:automatic-styles>');
|
||||||
' </style:page-layout>' + LineEnding +
|
AppendToStream(FSStyles,
|
||||||
'</office:automatic-styles>' + LineEnding +
|
'<style:page-layout style:name="pm1">');
|
||||||
'<office:master-styles>' + LineEnding +
|
AppendToStream(FSStyles,
|
||||||
' <style:master-page style:name="Default" style:page-layout-name="pm1">' + LineEnding +
|
'<style:page-layout-properties fo:margin-top="1.25cm" fo:margin-bottom="1.25cm" fo:margin-left="1.905cm" fo:margin-right="1.905cm" />');
|
||||||
' <style:header />' + LineEnding +
|
AppendToStream(FSStyles,
|
||||||
' <style:header-left style:display="false" />' + LineEnding +
|
'<style:header-style>',
|
||||||
' <style:footer />' + LineEnding +
|
'<style:header-footer-properties fo:min-height="0.751cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-bottom="0.25cm" fo:margin-top="0cm" />',
|
||||||
' <style:footer-left style:display="false" />' + LineEnding +
|
'</style:header-style>');
|
||||||
' </style:master-page>' + LineEnding +
|
AppendToStream(FSStyles,
|
||||||
'</office:master-styles>' + LineEnding +
|
'<style:footer-style>',
|
||||||
'</office:document-styles>';
|
'<style:header-footer-properties fo:min-height="0.751cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0.25cm" fo:margin-bottom="0cm" />',
|
||||||
|
'</style:footer-style>');
|
||||||
|
AppendToStream(FSStyles,
|
||||||
|
'</style:page-layout>');
|
||||||
|
AppendToStream(FSStyles,
|
||||||
|
'</office:automatic-styles>');
|
||||||
|
|
||||||
|
AppendToStream(FSStyles,
|
||||||
|
'<office:master-styles>');
|
||||||
|
AppendToStream(FSStyles,
|
||||||
|
'<style:master-page style:name="Default" style:page-layout-name="pm1">');
|
||||||
|
AppendToStream(FSStyles,
|
||||||
|
'<style:header />',
|
||||||
|
'<style:header-left style:display="false" />');
|
||||||
|
AppendToStream(FSStyles,
|
||||||
|
'<style:footer />',
|
||||||
|
'<style:footer-left style:display="false" />');
|
||||||
|
AppendToStream(FSStyles,
|
||||||
|
'</style:master-page>');
|
||||||
|
AppendToStream(FSStyles,
|
||||||
|
'</office:master-styles>');
|
||||||
|
AppendToStream(FSStyles,
|
||||||
|
'</office:document-styles>');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsSpreadOpenDocWriter.WriteContent;
|
procedure TsSpreadOpenDocWriter.WriteContent;
|
||||||
@ -2481,11 +2592,69 @@ var
|
|||||||
lRowStylesCode: String;
|
lRowStylesCode: String;
|
||||||
lNumFmtCode: String;
|
lNumFmtCode: String;
|
||||||
begin
|
begin
|
||||||
ListAllNumFormats;
|
AppendToStream(FSContent,
|
||||||
ListAllFormattingStyles;
|
XML_HEADER);
|
||||||
ListAllColumnStyles;
|
AppendToStream(FSContent,
|
||||||
ListAllRowStyles;
|
'<office:document-content xmlns:office="' + SCHEMAS_XMLNS_OFFICE +
|
||||||
|
'" xmlns:fo="' + SCHEMAS_XMLNS_FO +
|
||||||
|
'" xmlns:style="' + SCHEMAS_XMLNS_STYLE +
|
||||||
|
'" xmlns:text="' + SCHEMAS_XMLNS_TEXT +
|
||||||
|
'" xmlns:table="' + SCHEMAS_XMLNS_TABLE +
|
||||||
|
'" xmlns:svg="' + SCHEMAS_XMLNS_SVG +
|
||||||
|
'" xmlns:number="' + SCHEMAS_XMLNS_NUMBER +
|
||||||
|
'" xmlns:meta="' + SCHEMAS_XMLNS_META +
|
||||||
|
'" xmlns:chart="' + SCHEMAS_XMLNS_CHART +
|
||||||
|
'" xmlns:dr3d="' + SCHEMAS_XMLNS_DR3D +
|
||||||
|
'" xmlns:math="' + SCHEMAS_XMLNS_MATH +
|
||||||
|
'" xmlns:form="' + SCHEMAS_XMLNS_FORM +
|
||||||
|
'" xmlns:script="' + SCHEMAS_XMLNS_SCRIPT +
|
||||||
|
'" xmlns:ooo="' + SCHEMAS_XMLNS_OOO +
|
||||||
|
'" xmlns:ooow="' + SCHEMAS_XMLNS_OOOW +
|
||||||
|
'" xmlns:oooc="' + SCHEMAS_XMLNS_OOOC +
|
||||||
|
'" xmlns:dom="' + SCHEMAS_XMLNS_DOM +
|
||||||
|
'" xmlns:xforms="' + SCHEMAS_XMLNS_XFORMS +
|
||||||
|
'" xmlns:xsd="' + SCHEMAS_XMLNS_XSD +
|
||||||
|
'" xmlns:xsi="' + SCHEMAS_XMLNS_XSI + '">' +
|
||||||
|
'<office:scripts />');
|
||||||
|
|
||||||
|
// Fonts
|
||||||
|
WriteFontNames(FSContent);
|
||||||
|
|
||||||
|
// Automatic styles
|
||||||
|
AppendToStream(FSContent,
|
||||||
|
'<office:automatic-styles>');
|
||||||
|
|
||||||
|
WriteNumFormats(FSContent);
|
||||||
|
WriteColStyles(FSContent);
|
||||||
|
WriteRowStyles(FSContent);
|
||||||
|
|
||||||
|
AppendToStream(FSContent,
|
||||||
|
'<style:style style:name="ta1" style:family="table" style:master-page-name="Default">',
|
||||||
|
'<style:table-properties table:display="true" style:writing-mode="lr-tb"/>',
|
||||||
|
'</style:style>');
|
||||||
|
// Automatically generated styles
|
||||||
|
WriteCellStyles(FSContent);
|
||||||
|
AppendToStream(FSContent,
|
||||||
|
'</office:automatic-styles>');
|
||||||
|
|
||||||
|
// Body
|
||||||
|
AppendToStream(FSContent,
|
||||||
|
'<office:body>',
|
||||||
|
'<office:spreadsheet>');
|
||||||
|
|
||||||
|
// Write all worksheets
|
||||||
|
for i := 0 to Workbook.GetWorksheetCount - 1 do
|
||||||
|
WriteWorksheet(FSContent, Workbook.GetWorksheetByIndex(i));
|
||||||
|
|
||||||
|
AppendToStream(FSContent,
|
||||||
|
'</office:spreadsheet>',
|
||||||
|
'</office:body>',
|
||||||
|
'</office:document-content>'
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(*
|
||||||
lNumFmtCode := WriteNumFormatsXMLAsString;
|
lNumFmtCode := WriteNumFormatsXMLAsString;
|
||||||
|
|
||||||
lColStylesCode := WriteColStylesXMLAsString;
|
lColStylesCode := WriteColStylesXMLAsString;
|
||||||
@ -2557,58 +2726,55 @@ begin
|
|||||||
' </office:spreadsheet>' + LineEnding +
|
' </office:spreadsheet>' + LineEnding +
|
||||||
' </office:body>' + LineEnding +
|
' </office:body>' + LineEnding +
|
||||||
'</office:document-content>';
|
'</office:document-content>';
|
||||||
|
*)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsSpreadOpenDocWriter.WriteWorksheet(CurSheet: TsWorksheet);
|
procedure TsSpreadOpenDocWriter.WriteWorksheet(AStream: TStream;
|
||||||
|
CurSheet: TsWorksheet);
|
||||||
begin
|
begin
|
||||||
// Header
|
// Header
|
||||||
FContent := FContent +
|
AppendToStream(AStream,
|
||||||
' <table:table table:name="' + CurSheet.Name + '" table:style-name="ta1">' + LineEnding;
|
'<table:table table:name="' + CurSheet.Name + '" table:style-name="ta1">');
|
||||||
|
|
||||||
// columns
|
// columns
|
||||||
FContent := FContent + WriteColumnsXMLAsString(CurSheet);
|
WriteColumns(AStream, CurSheet);
|
||||||
|
|
||||||
// rows and cells
|
// rows and cells
|
||||||
// The cells need to be written in order, row by row, cell by cell
|
// The cells need to be written in order, row by row, cell by cell
|
||||||
FContent := FContent + WriteRowsAndCellsXMLAsString(CurSheet);
|
WriteRowsAndCells(AStream, CurSheet);
|
||||||
|
|
||||||
// Footer
|
// Footer
|
||||||
FContent := FContent +
|
AppendToStream(AStream,
|
||||||
' </table:table>' + LineEnding;
|
'</table:table>');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsSpreadOpenDocWriter.WriteCellStylesXMLAsString: string;
|
procedure TsSpreadOpenDocWriter.WriteCellStyles(AStream: TStream);
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
s: String;
|
s: String;
|
||||||
fmtIndex: Integer;
|
fmtIndex: Integer;
|
||||||
fmt: String;
|
fmt: String;
|
||||||
begin
|
begin
|
||||||
Result := '';
|
for i := 0 to Length(FFormattingStyles) - 1 do begin
|
||||||
|
|
||||||
for i := 0 to Length(FFormattingStyles) - 1 do
|
|
||||||
begin
|
|
||||||
fmtIndex := NumFormatList.Find(FFormattingStyles[i].NumberFormatStr);
|
fmtIndex := NumFormatList.Find(FFormattingStyles[i].NumberFormatStr);
|
||||||
if fmtIndex <> -1
|
if fmtIndex <> -1
|
||||||
then fmt := 'style:data-style-name="' + NumFormatList[fmtIndex].Name +'"'
|
then fmt := 'style:data-style-name="' + NumFormatList[fmtIndex].Name +'"'
|
||||||
else fmt := '';
|
else fmt := '';
|
||||||
|
|
||||||
// Start and Name
|
// Start and name
|
||||||
Result := Result +
|
AppendToStream(AStream,
|
||||||
' <style:style style:name="ce' + IntToStr(i) + '" style:family="table-cell" ' +
|
'<style:style style:name="ce' + IntToStr(i) + '" style:family="table-cell" ' +
|
||||||
'style:parent-style-name="Default" '+ fmt + '>' + LineEnding;
|
'style:parent-style-name="Default" '+ fmt + '>');
|
||||||
|
|
||||||
// Fields
|
|
||||||
|
|
||||||
// style:text-properties
|
// style:text-properties
|
||||||
if uffBold in FFormattingStyles[i].UsedFormattingFields then
|
if uffBold in FFormattingStyles[i].UsedFormattingFields then
|
||||||
Result := Result +
|
AppendToStream(AStream,
|
||||||
' <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/>' + LineEnding;
|
'<style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/>');
|
||||||
|
|
||||||
s := WriteFontStyleXMLAsString(FFormattingStyles[i]);
|
s := WriteFontStyleXMLAsString(FFormattingStyles[i]);
|
||||||
if s <> '' then
|
if s <> '' then
|
||||||
Result := Result +
|
AppendToStream(AStream,
|
||||||
' <style:text-properties '+ s + '/>' + LineEnding;
|
'<style:text-properties '+ s + '/>');
|
||||||
|
|
||||||
// style:table-cell-properties
|
// style:table-cell-properties
|
||||||
s := WriteBorderStyleXMLAsString(FFormattingStyles[i]) +
|
s := WriteBorderStyleXMLAsString(FFormattingStyles[i]) +
|
||||||
@ -2617,48 +2783,54 @@ begin
|
|||||||
WriteTextRotationStyleXMLAsString(FFormattingStyles[i]) +
|
WriteTextRotationStyleXMLAsString(FFormattingStyles[i]) +
|
||||||
WriteVertAlignmentStyleXMLAsString(FFormattingStyles[i]);
|
WriteVertAlignmentStyleXMLAsString(FFormattingStyles[i]);
|
||||||
if s <> '' then
|
if s <> '' then
|
||||||
Result := Result +
|
AppendToStream(AStream,
|
||||||
' <style:table-cell-properties ' + s + '/>' + LineEnding;
|
'<style:table-cell-properties ' + s + '/>');
|
||||||
|
|
||||||
// style:paragraph-properties
|
// style:paragraph-properties
|
||||||
s := WriteHorAlignmentStyleXMLAsString(FFormattingStyles[i]);
|
s := WriteHorAlignmentStyleXMLAsString(FFormattingStyles[i]);
|
||||||
if s <> '' then
|
if s <> '' then
|
||||||
Result := Result +
|
AppendToStream(AStream,
|
||||||
' <style:paragraph-properties ' + s + '/>' + LineEnding;
|
'<style:paragraph-properties ' + s + '/>');
|
||||||
|
|
||||||
// End
|
// End
|
||||||
Result := Result +
|
AppendToStream(AStream,
|
||||||
' </style:style>' + LineEnding;
|
'</style:style>');
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsSpreadOpenDocWriter.WriteColStylesXMLAsString: string;
|
procedure TsSpreadOpenDocWriter.WriteColStyles(AStream: TStream);
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
colstyle: TColumnStyleData;
|
colstyle: TColumnStyleData;
|
||||||
begin
|
begin
|
||||||
Result := '';
|
if FColumnStyleList.Count = 0 then begin
|
||||||
|
AppendToStream(AStream,
|
||||||
|
'<style:style style:name="co1" style:family="table-column">',
|
||||||
|
'<style:table-column-properties fo:break-before="auto" style:column-width="2.267cm"/>',
|
||||||
|
'</style:style>');
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
for i := 0 to FColumnStyleList.Count-1 do begin
|
for i := 0 to FColumnStyleList.Count-1 do begin
|
||||||
colStyle := TColumnStyleData(FColumnStyleList[i]);
|
colStyle := TColumnStyleData(FColumnStyleList[i]);
|
||||||
|
|
||||||
// Start and Name
|
// Start and Name
|
||||||
Result := Result +
|
AppendToStream(AStream, Format(
|
||||||
' <style:style style:name="%s" style:family="table-column">' + LineEnding;
|
'<style:style style:name="%s" style:family="table-column">', [colStyle.Name]));
|
||||||
|
|
||||||
// Column width
|
// Column width
|
||||||
Result := Result +
|
AppendToStream(AStream, Format(
|
||||||
' <style:table-column-properties style:column-width="%.3fmm" fo:break-before="auto"/>' + LineEnding;
|
'<style:table-column-properties style:column-width="%.3fmm" fo:break-before="auto"/>',
|
||||||
|
[colStyle.ColWidth], FPointSeparatorSettings));
|
||||||
|
|
||||||
// End
|
// End
|
||||||
Result := Result +
|
AppendToStream(AStream,
|
||||||
' </style:style>' + LineEnding;
|
'</style:style>');
|
||||||
|
|
||||||
Result := Format(Result, [colStyle.Name, colStyle.ColWidth], FPointSeparatorSettings);
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsSpreadOpenDocWriter.WriteColumnsXMLAsString(ASheet: TsWorksheet): String;
|
procedure TsSpreadOpenDocWriter.WriteColumns(AStream: TStream;
|
||||||
|
ASheet: TsWorksheet);
|
||||||
var
|
var
|
||||||
lastCol: Integer;
|
lastCol: Integer;
|
||||||
j, k: Integer;
|
j, k: Integer;
|
||||||
@ -2668,8 +2840,6 @@ var
|
|||||||
colsRepeated: Integer;
|
colsRepeated: Integer;
|
||||||
colsRepeatedStr: String;
|
colsRepeatedStr: String;
|
||||||
begin
|
begin
|
||||||
Result := '';
|
|
||||||
|
|
||||||
widthMultiplier := Workbook.GetFont(0).Size / 2;
|
widthMultiplier := Workbook.GetFont(0).Size / 2;
|
||||||
lastCol := ASheet.GetLastColIndex;
|
lastCol := ASheet.GetLastColIndex;
|
||||||
|
|
||||||
@ -2701,22 +2871,48 @@ begin
|
|||||||
end;
|
end;
|
||||||
colsRepeatedStr := IfThen(colsRepeated = 1, '', Format(' table:number-columns-repeated="%d"', [colsRepeated]));
|
colsRepeatedStr := IfThen(colsRepeated = 1, '', Format(' table:number-columns-repeated="%d"', [colsRepeated]));
|
||||||
|
|
||||||
Result := Result + Format(
|
AppendToStream(AStream, Format(
|
||||||
' <table:table-column table:style-name="%s"%s table:default-cell-style-name="Default"/>',
|
'<table:table-column table:style-name="%s"%s table:default-cell-style-name="Default" />',
|
||||||
[styleName, colsRepeatedStr]) + LineEnding;
|
[styleName, colsRepeatedStr]));
|
||||||
|
|
||||||
j := j + colsRepeated;
|
j := j + colsRepeated;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsSpreadOpenDocWriter.WriteNumFormatsXMLAsString: String;
|
procedure TsSpreadOpenDocWriter.WriteFontNames(AStream: TStream);
|
||||||
|
var
|
||||||
|
L: TStringList;
|
||||||
|
fnt: TsFont;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
AppendToStream(AStream,
|
||||||
|
'<office:font-face-decls>');
|
||||||
|
|
||||||
|
L := TStringList.Create;
|
||||||
|
try
|
||||||
|
for i:=0 to Workbook.GetFontCount-1 do begin
|
||||||
|
fnt := Workbook.GetFont(i);
|
||||||
|
if (fnt <> nil) and (L.IndexOf(fnt.FontName) = -1) then
|
||||||
|
L.Add(fnt.FontName);
|
||||||
|
end;
|
||||||
|
for i:=0 to L.Count-1 do
|
||||||
|
AppendToStream(AStream, Format(
|
||||||
|
'<style:font-face style:name="%s" svg:font-family="%s" />', [L[i], L[i]]));
|
||||||
|
finally
|
||||||
|
L.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
AppendToStream(AStream,
|
||||||
|
'</office:font-face-decls>');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TsSpreadOpenDocWriter.WriteNumFormats(AStream: TStream);
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
numFmtXML: String;
|
numFmtXML: String;
|
||||||
fmtItem: TsNumFormatData;
|
fmtItem: TsNumFormatData;
|
||||||
parser: TsSpreadOpenDocNumFormatParser;
|
parser: TsSpreadOpenDocNumFormatParser;
|
||||||
begin
|
begin
|
||||||
Result := '';
|
|
||||||
for i:=0 to FNumFormatList.Count-1 do begin
|
for i:=0 to FNumFormatList.Count-1 do begin
|
||||||
fmtItem := FNumFormatList.Items[i];
|
fmtItem := FNumFormatList.Items[i];
|
||||||
parser := TsSpreadOpenDocNumFormatParser.Create(Workbook, fmtItem.FormatString,
|
parser := TsSpreadOpenDocNumFormatParser.Create(Workbook, fmtItem.FormatString,
|
||||||
@ -2724,14 +2920,14 @@ begin
|
|||||||
try
|
try
|
||||||
numFmtXML := parser.BuildXMLAsString(' ', fmtItem.Name);
|
numFmtXML := parser.BuildXMLAsString(' ', fmtItem.Name);
|
||||||
if numFmtXML <> '' then
|
if numFmtXML <> '' then
|
||||||
Result := Result + numFmtXML;
|
AppendToStream(AStream, numFmtXML);
|
||||||
finally
|
finally
|
||||||
parser.Free;
|
parser.Free;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsSpreadOpenDocWriter.WriteRowsAndCellsXMLAsString(ASheet: TsWorksheet): String;
|
procedure TsSpreadOpenDocWriter.WriteRowsAndCells(AStream: TStream; ASheet: TsWorksheet);
|
||||||
var
|
var
|
||||||
r, rr: Cardinal; // row index in sheet
|
r, rr: Cardinal; // row index in sheet
|
||||||
c, cc: Cardinal; // column index in sheet
|
c, cc: Cardinal; // column index in sheet
|
||||||
@ -2749,8 +2945,6 @@ var
|
|||||||
rowStyleData: TRowStyleData;
|
rowStyleData: TRowStyleData;
|
||||||
defFontSize: Single;
|
defFontSize: Single;
|
||||||
begin
|
begin
|
||||||
Result := '';
|
|
||||||
|
|
||||||
// some abbreviations...
|
// some abbreviations...
|
||||||
lastCol := ASheet.GetLastColIndex;
|
lastCol := ASheet.GetLastColIndex;
|
||||||
lastRow := ASheet.GetLastRowIndex;
|
lastRow := ASheet.GetLastRowIndex;
|
||||||
@ -2799,19 +2993,22 @@ begin
|
|||||||
colsRepeated := lastCol+1;
|
colsRepeated := lastCol+1;
|
||||||
colsRepeatedStr := IfThen(colsRepeated = 1, '',
|
colsRepeatedStr := IfThen(colsRepeated = 1, '',
|
||||||
Format('table:number-columns-repeated="%d"', [colsRepeated]));
|
Format('table:number-columns-repeated="%d"', [colsRepeated]));
|
||||||
Result := Result + Format(
|
|
||||||
' <table:table-row table:style-name="%s" %s>' + LineEnding +
|
AppendToStream(AStream, Format(
|
||||||
' <table:table-cell %s/>' + LineEnding +
|
'<table:table-row table:style-name="%s" %s>', [styleName, rowsRepeatedStr]));
|
||||||
' </table:table-row>' + LineEnding,
|
AppendToStream(AStream, Format(
|
||||||
[styleName, rowsRepeatedStr, colsRepeatedStr]);
|
'<table:table-cell %s/>', [colsRepeatedStr]));
|
||||||
|
AppendToStream(AStream,
|
||||||
|
'</table:table-row>');
|
||||||
|
|
||||||
r := rr;
|
r := rr;
|
||||||
continue;
|
continue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Now we know that there are cells.
|
// Now we know that there are cells.
|
||||||
// Write the row XML
|
// Write the row XML
|
||||||
Result := Result + Format(
|
AppendToStream(AStream, Format(
|
||||||
' <table:table-row table:style-name="%s">', [styleName]) + LineEnding;
|
'<table:table-row table:style-name="%s">', [styleName]));
|
||||||
|
|
||||||
// Loop along the row and find the cells.
|
// Loop along the row and find the cells.
|
||||||
c := 0;
|
c := 0;
|
||||||
@ -2831,50 +3028,53 @@ begin
|
|||||||
colsRepeated := cc - c;
|
colsRepeated := cc - c;
|
||||||
colsRepeatedStr := IfThen(colsRepeated = 1, '',
|
colsRepeatedStr := IfThen(colsRepeated = 1, '',
|
||||||
Format('table:number-columns-repeated="%d"', [colsRepeated]));
|
Format('table:number-columns-repeated="%d"', [colsRepeated]));
|
||||||
Result := Result + Format(
|
AppendToStream(AStream, Format(
|
||||||
' <table:table-cell %s/>', [colsRepeatedStr]) + LineEnding;
|
'<table:table-cell %s/>', [colsRepeatedStr]));
|
||||||
end
|
end else
|
||||||
else begin
|
WriteCellCallback(cell, AStream);
|
||||||
WriteCellCallback(cell, nil);
|
|
||||||
Result := Result + FCellContent;
|
|
||||||
end;
|
|
||||||
inc(c, colsRepeated);
|
inc(c, colsRepeated);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Result := Result +
|
AppendToStream(AStream,
|
||||||
' </table:table-row>' + LineEnding;
|
'</table:table-row>');
|
||||||
|
|
||||||
// Next row
|
// Next row
|
||||||
inc(r, rowsRepeated);
|
inc(r, rowsRepeated);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsSpreadOpenDocWriter.WriteRowStylesXMLAsString: string;
|
procedure TsSpreadOpenDocWriter.WriteRowStyles(AStream: TStream);
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
rowstyle: TRowStyleData;
|
rowstyle: TRowStyleData;
|
||||||
|
s: String;
|
||||||
|
useOptRowH: String;
|
||||||
begin
|
begin
|
||||||
Result := '';
|
if FRowStyleList.Count = 0 then begin
|
||||||
|
AppendToStream(AStream,
|
||||||
|
'<style:style style:name="ro1" style:family="table-row">',
|
||||||
|
'<style:table-row-properties style:row-height="0.416cm" fo:break-before="auto" style:use-optimal-row-height="true"/>',
|
||||||
|
'</style:style>');
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
for i := 0 to FRowStyleList.Count-1 do begin
|
for i := 0 to FRowStyleList.Count-1 do begin
|
||||||
rowStyle := TRowStyleData(FRowStyleList[i]);
|
rowStyle := TRowStyleData(FRowStyleList[i]);
|
||||||
|
|
||||||
// Start and Name
|
// Start and Name
|
||||||
Result := Result +
|
AppendToStream(AStream, Format(
|
||||||
' <style:style style:name="%s" style:family="table-row">' + LineEnding;
|
'<style:style style:name="%s" style:family="table-row">', [rowStyle.Name]));
|
||||||
|
|
||||||
// Column width
|
// Column width
|
||||||
Result := Result +
|
AppendToStream(AStream, Format(
|
||||||
' <style:table-row-properties ' +
|
'<style:table-row-properties style:row-height="%.3gmm" ', [rowStyle.RowHeight], FPointSeparatorSettings));
|
||||||
'style:row-height="%.3gmm" ' +
|
if rowStyle.AutoRowHeight then
|
||||||
IfThen(rowStyle.AutoRowHeight, 'style:use-optimal-row-height="true" ', '') +
|
AppendToStream(AStream, 'style:use-optimal-row-height="true" ');
|
||||||
'fo:break-before="auto"/>' + LineEnding;
|
AppendToStream(AStream, 'fo:break-before="auto"/>');
|
||||||
|
|
||||||
// End
|
// End
|
||||||
Result := Result +
|
AppendToStream(AStream,
|
||||||
' </style:style>' + LineEnding;
|
'</style:style>');
|
||||||
|
|
||||||
Result := Format(Result, [rowStyle.Name, rowStyle.RowHeight], FPointSeparatorSettings);
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2929,8 +3129,16 @@ var
|
|||||||
begin
|
begin
|
||||||
Unused(AOverwriteExisting);
|
Unused(AOverwriteExisting);
|
||||||
|
|
||||||
{ Fill the strings with the contents of the files }
|
{ Analyze the workbook and collect all information needed }
|
||||||
|
ListAllNumFormats;
|
||||||
|
ListAllFormattingStyles;
|
||||||
|
ListAllColumnStyles;
|
||||||
|
ListAllRowStyles;
|
||||||
|
|
||||||
|
{ Create the streams that will hold the file contents }
|
||||||
|
CreateStreams;
|
||||||
|
|
||||||
|
{ Fill the strings with the contents of the files }
|
||||||
WriteMimetype();
|
WriteMimetype();
|
||||||
WriteMetaInfManifest();
|
WriteMetaInfManifest();
|
||||||
WriteMeta();
|
WriteMeta();
|
||||||
@ -2938,17 +3146,7 @@ begin
|
|||||||
WriteStyles();
|
WriteStyles();
|
||||||
WriteContent;
|
WriteContent;
|
||||||
|
|
||||||
{ Write the data to streams }
|
|
||||||
|
|
||||||
FSMeta := TStringStream.Create(FMeta);
|
|
||||||
FSSettings := TStringStream.Create(FSettings);
|
|
||||||
FSStyles := TStringStream.Create(FStyles);
|
|
||||||
FSContent := TStringStream.Create(FContent);
|
|
||||||
FSMimetype := TStringStream.Create(FMimetype);
|
|
||||||
FSMetaInfManifest := TStringStream.Create(FMetaInfManifest);
|
|
||||||
|
|
||||||
{ Now compress the files }
|
{ Now compress the files }
|
||||||
|
|
||||||
FZip := TZipper.Create;
|
FZip := TZipper.Create;
|
||||||
try
|
try
|
||||||
FZip.FileName := AFileName;
|
FZip.FileName := AFileName;
|
||||||
@ -2960,15 +3158,12 @@ begin
|
|||||||
FZip.Entries.AddFileEntry(FSMimetype, OPENDOC_PATH_MIMETYPE);
|
FZip.Entries.AddFileEntry(FSMimetype, OPENDOC_PATH_MIMETYPE);
|
||||||
FZip.Entries.AddFileEntry(FSMetaInfManifest, OPENDOC_PATH_METAINF_MANIFEST);
|
FZip.Entries.AddFileEntry(FSMetaInfManifest, OPENDOC_PATH_METAINF_MANIFEST);
|
||||||
|
|
||||||
|
ResetStreams;
|
||||||
|
|
||||||
FZip.ZipAllFiles;
|
FZip.ZipAllFiles;
|
||||||
finally
|
finally
|
||||||
|
DestroyStreams;
|
||||||
FZip.Free;
|
FZip.Free;
|
||||||
FSMeta.Free;
|
|
||||||
FSSettings.Free;
|
|
||||||
FSStyles.Free;
|
|
||||||
FSContent.Free;
|
|
||||||
FSMimetype.Free;
|
|
||||||
FSMetaInfManifest.Free;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -3012,12 +3207,10 @@ begin
|
|||||||
// Write empty cell only if it has formatting
|
// Write empty cell only if it has formatting
|
||||||
if ACell^.UsedFormattingFields <> [] then begin
|
if ACell^.UsedFormattingFields <> [] then begin
|
||||||
lIndex := FindFormattingInList(ACell);
|
lIndex := FindFormattingInList(ACell);
|
||||||
lStyle := ' table:style-name="ce' + IntToStr(lIndex) + '" ';
|
AppendToStream(AStream, Format(
|
||||||
FCellContent :=
|
'<table:table-cell table:style-name="ce%d">', [lIndex]),
|
||||||
' <table:table-cell ' + lStyle + '>' + LineEnding +
|
'</table:table-cell>');
|
||||||
' </table:table-cell>' + LineEnding;
|
end;
|
||||||
end else
|
|
||||||
FCellContent := '';
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Creates an XML string for inclusion of the background color into the
|
{ Creates an XML string for inclusion of the background color into the
|
||||||
@ -3034,7 +3227,6 @@ begin
|
|||||||
Result := Format('fo:background-color="%s" ', [
|
Result := Format('fo:background-color="%s" ', [
|
||||||
Workbook.GetPaletteColorAsHTMLStr(AFormat.BackgroundColor)
|
Workbook.GetPaletteColorAsHTMLStr(AFormat.BackgroundColor)
|
||||||
]);
|
]);
|
||||||
// + Workbook.FPSColorToHexString(FFormattingStyles[i].BackgroundColor, FFormattingStyles[i].RGBBackgroundColor) +'" ';
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Creates an XML string for inclusion of borders and border styles into the
|
{ Creates an XML string for inclusion of borders and border styles into the
|
||||||
@ -3106,30 +3298,6 @@ begin
|
|||||||
);
|
);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsSpreadOpenDocWriter.WriteFontNamesXMLAsString: String;
|
|
||||||
var
|
|
||||||
L: TStringList;
|
|
||||||
fnt: TsFont;
|
|
||||||
i: Integer;
|
|
||||||
begin
|
|
||||||
Result := '';
|
|
||||||
L := TStringList.Create;
|
|
||||||
try
|
|
||||||
for i:=0 to Workbook.GetFontCount-1 do begin
|
|
||||||
fnt := Workbook.GetFont(i);
|
|
||||||
if (fnt <> nil) and (L.IndexOf(fnt.FontName) = -1) then
|
|
||||||
L.Add(fnt.FontName);
|
|
||||||
end;
|
|
||||||
for i:=0 to L.Count-1 do
|
|
||||||
Result := Format(
|
|
||||||
'<style:font-face style:name="%s" svg:font-family="%s" />',
|
|
||||||
[ L[i], L[i] ]
|
|
||||||
);
|
|
||||||
finally
|
|
||||||
L.Free;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TsSpreadOpenDocWriter.WriteFontStyleXMLAsString(const AFormat: TCell): String;
|
function TsSpreadOpenDocWriter.WriteFontStyleXMLAsString(const AFormat: TCell): String;
|
||||||
var
|
var
|
||||||
fnt: TsFont;
|
fnt: TsFont;
|
||||||
@ -3182,7 +3350,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsSpreadOpenDocWriter.WriteTableSettingsXMLAsString(AIndent: String): String;
|
procedure TsSpreadOpenDocWriter.WriteTableSettings(AStream: TStream);
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
sheet: TsWorkSheet;
|
sheet: TsWorkSheet;
|
||||||
@ -3191,11 +3359,12 @@ var
|
|||||||
asr: Integer; // ActiveSplitRange
|
asr: Integer; // ActiveSplitRange
|
||||||
showGrid: Boolean;
|
showGrid: Boolean;
|
||||||
begin
|
begin
|
||||||
Result := '';
|
|
||||||
for i:=0 to Workbook.GetWorksheetCount-1 do begin
|
for i:=0 to Workbook.GetWorksheetCount-1 do begin
|
||||||
sheet := Workbook.GetWorksheetByIndex(i);
|
sheet := Workbook.GetWorksheetByIndex(i);
|
||||||
Result := Result + AIndent +
|
|
||||||
'<config:config-item-map-entry config:name="' + sheet.Name + '">' + LineEnding;
|
AppendToStream(AStream,
|
||||||
|
'<config:config-item-map-entry config:name="' + sheet.Name + '">');
|
||||||
|
|
||||||
hsm := 0; vsm := 0; asr := 2;
|
hsm := 0; vsm := 0; asr := 2;
|
||||||
if (soHasFrozenPanes in sheet.Options) then begin
|
if (soHasFrozenPanes in sheet.Options) then begin
|
||||||
if (sheet.LeftPaneWidth > 0) and (sheet.TopPaneHeight > 0) then begin
|
if (sheet.LeftPaneWidth > 0) and (sheet.TopPaneHeight > 0) then begin
|
||||||
@ -3208,21 +3377,34 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
showGrid := (soShowGridLines in sheet.Options);
|
showGrid := (soShowGridLines in sheet.Options);
|
||||||
Result := Result + AIndent +
|
|
||||||
' <config:config-item config:name="CursorPositionX" config:type="int">'+IntToStr(sheet.LeftPaneWidth)+'</config:config-item>' + LineEnding + AIndent +
|
AppendToStream(AStream,
|
||||||
' <config:config-item config:name="CursorPositionY" config:type="int">'+IntToStr(sheet.TopPaneHeight)+'</config:config-item>' + LineEnding + AIndent +
|
'<config:config-item config:name="CursorPositionX" config:type="int">'+IntToStr(sheet.LeftPaneWidth)+'</config:config-item>');
|
||||||
' <config:config-item config:name="HorizontalSplitMode" config:type="short">'+IntToStr(hsm)+'</config:config-item>' + LineEnding + AIndent +
|
AppendToStream(AStream,
|
||||||
' <config:config-item config:name="VerticalSplitMode" config:type="short">'+IntToStr(vsm)+'</config:config-item>' + LineEnding + AIndent +
|
'<config:config-item config:name="CursorPositionY" config:type="int">'+IntToStr(sheet.TopPaneHeight)+'</config:config-item>');
|
||||||
' <config:config-item config:name="HorizontalSplitPosition" config:type="int">'+IntToStr(sheet.LeftPaneWidth)+'</config:config-item>' + LineEnding + AIndent +
|
AppendToStream(AStream,
|
||||||
' <config:config-item config:name="VerticalSplitPosition" config:type="int">'+IntToStr(sheet.TopPaneHeight)+'</config:config-item>' + LineEnding + AIndent +
|
'<config:config-item config:name="HorizontalSplitMode" config:type="short">'+IntToStr(hsm)+'</config:config-item>');
|
||||||
' <config:config-item config:name="ActiveSplitRange" config:type="short">'+IntToStr(asr)+'</config:config-item>' + LineEnding + AIndent +
|
AppendToStream(AStream,
|
||||||
' <config:config-item config:name="PositionLeft" config:type="int">0</config:config-item>' + LineEnding + AIndent +
|
'<config:config-item config:name="VerticalSplitMode" config:type="short">'+IntToStr(vsm)+'</config:config-item>');
|
||||||
' <config:config-item config:name="PositionRight" config:type="int">'+IntToStr(sheet.LeftPaneWidth)+'</config:config-item>' + LineEnding + AIndent +
|
AppendToStream(AStream,
|
||||||
' <config:config-item config:name="PositionTop" config:type="int">0</config:config-item>' + LineEnding + AIndent +
|
'<config:config-item config:name="HorizontalSplitPosition" config:type="int">'+IntToStr(sheet.LeftPaneWidth)+'</config:config-item>');
|
||||||
' <config:config-item config:name="PositionBottom" config:type="int">'+IntToStr(sheet.TopPaneHeight)+'</config:config-item>' + LineEnding + AIndent +
|
AppendToStream(AStream,
|
||||||
' <config:config-item config:name="ShowGrid" config:type="boolean">true</config:config-item>' + LineEnding + AIndent +
|
'<config:config-item config:name="VerticalSplitPosition" config:type="int">'+IntToStr(sheet.TopPaneHeight)+'</config:config-item>');
|
||||||
|
AppendToStream(AStream,
|
||||||
|
'<config:config-item config:name="ActiveSplitRange" config:type="short">'+IntToStr(asr)+'</config:config-item>');
|
||||||
|
AppendToStream(AStream,
|
||||||
|
'<config:config-item config:name="PositionLeft" config:type="int">0</config:config-item>');
|
||||||
|
AppendToStream(AStream,
|
||||||
|
'<config:config-item config:name="PositionRight" config:type="int">'+IntToStr(sheet.LeftPaneWidth)+'</config:config-item>');
|
||||||
|
AppendToStream(AStream,
|
||||||
|
'<config:config-item config:name="PositionTop" config:type="int">0</config:config-item>');
|
||||||
|
AppendToStream(AStream,
|
||||||
|
'<config:config-item config:name="PositionBottom" config:type="int">'+IntToStr(sheet.TopPaneHeight)+'</config:config-item>');
|
||||||
|
AppendToStream(AStream,
|
||||||
|
'<config:config-item config:name="ShowGrid" config:type="boolean">true</config:config-item>');
|
||||||
// this "ShowGrid" overrides the global setting. But Open/LibreOffice do not allow to change ShowGrid per sheet.
|
// this "ShowGrid" overrides the global setting. But Open/LibreOffice do not allow to change ShowGrid per sheet.
|
||||||
'</config:config-item-map-entry>' + LineEnding;
|
AppendToStream(AStream,
|
||||||
|
'</config:config-item-map-entry>');
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -3293,10 +3475,10 @@ begin
|
|||||||
lStyle := '';
|
lStyle := '';
|
||||||
|
|
||||||
// The row should already be the correct one
|
// The row should already be the correct one
|
||||||
FCellContent :=
|
AppendToStream(AStream,
|
||||||
' <table:table-cell office:value-type="string"' + lStyle + '>' + LineEnding +
|
'<table:table-cell office:value-type="string"' + lStyle + '>',
|
||||||
' <text:p>' + UTF8TextToXMLText(AValue) + '</text:p>' + LineEnding +
|
'<text:p>' + UTF8TextToXMLText(AValue) + '</text:p>',
|
||||||
' </table:table-cell>' + LineEnding;
|
'</table:table-cell>');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsSpreadOpenDocWriter.WriteNumber(AStream: TStream; const ARow,
|
procedure TsSpreadOpenDocWriter.WriteNumber(AStream: TStream; const ARow,
|
||||||
@ -3324,16 +3506,17 @@ begin
|
|||||||
|
|
||||||
// The row should already be the correct one
|
// The row should already be the correct one
|
||||||
if IsInfinite(AValue) then begin
|
if IsInfinite(AValue) then begin
|
||||||
StrValue:='1.#INF';
|
StrValue := '1.#INF';
|
||||||
DisplayStr:='1.#INF';
|
DisplayStr := '1.#INF';
|
||||||
end else begin
|
end else begin
|
||||||
StrValue:=FloatToStr(AValue,FPointSeparatorSettings); //Uses '.' as decimal separator
|
StrValue := FloatToStr(AValue, FPointSeparatorSettings); // Uses '.' as decimal separator
|
||||||
DisplayStr:=FloatToStr(AValue); // Uses locale decimal separator
|
DisplayStr := FloatToStr(AValue); // Uses locale decimal separator
|
||||||
end;
|
end;
|
||||||
FCellContent :=
|
|
||||||
' <table:table-cell office:value-type="' + valType + '" office:value="' + StrValue + '"' + lStyle + '>' + LineEnding +
|
AppendToStream(AStream,
|
||||||
' <text:p>' + DisplayStr + '</text:p>' + LineEnding +
|
'<table:table-cell office:value-type="' + valType + '" office:value="' + StrValue + '"' + lStyle + '>',
|
||||||
' </table:table-cell>' + LineEnding;
|
'<text:p>' + DisplayStr + '</text:p>',
|
||||||
|
'</table:table-cell>');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{*******************************************************************
|
{*******************************************************************
|
||||||
@ -3372,12 +3555,10 @@ begin
|
|||||||
strValue := FormatDateTime(FMT[isTimeOnly], AValue);
|
strValue := FormatDateTime(FMT[isTimeOnly], AValue);
|
||||||
displayStr := FormatDateTime(ACell^.NumberFormatStr, AValue);
|
displayStr := FormatDateTime(ACell^.NumberFormatStr, AValue);
|
||||||
|
|
||||||
FCellContent := Format(
|
AppendToStream(AStream, Format(
|
||||||
' <table:table-cell office:value-type="%s" office:%s-value="%s" %s>' + LineEnding +
|
'<table:table-cell office:value-type="%s" office:%s-value="%s" %s>' +
|
||||||
' <text:p>%s</text:p> ' + LineEnding +
|
'<text:p>%s</text:p> ' +
|
||||||
' </table:table-cell>' + LineEnding, [
|
'</table:table-cell>', [DT[isTimeOnly], DT[isTimeOnly], strValue, lStyle, displayStr]));
|
||||||
DT[isTimeOnly], DT[isTimeOnly], strValue, lStyle, displayStr
|
|
||||||
]);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user