You've already forked lazarus-ccr
fpspreadsheet: Add BIFF5 writer for 3d references. Add corresponding unit test. Some related bug fixes. Less hints.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@6401 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -599,7 +599,6 @@ type
|
||||
FIsRef: Boolean;
|
||||
FOtherSheet: Boolean;
|
||||
protected
|
||||
procedure Check; override;
|
||||
function GetCol: Cardinal;
|
||||
function GetRow: Cardinal;
|
||||
function GetSheetIndex: Integer;
|
||||
@ -611,6 +610,7 @@ type
|
||||
ACellString: String; Othersheet: Boolean); overload;
|
||||
function AsRPNItem(ANext: PRPNItem): PRPNItem; override;
|
||||
function AsString: string; override;
|
||||
procedure Check; override;
|
||||
function NodeType: TsResultType; override;
|
||||
property Worksheet: TsWorksheet read FWorksheet;
|
||||
end;
|
||||
@ -1020,12 +1020,10 @@ var
|
||||
S: String;
|
||||
row, row2: Cardinal;
|
||||
col, col2: Cardinal;
|
||||
sheetName: String;
|
||||
flags: TsRelFlags;
|
||||
begin
|
||||
C := CurrentChar;
|
||||
if C = FSheetNameTerminator then C := NextPos;
|
||||
sheetName := '';
|
||||
while (not IsWordDelim(C)) and (C <> cNull) and (C <> FSheetNameTerminator) do
|
||||
begin
|
||||
if ((FParser.Dialect = fdOpenDocument) and (C = ']')) then begin
|
||||
|
@ -3760,7 +3760,7 @@ begin
|
||||
'_': // Excel: Leave width of next character empty
|
||||
begin
|
||||
FToken := NextToken;
|
||||
uch := UTF8CharacterToUnicode(FCurrent, n);
|
||||
uch := UTF8CharacterToUnicode(FCurrent, n); // wp: Why Unicode ???
|
||||
if n > 1 then
|
||||
begin
|
||||
AddElement(nftEmptyCharWidth, UnicodeToUTF8(uch));
|
||||
|
@ -2384,7 +2384,6 @@ var
|
||||
valueType, calcExtValueType: String;
|
||||
valueStr: String;
|
||||
node: TDOMNode;
|
||||
parser: TsSpreadsheetParser;
|
||||
p: Integer;
|
||||
fmt: PsCellFormat;
|
||||
ns: String;
|
||||
@ -7949,7 +7948,6 @@ var
|
||||
fmt: TsCellFormat;
|
||||
numFmtParams: TsNumFormatParams;
|
||||
h,m,s,ms: Word;
|
||||
mask: String;
|
||||
begin
|
||||
Unused(ARow, ACol);
|
||||
|
||||
|
@ -111,9 +111,13 @@ type
|
||||
procedure WriteFonts(AStream: TStream);
|
||||
procedure WriteFORMAT(AStream: TStream; ANumFormatStr: String;
|
||||
ANumFormatIndex: Integer); override;
|
||||
procedure WriteGlobalLinkTable(AStream: TStream);
|
||||
procedure WriteIndex(AStream: TStream);
|
||||
procedure WriteLABEL(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
const AValue: string; ACell: PCell); override;
|
||||
procedure WriteLocalLinkTable(AStream: TStream);
|
||||
function WriteRPNCellAddress3D(AStream: TStream; ASheet, ARow, ACol: Cardinal;
|
||||
AFlags: TsRelFlags): Word; override;
|
||||
procedure WriteStringRecord(AStream: TStream; AString: String); override;
|
||||
procedure WriteStyle(AStream: TStream);
|
||||
procedure WriteWindow2(AStream: TStream; ASheet: TsWorksheet);
|
||||
@ -394,13 +398,6 @@ begin
|
||||
sheet := FWorkbook.AddWorksheet(ConvertEncoding(s, FCodePage, EncodingUTF8), true);
|
||||
if sheetState <> 0 then
|
||||
sheet.Options := sheet.Options + [soHidden];
|
||||
(*
|
||||
{ Temporarily store parameters for worksheet in FSheetList }
|
||||
sheetData := TsSheetData.Create;
|
||||
sheetData.Name := ConvertEncoding(s, FCodePage, EncodingUTF8);
|
||||
sheetData.Hidden := sheetState <> 0;
|
||||
FSheetList.Add(sheetData);
|
||||
*)
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
@ -512,13 +509,7 @@ var
|
||||
SectionEOF: Boolean = False;
|
||||
RecordType: Word;
|
||||
CurStreamPos: Int64;
|
||||
// sheetData: TsSheetData;
|
||||
begin (*
|
||||
sheetData := TsSheetData(FSheetList[FCurSheetIndex]);
|
||||
FWorksheet := FWorkbook.AddWorksheet(sheetData.Name, true);
|
||||
if sheetData.Hidden then
|
||||
FWorksheet.Options := FWorksheet.Options + [soHidden];
|
||||
*)
|
||||
begin
|
||||
FWorksheet := FWorkbook.GetWorksheetByIndex(FCurSheetIndex);
|
||||
while (not SectionEOF) do
|
||||
begin
|
||||
@ -1188,8 +1179,9 @@ begin
|
||||
WriteWindowProtect(AStream, bpLockWindows in Workbook.Protection);
|
||||
WritePROTECT(AStream, bpLockStructure in Workbook.Protection);
|
||||
WritePASSWORD(AStream, Workbook.CryptoInfo);
|
||||
WriteEXTERNCOUNT(AStream);
|
||||
WriteEXTERNSHEET(AStream);
|
||||
WriteGlobalLinkTable(AStream);
|
||||
// WriteEXTERNCOUNT(AStream);
|
||||
// WriteEXTERNSHEET(AStream);
|
||||
WriteDefinedNames(AStream);
|
||||
WriteWINDOW1(AStream);
|
||||
WriteFonts(AStream);
|
||||
@ -1236,6 +1228,9 @@ begin
|
||||
WriteMargin(AStream, 3); // 3 = bottom margin
|
||||
WritePageSetup(AStream);
|
||||
|
||||
// Local link table
|
||||
WriteLocalLinkTable(AStream);
|
||||
|
||||
// Protection
|
||||
if FWorksheet.IsProtected then begin
|
||||
WritePROTECT(AStream, true);
|
||||
@ -1731,6 +1726,36 @@ begin
|
||||
SetLength(buf, 0);
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Writes the global link table: an EXTERNCOUNT record and several EXTERNSHEET
|
||||
records
|
||||
-------------------------------------------------------------------------------}
|
||||
procedure TsSpreadBIFF5Writer.WriteGlobalLinkTable(AStream: TStream);
|
||||
var
|
||||
L: TStringList;
|
||||
i: Integer;
|
||||
sheet: TsWorksheet;
|
||||
begin
|
||||
L := TStringList.Create;
|
||||
try
|
||||
for i := 0 to FWorkbook.GetWorksheetCount-1 do
|
||||
begin
|
||||
sheet := FWorkbook.GetWorksheetByIndex(i);
|
||||
with sheet.PageLayout do
|
||||
if (NumPrintRanges > 0) or HasRepeatedCols or HasRepeatedRows then
|
||||
L.Add(sheet.Name);
|
||||
end;
|
||||
if L.Count = 0 then
|
||||
exit;
|
||||
|
||||
WriteEXTERNCOUNT(AStream, L.Count);
|
||||
for i:=0 to L.Count-1 do
|
||||
WriteEXTERNSHEET(AStream, L[i]);
|
||||
finally
|
||||
L.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Writes an Excel 5 INDEX record
|
||||
|
||||
@ -1854,6 +1879,75 @@ begin
|
||||
SetLength(buf, 0);
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Writes a local Link Table with EXTERNCOUNT and EXTERSHEET records for
|
||||
internal 3D references to other sheets
|
||||
-------------------------------------------------------------------------------}
|
||||
procedure TsSpreadBIFF5Writer.WriteLocalLinkTable(AStream: TStream);
|
||||
var
|
||||
L: TStringList;
|
||||
cell: PCell;
|
||||
found: Boolean;
|
||||
i, n: Integer;
|
||||
begin
|
||||
L := TStringList.Create;
|
||||
try
|
||||
// Check whether there is any cell with a formula with 3D reference
|
||||
found := false;
|
||||
for cell in FWorksheet.Cells do
|
||||
if HasFormula(cell) and (pos('!', cell^.FormulaValue) <> 0) then begin
|
||||
found := true;
|
||||
break;
|
||||
end;
|
||||
// Write every sheet to local link table. This is too much - it would be
|
||||
// enough to write only those sheets involved in a 3d reference - but it
|
||||
// simplifies processing of 3d references a lot.
|
||||
if found then begin
|
||||
n := FWorkbook.GetWorksheetCount;
|
||||
if n > 0 then begin
|
||||
WriteEXTERNCOUNT(AStream, word(n));
|
||||
for i := 0 to n-1 do
|
||||
WriteEXTERNSHEET(AStream, FWorkbook.GetWorksheetByIndex(i).Name);
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
L.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Writes a 3D cell address consisting of worksheet, row and column indexes.
|
||||
Needed for references to other worksheets within the same workbook.
|
||||
Returns the number of bytes written.
|
||||
-------------------------------------------------------------------------------}
|
||||
function TsSpreadBIFF5Writer.WriteRPNCellAddress3D(AStream: TStream;
|
||||
ASheet, ARow, ACol: Cardinal; AFlags: TsRelFlags): Word;
|
||||
var
|
||||
p: Int64;
|
||||
begin
|
||||
p := AStream.Position;
|
||||
|
||||
// One-based index to EXTERNSHEET record in the Local Link Table
|
||||
// containing the name of the first referenced sheet.
|
||||
// This is always a negative value to indicate a 3D reference.
|
||||
AStream.WriteWord(WordToLE(-(ASheet+1)));
|
||||
|
||||
// 8 unused bytes
|
||||
AStream.WriteDWord(0);
|
||||
AStream.WriteDWord(0);
|
||||
|
||||
// Zero-based index to first referenced sheet (FFFFH = deleted sheet)
|
||||
AStream.WriteWord(WordToLE(ASheet));
|
||||
|
||||
// Zero-based index to last referenced sheet (FFFFH = deleted sheet)
|
||||
AStream.WriteWord(WordToLE(ASheet));
|
||||
|
||||
// Write row/column address
|
||||
WriteRPNCellAddress(AStream, ARow, ACol, AFlags);
|
||||
|
||||
Result := AStream.Position - p;
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Writes an Excel 5 STRING record which immediately follows a FORMULA record
|
||||
when the formula result is a string.
|
||||
|
@ -177,7 +177,7 @@ type
|
||||
procedure WriteDimensions(AStream: TStream; AWorksheet: TsWorksheet);
|
||||
procedure WriteEOF(AStream: TStream);
|
||||
procedure WriteEXTERNBOOK(AStream: TStream);
|
||||
procedure WriteEXTERNSHEET(AStream: TStream); override;
|
||||
procedure WriteEXTERNSHEET(AStream: TStream);
|
||||
procedure WriteFONT(AStream: TStream; AFont: TsFont);
|
||||
procedure WriteFonts(AStream: TStream);
|
||||
procedure WriteFORMAT(AStream: TStream; ANumFormatStr: String;
|
||||
@ -915,14 +915,7 @@ var
|
||||
SectionEOF: Boolean = False;
|
||||
RecordType: Word;
|
||||
CurStreamPos: Int64;
|
||||
// sheetData: TsSheetData;
|
||||
begin
|
||||
(*
|
||||
sheetData := TsSheetData(FSheetList[FCurSheetIndex]);
|
||||
FWorksheet := FWorkbook.AddWorksheet(sheetData.Name, true);
|
||||
if sheetData.Hidden then
|
||||
FWorksheet.Options := FWorksheet.Options + [soHidden];
|
||||
*)
|
||||
FWorksheet := FWorkbook.GetWorksheetByIndex(FCurSheetIndex);
|
||||
while (not SectionEOF) do
|
||||
begin
|
||||
@ -1016,7 +1009,6 @@ var
|
||||
rtParams: TsRichTextParams;
|
||||
sheet: TsWorksheet;
|
||||
sheetstate: Byte;
|
||||
sheetdata: TsSheetData;
|
||||
begin
|
||||
{ Absolute stream position of the BOF record of the sheet represented
|
||||
by this record }
|
||||
@ -1038,12 +1030,6 @@ begin
|
||||
sheet := FWorkbook.AddWorksheet(UTF8Encode(widename), true);
|
||||
if sheetState <> 0 then
|
||||
sheet.Options := sheet.Options + [soHidden];
|
||||
(*
|
||||
sheetData := TsSheetData.Create;
|
||||
sheetData.Name := UTF8Encode(wideName);
|
||||
sheetData.Hidden := sheetState <> 0;
|
||||
FSheetList.Add(sheetdata);
|
||||
*)
|
||||
end;
|
||||
|
||||
function TsSpreadBIFF8Reader.ReadString(const AStream: TStream;
|
||||
@ -1886,7 +1872,7 @@ var
|
||||
sheetnames: widestring;
|
||||
externbook: TBiff8Externbook;
|
||||
p: Int64;
|
||||
t: array[0..1] of byte;
|
||||
t: array[0..1] of byte = (0, 0);
|
||||
begin
|
||||
if FBiff8ExternBooks = nil then
|
||||
FBiff8ExternBooks := TFPObjectList.Create(true);
|
||||
@ -1904,8 +1890,7 @@ begin
|
||||
else
|
||||
if (t[0] = 1) and (t[1] = $3A) then
|
||||
externbook.Kind := ebkAddInFunc
|
||||
else
|
||||
if n = 0 then
|
||||
else if n = 0 then
|
||||
externbook.Kind := ebkDDE_OLE
|
||||
else
|
||||
externbook.Kind := ebkExternal;
|
||||
@ -1922,11 +1907,11 @@ begin
|
||||
sheetnames := ''
|
||||
else begin
|
||||
// Sheet names (Unicode strings with 16bit string length)
|
||||
sheetnames := UTF8Encode(ReadWideString(AStream, false));
|
||||
sheetnames := ReadWideString(AStream, false);
|
||||
for i := 2 to n do
|
||||
sheetnames := sheetnames + #1 + UTF8Encode(ReadWideString(AStream, false));
|
||||
sheetnames := sheetnames + widechar(#1) + ReadWideString(AStream, false);
|
||||
end;
|
||||
externbook.SheetNames := sheetNames;
|
||||
externbook.SheetNames := UTF8Encode(sheetNames);
|
||||
end;
|
||||
|
||||
FBiff8ExternBooks.Add(externbook);
|
||||
@ -3759,16 +3744,14 @@ end;
|
||||
|
||||
function TsSpreadBIFF8Writer.WriteRPNCellAddress3D(AStream: TStream;
|
||||
ASheet, ARow, ACol: Cardinal; AFlags: TsRelFlags): Word;
|
||||
var
|
||||
c: Cardinal;
|
||||
begin
|
||||
// Next line is a simplification: We should write the index of the sheet
|
||||
// in the REF record here, but these are arranged in the same order as the
|
||||
// sheets. --> MUST BE RE-DONE ONCE SHEET RANGES ARE ALLOWED.
|
||||
AStream.WriteWord(WordToLE(ASheet));
|
||||
|
||||
// The row/col address is written in relative notation!
|
||||
Result := 2 + WriteRPNCellAddress(AStream, ARow, ACol, [rfRelRow, rfRelCol]);
|
||||
// Write row/column address
|
||||
Result := 2 + WriteRPNCellAddress(AStream, ARow, ACol, AFlags);
|
||||
end;
|
||||
|
||||
|
||||
|
@ -395,7 +395,6 @@ type
|
||||
FCurSheetIndex: Integer;
|
||||
FActivePane: Integer;
|
||||
FExternSheets: TStrings;
|
||||
// FSheetList: TFPList;
|
||||
|
||||
procedure AddBuiltinNumFormats; override;
|
||||
procedure ApplyCellFormatting(ACell: PCell; XFIndex: Word); virtual;
|
||||
@ -573,9 +572,9 @@ type
|
||||
procedure WriteError(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
const AValue: TsErrorValue; ACell: PCell); override;
|
||||
// Writes out an EXTERNCOUNT record
|
||||
procedure WriteEXTERNCOUNT(AStream: TStream);
|
||||
procedure WriteEXTERNCOUNT(AStream: TStream; ACount: Word);
|
||||
// Writes out an EXTERNSHEET record
|
||||
procedure WriteEXTERNSHEET(AStream: TStream); virtual;
|
||||
procedure WriteEXTERNSHEET(AStream: TStream; ASheetName: String);
|
||||
// Writes out a FORMAT record
|
||||
procedure WriteFORMAT(AStream: TStream; ANumFormatStr: String;
|
||||
ANumFormatIndex: Integer); virtual;
|
||||
@ -613,7 +612,7 @@ type
|
||||
function WriteRPNCellAddress(AStream: TStream; ARow, ACol: Cardinal;
|
||||
AFlags: TsRelFlags): Word; virtual;
|
||||
function WriteRPNCellAddress3D(AStream: TStream; ASheet, ARow, ACol: Cardinal;
|
||||
AFlags: TsRelFlags): Word; virtual;
|
||||
{%H-}AFlags: TsRelFlags): Word; virtual;
|
||||
function WriteRPNCellOffset(AStream: TStream; ARowOffset, AColOffset: Integer;
|
||||
AFlags: TsRelFlags): Word; virtual;
|
||||
function WriteRPNCellRangeAddress(AStream: TStream; ARow1, ACol1, ARow2, ACol2: Cardinal;
|
||||
@ -978,8 +977,6 @@ constructor TsSpreadBIFFReader.Create(AWorkbook: TsWorkbook);
|
||||
begin
|
||||
inherited Create(AWorkbook);
|
||||
|
||||
// FSheetList := TFPList.Create;
|
||||
|
||||
FPalette := TsPalette.Create;
|
||||
PopulatePalette;
|
||||
|
||||
@ -1008,9 +1005,6 @@ var
|
||||
begin
|
||||
for j:=0 to FDefinedNames.Count-1 do TObject(FDefinedNames[j]).Free;
|
||||
FDefinedNames.Free;
|
||||
{
|
||||
for j:= 0 to FSheetList.Count-1 do TObject(FSheetList[j]).Free;
|
||||
FSheetList.Free; }
|
||||
|
||||
FExternSheets.Free;
|
||||
FPalette.Free;
|
||||
@ -2483,6 +2477,7 @@ end;
|
||||
procedure TsSpreadBIFFReader.ReadRPNSheetIndex(AStream: TStream;
|
||||
out ASheet1, ASheet2: Integer);
|
||||
begin
|
||||
Unused(AStream);
|
||||
ASheet1 := -1;
|
||||
ASheet2 := -1;
|
||||
end;
|
||||
@ -2733,7 +2728,13 @@ begin
|
||||
INT_EXCEL_TOKEN_TREFN_R: rpnItem := RPNCellRef(r, c, flags, rpnItem);
|
||||
end;
|
||||
end;
|
||||
INT_EXCEL_TOKEN_TREF3D_R, INT_EXCEL_TOKEN_TREF3d_V:
|
||||
INT_EXCEL_TOKEN_TREF3D_V:
|
||||
begin
|
||||
ReadRPNSheetIndex(AStream, sheet1, sheet2);
|
||||
ReadRPNCellAddress(AStream, r, c, flags);
|
||||
rpnItem := RpnCellValue3D(sheet1, r, c, flags, rpnItem);
|
||||
end;
|
||||
INT_EXCEL_TOKEN_TREF3D_R: //, INT_EXCEL_TOKEN_TREF3d_V:
|
||||
begin
|
||||
ReadRPNSheetIndex(AStream, sheet1, sheet2);
|
||||
ReadRPNCellAddressOffset(AStream, dr, dc, flags);
|
||||
@ -3711,6 +3712,7 @@ end;
|
||||
Writes a BIFF EXTERNCOUNT record.
|
||||
Valid for BIFF2-BIFF5.
|
||||
-------------------------------------------------------------------------------}
|
||||
(*
|
||||
procedure TsSpreadBIFFWriter.WriteEXTERNCOUNT(AStream: TStream);
|
||||
var
|
||||
i: Integer;
|
||||
@ -3734,11 +3736,42 @@ begin
|
||||
{ Count of EXTERNSHEET records following }
|
||||
AStream.WriteWord(WordToLE(n));
|
||||
end;
|
||||
*)
|
||||
procedure TsSpreadBIFFWriter.WriteEXTERNCOUNT(AStream: TStream; ACount: Word);
|
||||
begin
|
||||
{ BIFF record header }
|
||||
WriteBIFFHeader(AStream, INT_EXCEL_ID_EXTERNCOUNT, 2);
|
||||
|
||||
{ Count of EXTERNSHEET records following }
|
||||
AStream.WriteWord(WordToLE(ACount));
|
||||
end;
|
||||
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Writes a BIFF EXTERNSHEET record.
|
||||
Valid for BIFF2-BIFF5.
|
||||
-------------------------------------------------------------------------------}
|
||||
procedure TsSpreadBIFFWriter.WriteEXTERNSHEET(AStream: TStream;
|
||||
ASheetName: String);
|
||||
var
|
||||
s: ansistring;
|
||||
begin
|
||||
// Convert to ANSI
|
||||
s := ConvertEncoding(ASheetName, encodingUTF8, FCodePage);
|
||||
|
||||
{ BIFF record header }
|
||||
WriteBIFFHeader(AStream, INT_EXCEL_ID_EXTERNSHEET, 2 + Length(s));
|
||||
|
||||
{ Character count in worksheet name - don't count the following flag! }
|
||||
AStream.WriteByte(Length(s));
|
||||
|
||||
{ Flag for identification as own sheet }
|
||||
AStream.WriteByte($03);
|
||||
|
||||
{ Sheet name }
|
||||
AStream.WriteBuffer(s[1], Length(s));
|
||||
end;
|
||||
(*
|
||||
procedure TsSpreadBIFFWriter.WriteEXTERNSHEET(AStream: TStream);
|
||||
var
|
||||
sheet: TsWorksheet;
|
||||
@ -3766,7 +3799,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
*)
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Writes the a margin record for printing (margin is in inches).
|
||||
The margin is identified by the parameter AMargin:
|
||||
@ -4330,12 +4363,15 @@ end;
|
||||
|
||||
{@ -----------------------------------------------------------------------------
|
||||
Writes the address of a cell as used in an RPN formula and returns the
|
||||
count of bytes written.
|
||||
count of bytes written. The return value is $FFFF if 3D addresses are not
|
||||
supported (BIFF 2).
|
||||
Placeholder. To be overridden by BIFF5 and BIFF8.
|
||||
-------------------------------------------------------------------------------}
|
||||
function TsSpreadBIFFWriter.WriteRPNCellAddress3D(AStream: TStream;
|
||||
ASheet, ARow, ACol: Cardinal; AFlags: TsRelFlags): Word;
|
||||
begin
|
||||
Unused(AStream, ASheet);
|
||||
Unused(ARow, ACol);
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
@ -4626,7 +4662,10 @@ begin
|
||||
AFormula[i].Row, AFormula[i].Col,
|
||||
AFormula[i].RelFlags
|
||||
);
|
||||
inc(RPNLength, n);
|
||||
if n = $FFFF then
|
||||
FWorkbook.AddErrorMsg('3D cell addresses are not supported.')
|
||||
else
|
||||
inc(RPNLength, n);
|
||||
end;
|
||||
|
||||
INT_EXCEL_TOKEN_TAREA_R: { fekCellRange }
|
||||
|
@ -76,6 +76,7 @@ type
|
||||
procedure Test_Write_Read_CalcStringFormula_ODS;
|
||||
|
||||
{ Formulas with 3D references to other sheets }
|
||||
procedure Test_Write_Read_Calc3DFormula_BIFF5;
|
||||
procedure Test_Write_Read_Calc3DFormula_BIFF8;
|
||||
procedure Test_Write_Read_Calc3DFormula_OOXML;
|
||||
procedure Test_Write_Read_Calc3DFormula_ODS;
|
||||
@ -698,20 +699,11 @@ var
|
||||
workbook: TsWorkbook;
|
||||
row: Integer;
|
||||
tempFile: string; //write xls/xml to this file and read back from it
|
||||
actual: TsExpressionResult;
|
||||
expected: TsExpressionResult;
|
||||
actual, expected: TsExpressionResult;
|
||||
cell: PCell;
|
||||
sollValues: array of TsExpressionResult;
|
||||
formula: String;
|
||||
ErrorMargin: Double;
|
||||
formula, actualformula: String;
|
||||
begin
|
||||
ErrorMargin:=0; //1.44E-7;
|
||||
//1.44E-7 for SUMSQ formula
|
||||
//6.0E-8 for SUM formula
|
||||
//4.8E-8 for MAX formula
|
||||
//2.4E-8 for now formula
|
||||
//about 1E-15 is needed for some trig functions
|
||||
|
||||
// Create test workbook
|
||||
workbook := TsWorkbook.Create;
|
||||
try
|
||||
@ -746,10 +738,14 @@ begin
|
||||
|
||||
for row := 0 to sheet1.GetLastRowIndex do
|
||||
begin
|
||||
cell := sheet1.FindCell(Row, 0);
|
||||
if (Cell = nil) then
|
||||
Fail('Error in test code: failed to get cell ' + CellNotation(sheet1, Row, 0));
|
||||
formula := sheet1.ReadAsText(cell);
|
||||
|
||||
cell := sheet1.FindCell(Row, 1);
|
||||
if (cell = nil) then
|
||||
fail('Error in test code: Failed to get cell ' + CellNotation(sheet1, Row, 1));
|
||||
|
||||
case cell^.ContentType of
|
||||
cctBool : actual := BooleanResult(cell^.BoolValue);
|
||||
cctNumber : actual := FloatResult(cell^.NumberValue);
|
||||
@ -759,6 +755,7 @@ begin
|
||||
cctEmpty : actual := EmptyResult;
|
||||
else fail('ContentType not supported');
|
||||
end;
|
||||
actualformula := cell^.FormulaValue;
|
||||
|
||||
expected := SollValues[row];
|
||||
// Cell does not store integers!
|
||||
@ -784,7 +781,7 @@ begin
|
||||
rtFloat:
|
||||
{$if (defined(mswindows)) or (FPC_FULLVERSION>=20701)}
|
||||
// FPC 2.6.x and trunk on Windows need this, also FPC trunk on Linux x64
|
||||
CheckEquals(expected.ResFloat, actual.ResFloat, ErrorMargin,
|
||||
CheckEquals(expected.ResFloat, actual.ResFloat,
|
||||
'Test read calculated formula result mismatch, cell '+CellNotation(sheet1, Row, 1));
|
||||
{$else}
|
||||
// Non-Windows: test without error margin
|
||||
@ -800,6 +797,9 @@ begin
|
||||
GetEnumname(TypeInfo(TsErrorValue), ord(actual.ResError)),
|
||||
'Test read calculated formula error value mismatch, cell '+CellNotation(sheet1, Row, 1));
|
||||
end;
|
||||
|
||||
CheckEquals(
|
||||
formula, actualformula, 'Read formula string mismatch, cell ' +CellNotation(sheet1, Row, 1));
|
||||
end;
|
||||
|
||||
finally
|
||||
@ -809,6 +809,11 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_Calc3DFormula_BIFF5;
|
||||
begin
|
||||
Test_Write_Read_Calc3DFormulas(sfExcel5);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_Calc3DFormula_BIFF8;
|
||||
begin
|
||||
Test_Write_Read_Calc3DFormulas(sfExcel8);
|
||||
|
@ -69,7 +69,6 @@
|
||||
SetLength(SollValues, Row+1);
|
||||
SollValues[Row] := StringResult('AB');
|
||||
|
||||
|
||||
{
|
||||
inc(Row);
|
||||
formula := 'D1&Sheet2!B3%"BC"';
|
||||
|
Reference in New Issue
Block a user