{ fpsopendocument.pas Writes an OpenDocument 1.0 Spreadsheet document An OpenDocument document is a compressed ZIP file with the following files inside: content.xml meta.xml settings.xml styles.xml META-INF\manifest.xml Specifications obtained from: write url here AUTHORS: Felipe Monteiro de Carvalho IMPORTANT: This writer doesn't work yet!!! This is just initial code. } unit fpsopendocument; {$ifdef fpc} {$mode delphi} {$endif} interface uses Classes, SysUtils, {zipper,} fpspreadsheet; type { TsSpreadOpenDocWriter } TsSpreadOpenDocWriter = class(TsCustomSpreadWriter) protected // FZip: TZipper; FMetaInfManifest: string; FMeta, FSettings, FStyles: string; FContent: string; public { General writing methods } procedure WriteStringToFile(AFileName, AString: string); procedure WriteToFile(AFileName: string; AData: TsWorkbook); override; procedure WriteToStream(AStream: TStream; AData: TsWorkbook); override; { Record writing methods } procedure WriteLabel(AStream: TStream; const ARow, ACol: Word; const AValue: string); override; procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal; const AValue: double); override; end; implementation const { OpenDocument general XML constants } XML_HEADER = ''; { OpenDocument Directory structure constants } OOXML_PATH_CONTENT = 'content.xml'; OOXML_PATH_META = 'meta.xml'; OOXML_PATH_SETTINGS = 'settings.xml'; OOXML_PATH_STYLES = 'styles.xml'; OPENDOC_PATH_METAINF = 'META-INF\'; OPENDOC_PATH_METAINF_MANIFEST = 'META-INF\manifest.xml'; { OpenDocument schemas constants } SCHEMAS_XMLNS_OFFICE = 'urn:oasis:names:tc:opendocument:xmlns:office:1.0'; SCHEMAS_XMLNS_DCTERMS = 'http://purl.org/dc/terms/'; SCHEMAS_XMLNS_META = 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0'; SCHEMAS_XMLNS = 'http://schemas.openxmlformats.org/officeDocument/2006/extended-properties'; SCHEMAS_XMLNS_CONFIG = 'urn:oasis:names:tc:opendocument:xmlns:config:1.0'; SCHEMAS_XMLNS_OOO = 'http://openoffice.org/2004/office'; SCHEMAS_XMLNS_MANIFEST = 'urn:oasis:names:tc:opendocument:xmlns:manifest:1.0'; SCHEMAS_XMLNS_FO = 'urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0'; SCHEMAS_XMLNS_STYLE = 'urn:oasis:names:tc:opendocument:xmlns:style:1.0'; SCHEMAS_XMLNS_SVG = 'urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0'; SCHEMAS_XMLNS_TABLE = 'urn:oasis:names:tc:opendocument:xmlns:table:1.0'; SCHEMAS_XMLNS_TEXT = 'urn:oasis:names:tc:opendocument:xmlns:text:1.0'; SCHEMAS_XMLNS_V = 'urn:schemas-microsoft-com:vml'; SCHEMAS_XMLNS_NUMBER = 'urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0'; SCHEMAS_XMLNS_CHART = 'urn:oasis:names:tc:opendocument:xmlns:chart:1.0'; SCHEMAS_XMLNS_DR3D = 'urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0'; SCHEMAS_XMLNS_MATH = 'http://www.w3.org/1998/Math/MathML'; SCHEMAS_XMLNS_FORM = 'urn:oasis:names:tc:opendocument:xmlns:form:1.0'; SCHEMAS_XMLNS_SCRIPT = 'urn:oasis:names:tc:opendocument:xmlns:script:1.0'; SCHEMAS_XMLNS_OOOW = 'http://openoffice.org/2004/writer'; SCHEMAS_XMLNS_OOOC = 'http://openoffice.org/2004/calc'; SCHEMAS_XMLNS_DOM = 'http://www.w3.org/2001/xml-events'; SCHEMAS_XMLNS_XFORMS = 'http://www.w3.org/2002/xforms'; SCHEMAS_XMLNS_XSD = 'http://www.w3.org/2001/XMLSchema'; SCHEMAS_XMLNS_XSI = 'http://www.w3.org/2001/XMLSchema-instance'; { TsSpreadOpenDocWriter } {******************************************************************* * TsSpreadOOXMLWriter.WriteStringToFile () * * DESCRIPTION: Writes a string to a file. Helper convenience method. * *******************************************************************} procedure TsSpreadOpenDocWriter.WriteStringToFile(AFileName, AString: string); var TheStream : TFileStream; S : String; begin TheStream := TFileStream.Create(AFileName, fmCreate); S:=AString; TheStream.WriteBuffer(Pointer(S)^,Length(S)); TheStream.Free; end; {******************************************************************* * TsSpreadOOXMLWriter.WriteToFile () * * DESCRIPTION: Writes an OOXML document to the disc * *******************************************************************} procedure TsSpreadOpenDocWriter.WriteToFile(AFileName: string; AData: TsWorkbook); var TempDir: string; begin {FZip := TZipper.Create; FZip.ZipFiles(AFileName, x); FZip.Free;} WriteToStream(nil, AData); TempDir := IncludeTrailingBackslash(AFileName); { files on the root path } ForceDirectories(TempDir); WriteStringToFile(TempDir + OOXML_PATH_CONTENT, FContent); WriteStringToFile(TempDir + OOXML_PATH_META, FMeta); WriteStringToFile(TempDir + OOXML_PATH_SETTINGS, FSettings); WriteStringToFile(TempDir + OOXML_PATH_STYLES, FStyles); { META-INF directory } ForceDirectories(TempDir + OPENDOC_PATH_METAINF); WriteStringToFile(TempDir + OPENDOC_PATH_METAINF_MANIFEST, FMetaInfManifest); end; {******************************************************************* * TsSpreadOOXMLWriter.WriteToStream () * * DESCRIPTION: Writes an Excel 2 file to a stream * * Excel 2.x files support only one Worksheet per Workbook, * so only the first will be written. * *******************************************************************} procedure TsSpreadOpenDocWriter.WriteToStream(AStream: TStream; AData: TsWorkbook); begin // WriteCellsToStream(AStream, AData.GetFirstWorksheet.FCells); FMetaInfManifest := XML_HEADER + LineEnding + '' + LineEnding + ' ' + LineEnding + ' ' + LineEnding + ' ' + LineEnding + ' ' + LineEnding + ' ' + LineEnding + ''; FMeta := XML_HEADER + LineEnding + '' + LineEnding + ' ' + LineEnding + ' FPSpreadsheet Library' + LineEnding + ' ' + LineEnding + ' ' + LineEnding + ''; FSettings := XML_HEADER + LineEnding + '' + LineEnding + '' + LineEnding + ' ' + LineEnding + ' ' + LineEnding + ' ' + LineEnding + ' Tabelle1' + LineEnding + ' 100' + LineEnding + ' 100' + LineEnding + ' false' + LineEnding + ' true' + LineEnding + ' ' + LineEnding + ' ' + LineEnding + ' 3' + LineEnding + ' 2' + LineEnding + ' ' + LineEnding + ' ' + LineEnding + ' ' + LineEnding + ' ' + LineEnding + ' ' + LineEnding + ' ' + LineEnding + ''; FStyles := XML_HEADER + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + ''; FContent := XML_HEADER + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '1' + LineEnding + '' + LineEnding + '' + LineEnding + '2' + LineEnding + '' + LineEnding + '' + LineEnding + '3' + LineEnding + '' + LineEnding + '' + LineEnding + '4' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + 'First' + LineEnding + '' + LineEnding + '' + LineEnding + 'Second' + LineEnding + '' + LineEnding + '' + LineEnding + 'Third' + LineEnding + '' + LineEnding + '' + LineEnding + 'Fourth' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + '' + LineEnding + ''; end; {******************************************************************* * TsSpreadOOXMLWriter.WriteLabel () * * DESCRIPTION: Writes an Excel 2 LABEL record * * Writes a string to the sheet * *******************************************************************} procedure TsSpreadOpenDocWriter.WriteLabel(AStream: TStream; const ARow, ACol: Word; const AValue: string); var L: Byte; begin L := Length(AValue); { BIFF Record header } // AStream.WriteWord(WordToLE(INT_EXCEL_ID_LABEL)); // AStream.WriteWord(WordToLE(8 + L)); { BIFF Record data } // AStream.WriteWord(WordToLE(ARow)); // AStream.WriteWord(WordToLE(ACol)); { BIFF2 Attributes } AStream.WriteByte($0); AStream.WriteByte($0); AStream.WriteByte($0); { String with 8-bit size } AStream.WriteByte(L); AStream.WriteBuffer(AValue[1], L); end; {******************************************************************* * TsSpreadOOXMLWriter.WriteNumber () * * DESCRIPTION: Writes an Excel 2 NUMBER record * * Writes a number (64-bit IEE 754 floating point) to the sheet * *******************************************************************} procedure TsSpreadOpenDocWriter.WriteNumber(AStream: TStream; const ARow, ACol: Cardinal; const AValue: double); begin { BIFF Record header } // AStream.WriteWord(WordToLE(INT_EXCEL_ID_NUMBER)); // AStream.WriteWord(WordToLE(15)); { BIFF Record data } // AStream.WriteWord(WordToLE(ARow)); // AStream.WriteWord(WordToLE(ACol)); { BIFF2 Attributes } AStream.WriteByte($0); AStream.WriteByte($0); AStream.WriteByte($0); { IEE 754 floating-point value } AStream.WriteBuffer(AValue, 8); end; {******************************************************************* * Initialization section * * Registers this reader / writer on fpSpreadsheet * *******************************************************************} initialization RegisterSpreadFormat(TsCustomSpreadReader, TsSpreadOpenDocWriter, sfOpenDocument); end.