fpspreadsheet: Add test cases for shared formulas

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3529 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2014-09-08 11:09:23 +00:00
parent e9bf681d97
commit 6b5cc615d3
3 changed files with 220 additions and 26 deletions

View File

@ -815,6 +815,8 @@ function ArgToFloat(Arg: TsExpressionResult): TsExprFloat;
function ArgToString(Arg: TsExpressionResult): String; function ArgToString(Arg: TsExpressionResult): String;
procedure ArgsToFloatArray(const Args: TsExprParameterArray; out AData: TsExprFloatArray); procedure ArgsToFloatArray(const Args: TsExprParameterArray; out AData: TsExprFloatArray);
function BooleanResult(AValue: Boolean): TsExpressionResult; function BooleanResult(AValue: Boolean): TsExpressionResult;
function CellResult(AValue: String): TsExpressionResult; overload;
function CellResult(ACellRow, ACellCol: Cardinal): TsExpressionResult; overload;
function DateTimeResult(AValue: TDateTime): TsExpressionResult; function DateTimeResult(AValue: TDateTime): TsExpressionResult;
function EmptyResult: TsExpressionResult; function EmptyResult: TsExpressionResult;
function ErrorResult(const AValue: TsErrorValue): TsExpressionResult; function ErrorResult(const AValue: TsErrorValue): TsExpressionResult;
@ -4120,6 +4122,19 @@ begin
Result.ResBoolean := AValue; Result.ResBoolean := AValue;
end; end;
function CellResult(AValue: String): TsExpressionResult;
begin
Result.ResultType := rtCell;
ParseCellString(AValue, Result.ResRow, Result.ResCol);
end;
function CellResult(ACellRow, ACellCol: Cardinal): TsExpressionResult;
begin
Result.ResultType := rtCell;
Result.ResRow := ACellRow;
Result.ResCol := ACellCol;
end;
function DateTimeResult(AValue: TDateTime): TsExpressionResult; function DateTimeResult(AValue: TDateTime): TsExpressionResult;
begin begin
Result.ResultType := rtDateTime; Result.ResultType := rtDateTime;

View File

@ -30,12 +30,16 @@ type
// Set up expected values: // Set up expected values:
procedure SetUp; override; procedure SetUp; override;
procedure TearDown; override; procedure TearDown; override;
// Test formula strings // Test reconstruction of formula strings
procedure TestWriteReadFormulaStrings(AFormat: TsSpreadsheetFormat; procedure Test_Write_Read_FormulaStrings(AFormat: TsSpreadsheetFormat;
UseRPNFormula: Boolean); UseRPNFormula: Boolean);
// Test reconstruction of shared formula strings
procedure Test_Write_Read_SharedFormulaStrings(AFormat: TsSpreadsheetFormat); procedure Test_Write_Read_SharedFormulaStrings(AFormat: TsSpreadsheetFormat);
// Test calculation of rpn formulas // Test calculation of formulas
procedure TestCalcFormulas(AFormat: TsSpreadsheetformat; UseRPNFormula: Boolean); procedure Test_Write_Read_CalcFormulas(AFormat: TsSpreadsheetformat;
UseRPNFormula: Boolean);
// Test calculation of shared formulas
procedure Test_Write_Read_CalcSharedFormulas(AFormat: TsSpreadsheetformat);
published published
// Writes out formulas & reads them back. // Writes out formulas & reads them back.
@ -85,6 +89,19 @@ type
procedure Test_Write_Read_CalcStringFormula_OOXML; procedure Test_Write_Read_CalcStringFormula_OOXML;
{ ODS Tests } { ODS Tests }
procedure Test_Write_Read_CalcStringFormula_ODS; procedure Test_Write_Read_CalcStringFormula_ODS;
// Writes out and calculates shared formulas, read back
{ BIFF2 Tests }
procedure Test_Write_Read_CalcSharedFormula_BIFF2;
{ BIFF5 Tests }
procedure Test_Write_Read_CalcSharedFormula_BIFF5;
{ BIFF8 Tests }
procedure Test_Write_Read_CalcSharedFormula_BIFF8;
{ OOXML Tests }
procedure Test_Write_Read_CalcSharedFormula_OOXML;
{ ODS Tests }
procedure Test_Write_Read_CalcSharedFormula_ODS;
end; end;
implementation implementation
@ -116,7 +133,7 @@ begin
inherited TearDown; inherited TearDown;
end; end;
procedure TSpreadWriteReadFormulaTests.TestWriteReadFormulaStrings( procedure TSpreadWriteReadFormulaTests.Test_Write_Read_FormulaStrings(
AFormat: TsSpreadsheetFormat; UseRPNFormula: Boolean); AFormat: TsSpreadsheetFormat; UseRPNFormula: Boolean);
{ If UseRPNFormula is true the test formulas are generated from RPN formulas. { If UseRPNFormula is true the test formulas are generated from RPN formulas.
Otherwise they are generated from string formulas. } Otherwise they are generated from string formulas. }
@ -185,27 +202,27 @@ end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_FormulaStrings_BIFF2; procedure TSpreadWriteReadFormulaTests.Test_Write_Read_FormulaStrings_BIFF2;
begin begin
TestWriteReadFormulaStrings(sfExcel2, true); Test_Write_Read_FormulaStrings(sfExcel2, true);
end; end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_FormulaStrings_BIFF5; procedure TSpreadWriteReadFormulaTests.Test_Write_Read_FormulaStrings_BIFF5;
begin begin
TestWriteReadFormulaStrings(sfExcel5, true); Test_Write_Read_FormulaStrings(sfExcel5, true);
end; end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_FormulaStrings_BIFF8; procedure TSpreadWriteReadFormulaTests.Test_Write_Read_FormulaStrings_BIFF8;
begin begin
TestWriteReadFormulaStrings(sfExcel8, true); Test_Write_Read_FormulaStrings(sfExcel8, true);
end; end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_FormulaStrings_OOXML; procedure TSpreadWriteReadFormulaTests.Test_Write_Read_FormulaStrings_OOXML;
begin begin
TestWriteReadFormulaStrings(sfOOXML, true); Test_Write_Read_FormulaStrings(sfOOXML, true);
end; end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_FormulaStrings_ODS; procedure TSpreadWriteReadFormulaTests.Test_Write_Read_FormulaStrings_ODS;
begin begin
TestWriteReadFormulaStrings(sfOpenDocument, true); Test_Write_Read_FormulaStrings(sfOpenDocument, true);
end; end;
@ -222,7 +239,7 @@ var
row, col: Cardinal; row, col: Cardinal;
TempFile: String; TempFile: String;
actual, expected: String; actual, expected: String;
sollValues: array[1..4, 0..5] of string; sollValues: array[1..4, 0..4] of string;
begin begin
TempFile := GetTempFileName; TempFile := GetTempFileName;
@ -338,8 +355,8 @@ end;
{ Test calculation of formulas } { Test calculation of formulas }
procedure TSpreadWriteReadFormulaTests.TestCalcFormulas(AFormat: TsSpreadsheetFormat; procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcFormulas(
UseRPNFormula: Boolean); AFormat: TsSpreadsheetFormat; UseRPNFormula: Boolean);
{ If UseRPNFormula is TRUE, the test formulas are generated from RPN syntax, { If UseRPNFormula is TRUE, the test formulas are generated from RPN syntax,
otherwise string formulas are used. } otherwise string formulas are used. }
const const
@ -482,52 +499,213 @@ end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcRPNFormula_BIFF2; procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcRPNFormula_BIFF2;
begin begin
TestCalcFormulas(sfExcel2, true); Test_Write_Read_CalcFormulas(sfExcel2, true);
end; end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcRPNFormula_BIFF5; procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcRPNFormula_BIFF5;
begin begin
TestCalcFormulas(sfExcel5, true); Test_Write_Read_CalcFormulas(sfExcel5, true);
end; end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcRPNFormula_BIFF8; procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcRPNFormula_BIFF8;
begin begin
TestCalcFormulas(sfExcel8, true); Test_Write_Read_CalcFormulas(sfExcel8, true);
end; end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcRPNFormula_OOXML; procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcRPNFormula_OOXML;
begin begin
TestCalcFormulas(sfOOXML, true); Test_Write_Read_CalcFormulas(sfOOXML, true);
end; end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcRPNFormula_ODS; procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcRPNFormula_ODS;
begin begin
TestCalcFormulas(sfOpenDocument, true); Test_Write_Read_CalcFormulas(sfOpenDocument, true);
end; end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcStringFormula_BIFF2; procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcStringFormula_BIFF2;
begin begin
TestCalcFormulas(sfExcel2, false); Test_Write_Read_CalcFormulas(sfExcel2, false);
end; end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcStringFormula_BIFF5; procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcStringFormula_BIFF5;
begin begin
TestCalcFormulas(sfExcel5, false); Test_Write_Read_CalcFormulas(sfExcel5, false);
end; end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcStringFormula_BIFF8; procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcStringFormula_BIFF8;
begin begin
TestCalcFormulas(sfExcel8, false); Test_Write_Read_CalcFormulas(sfExcel8, false);
end; end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcStringFormula_OOXML; procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcStringFormula_OOXML;
begin begin
TestCalcFormulas(sfOOXML, false); Test_Write_Read_CalcFormulas(sfOOXML, false);
end; end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcStringFormula_ODS; procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcStringFormula_ODS;
begin begin
TestCalcFormulas(sfOpenDocument, false); Test_Write_Read_CalcFormulas(sfOpenDocument, false);
end;
//------------------------------------------------------------------------------
// Calculation of shared formulas
//------------------------------------------------------------------------------
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcSharedFormulas(
AFormat: TsSpreadsheetFormat);
const
SHEET = 'SharedFormulaSheet';
vA1 = 1.0;
vB1 = 2.0;
vC1 = 3.0;
vD1 = 4.0;
vE1 = 5.0;
vF1 = 'A';
var
MyWorksheet: TsWorksheet;
MyWorkbook: TsWorkbook;
cell: PCell;
row, col: Cardinal;
TempFile: String;
actual, expected: String;
sollValues: array[1..8, 0..5] of String;
begin
TempFile := GetTempFileName;
// Create test workbook
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.Options := MyWorkbook.Options + [boCalcBeforeSaving];
MyWorkSheet:= MyWorkBook.AddWorksheet(SHEET);
// Write out test values
MyWorksheet.WriteNumber(0, 0, vA1); // A1
MyWorksheet.WriteNumber(0, 1, vB1); // B1
MyWorksheet.WriteNumber(0, 2, vC1); // C1
MyWorksheet.WriteNumber(0, 3, vD1); // D1
MyWorksheet.WriteNumber(0, 4, vE1); // E1
MyWorksheet.WriteUTF8Text(0, 5, vF1); // F1
// Write out all test formulas
// sollValues contains the expected formula as seen from each cell in the
// shared formula block.
MyWorksheet.WriteSharedFormula('A2:F2', 'A1');
sollValues[1, 0] := Format('%g', [vA1]);
sollValues[1, 1] := Format('%g', [vB1]);
sollValues[1, 2] := Format('%g', [vC1]);
sollValues[1, 3] := Format('%g', [vD1]);
sollValues[1, 4] := Format('%g', [vE1]);
sollValues[1, 5] := vF1; // is a string
MyWorksheet.WriteSharedFormula('A3:F3', '$A1');
sollValues[2, 0] := Format('%g', [vA1]);
sollValues[2, 1] := Format('%g', [vA1]);
sollValues[2, 2] := Format('%g', [vA1]);
sollValues[2, 3] := Format('%g', [vA1]);
sollValues[2, 4] := Format('%g', [vA1]);
sollValues[2, 5] := Format('%g', [vA1]);
MyWorksheet.WriteSharedFormula('A4:F4', 'A$1');
sollValues[3, 0] := Format('%g', [vA1]);
sollValues[3, 1] := Format('%g', [vB1]);
sollValues[3, 2] := Format('%g', [vC1]);
sollValues[3, 3] := Format('%g', [vD1]);
sollValues[3, 4] := Format('%g', [vE1]);
sollValues[3, 5] := vF1; // is a string
MyWorksheet.WriteSharedFormula('A5:F5', '$A$1');
sollValues[4, 0] := Format('%g', [vA1]);
sollValues[4, 1] := Format('%g', [vA1]);
sollValues[4, 2] := Format('%g', [vA1]);
sollValues[4, 3] := Format('%g', [vA1]);
sollValues[4, 4] := Format('%g', [vA1]);
sollValues[4, 5] := Format('%g', [vA1]);
MyWorksheet.WriteSharedFormula('A6:F6', 'SIN(A1)');
sollValues[5, 0] := FloatToStr(sin(vA1)); // Using "FloatToStr" here like in ReadAsUTF8Text
sollValues[5, 1] := FloatToStr(sin(vB1));
sollValues[5, 2] := FloatToStr(sin(vC1));
sollValues[5, 3] := FloatToStr(sin(vD1));
sollValues[5, 4] := FloatToStr(sin(vE1));
sollValues[5, 5] := FloatToStr(sin(0.0)); // vF1 is a string
MyWorksheet.WriteSharedFormula('A7:F7', 'SIN($A1)');
sollValues[6, 0] := FloatToStr(sin(vA1));
sollValues[6, 1] := FloatToStr(sin(vA1));
sollValues[6, 2] := FloatToStr(sin(vA1));
sollValues[6, 3] := FloatToStr(sin(vA1));
sollValues[6, 4] := FloatToStr(sin(vA1));
sollValues[6, 5] := FloatToStr(sin(vA1));
MyWorksheet.WriteSharedFormula('A8:F8', 'SIN(A$1)');
sollValues[7, 0] := FloatToStr(sin(vA1));
sollValues[7, 1] := FloatToStr(sin(vB1));
sollValues[7, 2] := FloatToStr(sin(vC1));
sollValues[7, 3] := FloatToStr(sin(vD1));
sollValues[7, 4] := FloatToStr(sin(vE1));
sollValues[7, 5] := FloatToStr(sin(0.0)); // vF1 is a string
MyWorksheet.WriteSharedFormula('A9:F9', 'SIN($A$1)');
sollValues[8, 0] := FloatToStr(sin(vA1));
sollValues[8, 1] := FloatToStr(sin(vA1));
sollValues[8, 2] := FloatToStr(sin(vA1));
sollValues[8, 3] := FloatToStr(sin(vA1));
sollValues[8, 4] := FloatToStr(sin(vA1));
sollValues[8, 5] := FloatToStr(sin(vA1));
MyWorkBook.WriteToFile(TempFile, AFormat, true);
finally
MyWorkbook.Free;
end;
// Open the spreadsheet
MyWorkbook := TsWorkbook.Create;
try
MyWorkbook.Options := MyWorkbook.Options + [boReadFormulas, boAutoCalc];
MyWorkbook.ReadFromFile(TempFile, AFormat);
if AFormat = sfExcel2 then
MyWorksheet := MyWorkbook.GetFirstWorksheet
else
MyWorksheet := GetWorksheetByName(MyWorkBook, SHEET);
if MyWorksheet=nil then
fail('Error in test code. Failed to get named worksheet');
for row := 1 to 8 do begin
for col := 0 to MyWorksheet.GetLastColIndex do begin
cell := Myworksheet.FindCell(row, col);
if HasFormula(cell) then begin
actual := copy(MyWorksheet.ReadAsUTF8Text(cell), 1, 6); // cutting converted numbers off after some digits, certainly not always correct
expected := copy(SollValues[row, col], 1, 6);
CheckEquals(expected, actual, 'Test read formula mismatch, cell '+CellNotation(MyWorkSheet,Row,Col));
end else
fail('No formula found in cell ' + CellNotation(MyWorksheet, Row, Col));
end;
end;
finally
MyWorkbook.Free;
DeleteFile(TempFile);
end;
end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcSharedFormula_BIFF2;
begin
Test_Write_Read_CalcSharedFormulas(sfExcel2);
end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcSharedFormula_BIFF5;
begin
Test_Write_Read_CalcSharedFormulas(sfExcel5);
end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcSharedFormula_BIFF8;
begin
Test_Write_Read_CalcSharedFormulas(sfExcel8);
end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcSharedFormula_OOXML;
begin
Test_Write_Read_CalcSharedFormulas(sfOOXML);
end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcSharedFormula_ODS;
begin
Test_Write_Read_CalcSharedFormulas(sfOpenDocument);
end; end;

View File

@ -56,7 +56,6 @@
<Unit3> <Unit3>
<Filename Value="numberstests.pas"/> <Filename Value="numberstests.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="numberstests"/>
</Unit3> </Unit3>
<Unit4> <Unit4>
<Filename Value="manualtests.pas"/> <Filename Value="manualtests.pas"/>
@ -66,20 +65,20 @@
<Unit5> <Unit5>
<Filename Value="testsutility.pas"/> <Filename Value="testsutility.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="testsutility"/>
</Unit5> </Unit5>
<Unit6> <Unit6>
<Filename Value="internaltests.pas"/> <Filename Value="internaltests.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="internaltests"/>
</Unit6> </Unit6>
<Unit7> <Unit7>
<Filename Value="formattests.pas"/> <Filename Value="formattests.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="formattests"/>
</Unit7> </Unit7>
<Unit8> <Unit8>
<Filename Value="colortests.pas"/> <Filename Value="colortests.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="colortests"/>
</Unit8> </Unit8>
<Unit9> <Unit9>
<Filename Value="fonttests.pas"/> <Filename Value="fonttests.pas"/>
@ -110,10 +109,12 @@
<Unit15> <Unit15>
<Filename Value="errortests.pas"/> <Filename Value="errortests.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="errortests"/>
</Unit15> </Unit15>
<Unit16> <Unit16>
<Filename Value="virtualmodetests.pas"/> <Filename Value="virtualmodetests.pas"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="virtualmodetests"/>
</Unit16> </Unit16>
</Units> </Units>
</ProjectOptions> </ProjectOptions>