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;
procedure ArgsToFloatArray(const Args: TsExprParameterArray; out AData: TsExprFloatArray);
function BooleanResult(AValue: Boolean): TsExpressionResult;
function CellResult(AValue: String): TsExpressionResult; overload;
function CellResult(ACellRow, ACellCol: Cardinal): TsExpressionResult; overload;
function DateTimeResult(AValue: TDateTime): TsExpressionResult;
function EmptyResult: TsExpressionResult;
function ErrorResult(const AValue: TsErrorValue): TsExpressionResult;
@ -4120,6 +4122,19 @@ begin
Result.ResBoolean := AValue;
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;
begin
Result.ResultType := rtDateTime;

View File

@ -30,12 +30,16 @@ type
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
// Test formula strings
procedure TestWriteReadFormulaStrings(AFormat: TsSpreadsheetFormat;
// Test reconstruction of formula strings
procedure Test_Write_Read_FormulaStrings(AFormat: TsSpreadsheetFormat;
UseRPNFormula: Boolean);
// Test reconstruction of shared formula strings
procedure Test_Write_Read_SharedFormulaStrings(AFormat: TsSpreadsheetFormat);
// Test calculation of rpn formulas
procedure TestCalcFormulas(AFormat: TsSpreadsheetformat; UseRPNFormula: Boolean);
// Test calculation of formulas
procedure Test_Write_Read_CalcFormulas(AFormat: TsSpreadsheetformat;
UseRPNFormula: Boolean);
// Test calculation of shared formulas
procedure Test_Write_Read_CalcSharedFormulas(AFormat: TsSpreadsheetformat);
published
// Writes out formulas & reads them back.
@ -85,6 +89,19 @@ type
procedure Test_Write_Read_CalcStringFormula_OOXML;
{ ODS Tests }
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;
implementation
@ -116,7 +133,7 @@ begin
inherited TearDown;
end;
procedure TSpreadWriteReadFormulaTests.TestWriteReadFormulaStrings(
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_FormulaStrings(
AFormat: TsSpreadsheetFormat; UseRPNFormula: Boolean);
{ If UseRPNFormula is true the test formulas are generated from RPN formulas.
Otherwise they are generated from string formulas. }
@ -185,27 +202,27 @@ end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_FormulaStrings_BIFF2;
begin
TestWriteReadFormulaStrings(sfExcel2, true);
Test_Write_Read_FormulaStrings(sfExcel2, true);
end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_FormulaStrings_BIFF5;
begin
TestWriteReadFormulaStrings(sfExcel5, true);
Test_Write_Read_FormulaStrings(sfExcel5, true);
end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_FormulaStrings_BIFF8;
begin
TestWriteReadFormulaStrings(sfExcel8, true);
Test_Write_Read_FormulaStrings(sfExcel8, true);
end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_FormulaStrings_OOXML;
begin
TestWriteReadFormulaStrings(sfOOXML, true);
Test_Write_Read_FormulaStrings(sfOOXML, true);
end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_FormulaStrings_ODS;
begin
TestWriteReadFormulaStrings(sfOpenDocument, true);
Test_Write_Read_FormulaStrings(sfOpenDocument, true);
end;
@ -222,7 +239,7 @@ var
row, col: Cardinal;
TempFile: String;
actual, expected: String;
sollValues: array[1..4, 0..5] of string;
sollValues: array[1..4, 0..4] of string;
begin
TempFile := GetTempFileName;
@ -338,8 +355,8 @@ end;
{ Test calculation of formulas }
procedure TSpreadWriteReadFormulaTests.TestCalcFormulas(AFormat: TsSpreadsheetFormat;
UseRPNFormula: Boolean);
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcFormulas(
AFormat: TsSpreadsheetFormat; UseRPNFormula: Boolean);
{ If UseRPNFormula is TRUE, the test formulas are generated from RPN syntax,
otherwise string formulas are used. }
const
@ -482,52 +499,213 @@ end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcRPNFormula_BIFF2;
begin
TestCalcFormulas(sfExcel2, true);
Test_Write_Read_CalcFormulas(sfExcel2, true);
end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcRPNFormula_BIFF5;
begin
TestCalcFormulas(sfExcel5, true);
Test_Write_Read_CalcFormulas(sfExcel5, true);
end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcRPNFormula_BIFF8;
begin
TestCalcFormulas(sfExcel8, true);
Test_Write_Read_CalcFormulas(sfExcel8, true);
end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcRPNFormula_OOXML;
begin
TestCalcFormulas(sfOOXML, true);
Test_Write_Read_CalcFormulas(sfOOXML, true);
end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcRPNFormula_ODS;
begin
TestCalcFormulas(sfOpenDocument, true);
Test_Write_Read_CalcFormulas(sfOpenDocument, true);
end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcStringFormula_BIFF2;
begin
TestCalcFormulas(sfExcel2, false);
Test_Write_Read_CalcFormulas(sfExcel2, false);
end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcStringFormula_BIFF5;
begin
TestCalcFormulas(sfExcel5, false);
Test_Write_Read_CalcFormulas(sfExcel5, false);
end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcStringFormula_BIFF8;
begin
TestCalcFormulas(sfExcel8, false);
Test_Write_Read_CalcFormulas(sfExcel8, false);
end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcStringFormula_OOXML;
begin
TestCalcFormulas(sfOOXML, false);
Test_Write_Read_CalcFormulas(sfOOXML, false);
end;
procedure TSpreadWriteReadFormulaTests.Test_Write_Read_CalcStringFormula_ODS;
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;

View File

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