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;
|
||||
AWorksheet: TsWorksheet; ASheet1, ASheet2: String;
|
||||
ARow1, ACol1, ARow2, ACol2: Cardinal; AFlags: tsRelFlags; Is3DRange: Boolean);
|
||||
var
|
||||
tmp: Integer;
|
||||
begin
|
||||
FParser := AParser;
|
||||
FWorksheet := AWorksheet;
|
||||
FFlags := [];
|
||||
|
||||
if (ASheet1 = '') and (ASheet2 <> '') then
|
||||
raise Exception.Create('Invalid parameters in cell range');
|
||||
|
||||
FSheet[1] := GetWorkbook.GetWorksheetIndex(ASheet1);
|
||||
if ASheet2 = '' then FSheet[2] := FSheet[1] else FSheet[2] := GetWorkbook.GetWorksheetIndex(ASheet2);
|
||||
FRow[1] := ARow1;
|
||||
FCol[1] := ACol1;
|
||||
if ARow2 = Cardinal(-1) then FRow[2] := FRow[1] else FRow[2] := ARow2;
|
||||
if ACol2 = Cardinal(-1) then FCol[2] := FCol[1] else FCol[2] := ACol2;
|
||||
FFlags := AFlags;
|
||||
if ASheet2 <> '' then
|
||||
FSheet[2] := GetWorkbook.GetWorksheetIndex(ASheet2)
|
||||
else
|
||||
FSheet[2] := FSheet[1];
|
||||
EnsureOrder(FSheet[1], FSheet[2]);
|
||||
|
||||
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;
|
||||
end;
|
||||
|
||||
|
@ -5731,12 +5731,12 @@ begin
|
||||
|
||||
parser := TsSpreadsheetParser.Create(self);
|
||||
try
|
||||
if ALocalized then begin
|
||||
if ALocalized then
|
||||
// Convert "localized" formula to standard format
|
||||
parser.LocalizedExpression[Workbook.FormatSettings] := AFormula;
|
||||
AFormula := parser.Expression;
|
||||
end else
|
||||
parser.LocalizedExpression[Workbook.FormatSettings] := AFormula
|
||||
else
|
||||
parser.Expression := AFormula;
|
||||
AFormula := parser.Expression;
|
||||
if parser.Has3DLinks
|
||||
then ACell.Flags := ACell.Flags + [cf3dFormula]
|
||||
else ACell.Flags := ACell.Flags - [cf3dFormula];
|
||||
|
@ -23,7 +23,8 @@ type
|
||||
procedure SetUp; override;
|
||||
procedure TearDown; override;
|
||||
procedure TestFloatFormula(AFormula: String; AExpected: Double;
|
||||
ATestKind: TFormulaTestKind; AFormat: TsSpreadsheetFormat);
|
||||
ATestKind: TFormulaTestKind; AFormat: TsSpreadsheetFormat;
|
||||
AExpectedFormula: String = '');
|
||||
|
||||
published
|
||||
procedure AddConst_BIFF2;
|
||||
@ -54,6 +55,10 @@ type
|
||||
procedure SumMultiSheetRange_OOXML;
|
||||
procedure SumMultiSheetRange_ODS;
|
||||
|
||||
procedure SumMultiSheetRange_FlippedCells_OOXML;
|
||||
procedure SumMultiSheetRange_FlippedSheets_OOXML;
|
||||
procedure SumMultiSheetRange_FlippedSheetsAndCells_OOXML;
|
||||
|
||||
end;
|
||||
|
||||
implementation
|
||||
@ -78,7 +83,8 @@ begin
|
||||
end;
|
||||
|
||||
procedure TSpreadSingleFormulaTests.TestFloatFormula(AFormula: String;
|
||||
AExpected: Double; ATestKind: TFormulaTestKind; AFormat: TsSpreadsheetFormat);
|
||||
AExpected: Double; ATestKind: TFormulaTestKind; AFormat: TsSpreadsheetFormat;
|
||||
AExpectedFormula: String = '');
|
||||
const
|
||||
SHEET1 = 'Sheet1';
|
||||
SHEET2 = 'Sheet2';
|
||||
@ -95,6 +101,7 @@ var
|
||||
actualValue: Double;
|
||||
begin
|
||||
TempFile := GetTempFileName;
|
||||
if AExpectedFormula = '' then AExpectedFormula := AFormula;
|
||||
|
||||
try
|
||||
// Create test workbook and write test formula and needed cells
|
||||
@ -132,7 +139,7 @@ begin
|
||||
|
||||
// Read formula before saving
|
||||
actualFormula := cell^.Formulavalue;
|
||||
CheckEquals(AFormula, actualFormula, 'Unsaved formula text mismatch');
|
||||
CheckEquals(AExpectedFormula, actualFormula, 'Unsaved formula text mismatch');
|
||||
|
||||
// Read calculated value before saving
|
||||
actualvalue := worksheet.ReadAsNumber(TESTCELL_ROW, TESTCELL_COL);
|
||||
@ -157,7 +164,7 @@ begin
|
||||
|
||||
cell := worksheet.FindCell(TESTCELL_ROW, TESTCELL_COL);
|
||||
actualformula := cell^.FormulaValue;
|
||||
CheckEquals(AFormula, actualformula, 'Saved formula text mismatch.');
|
||||
CheckEquals(AExpectedFormula, actualformula, 'Saved formula text mismatch.');
|
||||
finally
|
||||
workbook.Free;
|
||||
end;
|
||||
@ -290,6 +297,23 @@ begin
|
||||
TestFloatFormula('SUM(Sheet2:Sheet3!C3:C5)', 55.0, ftkCellRangeSheetRange, sfOpenDocument);
|
||||
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
|
||||
// Register to include these tests in a full run
|
||||
RegisterTest(TSpreadSingleFormulaTests);
|
||||
|
Reference in New Issue
Block a user