fpspreadsheet: Cross-platform OLE code now works for most spreadsheets
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@653 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
parent
5d89c8cf03
commit
111b3f819c
@ -6,7 +6,7 @@
|
||||
<General>
|
||||
<MainUnit Value="0"/>
|
||||
<TargetFileExt Value=".exe"/>
|
||||
<ActiveEditorIndexAtStart Value="4"/>
|
||||
<ActiveEditorIndexAtStart Value="0"/>
|
||||
</General>
|
||||
<VersionInfo>
|
||||
<ProjectVersion Value=""/>
|
||||
@ -30,15 +30,15 @@
|
||||
<PackageName Value="laz_fpspreadsheet"/>
|
||||
</Item1>
|
||||
</RequiredPackages>
|
||||
<Units Count="21">
|
||||
<Units Count="19">
|
||||
<Unit0>
|
||||
<Filename Value="excel5demo.lpr"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="excel5demo"/>
|
||||
<CursorPos X="16" Y="16"/>
|
||||
<TopLine Value="1"/>
|
||||
<CursorPos X="1" Y="33"/>
|
||||
<TopLine Value="28"/>
|
||||
<EditorIndex Value="0"/>
|
||||
<UsageCount Value="112"/>
|
||||
<UsageCount Value="152"/>
|
||||
<Loaded Value="True"/>
|
||||
</Unit0>
|
||||
<Unit1>
|
||||
@ -46,273 +46,262 @@
|
||||
<UnitName Value="fpspreadsheet"/>
|
||||
<CursorPos X="32" Y="414"/>
|
||||
<TopLine Value="388"/>
|
||||
<UsageCount Value="19"/>
|
||||
<UsageCount Value="15"/>
|
||||
</Unit1>
|
||||
<Unit2>
|
||||
<Filename Value="..\xlsbiff5.pas"/>
|
||||
<UnitName Value="xlsbiff5"/>
|
||||
<CursorPos X="16" Y="320"/>
|
||||
<TopLine Value="300"/>
|
||||
<UsageCount Value="19"/>
|
||||
<UsageCount Value="15"/>
|
||||
</Unit2>
|
||||
<Unit3>
|
||||
<Filename Value="..\..\..\..\..\FPC220\source\packages\base\winunits\activex.pp"/>
|
||||
<UnitName Value="ActiveX"/>
|
||||
<CursorPos X="27" Y="29"/>
|
||||
<TopLine Value="6"/>
|
||||
<UsageCount Value="3"/>
|
||||
</Unit3>
|
||||
<Unit4>
|
||||
<Filename Value="..\fpolestorage.pas"/>
|
||||
<UnitName Value="fpolestorage"/>
|
||||
<CursorPos X="1" Y="1"/>
|
||||
<TopLine Value="1"/>
|
||||
<UsageCount Value="39"/>
|
||||
</Unit4>
|
||||
<Unit5>
|
||||
<Filename Value="..\..\..\..\..\FPC220\source\rtl\inc\objpash.inc"/>
|
||||
<CursorPos X="21" Y="141"/>
|
||||
<TopLine Value="131"/>
|
||||
<UsageCount Value="3"/>
|
||||
</Unit5>
|
||||
<Unit6>
|
||||
<UsageCount Value="35"/>
|
||||
</Unit3>
|
||||
<Unit4>
|
||||
<Filename Value="..\xlsbiff2.pas"/>
|
||||
<UnitName Value="xlsbiff2"/>
|
||||
<CursorPos X="20" Y="277"/>
|
||||
<TopLine Value="260"/>
|
||||
<UsageCount Value="12"/>
|
||||
</Unit6>
|
||||
<Unit7>
|
||||
<UsageCount Value="8"/>
|
||||
</Unit4>
|
||||
<Unit5>
|
||||
<Filename Value="..\..\..\..\..\FPC220\source\rtl\objpas\classes\classesh.inc"/>
|
||||
<CursorPos X="22" Y="1602"/>
|
||||
<TopLine Value="1598"/>
|
||||
<UsageCount Value="5"/>
|
||||
</Unit7>
|
||||
<Unit8>
|
||||
<Filename Value="..\..\..\..\..\FPC220\source\rtl\win32\buildrtl.pp"/>
|
||||
<UnitName Value="buildrtl"/>
|
||||
<CursorPos X="29" Y="5"/>
|
||||
<TopLine Value="1"/>
|
||||
<UsageCount Value="3"/>
|
||||
</Unit8>
|
||||
<Unit9>
|
||||
<UsageCount Value="1"/>
|
||||
</Unit5>
|
||||
<Unit6>
|
||||
<Filename Value="..\..\..\..\..\FPC220\source\rtl\objpas\fgl.pp"/>
|
||||
<UnitName Value="fgl"/>
|
||||
<CursorPos X="15" Y="86"/>
|
||||
<TopLine Value="55"/>
|
||||
<UsageCount Value="12"/>
|
||||
</Unit9>
|
||||
<Unit10>
|
||||
<UsageCount Value="8"/>
|
||||
</Unit6>
|
||||
<Unit7>
|
||||
<Filename Value="..\..\..\..\..\lazarus\lcl\interfaces\win32\win32wsstdctrls.pp"/>
|
||||
<UnitName Value="Win32WSStdCtrls"/>
|
||||
<CursorPos X="11" Y="737"/>
|
||||
<TopLine Value="713"/>
|
||||
<EditorIndex Value="8"/>
|
||||
<UsageCount Value="45"/>
|
||||
<EditorIndex Value="9"/>
|
||||
<UsageCount Value="66"/>
|
||||
<Loaded Value="True"/>
|
||||
</Unit10>
|
||||
<Unit11>
|
||||
</Unit7>
|
||||
<Unit8>
|
||||
<Filename Value="..\..\..\..\..\lazarus\lcl\interfaces\win32\win32wscontrols.pp"/>
|
||||
<UnitName Value="Win32WSControls"/>
|
||||
<CursorPos X="13" Y="206"/>
|
||||
<TopLine Value="199"/>
|
||||
<UsageCount Value="6"/>
|
||||
</Unit11>
|
||||
<Unit12>
|
||||
<UsageCount Value="2"/>
|
||||
</Unit8>
|
||||
<Unit9>
|
||||
<Filename Value="..\..\..\..\..\lazarus\components\sqlite\registersqlite3.pas"/>
|
||||
<UnitName Value="registersqlite3"/>
|
||||
<CursorPos X="15" Y="5"/>
|
||||
<TopLine Value="1"/>
|
||||
<UsageCount Value="5"/>
|
||||
</Unit12>
|
||||
<Unit13>
|
||||
<UsageCount Value="1"/>
|
||||
</Unit9>
|
||||
<Unit10>
|
||||
<Filename Value="..\..\..\..\..\lazarus\ideintf\componenteditors.pas"/>
|
||||
<UnitName Value="ComponentEditors"/>
|
||||
<CursorPos X="54" Y="353"/>
|
||||
<TopLine Value="330"/>
|
||||
<EditorIndex Value="7"/>
|
||||
<UsageCount Value="43"/>
|
||||
<EditorIndex Value="8"/>
|
||||
<UsageCount Value="64"/>
|
||||
<Loaded Value="True"/>
|
||||
</Unit13>
|
||||
<Unit14>
|
||||
</Unit10>
|
||||
<Unit11>
|
||||
<Filename Value="..\..\..\..\..\FPC220\source\rtl\objpas\classes\cregist.inc"/>
|
||||
<CursorPos X="17" Y="124"/>
|
||||
<TopLine Value="121"/>
|
||||
<UsageCount Value="5"/>
|
||||
</Unit14>
|
||||
<Unit15>
|
||||
<UsageCount Value="1"/>
|
||||
</Unit11>
|
||||
<Unit12>
|
||||
<Filename Value="..\..\xlsbiff5.pas"/>
|
||||
<UnitName Value="xlsbiff5"/>
|
||||
<CursorPos X="28" Y="62"/>
|
||||
<TopLine Value="59"/>
|
||||
<EditorIndex Value="2"/>
|
||||
<UsageCount Value="41"/>
|
||||
<CursorPos X="1" Y="224"/>
|
||||
<TopLine Value="215"/>
|
||||
<EditorIndex Value="3"/>
|
||||
<UsageCount Value="61"/>
|
||||
<Loaded Value="True"/>
|
||||
</Unit15>
|
||||
<Unit16>
|
||||
</Unit12>
|
||||
<Unit13>
|
||||
<Filename Value="..\..\fpsutils.pas"/>
|
||||
<UnitName Value="fpsutils"/>
|
||||
<CursorPos X="1" Y="49"/>
|
||||
<TopLine Value="30"/>
|
||||
<EditorIndex Value="1"/>
|
||||
<UsageCount Value="41"/>
|
||||
<EditorIndex Value="2"/>
|
||||
<UsageCount Value="61"/>
|
||||
<Loaded Value="True"/>
|
||||
</Unit16>
|
||||
<Unit17>
|
||||
</Unit13>
|
||||
<Unit14>
|
||||
<Filename Value="..\..\xlsbiff2.pas"/>
|
||||
<UnitName Value="xlsbiff2"/>
|
||||
<CursorPos X="1" Y="69"/>
|
||||
<TopLine Value="57"/>
|
||||
<EditorIndex Value="3"/>
|
||||
<UsageCount Value="41"/>
|
||||
<EditorIndex Value="4"/>
|
||||
<UsageCount Value="61"/>
|
||||
<Loaded Value="True"/>
|
||||
</Unit17>
|
||||
<Unit18>
|
||||
</Unit14>
|
||||
<Unit15>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<UnitName Value="fpolestorage"/>
|
||||
<CursorPos X="1" Y="316"/>
|
||||
<TopLine Value="308"/>
|
||||
<EditorIndex Value="4"/>
|
||||
<UsageCount Value="41"/>
|
||||
<CursorPos X="37" Y="381"/>
|
||||
<TopLine Value="367"/>
|
||||
<EditorIndex Value="5"/>
|
||||
<UsageCount Value="61"/>
|
||||
<Loaded Value="True"/>
|
||||
</Unit18>
|
||||
<Unit19>
|
||||
</Unit15>
|
||||
<Unit16>
|
||||
<Filename Value="..\..\..\..\..\lazarus26\fpc\2.2.2\source\rtl\objpas\classes\classesh.inc"/>
|
||||
<CursorPos X="17" Y="724"/>
|
||||
<TopLine Value="714"/>
|
||||
<EditorIndex Value="5"/>
|
||||
<UsageCount Value="11"/>
|
||||
<EditorIndex Value="6"/>
|
||||
<UsageCount Value="31"/>
|
||||
<Loaded Value="True"/>
|
||||
</Unit19>
|
||||
<Unit20>
|
||||
</Unit16>
|
||||
<Unit17>
|
||||
<Filename Value="..\..\..\..\..\lazarus26\fpc\2.2.2\source\rtl\objpas\classes\streams.inc"/>
|
||||
<CursorPos X="1" Y="159"/>
|
||||
<TopLine Value="151"/>
|
||||
<EditorIndex Value="6"/>
|
||||
<EditorIndex Value="7"/>
|
||||
<UsageCount Value="31"/>
|
||||
<Loaded Value="True"/>
|
||||
</Unit17>
|
||||
<Unit18>
|
||||
<Filename Value="..\..\fpspreadsheet.pas"/>
|
||||
<UnitName Value="fpspreadsheet"/>
|
||||
<CursorPos X="1" Y="319"/>
|
||||
<TopLine Value="309"/>
|
||||
<EditorIndex Value="1"/>
|
||||
<UsageCount Value="11"/>
|
||||
<Loaded Value="True"/>
|
||||
</Unit20>
|
||||
</Unit18>
|
||||
</Units>
|
||||
<JumpHistory Count="30" HistoryIndex="29">
|
||||
<Position1>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="51" Column="25" TopLine="34"/>
|
||||
<Filename Value="..\..\fpsutils.pas"/>
|
||||
<Caret Line="45" Column="5" TopLine="26"/>
|
||||
</Position1>
|
||||
<Position2>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="157" Column="21" TopLine="151"/>
|
||||
<Caret Line="150" Column="5" TopLine="131"/>
|
||||
</Position2>
|
||||
<Position3>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="155" Column="5" TopLine="136"/>
|
||||
<Caret Line="191" Column="5" TopLine="172"/>
|
||||
</Position3>
|
||||
<Position4>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="65" Column="3" TopLine="58"/>
|
||||
<Caret Line="49" Column="15" TopLine="39"/>
|
||||
</Position4>
|
||||
<Position5>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="25" Column="11" TopLine="16"/>
|
||||
<Caret Line="331" Column="45" TopLine="326"/>
|
||||
</Position5>
|
||||
<Position6>
|
||||
<Filename Value="..\..\xlsbiff5.pas"/>
|
||||
<Caret Line="194" Column="15" TopLine="60"/>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="24" Column="27" TopLine="19"/>
|
||||
</Position6>
|
||||
<Position7>
|
||||
<Filename Value="..\..\fpsutils.pas"/>
|
||||
<Caret Line="45" Column="5" TopLine="26"/>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="247" Column="1" TopLine="229"/>
|
||||
</Position7>
|
||||
<Position8>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="150" Column="5" TopLine="131"/>
|
||||
<Caret Line="224" Column="5" TopLine="205"/>
|
||||
</Position8>
|
||||
<Position9>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="191" Column="5" TopLine="172"/>
|
||||
<Caret Line="231" Column="1" TopLine="219"/>
|
||||
</Position9>
|
||||
<Position10>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="49" Column="15" TopLine="39"/>
|
||||
<Caret Line="377" Column="5" TopLine="358"/>
|
||||
</Position10>
|
||||
<Position11>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="331" Column="45" TopLine="326"/>
|
||||
<Caret Line="225" Column="1" TopLine="211"/>
|
||||
</Position11>
|
||||
<Position12>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="24" Column="27" TopLine="19"/>
|
||||
<Caret Line="246" Column="12" TopLine="237"/>
|
||||
</Position12>
|
||||
<Position13>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="247" Column="1" TopLine="229"/>
|
||||
<Caret Line="79" Column="16" TopLine="78"/>
|
||||
</Position13>
|
||||
<Position14>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="224" Column="5" TopLine="205"/>
|
||||
<Filename Value="..\..\xlsbiff5.pas"/>
|
||||
<Caret Line="87" Column="16" TopLine="77"/>
|
||||
</Position14>
|
||||
<Position15>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="231" Column="1" TopLine="219"/>
|
||||
<Filename Value="..\..\xlsbiff5.pas"/>
|
||||
<Caret Line="218" Column="24" TopLine="207"/>
|
||||
</Position15>
|
||||
<Position16>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="377" Column="5" TopLine="358"/>
|
||||
<Caret Line="235" Column="30" TopLine="224"/>
|
||||
</Position16>
|
||||
<Position17>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="225" Column="1" TopLine="211"/>
|
||||
<Caret Line="80" Column="28" TopLine="68"/>
|
||||
</Position17>
|
||||
<Position18>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="246" Column="12" TopLine="237"/>
|
||||
<Caret Line="40" Column="5" TopLine="31"/>
|
||||
</Position18>
|
||||
<Position19>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="79" Column="16" TopLine="78"/>
|
||||
<Caret Line="472" Column="49" TopLine="461"/>
|
||||
</Position19>
|
||||
<Position20>
|
||||
<Filename Value="..\..\xlsbiff5.pas"/>
|
||||
<Caret Line="87" Column="16" TopLine="77"/>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="405" Column="5" TopLine="386"/>
|
||||
</Position20>
|
||||
<Position21>
|
||||
<Filename Value="..\..\xlsbiff5.pas"/>
|
||||
<Caret Line="218" Column="24" TopLine="207"/>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="404" Column="14" TopLine="401"/>
|
||||
</Position21>
|
||||
<Position22>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="235" Column="30" TopLine="224"/>
|
||||
<Caret Line="79" Column="42" TopLine="72"/>
|
||||
</Position22>
|
||||
<Position23>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="80" Column="28" TopLine="68"/>
|
||||
<Caret Line="78" Column="31" TopLine="67"/>
|
||||
</Position23>
|
||||
<Position24>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="40" Column="5" TopLine="31"/>
|
||||
<Caret Line="314" Column="39" TopLine="296"/>
|
||||
</Position24>
|
||||
<Position25>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="472" Column="49" TopLine="461"/>
|
||||
<Filename Value="excel5demo.lpr"/>
|
||||
<Caret Line="34" Column="1" TopLine="25"/>
|
||||
</Position25>
|
||||
<Position26>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="405" Column="5" TopLine="386"/>
|
||||
<Filename Value="excel5demo.lpr"/>
|
||||
<Caret Line="35" Column="1" TopLine="25"/>
|
||||
</Position26>
|
||||
<Position27>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="404" Column="14" TopLine="401"/>
|
||||
<Caret Line="479" Column="1" TopLine="469"/>
|
||||
</Position27>
|
||||
<Position28>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="79" Column="42" TopLine="72"/>
|
||||
<Caret Line="470" Column="1" TopLine="460"/>
|
||||
</Position28>
|
||||
<Position29>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="78" Column="31" TopLine="67"/>
|
||||
<Filename Value="..\..\xlsbiff5.pas"/>
|
||||
<Caret Line="217" Column="3" TopLine="205"/>
|
||||
</Position29>
|
||||
<Position30>
|
||||
<Filename Value="..\..\fpolestorage.pas"/>
|
||||
<Caret Line="314" Column="39" TopLine="296"/>
|
||||
<Filename Value="..\..\xlsbiff5.pas"/>
|
||||
<Caret Line="218" Column="23" TopLine="208"/>
|
||||
</Position30>
|
||||
</JumpHistory>
|
||||
</ProjectOptions>
|
||||
|
@ -5,18 +5,17 @@ Writes an OLE document
|
||||
|
||||
AUTHORS: Felipe Monteiro de Carvalho
|
||||
|
||||
Limitations of this unit for creating OLE documents:
|
||||
Properties of this unit for creating OLE documents:
|
||||
|
||||
* Can only create documents with an array of streams. It's not possible
|
||||
* Can only create documents with one stream. It's not possible
|
||||
to create real directory structures like the OLE format supports.
|
||||
This is no problem for most applications.
|
||||
* No limitations interfere with the creation of multi-sheet Excel files
|
||||
|
||||
The Windows only code, which calls COM to write the documents
|
||||
should work very well. It's limitations are:
|
||||
should work very well.
|
||||
|
||||
* Supports only 1 stream in the file
|
||||
|
||||
The cross-platform code at this moment has several limitations,
|
||||
The cross-platform code at this moment has some limitations,
|
||||
but should work for most documents. Some limitations are:
|
||||
|
||||
* Supports only 1 stream in the file
|
||||
@ -52,11 +51,8 @@ type
|
||||
{ Describes an OLE Document }
|
||||
|
||||
TOLEDocument = record
|
||||
// Information about the streams
|
||||
// All arrays here should have the same length
|
||||
// Actually at the time all of them should have length 1
|
||||
Streams: array of TMemoryStream;
|
||||
StreamsNumSectors: array of Cardinal;
|
||||
// Information about the document
|
||||
Stream: TMemoryStream;
|
||||
end;
|
||||
|
||||
|
||||
@ -70,7 +66,9 @@ type
|
||||
{$endif}
|
||||
{ Information filled by the write routines for the helper routines }
|
||||
FOLEDocument: TOLEDocument;
|
||||
FNumStreams, FNumSATSectors, FNumStreamSectors, FNumTotalSectors: Cardinal;
|
||||
FNumSATSectors, FNumStreamSectors, FNumTotalSectors: Cardinal;
|
||||
FNumStreamShortSectors: Cardinal;
|
||||
FUseShortSectors: Boolean;
|
||||
{ Helper routines }
|
||||
procedure WriteOLEHeader(AStream: TStream);
|
||||
procedure WriteSectorAllocationTable(AStream: TStream);
|
||||
@ -92,6 +90,7 @@ const
|
||||
INT_OLE_SECTOR_SIZE = 512; // in bytes
|
||||
INT_OLE_SECTOR_DWORD_SIZE = 512 div 4; // in dwords
|
||||
INT_OLE_SHORT_SECTOR_SIZE = 64; // in bytes
|
||||
INT_OLE_MIN_SIZE_FOR_STANDARD_STREAMS = 4096;
|
||||
|
||||
INT_OLE_DIR_ENTRY_TYPE_EMPTY = 0;
|
||||
INT_OLE_DIR_ENTRY_TYPE_USER_STREAM = 2;
|
||||
@ -138,7 +137,9 @@ begin
|
||||
AStream.WriteWord(WordToLE($0003));
|
||||
|
||||
{ 28 2 Byte order identifier (➜4.2): FEH FFH = Little-Endian
|
||||
FFH FEH = Big-Endian }
|
||||
FFH FEH = Big-Endian
|
||||
|
||||
Real applications only use Little-Endian, so we follow that }
|
||||
AStream.WriteByte($FE);
|
||||
AStream.WriteByte($FF);
|
||||
|
||||
@ -191,38 +192,61 @@ begin
|
||||
for i := 1 to 108 do AStream.WriteDWord($FFFFFFFF);
|
||||
end;
|
||||
|
||||
{
|
||||
The file is organized as following:
|
||||
|
||||
HEADER
|
||||
SECTOR 0 - SAT
|
||||
SECTOR 1 - Directory stream
|
||||
SECTOR 2 - Short SAT
|
||||
SECTOR 3 and on - User data
|
||||
|
||||
And this SAT will describe that.
|
||||
|
||||
This results in the following SecID array for the SAT:
|
||||
|
||||
Array indexes 0 1 2 3 ... N-1 N ...
|
||||
SecID array –3 –1 –2 4 ... -2 -1 ...
|
||||
|
||||
As expected, sector 0 is marked with the special SAT SecID (➜3.1).
|
||||
Sector 1 and all sectors starting with sector 5 are
|
||||
not used (special Free SecID with value –1).
|
||||
}
|
||||
procedure TOLEStorage.WriteSectorAllocationTable(AStream: TStream);
|
||||
var
|
||||
i: Integer;
|
||||
i, CurrentPos, NextSecID: Integer;
|
||||
begin
|
||||
{ Simple copy of an example OLE file
|
||||
{ Example values:
|
||||
|
||||
00000200H FD FF FF FF FF FF FF FF FE FF FF FF 04 00 00 00
|
||||
00000210H FE FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
|
||||
|
||||
And from now on only $FFFFFFFF covering $220 to $3FF
|
||||
for a total of $400 - $220 bytes of $FF }
|
||||
And after that only $FFFFFFFF until $400 }
|
||||
|
||||
AStream.WriteDWord(DWordToLE($FFFFFFFD));
|
||||
AStream.WriteDWord($FFFFFFFF);
|
||||
AStream.WriteDWord(DWordToLE($FFFFFFFE));
|
||||
AStream.WriteDWord(DWordToLE($00000004));
|
||||
AStream.WriteDWord(DWordToLE($FFFFFFFE));
|
||||
AStream.WriteDWord($FFFFFFFF);
|
||||
AStream.WriteDWord($FFFFFFFF);
|
||||
AStream.WriteDWord($FFFFFFFF);
|
||||
AStream.WriteDWord(DWordToLE($FFFFFFFD)); // SAT
|
||||
AStream.WriteDWord($FFFFFFFF); // Empty
|
||||
AStream.WriteDWord(DWordToLE($FFFFFFFE)); // Start and End of Short SAT
|
||||
|
||||
for i := 1 to ($400 - $220) do AStream.WriteByte($FF);
|
||||
CurrentPos := $200 + 12;
|
||||
|
||||
{
|
||||
This results in the following SecID array for the SAT:
|
||||
// Now write the user data
|
||||
|
||||
Array indexes 0 1 2 3 4 5 ...
|
||||
SecID array –3 –1 –2 4 -2 -1 ...
|
||||
NextSecID := $00000004;
|
||||
|
||||
As expected, sector 0 is marked with the special SAT SecID (➜3.1).
|
||||
Sector 1 and all sectors starting with sector 5 are
|
||||
not used (special Free SecID with value –1). }
|
||||
for i := 2 to FNumStreamSectors do
|
||||
begin
|
||||
AStream.WriteDWord(DWordToLE(NextSecID));
|
||||
Inc(NextSecID);
|
||||
CurrentPos := CurrentPos + 4;
|
||||
end;
|
||||
|
||||
AStream.WriteDWord(DWordToLE($FFFFFFFE)); // End of user data
|
||||
|
||||
CurrentPos := CurrentPos + 4;
|
||||
|
||||
// Fill the rest of the sector with $FF
|
||||
|
||||
for i := 1 to ($400 - CurrentPos) do AStream.WriteByte($FF);
|
||||
end;
|
||||
|
||||
{
|
||||
@ -258,9 +282,6 @@ begin
|
||||
Item #3 e #4
|
||||
00000540H 00 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF
|
||||
|
||||
Root Storage #5
|
||||
00000640H 16 00 05 00 FF FF FF FF FF FF FF FF 01 00 00 00
|
||||
|
||||
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)
|
||||
@ -322,19 +343,16 @@ begin
|
||||
Item #3 e #4
|
||||
00000570H XX XX XX XX 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
|
||||
Root Storage #5
|
||||
00000670H XX XX XX XX 03 00 00 00 40 03 00 00 00 00 00 00
|
||||
|
||||
Book #6
|
||||
000004F0H XX XX XX XX 00 00 00 00 3F 03 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
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@ -347,14 +365,20 @@ begin
|
||||
end;
|
||||
|
||||
procedure TOLEStorage.WriteDirectoryStream(AStream: TStream);
|
||||
var
|
||||
FContainerSize: Cardinal;
|
||||
begin
|
||||
{ Size of the container stream }
|
||||
|
||||
FContainerSize := Ceil(FOLEDocument.Stream.Size / INT_OLE_SECTOR_SIZE) * INT_OLE_SECTOR_SIZE;
|
||||
|
||||
WriteDirectoryEntry(AStream, 'Root Entry'#0,
|
||||
INT_OLE_DIR_ENTRY_TYPE_ROOT_STORAGE, INT_OLE_DIR_COLOR_RED,
|
||||
True, $00000340);
|
||||
True, FContainerSize);
|
||||
|
||||
WriteDirectoryEntry(AStream, 'Book'#0,
|
||||
INT_OLE_DIR_ENTRY_TYPE_USER_STREAM, INT_OLE_DIR_COLOR_BLACK,
|
||||
False, $0000033F);
|
||||
False, FOLEDocument.Stream.Size);
|
||||
|
||||
WriteDirectoryEntry(AStream, #0,
|
||||
INT_OLE_DIR_ENTRY_TYPE_EMPTY, INT_OLE_DIR_COLOR_RED,
|
||||
@ -386,29 +410,22 @@ All short-sectors starting with sector 54 are not used (special Free SecID with
|
||||
}
|
||||
procedure TOLEStorage.WriteShortSectorAllocationTable(AStream: TStream);
|
||||
var
|
||||
i: Integer;
|
||||
i, NextShortSecID, CurrentPos: Integer;
|
||||
begin
|
||||
AStream.WriteDWord(DWordToLE($00000001));
|
||||
AStream.WriteDWord(DWordToLE($00000002));
|
||||
AStream.WriteDWord(DWordToLE($00000003));
|
||||
AStream.WriteDWord(DWordToLE($00000004));
|
||||
CurrentPos := $800;
|
||||
NextShortSecID := $00000001;
|
||||
|
||||
AStream.WriteDWord(DWordToLE($00000005));
|
||||
AStream.WriteDWord(DWordToLE($00000006));
|
||||
AStream.WriteDWord(DWordToLE($00000007));
|
||||
AStream.WriteDWord(DWordToLE($00000008));
|
||||
|
||||
AStream.WriteDWord(DWordToLE($00000009));
|
||||
AStream.WriteDWord(DWordToLE($0000000A));
|
||||
AStream.WriteDWord(DWordToLE($0000000B));
|
||||
AStream.WriteDWord(DWordToLE($0000000C));
|
||||
for i := 2 to FNumStreamShortSectors do
|
||||
begin
|
||||
AStream.WriteDWord(DWordToLE(NextShortSecID));
|
||||
Inc(NextShortSecID);
|
||||
Inc(CurrentPos, 4);
|
||||
end;
|
||||
|
||||
AStream.WriteDWord(DWordToLE($FFFFFFFE));
|
||||
AStream.WriteDWord(DWordToLE($FFFFFFFF));
|
||||
AStream.WriteDWord(DWordToLE($FFFFFFFF));
|
||||
AStream.WriteDWord(DWordToLE($FFFFFFFF));
|
||||
Inc(CurrentPos, 4);
|
||||
|
||||
for i := 1 to ($A00 - $840) do AStream.WriteByte($FF);
|
||||
for i := 1 to ($A00 - CurrentPos) do AStream.WriteByte($FF);
|
||||
end;
|
||||
|
||||
procedure TOLEStorage.WriteUserStream(ADest, ASource: TStream);
|
||||
@ -443,23 +460,23 @@ var
|
||||
begin
|
||||
{ Fill information for helper routines }
|
||||
FOLEDocument := AOLEDocument;
|
||||
FNumStreams := Length(AOLEDocument.Streams);
|
||||
|
||||
{ Calculate the number of sectors necessary for each stream }
|
||||
SetLength(FOLEDocument.StreamsNumSectors, FNumStreams);
|
||||
{ Calculate the number of sectors necessary for the stream }
|
||||
|
||||
FNumStreamSectors := 0;
|
||||
FNumStreamSectors := Ceil(AOLEDocument.Stream.Size / INT_OLE_SECTOR_SIZE);
|
||||
|
||||
for i := 0 to FNumStreams - 1 do
|
||||
begin
|
||||
x := Ceil(AOLEDocument.Streams[i].Size / INT_OLE_SECTOR_SIZE);
|
||||
FOLEDocument.StreamsNumSectors[i] := x;
|
||||
FNumStreamSectors := FNumStreamSectors + x;
|
||||
end;
|
||||
{ Calculates the number of short sectors for the stream, if it applies }
|
||||
|
||||
FUseShortSectors := AOLEDocument.Stream.Size < INT_OLE_MIN_SIZE_FOR_STANDARD_STREAMS;
|
||||
|
||||
FNumStreamShortSectors := Ceil(AOLEDocument.Stream.Size / INT_OLE_SHORT_SECTOR_SIZE);
|
||||
|
||||
{ Numbers of sectors necessary for the SAT }
|
||||
|
||||
FNumSATSectors := 1; // Ceil(FNumStreamSectors / INT_OLE_SECTOR_DWORD_SIZE);
|
||||
|
||||
{$ifdef FPOLESTORAGE_USE_COM}
|
||||
|
||||
{ Initialize the Component Object Model (COM) before calling s functions }
|
||||
OleCheck(CoInitialize(nil));
|
||||
|
||||
@ -468,18 +485,17 @@ begin
|
||||
STGM_READWRITE or STGM_FAILIFTHERE or STGM_SHARE_EXCLUSIVE or STGM_DIRECT,
|
||||
0, FStorage));
|
||||
|
||||
for i := 0 to FNumStreams - 1 do
|
||||
begin
|
||||
{ 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));
|
||||
{ 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(FOLEDocument.Stream.Memory,
|
||||
FOLEDocument.Stream.Size, @cbWritten);
|
||||
|
||||
{ Write all data }
|
||||
FStream.Write(FOLEDocument.Streams[i].Memory,
|
||||
FOLEDocument.Streams[i].Size, @cbWritten);
|
||||
end;
|
||||
{$else}
|
||||
|
||||
AFileStream := TFileStream.Create(AFileName, fmOpenWrite or fmCreate);
|
||||
try
|
||||
// Header
|
||||
@ -495,10 +511,11 @@ begin
|
||||
WriteShortSectorAllocationTable(AFileStream);
|
||||
|
||||
// Records 3 and on, the user data
|
||||
WriteUserStream(AFileStream, FOLEDocument.Streams[0]);
|
||||
WriteUserStream(AFileStream, FOLEDocument.Stream);
|
||||
finally
|
||||
AFileStream.Free;
|
||||
end;
|
||||
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
|
@ -213,16 +213,14 @@ begin
|
||||
OutputStorage := TOLEStorage.Create;
|
||||
try
|
||||
WriteToStream(MemStream, AData);
|
||||
|
||||
SetLength(OLEDocument.Streams, 1);
|
||||
OLEDocument.Streams[0] := MemStream;
|
||||
|
||||
// Only one stream is necessary for any number of worksheets
|
||||
OLEDocument.Stream := MemStream;
|
||||
|
||||
OutputStorage.WriteOLEFile(AFileName, OLEDocument);
|
||||
finally
|
||||
MemStream.Free;
|
||||
OutputStorage.Free;
|
||||
|
||||
SetLength(OLEDocument.Streams, 0);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -302,6 +300,7 @@ begin
|
||||
|
||||
WriteStyle(AStream);
|
||||
|
||||
// A BOUNDSHEET for each worksheet
|
||||
for i := 0 to AData.GetWorksheetCount - 1 do
|
||||
begin
|
||||
len := Length(Boundsheets);
|
||||
|
Loading…
Reference in New Issue
Block a user