fpspreadsheet: Starts adding read support

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@656 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
sekelsenmat 2009-01-10 21:47:59 +00:00
parent 0b32db4780
commit 6bc68ea9b5
16 changed files with 1584 additions and 134 deletions

View File

@ -0,0 +1,273 @@
<?xml version="1.0"?>
<CONFIG>
<ProjectOptions>
<PathDelim Value="\"/>
<Version Value="7"/>
<General>
<Flags>
<LRSInOutputDirectory Value="False"/>
</Flags>
<MainUnit Value="0"/>
<TargetFileExt Value=".exe"/>
<Title Value="excel2read"/>
<ActiveEditorIndexAtStart Value="4"/>
</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>
<RequiredPackages Count="1">
<Item1>
<PackageName Value="laz_fpspreadsheet"/>
</Item1>
</RequiredPackages>
<Units Count="13">
<Unit0>
<Filename Value="excel2read.lpr"/>
<IsPartOfProject Value="True"/>
<UnitName Value="excel2read"/>
<CursorPos X="6" Y="23"/>
<TopLine Value="12"/>
<EditorIndex Value="0"/>
<UsageCount Value="309"/>
<Loaded Value="True"/>
</Unit0>
<Unit1>
<Filename Value="..\fpolestorage.pas"/>
<UnitName Value="fpolestorage"/>
<CursorPos X="1" Y="1"/>
<TopLine Value="1"/>
<UsageCount Value="19"/>
</Unit1>
<Unit2>
<Filename Value="..\..\..\..\..\lazarus\lcl\interfaces\win32\win32wsstdctrls.pp"/>
<UnitName Value="Win32WSStdCtrls"/>
<CursorPos X="35" Y="720"/>
<TopLine Value="713"/>
<UsageCount Value="76"/>
</Unit2>
<Unit3>
<Filename Value="..\..\..\..\..\lazarus\ideintf\componenteditors.pas"/>
<UnitName Value="ComponentEditors"/>
<CursorPos X="40" Y="332"/>
<TopLine Value="330"/>
<UsageCount Value="74"/>
</Unit3>
<Unit4>
<Filename Value="..\..\xlsbiff5.pas"/>
<UnitName Value="xlsbiff5"/>
<CursorPos X="29" Y="1"/>
<TopLine Value="22"/>
<EditorIndex Value="3"/>
<UsageCount Value="140"/>
<Loaded Value="True"/>
</Unit4>
<Unit5>
<Filename Value="..\..\fpsutils.pas"/>
<UnitName Value="fpsutils"/>
<CursorPos X="1" Y="49"/>
<TopLine Value="30"/>
<EditorIndex Value="2"/>
<UsageCount Value="140"/>
<Loaded Value="True"/>
</Unit5>
<Unit6>
<Filename Value="..\..\xlsbiff2.pas"/>
<UnitName Value="xlsbiff2"/>
<CursorPos X="16" Y="357"/>
<TopLine Value="347"/>
<EditorIndex Value="4"/>
<UsageCount Value="139"/>
<Loaded Value="True"/>
</Unit6>
<Unit7>
<Filename Value="..\..\fpolestorage.pas"/>
<UnitName Value="fpolestorage"/>
<CursorPos X="30" Y="654"/>
<TopLine Value="642"/>
<EditorIndex Value="5"/>
<UsageCount Value="139"/>
<Loaded Value="True"/>
</Unit7>
<Unit8>
<Filename Value="..\..\..\..\..\lazarus26\fpc\2.2.2\source\rtl\objpas\classes\classesh.inc"/>
<CursorPos X="19" Y="562"/>
<TopLine Value="553"/>
<UsageCount Value="41"/>
</Unit8>
<Unit9>
<Filename Value="..\..\..\..\..\lazarus26\fpc\2.2.2\source\rtl\objpas\classes\streams.inc"/>
<CursorPos X="21" Y="158"/>
<TopLine Value="151"/>
<UsageCount Value="41"/>
</Unit9>
<Unit10>
<Filename Value="..\..\fpspreadsheet.pas"/>
<UnitName Value="fpspreadsheet"/>
<CursorPos X="2" Y="714"/>
<TopLine Value="701"/>
<EditorIndex Value="1"/>
<UsageCount Value="92"/>
<Loaded Value="True"/>
</Unit10>
<Unit11>
<Filename Value="..\..\..\..\..\lazarus\lcl\include\customtrayicon.inc"/>
<CursorPos X="22" Y="203"/>
<TopLine Value="197"/>
<UsageCount Value="67"/>
</Unit11>
<Unit12>
<Filename Value="..\..\..\..\..\lazarus26\fpc\2.2.2\source\rtl\objpas\sysutils\sysstrh.inc"/>
<CursorPos X="26" Y="154"/>
<TopLine Value="144"/>
<UsageCount Value="10"/>
</Unit12>
</Units>
<JumpHistory Count="30" HistoryIndex="29">
<Position1>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="309" Column="1" TopLine="299"/>
</Position1>
<Position2>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="310" Column="1" TopLine="300"/>
</Position2>
<Position3>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="312" Column="1" TopLine="302"/>
</Position3>
<Position4>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="314" Column="1" TopLine="304"/>
</Position4>
<Position5>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="317" Column="1" TopLine="307"/>
</Position5>
<Position6>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="326" Column="1" TopLine="316"/>
</Position6>
<Position7>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="328" Column="1" TopLine="318"/>
</Position7>
<Position8>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="309" Column="1" TopLine="299"/>
</Position8>
<Position9>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="310" Column="1" TopLine="300"/>
</Position9>
<Position10>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="312" Column="1" TopLine="302"/>
</Position10>
<Position11>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="314" Column="1" TopLine="304"/>
</Position11>
<Position12>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="317" Column="1" TopLine="307"/>
</Position12>
<Position13>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="326" Column="1" TopLine="316"/>
</Position13>
<Position14>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="328" Column="1" TopLine="318"/>
</Position14>
<Position15>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="309" Column="1" TopLine="299"/>
</Position15>
<Position16>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="310" Column="1" TopLine="300"/>
</Position16>
<Position17>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="312" Column="1" TopLine="302"/>
</Position17>
<Position18>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="314" Column="1" TopLine="304"/>
</Position18>
<Position19>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="317" Column="1" TopLine="307"/>
</Position19>
<Position20>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="326" Column="1" TopLine="316"/>
</Position20>
<Position21>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="328" Column="1" TopLine="318"/>
</Position21>
<Position22>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="309" Column="1" TopLine="299"/>
</Position22>
<Position23>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="310" Column="1" TopLine="300"/>
</Position23>
<Position24>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="312" Column="1" TopLine="302"/>
</Position24>
<Position25>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="314" Column="1" TopLine="304"/>
</Position25>
<Position26>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="320" Column="1" TopLine="310"/>
</Position26>
<Position27>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="100" Column="16" TopLine="87"/>
</Position27>
<Position28>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="357" Column="16" TopLine="348"/>
</Position28>
<Position29>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="354" Column="6" TopLine="344"/>
</Position29>
<Position30>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="356" Column="14" TopLine="340"/>
</Position30>
</JumpHistory>
</ProjectOptions>
<CompilerOptions>
<Version Value="8"/>
<PathDelim Value="\"/>
<SearchPaths>
<OtherUnitFiles Value="..\"/>
<SrcPath Value="..\"/>
</SearchPaths>
<Other>
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
</CONFIG>

View File

@ -0,0 +1,49 @@
{
excel2read.dpr
Demonstrates how to read an Excel 2.x file using the fpspreadsheet library
AUTHORS: Felipe Monteiro de Carvalho
}
program excel2read;
{$mode delphi}{$H+}
uses
Classes, SysUtils, fpspreadsheet, xlsbiff2, laz_fpspreadsheet;
var
MyWorkbook: TsWorkbook;
MyWorksheet: TsWorksheet;
InputFilename: string;
MyDir: string;
i: Integer;
CurCell: PCell;
begin
// Open the input file
MyDir := ExtractFilePath(ParamStr(0));
InputFileName := MyDir + 'test' + STR_EXCEL_EXTENSION;
WriteLn('Opening input file ', InputFilename);
// Create the spreadsheet
MyWorkbook := TsWorkbook.Create;
MyWorkbook.ReadFromFile(InputFilename, sfExcel2);
MyWorksheet := MyWorkbook.GetFirstWorksheet;
// Write all cells with contents to the console
WriteLn('');
WriteLn('Contents of the first worksheet of the file:');
WriteLn('');
for i := 0 to MyWorksheet.GetCellCount - 1 do
begin
CurCell := MyWorkSheet.GetCellByIndex(i);
WriteLn('Row: ', CurCell^.Row, ' Col: ', CurCell^.Col, ' Value: ',
MyWorkSheet.ReadAsAnsiText(CurCell^.Row, CurCell^.Col));
end;
// Finalization
MyWorkbook.Free;
end.

View File

@ -0,0 +1,251 @@
<?xml version="1.0"?>
<CONFIG>
<ProjectOptions>
<PathDelim Value="\"/>
<Version Value="7"/>
<General>
<Flags>
<LRSInOutputDirectory Value="False"/>
</Flags>
<MainUnit Value="0"/>
<TargetFileExt Value=".exe"/>
<Title Value="excel2write"/>
<ActiveEditorIndexAtStart Value="0"/>
</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>
<RequiredPackages Count="1">
<Item1>
<PackageName Value="laz_fpspreadsheet"/>
</Item1>
</RequiredPackages>
<Units Count="12">
<Unit0>
<Filename Value="excel2write.lpr"/>
<IsPartOfProject Value="True"/>
<UnitName Value="excel2write"/>
<CursorPos X="30" Y="37"/>
<TopLine Value="19"/>
<EditorIndex Value="0"/>
<UsageCount Value="309"/>
<Loaded Value="True"/>
</Unit0>
<Unit1>
<Filename Value="..\fpolestorage.pas"/>
<UnitName Value="fpolestorage"/>
<CursorPos X="1" Y="1"/>
<TopLine Value="1"/>
<UsageCount Value="19"/>
</Unit1>
<Unit2>
<Filename Value="..\..\..\..\..\lazarus\lcl\interfaces\win32\win32wsstdctrls.pp"/>
<UnitName Value="Win32WSStdCtrls"/>
<CursorPos X="35" Y="720"/>
<TopLine Value="713"/>
<UsageCount Value="76"/>
</Unit2>
<Unit3>
<Filename Value="..\..\..\..\..\lazarus\ideintf\componenteditors.pas"/>
<UnitName Value="ComponentEditors"/>
<CursorPos X="40" Y="332"/>
<TopLine Value="330"/>
<UsageCount Value="74"/>
</Unit3>
<Unit4>
<Filename Value="..\..\xlsbiff5.pas"/>
<UnitName Value="xlsbiff5"/>
<CursorPos X="1" Y="224"/>
<TopLine Value="215"/>
<EditorIndex Value="3"/>
<UsageCount Value="140"/>
<Loaded Value="True"/>
</Unit4>
<Unit5>
<Filename Value="..\..\fpsutils.pas"/>
<UnitName Value="fpsutils"/>
<CursorPos X="1" Y="49"/>
<TopLine Value="30"/>
<EditorIndex Value="2"/>
<UsageCount Value="140"/>
<Loaded Value="True"/>
</Unit5>
<Unit6>
<Filename Value="..\..\xlsbiff2.pas"/>
<UnitName Value="xlsbiff2"/>
<CursorPos X="1" Y="69"/>
<TopLine Value="57"/>
<EditorIndex Value="4"/>
<UsageCount Value="139"/>
<Loaded Value="True"/>
</Unit6>
<Unit7>
<Filename Value="..\..\fpolestorage.pas"/>
<UnitName Value="fpolestorage"/>
<CursorPos X="30" Y="654"/>
<TopLine Value="642"/>
<EditorIndex Value="5"/>
<UsageCount Value="139"/>
<Loaded Value="True"/>
</Unit7>
<Unit8>
<Filename Value="..\..\..\..\..\lazarus26\fpc\2.2.2\source\rtl\objpas\classes\classesh.inc"/>
<CursorPos X="19" Y="562"/>
<TopLine Value="553"/>
<UsageCount Value="41"/>
</Unit8>
<Unit9>
<Filename Value="..\..\..\..\..\lazarus26\fpc\2.2.2\source\rtl\objpas\classes\streams.inc"/>
<CursorPos X="21" Y="158"/>
<TopLine Value="151"/>
<UsageCount Value="41"/>
</Unit9>
<Unit10>
<Filename Value="..\..\fpspreadsheet.pas"/>
<UnitName Value="fpspreadsheet"/>
<CursorPos X="3" Y="428"/>
<TopLine Value="420"/>
<EditorIndex Value="1"/>
<UsageCount Value="92"/>
<Loaded Value="True"/>
</Unit10>
<Unit11>
<Filename Value="..\..\..\..\..\lazarus\lcl\include\customtrayicon.inc"/>
<CursorPos X="22" Y="203"/>
<TopLine Value="197"/>
<UsageCount Value="67"/>
</Unit11>
</Units>
<JumpHistory Count="26" HistoryIndex="25">
<Position1>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="40" Column="5" TopLine="31"/>
</Position1>
<Position2>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="472" Column="49" TopLine="461"/>
</Position2>
<Position3>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="405" Column="5" TopLine="386"/>
</Position3>
<Position4>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="404" Column="14" TopLine="401"/>
</Position4>
<Position5>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="79" Column="42" TopLine="72"/>
</Position5>
<Position6>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="78" Column="31" TopLine="67"/>
</Position6>
<Position7>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="314" Column="39" TopLine="296"/>
</Position7>
<Position8>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="479" Column="1" TopLine="469"/>
</Position8>
<Position9>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="470" Column="1" TopLine="460"/>
</Position9>
<Position10>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="217" Column="3" TopLine="205"/>
</Position10>
<Position11>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="218" Column="23" TopLine="208"/>
</Position11>
<Position12>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="78" Column="10" TopLine="66"/>
</Position12>
<Position13>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="375" Column="1" TopLine="367"/>
</Position13>
<Position14>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="76" Column="17" TopLine="65"/>
</Position14>
<Position15>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="363" Column="1" TopLine="357"/>
</Position15>
<Position16>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="77" Column="7" TopLine="76"/>
</Position16>
<Position17>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="137" Column="40" TopLine="129"/>
</Position17>
<Position18>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="563" Column="5" TopLine="544"/>
</Position18>
<Position19>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="486" Column="5" TopLine="467"/>
</Position19>
<Position20>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="510" Column="5" TopLine="491"/>
</Position20>
<Position21>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="94" Column="46" TopLine="84"/>
</Position21>
<Position22>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="686" Column="5" TopLine="667"/>
</Position22>
<Position23>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="567" Column="5" TopLine="548"/>
</Position23>
<Position24>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="622" Column="1" TopLine="618"/>
</Position24>
<Position25>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="621" Column="29" TopLine="611"/>
</Position25>
<Position26>
<Filename Value="excel2write.lpr"/>
<Caret Line="30" Column="21" TopLine="19"/>
</Position26>
</JumpHistory>
</ProjectOptions>
<CompilerOptions>
<Version Value="8"/>
<PathDelim Value="\"/>
<SearchPaths>
<OtherUnitFiles Value="..\"/>
<SrcPath Value="..\"/>
</SearchPaths>
<Other>
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
</CONFIG>

View File

@ -0,0 +1,43 @@
{
excel2write.dpr
Demonstrates how to write an Excel 2.x file using the fpspreadsheet library
AUTHORS: Felipe Monteiro de Carvalho
}
program excel2write;
{$mode delphi}{$H+}
uses
Classes, SysUtils, fpspreadsheet, xlsbiff2, laz_fpspreadsheet;
var
MyWorkbook: TsWorkbook;
MyWorksheet: TsWorksheet;
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 some string cells
MyWorksheet.WriteAnsiText(1, 0, 'First');
MyWorksheet.WriteAnsiText(1, 1, 'Second');
MyWorksheet.WriteAnsiText(1, 2, 'Third');
MyWorksheet.WriteAnsiText(1, 3, 'Fourth');
// Save the spreadsheet to a file
MyWorkbook.WriteToFile(MyDir + 'test' + STR_EXCEL_EXTENSION, sfExcel2);
MyWorkbook.Free;
end.

View File

@ -0,0 +1,2 @@
excel2read.exe
pause

View File

@ -0,0 +1,3 @@
del test.xls
excel2write.exe
pause

View File

@ -0,0 +1,273 @@
<?xml version="1.0"?>
<CONFIG>
<ProjectOptions>
<PathDelim Value="\"/>
<Version Value="7"/>
<General>
<Flags>
<LRSInOutputDirectory Value="False"/>
</Flags>
<MainUnit Value="0"/>
<TargetFileExt Value=".exe"/>
<Title Value="excel5read"/>
<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>
<RequiredPackages Count="1">
<Item1>
<PackageName Value="laz_fpspreadsheet"/>
</Item1>
</RequiredPackages>
<Units Count="13">
<Unit0>
<Filename Value="excel5read.lpr"/>
<IsPartOfProject Value="True"/>
<UnitName Value="excel5read"/>
<CursorPos X="1" Y="21"/>
<TopLine Value="3"/>
<EditorIndex Value="0"/>
<UsageCount Value="309"/>
<Loaded Value="True"/>
</Unit0>
<Unit1>
<Filename Value="..\fpolestorage.pas"/>
<UnitName Value="fpolestorage"/>
<CursorPos X="1" Y="1"/>
<TopLine Value="1"/>
<UsageCount Value="19"/>
</Unit1>
<Unit2>
<Filename Value="..\..\..\..\..\lazarus\lcl\interfaces\win32\win32wsstdctrls.pp"/>
<UnitName Value="Win32WSStdCtrls"/>
<CursorPos X="35" Y="720"/>
<TopLine Value="713"/>
<UsageCount Value="76"/>
</Unit2>
<Unit3>
<Filename Value="..\..\..\..\..\lazarus\ideintf\componenteditors.pas"/>
<UnitName Value="ComponentEditors"/>
<CursorPos X="40" Y="332"/>
<TopLine Value="330"/>
<UsageCount Value="74"/>
</Unit3>
<Unit4>
<Filename Value="..\..\xlsbiff5.pas"/>
<UnitName Value="xlsbiff5"/>
<CursorPos X="15" Y="64"/>
<TopLine Value="54"/>
<EditorIndex Value="3"/>
<UsageCount Value="140"/>
<Loaded Value="True"/>
</Unit4>
<Unit5>
<Filename Value="..\..\fpsutils.pas"/>
<UnitName Value="fpsutils"/>
<CursorPos X="1" Y="49"/>
<TopLine Value="30"/>
<EditorIndex Value="2"/>
<UsageCount Value="140"/>
<Loaded Value="True"/>
</Unit5>
<Unit6>
<Filename Value="..\..\xlsbiff2.pas"/>
<UnitName Value="xlsbiff2"/>
<CursorPos X="1" Y="69"/>
<TopLine Value="57"/>
<EditorIndex Value="4"/>
<UsageCount Value="139"/>
<Loaded Value="True"/>
</Unit6>
<Unit7>
<Filename Value="..\..\fpolestorage.pas"/>
<UnitName Value="fpolestorage"/>
<CursorPos X="30" Y="654"/>
<TopLine Value="642"/>
<EditorIndex Value="5"/>
<UsageCount Value="139"/>
<Loaded Value="True"/>
</Unit7>
<Unit8>
<Filename Value="..\..\..\..\..\lazarus26\fpc\2.2.2\source\rtl\objpas\classes\classesh.inc"/>
<CursorPos X="19" Y="562"/>
<TopLine Value="553"/>
<UsageCount Value="41"/>
</Unit8>
<Unit9>
<Filename Value="..\..\..\..\..\lazarus26\fpc\2.2.2\source\rtl\objpas\classes\streams.inc"/>
<CursorPos X="21" Y="158"/>
<TopLine Value="151"/>
<UsageCount Value="41"/>
</Unit9>
<Unit10>
<Filename Value="..\..\fpspreadsheet.pas"/>
<UnitName Value="fpspreadsheet"/>
<CursorPos X="1" Y="197"/>
<TopLine Value="189"/>
<EditorIndex Value="1"/>
<UsageCount Value="92"/>
<Loaded Value="True"/>
</Unit10>
<Unit11>
<Filename Value="..\..\..\..\..\lazarus\lcl\include\customtrayicon.inc"/>
<CursorPos X="22" Y="203"/>
<TopLine Value="197"/>
<UsageCount Value="67"/>
</Unit11>
<Unit12>
<Filename Value="..\..\..\..\..\lazarus26\fpc\2.2.2\source\rtl\objpas\sysutils\sysstrh.inc"/>
<CursorPos X="26" Y="154"/>
<TopLine Value="144"/>
<UsageCount Value="10"/>
</Unit12>
</Units>
<JumpHistory Count="30" HistoryIndex="29">
<Position1>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="486" Column="5" TopLine="467"/>
</Position1>
<Position2>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="510" Column="5" TopLine="491"/>
</Position2>
<Position3>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="94" Column="46" TopLine="84"/>
</Position3>
<Position4>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="686" Column="5" TopLine="667"/>
</Position4>
<Position5>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="567" Column="5" TopLine="548"/>
</Position5>
<Position6>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="622" Column="1" TopLine="618"/>
</Position6>
<Position7>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="621" Column="29" TopLine="611"/>
</Position7>
<Position8>
<Filename Value="excel5read.lpr"/>
<Caret Line="40" Column="17" TopLine="29"/>
</Position8>
<Position9>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="85" Column="3" TopLine="83"/>
</Position9>
<Position10>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="304" Column="5" TopLine="293"/>
</Position10>
<Position11>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="319" Column="32" TopLine="305"/>
</Position11>
<Position12>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="363" Column="15" TopLine="349"/>
</Position12>
<Position13>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="362" Column="36" TopLine="353"/>
</Position13>
<Position14>
<Filename Value="excel5read.lpr"/>
<Caret Line="40" Column="17" TopLine="29"/>
</Position14>
<Position15>
<Filename Value="excel5read.lpr"/>
<Caret Line="24" Column="1" TopLine="13"/>
</Position15>
<Position16>
<Filename Value="excel5read.lpr"/>
<Caret Line="29" Column="6" TopLine="19"/>
</Position16>
<Position17>
<Filename Value="excel5read.lpr"/>
<Caret Line="16" Column="17" TopLine="6"/>
</Position17>
<Position18>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="110" Column="3" TopLine="108"/>
</Position18>
<Position19>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="475" Column="5" TopLine="456"/>
</Position19>
<Position20>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="505" Column="42" TopLine="496"/>
</Position20>
<Position21>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="175" Column="24" TopLine="165"/>
</Position21>
<Position22>
<Filename Value="excel5read.lpr"/>
<Caret Line="16" Column="17" TopLine="6"/>
</Position22>
<Position23>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="143" Column="15" TopLine="115"/>
</Position23>
<Position24>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="119" Column="67" TopLine="108"/>
</Position24>
<Position25>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="485" Column="42" TopLine="474"/>
</Position25>
<Position26>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="161" Column="3" TopLine="159"/>
</Position26>
<Position27>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="141" Column="3" TopLine="139"/>
</Position27>
<Position28>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="669" Column="20" TopLine="658"/>
</Position28>
<Position29>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="158" Column="15" TopLine="143"/>
</Position29>
<Position30>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="116" Column="71" TopLine="106"/>
</Position30>
</JumpHistory>
</ProjectOptions>
<CompilerOptions>
<Version Value="8"/>
<PathDelim Value="\"/>
<SearchPaths>
<OtherUnitFiles Value="..\"/>
<SrcPath Value="..\"/>
</SearchPaths>
<Other>
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
</CONFIG>

View File

@ -0,0 +1,49 @@
{
excel5read.dpr
Demonstrates how to read an Excel 5.x file using the fpspreadsheet library
AUTHORS: Felipe Monteiro de Carvalho
}
program excel5read;
{$mode delphi}{$H+}
uses
Classes, SysUtils, fpspreadsheet, xlsbiff5, laz_fpspreadsheet;
var
MyWorkbook: TsWorkbook;
MyWorksheet: TsWorksheet;
InputFilename: string;
MyDir: string;
i: Integer;
CurCell: PCell;
begin
// Open the input file
MyDir := ExtractFilePath(ParamStr(0));
InputFileName := MyDir + 'test' + STR_EXCEL_EXTENSION;
WriteLn('Opening input file ', InputFilename);
// Create the spreadsheet
MyWorkbook := TsWorkbook.Create;
MyWorkbook.ReadFromFile(InputFilename, sfExcel5);
MyWorksheet := MyWorkbook.GetFirstWorksheet;
// Write all cells with contents to the console
WriteLn('');
WriteLn('Contents of the first worksheet of the file:');
WriteLn('');
for i := 0 to MyWorksheet.GetCellCount do
begin
CurCell := MyWorkSheet.GetCellByIndex(i);
WriteLn('Row: ', CurCell^.Row, ' Col: ', CurCell^.Col, ' Value: ',
MyWorkSheet.ReadAsAnsiText(CurCell^.Row, CurCell^.Col));
end;
// Finalization
MyWorkbook.Free;
end.

View File

@ -2,10 +2,14 @@
<CONFIG>
<ProjectOptions>
<PathDelim Value="\"/>
<Version Value="6"/>
<Version Value="7"/>
<General>
<Flags>
<LRSInOutputDirectory Value="False"/>
</Flags>
<MainUnit Value="0"/>
<TargetFileExt Value=".exe"/>
<Title Value="excel5write"/>
<ActiveEditorIndexAtStart Value="0"/>
</General>
<VersionInfo>
@ -30,243 +34,203 @@
<PackageName Value="laz_fpspreadsheet"/>
</Item1>
</RequiredPackages>
<Units Count="16">
<Units Count="12">
<Unit0>
<Filename Value="excel5demo.lpr"/>
<Filename Value="excel5write.lpr"/>
<IsPartOfProject Value="True"/>
<UnitName Value="excel5demo"/>
<UnitName Value="excel5write"/>
<CursorPos X="8" Y="21"/>
<TopLine Value="52"/>
<EditorIndex Value="0"/>
<UsageCount Value="196"/>
<UsageCount Value="309"/>
<Loaded Value="True"/>
</Unit0>
<Unit1>
<Filename Value="..\fpspreadsheet.pas"/>
<UnitName Value="fpspreadsheet"/>
<CursorPos X="32" Y="414"/>
<TopLine Value="388"/>
<UsageCount Value="10"/>
</Unit1>
<Unit2>
<Filename Value="..\xlsbiff5.pas"/>
<UnitName Value="xlsbiff5"/>
<CursorPos X="16" Y="320"/>
<TopLine Value="300"/>
<UsageCount Value="10"/>
</Unit2>
<Unit3>
<Filename Value="..\fpolestorage.pas"/>
<UnitName Value="fpolestorage"/>
<CursorPos X="1" Y="1"/>
<TopLine Value="1"/>
<UsageCount Value="30"/>
</Unit3>
<Unit4>
<Filename Value="..\xlsbiff2.pas"/>
<UnitName Value="xlsbiff2"/>
<CursorPos X="20" Y="277"/>
<TopLine Value="260"/>
<UsageCount Value="3"/>
</Unit4>
<Unit5>
<Filename Value="..\..\..\..\..\FPC220\source\rtl\objpas\fgl.pp"/>
<UnitName Value="fgl"/>
<CursorPos X="15" Y="86"/>
<TopLine Value="55"/>
<UsageCount Value="3"/>
</Unit5>
<Unit6>
<UsageCount Value="19"/>
</Unit1>
<Unit2>
<Filename Value="..\..\..\..\..\lazarus\lcl\interfaces\win32\win32wsstdctrls.pp"/>
<UnitName Value="Win32WSStdCtrls"/>
<CursorPos X="11" Y="737"/>
<CursorPos X="35" Y="720"/>
<TopLine Value="713"/>
<EditorIndex Value="7"/>
<UsageCount Value="88"/>
<Loaded Value="True"/>
</Unit6>
<Unit7>
<UsageCount Value="76"/>
</Unit2>
<Unit3>
<Filename Value="..\..\..\..\..\lazarus\ideintf\componenteditors.pas"/>
<UnitName Value="ComponentEditors"/>
<CursorPos X="54" Y="353"/>
<CursorPos X="40" Y="332"/>
<TopLine Value="330"/>
<EditorIndex Value="6"/>
<UsageCount Value="86"/>
<Loaded Value="True"/>
</Unit7>
<Unit8>
<UsageCount Value="74"/>
</Unit3>
<Unit4>
<Filename Value="..\..\xlsbiff5.pas"/>
<UnitName Value="xlsbiff5"/>
<CursorPos X="1" Y="224"/>
<TopLine Value="215"/>
<EditorIndex Value="3"/>
<UsageCount Value="83"/>
<UsageCount Value="140"/>
<Loaded Value="True"/>
</Unit8>
<Unit9>
</Unit4>
<Unit5>
<Filename Value="..\..\fpsutils.pas"/>
<UnitName Value="fpsutils"/>
<CursorPos X="1" Y="49"/>
<TopLine Value="30"/>
<EditorIndex Value="2"/>
<UsageCount Value="83"/>
<UsageCount Value="140"/>
<Loaded Value="True"/>
</Unit9>
<Unit10>
</Unit5>
<Unit6>
<Filename Value="..\..\xlsbiff2.pas"/>
<UnitName Value="xlsbiff2"/>
<CursorPos X="1" Y="69"/>
<TopLine Value="57"/>
<EditorIndex Value="4"/>
<UsageCount Value="83"/>
<UsageCount Value="139"/>
<Loaded Value="True"/>
</Unit10>
<Unit11>
</Unit6>
<Unit7>
<Filename Value="..\..\fpolestorage.pas"/>
<UnitName Value="fpolestorage"/>
<CursorPos X="48" Y="534"/>
<TopLine Value="520"/>
<CursorPos X="30" Y="654"/>
<TopLine Value="642"/>
<EditorIndex Value="5"/>
<UsageCount Value="83"/>
<UsageCount Value="139"/>
<Loaded Value="True"/>
</Unit11>
<Unit12>
</Unit7>
<Unit8>
<Filename Value="..\..\..\..\..\lazarus26\fpc\2.2.2\source\rtl\objpas\classes\classesh.inc"/>
<CursorPos X="19" Y="562"/>
<TopLine Value="553"/>
<UsageCount Value="53"/>
</Unit12>
<Unit13>
<UsageCount Value="41"/>
</Unit8>
<Unit9>
<Filename Value="..\..\..\..\..\lazarus26\fpc\2.2.2\source\rtl\objpas\classes\streams.inc"/>
<CursorPos X="21" Y="158"/>
<TopLine Value="151"/>
<UsageCount Value="53"/>
</Unit13>
<Unit14>
<UsageCount Value="41"/>
</Unit9>
<Unit10>
<Filename Value="..\..\fpspreadsheet.pas"/>
<UnitName Value="fpspreadsheet"/>
<CursorPos X="40" Y="137"/>
<TopLine Value="129"/>
<EditorIndex Value="1"/>
<UsageCount Value="33"/>
<UsageCount Value="92"/>
<Loaded Value="True"/>
</Unit14>
<Unit15>
<Filename Value="..\..\..\..\..\lazarus26\fpc\2.2.2\source\rtl\objpas\classes\stringl.inc"/>
<CursorPos X="20" Y="768"/>
<TopLine Value="761"/>
<UsageCount Value="10"/>
</Unit15>
</Unit10>
<Unit11>
<Filename Value="..\..\..\..\..\lazarus\lcl\include\customtrayicon.inc"/>
<CursorPos X="22" Y="203"/>
<TopLine Value="197"/>
<UsageCount Value="67"/>
</Unit11>
</Units>
<JumpHistory Count="27" HistoryIndex="26">
<JumpHistory Count="25" HistoryIndex="24">
<Position1>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="246" Column="12" TopLine="237"/>
<Caret Line="40" Column="5" TopLine="31"/>
</Position1>
<Position2>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="79" Column="16" TopLine="78"/>
<Caret Line="472" Column="49" TopLine="461"/>
</Position2>
<Position3>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="87" Column="16" TopLine="77"/>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="405" Column="5" TopLine="386"/>
</Position3>
<Position4>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="218" Column="24" TopLine="207"/>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="404" Column="14" TopLine="401"/>
</Position4>
<Position5>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="235" Column="30" TopLine="224"/>
<Caret Line="79" Column="42" TopLine="72"/>
</Position5>
<Position6>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="80" Column="28" TopLine="68"/>
<Caret Line="78" Column="31" TopLine="67"/>
</Position6>
<Position7>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="40" Column="5" TopLine="31"/>
<Caret Line="314" Column="39" TopLine="296"/>
</Position7>
<Position8>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="472" Column="49" TopLine="461"/>
<Caret Line="479" Column="1" TopLine="469"/>
</Position8>
<Position9>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="405" Column="5" TopLine="386"/>
<Caret Line="470" Column="1" TopLine="460"/>
</Position9>
<Position10>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="404" Column="14" TopLine="401"/>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="217" Column="3" TopLine="205"/>
</Position10>
<Position11>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="79" Column="42" TopLine="72"/>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="218" Column="23" TopLine="208"/>
</Position11>
<Position12>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="78" Column="31" TopLine="67"/>
<Caret Line="78" Column="10" TopLine="66"/>
</Position12>
<Position13>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="314" Column="39" TopLine="296"/>
<Caret Line="375" Column="1" TopLine="367"/>
</Position13>
<Position14>
<Filename Value="excel5demo.lpr"/>
<Caret Line="34" Column="1" TopLine="25"/>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="76" Column="17" TopLine="65"/>
</Position14>
<Position15>
<Filename Value="excel5demo.lpr"/>
<Caret Line="35" Column="1" TopLine="25"/>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="363" Column="1" TopLine="357"/>
</Position15>
<Position16>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="479" Column="1" TopLine="469"/>
<Caret Line="77" Column="7" TopLine="76"/>
</Position16>
<Position17>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="470" Column="1" TopLine="460"/>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="137" Column="40" TopLine="129"/>
</Position17>
<Position18>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="217" Column="3" TopLine="205"/>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="563" Column="5" TopLine="544"/>
</Position18>
<Position19>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="218" Column="23" TopLine="208"/>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="486" Column="5" TopLine="467"/>
</Position19>
<Position20>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="78" Column="10" TopLine="66"/>
<Caret Line="510" Column="5" TopLine="491"/>
</Position20>
<Position21>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="375" Column="1" TopLine="367"/>
<Caret Line="94" Column="46" TopLine="84"/>
</Position21>
<Position22>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="76" Column="17" TopLine="65"/>
<Caret Line="686" Column="5" TopLine="667"/>
</Position22>
<Position23>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="363" Column="1" TopLine="357"/>
<Caret Line="567" Column="5" TopLine="548"/>
</Position23>
<Position24>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="77" Column="7" TopLine="76"/>
<Caret Line="622" Column="1" TopLine="618"/>
</Position24>
<Position25>
<Filename Value="excel5demo.lpr"/>
<Caret Line="67" Column="21" TopLine="51"/>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="621" Column="29" TopLine="611"/>
</Position25>
<Position26>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="137" Column="40" TopLine="129"/>
</Position26>
<Position27>
<Filename Value="excel5demo.lpr"/>
<Caret Line="21" Column="8" TopLine="6"/>
</Position27>
</JumpHistory>
</ProjectOptions>
<CompilerOptions>

View File

@ -1,11 +1,11 @@
{
excel5demo.dpr
excel5write.dpr
Demonstrates how to write an Excel 5.x file using the fpspreadsheet library
AUTHORS: Felipe Monteiro de Carvalho
}
program excel5demo;
program excel5write;
{$mode delphi}{$H+}

View File

@ -1,3 +0,0 @@
del test.xls
excel5demo.exe
pause

View File

@ -0,0 +1,2 @@
excel5read.exe
pause

View File

@ -0,0 +1,3 @@
del test.xls
excel5write.exe
pause

View File

@ -60,16 +60,19 @@ type
TOLEStorage = class
private
{ Information filled by the write routines for the helper routines }
{$ifdef FPOLESTORAGE_USE_COM}
FStorage: IStorage;
FStream: IStream;
{$endif}
{ Information filled by the write routines for the helper routines }
{ Fields for the read routines }
FReadingStreamSize: Int64;
{ Fields for both }
FOLEDocument: TOLEDocument;
FUseShortSectors: Boolean;
FNumSATSectors, FNumStreamSectors, FNumTotalSectors: Cardinal;
FNumStreamShortSectors: Cardinal;
FUseShortSectors: Boolean;
{ Helper routines }
{ Writer Helper routines }
procedure WriteOLEHeader(AStream: TStream);
procedure WriteSectorAllocationTable(AStream: TStream);
procedure WriteDirectoryStream(AStream: TStream);
@ -78,10 +81,21 @@ type
AFirstSecID, AStreamSize: Cardinal);
procedure WriteShortSectorAllocationTable(AStream: TStream);
procedure WriteUserStream(ADest, ASource: TStream);
{ Reader helper routines }
procedure ReadOLEHeader(AStream: TStream);
procedure ReadSectorAllocationTable(AStream: TStream);
procedure ReadDirectoryStream(AStream: TStream);
procedure ReadDirectoryEntry(AStream: TStream; var AName: widestring;
var EntryType, EntryColor: Byte; var AIsStorage: Boolean;
var AFirstSecID, AStreamSize: Cardinal);
procedure ReadShortSectorAllocationTable(AStream: TStream);
procedure ReadUserStream(ADest, ASource: TStream);
public
constructor Create;
destructor Destroy; override;
procedure WriteOLEFile(AFileName: string; AOLEDocument: TOLEDocument);
procedure ReadOLEFile(AFileName: string; AOLEDocument: TOLEDocument);
procedure FreeOLEDocumentData(AOLEDocument: TOLEDocument);
end;
implementation
@ -475,6 +489,183 @@ begin
for i := 1 to PadSize do ADest.WriteByte($00);
end;
procedure TOLEStorage.ReadOLEHeader(AStream: TStream);
var
BaseAddr: Int64;
begin
BaseAddr := AStream.Position;
{ 28 2 Byte order identifier (4.2): FEH FFH = Little-Endian
FFH FEH = Big-Endian }
// For now just assume little-endian
{ 30 2 Size of a sector in the compound document file (3.1) in power-of-two (ssz), real sector
size is sec_size = 2ssz bytes (minimum value is 7 which means 128 bytes, most used
value is 9 which means 512 bytes) }
// Assume default value
{ 32 2 Size of a short-sector in the short-stream container stream (6.1) in power-of-two (sssz),
real short-sector size is short_sec_size = 2sssz bytes (maximum value is sector size
ssz, see above, most used value is 6 which means 64 bytes) }
// Assume default value
{ 44 4 Total number of sectors used for the sector allocation table (➜5.2) }
// Assume 1
{ 48 4 SecID of first sector of the directory stream (➜7) }
// Assume 1
{ 56 4 Minimum size of a standard stream (in bytes, minimum allowed and most used size is 4096
bytes), streams with an actual size smaller than (and not equal to) this value are stored as
short-streams (6) }
// Assume 4096
{ 60 4 SecID of first sector of the short-sector allocation table (6.2), or 2 (End Of Chain
SecID, 3.1) if not extant }
// Assume 2
{ 64 4 Total number of sectors used for the short-sector allocation table (➜6.2) }
// Assume 1
{ 68 4 SecID of first sector of the master sector allocation table (5.1), or 2 (End Of Chain
SecID, 3.1) if no additional sectors used }
// Assume 2
{ 72 4 Total number of sectors used for the master sector allocation table (➜5.1) }
// Assume 0
{ 76 436 First part of the master sector allocation table (➜5.1) containing 109 SecIDs }
// Assume: 0, -1, -1, -1 ...
end;
procedure TOLEStorage.ReadSectorAllocationTable(AStream: TStream);
begin
end;
procedure TOLEStorage.ReadDirectoryStream(AStream: TStream);
var
EntryName: widestring;
EntryType, EntryColor: Byte;
EntryIsStorage: Boolean;
EntryFirstSecID, EntryStreamSize: Cardinal;
begin
ReadDirectoryEntry(AStream, EntryName,
EntryType, EntryColor, EntryIsStorage,
EntryFirstSecID, EntryStreamSize);
ReadDirectoryEntry(AStream, EntryName,
EntryType, EntryColor, EntryIsStorage,
EntryFirstSecID, EntryStreamSize);
FReadingStreamSize := EntryStreamSize;
end;
procedure TOLEStorage.ReadDirectoryEntry(AStream: TStream;
var AName: widestring; var EntryType, EntryColor: Byte;
var AIsStorage: Boolean; var AFirstSecID, AStreamSize: Cardinal);
var
BaseAddr: Int64;
EntryName: array[0..63] of WideChar;
begin
BaseAddr := AStream.Position;
{ Contents of the directory entry structure:
Offset Size Contents
0 64 Character array of the name of the entry, always 16-bit Unicode characters, with trailing
zero character (results in a maximum name length of 31 characters)
00000400H 52 00 6F 00 6F 00 74 00 20 00 45 00 6E 00 74 00 }
AStream.ReadBuffer(EntryName, 64);
AName := EntryName;
{Root Storage #1
00000440H 16 00 05 00 FF FF FF FF FF FF FF FF 01 00 00 00
Book #2
000004C0H 0A 00 02 01 FF FF FF FF FF FF FF FF FF FF FF FF
Item #3 e #4
00000540H 00 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF
64 2 Size of the used area of the character buffer of the name (not character count), including
the trailing zero character (e.g. 12 for a name with 5 characters: (5+1)2 = 12)
66 1 Type of the entry: 00H = Empty 03H = LockBytes (unknown)
01H = User storage 04H = Property (unknown)
02H = User stream 05H = Root storage
67 1 Node colour of the entry: 00H = Red 01H = Black
68 4 DirID of the left child node inside the red-black tree of all direct members of the parent
storage (if this entry is a user storage or stream, 7.1), 1 if there is no left child
72 4 DirID of the right child node inside the red-black tree of all direct members of the parent
storage (if this entry is a user storage or stream, 7.1), 1 if there is no right child
76 4 DirID of the root node entry of the red-black tree of all storage members (if this entry is a
storage, 7.1), 1 otherwise
}
AStream.ReadWord();
EntryType := AStream.ReadByte();
EntryColor := AStream.ReadByte();
AStream.ReadDWord();
AStream.ReadDWord();
AIsStorage := AStream.ReadDWord() <> $FFFFFFFF;
{Root Storage #1
00000470H XX XX XX XX 03 00 00 00 40 03 00 00 00 00 00 00
Book #2
000004F0H XX XX XX XX 00 00 00 00 3F 03 00 00 00 00 00 00
Item #3 e #4
00000570H XX XX XX XX 00 00 00 00 00 00 00 00 00 00 00 00
First 4 bytes still with the timestamp.
116 4 SecID of first sector or short-sector, if this entry refers to a stream (7.2.2),
SecID of first sector of the short-stream container stream (6.1),
if this is the root storage entry, 0 otherwise
120 4 Total stream size in bytes, if this entry refers to a stream (7.2.2),
total size of the short-stream container stream (6.1),
if this is the root storage entry, 0 otherwise
124 4 Not used
}
AStream.Seek(BaseAddr + $74, soFromBeginning);
AFirstSecID := AStream.ReadDWord();
AStreamSize := AStream.ReadDWord();
AStream.ReadDWord();
end;
procedure TOLEStorage.ReadShortSectorAllocationTable(AStream: TStream);
begin
end;
procedure TOLEStorage.ReadUserStream(ADest, ASource: TStream);
begin
ADest.CopyFrom(ASource, FReadingStreamSize);
end;
constructor TOLEStorage.Create;
begin
inherited Create;
@ -487,6 +678,12 @@ begin
inherited Destroy;
end;
{@@
Writes the OLE document specified in AOLEDocument
to the file with name AFileName. The routine will fail
if the file already exists, or if the directory where
it should be placed doesn't exist.
}
procedure TOLEStorage.WriteOLEFile(AFileName: string; AOLEDocument: TOLEDocument);
var
cbWritten: Cardinal;
@ -555,5 +752,58 @@ begin
{$endif}
end;
{@@
Reads an OLE file. Experimental
}
procedure TOLEStorage.ReadOLEFile(AFileName: string;
AOLEDocument: TOLEDocument);
var
AFileStream: TFileStream;
CurrentSectorPos: Int64;
begin
AOLEDocument.Stream := TMemoryStream.Create;
AFileStream := TFileStream.Create(AFileName, fmOpenRead);
try
// Header
ReadOLEHeader(AFileStream);
// Record 0, the SAT
CurrentSectorPos := $200;
AFileStream.Seek(CurrentSectorPos, soFromBeginning);
ReadSectorAllocationTable(AFileStream);
// Record 1, the directory stream
CurrentSectorPos := $400;
AFileStream.Seek(CurrentSectorPos, soFromBeginning);
ReadDirectoryStream(AFileStream);
// FReadingStreamSize is filled by ReadDirectoryStream
FUseShortSectors := FReadingStreamSize < INT_OLE_MIN_SIZE_FOR_STANDARD_STREAMS;
CurrentSectorPos := $600;
// Record 2, the Short SAT, if exists
if FUseShortSectors then
begin
AFileStream.Seek(CurrentSectorPos, soFromBeginning);
ReadShortSectorAllocationTable(AFileStream);
CurrentSectorPos := $800;
end
else
CurrentSectorPos := $600;
// Records 3 and on (or 2 and on without Short Sectors), the user data
AFileStream.Seek(CurrentSectorPos, soFromBeginning);
ReadUserStream(FOLEDocument.Stream, AFileStream);
finally
AFileStream.Free;
end;
end;
procedure TOLEStorage.FreeOLEDocumentData(AOLEDocument: TOLEDocument);
begin
AOLEDocument.Stream.Free;
end;
end.

View File

@ -76,10 +76,13 @@ type
type
TsCustomSpreadReader = class;
TsCustomSpreadWriter = class;
{@@ TsWorksheet }
{ TsWorksheet }
TsWorksheet = class
private
procedure RemoveCallback(data, arg: pointer);
@ -92,6 +95,9 @@ type
{ Data manipulation methods }
function FindCell(ARow, ACol: Cardinal): PCell;
function GetCell(ARow, ACol: Cardinal): PCell;
function GetCellCount: Cardinal;
function GetCellByIndex(AIndex: Cardinal): PCell;
function ReadAsAnsiText(ARow, ACol: Cardinal): ansistring;
procedure RemoveAllCells;
procedure WriteAnsiText(ARow, ACol: Cardinal; AText: ansistring);
procedure WriteNumber(ARow, ACol: Cardinal; ANumber: double);
@ -100,15 +106,22 @@ type
{@@ TsWorkbook }
{ TsWorkbook }
TsWorkbook = class
private
{ Internal data }
FWorksheets: TFPList;
{ Internal methods }
procedure RemoveCallback(data, arg: pointer);
public
{ Base methods }
constructor Create;
destructor Destroy; override;
function CreateSpreadReader(AFormat: TsSpreadsheetFormat): TsCustomSpreadReader;
function CreateSpreadWriter(AFormat: TsSpreadsheetFormat): TsCustomSpreadWriter;
procedure ReadFromFile(AFileName: string; AFormat: TsSpreadsheetFormat);
procedure ReadFromStream(AStream: TStream; AFormat: TsSpreadsheetFormat);
procedure WriteToFile(AFileName: string; AFormat: TsSpreadsheetFormat);
procedure WriteToStream(AStream: TStream; AFormat: TsSpreadsheetFormat);
{ Worksheet list handling methods }
@ -125,6 +138,8 @@ type
{@@ TsCustomSpreadReader }
{ TsCustomSpreadReader }
TsCustomSpreadReader = class
protected
FWorkbook: TsWorkbook;
@ -132,7 +147,7 @@ type
public
{ General writing methods }
procedure ReadFromFile(AFileName: string; AData: TsWorkbook); virtual;
procedure ReadFromStream(AStream: TStream; AData: TsWorkbook); virtual; abstract;
procedure ReadFromStream(AStream: TStream; AData: TsWorkbook); virtual;
{ Record reading methods }
procedure ReadFormula(AStream: TStream); virtual; abstract;
procedure ReadLabel(AStream: TStream); virtual; abstract;
@ -145,13 +160,15 @@ type
{@@ 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;
procedure WriteToStream(AStream: TStream; AData: TsWorkbook); virtual;
{ 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;
@ -176,6 +193,10 @@ procedure RegisterSpreadFormat(
implementation
var
{ Translatable strings }
lpUnsupportedReadFormat, lpUnsupportedWriteFormat: string;
{@@
Registers a new reader/writer pair for a format
}
@ -293,6 +314,75 @@ begin
end;
end;
{@@
Returns the number of cells in the worksheet with contents.
This routine is used together with GetCellByIndex to
iterate througth all cells in a worksheet efficiently.
@return The number of cells with contents in the worksheet
@see TCell
@see GetCellByIndex
}
function TsWorksheet.GetCellCount: Cardinal;
begin
Result := FCells.Count;
end;
{@@
Obtains the cell with a specific index in the internal list of cells.
The index goes from 0 to GetCellCount - 1.
This routine is used together with GetCellCount to
iterate througth all cells in a worksheet efficiently.
@param AIndex The index of the cell to be obtained
@return A pointer to the cell, or nil if it doesn't exist
@see TCell
@see GetCellCount
}
function TsWorksheet.GetCellByIndex(AIndex: Cardinal): PCell;
begin
if FCells.Count > AIndex then Result := PCell(FCells.Items[AIndex])
else Result := nil;
end;
{@@
Reads the contents of a cell and converts it to a user readable text,
if it isn't already a text.
@param ARow The row of the cell
@param ACol The column of the cell
@return The text representation of the cell
}
function TsWorksheet.ReadAsAnsiText(ARow, ACol: Cardinal): ansistring;
var
ACell: PCell;
begin
ACell := FindCell(ARow, ACol);
if ACell = nil then
begin
Result := '';
Exit;
end;
case ACell^.ContentType of
//cctFormula
cctNumber: Result := FloatToStr(ACell^.NumberValue);
cctString: Result := ACell^.StringValue;
cctWideString: Result := ACell^.WideStringValue;
else
Result := ACell^.StringValue;
end;
end;
{@@
Clears the list of Cells and releases their memory.
}
@ -375,6 +465,10 @@ begin
inherited Create;
FWorksheets := TFPList.Create;
// In the future: add support for translations
lpUnsupportedReadFormat := 'Tryed to read a spreadsheet using an unsupported format';
lpUnsupportedWriteFormat := 'Tryed to write a spreadsheet using an unsupported format';
end;
{@@
@ -389,6 +483,27 @@ begin
inherited Destroy;
end;
{@@
Convenience method which creates the correct
reader object for a given spreadsheet format.
}
function TsWorkbook.CreateSpreadReader(AFormat: TsSpreadsheetFormat): TsCustomSpreadReader;
var
i: Integer;
begin
Result := nil;
for i := 0 to Length(GsSpreadFormats) - 1 do
if GsSpreadFormats[i].Format = AFormat then
begin
Result := GsSpreadFormats[i].ReaderClass.Create;
Break;
end;
if Result = nil then raise Exception.Create(lpUnsupportedReadFormat);
end;
{@@
Convenience method which creates the correct
writer object for a given spreadsheet format.
@ -407,7 +522,41 @@ begin
Break;
end;
if Result = nil then raise Exception.Create('Unsuported spreadsheet format.');
if Result = nil then raise Exception.Create(lpUnsupportedWriteFormat);
end;
{@@
Reads the document from a file.
}
procedure TsWorkbook.ReadFromFile(AFileName: string;
AFormat: TsSpreadsheetFormat);
var
AReader: TsCustomSpreadReader;
begin
AReader := CreateSpreadReader(AFormat);
try
AReader.ReadFromFile(AFileName, Self);
finally
AReader.Free;
end;
end;
{@@
Reads the document from a seekable stream.
}
procedure TsWorkbook.ReadFromStream(AStream: TStream;
AFormat: TsSpreadsheetFormat);
var
AReader: TsCustomSpreadReader;
begin
AReader := CreateSpreadReader(AFormat);
try
AReader.ReadFromStream(AStream, Self);
finally
AReader.Free;
end;
end;
{@@
@ -517,9 +666,34 @@ end;
{ TsCustomSpreadReader }
procedure TsCustomSpreadReader.ReadFromFile(AFileName: string; AData: TsWorkbook);
begin
{@@
Default file reading method.
Opens the file and calls ReadFromStream
@param AFileName The input file name.
@param AData The Workbook to be filled with information from the file.
@see TsWorkbook
}
procedure TsCustomSpreadReader.ReadFromFile(AFileName: string; AData: TsWorkbook);
var
InputFile: TFileStream;
begin
InputFile := TFileStream.Create(AFileName, fmOpenRead);
try
ReadFromStream(InputFile, AData);
finally
InputFile.Free;
end;
end;
{@@
This routine should be overriden in descendent classes.
}
procedure TsCustomSpreadReader.ReadFromStream(AStream: TStream; AData: TsWorkbook);
begin
raise Exception.Create(lpUnsupportedReadFormat);
end;
{ TsCustomSpreadWriter }
@ -580,6 +754,15 @@ begin
end;
end;
{@@
This routine should be overriden in descendent classes.
}
procedure TsCustomSpreadWriter.WriteToStream(AStream: TStream; AData: TsWorkbook);
begin
raise Exception.Create(lpUnsupportedWriteFormat);
end;
finalization
SetLength(GsSpreadFormats, 0);

View File

@ -33,6 +33,21 @@ uses
type
{ TsSpreadBIFF2Reader }
TsSpreadBIFF2Reader = class(TsCustomSpreadReader)
private
RecordSize: Word;
FWorksheet: TsWorksheet;
public
{ General reading methods }
procedure ReadFromStream(AStream: TStream; AData: TsWorkbook); override;
{ Record writing methods }
procedure ReadFormula(AStream: TStream); override;
procedure ReadLabel(AStream: TStream); override;
procedure ReadNumber(AStream: TStream); override;
end;
{ TsSpreadBIFF2Writer }
TsSpreadBIFF2Writer = class(TsCustomSpreadWriter)
@ -274,15 +289,108 @@ begin
AStream.WriteBuffer(AValue, 8);
end;
{ TsSpreadBIFF2Reader }
procedure TsSpreadBIFF2Reader.ReadFromStream(AStream: TStream; AData: TsWorkbook);
var
BIFF2EOF: Boolean;
RecordType: Word;
CurStreamPos: Int64;
begin
BIFF2EOF := False;
{ In BIFF2 files there is only one worksheet, let's create it }
FWorksheet := AData.AddWorksheet('');
{ Read all records in a loop }
while not BIFF2EOF do
begin
{ Read the record header }
RecordType := AStream.ReadWord;
RecordSize := AStream.ReadWord;
CurStreamPos := AStream.Position;
case RecordType of
INT_EXCEL_ID_NUMBER: ReadNumber(AStream);
INT_EXCEL_ID_LABEL: ReadLabel(AStream);
INT_EXCEL_ID_FORMULA: ReadFormula(AStream);
INT_EXCEL_ID_BOF: ;
INT_EXCEL_ID_EOF: BIFF2EOF := True;
else
// nothing
end;
// Make sure we are in the right position for the next record
AStream.Seek(CurStreamPos + RecordSize, soFromBeginning);
if AStream.Position >= AStream.Size then BIFF2EOF := True;
end;
end;
procedure TsSpreadBIFF2Reader.ReadFormula(AStream: TStream);
begin
end;
procedure TsSpreadBIFF2Reader.ReadLabel(AStream: TStream);
var
L: Byte;
ARow, ACol: Word;
AValue: array[0..255] of Char;
AStrValue: ansistring;
begin
{ BIFF Record data }
ARow := AStream.ReadWord();
ACol := AStream.ReadWord();
{ BIFF2 Attributes }
AStream.ReadByte();
AStream.ReadByte();
AStream.ReadByte();
{ String with 8-bit size }
L := AStream.ReadByte();
AStream.ReadBuffer(AValue, L);
AValue[L] := #0;
AStrValue := AValue;
{ Save the data }
FWorksheet.WriteAnsiText(ARow, ACol, AStrValue);
end;
procedure TsSpreadBIFF2Reader.ReadNumber(AStream: TStream);
var
ARow, ACol: Word;
AValue: Double;
begin
{ BIFF Record data }
ARow := AStream.ReadWord();
ACol := AStream.ReadWord();
{ BIFF2 Attributes }
AStream.ReadByte();
AStream.ReadByte();
AStream.ReadByte();
{ IEE 754 floating-point value }
AStream.ReadBuffer(AValue, 8);
{ Save the data }
FWorksheet.WriteNumber(ARow, ACol, AValue);
end;
{*******************************************************************
* Initialization section
*
* Registers this reader / writer on fpSpreadsheet
*
*******************************************************************}
initialization
RegisterSpreadFormat(TsCustomSpreadReader, TsSpreadBIFF2Writer, sfExcel2);
RegisterSpreadFormat(TsSpreadBIFF2Reader, TsSpreadBIFF2Writer, sfExcel2);
end.