diff --git a/components/fpspreadsheet/examples/other/demo_expression_parser.pas b/components/fpspreadsheet/examples/other/demo_expression_parser.pas
index 8f3db5e44..7c9c9bc81 100644
--- a/components/fpspreadsheet/examples/other/demo_expression_parser.pas
+++ b/components/fpspreadsheet/examples/other/demo_expression_parser.pas
@@ -41,7 +41,8 @@ begin
//cell := Worksheet.WriteFormula(1, 0, 'Day(Date(2014, 1, 12))');
//cell := Worksheet.WriteFormula(1, 0, 'SUM(1,2,3)');
//cell := Worksheet.WriteFormula(1, 0, 'CELL("address",A1)');
- cell := Worksheet.WriteFormula(1, 0, 'REPT("Hallo", 3)');
+// cell := Worksheet.WriteFormula(1, 0, 'REPT("Hallo", 3)');
+ cell := Worksheet.WriteFormula(1, 0, '#REF!');
WriteLn('A1: ', worksheet.ReadAsUTF8Text(0, 0));
WriteLn('B1: ', worksheet.ReadAsUTF8Text(0, 1));
@@ -76,6 +77,7 @@ begin
fekInteger : Write(' / integer value: ', IntToStr(formula[i].IntValue));
fekString : Write(' / string value: "', formula[i].StringValue, '"');
fekBool : Write(' / boolean value: ', BoolToStr(formula[i].DoubleValue <> 0, true));
+ fekErr : Write(' / error value: ', GetErrorValueStr(TsErrorValue(formula[i].IntValue)));
end;
WriteLn;
end;
diff --git a/components/fpspreadsheet/fpsexprparser.pas b/components/fpspreadsheet/fpsexprparser.pas
index 268579c29..6aa12dc43 100644
--- a/components/fpspreadsheet/fpsexprparser.pas
+++ b/components/fpspreadsheet/fpsexprparser.pas
@@ -57,20 +57,11 @@ uses
type
{ Tokens }
-(* { Basic operands }
- fekCell, fekCellRef, fekCellRange, fekCellOffset, fekNum, fekInteger,
- fekString, fekBool, fekErr, fekMissingArg,
- { Basic operations }
- fekAdd, fekSub, fekMul, fekDiv, fekPercent, fekPower, fekUMinus, fekUPlus,
- fekConcat, // string concatenation
- fekEqual, fekGreater, fekGreaterEqual, fekLess, fekLessEqual, fekNotEqual,
- fekParen,
-*)
TsTokenType = (
ttCell, ttCellRange, ttNumber, ttString, ttIdentifier,
ttPlus, ttMinus, ttMul, ttDiv, ttConcat, ttPercent, ttPower, ttLeft, ttRight,
ttLessThan, ttLargerThan, ttEqual, ttNotEqual, ttLessThanEqual, ttLargerThanEqual,
- ttListSep, ttTrue, ttFalse, ttEOF
+ ttListSep, ttTrue, ttFalse, ttError, ttEOF
);
TsExprFloat = Double;
@@ -409,7 +400,8 @@ type
constructor CreateDateTime(AParser: TsExpressionParser; AValue: TDateTime);
constructor CreateFloat(AParser: TsExpressionParser; AValue: TsExprFloat);
constructor CreateBoolean(AParser: TsExpressionParser; AValue: Boolean);
- constructor CreateError(AParser: TsExpressionParser; AValue: TsErrorValue);
+ constructor CreateError(AParser: TsExpressionParser; AValue: TsErrorValue); overload;
+ constructor CreateError(AParser: TsExpressionParser; AValue: String); overload;
function AsString: string; override;
function AsRPNItem(ANext: PRPNItem): PRPNItem; override;
function NodeType : TsResultType; override;
@@ -653,6 +645,7 @@ type
procedure ScanError(Msg: String);
protected
procedure SetSource(const AValue: String); virtual;
+ function DoError: TsTokenType;
function DoIdentifier: TsTokenType;
function DoNumber: TsTokenType;
function DoDelimiter: TsTokenType;
@@ -842,6 +835,7 @@ uses
const
cNull = #0;
cDoubleQuote = '"';
+ cError = '#';
Digits = ['0'..'9']; // + decimalseparator
WhiteSpace = [' ', #13, #10, #9];
@@ -998,6 +992,21 @@ begin
end;
end;
+function TsExpressionScanner.DoError: TsTokenType;
+var
+ C: Char;
+ s: String;
+begin
+ C := CurrentChar;
+ while (not IsWordDelim(C)) and (C <> cNull) do
+ begin
+ FToken := FToken + C;
+ C := NextPos;
+ end;
+ S := UpperCase(Token);
+ Result := ttError;
+end;
+
function TsExpressionScanner.DoIdentifier: TsTokenType;
var
C: Char;
@@ -1137,6 +1146,8 @@ begin
Result := DoString
else if IsDigit(C) then
Result := DoNumber
+ else if (C = cError) then
+ Result := DoError
else if IsAlpha(C) or (C = '$') then
Result := DoIdentifier
else
@@ -1662,6 +1673,8 @@ begin
Result := TsCellExprNode.Create(self, FWorksheet, CurrentToken)
else if (TokenType = ttCellRange) then
Result := TsCellRangeExprNode.Create(self, FWorksheet, CurrentToken)
+ else if (TokenType = ttError) then
+ Result := tsConstExprNode.CreateError(self, CurrentToken)
else if not (TokenType in [ttIdentifier]) then
ParserError(Format(SerrUnknownTokenAtPos, [Scanner.Pos, CurrentToken]))
else
@@ -2648,6 +2661,28 @@ begin
FValue.ResError := AValue;
end;
+constructor TsConstExprNode.CreateError(AParser: TsExpressionParser;
+ AValue: String);
+var
+ err: TsErrorValue;
+begin
+ if AValue = '#NULL!' then
+ err := errEmptyIntersection
+ else if AValue = '#DIV/0!' then
+ err := errDivideByZero
+ else if AValue = '#VALUE!' then
+ err := errWrongType
+ else if AVAlue = '#REF!' then
+ err := errIllegalRef
+ else if AVAlue = '#NAME?' then
+ err := errWrongName
+ else if AValue = '#FORMULA?' then
+ err := errFormulaNotSupported
+ else
+ AParser.ParserError('Unknown error type.');
+ CreateError(AParser, err);
+end;
+
procedure TsConstExprNode.Check;
begin
// Nothing to check;
@@ -2671,6 +2706,7 @@ begin
rtDateTime : Result := '''' + FormatDateTime('cccc', FValue.ResDateTime, Parser.FFormatSettings) + ''''; // Probably wrong !!!
rtBoolean : if FValue.ResBoolean then Result := 'TRUE' else Result := 'FALSE';
rtFloat : Result := FloatToStr(FValue.ResFloat, Parser.FFormatSettings);
+ rtError : Result := GetErrorValueStr(FValue.ResError);
end;
end;
@@ -2682,6 +2718,7 @@ begin
rtDateTime : Result := RPNNumber(FValue.ResDateTime, ANext);
rtBoolean : Result := RPNBool(FValue.ResBoolean, ANext);
rtFloat : Result := RPNNumber(FValue.ResFloat, ANext);
+ rtError : Result := RPNErr(ord(FValue.ResError), ANext);
end;
end;
diff --git a/components/fpspreadsheet/fpspreadsheet.pas b/components/fpspreadsheet/fpspreadsheet.pas
index 76b25124b..8147f57fb 100755
--- a/components/fpspreadsheet/fpspreadsheet.pas
+++ b/components/fpspreadsheet/fpspreadsheet.pas
@@ -5068,9 +5068,13 @@ var
r, c, rr, cc: Cardinal;
r1, c1, r2, c2: Cardinal;
cell, nextcell, basecell: PCell;
+ lastCol, lastRow: Cardinal;
begin
+ lastCol := GetLastColIndex;
+ lastRow := GetLastOccupiedRowIndex;
+
// Loop along the column to be deleted and fix merged cells and shared formulas
- for r := 0 to GetLastRowIndex do
+ for r := 0 to lastRow do
begin
cell := FindCell(r, ACol);
@@ -5099,8 +5103,8 @@ begin
// Write adapted formula to the cell below.
WriteFormula(nextcell, basecell^.Formulavalue); //ReadFormulaAsString(nextcell));
// Have all cells sharing the formula use the new formula base
- for rr := r to GetLastOccupiedRowIndex do
- for cc := ACol+1 to GetLastOccupiedColIndex do
+ for rr := r to lastRow do
+ for cc := ACol+1 to lastCol do
begin
cell := FindCell(rr, cc);
if (cell <> nil) and (cell^.SharedFormulaBase = basecell) then
@@ -5112,7 +5116,7 @@ begin
end;
// Delete cells
- for r := GetLastRowIndex downto 0 do
+ for r := lastRow downto 0 do
RemoveCell(r, ACol);
// Update column index of cell records
diff --git a/components/fpspreadsheet/tests/insertdeletetests.pas b/components/fpspreadsheet/tests/insertdeletetests.pas
index ecc9a59d6..c133616f1 100644
--- a/components/fpspreadsheet/tests/insertdeletetests.pas
+++ b/components/fpspreadsheet/tests/insertdeletetests.pas
@@ -23,6 +23,7 @@ type
DeleteCol: Integer;
DeleteRow: Integer;
Formula: String;
+ SollFormula: String;
SharedFormulaRowCount: Integer;
SharedFormulaColCount: Integer;
MergedColCount: Integer;
@@ -31,7 +32,7 @@ type
end;
var
- InsDelTestData: array[0..5] of TInsDelTestDataItem;
+ InsDelTestData: array[0..21] of TInsDelTestDataItem;
procedure InitTestData;
@@ -54,6 +55,30 @@ type
procedure TestWriteRead_InsDelColRow_3; // first
procedure TestWriteRead_InsDelColRow_4; // middle
procedure TestWriteRead_InsDelColRow_5; // last
+ // Writes out simple cell layout and inserts rows
+ procedure TestWriteRead_InsDelColRow_6; // before first
+ procedure TestWriteRead_InsDelColRow_7; // middle
+ procedure TestWriteRead_InsDelColRow_8; // before last
+ // Writes out simple cell layout and deletes rows
+ procedure TestWriteRead_InsDelColRow_9; // first
+ procedure TestWriteRead_InsDelColRow_10; // middle
+ procedure TestWriteRead_InsDelColRow_11; // last
+
+ // Writes out cell layout with formula and inserts columns
+ procedure TestWriteRead_InsDelColRow_12; // before formula cell
+ procedure TestWriteRead_InsDelColRow_13; // after formula cell
+ // Writes out cell layout with formula and inserts rows
+ procedure TestWriteRead_InsDelColRow_14; // before formula cell
+ procedure TestWriteRead_InsDelColRow_15; // after formula cell
+ // Writes out cell layout with formula and deletes columns
+ procedure TestWriteRead_InsDelColRow_16; // before formula cell
+ procedure TestWriteRead_InsDelColRow_17; // after formula cell
+ procedure TestWriteRead_InsDelColRow_18; // cell in formula
+ // Writes out cell layout with formula and deletes rows
+ procedure TestWriteRead_InsDelColRow_19; // before formula cell
+ procedure TestWriteRead_InsDelColRow_20; // after formula cell
+ procedure TestWriteRead_InsDelColRow_21; // cell in formula
+
end;
implementation
@@ -77,12 +102,17 @@ begin
DeleteCol := -1;
DeleteRow := -1;
Formula := '';
+ SollFormula := '';
SharedFormulaColCount := 0;
SharedFormulaRowCount := 0;
MergedColCount := 0;
MergedRowCount := 0;
end;
+ { ---------------------------------------------------------------------------}
+ { Simple layouts }
+ { ---------------------------------------------------------------------------}
+
// Insert a column before col 0
with InsDelTestData[0] do begin
Layout := '12345678|'+
@@ -160,6 +190,305 @@ begin
'3456789|'+
'4567890';
end;
+
+ // Insert a ROW before row 0
+ with InsDelTestData[6] do begin
+ Layout := '12345|'+
+ '23456|'+
+ '34567|'+
+ '45678|'+
+ '56789|'+
+ '67890|';
+ InsertRow := 0;
+ SollLayout := ' |'+
+ '12345|'+
+ '23456|'+
+ '34567|'+
+ '45678|'+
+ '56789|'+
+ '67890|';
+ end;
+
+ // Insert a ROW before row 2
+ with InsDelTestData[7] do begin
+ Layout := '12345|'+
+ '23456|'+
+ '34567|'+
+ '45678|'+
+ '56789|'+
+ '67890|';
+ InsertRow := 2;
+ SollLayout := '12345|'+
+ '23456|'+
+ ' |'+
+ '34567|'+
+ '45678|'+
+ '56789|'+
+ '67890|';
+ end;
+
+ // Insert a ROW before last row
+ with InsDelTestData[8] do begin
+ Layout := '12345|'+
+ '23456|'+
+ '34567|'+
+ '45678|'+
+ '56789|'+
+ '67890|';
+ InsertRow := 5;
+ SollLayout := '12345|'+
+ '23456|'+
+ '34567|'+
+ '45678|'+
+ '56789|'+
+ ' |'+
+ '67890|';
+ end;
+
+ // Delete the first row
+ with InsDelTestData[9] do begin
+ Layout := '12345|'+
+ '23456|'+
+ '34567|'+
+ '45678|'+
+ '56789|'+
+ '67890|';
+ DeleteRow := 0;
+ SollLayout := '23456|'+
+ '34567|'+
+ '45678|'+
+ '56789|'+
+ '67890|';
+ end;
+
+ // Delete row #2
+ with InsDelTestData[10] do begin
+ Layout := '12345|'+
+ '23456|'+
+ '34567|'+
+ '45678|'+
+ '56789|'+
+ '67890|';
+ DeleteRow := 2;
+ SollLayout := '12345|'+
+ '23456|'+
+ '45678|'+
+ '56789|'+
+ '67890|';
+ end;
+
+ // Delete last row
+ with InsDelTestData[11] do begin
+ Layout := '12345|'+
+ '23456|'+
+ '34567|'+
+ '45678|'+
+ '56789|'+
+ '67890|';
+ DeleteRow := 5;
+ SollLayout := '12345|'+
+ '23456|'+
+ '34567|'+
+ '45678|'+
+ '56789';
+ end;
+
+ { ---------------------------------------------------------------------------}
+ { Layouts with formula }
+ { ---------------------------------------------------------------------------}
+
+ // Insert a column before #1, i.e. before formula cell
+ with InsDelTestData[12] do begin
+ Layout := '12345678|'+
+ '23456789|'+
+ '3456F890|'+ // "F" = Formula in row 2, col 4
+ '45678901|'+
+ '56789012|'+
+ '67890123';
+ InsertCol := 1;
+ Formula := 'C3';
+ SollFormula := 'D3'; // col index increases due to inserted col
+ SollLayout := '1 2345678|'+
+ '2 3456789|'+
+ '3 4565890|'+
+ '4 5678901|'+
+ '5 6789012|'+
+ '6 7890123';
+ end;
+
+ // Insert a column before #3, i.e. after formula cell
+ with InsDelTestData[13] do begin
+ Layout := '12345678|'+
+ '23456789|'+
+ '3456F890|'+ // "F" = Formula in row 2, col 4
+ '45678901|'+
+ '56789012|'+
+ '67890123';
+ InsertCol := 3;
+ Formula := 'C3';
+ SollFormula := 'C3'; // no change of cell because insertion is behind
+ SollLayout := '123 45678|'+
+ '234 56789|'+
+ '345 65890|'+
+ '456 78901|'+
+ '567 89012|'+
+ '678 90123';
+ end;
+
+ // Insert a row before #1, i.e. before formula cell
+ with InsDelTestData[14] do begin
+ Layout := '12345678|'+
+ '23456789|'+
+ '3456F890|'+ // "F" = Formula in row 2, col 4
+ '45678901|'+
+ '56789012|'+
+ '67890123';
+ InsertRow := 1;
+ Formula := 'E4';
+ SollFormula := 'E5'; // row index increaes due to inserted row
+ SollLayout := '12345678|'+
+ ' |'+
+ '23456789|'+
+ '34568890|'+
+ '45678901|'+
+ '56789012|'+
+ '67890123';
+ end;
+
+ // Insert a row before #4, i.e. after formula cell
+ with InsDelTestData[15] do begin
+ Layout := '12345678|'+
+ '23456789|'+
+ '3456F890|'+ // "F" = Formula in row 2, col 4
+ '45678901|'+
+ '56789012|'+
+ '67890123';
+ InsertRow := 5;
+ Formula := 'E4';
+ SollFormula := 'E4'; // row index not changed dur to insert after cell
+ SollLayout := '12345678|'+
+ '23456789|'+
+ '34568890|'+
+ '45678901|'+
+ '56789012|'+
+ ' |'+
+ '67890123';
+ end;
+
+ // Deletes column #1, i.e. before formula cell
+ with InsDelTestData[16] do begin
+ Layout := '12345678|'+
+ '23456789|'+
+ '3456F890|'+ // "F" = Formula in row 2, col 4
+ '45678901|'+
+ '56789012|'+
+ '67890123';
+ DeleteCol := 1;
+ Formula := 'C3';
+ SollFormula := 'B3'; // col index decreases due to delete before cell
+ SollLayout := '1345678|'+
+ '2456789|'+
+ '3565890|'+
+ '4678901|'+
+ '5789012|'+
+ '6890123';
+ end;
+
+ // Deletes column #5, i.e. after formula cell
+ with InsDelTestData[17] do begin
+ Layout := '12345678|'+
+ '23456789|'+
+ '3456F890|'+ // "F" = Formula in row 2, col 4
+ '45678901|'+
+ '56789012|'+
+ '67890123';
+ DeleteCol := 5;
+ Formula := 'C3';
+ SollFormula := 'C3'; // col index unchanged due to deleted after cell
+ SollLayout := '1234578|'+
+ '2345689|'+
+ '3456590|'+
+ '4567801|'+
+ '5678912|'+
+ '6789023';
+ end;
+
+ // Deletes column #2, i.e. cell appearing in formula is gone --> #REF! error
+ with InsDelTestData[18] do begin
+ Layout := '12345678|'+
+ '23456789|'+
+ '3456F890|'+ // "F" = Formula in row 2, col 4
+ '45678901|'+
+ '56789012|'+
+ '67890123';
+ DeleteCol := 2;
+ Formula := 'C3';
+ SollFormula := '#REF!'; // col index unchanged due to deletion after cell
+ SollLayout := '1245678|'+
+ '2356789|'+
+ '346E890|'+ // "E" = error
+ '4578901|'+
+ '5689012|'+
+ '6790123';
+ end;
+
+ // Deletes row #1, i.e. before formula cell
+ with InsDelTestData[19] do begin
+ Layout := '12345678|'+
+ '23456789|'+
+ '3456F890|'+ // "F" = Formula in row 2, col 4
+ '45678901|'+
+ '56789012|'+
+ '67890123';
+ DeleteRow := 1;
+ Formula := 'E4';
+ SollFormula := 'E3'; // row index decreases due to delete before cell
+ SollLayout := '12345678|'+
+// '23456789|'+
+ '34568890|'+
+ '45678901|'+
+ '56789012|'+
+ '67890123';
+ end;
+
+ // Deletes row #4, i.e. after formula cell
+ with InsDelTestData[20] do begin
+ Layout := '12345678|'+
+ '23456789|'+
+ '3456F890|'+ // "F" = Formula in row 2, col 4
+ '45678901|'+
+ '56789012|'+
+ '67890123';
+ DeleteRow := 4;
+ Formula := 'E4';
+ SollFormula := 'E4'; // row index unchanged (delete is after cell)
+ SollLayout := '12345678|'+
+ '23456789|'+
+ '34568890|'+
+ '45678901|'+
+// '56789012|'+
+ '67890123';
+ end;
+
+ // Deletes row #2, i.e. row containing cell used in formula --> #REF! error!
+ with InsDelTestData[21] do begin
+ Layout := '12345678|'+
+ '23456789|'+
+ '3456F890|'+ // "F" = Formula in row 2, col 4
+ '45678901|'+
+ '56789012|'+
+ '67890123';
+ DeleteRow := 3;
+ Formula := 'E4';
+ SollFormula := '#REF!';
+ SollLayout := '12345678|'+
+ '23456789|'+
+ '34568890|'+
+// '45678901|'+
+ '56789012|'+
+ '67890123';
+ end;
+
end;
@@ -211,6 +540,7 @@ begin
for col := 0 to Length(s)-1 do
case s[col+1] of
'0'..'9': MyWorksheet.WriteNumber(row, col, StrToInt(s[col+1]));
+ 'F' : MyWorksheet.WriteFormula(row, col, InsDelTestData[ATestIndex].Formula);
' ' : ;
end;
end;
@@ -237,7 +567,9 @@ begin
// 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
@@ -253,11 +585,20 @@ begin
MyCell := MyWorksheet.FindCell(row, col);
if MyCell = nil then
actual := actual + ' '
- else
+ else begin
case MyCell^.ContentType of
cctEmpty : actual := actual + ' ';
cctNumber: actual := actual + IntToStr(Round(Mycell^.NumberValue));
+ cctError : actual := actual + 'E';
end;
+ if HasFormula(MyCell) then begin
+ CheckEquals(
+ MyWorksheet.ReadFormulaAsString(MyCell),
+ InsDelTestData[ATestIndex].SollFormula,
+ 'Formula mismatch, cell '+CellNotation(MyWorksheet, Row, Col)
+ );
+ end;
+ end;
end;
CheckEquals(actual, expected,
'Test empty cell layout mismatch, cell '+CellNotation(MyWorksheet, Row, Col));
@@ -309,6 +650,101 @@ begin
TestWriteRead_InsDelColRow(5);
end;
+procedure TSpreadWriteRead_InsDelColRow_Tests.TestWriteRead_InsDelColRow_6;
+// insert row before first one
+begin
+ TestWriteRead_InsDelColRow(6);
+end;
+
+procedure TSpreadWriteRead_InsDelColRow_Tests.TestWriteRead_InsDelColRow_7;
+// insert row before #2
+begin
+ TestWriteRead_InsDelColRow(7);
+end;
+
+procedure TSpreadWriteRead_InsDelColRow_Tests.TestWriteRead_InsDelColRow_8;
+// insert row before last one
+begin
+ TestWriteRead_InsDelColRow(8);
+end;
+
+procedure TSpreadWriteRead_InsDelColRow_Tests.TestWriteRead_InsDelColRow_9;
+// delete first row
+begin
+ TestWriteRead_InsDelColRow(9);
+end;
+
+procedure TSpreadWriteRead_InsDelColRow_Tests.TestWriteRead_InsDelColRow_10;
+// delete row #2
+begin
+ TestWriteRead_InsDelColRow(10);
+end;
+
+procedure TSpreadWriteRead_InsDelColRow_Tests.TestWriteRead_InsDelColRow_11;
+// delete last row
+begin
+ TestWriteRead_InsDelColRow(11);
+end;
+
+procedure TSpreadWriteRead_InsDelColRow_Tests.TestWriteRead_InsDelColRow_12;
+// insert column before formula cell
+begin
+ TestWriteRead_InsDelColRow(12);
+end;
+
+procedure TSpreadWriteRead_InsDelColRow_Tests.TestWriteRead_InsDelColRow_13;
+// insert column after formula cell
+begin
+ TestWriteRead_InsDelColRow(13);
+end;
+
+procedure TSpreadWriteRead_InsDelColRow_Tests.TestWriteRead_InsDelColRow_14;
+// insert row before formula cell
+begin
+ TestWriteRead_InsDelColRow(14);
+end;
+
+procedure TSpreadWriteRead_InsDelColRow_Tests.TestWriteRead_InsDelColRow_15;
+// insert row after formula cell
+begin
+ TestWriteRead_InsDelColRow(15);
+end;
+
+procedure TSpreadWriteRead_InsDelColRow_Tests.TestWriteRead_InsDelColRow_16;
+// delete column before formula cell
+begin
+ TestWriteRead_InsDelColRow(16);
+end;
+
+procedure TSpreadWriteRead_InsDelColRow_Tests.TestWriteRead_InsDelColRow_17;
+// delete column after formula cell
+begin
+ TestWriteRead_InsDelColRow(17);
+end;
+
+procedure TSpreadWriteRead_InsDelColRow_Tests.TestWriteRead_InsDelColRow_18;
+// delete column containing a cell used in formula
+begin
+ TestWriteRead_InsDelColRow(18);
+end;
+
+procedure TSpreadWriteRead_InsDelColRow_Tests.TestWriteRead_InsDelColRow_19;
+// delete row before formula cell
+begin
+ TestWriteRead_InsDelColRow(19);
+end;
+
+procedure TSpreadWriteRead_InsDelColRow_Tests.TestWriteRead_InsDelColRow_20;
+// delete row after formula cell
+begin
+ TestWriteRead_InsDelColRow(20);
+end;
+
+procedure TSpreadWriteRead_InsDelColRow_Tests.TestWriteRead_InsDelColRow_21;
+// delete row containing a cell used in formula
+begin
+ TestWriteRead_InsDelColRow(21);
+end;
initialization
RegisterTest(TSpreadWriteRead_InsDelColRow_Tests);
diff --git a/components/fpspreadsheet/tests/spreadtestgui.lpi b/components/fpspreadsheet/tests/spreadtestgui.lpi
index 6c7085907..83b01a2a7 100644
--- a/components/fpspreadsheet/tests/spreadtestgui.lpi
+++ b/components/fpspreadsheet/tests/spreadtestgui.lpi
@@ -48,6 +48,7 @@
+
@@ -56,7 +57,6 @@
-
@@ -66,20 +66,20 @@
-
+
-
+
@@ -106,15 +106,16 @@
-
+
+