Initial commit of fpspreadsheet.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@362 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
sekelsenmat 2008-02-24 13:18:34 +00:00
parent a736e0a50d
commit 4f04afdb1c
13 changed files with 4247 additions and 0 deletions

View File

@ -0,0 +1,2 @@
"C:\Program Files\Doc-O-Matic 6 Express\domexpress.exe" -config "HTML Help" fpspreadsheet.dox-express
pause

View File

@ -0,0 +1,251 @@
<?xml version="1.0"?>
<CONFIG>
<ProjectOptions>
<PathDelim Value="\"/>
<Version Value="6"/>
<General>
<MainUnit Value="0"/>
<IconPath Value="./"/>
<TargetFileExt Value=".exe"/>
<ActiveEditorIndexAtStart Value="1"/>
</General>
<VersionInfo>
<ProjectVersion Value=""/>
<Language Value=""/>
<CharSet Value=""/>
</VersionInfo>
<PublishOptions>
<Version Value="2"/>
<IgnoreBinaries Value="False"/>
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
<ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
</PublishOptions>
<RunParams>
<local>
<FormatVersion Value="1"/>
<LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
</local>
</RunParams>
<Units Count="15">
<Unit0>
<Filename Value="excel5demo.lpr"/>
<IsPartOfProject Value="True"/>
<UnitName Value="excel5demo"/>
<CursorPos X="5" Y="12"/>
<TopLine Value="1"/>
<EditorIndex Value="0"/>
<UsageCount Value="49"/>
<Loaded Value="True"/>
</Unit0>
<Unit1>
<Filename Value="..\fpspreadsheet.pas"/>
<UnitName Value="fpspreadsheet"/>
<CursorPos X="32" Y="414"/>
<TopLine Value="388"/>
<EditorIndex Value="1"/>
<UsageCount Value="25"/>
<Loaded Value="True"/>
</Unit1>
<Unit2>
<Filename Value="..\xlsbiff5.pas"/>
<UnitName Value="xlsbiff5"/>
<CursorPos X="16" Y="320"/>
<TopLine Value="300"/>
<EditorIndex Value="4"/>
<UsageCount Value="25"/>
<Loaded Value="True"/>
</Unit2>
<Unit3>
<Filename Value="C:\Programas\FPC220\source\packages\base\winunits\activex.pp"/>
<UnitName Value="ActiveX"/>
<CursorPos X="27" Y="29"/>
<TopLine Value="6"/>
<UsageCount Value="9"/>
</Unit3>
<Unit4>
<Filename Value="..\fpolestorage.pas"/>
<UnitName Value="fpolestorage"/>
<CursorPos X="1" Y="1"/>
<TopLine Value="1"/>
<EditorIndex Value="5"/>
<UsageCount Value="45"/>
<Loaded Value="True"/>
</Unit4>
<Unit5>
<Filename Value="C:\Programas\FPC220\source\rtl\inc\objpash.inc"/>
<CursorPos X="21" Y="141"/>
<TopLine Value="131"/>
<UsageCount Value="9"/>
</Unit5>
<Unit6>
<Filename Value="..\xlsbiff2.pas"/>
<UnitName Value="xlsbiff2"/>
<CursorPos X="20" Y="277"/>
<TopLine Value="260"/>
<EditorIndex Value="2"/>
<UsageCount Value="18"/>
<Loaded Value="True"/>
</Unit6>
<Unit7>
<Filename Value="C:\Programas\FPC220\source\rtl\objpas\classes\classesh.inc"/>
<CursorPos X="22" Y="1602"/>
<TopLine Value="1598"/>
<UsageCount Value="11"/>
</Unit7>
<Unit8>
<Filename Value="C:\Programas\FPC220\source\rtl\win32\buildrtl.pp"/>
<UnitName Value="buildrtl"/>
<CursorPos X="29" Y="5"/>
<TopLine Value="1"/>
<UsageCount Value="9"/>
</Unit8>
<Unit9>
<Filename Value="C:\Programas\FPC220\source\rtl\objpas\fgl.pp"/>
<UnitName Value="fgl"/>
<CursorPos X="15" Y="86"/>
<TopLine Value="55"/>
<EditorIndex Value="7"/>
<UsageCount Value="18"/>
<Loaded Value="True"/>
</Unit9>
<Unit10>
<Filename Value="C:\Programas\lazarus\lcl\interfaces\win32\win32wsstdctrls.pp"/>
<UnitName Value="Win32WSStdCtrls"/>
<CursorPos X="11" Y="737"/>
<TopLine Value="713"/>
<EditorIndex Value="6"/>
<UsageCount Value="14"/>
<Loaded Value="True"/>
</Unit10>
<Unit11>
<Filename Value="C:\Programas\lazarus\lcl\interfaces\win32\win32wscontrols.pp"/>
<UnitName Value="Win32WSControls"/>
<CursorPos X="13" Y="206"/>
<TopLine Value="199"/>
<UsageCount Value="12"/>
</Unit11>
<Unit12>
<Filename Value="C:\Programas\lazarus\components\sqlite\registersqlite3.pas"/>
<UnitName Value="registersqlite3"/>
<CursorPos X="15" Y="5"/>
<TopLine Value="1"/>
<UsageCount Value="11"/>
</Unit12>
<Unit13>
<Filename Value="C:\Programas\lazarus\ideintf\componenteditors.pas"/>
<UnitName Value="ComponentEditors"/>
<CursorPos X="54" Y="353"/>
<TopLine Value="330"/>
<EditorIndex Value="3"/>
<UsageCount Value="12"/>
<Loaded Value="True"/>
</Unit13>
<Unit14>
<Filename Value="C:\Programas\FPC220\source\rtl\objpas\classes\cregist.inc"/>
<CursorPos X="17" Y="124"/>
<TopLine Value="121"/>
<UsageCount Value="11"/>
</Unit14>
</Units>
<JumpHistory Count="21" HistoryIndex="20">
<Position1>
<Filename Value="C:\Programas\FPC220\source\rtl\objpas\fgl.pp"/>
<Caret Line="1" Column="1" TopLine="1"/>
</Position1>
<Position2>
<Filename Value="C:\Programas\lazarus\lcl\interfaces\win32\win32wsstdctrls.pp"/>
<Caret Line="1" Column="1" TopLine="1"/>
</Position2>
<Position3>
<Filename Value="C:\Programas\lazarus\lcl\interfaces\win32\win32wsstdctrls.pp"/>
<Caret Line="737" Column="11" TopLine="713"/>
</Position3>
<Position4>
<Filename Value="C:\Programas\lazarus\ideintf\componenteditors.pas"/>
<Caret Line="353" Column="54" TopLine="330"/>
</Position4>
<Position5>
<Filename Value="..\xlsbiff5.pas"/>
<Caret Line="335" Column="1" TopLine="318"/>
</Position5>
<Position6>
<Filename Value="..\fpspreadsheet.pas"/>
<Caret Line="601" Column="1" TopLine="559"/>
</Position6>
<Position7>
<Filename Value="..\fpspreadsheet.pas"/>
<Caret Line="1" Column="1" TopLine="1"/>
</Position7>
<Position8>
<Filename Value="..\fpspreadsheet.pas"/>
<Caret Line="601" Column="1" TopLine="559"/>
</Position8>
<Position9>
<Filename Value="..\fpspreadsheet.pas"/>
<Caret Line="612" Column="1" TopLine="573"/>
</Position9>
<Position10>
<Filename Value="..\xlsbiff5.pas"/>
<Caret Line="61" Column="12" TopLine="44"/>
</Position10>
<Position11>
<Filename Value="..\xlsbiff5.pas"/>
<Caret Line="68" Column="17" TopLine="45"/>
</Position11>
<Position12>
<Filename Value="..\xlsbiff5.pas"/>
<Caret Line="216" Column="15" TopLine="193"/>
</Position12>
<Position13>
<Filename Value="..\xlsbiff5.pas"/>
<Caret Line="221" Column="15" TopLine="198"/>
</Position13>
<Position14>
<Filename Value="..\xlsbiff5.pas"/>
<Caret Line="334" Column="16" TopLine="311"/>
</Position14>
<Position15>
<Filename Value="..\xlsbiff5.pas"/>
<Caret Line="345" Column="37" TopLine="322"/>
</Position15>
<Position16>
<Filename Value="..\xlsbiff5.pas"/>
<Caret Line="332" Column="22" TopLine="311"/>
</Position16>
<Position17>
<Filename Value="..\xlsbiff5.pas"/>
<Caret Line="351" Column="28" TopLine="298"/>
</Position17>
<Position18>
<Filename Value="..\fpspreadsheet.pas"/>
<Caret Line="190" Column="13" TopLine="167"/>
</Position18>
<Position19>
<Filename Value="..\fpspreadsheet.pas"/>
<Caret Line="189" Column="1" TopLine="167"/>
</Position19>
<Position20>
<Filename Value="..\fpspreadsheet.pas"/>
<Caret Line="594" Column="1" TopLine="552"/>
</Position20>
<Position21>
<Filename Value="..\fpspreadsheet.pas"/>
<Caret Line="164" Column="1" TopLine="156"/>
</Position21>
</JumpHistory>
</ProjectOptions>
<CompilerOptions>
<Version Value="5"/>
<PathDelim Value="\"/>
<SearchPaths>
<OtherUnitFiles Value="..\"/>
<SrcPath Value="..\"/>
</SearchPaths>
<CodeGeneration>
<Generate Value="Faster"/>
</CodeGeneration>
<Other>
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
</CONFIG>

View File

@ -0,0 +1,59 @@
{
excel5demo.dpr
Demonstrates how to write an Excel 5.x file using the fpspreadsheet library
AUTHORS: Felipe Monteiro de Carvalho
}
program excel5demo;
{$mode delphi}{$H+}
uses
Classes, SysUtils, fpspreadsheet, xlsbiff5;
var
MyWorkbook: TsWorkbook;
MyWorksheet: TsWorksheet;
MyFormula: TRPNFormula;
MyDir: string;
begin
// Open the output file
MyDir := ExtractFilePath(ParamStr(0));
// Create the spreadsheet
MyWorkbook := TsWorkbook.Create;
MyWorksheet := MyWorkbook.AddWorksheet('My Worksheet');
// Write some number cells
MyWorksheet.WriteNumber(0, 0, 1.0);
MyWorksheet.WriteNumber(0, 1, 2.0);
MyWorksheet.WriteNumber(0, 2, 3.0);
MyWorksheet.WriteNumber(0, 3, 4.0);
// Write the formula E1 = A1 + B1
// or, in RPN: A1, B1, +
SetLength(MyFormula, 3);
MyFormula[0].TokenID := INT_EXCEL_TOKEN_TREFV; {A1}
MyFormula[0].Col := 0;
MyFormula[0].Row := 0;
MyFormula[1].TokenID := INT_EXCEL_TOKEN_TREFV; {B1}
MyFormula[1].Col := 1;
MyFormula[1].Row := 0;
MyFormula[2].TokenID := INT_EXCEL_TOKEN_TADD; {+}
MyWorksheet.WriteRPNFormula(0, 4, MyFormula);
// Creates a new worksheet
MyWorksheet := MyWorkbook.AddWorksheet('My Worksheet 2');
// Write some string cells
MyWorksheet.WriteAnsiText(0, 0, 'First');
MyWorksheet.WriteAnsiText(0, 1, 'Second');
MyWorksheet.WriteAnsiText(0, 2, 'Third');
MyWorksheet.WriteAnsiText(0, 3, 'Fourth');
// Save the spreadsheet to a file
MyWorkbook.WriteToFile(MyDir + 'test' + STR_EXCEL_EXTENSION, sfExcel5);
MyWorkbook.Free;
end.

View File

@ -0,0 +1,78 @@
{
fpolestorage.pas
Writes an OLE document
AUTHORS: Felipe Monteiro de Carvalho
}
unit fpolestorage;
{$ifdef fpc}
{$mode delphi}
{$endif}
interface
uses
{$ifdef Windows}
ActiveX, ComObj,
{$endif}
Classes, SysUtils;
type
{ TOLEStorage }
TOLEStorage = class
private
{$ifdef Windows}
FStorage: IStorage;
FStream: IStream;
{$endif}
public
constructor Create;
destructor Destroy; override;
procedure WriteStreamToOLEFile(AFileName: string; AMemStream: TMemoryStream);
end;
implementation
{ TOLEStorage }
constructor TOLEStorage.Create;
begin
inherited Create;
end;
destructor TOLEStorage.Destroy;
begin
inherited Destroy;
end;
procedure TOLEStorage.WriteStreamToOLEFile(AFileName: string; AMemStream: TMemoryStream);
var
cbWritten: Cardinal;
begin
{$ifdef Windows}
{ Initialize the Component Object Model (COM) before calling s functions }
OleCheck(CoInitialize(nil));
{ Create a Storage Object }
OleCheck(StgCreateDocfile(PWideChar(WideString(AFileName)),
STGM_READWRITE or STGM_FAILIFTHERE or STGM_SHARE_EXCLUSIVE or STGM_DIRECT,
0, FStorage));
{ Create a workbook stream in the storage. A BIFF5 file must
have at least a workbook stream. This stream *must* be named 'Book' }
OleCheck(FStorage.CreateStream('Book',
STGM_READWRITE or STGM_SHARE_EXCLUSIVE or STGM_DIRECT, 0, 0, FStream));
{ Write all data }
FStream.Write(AMemStream.Memory, AMemStream.Size, @cbWritten);
{$endif}
end;
end.

View File

@ -0,0 +1,18 @@
{
fpsallformats.pas
Unit to quickly add all supported fpspreadsheet formats to the project
AUTHORS: Felipe Monteiro de Carvalho
}
unit fpsallformats;
interface
uses
xlsbiff2, xlsbiff5;
implementation
end.

View File

@ -0,0 +1,407 @@
{
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 = '<?xml version="1.0" encoding="utf-8" ?>';
{ 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 +
'<manifest:manifest xmlns:manifest="' + SCHEMAS_XMLNS_MANIFEST + '">' + LineEnding +
' <manifest:file-entry manifest:media-type="application/vnd.oasis.opendocument.spreadsheet" manifest:full-path="/" />' + LineEnding +
' <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="content.xml" />' + LineEnding +
' <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="meta.xml" />' + LineEnding +
' <manifest:file-entry manifest:media-type="text/xml" manifest:full-path="settings.xml" />' + LineEnding +
'</manifest:manifest>';
FMeta :=
XML_HEADER + LineEnding +
'<office:document-meta xmlns:office="' + SCHEMAS_XMLNS_OFFICE +
'" xmlns:dcterms="' + SCHEMAS_XMLNS_DCTERMS +
'" xmlns:meta="' + SCHEMAS_XMLNS_META +
'" xmlns="' + SCHEMAS_XMLNS +
'" xmlns:ex="' + SCHEMAS_XMLNS + '">' + LineEnding +
' <office:meta>' + LineEnding +
' <meta:generator>FPSpreadsheet Library</meta:generator>' + LineEnding +
' <meta:document-statistic />' + LineEnding +
' </office:meta>' + LineEnding +
'</office:document-meta>';
FSettings :=
XML_HEADER + LineEnding +
'<office:document-settings xmlns:office="' + SCHEMAS_XMLNS_OFFICE +
'" xmlns:config="' + SCHEMAS_XMLNS_CONFIG +
'" xmlns:ooo="' + SCHEMAS_XMLNS_OOO + '">' + LineEnding +
'<office:settings>' + LineEnding +
' <config:config-item-set config:name="ooo:view-settings">' + LineEnding +
' <config:config-item-map-indexed config:name="Views">' + LineEnding +
' <config:config-item-map-entry>' + LineEnding +
' <config:config-item config:name="ActiveTable" config:type="string">Tabelle1</config:config-item>' + LineEnding +
' <config:config-item config:name="ZoomValue" config:type="int">100</config:config-item>' + LineEnding +
' <config:config-item config:name="PageViewZoomValue" config:type="int">100</config:config-item>' + LineEnding +
' <config:config-item config:name="ShowPageBreakPreview" config:type="boolean">false</config:config-item>' + LineEnding +
' <config:config-item config:name="HasColumnRowHeaders" config:type="boolean">true</config:config-item>' + LineEnding +
' <config:config-item-map-named config:name="Tables">' + LineEnding +
' <config:config-item-map-entry config:name="Tabelle1">' + LineEnding +
' <config:config-item config:name="CursorPositionX" config:type="int">3</config:config-item>' + LineEnding +
' <config:config-item config:name="CursorPositionY" config:type="int">2</config:config-item>' + LineEnding +
' </config:config-item-map-entry>' + LineEnding +
' </config:config-item-map-named>' + LineEnding +
' </config:config-item-map-entry>' + LineEnding +
' </config:config-item-map-indexed>' + LineEnding +
' </config:config-item-set>' + LineEnding +
' </office:settings>' + LineEnding +
'</office:document-settings>';
FStyles :=
XML_HEADER + LineEnding +
'<office:document-styles xmlns:office="' + SCHEMAS_XMLNS_OFFICE +
'" xmlns:fo="' + SCHEMAS_XMLNS_FO +
'" xmlns:style="' + SCHEMAS_XMLNS_STYLE +
'" xmlns:svg="' + SCHEMAS_XMLNS_SVG +
'" xmlns:table="' + SCHEMAS_XMLNS_TABLE +
'" xmlns:text="' + SCHEMAS_XMLNS_TEXT +
'" xmlns:v="' + SCHEMAS_XMLNS_V + '">' + LineEnding +
'<office:font-face-decls>' + LineEnding +
'<style:font-face style:name="Arial" svg:font-family="Arial" />' + LineEnding +
'</office:font-face-decls>' + LineEnding +
'<office:styles>' + LineEnding +
'<style:style style:name="Default" style:family="table-cell">' + LineEnding +
'<style:text-properties fo:font-size="10" style:font-name="Arial" />' + LineEnding +
'</style:style>' + LineEnding +
'</office:styles>' + LineEnding +
'<office:automatic-styles>' + LineEnding +
'<style:page-layout style: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" />' + LineEnding +
'<style:header-style>' + 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" />' + LineEnding +
'</style:header-style>' + LineEnding +
'<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 +
'</style:footer-style>' + LineEnding +
'</style:page-layout>' + LineEnding +
'</office:automatic-styles>' + LineEnding +
'<office:master-styles>' + LineEnding +
'<style:master-page style:name="Default" style:page-layout-name="pm1">' + LineEnding +
'<style:header />' + LineEnding +
'<style:header-left style:display="false" />' + LineEnding +
'<style:footer />' + LineEnding +
'<style:footer-left style:display="false" />' + LineEnding +
'</style:master-page>' + LineEnding +
'</office:master-styles>' + LineEnding +
'</office:document-styles>';
FContent :=
XML_HEADER + LineEnding +
'<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 + '">' + LineEnding +
'<office:scripts />' + LineEnding +
'<office:font-face-decls>' + LineEnding +
'<style:font-face style:name="Arial" svg:font-family="Arial" xmlns:v="urn:schemas-microsoft-com:vml" />' + LineEnding +
'</office:font-face-decls>' + LineEnding +
'<office:automatic-styles>' + LineEnding +
'<style:style style:name="ID0EM" style:family="table-column" xmlns:v="urn:schemas-microsoft-com:vml">' + LineEnding +
'<style:table-column-properties fo:break-before="auto" style:column-width="1.961cm" />' + LineEnding +
'</style:style>' + LineEnding +
'<style:style style:name="ID0EM" style:family="table-row" xmlns:v="urn:schemas-microsoft-com:vml">' + LineEnding +
'<style:table-row-properties fo:break-before="auto" style:row-height="0.45cm" />' + LineEnding +
'</style:style>' + LineEnding +
'<style:style style:name="ID1E6B" style:family="table-cell" style:parent-style-name="Default" xmlns:v="urn:schemas-microsoft-com:vml">' + LineEnding +
'<style:text-properties fo:font-size="10" style:font-name="Arial" />' + LineEnding +
'</style:style>' + LineEnding +
'<style:style style:name="ID2EY" style:family="table" style:master-page-name="Default" xmlns:v="urn:schemas-microsoft-com:vml">' + LineEnding +
'<style:table-properties />' + LineEnding +
'</style:style>' + LineEnding +
'<style:style style:name="scenario" style:family="table" style:master-page-name="Default">' + LineEnding +
'<style:table-properties table:display="false" style:writing-mode="lr-tb" />' + LineEnding +
'</style:style>' + LineEnding +
'</office:automatic-styles>' + LineEnding +
'<office:body>' + LineEnding +
'<office:spreadsheet>' + LineEnding +
'<table:table table:name="Tabelle1" table:style-name="ID2EY">' + LineEnding +
'<table:table-column table:style-name="ID0EM" table:number-columns-repeated="256" table:default-cell-style-name="ID1E6B" xmlns:v="urn:schemas-microsoft-com:vml" />' + LineEnding +
'<table:table-row table:style-name="ID0EM" xmlns:v="urn:schemas-microsoft-com:vml">' + LineEnding +
'<table:table-cell office:value-type="float" office:value="1">' + LineEnding +
'<text:p>1</text:p>' + LineEnding +
'</table:table-cell>' + LineEnding +
'<table:table-cell office:value-type="float" office:value="2">' + LineEnding +
'<text:p>2</text:p>' + LineEnding +
'</table:table-cell>' + LineEnding +
'<table:table-cell office:value-type="float" office:value="3">' + LineEnding +
'<text:p>3</text:p>' + LineEnding +
'</table:table-cell>' + LineEnding +
'<table:table-cell office:value-type="float" office:value="4">' + LineEnding +
'<text:p>4</text:p>' + LineEnding +
'</table:table-cell>' + LineEnding +
'<table:table-cell table:number-columns-repeated="252" />' + LineEnding +
'</table:table-row>' + LineEnding +
'<table:table-row table:style-name="ID0EM" xmlns:v="urn:schemas-microsoft-com:vml">' + LineEnding +
'<table:table-cell office:value-type="string">' + LineEnding +
'<text:p>First</text:p>' + LineEnding +
'</table:table-cell>' + LineEnding +
'<table:table-cell office:value-type="string">' + LineEnding +
'<text:p>Second</text:p>' + LineEnding +
'</table:table-cell>' + LineEnding +
'<table:table-cell office:value-type="string">' + LineEnding +
'<text:p>Third</text:p>' + LineEnding +
'</table:table-cell>' + LineEnding +
'<table:table-cell office:value-type="string">' + LineEnding +
'<text:p>Fourth</text:p>' + LineEnding +
'</table:table-cell>' + LineEnding +
'<table:table-cell table:number-columns-repeated="252" />' + LineEnding +
'</table:table-row>' + LineEnding +
'</table:table>' + LineEnding +
'<table:database-ranges />' + LineEnding +
'</office:spreadsheet>' + LineEnding +
'</office:body>' + LineEnding +
'</office:document-content>';
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.

Binary file not shown.

View File

@ -0,0 +1,847 @@
; This is a Doc-O-Matic version 6.1.0.1246 project file.
; This file is maintained by Doc-O-Matic, do not edit manually.
[AutoTexts]
Empty=0
Saved=1
Text0=This is unknown %SYMBOLNAME%.
Text1=This is class %SYMBOLNAME%.
Text10=This is file %SYMBOLNAME%.
Text11=This is record %SYMBOLNAME%.
Text12=This is %SYMBOLNAME%.
Text13=This is nested type %SYMBOLNAME%.
Text14=This is namespace %SYMBOLNAME%.
Text2=This is %MEMBERNAME%, a member of class %CLASSNAME%.
Text3=This is %MEMBERNAME%, a member of class %CLASSNAME%.
Text4=This is %MEMBERNAME%, a member of class %CLASSNAME%.
Text5=This is function %SYMBOLNAME%.
Text6=This is type %SYMBOLNAME%.
Text7=This is variable %SYMBOLNAME%.
Text8=This is constant %SYMBOLNAME%.
Text9=This is macro %SYMBOLNAME%.
[Configurations]
Count=3
Current=0
Name0=HTML
Name1=HTML Help
Name2=Help 2
[Configurations\Help 2\{D3A588E0-9472-11D3-BDD1-0080C8BA053D}\AdditionalFiles]
Count=4
File0=C:\Program Files\Doc-O-Matic 6 Express\graphics\footer-bkg-whitegradient.gif
File1=C:\Program Files\Doc-O-Matic 6 Express\graphics\header-bkg-whitegradient.gif
File2=C:\Program Files\Doc-O-Matic 6 Express\graphics\html_fullframegradient.gif
File3=C:\Program Files\Doc-O-Matic 6 Express\graphics\html_titlebkg.jpg
[Configurations\Help 2\{D3A588E0-9472-11D3-BDD1-0080C8BA053D}\General]
ClearDirectoryBeforeExport=0
HelpKind=2
OutputDir=C:\Documents and Settings\mf75rt\My Documents\Doc-O-Matic\output
TargetBOM=1
TargetCodepage=utf-8
[Configurations\Help 2\{D3A588E0-9472-11D3-BDD1-0080C8BA053D}\General Build Options]
ShowDocumentation=1
[Configurations\Help 2\{D3A588E0-9472-11D3-BDD1-0080C8BA053D}\HTMLHelp]
CompileFullTextSearchInformation=1
CreateBinaryIndex=1
CreateBinaryTOC=0
CreateCHIFile=0
CreateHelp2FullTextIndex=1
DontIncludeFolders=0
Help2AdditionalXMLData=
Help2Collection=
Help2Compiler=
Help2CompileResult=0
Help2Dexplore=
Help2GenericInfoType=kbRef
Help2ID=
Help2Locale=kbEnglish
Help2Namespace=
Help2PluginNamespace=0
Help2PluginNamespaceName=MS.VSIPCC+
Help2RegisterType=0
Help2UnregisterNamespace=1
HelpCompiler=
HTMLHelp2Filename=
HTMLHelpDisplayFontScaleButton=0
HTMLHelpFilename=
SaveUserPosition=1
SupportEnhancedDecompilation=0
WindowPosition_Bottom=0
WindowPosition_Left=0
WindowPosition_Right=0
WindowPosition_Top=0
[Configurations\Help 2\Image Paths]
Count=2
Path0=C:\Program Files\Doc-O-Matic 6 Express\graphics
Path1=C:\Program Files\Doc-O-Matic 6 Express\graphics\en
[Configurations\Help 2\Output Options]
ClassHierarchyLayoutOutputDir=C:\Documents and Settings\mf75rt\My Documents\Doc-O-Matic\graphics
[Configurations\Help 2\OutputFormat]
ID={D3A588E0-9472-11D3-BDD1-0080C8BA053D}
[Configurations\HTML Help\{D3A588E0-9472-11D3-BDD1-0080C8BA053D}\AdditionalFiles]
Count=4
File0=C:\Program Files\Doc-O-Matic 6 Express\graphics\footer-bkg-whitegradient.gif
File1=C:\Program Files\Doc-O-Matic 6 Express\graphics\header-bkg-whitegradient.gif
File2=C:\Program Files\Doc-O-Matic 6 Express\graphics\html_fullframegradient.gif
File3=C:\Program Files\Doc-O-Matic 6 Express\graphics\html_titlebkg.jpg
[Configurations\HTML Help\{D3A588E0-9472-11D3-BDD1-0080C8BA053D}\General]
ClearDirectoryBeforeExport=0
HelpKind=1
OutputDir=C:\Documents and Settings\mf75rt\My Documents\Doc-O-Matic\output
TargetBOM=0
TargetCodepage=windows-1252
[Configurations\HTML Help\{D3A588E0-9472-11D3-BDD1-0080C8BA053D}\General Build Options]
ShowDocumentation=1
[Configurations\HTML Help\{D3A588E0-9472-11D3-BDD1-0080C8BA053D}\HTMLHelp]
CompileFullTextSearchInformation=1
CreateBinaryIndex=1
CreateBinaryTOC=1
CreateCHIFile=0
CreateHelp2FullTextIndex=1
DontIncludeFolders=0
Help2AdditionalXMLData=
Help2Collection=
Help2Compiler=
Help2CompileResult=0
Help2Dexplore=
Help2GenericInfoType=kbRef
Help2ID=
Help2Locale=kbEnglish
Help2Namespace=
Help2PluginNamespace=0
Help2PluginNamespaceName=MS.VSIPCC+
Help2RegisterType=0
Help2UnregisterNamespace=1
HelpCompiler=
HTMLHelp2Filename=
HTMLHelpDisplayFontScaleButton=0
HTMLHelpFilename=
SaveUserPosition=1
SupportEnhancedDecompilation=0
WindowPosition_Bottom=0
WindowPosition_Left=0
WindowPosition_Right=0
WindowPosition_Top=0
[Configurations\HTML Help\Image Paths]
Count=2
Path0=C:\Program Files\Doc-O-Matic 6 Express\graphics
Path1=C:\Program Files\Doc-O-Matic 6 Express\graphics\en
[Configurations\HTML Help\Output Options]
ClassHierarchyLayoutOutputDir=C:\Documents and Settings\mf75rt\My Documents\Doc-O-Matic\graphics
[Configurations\HTML Help\OutputFormat]
ID={D3A588E0-9472-11D3-BDD1-0080C8BA053D}
[Configurations\HTML\{D3A588E0-9472-11D3-BDD1-0080C8BA053D}\AdditionalFiles]
Count=4
File0=C:\Program Files\Doc-O-Matic 6 Express\graphics\footer-bkg-whitegradient.gif
File1=C:\Program Files\Doc-O-Matic 6 Express\graphics\header-bkg-whitegradient.gif
File2=C:\Program Files\Doc-O-Matic 6 Express\graphics\html_fullframegradient.gif
File3=C:\Program Files\Doc-O-Matic 6 Express\graphics\html_titlebkg.jpg
[Configurations\HTML\{D3A588E0-9472-11D3-BDD1-0080C8BA053D}\General]
ClearDirectoryBeforeExport=0
HelpKind=0
OutputDir=C:\Documents and Settings\mf75rt\My Documents\Doc-O-Matic\output
TargetBOM=0
TargetCodepage=utf-8
[Configurations\HTML\{D3A588E0-9472-11D3-BDD1-0080C8BA053D}\General Build Options]
ShowDocumentation=1
[Configurations\HTML\{D3A588E0-9472-11D3-BDD1-0080C8BA053D}\HTMLHelp]
CompileFullTextSearchInformation=1
CreateBinaryIndex=1
CreateBinaryTOC=0
CreateCHIFile=0
CreateHelp2FullTextIndex=1
DontIncludeFolders=0
Help2AdditionalXMLData=
Help2Collection=
Help2Compiler=
Help2CompileResult=0
Help2Dexplore=
Help2GenericInfoType=kbRef
Help2ID=
Help2Locale=kbEnglish
Help2Namespace=
Help2PluginNamespace=0
Help2PluginNamespaceName=MS.VSIPCC+
Help2RegisterType=0
Help2UnregisterNamespace=1
HelpCompiler=
HTMLHelp2Filename=
HTMLHelpDisplayFontScaleButton=0
HTMLHelpFilename=
SaveUserPosition=1
SupportEnhancedDecompilation=0
WindowPosition_Bottom=0
WindowPosition_Left=0
WindowPosition_Right=0
WindowPosition_Top=0
[Configurations\HTML\Image Paths]
Count=2
Path0=C:\Program Files\Doc-O-Matic 6 Express\graphics
Path1=C:\Program Files\Doc-O-Matic 6 Express\graphics\en
[Configurations\HTML\Output Options]
ClassHierarchyLayoutOutputDir=C:\Documents and Settings\mf75rt\My Documents\Doc-O-Matic\graphics
[Configurations\HTML\OutputFormat]
ID={D3A588E0-9472-11D3-BDD1-0080C8BA053D}
[General]
Author=Felipe Monteiro de Carvalho
AuthorEmail=
Copyright=Copyright (c) 2008
Summary=Free Pascal Spreadsheet Library
Title=FPSpreadsheet
VersionBuild=0
VersionMajor=1
VersionMinor=0
VersionRelease=0
[Macro Header Files]
Count=0
[Parsing]
AssignedCommentsToFollowingSymbols=1
CommentDistance=0
DocUseTripleSlashOnly=0
HeaderUnderlineCharactersCenter==
HeaderUnderlineCharactersJustify=#
HeaderUnderlineCharactersLeft=-
HeaderUnderlineCharactersRight=~
HeadlineDelimiterChars=*#-
IgnoredTrimLineCount=1
IgnoredTrimLine_0=__________________________________________________
InitOptional=0
InitSequence=@@
ListBulletChars=*+-#
NamespaceOption=2
ParameterDelimiterChars=:-
ParameterDescriptionMode=0
ParametersAllowSpaceAsDelimiter=0
SectionAllowSpaceAsDelimiter=0
SectionDelimiterChars=:*-
SupportJavaDoc=1
SupportJavaDocBackslashTags=0
SupportXMLDoc=0
TabExpandCount=4
TrailerChars=-+~/#
WallCharacters="#$%&'*+-/=@[\]^_`{|}~
[Project File Info]
Version=601
[Section\0]
Count=3
Description=Contains a short summary of the purpose of an object. This text usually contains one or two sentenses.
DisplayName=Summary
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=15
Type=4
Value0=Summary
Value1=Brief
Value2=Short
XMLDocTags=summary
[Section\1]
Count=2
Description=Contains the general description of an object. This text describes the purpose of the item.
DisplayName=Description
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=15
Type=0
Value0=Description
Value1=Long
XMLDocTags=value
[Section\10]
Count=3
Description=Contains text that describes bugs or problems related to the object.
DisplayName=Bugs
EditorName=
JavaDocTags=bug
OutputFind=
OutputReplace=
SectionFlags=15
Type=0
Value0=Bugs
Value1=Known Bugs
Value2=Current Bugs
XMLDocTags=
[Section\11]
Count=2
Description=Contains documentation parts which should only be available to internal team members and not to the general public.
DisplayName=Internal
EditorName=
JavaDocTags=internal
OutputFind=
OutputReplace=
SectionFlags=15
Type=0
Value0=Internal
Value1=Special Info
XMLDocTags=
[Section\12]
Count=1
Description=Contains text that describes which parts of the object are incomplete and need additional work.
DisplayName=Todo
EditorName=
JavaDocTags=todo
OutputFind=
OutputReplace=
SectionFlags=15
Type=0
Value0=TODO
XMLDocTags=
[Section\13]
Count=3
Description=Contains text that describes which exceptions can be raised by a function or method.
DisplayName=Exceptions
EditorName=
JavaDocTags=exception,exceptions,throws,raises
OutputFind=
OutputReplace=
SectionFlags=15
Type=12
Value0=Exceptions
Value1=Throws
Value2=Raises
XMLDocTags=exception
[Section\14]
Count=2
Description=Contains text that describes conditions (for example pre- and postconditions) for a function call.
DisplayName=Conditions
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=15
Type=0
Value0=Conditions
Value1=Preconditions
XMLDocTags=permission
[Section\15]
Count=2
Description=Contains information who the author(s) of a topic are
DisplayName=Author
EditorName=
JavaDocTags=author
OutputFind=
OutputReplace=
SectionFlags=15
Type=0
Value0=Author
Value1=Authors
XMLDocTags=
[Section\16]
Count=1
Description=Contains text which describes the history of the object
DisplayName=History
EditorName=
JavaDocTags=since,history
OutputFind=
OutputReplace=
SectionFlags=15
Type=0
Value0=History
XMLDocTags=
[Section\17]
Count=2
Description=Contains version information of the object.
DisplayName=Version
EditorName=
JavaDocTags=version
OutputFind=
OutputReplace=
SectionFlags=15
Type=0
Value0=Version
Value1=Current Version
XMLDocTags=
[Section\18]
Count=1
Description=Contains the text for the glossary entry of the topic.
DisplayName=Glossary
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=15
Type=7
Value0=Glossary
XMLDocTags=
[Section\19]
Count=3
Description=Contains the text for the description of the implementation source of functions.
DisplayName=Source Description
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=15
Type=9
Value0=Source Description
Value1=Implementation Notes
Value2=Implementation Description
XMLDocTags=
[Section\2]
Count=1
Description=Used for one or more short notes on an object.
DisplayName=Notes
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=15
Type=0
Value0=Note
XMLDocTags=
[Section\20]
Count=4
Description=Like a standard section with the additional possibility to give it an individual name in each topic it is used.
DisplayName=Link List
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=15
Type=10
Value0=Link List
Value1=Membergroups
Value2=Member Groups
Value3=Class Group
XMLDocTags=
[Section\21]
Count=1
Description=Contains the Pascal declaration syntax. It will be generated automatically if it does not exist in a topic.
DisplayName=Pascal
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=9
Type=21
Value0=Pascal Syntax
XMLDocTags=
[Section\22]
Count=1
Description=Contains the C++ declaration syntax. It will be generated automatically if it does not exist in a topic.
DisplayName=C++
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=9
Type=22
Value0=C++ Syntax
XMLDocTags=
[Section\23]
Count=1
Description=Contains the C# declaration syntax. It will be generated automatically if it does not exist in a topic.
DisplayName=C#
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=9
Type=23
Value0=C# Syntax
XMLDocTags=
[Section\24]
Count=1
Description=Contains the Visual Basic declaration syntax. It will be generated automatically if it does not exist in a topic.
DisplayName=Visual Basic
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=9
Type=24
Value0=Visual Basic Syntax
XMLDocTags=
[Section\25]
Count=1
Description=Contains the Java declaration syntax. It will be generated automatically if it does not exist in a topic.
DisplayName=Java
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=9
Type=25
Value0=Java Syntax
XMLDocTags=
[Section\26]
Count=1
Description=Contains the IDL declaration syntax. It will be generated automatically if it does not exist in a topic.
DisplayName=IDL
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=9
Type=26
Value0=IDL Syntax
XMLDocTags=
[Section\27]
Count=1
Description=Contains the JavaScript declaration syntax. It will be generated automatically if it does not exist in a topic.
DisplayName=JavaScript
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=9
Type=27
Value0=JavaScript Syntax
XMLDocTags=
[Section\28]
Count=1
Description=Contains the MATLAB declaration syntax. It will be generated automatically if it does not exist in a topic.
DisplayName=MATLAB
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=9
Type=29
Value0=MATLAB Syntax
XMLDocTags=
[Section\29]
Count=1
Description=Contains the PHP declaration syntax. It will be generated automatically if it does not exist in a topic.
DisplayName=PHP
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=9
Type=30
Value0=PHP Syntax
XMLDocTags=
[Section\3]
Count=1
Description=Used for special remarks on a topic. Contrary to Notes, this text can be fairly long.
DisplayName=Remarks
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=15
Type=0
Value0=Remarks
XMLDocTags=remarks
[Section\30]
Count=0
Description=Automatically filled section that contains a table of members of structs, records, enumerations and unions along with their descriptions.
DisplayName=Members
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=15
Type=13
XMLDocTags=
[Section\31]
Count=0
Description=Automatically filled section that contains navigation listings for class and namespace members and sub-topics.
DisplayName=Navigation
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=15
Type=14
XMLDocTags=
[Section\32]
Count=0
Description=Automatically filled section that contains the body source code for functions and files.
DisplayName=Body Source
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=15
Type=16
XMLDocTags=
[Section\33]
Count=0
Description=Automatically filled section that contains the local class hierarchy for a single class.
DisplayName=Class Hierarchy
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=15
Type=17
XMLDocTags=
[Section\34]
Count=0
Description=Automatically filled section that contains a link to the file in which a symbol is declared.
DisplayName=File
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=15
Type=18
XMLDocTags=
[Section\35]
Count=0
Description=Automatically filled section that contains a list of links to pages with more information about the topic that are maintained by Doc-O-Matic
DisplayName=Links
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=15
Type=19
XMLDocTags=
[Section\36]
Count=0
Description=Automatically filled section that contains the reports assigned to a topic.
DisplayName=Reports
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=15
Type=20
XMLDocTags=
[Section\37]
Count=0
Description=Automatically filled section that contains an overview for overloaded member functions.
DisplayName=Overload List
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=15
Type=28
XMLDocTags=
[Section\38]
Count=1
Description=Contains multiple glossary entries of the topic.
DisplayName=Multi Item Glossary
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=15
Type=12
Value0=Multi Item Glossary
XMLDocTags=
[Section\39]
Count=1
Description=Contains a parameter descriptions for generic types.
DisplayName=Type Parameters
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=15
Type=1
Value0=Type Parameters
XMLDocTags=typeparam
[Section\4]
Count=4
Description=Used for detailed descriptions of each parameter of a global or member function.
DisplayName=Parameters
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=15
Type=1
Value0=Parameters
Value1=Arguments
Value2=Inputs
Value3=Input
XMLDocTags=
[Section\5]
Count=4
Description=Used to generally describe the return value of a global or member function.
DisplayName=Returns
EditorName=
JavaDocTags=return,returns
OutputFind=
OutputReplace=
SectionFlags=15
Type=2
Value0=Returns
Value1=Return Value
Value2=Result
Value3=Output
XMLDocTags=returns
[Section\6]
Count=2
Description=Used to describe all possible return values in detail in form of a value-description list.
DisplayName=Return Values
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=15
Type=11
Value0=Return Value List
Value1=Return Value Details
XMLDocTags=
[Section\7]
Count=3
Description=Used for one or more usage examples of the object being described.
DisplayName=Example
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=15
Type=3
Value0=Example
Value1=Examples
Value2=Sample
XMLDocTags=example
[Section\8]
Count=8
Description=All text that appears in this section is ignored.
DisplayName=Ignore
EditorName=
JavaDocTags=beaninfo,component,deprecated,event,exclude,index,obsolete,seealso,serial,serialdata,serialfield,tutorial
OutputFind=
OutputReplace=
SectionFlags=8
Type=6
Value0=Ignore Text
Value1=$Log
Value2=$Filename
Value3=$Revision
Value4=$Date
Value5=$Author
Value6=$History
Value7=$Id
XMLDocTags=
[Section\9]
Count=2
Description=Contains a comma separated list of topic IDs which build the see also list of the topic.
DisplayName=See Also
EditorName=
JavaDocTags=
OutputFind=
OutputReplace=
SectionFlags=15
Type=5
Value0=See Also
Value1=Seealso
XMLDocTags=
[Sections]
Count=40
DefID=1
ID0=0
ID1=1
ID10=10
ID11=11
ID12=12
ID13=13
ID14=14
ID15=15
ID16=16
ID17=17
ID18=18
ID19=19
ID2=2
ID20=20
ID21=21
ID22=22
ID23=23
ID24=24
ID25=25
ID26=26
ID27=27
ID28=28
ID29=29
ID3=3
ID30=30
ID31=31
ID32=32
ID33=33
ID34=34
ID35=35
ID36=36
ID37=37
ID38=38
ID39=39
ID4=4
ID5=5
ID6=6
ID7=7
ID8=8
ID9=9
SavedValues=1
[Source Files]
Count=1
File0=fpspreadsheet.pas
[Source Include Directories]
Count=0

View File

@ -0,0 +1,588 @@
{
fpspreadsheet.pas
Writes an spreadsheet document
AUTHORS: Felipe Monteiro de Carvalho
}
unit fpspreadsheet;
{$ifdef fpc}
{$mode delphi}
{$endif}
interface
uses
Classes, SysUtils;
type
TsSpreadsheetFormat = (sfExcel2, sfExcel3, sfExcel4, sfExcel5, sfExcel8,
sfOOXML, sfOpenDocument, sfCSV);
const
{ Default extensions }
STR_EXCEL_EXTENSION = '.xls';
const
{ TokenID values }
{ Binary Operator Tokens }
INT_EXCEL_TOKEN_TADD = $03;
INT_EXCEL_TOKEN_TSUB = $04;
INT_EXCEL_TOKEN_TMUL = $05;
INT_EXCEL_TOKEN_TDIV = $06;
INT_EXCEL_TOKEN_TPOWER = $07;
{ Constant Operand Tokens }
INT_EXCEL_TOKEN_TNUM = $1F;
{ Operand Tokens }
INT_EXCEL_TOKEN_TREFR = $24;
INT_EXCEL_TOKEN_TREFV = $44;
INT_EXCEL_TOKEN_TREFA = $64;
type
{@@ A Token of a RPN Token array for formulas }
TRPNToken = record
TokenID: Byte;
Col: Byte;
Row: Word;
DoubleValue: double;
end;
{@@ RPN Token array for formulas }
TRPNFormula = array of TRPNToken;
{@@ Describes the type of content of a cell on a TsWorksheet }
TCellContentType = (cctFormula, cctNumber, cctString, cctWideString);
{@@ Cell structure for TsWorksheet }
TCell = record
Row, Col: Cardinal;
ContentType: TCellContentType;
FormulaValue: TRPNFormula;
NumberValue: double;
StringValue: string;
WideStringValue: widestring;
end;
PCell = ^TCell;
type
TsCustomSpreadWriter = class;
{@@ TsWorksheet }
TsWorksheet = class
private
procedure RemoveCallback(data, arg: pointer);
public
FCells: TFPList;
Name: string;
{ Base methods }
constructor Create;
destructor Destroy; override;
{ Data manipulation methods }
function FindCell(ARow, ACol: Cardinal): PCell;
function GetCell(ARow, ACol: Cardinal): PCell;
procedure RemoveAllCells;
procedure WriteAnsiText(ARow, ACol: Cardinal; AText: ansistring);
procedure WriteNumber(ARow, ACol: Cardinal; ANumber: double);
procedure WriteRPNFormula(ARow, ACol: Cardinal; AFormula: TRPNFormula);
end;
{@@ TsWorkbook }
TsWorkbook = class
private
FWorksheets: TFPList;
procedure RemoveCallback(data, arg: pointer);
public
{ Base methods }
constructor Create;
destructor Destroy; override;
function CreateSpreadWriter(AFormat: TsSpreadsheetFormat): TsCustomSpreadWriter;
procedure WriteToFile(AFileName: string; AFormat: TsSpreadsheetFormat);
procedure WriteToStream(AStream: TStream; AFormat: TsSpreadsheetFormat);
{ Worksheet list handling methods }
function AddWorksheet(AName: string): TsWorksheet;
function GetFirstWorksheet: TsWorksheet;
function GetWorksheetByIndex(AIndex: Cardinal): TsWorksheet;
function GetWorksheetCount: Cardinal;
procedure RemoveAllWorksheets;
end;
{@@ TsSpreadReader class reference type }
TsSpreadReaderClass = class of TsCustomSpreadReader;
{@@ TsCustomSpreadReader }
TsCustomSpreadReader = class
protected
FWorkbook: TsWorkbook;
FCurrentWorksheet: TsWorksheet;
public
{ General writing methods }
procedure ReadFromFile(AFileName: string; AData: TsWorkbook); virtual;
procedure ReadFromStream(AStream: TStream; AData: TsWorkbook); virtual; abstract;
{ Record reading methods }
procedure ReadFormula(AStream: TStream); virtual; abstract;
procedure ReadLabel(AStream: TStream); virtual; abstract;
procedure ReadNumber(AStream: TStream); virtual; abstract;
end;
{@@ TsSpreadWriter class reference type }
TsSpreadWriterClass = class of TsCustomSpreadWriter;
{@@ TsCustomSpreadWriter }
TsCustomSpreadWriter = class
public
{ General writing methods }
procedure WriteCellCallback(data, arg: pointer);
procedure WriteCellsToStream(AStream: TStream; ACells: TFPList);
procedure WriteToFile(AFileName: string; AData: TsWorkbook); virtual;
procedure WriteToStream(AStream: TStream; AData: TsWorkbook); virtual; abstract;
{ Record writing methods }
procedure WriteFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TRPNFormula); virtual; abstract;
procedure WriteLabel(AStream: TStream; const ARow, ACol: Word; const AValue: string); virtual; abstract;
procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal; const AValue: double); virtual; abstract;
end;
{@@ List of registered formats }
TsSpreadFormatData = record
ReaderClass: TsSpreadReaderClass;
WriterClass: TsSpreadWriterClass;
Format: TsSpreadsheetFormat;
end;
var
GsSpreadFormats: array of TsSpreadFormatData;
procedure RegisterSpreadFormat(
AReaderClass: TsSpreadReaderClass;
AWriterClass: TsSpreadWriterClass;
AFormat: TsSpreadsheetFormat);
implementation
{@@
Registers a new reader/writer pair for a format
}
procedure RegisterSpreadFormat(
AReaderClass: TsSpreadReaderClass;
AWriterClass: TsSpreadWriterClass;
AFormat: TsSpreadsheetFormat);
var
len: Integer;
begin
len := Length(GsSpreadFormats);
SetLength(GsSpreadFormats, len + 1);
GsSpreadFormats[len].ReaderClass := AReaderClass;
GsSpreadFormats[len].WriterClass := AWriterClass;
GsSpreadFormats[len].Format := AFormat;
end;
{ TsWorksheet }
{@@
Helper method for clearing the records in a spreadsheet.
}
procedure TsWorksheet.RemoveCallback(data, arg: pointer);
begin
FreeMem(data);
end;
{@@
Constructor.
}
constructor TsWorksheet.Create;
begin
inherited Create;
FCells := TFPList.Create;
end;
{@@
Destructor.
}
destructor TsWorksheet.Destroy;
begin
RemoveAllCells;
FCells.Free;
inherited Destroy;
end;
{@@
Tryes to locate a Cell in the list of already
written Cells
@param ARow The row of the cell
@param ACol The column of the cell
@return Nil if no existing cell was found,
otherwise a pointer to the desired Cell
@see TCell
}
function TsWorksheet.FindCell(ARow, ACol: Cardinal): PCell;
var
i: Integer;
ACell: PCell;
begin
i := 0;
Result := nil;
while (i < FCells.Count) do
begin
ACell := PCell(FCells.Items[i]);
if (ACell^.Row = ARow) and (ACell^.Col = ACol) then
begin
Result := ACell;
Exit;
end;
Inc(i);
end;
end;
{@@
Obtains an allocated cell at the desired location.
If the Cell already exists, a pointer to it will
be returned.
If not, then new memory for the cell will be allocated,
a pointer to it will be returned and it will be added
to the list of Cells.
@param ARow The row of the cell
@param ACol The column of the cell
@return A pointer to the Cell on the desired location.
@see TCell
}
function TsWorksheet.GetCell(ARow, ACol: Cardinal): PCell;
begin
Result := FindCell(ARow, ACol);
if (Result = nil) then
begin
Result := GetMem(SizeOf(TCell));
FillChar(Result^, SizeOf(TCell), #0);
Result^.Row := ARow;
Result^.Col := ACol;
FCells.Add(Result);
end;
end;
{@@
Clears the list of Cells and releases their memory.
}
procedure TsWorksheet.RemoveAllCells;
begin
FCells.ForEachCall(RemoveCallback, nil);
end;
{@@
Writes ansi text to a determined cell.
The text must be encoded on the system default encoding.
On formats the support unicode the text will be converted to the unicode
encoding that the format supports.
@param ARow The row of the cell
@param ACol The column of the cell
@param AText The text to be written encoded with the system encoding
}
procedure TsWorksheet.WriteAnsiText(ARow, ACol: Cardinal; AText: ansistring);
var
ACell: PCell;
begin
ACell := GetCell(ARow, ACol);
ACell^.ContentType := cctString;
ACell^.StringValue := AText;
end;
{@@
Writes a floating-point number to a determined cell
@param ARow The row of the cell
@param ACol The column of the cell
@param ANumber The number to be written
}
procedure TsWorksheet.WriteNumber(ARow, ACol: Cardinal; ANumber: double);
var
ACell: PCell;
begin
ACell := GetCell(ARow, ACol);
ACell^.ContentType := cctNumber;
ACell^.NumberValue := ANumber;
end;
{@@
Writes a formula to a determined cell
@param ARow The row of the cell
@param ACol The column of the cell
@param AFormula The formula in RPN array format
}
procedure TsWorksheet.WriteRPNFormula(ARow, ACol: Cardinal; AFormula: TRPNFormula);
var
ACell: PCell;
begin
ACell := GetCell(ARow, ACol);
ACell^.ContentType := cctFormula;
ACell^.FormulaValue := AFormula;
end;
{ TsWorkbook }
{@@
Helper method for clearing the spreadsheet list.
}
procedure TsWorkbook.RemoveCallback(data, arg: pointer);
begin
TsWorksheet(data).Free;
end;
{@@
Constructor.
}
constructor TsWorkbook.Create;
begin
inherited Create;
FWorksheets := TFPList.Create;
end;
{@@
Destructor.
}
destructor TsWorkbook.Destroy;
begin
RemoveAllWorksheets;
FWorksheets.Free;
inherited Destroy;
end;
{@@
Convenience method which creates the correct
writer object for a given spreadsheet format.
}
function TsWorkbook.CreateSpreadWriter(AFormat: TsSpreadsheetFormat): TsCustomSpreadWriter;
var
i: Integer;
begin
Result := nil;
for i := 0 to Length(GsSpreadFormats) - 1 do
if GsSpreadFormats[i].Format = AFormat then
begin
Result := GsSpreadFormats[i].WriterClass.Create;
Break;
end;
if Result = nil then raise Exception.Create('Unsuported spreadsheet format.');
end;
{@@
Writes the document to a file.
If the file doesn't exist, it will be created.
}
procedure TsWorkbook.WriteToFile(AFileName: string; AFormat: TsSpreadsheetFormat);
var
AWriter: TsCustomSpreadWriter;
begin
AWriter := CreateSpreadWriter(AFormat);
try
AWriter.WriteToFile(AFileName, Self);
finally
AWriter.Free;
end;
end;
{@@
Writes the document to a stream
}
procedure TsWorkbook.WriteToStream(AStream: TStream; AFormat: TsSpreadsheetFormat);
var
AWriter: TsCustomSpreadWriter;
begin
AWriter := CreateSpreadWriter(AFormat);
try
AWriter.WriteToStream(AStream, Self);
finally
AWriter.Free;
end;
end;
{@@
Adds a new worksheet to the workbook
It is added to the end of the list of worksheets
@param AName The name of the new worksheet
@return The instace of the newly created worksheet
@see TsWorkbook
}
function TsWorkbook.AddWorksheet(AName: string): TsWorksheet;
begin
Result := TsWorksheet.Create;
Result.Name := AName;
FWorksheets.Add(Pointer(Result));
end;
{@@
Quick helper routine which returns the first worksheet
@return A TsWorksheet instance if at least one is present.
nil otherwise.
@see TsWorkbook.GetWorksheetByIndex
@see TsWorksheet
}
function TsWorkbook.GetFirstWorksheet: TsWorksheet;
begin
Result := TsWorksheet(FWorksheets.First);
end;
{@@
Gets the worksheet with a given index
The index is zero-based, so the first worksheet
added has index 0, the second 1, etc.
@param AIndex The index of the worksheet (0-based)
@return A TsWorksheet instance if one is present at that index.
nil otherwise.
@see TsWorkbook.GetFirstWorksheet
@see TsWorksheet
}
function TsWorkbook.GetWorksheetByIndex(AIndex: Cardinal): TsWorksheet;
begin
Result := TsWorksheet(FWorksheets.Items[AIndex]);
end;
{@@
The number of worksheets on the workbook
@see TsWorksheet
}
function TsWorkbook.GetWorksheetCount: Cardinal;
begin
Result := FWorksheets.Count;
end;
{@@
Clears the list of Worksheets and releases their memory.
}
procedure TsWorkbook.RemoveAllWorksheets;
begin
FWorksheets.ForEachCall(RemoveCallback, nil);
end;
{ TsCustomSpreadReader }
procedure TsCustomSpreadReader.ReadFromFile(AFileName: string; AData: TsWorkbook);
begin
end;
{ TsCustomSpreadWriter }
{@@
Helper function for the spreadsheet writers.
@see TsCustomSpreadWriter.WriteCellsToStream
}
procedure TsCustomSpreadWriter.WriteCellCallback(data, arg: pointer);
var
ACell: PCell;
AStream: TStream;
begin
ACell := PCell(data);
AStream := TStream(arg);
case ACell.ContentType of
cctFormula: WriteFormula(AStream, ACell^.Row, ACell^.Col, ACell^.FormulaValue);
cctNumber: WriteNumber(AStream, ACell^.Row, ACell^.Col, ACell^.NumberValue);
cctString: WriteLabel(AStream, ACell^.Row, ACell^.Col, ACell^.StringValue);
end;
end;
{@@
Helper function for the spreadsheet writers.
Iterates all cells on a list, calling the appropriate write method for them.
@param AStream The output stream.
@param ACells List of cells to be writeen
}
procedure TsCustomSpreadWriter.WriteCellsToStream(AStream: TStream; ACells: TFPList);
begin
ACells.ForEachCall(WriteCellCallback, Pointer(AStream));
end;
{@@
Default file writting method.
Opens the file and calls WriteToStream
@param AFileName The output file name.
If the file already exists it will be replaced.
@param AData The Workbook to be saved.
@see TsWorkbook
}
procedure TsCustomSpreadWriter.WriteToFile(AFileName: string; AData: TsWorkbook);
var
OutputFile: TFileStream;
begin
OutputFile := TFileStream.Create(AFileName, fmCreate or fmOpenWrite);
try
WriteToStream(OutputFile, AData);
finally
OutputFile.Free;
end;
end;
finalization
SetLength(GsSpreadFormats, 0);
end.

View File

@ -0,0 +1,305 @@
{
xlsbiff2.pas
Writes an Excel 2.x file
Excel 2.x files support only one Worksheet per Workbook, so only the first
will be written.
An Excel file consists of a number of subsequent records.
To ensure a properly formed file, the following order must be respected:
1st record: BOF
2nd to Nth record: Any record
Last record: EOF
Excel file format specification obtained from:
http://sc.openoffice.org/excelfileformat.pdf
AUTHORS: Felipe Monteiro de Carvalho
}
unit xlsbiff2;
{$ifdef fpc}
{$mode delphi}
{$endif}
interface
uses
Classes, SysUtils,
fpspreadsheet;
type
{ TsSpreadBIFF2Writer }
TsSpreadBIFF2Writer = class(TsCustomSpreadWriter)
public
{ General writing methods }
procedure WriteToStream(AStream: TStream; AData: TsWorkbook); override;
{ Record writing methods }
procedure WriteBOF(AStream: TStream);
procedure WriteEOF(AStream: TStream);
procedure WriteFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TRPNFormula); override;
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
{ Excel record IDs }
INT_EXCEL_ID_NUMBER = $0003;
INT_EXCEL_ID_LABEL = $0004;
INT_EXCEL_ID_FORMULA = $0006;
INT_EXCEL_ID_BOF = $0009;
INT_EXCEL_ID_EOF = $000A;
{ Cell Addresses constants }
MASK_EXCEL_ROW = $3FFF;
MASK_EXCEL_RELATIVE_ROW = $4000;
MASK_EXCEL_RELATIVE_COL = $8000;
{ BOF record constants }
INT_EXCEL_SHEET = $0010;
INT_EXCEL_CHART = $0020;
INT_EXCEL_MACRO_SHEET = $0040;
{
Endianess helper functions
Excel files are all written with Little Endian byte order,
so it's necessary to swap the data to be able to build a
correct file on big endian systems.
}
function WordToLE(AValue: Word): Word;
begin
{$IFDEF BIG_ENDIAN}
Result := ((AValue shl 8) and $FF00) or ((AValue shr 8) and $00FF);
{$ELSE}
Result := AValue;
{$ENDIF}
end;
{ TsSpreadBIFF2Writer }
{*******************************************************************
* TsSpreadBIFF2Writer.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 TsSpreadBIFF2Writer.WriteToStream(AStream: TStream; AData: TsWorkbook);
begin
WriteBOF(AStream);
WriteCellsToStream(AStream, AData.GetFirstWorksheet.FCells);
WriteEOF(AStream);
end;
{*******************************************************************
* TsSpreadBIFF2Writer.WriteBOF ()
*
* DESCRIPTION: Writes an Excel 2 BOF record
*
* This must be the first record on an Excel 2 stream
*
*******************************************************************}
procedure TsSpreadBIFF2Writer.WriteBOF(AStream: TStream);
begin
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_BOF));
AStream.WriteWord(WordToLE($0004));
{ Unused }
AStream.WriteWord($0000);
{ Data type }
AStream.WriteWord(WordToLE(INT_EXCEL_SHEET));
end;
{*******************************************************************
* TsSpreadBIFF2Writer.WriteEOF ()
*
* DESCRIPTION: Writes an Excel 2 EOF record
*
* This must be the last record on an Excel 2 stream
*
*******************************************************************}
procedure TsSpreadBIFF2Writer.WriteEOF(AStream: TStream);
begin
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_EOF));
AStream.WriteWord($0000);
end;
{*******************************************************************
* TsSpreadBIFF2Writer.WriteFormula ()
*
* DESCRIPTION: Writes an Excel 2 FORMULA record
*
* To input a formula to this method, first convert it
* to RPN, and then list all it's members in the
* AFormula array
*
*******************************************************************}
procedure TsSpreadBIFF2Writer.WriteFormula(AStream: TStream; const ARow,
ACol: Word; const AFormula: TRPNFormula);
var
FormulaResult: double;
i: Integer;
RPNLength: Word;
TokenArraySizePos, RecordSizePos, FinalPos: Cardinal;
begin
RPNLength := 0;
FormulaResult := 0.0;
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_FORMULA));
RecordSizePos := AStream.Position;
AStream.WriteWord(WordToLE(17 + RPNLength));
{ BIFF Record data }
AStream.WriteWord(WordToLE(ARow));
AStream.WriteWord(WordToLE(ACol));
{ BIFF2 Attributes }
AStream.WriteByte($0);
AStream.WriteByte($0);
AStream.WriteByte($0);
{ Result of the formula in IEE 754 floating-point value }
AStream.WriteBuffer(FormulaResult, 8);
{ 0 = Do not recalculate
1 = Always recalculate }
AStream.WriteByte($1);
{ Formula }
{ The size of the token array is written later,
because it's necessary to calculate if first,
and this is done at the same time it is written }
TokenArraySizePos := AStream.Position;
AStream.WriteByte(RPNLength);
{ Formula data (RPN token array) }
for i := 0 to Length(AFormula) - 1 do
begin
{ Token identifier }
AStream.WriteByte(AFormula[i].TokenID);
Inc(RPNLength);
{ Additional data }
case AFormula[i].TokenID of
{ binary operation tokens }
INT_EXCEL_TOKEN_TADD, INT_EXCEL_TOKEN_TSUB, INT_EXCEL_TOKEN_TMUL,
INT_EXCEL_TOKEN_TDIV, INT_EXCEL_TOKEN_TPOWER: begin end;
INT_EXCEL_TOKEN_TNUM:
begin
AStream.WriteBuffer(AFormula[i].DoubleValue, 8);
Inc(RPNLength, 8);
end;
INT_EXCEL_TOKEN_TREFR, INT_EXCEL_TOKEN_TREFV, INT_EXCEL_TOKEN_TREFA:
begin
AStream.WriteWord(AFormula[i].Row and MASK_EXCEL_ROW);
AStream.WriteByte(AFormula[i].Col);
Inc(RPNLength, 3);
end;
end;
end;
{ Write sizes in the end, after we known them }
FinalPos := AStream.Position;
AStream.position := TokenArraySizePos;
AStream.WriteByte(RPNLength);
AStream.Position := RecordSizePos;
AStream.WriteWord(WordToLE(17 + RPNLength));
AStream.position := FinalPos;
end;
{*******************************************************************
* TsSpreadBIFF2Writer.WriteLabel ()
*
* DESCRIPTION: Writes an Excel 2 LABEL record
*
* Writes a string to the sheet
*
*******************************************************************}
procedure TsSpreadBIFF2Writer.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;
{*******************************************************************
* TsSpreadBIFF2Writer.WriteNumber ()
*
* DESCRIPTION: Writes an Excel 2 NUMBER record
*
* Writes a number (64-bit IEE 754 floating point) to the sheet
*
*******************************************************************}
procedure TsSpreadBIFF2Writer.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, TsSpreadBIFF2Writer, sfExcel2);
end.

View File

@ -0,0 +1,879 @@
{
xlsbiff5.pas
Writes an Excel 5 file
An Excel worksheet stream consists of a number of subsequent records.
To ensure a properly formed file, the following order must be respected:
1st record: BOF
2nd to Nth record: Any record
Last record: EOF
Excel 5 files are OLE compound document files, and must be written using the
fpOLE library.
Records Needed to Make a BIFF5 File Microsoft Excel Can Use:
Required Records:
BOF - Set the 6 byte offset to 0x0005 (workbook globals)
Window1
FONT - At least five of these records must be included
XF - At least 15 Style XF records and 1 Cell XF record must be included
STYLE
BOUNDSHEET - Include one BOUNDSHEET record per worksheet
EOF
BOF - Set the 6 byte offset to 0x0010 (worksheet)
INDEX
DIMENSIONS
WINDOW2
EOF
Excel file format specification obtained from:
http://sc.openoffice.org/excelfileformat.pdf
Records Needed to Make a BIFF5 File Microsoft Excel Can Use obtained from:
http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q147732&ID=KB;EN-US;Q147732&LN=EN-US&rnk=2&SD=msdn&FR=0&qry=BIFF&src=DHCS_MSPSS_msdn_SRCH&SPR=MSALL&
Microsoft BIFF 5 writer example:
http://support.microsoft.com/kb/150447/en-us
AUTHORS: Felipe Monteiro de Carvalho
}
unit xlsbiff5;
{$ifdef fpc}
{$mode delphi}
{$endif}
interface
uses
Classes, SysUtils, fpcanvas,
fpspreadsheet, fpolestorage;
type
{ TsSpreadBIFF5Writer }
TsSpreadBIFF5Writer = class(TsCustomSpreadWriter)
public
// constructor Create;
// destructor Destroy; override;
{ General writing methods }
procedure WriteToFile(AFileName: string; AData: TsWorkbook); override;
procedure WriteToStream(AStream: TStream; AData: TsWorkbook); override;
{ Record writing methods }
procedure WriteBOF(AStream: TStream; ADataType: Word);
function WriteBoundsheet(AStream: TStream; ASheetName: string): Int64;
procedure WriteDimensions(AStream: TStream);
procedure WriteEOF(AStream: TStream);
procedure WriteFont(AStream: TStream; AFont: TFPCustomFont);
procedure WriteFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TRPNFormula); override;
procedure WriteIndex(AStream: TStream);
procedure WriteLabel(AStream: TStream; const ARow, ACol: Word; const AValue: string); override;
procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal; const AValue: double); override;
procedure WriteStyle(AStream: TStream);
procedure WriteWindow1(AStream: TStream);
procedure WriteWindow2(AStream: TStream; ASheetSelected: Boolean);
procedure WriteXF(AStream: TStream; AFontIndex: Word; AXF_TYPE_PROT: Byte);
end;
implementation
const
{ Excel record IDs }
INT_EXCEL_ID_BOF = $0809;
INT_EXCEL_ID_BOUNDSHEET = $0085;
INT_EXCEL_ID_EOF = $000A;
INT_EXCEL_ID_DIMENSIONS = $0200;
INT_EXCEL_ID_FONT = $0031;
INT_EXCEL_ID_FORMULA = $0006;
INT_EXCEL_ID_INDEX = $020B;
INT_EXCEL_ID_LABEL = $0204;
INT_EXCEL_ID_NUMBER = $0203;
INT_EXCEL_ID_STYLE = $0293;
INT_EXCEL_ID_WINDOW1 = $003D;
INT_EXCEL_ID_WINDOW2 = $023E;
INT_EXCEL_ID_XF = $00E0;
{ Cell Addresses constants }
MASK_EXCEL_ROW = $3FFF;
MASK_EXCEL_RELATIVE_ROW = $4000;
MASK_EXCEL_RELATIVE_COL = $8000;
{ BOF record constants }
INT_BOF_BIFF5_VER = $0500;
INT_BOF_WORKBOOK_GLOBALS= $0005;
INT_BOF_VB_MODULE = $0006;
INT_BOF_SHEET = $0010;
INT_BOF_CHART = $0020;
INT_BOF_MACRO_SHEET = $0040;
INT_BOF_WORKSPACE = $0100;
INT_BOF_BUILD_ID = $1FD2;
INT_BOF_BUILD_YEAR = $07CD;
{ FONT record constants }
INT_FONT_WEIGHT_NORMAL = $0190;
{ FORMULA record constants }
MASK_FORMULA_RECALCULATE_ALWAYS = $0001;
MASK_FORMULA_RECALCULATE_ON_OPEN = $0002;
MASK_FORMULA_SHARED_FORMULA = $0008;
{ STYLE record constants }
MASK_STYLE_BUILT_IN = $8000;
{ WINDOW1 record constants }
MASK_WINDOW1_OPTION_WINDOW_HIDDEN = $0001;
MASK_WINDOW1_OPTION_WINDOW_MINIMISED = $0002;
MASK_WINDOW1_OPTION_HORZ_SCROLL_VISIBLE = $0008;
MASK_WINDOW1_OPTION_VERT_SCROLL_VISIBLE = $0010;
MASK_WINDOW1_OPTION_WORKSHEET_TAB_VISIBLE = $0020;
{ WINDOW2 record constants }
MASK_WINDOW2_OPTION_SHOW_FORMULAS = $0001;
MASK_WINDOW2_OPTION_SHOW_GRID_LINES = $0002;
MASK_WINDOW2_OPTION_SHOW_SHEET_HEADERS = $0004;
MASK_WINDOW2_OPTION_PANES_ARE_FROZEN = $0008;
MASK_WINDOW2_OPTION_SHOW_ZERO_VALUES = $0010;
MASK_WINDOW2_OPTION_AUTO_GRIDLINE_COLOR = $0020;
MASK_WINDOW2_OPTION_COLUMNS_RIGHT_TO_LEFT = $0040;
MASK_WINDOW2_OPTION_SHOW_OUTLINE_SYMBOLS = $0080;
MASK_WINDOW2_OPTION_REMOVE_SPLITS_ON_UNFREEZE = $0100;
MASK_WINDOW2_OPTION_SHEET_SELECTED = $0200;
MASK_WINDOW2_OPTION_SHEET_ACTIVE = $0400;
{ XF substructures }
{ XF_TYPE_PROT - XF Type and Cell protection (3 Bits) - BIFF3-BIFF8 }
MASK_XF_TYPE_PROT_LOCKED = $1;
MASK_XF_TYPE_PROT_FORMULA_HIDDEN = $2;
MASK_XF_TYPE_PROT_STYLE_XF = $4; // 0 = CELL XF
{ XF_USED_ATTRIB - Attributes from parent Style XF (6 Bits) - BIFF3-BIFF8
In a CELL XF a cleared bit means that the parent attribute is used,
while a set bit indicates that the data in this XF is used
In a STYLE XF a cleared bit means that the data in this XF is used,
while a set bit indicates that the attribute should be ignored }
MASK_XF_USED_ATTRIB_NUMBER_FORMAT = $04;
MASK_XF_USED_ATTRIB_FONT = $08;
MASK_XF_USED_ATTRIB_TEXT = $10;
MASK_XF_USED_ATTRIB_BORDER_LINES = $20;
MASK_XF_USED_ATTRIB_BACKGROUND = $40;
MASK_XF_USED_ATTRIB_CELL_PROTECTION = $80;
{ XF_VERT_ALIGN }
MASK_XF_VERT_ALIGN_TOP = $00;
MASK_XF_VERT_ALIGN_CENTRED = $10;
MASK_XF_VERT_ALIGN_BOTTOM = $20;
MASK_XF_VERT_ALIGN_JUSTIFIED = $30;
{ XF record constants }
MASK_XF_TYPE_PROT = $0007;
MASK_XF_TYPE_PROT_PARENT = $FFF0;
MASK_XF_VERT_ALIGN = $70;
{
Endianess helper functions
Excel files are all written with Little Endian byte order,
so it's necessary to swap the data to be able to build a
correct file on big endian systems.
}
function WordToLE(AValue: Word): Word;
begin
{$IFDEF BIG_ENDIAN}
Result := ((AValue shl 8) and $FF00) or ((AValue shr 8) and $00FF);
{$ELSE}
Result := AValue;
{$ENDIF}
end;
{
Exported functions
}
{ TsSpreadBIFF5Writer }
{*******************************************************************
* TsSpreadBIFF5Writer.WriteToFile ()
*
* DESCRIPTION: Writes an Excel BIFF5 file to the disc
*
* The BIFF 5 writer overrides this method because
* BIFF 5 is written as an OLE document, and our
* current OLE document writing method involves:
*
* 1 - Writing the BIFF data to a memory stream
*
* 2 - Write the memory stream data to disk using
* COM functions
*
*******************************************************************}
procedure TsSpreadBIFF5Writer.WriteToFile(AFileName: string; AData: TsWorkbook);
var
MemStream: TMemoryStream;
OutputStorage: TOLEStorage;
begin
MemStream := TMemoryStream.Create;
OutputStorage := TOLEStorage.Create;
try
WriteToStream(MemStream, AData);
OutputStorage.WriteStreamToOLEFile(AFileName, MemStream);
finally
MemStream.Free;
OutputStorage.Free;
end;
end;
{*******************************************************************
* TsSpreadBIFF5Writer.WriteToStream ()
*
* DESCRIPTION: Writes an Excel BIFF5 record structure
*
* Be careful as this method doesn't write the OLE
* part of the document, just the BIFF records
*
*******************************************************************}
procedure TsSpreadBIFF5Writer.WriteToStream(AStream: TStream; AData: TsWorkbook);
var
FontData: TFPCustomFont;
MyData: TMemoryStream;
CurrentPos: Int64;
Boundsheets: array of Int64;
i, len: Integer;
begin
{ Write workbook globals }
WriteBOF(AStream, INT_BOF_WORKBOOK_GLOBALS);
WriteWindow1(AStream);
FontData := TFPCustomFont.Create;
try
FontData.Name := 'Arial';
// FONT0
WriteFont(AStream, FontData);
// FONT1
WriteFont(AStream, FontData);
// FONT2
WriteFont(AStream, FontData);
// FONT3
WriteFont(AStream, FontData);
// FONT5
WriteFont(AStream, FontData);
finally
FontData.Free;
end;
// XF0
WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF);
// XF1
WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF);
// XF2
WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF);
// XF3
WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF);
// XF4
WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF);
// XF5
WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF);
// XF6
WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF);
// XF7
WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF);
// XF8
WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF);
// XF9
WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF);
// XF10
WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF);
// XF11
WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF);
// XF12
WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF);
// XF13
WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF);
// XF14
WriteXF(AStream, 0, MASK_XF_TYPE_PROT_STYLE_XF);
// XF15
WriteXF(AStream, 0, 0);
WriteStyle(AStream);
for i := 0 to AData.GetWorksheetCount - 1 do
begin
len := Length(Boundsheets);
SetLength(Boundsheets, len + 1);
Boundsheets[len] := WriteBoundsheet(AStream, AData.GetWorksheetByIndex(i).Name);
end;
WriteEOF(AStream);
{ Write each worksheet }
for i := 0 to AData.GetWorksheetCount - 1 do
begin
{ First goes back and writes the position of the BOF of the
sheet on the respective BOUNDSHEET record }
CurrentPos := AStream.Position;
AStream.Position := Boundsheets[i];
AStream.WriteDWord(CurrentPos);
AStream.Position := CurrentPos;
WriteBOF(AStream, INT_BOF_SHEET);
WriteIndex(AStream);
WriteDimensions(AStream);
WriteWindow2(AStream, True);
WriteCellsToStream(AStream, AData.GetWorksheetByIndex(i).FCells);
WriteEOF(AStream);
end;
{ Cleanup }
SetLength(Boundsheets, 0);
end;
{*******************************************************************
* TsSpreadBIFF5Writer.WriteBOF ()
*
* DESCRIPTION: Writes an Excel 5 BOF record
*
* This must be the first record on an Excel 5 stream
*
*******************************************************************}
procedure TsSpreadBIFF5Writer.WriteBOF(AStream: TStream; ADataType: Word);
begin
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_BOF));
AStream.WriteWord(WordToLE(8));
{ BIFF version. Should only be used if this BOF is for the workbook globals }
if ADataType = INT_BOF_WORKBOOK_GLOBALS then
AStream.WriteWord(WordToLE(INT_BOF_BIFF5_VER))
else AStream.WriteWord(0);
{ Data type }
AStream.WriteWord(WordToLE(ADataType));
{ Build identifier, must not be 0 }
AStream.WriteWord(WordToLE(INT_BOF_BUILD_ID));
{ Build year, must not be 0 }
AStream.WriteWord(WordToLE(INT_BOF_BUILD_YEAR));
end;
{*******************************************************************
* TsSpreadBIFF5Writer.WriteBoundsheet ()
*
* DESCRIPTION: Writes an Excel 5 BOUNDSHEET record
*
* Always located on the workbook globals substream.
*
* One BOUNDSHEET is written for each worksheet.
*
* RETURNS: The stream position where the absolute stream position
* of the BOF of this sheet should be written (4 bytes size).
*
*******************************************************************}
function TsSpreadBIFF5Writer.WriteBoundsheet(AStream: TStream; ASheetName: string): Int64;
var
Len: Byte;
begin
Len := Length(ASheetName);
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_BOUNDSHEET));
AStream.WriteWord(WordToLE(6 + 1 + Len));
{ Absolute stream position of the BOF record of the sheet represented
by this record }
Result := AStream.Position;
AStream.WriteDWord(WordToLE(0));
{ Visibility }
AStream.WriteByte(0);
{ Sheet type }
AStream.WriteByte(0);
{ Sheet name: Byte string, 8-bit length }
AStream.WriteByte(Len);
AStream.WriteBuffer(ASheetName[1], Len);
end;
{*******************************************************************
* TsSpreadBIFF5Writer.WriteIndex ()
*
* DESCRIPTION: Writes an Excel 5 DIMENSIONS record
*
* nm = (rl - rf - 1) / 32 + 1 (using integer division)
*
*******************************************************************}
procedure TsSpreadBIFF5Writer.WriteDimensions(AStream: TStream);
begin
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_DIMENSIONS));
AStream.WriteWord(WordToLE(10));
{ Index to first used row }
AStream.WriteWord(0);
{ Index to last used row, increased by 1 }
AStream.WriteWord(33);
{ Index to first used column }
AStream.WriteWord(0);
{ Index to last used column, increased by 1 }
AStream.WriteWord(10);
{ Not used }
AStream.WriteWord(0);
end;
{*******************************************************************
* TsSpreadBIFF5Writer.WriteEOF ()
*
* DESCRIPTION: Writes an Excel 5 EOF record
*
* This must be the last record on an Excel 5 stream
*
*******************************************************************}
procedure TsSpreadBIFF5Writer.WriteEOF(AStream: TStream);
begin
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_EOF));
AStream.WriteWord($0000);
end;
{*******************************************************************
* TsSpreadBIFF5Writer.WriteFont ()
*
* DESCRIPTION: Writes an Excel 5 FONT record
*
* The font data is passed in an instance of TFPCustomFont
*
*******************************************************************}
procedure TsSpreadBIFF5Writer.WriteFont(AStream: TStream; AFont: TFPCustomFont);
var
Len: Byte;
begin
Len := Length(AFont.Name);
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_FONT));
AStream.WriteWord(WordToLE(14 + 1 + Len));
{ Height of the font in twips = 1/20 of a point }
AStream.WriteWord(WordToLE(200));
{ Option flags }
AStream.WriteWord(0);
{ Colour index }
AStream.WriteWord($7FFF);
{ Font weight }
AStream.WriteWord(WordToLE(INT_FONT_WEIGHT_NORMAL));
{ Escapement type }
AStream.WriteWord(0);
{ Underline type }
AStream.WriteByte(0);
{ Font family }
AStream.WriteByte(0);
{ Character set }
AStream.WriteByte(0);
{ Not used }
AStream.WriteByte(0);
{ Font name: Byte string, 8-bit length }
AStream.WriteByte(Len);
AStream.WriteBuffer(AFont.Name[1], Len);
end;
{*******************************************************************
* TsSpreadBIFF5Writer.WriteFormula ()
*
* DESCRIPTION: Writes an Excel 5 FORMULA record
*
* To input a formula to this method, first convert it
* to RPN, and then list all it's members in the
* AFormula array
*
*******************************************************************}
procedure TsSpreadBIFF5Writer.WriteFormula(AStream: TStream; const ARow,
ACol: Word; const AFormula: TRPNFormula);
var
FormulaResult: double;
i: Integer;
RPNLength: Word;
TokenArraySizePos, RecordSizePos, FinalPos: Int64;
begin
RPNLength := 0;
FormulaResult := 0.0;
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_FORMULA));
RecordSizePos := AStream.Position;
AStream.WriteWord(WordToLE(22 + RPNLength));
{ BIFF Record data }
AStream.WriteWord(WordToLE(ARow));
AStream.WriteWord(WordToLE(ACol));
{ Index to XF Record }
AStream.WriteWord($0000);
{ Result of the formula in IEE 754 floating-point value }
AStream.WriteBuffer(FormulaResult, 8);
{ Options flags }
AStream.WriteWord(WordToLE(MASK_FORMULA_RECALCULATE_ALWAYS));
{ Not used }
AStream.WriteDWord(0);
{ Formula }
{ The size of the token array is written later,
because it's necessary to calculate if first,
and this is done at the same time it is written }
TokenArraySizePos := AStream.Position;
AStream.WriteWord(RPNLength);
{ Formula data (RPN token array) }
for i := 0 to Length(AFormula) - 1 do
begin
{ Token identifier }
AStream.WriteByte(AFormula[i].TokenID);
Inc(RPNLength);
{ Additional data }
case AFormula[i].TokenID of
{ binary operation tokens }
INT_EXCEL_TOKEN_TADD, INT_EXCEL_TOKEN_TSUB, INT_EXCEL_TOKEN_TMUL,
INT_EXCEL_TOKEN_TDIV, INT_EXCEL_TOKEN_TPOWER: begin end;
INT_EXCEL_TOKEN_TNUM:
begin
AStream.WriteBuffer(AFormula[i].DoubleValue, 8);
Inc(RPNLength, 8);
end;
INT_EXCEL_TOKEN_TREFR, INT_EXCEL_TOKEN_TREFV, INT_EXCEL_TOKEN_TREFA:
begin
AStream.WriteWord(AFormula[i].Row and MASK_EXCEL_ROW);
AStream.WriteByte(AFormula[i].Col);
Inc(RPNLength, 3);
end;
end;
end;
{ Write sizes in the end, after we known them }
FinalPos := AStream.Position;
AStream.position := TokenArraySizePos;
AStream.WriteByte(RPNLength);
AStream.Position := RecordSizePos;
AStream.WriteWord(WordToLE(22 + RPNLength));
AStream.position := FinalPos;
end;
{*******************************************************************
* TsSpreadBIFF5Writer.WriteIndex ()
*
* DESCRIPTION: Writes an Excel 5 INDEX record
*
* nm = (rl - rf - 1) / 32 + 1 (using integer division)
*
*******************************************************************}
procedure TsSpreadBIFF5Writer.WriteIndex(AStream: TStream);
begin
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_INDEX));
AStream.WriteWord(WordToLE(12));
{ Not used }
AStream.WriteDWord(0);
{ Index to first used row, rf, 0 based }
AStream.WriteWord(0);
{ Index to first row of unused tail of sheet, rl, last used row + 1, 0 based }
AStream.WriteWord(33);
{ Absolute stream position of the DEFCOLWIDTH record of the current sheet.
If it doesn't exist, the offset points to where it would occur. }
AStream.WriteDWord($00);
{ Array of nm absolute stream positions of the DBCELL record of each Row Block }
{ OBS: It seams to be no problem just ignoring this part of the record }
end;
{*******************************************************************
* TsSpreadBIFF5Writer.WriteLabel ()
*
* DESCRIPTION: Writes an Excel 8 LABEL record
*
* Writes a string to the sheet
*
*******************************************************************}
procedure TsSpreadBIFF5Writer.WriteLabel(AStream: TStream; const ARow,
ACol: Word; const AValue: string);
var
L: Word;
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));
{ Index to XF record }
AStream.WriteWord(15);
{ Byte String with 16-bit size }
AStream.WriteWord(L);
AStream.WriteBuffer(AValue[1], L);
end;
{*******************************************************************
* TsSpreadBIFF5Writer.WriteNumber ()
*
* DESCRIPTION: Writes an Excel 5 NUMBER record
*
* Writes a number (64-bit floating point) to the sheet
*
*******************************************************************}
procedure TsSpreadBIFF5Writer.WriteNumber(AStream: TStream; const ARow,
ACol: Cardinal; const AValue: double);
begin
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_NUMBER));
AStream.WriteWord(WordToLE(14));
{ BIFF Record data }
AStream.WriteWord(WordToLE(ARow));
AStream.WriteWord(WordToLE(ACol));
{ Index to XF record }
AStream.WriteWord($0);
{ IEE 754 floating-point value }
AStream.WriteBuffer(AValue, 8);
end;
{*******************************************************************
* TsSpreadBIFF5Writer.WriteStyle ()
*
* DESCRIPTION: Writes an Excel 5 STYLE record
*
* Registers the name of a user-defined style or
* specific options for a built-in cell style.
*
*******************************************************************}
procedure TsSpreadBIFF5Writer.WriteStyle(AStream: TStream);
begin
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_STYLE));
AStream.WriteWord(WordToLE(4));
{ Index to style XF and defines if it's a built-in or used defined style }
AStream.WriteWord(WordToLE(MASK_STYLE_BUILT_IN));
{ Built-in cell style identifier }
AStream.WriteByte($00);
{ Level if the identifier for a built-in style is RowLevel or ColLevel, $FF otherwise }
AStream.WriteByte(WordToLE($FF));
end;
{*******************************************************************
* TsSpreadBIFF5Writer.WriteWindow1 ()
*
* DESCRIPTION: Writes an Excel 5 WINDOW1 record
*
* This record contains general settings for the
* document window and global workbook settings.
*
* The values written here are reasonable defaults,
* which should work for most sheets.
*
*******************************************************************}
procedure TsSpreadBIFF5Writer.WriteWindow1(AStream: TStream);
begin
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_WINDOW1));
AStream.WriteWord(WordToLE(18));
{ Horizontal position of the document window, in twips = 1 / 20 of a point }
AStream.WriteWord(0);
{ Vertical position of the document window, in twips = 1 / 20 of a point }
AStream.WriteWord(WordToLE($0069));
{ Width of the document window, in twips = 1 / 20 of a point }
AStream.WriteWord(WordToLE($339F));
{ Height of the document window, in twips = 1 / 20 of a point }
AStream.WriteWord(WordToLE($1B5D));
{ Option flags }
AStream.WriteWord(WordToLE(
MASK_WINDOW1_OPTION_HORZ_SCROLL_VISIBLE or
MASK_WINDOW1_OPTION_VERT_SCROLL_VISIBLE or
MASK_WINDOW1_OPTION_WORKSHEET_TAB_VISIBLE));
{ Index to active (displayed) worksheet }
AStream.WriteWord($00);
{ Index of first visible tab in the worksheet tab bar }
AStream.WriteWord($00);
{ Number of selected worksheets }
AStream.WriteWord(WordToLE(1));
{ Width of worksheet tab bar (in 1/1000 of window width).
The remaining space is used by the horizontal scroll bar }
AStream.WriteWord(WordToLE(600));
end;
{*******************************************************************
* TsSpreadBIFF5Writer.WriteWindow1 ()
*
* DESCRIPTION: Writes an Excel 5 WINDOW1 record
*
* This record contains aditional settings for the
* document window (BIFF2-BIFF4) or for a specific
* worksheet (BIFF5-BIFF8).
*
* The values written here are reasonable defaults,
* which should work for most sheets.
*
*******************************************************************}
procedure TsSpreadBIFF5Writer.WriteWindow2(AStream: TStream;
ASheetSelected: Boolean);
var
Options: Word;
begin
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_WINDOW2));
AStream.WriteWord(WordToLE(10));
{ Options flags }
Options := MASK_WINDOW2_OPTION_SHOW_GRID_LINES or
MASK_WINDOW2_OPTION_SHOW_SHEET_HEADERS or
MASK_WINDOW2_OPTION_SHOW_ZERO_VALUES or
MASK_WINDOW2_OPTION_AUTO_GRIDLINE_COLOR or
MASK_WINDOW2_OPTION_SHOW_OUTLINE_SYMBOLS or
MASK_WINDOW2_OPTION_SHEET_ACTIVE;
if ASheetSelected then Options := Options or MASK_WINDOW2_OPTION_SHEET_SELECTED;
AStream.WriteWord(WordToLE(Options));
{ Index to first visible row }
AStream.WriteWord(WordToLE(0));
{ Index to first visible column }
AStream.WriteWord(WordToLE(0));
{ Grid line RGB colour }
AStream.WriteDWord(WordToLE(0));
end;
{*******************************************************************
* TsSpreadBIFF5Writer.WriteXF ()
*
* DESCRIPTION: Writes an Excel 5 XF record
*
* Writes a number (64-bit floating point) to the sheet
*
*******************************************************************}
procedure TsSpreadBIFF5Writer.WriteXF(AStream: TStream; AFontIndex: Word;
AXF_TYPE_PROT: Byte);
var
XFOptions: Word;
XFAlignment, XFOrientationAttrib: Byte;
begin
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_XF));
AStream.WriteWord(WordToLE(16));
{ Index to FONT record }
AStream.WriteWord(WordToLE(AFontIndex));
{ Index to FORMAT record }
AStream.WriteWord($00);
{ XF type, cell protection and parent style XF }
XFOptions := AXF_TYPE_PROT and MASK_XF_TYPE_PROT;
if AXF_TYPE_PROT and MASK_XF_TYPE_PROT_STYLE_XF <> 0 then
XFOptions := XFOptions or MASK_XF_TYPE_PROT_PARENT;
AStream.WriteWord(WordToLE(XFOptions));
{ Alignment and text break }
XFAlignment := MASK_XF_VERT_ALIGN_BOTTOM;
AStream.WriteByte(WordToLE(XFAlignment));
{ Text orientation and flags for used attribute groups }
XFOrientationAttrib :=
MASK_XF_USED_ATTRIB_NUMBER_FORMAT or
MASK_XF_USED_ATTRIB_FONT or
MASK_XF_USED_ATTRIB_TEXT or
MASK_XF_USED_ATTRIB_BORDER_LINES or
MASK_XF_USED_ATTRIB_BACKGROUND or
MASK_XF_USED_ATTRIB_CELL_PROTECTION;
AStream.WriteByte(WordToLE(XFOrientationAttrib));
{ Cell border lines and background area }
AStream.WriteDWord($000020C0);
AStream.WriteDWord($00000000);
end;
{*******************************************************************
* Initialization section
*
* Registers this reader / writer on fpSpreadsheet
*
*******************************************************************}
initialization
RegisterSpreadFormat(TsCustomSpreadReader, TsSpreadBIFF5Writer, sfExcel5);
end.

View File

@ -0,0 +1,430 @@
{
xlsbiff5.pas
Writes an Excel 5 file
An Excel worksheet stream consists of a number of subsequent records.
To ensure a properly formed file, the following order must be respected:
1st record: BOF
2nd to Nth record: Any record
Last record: EOF
Excel 5 files are OLE compound document files, and must be written using the
fpOLE library.
Records Needed to Make a BIFF5 File Microsoft Excel Can Use:
Required Records:
BOF - Set the 6 byte offset to 0x0005 (workbook globals)
Window1
FONT - At least five of these records must be included
XF - At least 15 Style XF records and 1 Cell XF record must be included
STYLE
BOUNDSHEET - Include one BOUNDSHEET record per worksheet
EOF
BOF - Set the 6 byte offset to 0x0010 (worksheet)
INDEX
DIMENSIONS
WINDOW2
EOF
Excel file format specification obtained from:
http://sc.openoffice.org/excelfileformat.pdf
Records Needed to Make a BIFF5 File Microsoft Excel Can Use obtained from:
http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q147732&ID=KB;EN-US;Q147732&LN=EN-US&rnk=2&SD=msdn&FR=0&qry=BIFF&src=DHCS_MSPSS_msdn_SRCH&SPR=MSALL&
AUTHORS: Felipe Monteiro de Carvalho
}
unit xlsbiff8;
{$ifdef fpc}
{$mode delphi}{$H+}
{$endif}
interface
uses
Classes, SysUtils,
fpspreadsheet;
type
{ TsSpreadBIFF5Writer }
TsSpreadBIFF5Writer = class(TsCustomSpreadWriter)
public
{ General writing methods }
procedure WriteToStream(AStream: TStream; AData: TsWorkbook); override;
{ Record writing methods }
procedure WriteBOF(AStream: TStream);
procedure WriteEOF(AStream: TStream);
procedure WriteFont(AStream: TStream; AFontName: Widestring = 'Arial');
procedure WriteFormat(AStream: TStream; AIndex: Word = 0; AFormatString: Widestring = 'General');
procedure WriteFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TRPNFormula); override;
procedure WriteLabel(AStream: TStream; const ARow, ACol: Word; const AValue: string); override;
procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal; const AValue: double); override;
procedure WriteXF(AStream: TStream);
end;
implementation
const
{ Excel record IDs }
INT_EXCEL_ID_BOF = $0809;
INT_EXCEL_ID_EOF = $000A;
INT_EXCEL_ID_FONT = $0031;
INT_EXCEL_ID_FORMAT = $041E;
INT_EXCEL_ID_FORMULA = $0006;
INT_EXCEL_ID_LABEL = $0004;
INT_EXCEL_ID_NUMBER = $0203;
INT_EXCEL_ID_XF = $00E0;
{ Cell Addresses constants }
MASK_EXCEL_ROW = $3FFF;
MASK_EXCEL_RELATIVE_ROW = $4000;
MASK_EXCEL_RELATIVE_COL = $8000;
{ Unicode string constants }
INT_EXCEL_UNCOMPRESSED_STRING = $01;
{ BOF record constants }
INT_EXCEL_BIFF8_VER = $0600;
INT_EXCEL_WORKBOOK = $0005;
INT_EXCEL_SHEET = $0010;
INT_EXCEL_CHART = $0020;
INT_EXCEL_MACRO_SHEET = $0040;
INT_EXCEL_BUILD_ID = $1FD2;
INT_EXCEL_BUILD_YEAR = $07CD;
INT_EXCEL_FILE_HISTORY = $0000C0C1;
INT_EXCEL_LOWEST_VER = $00000306;
{ FONT record constants}
INT_EXCEL_FONTWEIGHT_NORMAL = $0190;
{ XF record constants }
INT_EXCEL_XF_TYPE_PROT_STYLEXF = $FFF4;
{
Excel files are all written with Little Endian number,
so it's necessary to swap the numbers to be able to build a
correct file on big endian systems.
Endianess helper functions
}
function WordToLE(AValue: Word): Word;
begin
{$IFDEF BIG_ENDIAN}
Result := ((AValue shl 8) and $FF00) or ((AValue shr 8) and $00FF);
{$ELSE}
Result := AValue;
{$ENDIF}
end;
{
Exported functions
}
{ TsSpreadBIFF5Writer }
procedure TsSpreadBIFF5Writer.WriteToStream(AStream: TStream; AData: TsWorkbook);
begin
end;
{*******************************************************************
* TsSpreadBIFF5Writer.WriteBOF ()
*
* DESCRIPTION: Writes an Excel 5 BOF record
*
* This must be the first record on an Excel 5 stream
*
*******************************************************************}
procedure TsSpreadBIFF5Writer.WriteBOF(AStream: TStream);
begin
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_BOF));
AStream.WriteWord(WordToLE(16));
{ BIFF version }
AStream.WriteWord(WordToLE(INT_EXCEL_BIFF8_VER));
{ Data type }
AStream.WriteWord(WordToLE(INT_EXCEL_WORKBOOK));
{ Build identifier, must not be 0 }
AStream.WriteWord(WordToLE(INT_EXCEL_BUILD_ID));
{ Build year, must not be 0 }
AStream.WriteWord(WordToLE(INT_EXCEL_BUILD_YEAR));
{ File history flags }
// AStream.WriteDWord($00000000);
AStream.WriteWord(WordToLE(INT_EXCEL_FILE_HISTORY));
{ Lowest Excel version that can read all records of this file }
// AStream.WriteDWord($00000000);
AStream.WriteWord(WordToLE(INT_EXCEL_LOWEST_VER));
end;
{*******************************************************************
* TsSpreadBIFF5Writer.WriteEOF ()
*
* DESCRIPTION: Writes an Excel 5 EOF record
*
* This must be the last record on an Excel 5 stream
*
*******************************************************************}
procedure TsSpreadBIFF5Writer.WriteEOF(AStream: TStream);
begin
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_EOF));
AStream.WriteWord($0000);
end;
procedure TsSpreadBIFF5Writer.WriteFont(AStream: TStream;
AFontName: Widestring);
var
Len: Byte;
begin
Len := Length(AFontName);
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_FONT));
AStream.WriteWord(WordToLE(14 + 2 + Len*2));
{ Height of the font in twips = 1/20 of a point }
AStream.WriteWord(WordToLE(200));
{ Option flags }
AStream.WriteWord(0);
{ Colour index }
AStream.WriteWord(0);
{ Font weight }
AStream.WriteWord(WordToLE(INT_EXCEL_FONTWEIGHT_NORMAL));
{ Underline type }
AStream.WriteByte(0);
{ Font family }
AStream.WriteByte(0);
{ Character set }
AStream.WriteByte(0);
{ Not used }
AStream.WriteByte(0);
{ Font name: Unicode string, 8-bit length }
AStream.WriteByte(Len);
AStream.WriteByte(INT_EXCEL_UNCOMPRESSED_STRING);
AStream.WriteBuffer(AFontName[1], Len*2);
end;
procedure TsSpreadBIFF5Writer.WriteFormat(AStream: TStream; AIndex: Word;
AFormatString: Widestring);
var
Len: Integer;
begin
Len := Length(AFormatString);
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_FORMAT));
AStream.WriteWord(WordToLE(2 + 3 + Len*2));
{ Format index used by other records }
AStream.WriteWord(WordToLE(AIndex));
{ Unicode string, 16-bit length }
AStream.WriteWord(WordToLE(Len));
AStream.WriteByte(INT_EXCEL_UNCOMPRESSED_STRING);
AStream.WriteBuffer(AFormatString[1], Len*2);
end;
{*******************************************************************
* TsSpreadBIFF5Writer.WriteFormula ()
*
* DESCRIPTION: Writes an Excel 5 FORMULA record
*
* To input a formula to this method, first convert it
* to RPN, and then list all it's members in the
* AFormula array
*
*******************************************************************}
procedure TsSpreadBIFF5Writer.WriteFormula(AStream: TStream; const ARow,
ACol: Word; const AFormula: TRPNFormula);
var
FormulaResult: double;
i: Integer;
RPNLength: Word;
TokenArraySizePos, RecordSizePos, FinalPos: Cardinal;
begin
RPNLength := 0;
FormulaResult := 0.0;
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_FORMULA));
RecordSizePos := AStream.Position;
AStream.WriteWord(WordToLE(17 + RPNLength));
{ BIFF Record data }
AStream.WriteWord(WordToLE(ARow));
AStream.WriteWord(WordToLE(ACol));
{ BIFF2 Attributes }
AStream.WriteByte($0);
AStream.WriteByte($0);
AStream.WriteByte($0);
{ Result of the formula in IEE 754 floating-point value }
AStream.WriteBuffer(FormulaResult, 8);
{ 0 = Do not recalculate
1 = Always recalculate }
AStream.WriteByte($1);
{ Formula }
{ The size of the token array is written later,
because it's necessary to calculate if first,
and this is done at the same time it is written }
TokenArraySizePos := AStream.Position;
AStream.WriteByte(RPNLength);
{ Formula data (RPN token array) }
for i := 0 to Length(AFormula) - 1 do
begin
{ Token identifier }
AStream.WriteByte(AFormula[i].TokenID);
Inc(RPNLength);
{ Additional data }
case AFormula[i].TokenID of
{ binary operation tokens }
INT_EXCEL_TOKEN_TADD, INT_EXCEL_TOKEN_TSUB, INT_EXCEL_TOKEN_TMUL,
INT_EXCEL_TOKEN_TDIV, INT_EXCEL_TOKEN_TPOWER: begin end;
INT_EXCEL_TOKEN_TNUM:
begin
AStream.WriteBuffer(AFormula[i].DoubleValue, 8);
Inc(RPNLength, 8);
end;
INT_EXCEL_TOKEN_TREFR, INT_EXCEL_TOKEN_TREFV, INT_EXCEL_TOKEN_TREFA:
begin
AStream.WriteWord(AFormula[i].Row and MASK_EXCEL_ROW);
AStream.WriteByte(AFormula[i].Col);
Inc(RPNLength, 3);
end;
end;
end;
{ Write sizes in the end, after we known them }
FinalPos := AStream.Position;
AStream.position := TokenArraySizePos;
AStream.WriteByte(RPNLength);
AStream.Position := RecordSizePos;
AStream.WriteWord(WordToLE(17 + RPNLength));
AStream.position := FinalPos;
end;
{*******************************************************************
* TsSpreadBIFF5Writer.WriteLabel ()
*
* DESCRIPTION: Writes an Excel 8 LABEL record
*
* Writes a string to the sheet
*
*******************************************************************}
procedure TsSpreadBIFF5Writer.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(Pointer(AValue)^, L);
end;
{*******************************************************************
* TsSpreadBIFF5Writer.WriteNumber ()
*
* DESCRIPTION: Writes an Excel 5 NUMBER record
*
* Writes a number (64-bit floating point) to the sheet
*
*******************************************************************}
procedure TsSpreadBIFF5Writer.WriteNumber(AStream: TStream; const ARow,
ACol: Cardinal; const AValue: double);
begin
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_NUMBER));
AStream.WriteWord(WordToLE(14));
{ BIFF Record data }
AStream.WriteWord(WordToLE(ARow));
AStream.WriteWord(WordToLE(ACol));
{ Index to XF record }
AStream.WriteWord($0);
{ IEE 754 floating-point value }
AStream.WriteBuffer(AValue, 8);
end;
procedure TsSpreadBIFF5Writer.WriteXF(AStream: TStream);
begin
{ BIFF Record header }
AStream.WriteWord(WordToLE(INT_EXCEL_ID_XF));
AStream.WriteWord(WordToLE(12));
{ Index to FONT record }
AStream.WriteByte($00);
{ Index to FORMAT record }
AStream.WriteByte($00);
{ XF type, cell protection and parent style XF }
AStream.WriteWord(WordToLE(INT_EXCEL_XF_TYPE_PROT_STYLEXF));
{ Alignment, text break and text orientation }
AStream.WriteByte($00);
{ Flags for used attribute groups }
AStream.WriteByte($00);
{ XF_AREA_34 - Cell background area }
AStream.WriteWord($0000);
{ XF_BORDER_34 - Cell border lines }
AStream.WriteDWord($00000000);
end;
end.

View File

@ -0,0 +1,383 @@
{
xlsxooxml.pas
Writes an OOXML (Office Open XML) document
An OOXML document is a compressed ZIP file with the following files inside:
[Content_Types].xml
_rels\.rels
xl\_rels\workbook.xml.rels
xl\workbook.xml
xl\styles.xml
xl\sharedStrings.xml
xl\worksheets\sheet1.xml
...
xl\worksheets\sheetN.xml
Specifications obtained from:
http://openxmldeveloper.org/default.aspx
AUTHORS: Felipe Monteiro de Carvalho
IMPORTANT: This writer doesn't work yet!!! This is just initial code.
}
unit xlsxooxml;
{$ifdef fpc}
{$mode delphi}
{$endif}
interface
uses
Classes, SysUtils, {zipper,}
fpspreadsheet;
type
{ TsSpreadOOXMLWriter }
TsSpreadOOXMLWriter = class(TsCustomSpreadWriter)
protected
// FZip: TZipper;
FContentTypes: string;
FRelsRels: string;
FWorkbook, FWorkbookRels, FStyles, FSharedString, FSheet1: 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
{ OOXML general XML constants }
XML_HEADER = '<?xml version="1.0" encoding="utf-8" ?>';
{ OOXML Directory structure constants }
OOXML_PATH_TYPES = '[Content_Types].xml';
OOXML_PATH_RELS = '_rels\';
OOXML_PATH_RELS_RELS = '_rels\.rels';
OOXML_PATH_XL = 'xl\';
OOXML_PATH_XL_RELS = 'xl\_rels\';
OOXML_PATH_XL_RELS_RELS = 'xl\_rels\workbook.xml.rels';
OOXML_PATH_XL_WORKBOOK = 'xl\workbook.xml';
OOXML_PATH_XL_STYLES = 'xl\styles.xml';
OOXML_PATH_XL_STRINGS = 'xl\sharedStrings.xml';
OOXML_PATH_XL_WORKSHEETS = 'xl\worksheets\';
{ OOXML schemas constants }
SCHEMAS_TYPES = 'http://schemas.openxmlformats.org/package/2006/content-types';
SCHEMAS_RELS = 'http://schemas.openxmlformats.org/package/2006/relationships';
SCHEMAS_DOC_RELS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships';
SCHEMAS_DOCUMENT = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument';
SCHEMAS_WORKSHEET = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet';
SCHEMAS_STYLES = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles';
SCHEMAS_STRINGS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings';
SCHEMAS_SPREADML = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main';
{ OOXML mime types constants }
MIME_XML = 'application/xml';
MIME_RELS = 'application/vnd.openxmlformats-package.relationships+xml';
MIME_SPREADML = 'application/vnd.openxmlformats-officedocument.spreadsheetml';
MIME_SHEET = MIME_SPREADML + '.sheet.main+xml';
MIME_WORKSHEET = MIME_SPREADML + '.worksheet+xml';
MIME_STYLES = MIME_SPREADML + '.styles+xml';
MIME_STRINGS = MIME_SPREADML + '.sharedStrings+xml';
{ TsSpreadOOXMLWriter }
{*******************************************************************
* TsSpreadOOXMLWriter.WriteStringToFile ()
*
* DESCRIPTION: Writes a string to a file. Helper convenience method.
*
*******************************************************************}
procedure TsSpreadOOXMLWriter.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 TsSpreadOOXMLWriter.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_TYPES, FContentTypes);
{ _rels directory }
ForceDirectories(TempDir + OOXML_PATH_RELS);
WriteStringToFile(TempDir + OOXML_PATH_RELS_RELS, FRelsRels);
{ xl directory }
ForceDirectories(TempDir + OOXML_PATH_XL_RELS);
WriteStringToFile(TempDir + OOXML_PATH_XL_RELS_RELS, FWorkbookRels);
WriteStringToFile(TempDir + OOXML_PATH_XL_WORKBOOK, FWorkbook);
WriteStringToFile(TempDir + OOXML_PATH_XL_STYLES, FStyles);
WriteStringToFile(TempDir + OOXML_PATH_XL_STRINGS, FSharedString);
{ xl\worksheets directory }
ForceDirectories(TempDir + OOXML_PATH_XL_WORKSHEETS);
WriteStringToFile(TempDir + OOXML_PATH_XL_WORKSHEETS + 'sheet1.xml', FSheet1);
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 TsSpreadOOXMLWriter.WriteToStream(AStream: TStream; AData: TsWorkbook);
begin
// WriteCellsToStream(AStream, AData.GetFirstWorksheet.FCells);
FContentTypes :=
XML_HEADER + LineEnding +
'<Types xmlns="' + SCHEMAS_TYPES + '">' + LineEnding +
' <Default Extension="xml" ContentType="' + MIME_XML + '" />' + LineEnding +
' <Default Extension="rels" ContentType="' + MIME_RELS + '" />' + LineEnding +
' <Override PartName="/xl/workbook.xml" ContentType="' + MIME_SHEET + '" />' + LineEnding +
' <Override PartName="/xl/worksheets/sheet1.xml" ContentType="' + MIME_WORKSHEET + '" />' + LineEnding +
' <Override PartName="/xl/styles.xml" ContentType="' + MIME_STYLES + '" />' + LineEnding +
' <Override PartName="/xl/sharedStrings.xml" ContentType="' + MIME_STRINGS + '" />' + LineEnding +
'</Types>';
FRelsRels :=
XML_HEADER + LineEnding +
'<Relationships xmlns="' + SCHEMAS_RELS + '">' + LineEnding +
'<Relationship Type="' + SCHEMAS_DOCUMENT + '" Target="/xl/workbook.xml" Id="rId1" />' + LineEnding +
'</Relationships>';
FWorkbookRels :=
XML_HEADER + LineEnding +
'<Relationships xmlns="' + SCHEMAS_RELS + '">' + LineEnding +
'<Relationship Type="' + SCHEMAS_WORKSHEET + '" Target="/xl/worksheets/sheet1.xml" Id="rId1" />' + LineEnding +
'<Relationship Type="' + SCHEMAS_STYLES + '" Target="/xl/styles.xml" Id="rId2" />' + LineEnding +
'<Relationship Type="' + SCHEMAS_STRINGS + '" Target="/xl/sharedStrings.xml" Id="rId3" />' + LineEnding +
'</Relationships>';
FWorkbook :=
XML_HEADER + LineEnding +
'<workbook xmlns="' + SCHEMAS_SPREADML + '" xmlns:r="' + SCHEMAS_DOC_RELS + '">' + LineEnding +
' <fileVersion appName="xl" lastEdited="4" lowestEdited="4" rupBuild="4505" />' + LineEnding +
' <workbookPr defaultThemeVersion="124226" />' + LineEnding +
' <bookViews>' + LineEnding +
' <workbookView xWindow="480" yWindow="90" windowWidth="15195" windowHeight="12525" />' + LineEnding +
' </bookViews>' + LineEnding +
' <sheets>' + LineEnding +
' <sheet name="Sheet1" sheetId="1" r:id="rId1" />' + LineEnding +
' </sheets>' + LineEnding +
' <calcPr calcId="114210" />' + LineEnding +
'</workbook>';
FStyles :=
XML_HEADER + LineEnding +
'<styleSheet xmlns="' + SCHEMAS_SPREADML + '">' + LineEnding +
' <fonts count="1">' + LineEnding +
' <font>' + LineEnding +
' <sz val="10" />' + LineEnding +
' <name val="Arial" />' + LineEnding +
' </font>' + LineEnding +
' </fonts>' + LineEnding +
' <fills count="2">' + LineEnding +
' <fill>' + LineEnding +
' <patternFill patternType="none" />' + LineEnding +
' </fill>' + LineEnding +
' <fill>' + LineEnding +
' <patternFill patternType="gray125" />' + LineEnding +
' </fill>' + LineEnding +
' </fills>' + LineEnding +
' <borders count="1">' + LineEnding +
' <border>' + LineEnding +
' <left />' + LineEnding +
' <right />' + LineEnding +
' <top />' + LineEnding +
' <bottom />' + LineEnding +
' <diagonal />' + LineEnding +
' </border>' + LineEnding +
' </borders>' + LineEnding +
' <cellStyleXfs count="1">' + LineEnding +
' <xf numFmtId="0" fontId="0" fillId="0" borderId="0" />' + LineEnding +
' </cellStyleXfs>' + LineEnding +
' <cellXfs count="1">' + LineEnding +
' <xf numFmtId="0" fontId="0" fillId="0" borderId="0" xfId="0" />' + LineEnding +
' </cellXfs>' + LineEnding +
' <cellStyles count="1">' + LineEnding +
' <cellStyle name="Normal" xfId="0" builtinId="0" />' + LineEnding +
' </cellStyles>' + LineEnding +
' <dxfs count="0" />' + LineEnding +
' <tableStyles count="0" defaultTableStyle="TableStyleMedium9" defaultPivotStyle="PivotStyleLight16" />' + LineEnding +
'</styleSheet>';
FSharedString :=
XML_HEADER + LineEnding +
'<sst xmlns="' + SCHEMAS_SPREADML + '" count="4" uniqueCount="4">' + LineEnding +
' <si>' + LineEnding +
' <t>First</t>' + LineEnding +
' </si>' + LineEnding +
' <si>' + LineEnding +
' <t>Second</t>' + LineEnding +
' </si>' + LineEnding +
' <si>' + LineEnding +
' <t>Third</t>' + LineEnding +
' </si>' + LineEnding +
' <si>' + LineEnding +
' <t>Fourth</t>' + LineEnding +
' </si>' + LineEnding +
'</sst>';
FSheet1 :=
XML_HEADER + LineEnding +
'<worksheet xmlns="' + SCHEMAS_SPREADML + '" xmlns:r="' + SCHEMAS_DOC_RELS + '">' + LineEnding +
' <sheetViews>' + LineEnding +
' <sheetView workbookViewId="0" />' + LineEnding +
' </sheetViews>' + LineEnding +
' <sheetData>' + LineEnding +
' <row r="1" spans="1:4">' + LineEnding +
' <c r="A1">' + LineEnding +
' <v>1</v>' + LineEnding +
' </c>' + LineEnding +
' <c r="B1">' + LineEnding +
' <v>2</v>' + LineEnding +
' </c>' + LineEnding +
' <c r="C1">' + LineEnding +
' <v>3</v>' + LineEnding +
' </c>' + LineEnding +
' <c r="D1">' + LineEnding +
' <v>4</v>' + LineEnding +
' </c>' + LineEnding +
' </row>' + LineEnding +
' <row r="2" spans="1:4">' + LineEnding +
' <c r="A2" t="s">' + LineEnding +
' <v>0</v>' + LineEnding +
' </c>' + LineEnding +
' <c r="B2" t="s">' + LineEnding +
' <v>1</v>' + LineEnding +
' </c>' + LineEnding +
' <c r="C2" t="s">' + LineEnding +
' <v>2</v>' + LineEnding +
' </c>' + LineEnding +
' <c r="D2" t="s">' + LineEnding +
' <v>3</v>' + LineEnding +
' </c>' + LineEnding +
' </row>' + LineEnding +
' </sheetData>' + LineEnding +
'</worksheet>';
end;
{*******************************************************************
* TsSpreadOOXMLWriter.WriteLabel ()
*
* DESCRIPTION: Writes an Excel 2 LABEL record
*
* Writes a string to the sheet
*
*******************************************************************}
procedure TsSpreadOOXMLWriter.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 TsSpreadOOXMLWriter.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, TsSpreadOOXMLWriter, sfOOXML);
end.