diff --git a/components/fpspreadsheet/examples/excel2demo/excel2read.lpi b/components/fpspreadsheet/examples/excel2demo/excel2read.lpi
index a620de222..607bca344 100644
--- a/components/fpspreadsheet/examples/excel2demo/excel2read.lpi
+++ b/components/fpspreadsheet/examples/excel2demo/excel2read.lpi
@@ -10,7 +10,7 @@
-
+
@@ -69,8 +69,8 @@
-
-
+
+
@@ -78,8 +78,8 @@
-
-
+
+
@@ -87,8 +87,8 @@
-
-
+
+
@@ -96,8 +96,8 @@
-
-
+
+
@@ -120,7 +120,7 @@
-
+
@@ -139,123 +139,123 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
+
-
+
-
-
+
+
-
-
+
+
diff --git a/components/fpspreadsheet/examples/excel5demo/excel5read.lpi b/components/fpspreadsheet/examples/excel5demo/excel5read.lpi
index 62ada40a3..e1a456364 100644
--- a/components/fpspreadsheet/examples/excel5demo/excel5read.lpi
+++ b/components/fpspreadsheet/examples/excel5demo/excel5read.lpi
@@ -10,7 +10,7 @@
-
+
@@ -39,8 +39,8 @@
-
-
+
+
@@ -69,8 +69,8 @@
-
-
+
+
@@ -87,8 +87,8 @@
-
-
+
+
@@ -96,8 +96,8 @@
-
-
+
+
@@ -117,8 +117,8 @@
-
-
+
+
@@ -138,124 +138,124 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -270,4 +270,12 @@
+
+
+
+
+
+
+
+
diff --git a/components/fpspreadsheet/examples/excel5demo/excel5read.lpr b/components/fpspreadsheet/examples/excel5demo/excel5read.lpr
index 044527a24..c4625a342 100644
--- a/components/fpspreadsheet/examples/excel5demo/excel5read.lpr
+++ b/components/fpspreadsheet/examples/excel5demo/excel5read.lpr
@@ -36,7 +36,7 @@ begin
WriteLn('Contents of the first worksheet of the file:');
WriteLn('');
- for i := 0 to MyWorksheet.GetCellCount do
+ for i := 0 to MyWorksheet.GetCellCount - 1 do
begin
CurCell := MyWorkSheet.GetCellByIndex(i);
WriteLn('Row: ', CurCell^.Row, ' Col: ', CurCell^.Col, ' Value: ',
diff --git a/components/fpspreadsheet/fpolestorage.pas b/components/fpspreadsheet/fpolestorage.pas
index fc551193e..b1566149e 100755
--- a/components/fpspreadsheet/fpolestorage.pas
+++ b/components/fpspreadsheet/fpolestorage.pas
@@ -623,7 +623,7 @@ begin
AStream.ReadDWord();
AStream.ReadDWord();
- AIsStorage := AStream.ReadDWord() <> $FFFFFFFF;
+ AIsStorage := DWordLEtoN(AStream.ReadDWord) <> $FFFFFFFF;
{Root Storage #1
00000470H XX XX XX XX 03 00 00 00 40 03 00 00 00 00 00 00
@@ -649,9 +649,9 @@ begin
AStream.Seek(BaseAddr + $74, soFromBeginning);
- AFirstSecID := AStream.ReadDWord();
+ AFirstSecID := DWordLEtoN(AStream.ReadDWord);
- AStreamSize := AStream.ReadDWord();
+ AStreamSize := DWordLEtoN(AStream.ReadDWord);
AStream.ReadDWord();
end;
@@ -662,8 +662,12 @@ begin
end;
procedure TOLEStorage.ReadUserStream(ADest, ASource: TStream);
+var
+ i: Integer;
begin
- ADest.CopyFrom(ASource, FReadingStreamSize);
+// ADest.CopyFrom(ASource, FReadingStreamSize);
+ for i := 1 to FReadingStreamSize do
+ ADest.WriteByte(ASource.ReadByte);
end;
constructor TOLEStorage.Create;
@@ -753,7 +757,7 @@ begin
end;
{@@
- Reads an OLE file. Experimental
+ Reads an OLE file.
}
procedure TOLEStorage.ReadOLEFile(AFileName: string;
AOLEDocument: TOLEDocument);
@@ -761,6 +765,7 @@ var
AFileStream: TFileStream;
CurrentSectorPos: Int64;
begin
+ FOLEDocument := AOLEDocument;
AOLEDocument.Stream := TMemoryStream.Create;
AFileStream := TFileStream.Create(AFileName, fmOpenRead);
try
@@ -800,9 +805,12 @@ begin
end;
end;
+{@@
+ Frees all internal objects storable in a TOLEDocument structure
+}
procedure TOLEStorage.FreeOLEDocumentData(AOLEDocument: TOLEDocument);
begin
- AOLEDocument.Stream.Free;
+ if Assigned(AOLEDocument.Stream) then FreeAndNil(AOLEDocument.Stream);
end;
end.
diff --git a/components/fpspreadsheet/fpsutils.pas b/components/fpspreadsheet/fpsutils.pas
index fcb7b548c..81aa77861 100644
--- a/components/fpspreadsheet/fpsutils.pas
+++ b/components/fpspreadsheet/fpsutils.pas
@@ -11,6 +11,9 @@ function WordToLE(AValue: Word): Word;
function DWordToLE(AValue: Cardinal): Cardinal;
function IntegerToLE(AValue: Integer): Integer;
+function WordLEtoN(AValue: Word): Word;
+function DWordLEtoN(AValue: Cardinal): Cardinal;
+
implementation
{
@@ -19,12 +22,19 @@ implementation
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.
+
+ These routines are preferable to System unit routines because they
+ ensure that the correct overloaded version of the conversion routines
+ will be used, avoiding typecasts which are less readable.
+
+ They also guarantee delphi compatibility. For Delphi we just support
+ big-endian isn't support, because Delphi doesn't support it.
}
function WordToLE(AValue: Word): Word;
begin
- {$IFDEF BIG_ENDIAN}
- Result := ((AValue shl 8) and $FF00) or ((AValue shr 8) and $00FF);
+ {$IFDEF FPC}
+ Result := NtoLE(AValue);
{$ELSE}
Result := AValue;
{$ENDIF}
@@ -32,8 +42,8 @@ end;
function DWordToLE(AValue: Cardinal): Cardinal;
begin
- {$IFDEF BIG_ENDIAN}
-// ?? Result := ((AValue shl 8) and $FF00) or ((AValue shr 8) and $00FF);
+ {$IFDEF FPC}
+ Result := NtoLE(AValue);
{$ELSE}
Result := AValue;
{$ENDIF}
@@ -41,8 +51,26 @@ end;
function IntegerToLE(AValue: Integer): Integer;
begin
- {$IFDEF BIG_ENDIAN}
-// ?? Result := ((AValue shl 8) and $FF00) or ((AValue shr 8) and $00FF);
+ {$IFDEF FPC}
+ Result := NtoLE(AValue);
+ {$ELSE}
+ Result := AValue;
+ {$ENDIF}
+end;
+
+function WordLEtoN(AValue: Word): Word;
+begin
+ {$IFDEF FPC}
+ Result := LEtoN(AValue);
+ {$ELSE}
+ Result := AValue;
+ {$ENDIF}
+end;
+
+function DWordLEtoN(AValue: Cardinal): Cardinal;
+begin
+ {$IFDEF FPC}
+ Result := LEtoN(AValue);
{$ELSE}
Result := AValue;
{$ENDIF}
diff --git a/components/fpspreadsheet/xlsbiff2.pas b/components/fpspreadsheet/xlsbiff2.pas
index a15f5b754..bfc2a0b31 100755
--- a/components/fpspreadsheet/xlsbiff2.pas
+++ b/components/fpspreadsheet/xlsbiff2.pas
@@ -306,8 +306,8 @@ begin
while not BIFF2EOF do
begin
{ Read the record header }
- RecordType := AStream.ReadWord;
- RecordSize := AStream.ReadWord;
+ RecordType := WordLEToN(AStream.ReadWord);
+ RecordSize := WordLEToN(AStream.ReadWord);
CurStreamPos := AStream.Position;
@@ -342,8 +342,8 @@ var
AStrValue: ansistring;
begin
{ BIFF Record data }
- ARow := AStream.ReadWord();
- ACol := AStream.ReadWord();
+ ARow := WordLEToN(AStream.ReadWord);
+ ACol := WordLEToN(AStream.ReadWord);
{ BIFF2 Attributes }
AStream.ReadByte();
@@ -366,8 +366,8 @@ var
AValue: Double;
begin
{ BIFF Record data }
- ARow := AStream.ReadWord();
- ACol := AStream.ReadWord();
+ ARow := WordLEToN(AStream.ReadWord);
+ ACol := WordLEToN(AStream.ReadWord);
{ BIFF2 Attributes }
AStream.ReadByte();
diff --git a/components/fpspreadsheet/xlsbiff5.pas b/components/fpspreadsheet/xlsbiff5.pas
index b138a40f5..32df68798 100755
--- a/components/fpspreadsheet/xlsbiff5.pas
+++ b/components/fpspreadsheet/xlsbiff5.pas
@@ -59,6 +59,22 @@ uses
type
+ { TsSpreadBIFF5Reader }
+
+ TsSpreadBIFF5Reader = class(TsCustomSpreadReader)
+ private
+ RecordSize: Word;
+ FWorksheet: TsWorksheet;
+ public
+ { General reading methods }
+ procedure ReadFromFile(AFileName: string; AData: TsWorkbook); override;
+ 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;
+
{ TsSpreadBIFF5Writer }
TsSpreadBIFF5Writer = class(TsCustomSpreadWriter)
@@ -859,9 +875,101 @@ end;
* Registers this reader / writer on fpSpreadsheet
*
*******************************************************************}
+
+{ TsSpreadBIFF5Reader }
+
+procedure TsSpreadBIFF5Reader.ReadFromFile(AFileName: string; AData: TsWorkbook);
+var
+ MemStream: TMemoryStream;
+ OLEStorage: TOLEStorage;
+ OLEDocument: TOLEDocument;
+begin
+ MemStream := TMemoryStream.Create;
+ OLEStorage := TOLEStorage.Create;
+ try
+ // Only one stream is necessary for any number of worksheets
+ OLEDocument.Stream := MemStream;
+
+ OLEStorage.ReadOLEFile(AFileName, OLEDocument);
+
+ // Rewind the stream and read from it
+ MemStream.Position := 0;
+ ReadFromStream(MemStream, AData);
+ finally
+ MemStream.Free;
+ OLEStorage.Free;
+ end;
+end;
+
+procedure TsSpreadBIFF5Reader.ReadFromStream(AStream: TStream; AData: TsWorkbook);
+var
+ BIFF5EOF: Boolean;
+ RecordType: Word;
+ CurStreamPos: Int64;
+begin
+ BIFF5EOF := False;
+
+ FWorksheet := AData.AddWorksheet('');
+
+ { Read all records in a loop }
+ 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);
+
+ if AStream.Position >= AStream.Size then BIFF5EOF := True;
+ end;
+end;
+
+procedure TsSpreadBIFF5Reader.ReadFormula(AStream: TStream);
+begin
+
+end;
+
+procedure TsSpreadBIFF5Reader.ReadLabel(AStream: TStream);
+begin
+
+end;
+
+procedure TsSpreadBIFF5Reader.ReadNumber(AStream: TStream);
+var
+ ARow, ACol: Word;
+ AValue: Double;
+begin
+ { BIFF Record data }
+ ARow := WordLEToN(AStream.ReadWord);
+ ACol := WordLEToN(AStream.ReadWord);
+
+ { Index to XF record }
+ AStream.ReadWord();
+
+ { IEE 754 floating-point value }
+ AStream.ReadBuffer(AValue, 8);
+
+ { Save the data }
+ FWorksheet.WriteNumber(ARow, ACol, AValue);
+end;
+
initialization
- RegisterSpreadFormat(TsCustomSpreadReader, TsSpreadBIFF5Writer, sfExcel5);
+ RegisterSpreadFormat(TsSpreadBIFF5Reader, TsSpreadBIFF5Writer, sfExcel5);
end.