You've already forked lazarus-ccr
fpspreadsheet: Improved AVLTree enumerators (no speed loss of column enumerator compared to for-to cell access)
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4050 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -20,6 +20,7 @@ type
|
|||||||
|
|
||||||
{ TsRowColEnumerator }
|
{ TsRowColEnumerator }
|
||||||
TsRowColEnumerator = class
|
TsRowColEnumerator = class
|
||||||
|
private
|
||||||
protected
|
protected
|
||||||
FCurrentNode: TAVLTreeNode;
|
FCurrentNode: TAVLTreeNode;
|
||||||
FTree: TsRowColAVLTree;
|
FTree: TsRowColAVLTree;
|
||||||
@ -55,7 +56,7 @@ type
|
|||||||
procedure Delete(ARow, ACol: Cardinal); overload;
|
procedure Delete(ARow, ACol: Cardinal); overload;
|
||||||
procedure DeleteRowOrCol(AIndex: Cardinal; IsRow: Boolean); virtual;
|
procedure DeleteRowOrCol(AIndex: Cardinal; IsRow: Boolean); virtual;
|
||||||
procedure Exchange(ARow1, ACol1, ARow2, ACol2: Cardinal); virtual;
|
procedure Exchange(ARow1, ACol1, ARow2, ACol2: Cardinal); virtual;
|
||||||
function Find(ARow, ACol: Cardinal): PsRowCol; overload;
|
function FindByRowCol(ARow, ACol: Cardinal): PsRowCol; overload;
|
||||||
function GetData(ANode: TAVLTreeNode): PsRowCol;
|
function GetData(ANode: TAVLTreeNode): PsRowCol;
|
||||||
function GetFirst: PsRowCol;
|
function GetFirst: PsRowCol;
|
||||||
function GetLast: PsRowCol;
|
function GetLast: PsRowCol;
|
||||||
@ -197,6 +198,8 @@ end;
|
|||||||
|
|
||||||
constructor TsRowColEnumerator.Create(ATree: TsRowColAVLTree;
|
constructor TsRowColEnumerator.Create(ATree: TsRowColAVLTree;
|
||||||
AStartRow, AStartCol, AEndRow, AEndCol: Cardinal; AReverse: Boolean);
|
AStartRow, AStartCol, AEndRow, AEndCol: Cardinal; AReverse: Boolean);
|
||||||
|
var
|
||||||
|
node: TAVLTreeNode;
|
||||||
begin
|
begin
|
||||||
FTree := ATree;
|
FTree := ATree;
|
||||||
FReverse := AReverse;
|
FReverse := AReverse;
|
||||||
@ -218,6 +221,11 @@ begin
|
|||||||
FStartCol := AEndCol;
|
FStartCol := AEndCol;
|
||||||
FEndCol := AStartCol;
|
FEndCol := AStartCol;
|
||||||
end;
|
end;
|
||||||
|
if FEndRow = $7FFFFFFF then
|
||||||
|
begin
|
||||||
|
node := FTree.FindHighest;
|
||||||
|
FEndRow := PsRowCol(node.Data)^.Row;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TsRowColEnumerator.GetCurrent: PsRowCol;
|
function TsRowColEnumerator.GetCurrent: PsRowCol;
|
||||||
@ -236,6 +244,7 @@ end;
|
|||||||
function TsRowColEnumerator.MoveNext: Boolean;
|
function TsRowColEnumerator.MoveNext: Boolean;
|
||||||
var
|
var
|
||||||
curr: PsRowCol;
|
curr: PsRowCol;
|
||||||
|
rc: TsRowCol;
|
||||||
begin
|
begin
|
||||||
Result := false;
|
Result := false;
|
||||||
if FCurrentNode <> nil then begin
|
if FCurrentNode <> nil then begin
|
||||||
@ -245,29 +254,57 @@ begin
|
|||||||
if FCurrentNode <> nil then
|
if FCurrentNode <> nil then
|
||||||
begin
|
begin
|
||||||
curr := PsRowCol(FCurrentNode.Data);
|
curr := PsRowCol(FCurrentNode.Data);
|
||||||
if not InRange(curr^.Col, FStartCol, FEndCol) then
|
if not InRange(LongInt(curr^.Col), FStartCol, FEndCol) then
|
||||||
|
begin
|
||||||
|
rc := curr^;
|
||||||
|
if LongInt(rc.Col) < FStartCol then
|
||||||
|
dec(rc.Row);
|
||||||
|
rc.Col := FEndCol;
|
||||||
|
FCurrentNode := FTree.FindNearest(@rc);
|
||||||
|
if FCurrentNode <> nil then begin
|
||||||
|
curr := PsRowCol(FCurrentNode.Data);
|
||||||
while (FCurrentNode <> nil) and
|
while (FCurrentNode <> nil) and
|
||||||
not InRange(curr^.Col, FStartCol, FEndCol) and (curr^.Row >= FStartRow)
|
not (InRange(curr^.Row, FStartRow, FEndRow) and InRange(curr^.Col, FStartCol, FEndCol))
|
||||||
do begin
|
do begin
|
||||||
FCurrentNode := FTree.FindPrecessor(FCurrentNode);
|
FCurrentNode := FTree.FindPrecessor(FCurrentNode);
|
||||||
if FCurrentNode <> nil then curr := PsRowCol(FCurrentNode.Data);
|
if FCurrentNode <> nil then curr := PsRowCol(FCurrentNode.Data);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
end else
|
end else
|
||||||
begin
|
begin
|
||||||
FCurrentNode := FTree.FindSuccessor(FCurrentNode);
|
FCurrentNode := FTree.FindSuccessor(FCurrentNode);
|
||||||
if FCurrentNode <> nil then
|
if FCurrentNode <> nil then
|
||||||
begin
|
begin
|
||||||
curr := PsRowCol(FCurrentNode.Data);
|
curr := PsRowCol(FCurrentNode.Data);
|
||||||
if not InRange(curr^.Col, FStartCol, FEndCol) then
|
rc.Col := FStartCol;
|
||||||
|
if LongInt(rc.Col) > FEndCol then inc(rc.Row);
|
||||||
|
if not InRange(LongInt(curr^.Col), FStartCol, FEndCol) then
|
||||||
|
begin
|
||||||
|
rc := curr^;
|
||||||
|
if LongInt(rc.Col) > FEndCol then inc(rc.Row);
|
||||||
|
rc.Col := FStartCol;
|
||||||
|
FCurrentNode := FTree.FindNearest(@rc);
|
||||||
|
if FCurrentNode <> nil then
|
||||||
|
begin
|
||||||
|
curr := PsRowCol(FCurrentNode.Data);
|
||||||
|
if (curr^.Col < FStartCol) then
|
||||||
|
while (FCurrentNode <> nil) and not InRange(curr^.Col, FStartCol, FEndCol) do
|
||||||
|
begin
|
||||||
|
FCurrentNode := FTree.FindSuccessor(FCurrentNode);
|
||||||
|
if FCurrentNode <> nil then curr := PsRowCol(FCurrentNode.Data);
|
||||||
|
end;
|
||||||
while (FCurrentNode <> nil) and
|
while (FCurrentNode <> nil) and
|
||||||
not InRange(curr^.Col, FStartCol, FEndCol) and (curr^.Row <= FEndRow)
|
not (InRange(curr^.Row, FStartRow, FEndRow) and InRange(curr^.Col, FStartCol, FEndCol))
|
||||||
do begin
|
do begin
|
||||||
FCurrentNode := FTree.FindSuccessor(FCurrentNode);
|
FCurrentNode := FTree.FindSuccessor(FCurrentNode);
|
||||||
if FCurrentNode <> nil then curr := PsRowCol(FCurrentNode.Data);
|
if FCurrentNode <> nil then curr := PsRowCol(FCurrentNode.Data);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
Result := (FCurrentNode <> nil) and
|
Result := (FCurrentNode <> nil) and
|
||||||
InRange(curr^.Col, FStartCol, FEndCol) and
|
InRange(curr^.Col, FStartCol, FEndCol) and
|
||||||
InRange(curr^.Row, FStartRow, FEndRow);
|
InRange(curr^.Row, FStartRow, FEndRow);
|
||||||
@ -275,7 +312,10 @@ begin
|
|||||||
begin
|
begin
|
||||||
if FReverse then
|
if FReverse then
|
||||||
begin
|
begin
|
||||||
FCurrentNode := FTree.FindHighest;
|
rc.Row := FEndRow;
|
||||||
|
rc.Col := FEndCol;
|
||||||
|
FCurrentNode := FTree.FindNearest(@rc);
|
||||||
|
if FCurrentNode <> nil then
|
||||||
curr := PsRowCol(FCurrentNode.Data);
|
curr := PsRowCol(FCurrentNode.Data);
|
||||||
while (FCurrentNode <> nil) and
|
while (FCurrentNode <> nil) and
|
||||||
not (InRange(curr^.Row, FStartRow, FEndRow) and InRange(curr^.Col, FStartCol, FEndCol))
|
not (InRange(curr^.Row, FStartRow, FEndRow) and InRange(curr^.Col, FStartCol, FEndCol))
|
||||||
@ -285,8 +325,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
end else
|
end else
|
||||||
begin
|
begin
|
||||||
FCurrentNode := FTree.FindLowest;
|
rc.Row := FStartRow;
|
||||||
curr := Current;
|
rc.Col := FStartCol;
|
||||||
|
FCurrentNode := FTree.FindNearest(@rc);
|
||||||
|
if FCurrentNode <> nil then
|
||||||
|
curr := PsRowCol(FCurrentNode.Data);
|
||||||
while (FCurrentNode <> nil) and
|
while (FCurrentNode <> nil) and
|
||||||
not (InRange(curr^.Row, FStartRow, FEndRow) and InRange(curr^.Col, FStartCol, FEndCol))
|
not (InRange(curr^.Row, FStartRow, FEndRow) and InRange(curr^.Col, FStartCol, FEndCol))
|
||||||
do begin
|
do begin
|
||||||
@ -423,8 +466,8 @@ procedure TsRowColAVLTree.Exchange(ARow1, ACol1, ARow2, ACol2: Cardinal);
|
|||||||
var
|
var
|
||||||
item1, item2: PsRowCol;
|
item1, item2: PsRowCol;
|
||||||
begin
|
begin
|
||||||
item1 := Find(ARow1, ACol1);
|
item1 := FindByRowCol(ARow1, ACol1);
|
||||||
item2 := Find(ARow2, ACol2);
|
item2 := FindByRowCol(ARow2, ACol2);
|
||||||
|
|
||||||
// There are entries for both locations: Exchange row/col indexes
|
// There are entries for both locations: Exchange row/col indexes
|
||||||
if (item1 <> nil) and (item2 <> nil) then
|
if (item1 <> nil) and (item2 <> nil) then
|
||||||
@ -463,7 +506,7 @@ end;
|
|||||||
returns a pointer to the data record.
|
returns a pointer to the data record.
|
||||||
Returns nil if such a node does not exist
|
Returns nil if such a node does not exist
|
||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
function TsRowColAVLTree.Find(ARow, ACol: Cardinal): PsRowCol;
|
function TsRowColAVLTree.FindByRowCol(ARow, ACol: Cardinal): PsRowCol;
|
||||||
var
|
var
|
||||||
data: TsRowCol;
|
data: TsRowCol;
|
||||||
node: TAVLTreeNode;
|
node: TAVLTreeNode;
|
||||||
@ -608,7 +651,7 @@ end;
|
|||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
function TsCells.FindCell(ARow, ACol: Cardinal): PCell;
|
function TsCells.FindCell(ARow, ACol: Cardinal): PCell;
|
||||||
begin
|
begin
|
||||||
Result := PCell(Find(ARow, ACol));
|
Result := PCell(FindByRowCol(ARow, ACol));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{@@ ----------------------------------------------------------------------------
|
{@@ ----------------------------------------------------------------------------
|
||||||
@ -745,7 +788,7 @@ end;
|
|||||||
function TsComments.AddComment(ARow, ACol: Cardinal;
|
function TsComments.AddComment(ARow, ACol: Cardinal;
|
||||||
AComment: String): PsComment;
|
AComment: String): PsComment;
|
||||||
begin
|
begin
|
||||||
Result := PsComment(Find(ARow, ACol));
|
Result := PsComment(FindByRowCol(ARow, ACol));
|
||||||
if Result = nil then
|
if Result = nil then
|
||||||
Result := PsComment(Add(ARow, ACol));
|
Result := PsComment(Add(ARow, ACol));
|
||||||
Result^.Text := AComment;
|
Result^.Text := AComment;
|
||||||
@ -825,7 +868,7 @@ end;
|
|||||||
function TsHyperlinks.AddHyperlink(ARow, ACol: Cardinal; ATarget: String;
|
function TsHyperlinks.AddHyperlink(ARow, ACol: Cardinal; ATarget: String;
|
||||||
ATooltip: String = ''): PsHyperlink;
|
ATooltip: String = ''): PsHyperlink;
|
||||||
begin
|
begin
|
||||||
Result := PsHyperlink(Find(ARow, ACol));
|
Result := PsHyperlink(FindByRowCol(ARow, ACol));
|
||||||
if Result = nil then
|
if Result = nil then
|
||||||
Result := PsHyperlink(Add(ARow, ACol));
|
Result := PsHyperlink(Add(ARow, ACol));
|
||||||
Result^.Target := ATarget;
|
Result^.Target := ATarget;
|
||||||
@ -905,7 +948,7 @@ end;
|
|||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
function TsMergedCells.AddRange(ARow1, ACol1, ARow2, ACol2: Cardinal): PsCellRange;
|
function TsMergedCells.AddRange(ARow1, ACol1, ARow2, ACol2: Cardinal): PsCellRange;
|
||||||
begin
|
begin
|
||||||
Result := PsCellRange(Find(ARow1, ACol1));
|
Result := PsCellRange(FindByRowCol(ARow1, ACol1));
|
||||||
if Result = nil then
|
if Result = nil then
|
||||||
Result := PsCellRange(Add(ARow1, ACol1));
|
Result := PsCellRange(Add(ARow1, ACol1));
|
||||||
Result^.Row2 := ARow2;
|
Result^.Row2 := ARow2;
|
||||||
@ -999,7 +1042,7 @@ var
|
|||||||
rng: PsCellrange;
|
rng: PsCellrange;
|
||||||
dr, dc: Cardinal;
|
dr, dc: Cardinal;
|
||||||
begin
|
begin
|
||||||
rng := PsCellrange(Find(ARow1, ACol1));
|
rng := PsCellrange(FindByRowCol(ARow1, ACol1));
|
||||||
if rng <> nil then
|
if rng <> nil then
|
||||||
begin
|
begin
|
||||||
dr := rng^.Row2 - rng^.Row1;
|
dr := rng^.Row2 - rng^.Row1;
|
||||||
@ -1010,7 +1053,7 @@ begin
|
|||||||
rng^.Col2 := ACol2 + dc;
|
rng^.Col2 := ACol2 + dc;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
rng := PsCellRange(Find(ARow2, ACol2));
|
rng := PsCellRange(FindByRowCol(ARow2, ACol2));
|
||||||
if rng <> nil then
|
if rng <> nil then
|
||||||
begin
|
begin
|
||||||
dr := rng^.Row2 - rng^.Row1;
|
dr := rng^.Row2 - rng^.Row1;
|
||||||
|
@ -1360,7 +1360,7 @@ end;
|
|||||||
function TsWorksheet.FindComment(ACell: PCell): PsComment;
|
function TsWorksheet.FindComment(ACell: PCell): PsComment;
|
||||||
begin
|
begin
|
||||||
if HasComment(ACell) then
|
if HasComment(ACell) then
|
||||||
Result := PsComment(FComments.Find(ACell^.Row, ACell^.Col))
|
Result := PsComment(FComments.FindByRowCol(ACell^.Row, ACell^.Col))
|
||||||
else
|
else
|
||||||
Result := nil;
|
Result := nil;
|
||||||
end;
|
end;
|
||||||
@ -1385,7 +1385,7 @@ var
|
|||||||
comment: PsComment;
|
comment: PsComment;
|
||||||
begin
|
begin
|
||||||
Result := '';
|
Result := '';
|
||||||
comment := PsComment(FComments.Find(ARow, ACol));
|
comment := PsComment(FComments.FindByRowCol(ARow, ACol));
|
||||||
if comment <> nil then
|
if comment <> nil then
|
||||||
Result := comment^.Text;
|
Result := comment^.Text;
|
||||||
end;
|
end;
|
||||||
@ -1460,7 +1460,7 @@ end;
|
|||||||
function TsWorksheet.FindHyperlink(ACell: PCell): PsHyperlink;
|
function TsWorksheet.FindHyperlink(ACell: PCell): PsHyperlink;
|
||||||
begin
|
begin
|
||||||
if HasHyperlink(ACell) then
|
if HasHyperlink(ACell) then
|
||||||
Result := PsHyperlink(FHyperlinks.Find(ACell^.Row, ACell^.Col))
|
Result := PsHyperlink(FHyperlinks.FindByRowCol(ACell^.Row, ACell^.Col))
|
||||||
else
|
else
|
||||||
Result := nil;
|
Result := nil;
|
||||||
end;
|
end;
|
||||||
@ -2074,7 +2074,7 @@ end;
|
|||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
function TsWorksheet.FindCell(ARow, ACol: Cardinal): PCell;
|
function TsWorksheet.FindCell(ARow, ACol: Cardinal): PCell;
|
||||||
begin
|
begin
|
||||||
Result := PCell(FCells.Find(ARow, ACol));
|
Result := PCell(FCells.FindByRowCol(ARow, ACol));
|
||||||
{
|
{
|
||||||
if (ARow = FLastFoundRow) and (ACol = FLastFoundCol) then
|
if (ARow = FLastFoundRow) and (ACol = FLastFoundCol) then
|
||||||
Result := FLastFoundCell
|
Result := FLastFoundCell
|
||||||
@ -3119,7 +3119,7 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
|
|
||||||
// Is cell ARow1/ACol1 already the base of a merged range? ...
|
// Is cell ARow1/ACol1 already the base of a merged range? ...
|
||||||
rng := PsCellRange(FMergedCells.Find(ARow1, ACol1));
|
rng := PsCellRange(FMergedCells.FindByRowCol(ARow1, ACol1));
|
||||||
// ... no: --> Add a new merged range
|
// ... no: --> Add a new merged range
|
||||||
if rng = nil then
|
if rng = nil then
|
||||||
FMergedCells.AddRange(ARow1, ACol1, ARow2, ACol2)
|
FMergedCells.AddRange(ARow1, ACol1, ARow2, ACol2)
|
||||||
@ -3296,7 +3296,7 @@ end;
|
|||||||
-------------------------------------------------------------------------------}
|
-------------------------------------------------------------------------------}
|
||||||
function TsWorksheet.RemoveCell(ARow, ACol: Cardinal): PCell;
|
function TsWorksheet.RemoveCell(ARow, ACol: Cardinal): PCell;
|
||||||
begin
|
begin
|
||||||
Result := PCell(FCells.Find(ARow, ACol));
|
Result := PCell(FCells.FindByRowCol(ARow, ACol));
|
||||||
if Result <> nil then FCells.Remove(Result);
|
if Result <> nil then FCells.Remove(Result);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user