fpspreadsheet/formulas with 3d references: Implement BIFF5 reader for 3d references. Some DebugLn insertions for better debugging (triggered by define FPSpreadDebug).
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@6400 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
parent
bfb8cff66e
commit
74c64b7258
@ -34,9 +34,6 @@ unit fpsopendocument;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
{$IFDEF FPSpreadDebug}
|
|
||||||
LazLogger,
|
|
||||||
{$ENDIF}
|
|
||||||
Classes, SysUtils,
|
Classes, SysUtils,
|
||||||
laz2_xmlread, laz2_DOM,
|
laz2_xmlread, laz2_DOM,
|
||||||
avglvltree, math, dateutils, contnrs,
|
avglvltree, math, dateutils, contnrs,
|
||||||
@ -293,6 +290,9 @@ var
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
|
{$IFDEF FPSpreadDebug}
|
||||||
|
LazLogger,
|
||||||
|
{$ENDIF}
|
||||||
StrUtils, Variants, LazFileUtils, URIParser, LazUTF8,
|
StrUtils, Variants, LazFileUtils, URIParser, LazUTF8,
|
||||||
{$IFDEF FPS_VARISBOOL}
|
{$IFDEF FPS_VARISBOOL}
|
||||||
fpsPatches,
|
fpsPatches,
|
||||||
@ -2390,7 +2390,7 @@ var
|
|||||||
ns: String;
|
ns: String;
|
||||||
begin
|
begin
|
||||||
{$IFDEF FPSpreadDebug}
|
{$IFDEF FPSpreadDebug}
|
||||||
DebugLn(Format('ReadFormula: ARow=%d, ACol=%d, AStyleIndex=%d', [ARow, ACol, AStyleIndex]));
|
DebugLn(Format('[ReadFormula] ARow=%d, ACol=%d, AStyleIndex=%d', [ARow, ACol, AStyleIndex]));
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
// Create cell and apply format
|
// Create cell and apply format
|
||||||
@ -2416,7 +2416,7 @@ begin
|
|||||||
if formula <> '' then
|
if formula <> '' then
|
||||||
begin
|
begin
|
||||||
// Formulas written by Spread begin with 'of:=', by Excel with 'msof:='.
|
// Formulas written by Spread begin with 'of:=', by Excel with 'msof:='.
|
||||||
// Remove that. And both use different list separators
|
// Remove that. And both use different list separators.
|
||||||
p := pos('=', formula);
|
p := pos('=', formula);
|
||||||
ns := Copy(formula, 1, p-2);
|
ns := Copy(formula, 1, p-2);
|
||||||
case ns of
|
case ns of
|
||||||
@ -2425,36 +2425,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
Delete(formula, 1, p);
|
Delete(formula, 1, p);
|
||||||
end;
|
end;
|
||||||
(*
|
|
||||||
if not (boIgnoreFormulas in FWorkbook.Options) then
|
|
||||||
begin
|
|
||||||
// ... convert to Excel "A1" dialect used by fps by defailt
|
|
||||||
parser := TsSpreadsheetParser.Create(FWorksheet);
|
|
||||||
try
|
|
||||||
try
|
|
||||||
parser.Dialect := fdOpenDocument;
|
|
||||||
parser.LocalizedExpression[FPointSeparatorSettings] := formula;
|
|
||||||
parser.Dialect := fdExcelA1;
|
|
||||||
formula := parser.Expression;
|
|
||||||
except
|
|
||||||
on E:EExprParser do
|
|
||||||
begin
|
|
||||||
Workbook.AddErrorMsg(E.Message);
|
|
||||||
formula := '';
|
|
||||||
if (boAbortReadOnFormulaError in Workbook.Options) then raise;
|
|
||||||
end;
|
|
||||||
on E:ECalcEngine do
|
|
||||||
begin
|
|
||||||
Workbook.AddErrorMsg(E.Message);
|
|
||||||
formula := '';
|
|
||||||
if (boAbortReadOnFormulaError in Workbook.Options) then raise;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
finally
|
|
||||||
parser.Free;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
*)
|
|
||||||
// ... and store in cell's FormulaValue field.
|
// ... and store in cell's FormulaValue field.
|
||||||
cell^.FormulaValue := formula;
|
cell^.FormulaValue := formula;
|
||||||
// Note: This formula is still in OpenDocument dialect. Conversion to
|
// Note: This formula is still in OpenDocument dialect. Conversion to
|
||||||
@ -2464,10 +2435,6 @@ begin
|
|||||||
|
|
||||||
{$IFDEF FPSpreadDebug}
|
{$IFDEF FPSpreadDebug}
|
||||||
DebugLn(' Formula found: ' + formula);
|
DebugLn(' Formula found: ' + formula);
|
||||||
(*
|
|
||||||
if SameText(formula, 'IsText({.B1])') then
|
|
||||||
formula := formula + '';
|
|
||||||
*)
|
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -3535,11 +3502,11 @@ var
|
|||||||
s: String;
|
s: String;
|
||||||
colsSpanned, rowsSpanned: Integer;
|
colsSpanned, rowsSpanned: Integer;
|
||||||
begin
|
begin
|
||||||
{$IFDEF FPSpreadDebug}
|
{$IFDEF FPSpreadDebug}
|
||||||
DebugLn(Format('ReadCell: ARow=%d, ACol=%d, AFormatIndex=%d',
|
DebugLn(Format('[ReadCell] ARow=%d, ACol=%d, AFormatIndex=%d',
|
||||||
[ARow, ACol, AFormatIndex])
|
[ARow, ACol, AFormatIndex])
|
||||||
);
|
);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
// Workaround for Excel files converted to ods by Calc: These files are
|
// Workaround for Excel files converted to ods by Calc: These files are
|
||||||
// expanded to fill the entire max worksheet. They also have single empty
|
// expanded to fill the entire max worksheet. They also have single empty
|
||||||
|
@ -176,6 +176,9 @@ procedure InitBiff2Limitations(out ALimitations: TsSpreadsheetFormatLimitations)
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
|
{$IFDEF FPSpreadDebug}
|
||||||
|
LazLogger,
|
||||||
|
{$ENDIF}
|
||||||
Math,
|
Math,
|
||||||
fpsStrings, fpsReaderWriter, fpsPalette, fpsNumFormat;
|
fpsStrings, fpsReaderWriter, fpsPalette, fpsNumFormat;
|
||||||
|
|
||||||
|
@ -53,7 +53,6 @@ unit xlsbiff5;
|
|||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
{$define USE_NEW_OLE}
|
{$define USE_NEW_OLE}
|
||||||
{.$define FPSPREADDEBUG} //define to print out debug info to console. Used to be XLSDEBUG;
|
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
@ -81,6 +80,7 @@ type
|
|||||||
procedure ReadFORMAT(AStream: TStream); override;
|
procedure ReadFORMAT(AStream: TStream); override;
|
||||||
procedure ReadLABEL(AStream: TStream); override;
|
procedure ReadLABEL(AStream: TStream); override;
|
||||||
function ReadRPNCellRange3D(AStream: TStream; var ARPNItem: PRPNItem): Boolean; override;
|
function ReadRPNCellRange3D(AStream: TStream; var ARPNItem: PRPNItem): Boolean; override;
|
||||||
|
procedure ReadRPNSheetIndex(AStream: TStream; out ASheet1, ASheet2: Integer); override;
|
||||||
procedure ReadRSTRING(AStream: TStream);
|
procedure ReadRSTRING(AStream: TStream);
|
||||||
procedure ReadStandardWidth(AStream: TStream; ASheet: TsWorksheet);
|
procedure ReadStandardWidth(AStream: TStream; ASheet: TsWorksheet);
|
||||||
procedure ReadStringRecord(AStream: TStream); override;
|
procedure ReadStringRecord(AStream: TStream); override;
|
||||||
@ -218,6 +218,9 @@ var
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
|
{$IFDEF FPSpreadDebug}
|
||||||
|
LazLogger,
|
||||||
|
{$ENDIF}
|
||||||
Math,
|
Math,
|
||||||
fpsStrings, fpsReaderWriter, fpsStreams, fpsPalette, fpsNumFormat, xlsconst;
|
fpsStrings, fpsReaderWriter, fpsStreams, fpsPalette, fpsNumFormat, xlsconst;
|
||||||
|
|
||||||
@ -599,7 +602,7 @@ begin (*
|
|||||||
$0225: ; //(DEFAULTROWHEIGHT) This record specifies the default height and default flags for rows that do not have a corresponding ROW record.
|
$0225: ; //(DEFAULTROWHEIGHT) This record specifies the default height and default flags for rows that do not have a corresponding ROW record.
|
||||||
$023E: ; //(WINDOW2) This record contains the range address of the used area in the current sheet.
|
$023E: ; //(WINDOW2) This record contains the range address of the used area in the current sheet.
|
||||||
else
|
else
|
||||||
WriteLn(format('Record type: %.4X Record Size: %.4X',[RecordType,RecordSize]));
|
DebugLn(format('Record type: %.4X Record Size: %.4X',[RecordType,RecordSize]));
|
||||||
end;
|
end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
end;
|
end;
|
||||||
@ -647,6 +650,34 @@ begin
|
|||||||
ARPNItem := RPNCellRange3D(sheetIndex1, r1, c1, sheetIndex2, r2, c2, flags, ARPNItem);
|
ARPNItem := RPNCellRange3D(sheetIndex1, r1, c1, sheetIndex2, r2, c2, flags, ARPNItem);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TsSpreadBIFF5Reader.ReadRPNSheetIndex(AStream: TStream;
|
||||||
|
out ASheet1, ASheet2: Integer);
|
||||||
|
var
|
||||||
|
idx: Int16;
|
||||||
|
begin
|
||||||
|
// One-based index to EXTERNSHEET record. Negative to indicate a 3D reference.
|
||||||
|
// Positive to indicate an external reference
|
||||||
|
idx := WordLEToN(AStream.ReadWord);
|
||||||
|
|
||||||
|
// We don't support external references at the moment.
|
||||||
|
if idx > 0 then begin
|
||||||
|
ASheet1 := -1;
|
||||||
|
ASheet1 := -1;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Skip 8 unused bytes
|
||||||
|
AStream.Position := AStream.Position + 8;
|
||||||
|
|
||||||
|
// Zero-based index to first referenced sheet (-1 = deleted sheet)
|
||||||
|
idx := WordLEToN(AStream.ReadWord);
|
||||||
|
ASheet1 := idx;
|
||||||
|
|
||||||
|
// Zero-based index to last referenced sheet (-1 = deleted sheet)
|
||||||
|
idx := WordLEToN(AStream.ReadWord);
|
||||||
|
ASheet2 := idx;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TsSpreadBIFF5Reader.ReadRSTRING(AStream: TStream);
|
procedure TsSpreadBIFF5Reader.ReadRSTRING(AStream: TStream);
|
||||||
var
|
var
|
||||||
L, i: Word;
|
L, i: Word;
|
||||||
@ -1022,8 +1053,8 @@ begin
|
|||||||
|
|
||||||
{ Character set }
|
{ Character set }
|
||||||
lCodepage := AStream.ReadByte();
|
lCodepage := AStream.ReadByte();
|
||||||
{$ifdef FPSPREADDEBUG}
|
{$ifdef FPSpreadDebug}
|
||||||
WriteLn('Reading Font Codepage='+IntToStr(lCodepage));
|
DebugLn('Reading Font Codepage = ' + IntToStr(lCodepage));
|
||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
{ Not used }
|
{ Not used }
|
||||||
|
@ -50,7 +50,6 @@ unit xlsbiff8;
|
|||||||
|
|
||||||
// The new OLE code is much better, so always use it
|
// The new OLE code is much better, so always use it
|
||||||
{$define USE_NEW_OLE}
|
{$define USE_NEW_OLE}
|
||||||
{.$define FPSPREADDEBUG} //define to print out debug info to console. Used to be XLSDEBUG;
|
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
@ -318,6 +317,9 @@ procedure InitBIFF8Limitations(out ALimitations: TsSpreadsheetFormatLimitations)
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
|
{$IFDEF FPSpreadDebug}
|
||||||
|
LazLogger,
|
||||||
|
{$ENDIF}
|
||||||
Math, lconvencoding, LazFileUtils, URIParser,
|
Math, lconvencoding, LazFileUtils, URIParser,
|
||||||
fpsStrings, {%H-}fpsPatches, fpsStreams, fpsReaderWriter, fpsPalette,
|
fpsStrings, {%H-}fpsPatches, fpsStreams, fpsReaderWriter, fpsPalette,
|
||||||
fpsNumFormat, fpsExprParser, xlsEscher;
|
fpsNumFormat, fpsExprParser, xlsEscher;
|
||||||
@ -930,7 +932,9 @@ begin
|
|||||||
PendingRecordSize := RecordSize;
|
PendingRecordSize := RecordSize;
|
||||||
|
|
||||||
// For debugging to find out in which record a crash happens:
|
// For debugging to find out in which record a crash happens:
|
||||||
// WriteLn(Format('Stream.Pos: %d, RecordType: $%.04x, RecordSize: %d', [AStream.Position-4, RecordType, RecordSize]));
|
{$IFDEF FPSpreadDebug}
|
||||||
|
DebugLn(Format('[ReadWorksheet] Stream.Pos: %d, RecordType: $%.04x, RecordSize: %d', [AStream.Position-4, RecordType, RecordSize]));
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
CurStreamPos := AStream.Position;
|
CurStreamPos := AStream.Position;
|
||||||
|
|
||||||
@ -2009,8 +2013,8 @@ begin
|
|||||||
|
|
||||||
{ Character set }
|
{ Character set }
|
||||||
lCodepage := AStream.ReadByte();
|
lCodepage := AStream.ReadByte();
|
||||||
{$ifdef FPSPREADDEBUG}
|
{$ifdef FPSpreadDebug}
|
||||||
WriteLn('Reading Font Codepage='+IntToStr(lCodepage));
|
DebugLn('Reading Font Codepage='+IntToStr(lCodepage));
|
||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
{ Not used }
|
{ Not used }
|
||||||
|
@ -1622,6 +1622,9 @@ end;
|
|||||||
|
|
||||||
NOTE: A character #03 is prepended to the sheet name if the EXTERNSHEET stores
|
NOTE: A character #03 is prepended to the sheet name if the EXTERNSHEET stores
|
||||||
a reference to one of the own sheets.
|
a reference to one of the own sheets.
|
||||||
|
|
||||||
|
NOTE: The string length field is decreased by 1, if the EXTERNSHEET stores
|
||||||
|
a reference to one of the own sheets (first character is #03).
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
procedure TsSpreadBIFFReader.ReadExternSheet(AStream: TStream);
|
procedure TsSpreadBIFFReader.ReadExternSheet(AStream: TStream);
|
||||||
var
|
var
|
||||||
|
Loading…
Reference in New Issue
Block a user