OK. Danke für den Tip. So bin ich fast am Ziel. Die Daten werden vom StringGrid ins Treeview übernommen und zusammengefasst :
Delphi-Quellcode:
function AddTreeNodePathDupIgnore(TV: TTreeView;
Path: String;
Delimiter: Char;
var ReNode : TTreeNode;
AddType: TAddType): Boolean;
var sL : TStringList;
aNode : TTreeNode;
z,iCount,zz,i : Integer;
begin
Result := False;
aNode := nil;
ReNode := nil;
sL := TStringList.Create;
try
//alle Delimiter durch #13 (carriage return [CR]) ersetzen
for z := 1 to Length(Path) do
if Path[z] = Delimiter then
Path[z] := #13;
//interner Parser der Stringlist teilt Path in Path-Token auf
sL.Text := Path;
//durch eventuelle doppelte oder abschließende Delimiter
//erzeugte Leeritems in StringList löschen
for z := sL.Count-1 downto 0 do
if sL[z] = '' then
sL.Delete(z);
iCount := Pred(sL.Count);
if TV.Items.Count > 0 then//min 1 Knoten vorhanden
aNode := TV.Items[0];//beim ersten Knoten beginnen
for z := 0 to iCount do//alle Token der StringList im TreeView suchen
begin
//solange noch Knoten in der Ebene vorhanden
//und Knotentext ungleich gesuchten Token
while Assigned(aNode) and (AnsiCompareStr(aNode.Text,sL[z]) <> 0) do
aNode := aNode.GetNextSibling;//nächster Knoten
if Assigned(aNode) then//Knoten gefunden
//Funktions-Rückgabeparameter setzen
ReNode := aNode
else
begin
//Knoten nicht gefunden, also in TreeView einbauen
Result := True;//Funktions-Rückgabewert setzen
if assigned(ReNode) then//min Root wurde gefunden
aNode := ReNode;//ausgehend vom letzten gefundenen Knoten
case AddType of
//alle nicht gefundenen Path-Token als Child einfügen
AddTop :
for zz := z to iCount do
aNode := TV.Items.AddChildFirst(aNode,sL[zz]);
//alle nicht gefundenen Path-Token einsortieren
AddSort :
begin
for zz := z to iCount do
if TV.Items.Count = 0 then//TreeView ist noch leer
aNode := TV.Items.AddChild(aNode,sL[zz])
else
begin
if not (assigned(aNode)) then//in Root-Nodes suchen
begin
aNode := TV.Items[0];
while Assigned(aNode) and (AnsiCompareStr(aNode.Text,sL[zz]) < 0) do
aNode := aNode.GetNextSibling;
if Assigned(aNode) then//Einfügestelle gefunden
aNode := TV.Items.Insert(aNode,sL[zz])
else//nicht gefunden, also anhängen
aNode := TV.Items.AddChild(aNode,sL[zz]);
end
else//in weiteren Ebenen(Level) suchen
begin
if aNode.Count > 0 then//nur suchen wenn Child-Node vorhanden sind
begin
i := aNode.Count-1;
aNode := aNode[0];//auf ersten Child-Node setzen
while (aNode.Index < i) and (AnsiCompareStr(aNode.Text,sL[zz]) < 0) do
aNode := aNode.GetNextSibling;
if AnsiCompareStr(aNode.Text,sL[zz]) < 0 then
//Einfügestelle nicht gefunden
aNode := TV.Items.Add(aNode,sL[zz])
else
//Einfügestelle gefunden
aNode := TV.Items.Insert(aNode,sL[zz]);
end
else//kein Child-Node vorhanden
aNode := TV.Items.AddChild(aNode,sL[zz]);
end;
end;
end;
//alle nicht gefundenen Path-Token als Child anfügen
AddBottom :
for zz := z to iCount do
aNode := TV.Items.AddChild(aNode,sL[zz]);
end;{case}
ReNode := aNode;//Funktions-Rückgabeparameter setzen
Break;//beenden der Path-Token-Such-Schleife
end;{else}
if z < iCount then//beim letzten Path-Token nicht
aNode := aNode.GetFirstChild;
end;{for}
finally
sL.Free;
end;
end;
ABER, wie immer ein aber, der letzte eintrag soll etwas gesondert behandelt werden. z.B:
münchen
...Nürnberg
......
würzburg <------Hier als Durchfahrtsbahnhof
.........Frankfurt
......
Würzburg <------Hier als Endstation
Berlin
...
Hannover <------Hier als Durchfahrtsbahnhof
......Düsseldorf
.........Saarbrücken
...
Hannover <------Hier als Endstation
Hamburg
usw.
Die Einträge "Würzburg" und "Hannover" sollen zweimal im Tree erscheinen. Einmal als Endstation, einmal als Durchfahrt. Ich hab versucht, in der oberen prozedure rumzubasteln aber bekamm nicht das gewünchte ergebniss raus...