fpspreadsheet: Improves reading excel 5 files

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@658 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
sekelsenmat
2009-01-11 11:11:54 +00:00
parent 1d2b67596d
commit 63fc6d8da1
2 changed files with 186 additions and 83 deletions

View File

@ -34,13 +34,13 @@
<PackageName Value="laz_fpspreadsheet"/>
</Item1>
</RequiredPackages>
<Units Count="13">
<Units Count="15">
<Unit0>
<Filename Value="excel5read.lpr"/>
<IsPartOfProject Value="True"/>
<UnitName Value="excel5read"/>
<CursorPos X="16" Y="38"/>
<TopLine Value="30"/>
<CursorPos X="20" Y="30"/>
<TopLine Value="21"/>
<EditorIndex Value="0"/>
<UsageCount Value="309"/>
<Loaded Value="True"/>
@ -69,8 +69,8 @@
<Unit4>
<Filename Value="..\..\xlsbiff5.pas"/>
<UnitName Value="xlsbiff5"/>
<CursorPos X="1" Y="910"/>
<TopLine Value="904"/>
<CursorPos X="53" Y="913"/>
<TopLine Value="903"/>
<EditorIndex Value="3"/>
<UsageCount Value="140"/>
<Loaded Value="True"/>
@ -78,8 +78,8 @@
<Unit5>
<Filename Value="..\..\fpsutils.pas"/>
<UnitName Value="fpsutils"/>
<CursorPos X="1" Y="49"/>
<TopLine Value="30"/>
<CursorPos X="16" Y="10"/>
<TopLine Value="1"/>
<EditorIndex Value="2"/>
<UsageCount Value="140"/>
<Loaded Value="True"/>
@ -117,10 +117,10 @@
<Unit10>
<Filename Value="..\..\fpspreadsheet.pas"/>
<UnitName Value="fpspreadsheet"/>
<CursorPos X="47" Y="149"/>
<TopLine Value="133"/>
<CursorPos X="5" Y="181"/>
<TopLine Value="171"/>
<EditorIndex Value="1"/>
<UsageCount Value="92"/>
<UsageCount Value="94"/>
<Loaded Value="True"/>
</Unit10>
<Unit11>
@ -135,127 +135,141 @@
<TopLine Value="144"/>
<UsageCount Value="10"/>
</Unit12>
<Unit13>
<Filename Value="..\..\..\..\..\lazarus\lcl\stdctrls.pp"/>
<UnitName Value="StdCtrls"/>
<CursorPos X="19" Y="665"/>
<TopLine Value="662"/>
<UsageCount Value="10"/>
</Unit13>
<Unit14>
<Filename Value="..\..\..\..\..\lazarus\lcl\controls.pp"/>
<UnitName Value="Controls"/>
<CursorPos X="20" Y="1513"/>
<TopLine Value="1508"/>
<UsageCount Value="10"/>
</Unit14>
</Units>
<JumpHistory Count="30" HistoryIndex="29">
<Position1>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="119" Column="67" TopLine="108"/>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="895" Column="1" TopLine="885"/>
</Position1>
<Position2>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="485" Column="42" TopLine="474"/>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="908" Column="1" TopLine="898"/>
</Position2>
<Position3>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="161" Column="3" TopLine="159"/>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="910" Column="1" TopLine="900"/>
</Position3>
<Position4>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="141" Column="3" TopLine="139"/>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="913" Column="1" TopLine="903"/>
</Position4>
<Position5>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="669" Column="20" TopLine="658"/>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="911" Column="1" TopLine="900"/>
</Position5>
<Position6>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="158" Column="15" TopLine="143"/>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="912" Column="1" TopLine="902"/>
</Position6>
<Position7>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="116" Column="71" TopLine="106"/>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="915" Column="1" TopLine="905"/>
</Position7>
<Position8>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="886" Column="1" TopLine="876"/>
<Caret Line="918" Column="1" TopLine="908"/>
</Position8>
<Position9>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="888" Column="1" TopLine="878"/>
<Caret Line="919" Column="1" TopLine="909"/>
</Position9>
<Position10>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="891" Column="1" TopLine="881"/>
<Caret Line="921" Column="1" TopLine="911"/>
</Position10>
<Position11>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="894" Column="1" TopLine="884"/>
<Caret Line="923" Column="1" TopLine="913"/>
</Position11>
<Position12>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="895" Column="1" TopLine="885"/>
<Caret Line="918" Column="1" TopLine="908"/>
</Position12>
<Position13>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="897" Column="1" TopLine="887"/>
<Caret Line="921" Column="1" TopLine="911"/>
</Position13>
<Position14>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="899" Column="1" TopLine="889"/>
<Caret Line="913" Column="3" TopLine="919"/>
</Position14>
<Position15>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="904" Column="14" TopLine="895"/>
<Caret Line="924" Column="1" TopLine="914"/>
</Position15>
<Position16>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="768" Column="1" TopLine="765"/>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="926" Column="1" TopLine="916"/>
</Position16>
<Position17>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="886" Column="1" TopLine="876"/>
<Caret Line="918" Column="1" TopLine="910"/>
</Position17>
<Position18>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="888" Column="1" TopLine="878"/>
<Caret Line="886" Column="1" TopLine="867"/>
</Position18>
<Position19>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="891" Column="1" TopLine="881"/>
<Caret Line="889" Column="1" TopLine="876"/>
</Position19>
<Position20>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="886" Column="1" TopLine="867"/>
<Caret Line="68" Column="24" TopLine="58"/>
</Position20>
<Position21>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="894" Column="1" TopLine="882"/>
<Caret Line="887" Column="1" TopLine="882"/>
</Position21>
<Position22>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="64" Column="41" TopLine="60"/>
<Caret Line="64" Column="37" TopLine="55"/>
</Position22>
<Position23>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="70" Column="24" TopLine="60"/>
<Caret Line="934" Column="5" TopLine="915"/>
</Position23>
<Position24>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="797" Column="16" TopLine="784"/>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="941" Column="23" TopLine="925"/>
</Position24>
<Position25>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="670" Column="37" TopLine="655"/>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="72" Column="25" TopLine="62"/>
</Position25>
<Position26>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="666" Column="13" TopLine="659"/>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="499" Column="45" TopLine="486"/>
</Position26>
<Position27>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="895" Column="1" TopLine="885"/>
<Caret Line="948" Column="1" TopLine="946"/>
</Position27>
<Position28>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="908" Column="1" TopLine="898"/>
<Caret Line="994" Column="12" TopLine="981"/>
</Position28>
<Position29>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="910" Column="1" TopLine="900"/>
<Caret Line="891" Column="1" TopLine="872"/>
</Position29>
<Position30>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="913" Column="1" TopLine="903"/>
<Caret Line="70" Column="15" TopLine="60"/>
</Position30>
</JumpHistory>
</ProjectOptions>
@ -270,12 +284,4 @@
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
<Debugging>
<BreakPoints Count="1">
<Item1>
<Source Value="..\..\xlsbiff5.pas"/>
<Line Value="910"/>
</Item1>
</BreakPoints>
</Debugging>
</CONFIG>

View File

@ -65,6 +65,11 @@ type
private
RecordSize: Word;
FWorksheet: TsWorksheet;
FWorksheetNames: TStringList;
FCurrentWorksheet: Integer;
procedure ReadWorkbookGlobals(AStream: TStream; AData: TsWorkbook);
procedure ReadWorksheet(AStream: TStream; AData: TsWorkbook);
procedure ReadBoundsheet(AStream: TStream);
public
{ General reading methods }
procedure ReadFromFile(AFileName: string; AData: TsWorkbook); override;
@ -878,6 +883,96 @@ end;
{ TsSpreadBIFF5Reader }
procedure TsSpreadBIFF5Reader.ReadWorkbookGlobals(AStream: TStream;
AData: TsWorkbook);
var
SectionEOF: Boolean = False;
RecordType: Word;
CurStreamPos: Int64;
begin
while (not SectionEOF) do
begin
{ Read the record header }
RecordType := WordLEToN(AStream.ReadWord);
RecordSize := WordLEToN(AStream.ReadWord);
CurStreamPos := AStream.Position;
case RecordType of
INT_EXCEL_ID_BOF: ;
INT_EXCEL_ID_BOUNDSHEET: ReadBoundSheet(AStream);
INT_EXCEL_ID_EOF: SectionEOF := True;
else
// nothing
end;
// Make sure we are in the right position for the next record
AStream.Seek(CurStreamPos + RecordSize, soFromBeginning);
// Check for the end of the file
if AStream.Position >= AStream.Size then SectionEOF := True;
end;
end;
procedure TsSpreadBIFF5Reader.ReadWorksheet(AStream: TStream; AData: TsWorkbook);
var
SectionEOF: Boolean = False;
RecordType: Word;
CurStreamPos: Int64;
begin
FWorksheet := AData.AddWorksheet(FWorksheetNames.Strings[FCurrentWorksheet]);
while (not SectionEOF) do
begin
{ Read the record header }
RecordType := WordLEToN(AStream.ReadWord);
RecordSize := WordLEToN(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: SectionEOF := True;
else
// nothing
end;
// Make sure we are in the right position for the next record
AStream.Seek(CurStreamPos + RecordSize, soFromBeginning);
// Check for the end of the file
if AStream.Position >= AStream.Size then SectionEOF := True;
end;
end;
procedure TsSpreadBIFF5Reader.ReadBoundsheet(AStream: TStream);
var
Len: Byte;
Str: array[0..255] of Char;
begin
{ Absolute stream position of the BOF record of the sheet represented
by this record }
// Just assume that they are in order
AStream.ReadDWord();
{ Visibility }
AStream.ReadByte();
{ Sheet type }
AStream.ReadByte();
{ Sheet name: Byte string, 8-bit length }
Len := AStream.ReadByte();
AStream.ReadBuffer(Str, Len);
Str[Len] := #0;
FWorksheetNames.Add(Str);
end;
procedure TsSpreadBIFF5Reader.ReadFromFile(AFileName: string; AData: TsWorkbook);
var
MemStream: TMemoryStream;
@ -895,6 +990,9 @@ begin
// Rewind the stream and read from it
MemStream.Position := 0;
ReadFromStream(MemStream, AData);
// Uncomment to verify if the data was correctly optained from the OLE file
// MemStream.SaveToFile(SysUtils.ChangeFileExt(AFileName, 'bin.xls'));
finally
MemStream.Free;
OLEStorage.Free;
@ -904,38 +1002,37 @@ end;
procedure TsSpreadBIFF5Reader.ReadFromStream(AStream: TStream; AData: TsWorkbook);
var
BIFF5EOF: Boolean;
RecordType: Word;
CurStreamPos: Int64;
begin
{ Initializations }
FWorksheetNames := TStringList.Create;
FWorksheetNames.Clear;
FCurrentWorksheet := 0;
BIFF5EOF := False;
FWorksheet := AData.AddWorksheet('');
{ Read workbook globals }
{ Read all records in a loop }
while not BIFF5EOF do
ReadWorkbookGlobals(AStream, AData);
// Check for the end of the file
if AStream.Position >= AStream.Size then BIFF5EOF := True;
{ Now read all worksheets }
while (not BIFF5EOF) do
begin
{ Read the record header }
RecordType := WordLEToN(AStream.ReadWord);
RecordSize := WordLEToN(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: BIFF5EOF := True;
else
// nothing
end;
// Make sure we are in the right position for the next record
AStream.Seek(CurStreamPos + RecordSize, soFromBeginning);
ReadWorksheet(AStream, AData);
// Check for the end of the file
if AStream.Position >= AStream.Size then BIFF5EOF := True;
// Final preparations
Inc(FCurrentWorksheet);
end;
{ Finalizations }
FWorksheetNames.Free;
end;
procedure TsSpreadBIFF5Reader.ReadFormula(AStream: TStream);