You've already forked lazarus-ccr
fpspreadsheet: Ignore the order of indexes in cell ranges when parsing formulas. Add corresponding unit tests.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@6420 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -3991,16 +3991,55 @@ end;
|
|||||||
constructor TsCellRangeExprNode.Create(AParser: TsExpressionParser;
|
constructor TsCellRangeExprNode.Create(AParser: TsExpressionParser;
|
||||||
AWorksheet: TsWorksheet; ASheet1, ASheet2: String;
|
AWorksheet: TsWorksheet; ASheet1, ASheet2: String;
|
||||||
ARow1, ACol1, ARow2, ACol2: Cardinal; AFlags: tsRelFlags; Is3DRange: Boolean);
|
ARow1, ACol1, ARow2, ACol2: Cardinal; AFlags: tsRelFlags; Is3DRange: Boolean);
|
||||||
|
var
|
||||||
|
tmp: Integer;
|
||||||
begin
|
begin
|
||||||
FParser := AParser;
|
FParser := AParser;
|
||||||
FWorksheet := AWorksheet;
|
FWorksheet := AWorksheet;
|
||||||
|
FFlags := [];
|
||||||
|
|
||||||
|
if (ASheet1 = '') and (ASheet2 <> '') then
|
||||||
|
raise Exception.Create('Invalid parameters in cell range');
|
||||||
|
|
||||||
FSheet[1] := GetWorkbook.GetWorksheetIndex(ASheet1);
|
FSheet[1] := GetWorkbook.GetWorksheetIndex(ASheet1);
|
||||||
if ASheet2 = '' then FSheet[2] := FSheet[1] else FSheet[2] := GetWorkbook.GetWorksheetIndex(ASheet2);
|
if ASheet2 <> '' then
|
||||||
FRow[1] := ARow1;
|
FSheet[2] := GetWorkbook.GetWorksheetIndex(ASheet2)
|
||||||
FCol[1] := ACol1;
|
else
|
||||||
if ARow2 = Cardinal(-1) then FRow[2] := FRow[1] else FRow[2] := ARow2;
|
FSheet[2] := FSheet[1];
|
||||||
if ACol2 = Cardinal(-1) then FCol[2] := FCol[1] else FCol[2] := ACol2;
|
EnsureOrder(FSheet[1], FSheet[2]);
|
||||||
FFlags := AFlags;
|
|
||||||
|
if ARow2 = Cardinal(-1) then
|
||||||
|
ARow2 := ARow1;
|
||||||
|
if ARow1 <= ARow2 then
|
||||||
|
begin
|
||||||
|
FRow[1] := ARow1;
|
||||||
|
FRow[2] := ARow2;
|
||||||
|
FCol[1] := ACol1;
|
||||||
|
if rfRelRow in AFlags then Include(FFlags, rfRelRow);
|
||||||
|
if rfRelRow2 in AFlags then Include(FFlags, rfRelRow2);
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
FRow[1] := ARow2;
|
||||||
|
FRow[2] := ARow1;
|
||||||
|
if rfRelRow in AFlags then Include(FFlags, rfRelRow2);
|
||||||
|
if rfRelRow2 in AFlags then Include(FFlags, rfRelRow);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if ACol2 = Cardinal(-1) then
|
||||||
|
ACol2 := ACol1;
|
||||||
|
if ACol1 <= ACol2 then
|
||||||
|
begin
|
||||||
|
FCol[1] := ACol1;
|
||||||
|
FCol[2] := ACol2;
|
||||||
|
if (rfRelCol in AFlags) then Include(FFlags, rfRelCol);
|
||||||
|
if (rfRelCol2 in AFlags) then Include(FFlags, rfRelCol2);
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
FCol[1] := ACol2;
|
||||||
|
FCol[2] := ACol1;
|
||||||
|
if (rfRelCol in AFlags) then Include(FFlags, rfRelCol2);
|
||||||
|
if (rfRelCol2 in AFlags) then Include(FFlags, rfRelCol);
|
||||||
|
end;
|
||||||
F3dRange := Is3dRange;
|
F3dRange := Is3dRange;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -5731,12 +5731,12 @@ begin
|
|||||||
|
|
||||||
parser := TsSpreadsheetParser.Create(self);
|
parser := TsSpreadsheetParser.Create(self);
|
||||||
try
|
try
|
||||||
if ALocalized then begin
|
if ALocalized then
|
||||||
// Convert "localized" formula to standard format
|
// Convert "localized" formula to standard format
|
||||||
parser.LocalizedExpression[Workbook.FormatSettings] := AFormula;
|
parser.LocalizedExpression[Workbook.FormatSettings] := AFormula
|
||||||
AFormula := parser.Expression;
|
else
|
||||||
end else
|
|
||||||
parser.Expression := AFormula;
|
parser.Expression := AFormula;
|
||||||
|
AFormula := parser.Expression;
|
||||||
if parser.Has3DLinks
|
if parser.Has3DLinks
|
||||||
then ACell.Flags := ACell.Flags + [cf3dFormula]
|
then ACell.Flags := ACell.Flags + [cf3dFormula]
|
||||||
else ACell.Flags := ACell.Flags - [cf3dFormula];
|
else ACell.Flags := ACell.Flags - [cf3dFormula];
|
||||||
|
@ -23,7 +23,8 @@ type
|
|||||||
procedure SetUp; override;
|
procedure SetUp; override;
|
||||||
procedure TearDown; override;
|
procedure TearDown; override;
|
||||||
procedure TestFloatFormula(AFormula: String; AExpected: Double;
|
procedure TestFloatFormula(AFormula: String; AExpected: Double;
|
||||||
ATestKind: TFormulaTestKind; AFormat: TsSpreadsheetFormat);
|
ATestKind: TFormulaTestKind; AFormat: TsSpreadsheetFormat;
|
||||||
|
AExpectedFormula: String = '');
|
||||||
|
|
||||||
published
|
published
|
||||||
procedure AddConst_BIFF2;
|
procedure AddConst_BIFF2;
|
||||||
@ -54,6 +55,10 @@ type
|
|||||||
procedure SumMultiSheetRange_OOXML;
|
procedure SumMultiSheetRange_OOXML;
|
||||||
procedure SumMultiSheetRange_ODS;
|
procedure SumMultiSheetRange_ODS;
|
||||||
|
|
||||||
|
procedure SumMultiSheetRange_FlippedCells_OOXML;
|
||||||
|
procedure SumMultiSheetRange_FlippedSheets_OOXML;
|
||||||
|
procedure SumMultiSheetRange_FlippedSheetsAndCells_OOXML;
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -78,7 +83,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSpreadSingleFormulaTests.TestFloatFormula(AFormula: String;
|
procedure TSpreadSingleFormulaTests.TestFloatFormula(AFormula: String;
|
||||||
AExpected: Double; ATestKind: TFormulaTestKind; AFormat: TsSpreadsheetFormat);
|
AExpected: Double; ATestKind: TFormulaTestKind; AFormat: TsSpreadsheetFormat;
|
||||||
|
AExpectedFormula: String = '');
|
||||||
const
|
const
|
||||||
SHEET1 = 'Sheet1';
|
SHEET1 = 'Sheet1';
|
||||||
SHEET2 = 'Sheet2';
|
SHEET2 = 'Sheet2';
|
||||||
@ -95,6 +101,7 @@ var
|
|||||||
actualValue: Double;
|
actualValue: Double;
|
||||||
begin
|
begin
|
||||||
TempFile := GetTempFileName;
|
TempFile := GetTempFileName;
|
||||||
|
if AExpectedFormula = '' then AExpectedFormula := AFormula;
|
||||||
|
|
||||||
try
|
try
|
||||||
// Create test workbook and write test formula and needed cells
|
// Create test workbook and write test formula and needed cells
|
||||||
@ -132,7 +139,7 @@ begin
|
|||||||
|
|
||||||
// Read formula before saving
|
// Read formula before saving
|
||||||
actualFormula := cell^.Formulavalue;
|
actualFormula := cell^.Formulavalue;
|
||||||
CheckEquals(AFormula, actualFormula, 'Unsaved formula text mismatch');
|
CheckEquals(AExpectedFormula, actualFormula, 'Unsaved formula text mismatch');
|
||||||
|
|
||||||
// Read calculated value before saving
|
// Read calculated value before saving
|
||||||
actualvalue := worksheet.ReadAsNumber(TESTCELL_ROW, TESTCELL_COL);
|
actualvalue := worksheet.ReadAsNumber(TESTCELL_ROW, TESTCELL_COL);
|
||||||
@ -157,7 +164,7 @@ begin
|
|||||||
|
|
||||||
cell := worksheet.FindCell(TESTCELL_ROW, TESTCELL_COL);
|
cell := worksheet.FindCell(TESTCELL_ROW, TESTCELL_COL);
|
||||||
actualformula := cell^.FormulaValue;
|
actualformula := cell^.FormulaValue;
|
||||||
CheckEquals(AFormula, actualformula, 'Saved formula text mismatch.');
|
CheckEquals(AExpectedFormula, actualformula, 'Saved formula text mismatch.');
|
||||||
finally
|
finally
|
||||||
workbook.Free;
|
workbook.Free;
|
||||||
end;
|
end;
|
||||||
@ -290,6 +297,23 @@ begin
|
|||||||
TestFloatFormula('SUM(Sheet2:Sheet3!C3:C5)', 55.0, ftkCellRangeSheetRange, sfOpenDocument);
|
TestFloatFormula('SUM(Sheet2:Sheet3!C3:C5)', 55.0, ftkCellRangeSheetRange, sfOpenDocument);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ --- }
|
||||||
|
|
||||||
|
procedure TSpreadSingleFormulaTests.SumMultiSheetRange_FlippedSheetsAndCells_OOXML;
|
||||||
|
begin
|
||||||
|
TestFloatFormula('SUM(Sheet3:Sheet2!C5:C3)', 55.0, ftkCellRangeSheetRange, sfOOXML, 'SUM(Sheet2:Sheet3!C3:C5)');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSpreadSingleFormulaTests.SumMultiSheetRange_FlippedCells_OOXML;
|
||||||
|
begin
|
||||||
|
TestFloatFormula('SUM(Sheet2:Sheet3!C5:C3)', 55.0, ftkCellRangeSheetRange, sfOOXML, 'SUM(Sheet2:Sheet3!C3:C5)');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSpreadSingleFormulaTests.SumMultiSheetRange_FlippedSheets_OOXML;
|
||||||
|
begin
|
||||||
|
TestFloatFormula('SUM(Sheet3:Sheet2!C3:C5)', 55.0, ftkCellRangeSheetRange, sfOOXML, 'SUM(Sheet2:Sheet3!C3:C5)');
|
||||||
|
end;
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
// Register to include these tests in a full run
|
// Register to include these tests in a full run
|
||||||
RegisterTest(TSpreadSingleFormulaTests);
|
RegisterTest(TSpreadSingleFormulaTests);
|
||||||
|
Reference in New Issue
Block a user