You've already forked lazarus-ccr
fpspreadsheet: Fix 3d formulas not changing when rows/cols are inserted/deleted in referenced sheets.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@6454 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -193,10 +193,10 @@ type
|
||||
AParsedFormula: TsExpressionParser = nil): PsFormula;
|
||||
procedure DeleteFormula(ACell: PCell); overload;
|
||||
procedure DeleteFormula(ARow, ACol: Cardinal); overload;
|
||||
procedure DeleteRowOrCol(AIndex: Cardinal; IsRow: Boolean);
|
||||
function FindFormula(ACell: PCell): PsFormula; overload;
|
||||
function FindFormula(ARow, ACol: Cardinal): PsFormula; overload;
|
||||
procedure InsertRowOrCol(AIndex: Cardinal; IsRow: Boolean);
|
||||
procedure FixReferences(AIndex: Cardinal; IsRow, IsDeleting: Boolean;
|
||||
InSheet: TsBasicWorksheet);
|
||||
// enumerators
|
||||
function GetEnumerator: TsFormulaEnumerator;
|
||||
end;
|
||||
@ -252,140 +252,209 @@ end;
|
||||
|
||||
{ Call-back function for formulas when rows/cols are inserted/deleted }
|
||||
|
||||
procedure FixDeletedCol(AExprNode: TsExprNode; AData: Pointer;
|
||||
procedure FixDeletedCol(AExprNode: TsExprNode; AData1, AData2: Pointer;
|
||||
var MustRebuildFormulas: Boolean);
|
||||
var
|
||||
colIndex: Cardinal;
|
||||
referencedSheet, referencedSheet2: TsBasicWorksheet;
|
||||
changedSheet: TsBasicWorksheet;
|
||||
rng: TsCellRange;
|
||||
begin
|
||||
colIndex := PtrInt(AData);
|
||||
colIndex := PtrInt(AData1);
|
||||
changedSheet := TsBasicWorksheet(AData2);
|
||||
if AExprNode is TsCellExprNode then
|
||||
begin
|
||||
if not TsCellExprNode(AExprNode).Has3dLink then
|
||||
if TsCellExprNode(AExprNode).Col > colIndex then begin
|
||||
TsCellExprNode(AExprNode).Col := TsCellexprNode(AExprNode).Col - 1;
|
||||
MustRebuildFormulas := true;
|
||||
end else
|
||||
if TsCellExprNode(AExprNode).Col = colIndex then begin
|
||||
TsCellExprNode(AExprNode).Error := errIllegalRef;
|
||||
MustRebuildFormulas := true;
|
||||
end;
|
||||
end else
|
||||
if TsCellExprNode(AExprNode).Error <> errOK then
|
||||
exit;
|
||||
referencedSheet := TsCellExprNode(AExprNode).GetSheet;
|
||||
if TsCellExprNode(AExprNode).Has3dLink and (referencedSheet <> changedSheet) then
|
||||
exit;
|
||||
if TsCellExprNode(AExprNode).Col > colIndex then begin
|
||||
TsCellExprNode(AExprNode).Col := TsCellExprNode(AExprNode).Col - 1;
|
||||
MustRebuildFormulas := true;
|
||||
end else
|
||||
if TsCellExprNode(AExprNode).col = colIndex then begin
|
||||
TsCellExprNode(AExprNode).Error := errIllegalRef;
|
||||
MustRebuildFormulas := true;
|
||||
end;
|
||||
end
|
||||
else
|
||||
if AExprNode is TsCellRangeExprNode then
|
||||
begin
|
||||
if not TsCellRangeExprNode(AExprNode).Has3dLink then begin
|
||||
rng := TsCellRangeExprNode(AExprNode).Range;
|
||||
if (rng.Col1 = colIndex) and (rng.Col2 = colIndex) then begin
|
||||
TsCellRangeExprNode(AExprNode).Error := errIllegalRef;
|
||||
if TsCellRangeExprNode(AExprNode).Error <> errOK then
|
||||
exit;
|
||||
referencedSheet := TsCellRangeExprNode(AExprNode).GetSheet(1);
|
||||
referencedSheet2 := TsCellRangeExprNode(AExprNode).GetSheet(2);
|
||||
if TsCellRangeExprNode(AExprNode).Has3dLink and
|
||||
(referencedSheet <> changedSheet) and
|
||||
(referencedSheet2 <> changedSheet)
|
||||
then
|
||||
exit;
|
||||
rng := TsCellRangeExprNode(AExprNode).Range;
|
||||
if (rng.Col1 = colIndex) and (rng.Col2 = colIndex) then begin
|
||||
TsCellRangeExprNode(AExprNode).Error := errIllegalRef;
|
||||
MustRebuildFormulas := true;
|
||||
end else begin
|
||||
if rng.Col1 > colIndex then begin
|
||||
dec(rng.Col1);
|
||||
MustRebuildFormulas := true;
|
||||
end else begin
|
||||
if rng.Col1 > colIndex then begin
|
||||
dec(rng.Col1);
|
||||
MustRebuildFormulas := true;
|
||||
end;
|
||||
if rng.Col2 >= colIndex then begin
|
||||
dec(rng.Col2);
|
||||
MustRebuildFormulas := true;
|
||||
end;
|
||||
TsCellRangeExprNode(AExprNode).Range := rng;
|
||||
end;
|
||||
if rng.Col2 >= colIndex then begin
|
||||
dec(rng.Col2);
|
||||
MustRebuildFormulas := true;
|
||||
end;
|
||||
TsCellRangeExprNode(AExprNode).Range := rng;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure FixDeletedRow(AExprNode: TsExprNode; AData: Pointer;
|
||||
procedure FixDeletedRow(AExprNode: TsExprNode; AData1, AData2: Pointer;
|
||||
var MustRebuildFormulas: Boolean);
|
||||
var
|
||||
rowIndex: Cardinal;
|
||||
rng: TsCellRange;
|
||||
changedSheet: TsBasicWorksheet;
|
||||
referencedSheet, referencedSheet2: TsBasicWorksheet;
|
||||
begin
|
||||
rowIndex := PtrInt(AData);
|
||||
rowIndex := PtrInt(AData1);
|
||||
changedSheet := TsBasicWorksheet(AData2);
|
||||
|
||||
if AExprNode is TsCellExprNode then
|
||||
begin
|
||||
if not TsCellExprNode(AExprNode).Has3dLink then
|
||||
if TsCellExprNode(AExprNode).Row > rowIndex then begin
|
||||
TsCellExprNode(AExprNode).Row := TsCellExprNode(AExprNode).Row - 1;
|
||||
MustRebuildFormulas := true;
|
||||
end else
|
||||
if TsCellExprNode(AExprNode).Row = rowIndex then begin
|
||||
TsCelLExprNode(AExprNode).Error := errIllegalRef;
|
||||
MustRebuildFormulas := true;
|
||||
end;
|
||||
end else
|
||||
if TsCellExprNode(AExprNode).Error <> errOK then
|
||||
exit;
|
||||
referencedSheet := TsCellExprNode(AExprNode).GetSheet;
|
||||
if TsCellExprNode(AExprNode).Has3dLink and (referencedSheet <> changedSheet) then
|
||||
exit;
|
||||
if TsCellExprNode(AExprNode).Row > rowIndex then begin
|
||||
TsCellExprNode(AExprNode).Row := TsCellExprNode(AExprNode).Row - 1;
|
||||
MustRebuildFormulas := true;
|
||||
end else
|
||||
if TsCellExprNode(AExprNode).Row = rowIndex then begin
|
||||
TsCellExprNode(AExprNode).Error := errIllegalRef;
|
||||
MustRebuildFormulas := true;
|
||||
end;
|
||||
end
|
||||
else
|
||||
if AExprNode is TsCellRangeExprNode then
|
||||
begin
|
||||
if not TsCellRangeExprNode(AExprNode).Has3dLink then begin
|
||||
rng := TsCellRangeExprNode(AExprNode).Range;
|
||||
if (rng.Row1 = rowIndex) and (rng.Row2 = rowIndex) then begin
|
||||
TsCellRangeExprNode(AExprNode).Error := errIllegalRef;
|
||||
if TsCellRangeExprNode(AExprNode).Error <> errOK then
|
||||
exit;
|
||||
referencedSheet := TsCellRangeExprNode(AExprNode).GetSheet(1);
|
||||
referencedSheet2 := TsCellRangeExprNode(AExprNode).GetSheet(2);
|
||||
if TsCellRangeExprNode(AExprNode).Has3dLink and
|
||||
(referencedSheet <> changedSheet) and
|
||||
(referencedSheet2 <> changedSheet)
|
||||
then
|
||||
exit;
|
||||
rng := TsCellRangeExprNode(AExprNode).Range;
|
||||
if (rng.Row1 = rowIndex) and (rng.Row2 = rowIndex) then begin
|
||||
TsCellRangeExprNode(AExprNode).Error := errIllegalRef;
|
||||
MustRebuildFormulas := true;
|
||||
end else
|
||||
begin
|
||||
if rng.Row1 > rowIndex then begin
|
||||
dec(rng.Row1);
|
||||
MustRebuildFormulas := true;
|
||||
end else
|
||||
begin
|
||||
if rng.Row1 > rowIndex then begin
|
||||
dec(rng.Row1);
|
||||
MustRebuildFormulas := true;
|
||||
end;
|
||||
if rng.Row2 >= rowIndex then begin
|
||||
dec(rng.Row2);
|
||||
MustRebuildFormulas := true;
|
||||
end;
|
||||
TsCellRangeExprNode(AExprNode).Range := rng;
|
||||
end;
|
||||
if rng.Row2 >= rowIndex then begin
|
||||
dec(rng.Row2);
|
||||
MustRebuildFormulas := true;
|
||||
end;
|
||||
TsCellRangeExprNode(AExprNode).Range := rng;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure FixInsertedCol(AExprNode: TsExprNode; AData: Pointer;
|
||||
procedure FixInsertedCol(AExprNode: TsExprNode; AData1, AData2: Pointer;
|
||||
var MustRebuildFormulas: Boolean);
|
||||
var
|
||||
colIndex: Cardinal;
|
||||
changedSheet: TsBasicWorksheet;
|
||||
referencedSheet, referencedSheet2: TsBasicWorksheet;
|
||||
rng: TsCellRange;
|
||||
begin
|
||||
colIndex := PtrInt(AData);
|
||||
colIndex := PtrInt(AData1);
|
||||
changedSheet := TsBasicWorksheet(AData2);
|
||||
if AExprNode is TsCellExprNode then
|
||||
begin
|
||||
if not TsCellExprNode(AExprNode).Has3dLink then
|
||||
if TsCellExprNode(AExprNode).Col >= colIndex then begin
|
||||
TsCellExprNode(AExprNode).Col := TsCellexprNode(AExprNode).Col + 1;
|
||||
MustRebuildFormulas := true;
|
||||
end;
|
||||
if TsCellExprNode(AExprNode).Error <> errOK then
|
||||
exit;
|
||||
referencedSheet := TsCellExprNode(AExprNode).GetSheet;
|
||||
if TsCellExprNode(AExprNode).Has3dLink and (referencedSheet <> changedSheet) then
|
||||
exit;
|
||||
if TsCellExprNode(AExprNode).Col >= colIndex then begin
|
||||
TsCellExprNode(AExprNode).Col := TsCellExprNode(AExprNode).Col + 1;
|
||||
MustRebuildFormulas := true;
|
||||
end;
|
||||
end else
|
||||
if AExprNode is TsCellRangeExprNode then
|
||||
begin
|
||||
if not TsCellRangeExprNode(AExprNode).Has3dLink then begin
|
||||
rng := TsCellRangeExprNode(AExprNode).Range;
|
||||
if rng.Col1 >= colIndex then inc(rng.Col1);
|
||||
if rng.Col2 >= colIndex then inc(rng.Col2);
|
||||
TsCellRangeExprNode(AExprNode).Range := rng;
|
||||
if TsCellRangeExprNode(AExprNode).Error <> errOK then
|
||||
exit;
|
||||
referencedSheet := TsCellRangeExprNode(AExprNode).GetSheet(1);
|
||||
referencedSheet2 := TsCellRangeExprNode(AExprNode).GetSheet(2);
|
||||
if TsCellRangeExprNode(AExprNode).Has3dLink and
|
||||
(referencedSheet <> changedSheet) and
|
||||
(referencedSheet2 <> changedSheet)
|
||||
then
|
||||
exit;
|
||||
rng := TsCellRangeExprNode(AExprNode).Range;
|
||||
if rng.Col1 >= colIndex then begin
|
||||
inc(rng.Col1);
|
||||
MustRebuildFormulas := true;
|
||||
end;
|
||||
if rng.Col2 >= colIndex then begin
|
||||
inc(rng.Col2);
|
||||
MustRebuildFormulas := true;
|
||||
end;
|
||||
TsCellRangeExprNode(AExprNode).Range := rng;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure FixInsertedRow(AExprNode: TsExprNode; AData: Pointer;
|
||||
procedure FixInsertedRow(AExprNode: TsExprNode; AData1, AData2: Pointer;
|
||||
var MustRebuildFormulas: Boolean);
|
||||
var
|
||||
rowIndex: Cardinal;
|
||||
changedSheet: TsBasicWorksheet;
|
||||
referencedSheet, referencedSheet2: TsBasicWorksheet;
|
||||
rng: TsCellRange;
|
||||
begin
|
||||
rowIndex := PtrInt(AData);
|
||||
rowIndex := PtrInt(AData1);
|
||||
changedSheet := TsBasicWorksheet(AData2);
|
||||
if AExprNode is TsCellExprNode then
|
||||
begin
|
||||
if not TsCellexprNode(AExprNode).Has3dLink then
|
||||
if TsCellExprNode(AExprNode).Row >= rowIndex then begin
|
||||
TsCellExprNode(AExprNode).Row := TsCellExprNode(AExprNode).Row + 1;
|
||||
MustRebuildFormulas := true;
|
||||
end;
|
||||
if TsCellExprNode(AExprNode).Error <> errOK then
|
||||
exit;
|
||||
referencedSheet := TsCellExprNode(AExprNode).GetSheet;
|
||||
if TsCellExprNode(AExprNode).Has3dLink and (referencedSheet <> changedSheet) then
|
||||
exit;
|
||||
if TsCellExprNode(AExprNode).Row >= rowIndex then begin
|
||||
TsCellExprNode(AExprNode).Row := TsCellExprNode(AExprNode).Row + 1;
|
||||
MustRebuildFormulas := true;
|
||||
end;
|
||||
end else
|
||||
if AExprNode is TsCellRangeExprNode then
|
||||
begin
|
||||
if not TsCellRangeExprNode(AExprNode).Has3dLink then begin
|
||||
rng := TsCellRangeExprNode(AExprNode).Range;
|
||||
if rng.Row1 >= rowIndex then inc(rng.Row1);
|
||||
if rng.Row2 >= rowIndex then inc(rng.Row2);
|
||||
TsCellRangeExprNode(AExprNode).Range := rng;
|
||||
if TsCellRangeExprNode(AExprNode).Error <> errOK then
|
||||
exit;
|
||||
referencedSheet := TsCellRangeExprNode(AExprNode).GetSheet(1);
|
||||
referencedSheet2 := TsCellRangeExprNode(AExprNode).GetSheet(2);
|
||||
if TsCellRangeExprNode(AExprNode).Has3dLink and
|
||||
(referencedSheet <> changedSheet) and
|
||||
(referencedSheet2 <> changedSheet)
|
||||
then
|
||||
exit;
|
||||
rng := TsCellRangeExprNode(AExprNode).Range;
|
||||
if rng.Row1 >= rowIndex then begin
|
||||
inc(rng.Row1);
|
||||
MustRebuildFormulas := true;
|
||||
end;
|
||||
if rng.Row2 >= rowIndex then begin
|
||||
inc(rng.Row2);
|
||||
MustRebuildFormulas := true;
|
||||
end;
|
||||
TsCellRangeExprNode(AExprNode).Range := rng;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -1436,7 +1505,9 @@ begin
|
||||
Delete(ARow, ACol); // will release memory automatically
|
||||
end;
|
||||
|
||||
procedure TsFormulas.DeleteRowOrCol(AIndex: Cardinal; IsRow: Boolean);
|
||||
(*
|
||||
procedure TsFormulas.DeleteRowOrCol(AIndex: Cardinal; IsRow: Boolean;
|
||||
InSheet: TsBasicWorksheet);
|
||||
var
|
||||
node, nextnode: TAvgLvlTreeNode;
|
||||
formula: PsFormula;
|
||||
@ -1476,7 +1547,7 @@ begin
|
||||
formula^.Text := formula^.Parser.Expression;
|
||||
node := nextnode;
|
||||
end;
|
||||
end;
|
||||
end; *)
|
||||
|
||||
procedure TsFormulas.DisposeData(var AData: Pointer);
|
||||
begin
|
||||
@ -1501,12 +1572,38 @@ begin
|
||||
Result := PsFormula(FindByRowCol(ARow, ACol));
|
||||
end;
|
||||
|
||||
{ In worksheet "InSheet" a row or column has been inserted or deleted at the
|
||||
given index. "IsRow" tells whether it is a row or a column, and "IsDeleteing"
|
||||
tells whether it has been deleted (true) or inserted (false).
|
||||
This method must scan the formulas of the current worksheet whether there is
|
||||
a reference to the modified sheet and must adapt the reference correspondingly
|
||||
}
|
||||
procedure TsFormulas.FixReferences(AIndex: Cardinal; IsRow, IsDeleting: Boolean;
|
||||
InSheet: TsBasicWorksheet);
|
||||
var
|
||||
formula: PsFormula;
|
||||
proc: TsExprNodeProc;
|
||||
begin
|
||||
if IsRow and IsDeleting then
|
||||
proc := @FixDeletedRow
|
||||
else if IsRow and not IsDeleting then
|
||||
proc := @FixInsertedRow
|
||||
else if not IsRow and IsDeleting then
|
||||
proc := @FixDeletedCol
|
||||
else
|
||||
proc := @fixInsertedCol;
|
||||
|
||||
for formula in self do
|
||||
if formula^.Parser.IterateNodes(proc, Pointer(PtrInt(AIndex)), InSheet) then
|
||||
formula^.Text := formula^.Parser.Expression;
|
||||
end;
|
||||
|
||||
// Formula enumerators (use in "for ... in" syntax)
|
||||
function TsFormulas.GetEnumerator: TsFormulaEnumerator;
|
||||
begin
|
||||
Result := TsFormulaEnumerator.Create(self, 0, 0, $7FFFFFFF, $7FFFFFFF, false);
|
||||
end;
|
||||
|
||||
(*
|
||||
procedure TsFormulas.InsertRowOrCol(AIndex: Cardinal; IsRow: Boolean);
|
||||
var
|
||||
node: TAvgLvlTreeNode;
|
||||
@ -1529,7 +1626,7 @@ begin
|
||||
formula^.Text := formula^.Parser.Expression;
|
||||
node := FindSuccessor(node);
|
||||
end;
|
||||
end;
|
||||
end; *)
|
||||
|
||||
function TsFormulas.NewData: Pointer;
|
||||
var
|
||||
|
@ -109,7 +109,7 @@ type
|
||||
{ Proceudre executed when iterating through all nodes (Parser.IterateNodes).
|
||||
The procedure sets the parameter MustRebuildFormula to true if the
|
||||
text formula has to be rebuilt. }
|
||||
TsExprNodeProc = procedure(ANode: TsExprNode; AData: Pointer;
|
||||
TsExprNodeProc = procedure(ANode: TsExprNode; AData1, AData2: Pointer;
|
||||
var MustRebuildFormulas: Boolean);
|
||||
|
||||
{ TsExprNode }
|
||||
@ -124,7 +124,7 @@ type
|
||||
function AsString: string; virtual; abstract;
|
||||
procedure Check; virtual; //abstract;
|
||||
function Has3DLink: Boolean; virtual;
|
||||
procedure IterateNodes(AProc: TsExprNodeProc; AData: Pointer;
|
||||
procedure IterateNodes(AProc: TsExprNodeProc; AData1, AData2: Pointer;
|
||||
var MustRebuildFormulas: Boolean); virtual;
|
||||
function NodeType: TsResultType; virtual; abstract;
|
||||
function NodeValue: TsExpressionResult;
|
||||
@ -144,7 +144,7 @@ type
|
||||
constructor Create(AParser: TsExpressionParser; ALeft, ARight: TsExprNode);
|
||||
destructor Destroy; override;
|
||||
function Has3DLink: Boolean; override;
|
||||
procedure IterateNodes(AProc: TsExprNodeProc; AData: Pointer;
|
||||
procedure IterateNodes(AProc: TsExprNodeProc; AData1, AData2: Pointer;
|
||||
var MustRebuildFormulas: boolean); override;
|
||||
property Left: TsExprNode read FLeft;
|
||||
property Right: TsExprNode read FRight;
|
||||
@ -567,7 +567,7 @@ type
|
||||
function AsString: String; override;
|
||||
procedure Check; override;
|
||||
function Has3DLink: Boolean; override;
|
||||
procedure IterateNodes(AProc: TsExprNodeProc; AData: Pointer;
|
||||
procedure IterateNodes(AProc: TsExprNodeProc; AData1, AData2: Pointer;
|
||||
var MustRebuildFormulas: Boolean); override;
|
||||
property ArgumentNodes: TsExprArgumentArray read FArgumentNodes;
|
||||
property ArgumentParams: TsExprParameterArray read FArgumentParams;
|
||||
@ -612,7 +612,6 @@ type
|
||||
protected
|
||||
function GetCol: Cardinal;
|
||||
function GetRow: Cardinal;
|
||||
function GetSheet: TsBasicWorksheet;
|
||||
procedure GetNodeValue(out AResult: TsExpressionResult); override;
|
||||
public
|
||||
constructor Create(AParser: TsExpressionParser; AWorksheet: TsBasicWorksheet;
|
||||
@ -620,11 +619,12 @@ type
|
||||
function AsRPNItem(ANext: PRPNItem): PRPNItem; override;
|
||||
function AsString: string; override;
|
||||
procedure Check; override;
|
||||
function GetSheet: TsBasicWorksheet;
|
||||
function GetSheetIndex: Integer;
|
||||
function GetSheetName: String;
|
||||
function GetWorkbook: TsBasicWorkbook;
|
||||
function Has3DLink: Boolean; override;
|
||||
procedure IterateNodes(AProc: TsExprNodeProc; AData: Pointer;
|
||||
procedure IterateNodes(AProc: TsExprNodeProc; AData1, AData2: Pointer;
|
||||
var MustRebuildFormulas: Boolean); override;
|
||||
function NodeType: TsResultType; override;
|
||||
procedure SetSheetIndex(AIndex: Integer);
|
||||
@ -658,10 +658,11 @@ type
|
||||
function AsRPNItem(ANext: PRPNItem): PRPNItem; override;
|
||||
function AsString: String; override;
|
||||
procedure Check; override;
|
||||
function GetSheet(AIndex: TsCellRangeIndex): TsBasicWorksheet;
|
||||
function GetSheetIndex(AIndex: TsCellRangeIndex): Integer;
|
||||
function GetWorkbook: TsBasicWorkbook;
|
||||
function Has3DLink: Boolean; override;
|
||||
procedure IterateNodes(AProc: TsExprNodeProc; AData: Pointer;
|
||||
procedure IterateNodes(AProc: TsExprNodeProc; AData1, AData2: Pointer;
|
||||
var MustRebuildFormulas: Boolean); override;
|
||||
function NodeType: TsResultType; override;
|
||||
procedure SetSheetIndex(AIndex: TsCellRangeIndex; AValue: Integer);
|
||||
@ -788,7 +789,7 @@ type
|
||||
function Evaluate: TsExpressionResult;
|
||||
procedure EvaluateExpression(out AResult: TsExpressionResult);
|
||||
function Has3DLinks: Boolean;
|
||||
function IterateNodes(AProc: TsExprNodeProc; AData: Pointer): boolean;
|
||||
function IterateNodes(AProc: TsExprNodeProc; AData1, AData2: Pointer): boolean;
|
||||
procedure PrepareCopyMode(ASourceCell, ADestCell: PCell);
|
||||
function ResultType: TsResultType;
|
||||
|
||||
@ -1988,10 +1989,10 @@ begin
|
||||
end;
|
||||
|
||||
function TsExpressionParser.IterateNodes(AProc: TsExprNodeProc;
|
||||
AData: Pointer): Boolean;
|
||||
AData1, AData2: Pointer): Boolean;
|
||||
begin
|
||||
Result := false;
|
||||
FExprNode.IterateNodes(AProc, AData, Result);
|
||||
FExprNode.IterateNodes(AProc, AData1, AData2, Result);
|
||||
end;
|
||||
|
||||
procedure TsExpressionParser.SetDialect(const AValue: TsFormulaDialect);
|
||||
@ -2776,10 +2777,11 @@ begin
|
||||
Result := false;
|
||||
end;
|
||||
|
||||
procedure TsExprNode.IterateNodes(AProc: TsExprNodeProc; AData: Pointer;
|
||||
procedure TsExprNode.IterateNodes(AProc: TsExprNodeProc; AData1, AData2: Pointer;
|
||||
var MustRebuildFormulas: Boolean);
|
||||
begin
|
||||
Unused(AProc, AData, MustRebuildFormulas);
|
||||
Unused(AProc, AData1, AData2);
|
||||
Unused(MustRebuildFormulas);
|
||||
// to be overridden by descendant classes
|
||||
end;
|
||||
|
||||
@ -2834,12 +2836,12 @@ begin
|
||||
end;
|
||||
|
||||
procedure TsBinaryOperationExprNode.IterateNodes(AProc: TsExprNodeProc;
|
||||
AData: Pointer; var MustRebuildFormulas: Boolean);
|
||||
AData1, AData2: Pointer; var MustRebuildFormulas: Boolean);
|
||||
var
|
||||
rebuildLeft, rebuildRight: Boolean;
|
||||
begin
|
||||
FLeft.IterateNodes(AProc, AData, rebuildLeft);
|
||||
FRight.IterateNodes(AProc, AData, rebuildRight);
|
||||
FLeft.IterateNodes(AProc, AData1, AData2, rebuildLeft);
|
||||
FRight.IterateNodes(AProc, AData1, AData2, rebuildRight);
|
||||
MustRebuildFormulas := MustRebuildFormulas or rebuildLeft or rebuildRight;
|
||||
end;
|
||||
|
||||
@ -3795,12 +3797,12 @@ begin
|
||||
end;
|
||||
|
||||
procedure TsFunctionExprNode.IterateNodes(AProc: TsExprNodeProc;
|
||||
AData: Pointer; var MustRebuildFormulas: Boolean);
|
||||
AData1, AData2: Pointer; var MustRebuildFormulas: Boolean);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
for i:=0 to High(FArgumentParams) do
|
||||
FArgumentNodes[i].IterateNodes(AProc, AData, MustRebuildFormulas);
|
||||
FArgumentNodes[i].IterateNodes(AProc, AData1, AData2, MustRebuildFormulas);
|
||||
end;
|
||||
|
||||
|
||||
@ -3948,11 +3950,6 @@ begin
|
||||
if FError <> errOK then begin
|
||||
AResult.ResultType := rtError;
|
||||
AResult.ResError := FError;
|
||||
{
|
||||
AResult.ResRow := GetRow;
|
||||
AResult.ResCol := GetCol;
|
||||
AResult.Worksheet := GetSheet;
|
||||
}
|
||||
exit;
|
||||
end;
|
||||
|
||||
@ -4013,31 +4010,31 @@ end;
|
||||
|
||||
function TsCellExprNode.GetSheet: TsBasicWorksheet;
|
||||
begin
|
||||
if FSheetIndex = -1 then
|
||||
Result := FWorksheet
|
||||
else begin
|
||||
if FHas3dLink then begin
|
||||
Result := (GetWorkbook as TsWorkbook).GetWorksheetByIndex(FSheetIndex);
|
||||
if Result = nil then FError := errIllegalREF;
|
||||
end;
|
||||
end else
|
||||
Result := FWorksheet;
|
||||
end;
|
||||
|
||||
function TsCellExprNode.GetSheetIndex: Integer;
|
||||
var
|
||||
book: TsWorkbook;
|
||||
begin
|
||||
book := GetWorkbook as TsWorkbook;
|
||||
if FSheetIndex = -1 then
|
||||
if FHas3dLink then
|
||||
Result := FSheetIndex
|
||||
else begin
|
||||
book := GetWorkbook as TsWorkbook;
|
||||
Result := book.GetWorksheetIndex(FWorksheet)
|
||||
else
|
||||
Result := FSheetIndex;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsCellExprNode.GetSheetName: String;
|
||||
begin
|
||||
if FSheetIndex = -1 then
|
||||
Result := FWorksheet.Name
|
||||
if FHas3dLink then
|
||||
Result := TsWorkbook(GetWorkbook).GetWorksheetByIndex(FSheetIndex).Name
|
||||
else
|
||||
Result := TsWorkbook(GetWorkbook).GetWorksheetByIndex(FSheetIndex).Name;
|
||||
Result := FWorksheet.Name;
|
||||
end;
|
||||
|
||||
function TsCellExprNode.GetWorkbook: TsBasicWorkbook;
|
||||
@ -4056,9 +4053,9 @@ begin
|
||||
end;
|
||||
|
||||
procedure TsCellExprNode.IterateNodes(AProc: TsExprNodeProc;
|
||||
AData: Pointer; var MustRebuildFormulas: Boolean);
|
||||
AData1, AData2: Pointer; var MustRebuildFormulas: Boolean);
|
||||
begin
|
||||
AProc(self, AData, MustRebuildFormulas);
|
||||
AProc(self, AData1, AData2, MustRebuildFormulas);
|
||||
end;
|
||||
|
||||
procedure TsCellExprNode.SetSheetIndex(AIndex: Integer);
|
||||
@ -4301,6 +4298,14 @@ begin
|
||||
Result := (FWorksheet as TsWorksheet).Workbook;
|
||||
end;
|
||||
|
||||
function TsCellRangeExprNode.GetSheet(AIndex: TsCellRangeIndex): TsBasicWorksheet;
|
||||
begin
|
||||
if FError <> errOK then
|
||||
Result := nil
|
||||
else
|
||||
Result := TsWorkbook(GetWorkbook).GetWorksheetByIndex(GetSheetIndex(AIndex));
|
||||
end;
|
||||
|
||||
function TsCellRangeExprNode.GetSheetIndex(AIndex: TsCellRangeIndex): Integer;
|
||||
begin
|
||||
Result := FSheetIndex[AIndex];
|
||||
@ -4312,9 +4317,9 @@ begin
|
||||
end;
|
||||
|
||||
procedure TsCellRangeExprNode.IterateNodes(AProc: TsExprNodeProc;
|
||||
AData: Pointer; var MustRebuildFormulas: Boolean);
|
||||
AData1, AData2: Pointer; var MustRebuildFormulas: Boolean);
|
||||
begin
|
||||
AProc(self, AData, MustRebuildFormulas);
|
||||
AProc(self, AData1, AData2, MustRebuildFormulas);
|
||||
end;
|
||||
|
||||
function TsCellRangeExprNode.NodeType: TsResultType;
|
||||
|
@ -7386,6 +7386,7 @@ var
|
||||
i: Integer;
|
||||
r: Cardinal;
|
||||
formula: PsFormula;
|
||||
sheet: TsWorksheet;
|
||||
begin
|
||||
// Fix merged cells
|
||||
FMergedCells.DeleteRowOrCol(AIndex, IsRow);
|
||||
@ -7396,8 +7397,14 @@ begin
|
||||
// Fix hyperlinks
|
||||
FHyperlinks.DeleteRowOrCol(AIndex, IsRow);
|
||||
|
||||
// Fix formulas
|
||||
// Fix formulas:
|
||||
// 1) Fix Row/Col index of in-sheet formulas
|
||||
FFormulas.DeleteRowOrCol(AIndex, IsRow);
|
||||
// 2) Fix formula references to this sheet
|
||||
for i := 0 to FWorkbook.GetWorksheetcount-1 do begin
|
||||
sheet := FWorkbook.GetWorksheetByIndex(i);
|
||||
sheet.Formulas.FixReferences(AIndex, IsRow, true, self);
|
||||
end;
|
||||
|
||||
// Delete cells
|
||||
FCells.DeleteRowOrCol(AIndex, IsRow);
|
||||
@ -7483,6 +7490,7 @@ var
|
||||
col: PCol;
|
||||
i: Integer;
|
||||
rng: PsCellRange;
|
||||
sheet: TsWorksheet;
|
||||
begin
|
||||
// Update row indexes of cell comments
|
||||
FComments.InsertRowOrCol(AIndex, IsRow);
|
||||
@ -7490,8 +7498,14 @@ begin
|
||||
// Update row indexes of cell hyperlinks
|
||||
FHyperlinks.InsertRowOrCol(AIndex, IsRow);
|
||||
|
||||
// Update row indexes of cell formulas
|
||||
// Fix formulas:
|
||||
// 1) Update Row/Col index of in-sheet formulas
|
||||
FFormulas.InsertRowOrCol(AIndex, IsRow);
|
||||
// 2) Fix formula references to this sheet
|
||||
for i := 0 to FWorkbook.GetWorksheetcount-1 do begin
|
||||
sheet := FWorkbook.GetWorksheetByIndex(i);
|
||||
sheet.Formulas.FixReferences(AIndex, IsRow, false, self);
|
||||
end;
|
||||
|
||||
// Update cell indexes of cell records
|
||||
FCells.InsertRowOrCol(AIndex, IsRow);
|
||||
@ -9600,7 +9614,7 @@ end;
|
||||
|
||||
|
||||
{ AData points to the deleted worksheet }
|
||||
procedure FixWorksheetDeletedCallback(ANode: TsExprNode; AData: Pointer;
|
||||
procedure FixWorksheetDeletedCallback(ANode: TsExprNode; AData1, AData2: Pointer;
|
||||
var MustRebuildFormulas: Boolean);
|
||||
var
|
||||
deletedindex: Integer;
|
||||
@ -9609,10 +9623,12 @@ var
|
||||
rngNode: TsCellRangeExprNode;
|
||||
index, index1, index2: Integer;
|
||||
begin
|
||||
Unused(AData2);
|
||||
|
||||
if ANode is TsCellExprNode then
|
||||
begin
|
||||
cellNode := TsCellExprNode(ANode);
|
||||
deletedSheet := TsWorksheet(AData);
|
||||
deletedSheet := TsWorksheet(AData1);
|
||||
deletedindex := TsWorkbook(cellNode.GetWorkbook).GetWorksheetIndex(deletedSheet);
|
||||
index := cellNode.GetSheetIndex;
|
||||
if deletedindex < index then begin
|
||||
@ -9627,7 +9643,7 @@ begin
|
||||
if ANode is TsCellRangeExprNode then
|
||||
begin
|
||||
rngNode := TsCellRangeExprNode(ANode);
|
||||
deletedSheet := TsWorksheet(AData);
|
||||
deletedSheet := TsWorksheet(AData1);
|
||||
deletedIndex := TsWorkbook(rngNode.GetWorkbook).GetWorksheetIndex(deletedSheet);
|
||||
index1 := rngNode.GetSheetIndex(1);
|
||||
index2 := rngNode.GetSheetIndex(2);
|
||||
@ -9663,7 +9679,7 @@ begin
|
||||
fcWorksheetRenamed:
|
||||
Result := true; // Nothing to do, no sheet names in formula nodes
|
||||
fcWorksheetDeleted:
|
||||
Result := AFormula^.Parser.IterateNodes(FixWorksheetDeletedCallback, AData);
|
||||
Result := AFormula^.Parser.IterateNodes(FixWorksheetDeletedCallback, AData, nil);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -2559,14 +2559,15 @@ begin
|
||||
AStream.WriteWord(0);
|
||||
end;
|
||||
|
||||
procedure DoCollectSheetsWith3dRefs(ANode: TsExprNode; AData: Pointer;
|
||||
procedure DoCollectSheetsWith3dRefs(ANode: TsExprNode; AData1, AData2: Pointer;
|
||||
var MustRebuildFormulas: Boolean);
|
||||
var
|
||||
sheetlist: TsBIFF8ExternSheetList;
|
||||
sheetIdx, sheetIdx1, sheetIdx2: Integer;
|
||||
begin
|
||||
Unused(MustRebuildFormulas);
|
||||
sheetlist := TsBIFF8ExternSheetList(AData);
|
||||
Unused(AData2, MustRebuildFormulas);
|
||||
|
||||
sheetlist := TsBIFF8ExternSheetList(AData1);
|
||||
if (ANode is TsCellExprNode) and TsCellExprNode(ANode).Has3DLink then
|
||||
begin
|
||||
sheetIdx := TsCellExprNode(ANode).GetSheetIndex;
|
||||
@ -2593,7 +2594,7 @@ procedure TsSpreadBIFF8Writer.CollectExternData;
|
||||
formula: PsFormula;
|
||||
begin
|
||||
for formula in ASheet.Formulas do
|
||||
formula^.Parser.IterateNodes(@DoCollectSheetsWith3dRefs, FBiff8ExternSheets);
|
||||
formula^.Parser.IterateNodes(@DoCollectSheetsWith3dRefs, FBiff8ExternSheets, nil);
|
||||
end;
|
||||
|
||||
var
|
||||
|
@ -3463,7 +3463,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure DoCollectSheetsWith3dRefs(ANode: TsExprNode; AData: Pointer;
|
||||
procedure DoCollectSheetsWith3dRefs(ANode: TsExprNode; AData1, AData2: Pointer;
|
||||
var MustRebuildFormulas: Boolean);
|
||||
var
|
||||
sheetlist: TsBIFFExternSheetList;
|
||||
@ -3471,8 +3471,9 @@ var
|
||||
workbook: TsWorkbook;
|
||||
sheetName: String;
|
||||
begin
|
||||
Unused(MustRebuildFormulas);
|
||||
sheetlist := TsBIFFExternSheetList(AData);
|
||||
Unused(MustRebuildFormulas, AData2);
|
||||
|
||||
sheetlist := TsBIFFExternSheetList(AData1);
|
||||
if (ANode is TsCellExprNode) and TsCellExprNode(ANode).Has3DLink then
|
||||
begin
|
||||
if (ANode as TsCellExprNode).Error <> errOK then
|
||||
@ -3505,7 +3506,7 @@ function TsSpreadBIFFWriter.CollectExternData(AWorksheet: TsBasicWorksheet = nil
|
||||
formula: PsFormula;
|
||||
begin
|
||||
for formula in ASheet.Formulas do
|
||||
formula^.Parser.IterateNodes(@DoCollectSheetsWith3dRefs, ASheetList);
|
||||
formula^.Parser.IterateNodes(@DoCollectSheetsWith3dRefs, ASheetList, nil);
|
||||
end;
|
||||
|
||||
var
|
||||
|
Reference in New Issue
Block a user