You've already forked lazarus-ccr
fpspreadsheet: Fix missing error when cells are moved so that a circular reference formula is created (https://forum.lazarus.freepascal.org/index.php/topic,59137.msg441301.html#msg441301).
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@8269 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -2274,9 +2274,12 @@ end;
|
||||
procedure TsWorksheet.MoveCell(ACell: PCell; AToRow, AToCol: Cardinal);
|
||||
var
|
||||
fromRow, fromCol: Cardinal;
|
||||
destCell: PCell;
|
||||
sheet: TsWorksheet;
|
||||
i: Integer;
|
||||
formula: String;
|
||||
formula: PsFormula;
|
||||
formulaStr: String;
|
||||
srcHasFormula: Boolean;
|
||||
begin
|
||||
if ACell = nil then
|
||||
exit;
|
||||
@ -2294,12 +2297,12 @@ begin
|
||||
// location. This is different from copying a formula.
|
||||
// --> We must prevent CopyCell from adjusting the formula
|
||||
// --> Erase the formula temporarily.
|
||||
formula := ReadFormula(ACell);
|
||||
formulaStr := ReadFormula(ACell);
|
||||
DeleteFormula(ACell);
|
||||
CopyCell(fromRow, fromCol, AToRow, AToCol);
|
||||
// Restore the old formula which points to the old location.
|
||||
if formula <> '' then
|
||||
WriteFormula(AToRow, AToCol, formula);
|
||||
if formulaStr <> '' then
|
||||
WriteFormula(AToRow, AToCol, formulaStr);
|
||||
|
||||
// Fix formula references to this cell
|
||||
for i := 0 to FWorkbook.GetWorksheetcount-1 do begin
|
||||
@ -2307,6 +2310,11 @@ begin
|
||||
sheet.Formulas.FixReferenceToMovedCell(ACell, AToRow, AToCol, self);
|
||||
end;
|
||||
|
||||
// Mark destination cell to contain a formula (if applicable).
|
||||
destCell := FindCell(AToRow, AToCol);
|
||||
formula := Formulas.FindFormula(destCell);
|
||||
UseFormulaInCell(destCell, formula);
|
||||
|
||||
// Delete cell at old location
|
||||
DeleteCell(ACell);
|
||||
|
||||
|
@ -22,6 +22,7 @@ type
|
||||
|
||||
protected
|
||||
procedure Test_MoveCell(ATestKind: Integer);
|
||||
procedure Test_MoveCell_CircRef(ATestKind: Integer);
|
||||
|
||||
published
|
||||
procedure Test_MoveCell_Value;
|
||||
@ -32,6 +33,9 @@ type
|
||||
procedure Test_MoveCell_Formula_ABS;
|
||||
procedure Test_MoveCell_FormulaRef_REL;
|
||||
procedure Test_MoveCell_FormulaRef_ABS;
|
||||
|
||||
procedure Test_MoveCell_FormulaToValue;
|
||||
procedure Test_MoveCell_ValueToFormula;
|
||||
end;
|
||||
|
||||
implementation
|
||||
@ -185,6 +189,68 @@ begin
|
||||
Test_MoveCell(8);
|
||||
end;
|
||||
|
||||
{==============================================================================}
|
||||
|
||||
{ In the following test an occupied cell is moved to a different location
|
||||
such that a circular reference is created.
|
||||
ATestKind = 1: value cell is moved to formula cell which points to value cell
|
||||
2: formula cell is moved to cell to which it points. }
|
||||
procedure TSpreadMoveTests.Test_MoveCell_CircRef(ATestKind: Integer);
|
||||
const
|
||||
VALUE_CELL_ROW = 0;
|
||||
VALUE_CELL_COL = 0;
|
||||
FORMULA_CELL_ROW = 11;
|
||||
FORMULA_CELL_COL = 6;
|
||||
var
|
||||
worksheet: TsWorksheet;
|
||||
workbook: TsWorkbook;
|
||||
value_cell: PCell = nil;
|
||||
formula_cell: PCell = nil;
|
||||
dest_cell: PCell = nil;
|
||||
begin
|
||||
workbook := TsWorkbook.Create;
|
||||
try
|
||||
workbook.Options := workbook.Options + [boAutoCalc];
|
||||
|
||||
worksheet := workBook.AddWorksheet(MoveTestSheet);
|
||||
|
||||
// Prepare the worksheet in which a cell is moved.
|
||||
// The value cell is A1, the formula cell is B2 and it points to A1
|
||||
value_cell := worksheet.WriteText(VALUE_CELL_ROW, VALUE_CELL_COL, 'abc'); // A1
|
||||
formula_cell := worksheet.WriteFormula(FORMULA_CELL_ROW, FORMULA_CELL_COL, 'A1');
|
||||
|
||||
// Move the cell
|
||||
try
|
||||
case ATestKind of
|
||||
1: begin
|
||||
worksheet.MoveCell(value_cell, FORMULA_CELL_ROW, FORMULA_CELL_COL);
|
||||
dest_cell := worksheet.FindCell(FORMULA_CELL_ROW, FORMULA_CELL_COL);
|
||||
end;
|
||||
2: begin
|
||||
worksheet.MoveCell(formula_cell, VALUE_CELL_ROW, VALUE_CELL_COL);
|
||||
dest_cell := worksheet.FindCell(VALUE_CELL_ROW, VALUE_CELL_COL);
|
||||
end;
|
||||
end;
|
||||
except
|
||||
end;
|
||||
|
||||
// In each case, the destination cell should contain a #REF! error
|
||||
CheckEquals(true, dest_cell^.ErrorValue = errIllegalRef, 'Circular reference not detected.');
|
||||
|
||||
finally
|
||||
workbook.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSpreadMoveTests.Test_MoveCell_FormulaToValue;
|
||||
begin
|
||||
Test_MoveCell_CircRef(1);
|
||||
end;
|
||||
|
||||
procedure TSpreadMoveTests.Test_MoveCell_ValueToFormula;
|
||||
begin
|
||||
Test_MoveCell_CircRef(2);
|
||||
end;
|
||||
|
||||
initialization
|
||||
RegisterTest(TSpreadMoveTests);
|
||||
|
@ -233,7 +233,7 @@
|
||||
</Linking>
|
||||
</CompilerOptions>
|
||||
<Debugging>
|
||||
<Exceptions Count="7">
|
||||
<Exceptions Count="8">
|
||||
<Item1>
|
||||
<Name Value="EAbort"/>
|
||||
<Enabled Value="False"/>
|
||||
@ -259,6 +259,9 @@
|
||||
<Item7>
|
||||
<Name Value="EFPSpreadsheetReader"/>
|
||||
</Item7>
|
||||
<Item8>
|
||||
<Name Value="ECalcEngine"/>
|
||||
</Item8>
|
||||
</Exceptions>
|
||||
</Debugging>
|
||||
</CONFIG>
|
||||
|
Reference in New Issue
Block a user