Patrix2911 hat geschrieben:derem Verständnis ich scheinbar nicht würdig bin.
Dann wird's Zeit, dem Verständinis auf die Sprünge zu helfen.
In deinem konkreten Fall würde ich das Memo Zeile für Zeile durchlaufen und jeden String in die einzelnen Wörter aufspalten, wobei die letzten beiden später wieder zusammengefasst werden müssen:
Code: Alles auswählen
var
arr: TStringArray;
...
arr := Memo1.Lines[index].Split;
Bei der fest vorgegebenen Struktur des Baums brauchst du dann 4 Variablen für Nodes: node1 für SOLs, node2 für 11380, node3 für l, m etc, node4 für "royal blue" etc.
Beim Durchlaufen der Strings erzeugst du den 1.Node mit dem Element arr[0] und Parent nil:
Die "11380" ist ein Kind von "SOLs", analog ist "l" ein Kind von "11380", usw. Also
Code: Alles auswählen
node2 := TreeView1.Items.AddChild(node1, arr[1]);
node3 := TreeView1.Items.AddChild(node2, arr[2]);
node4 := TreeView1.Items.Addchild(node3, arr[3] + ' ' + arr[4]);
Das stimmt aber nicht ganz, weil nun für jede Memo-Zeile ein "SOLs" Node erzeugt wird. Daher musst du, bevor du die neuen Nodes erzeugst, suchen, ob es diese vielleicht schon gibt. Dazu prüft die folgende Funktion einen Node, ob sein "Text" dem Suchtext entspricht, also "SOLs" oder "11380" oder "m" oder "l" usw. Wenn das so ist, dann wird die Funktion verlassen, und der Node als Funktionswert übergeben. Wenn nicht, wird die Funktion mit dem ersten Kindknoten und den nächsten Geschwisterknoten aufgerufen. Dadurch wird effektiv der gesamte bereits angelegte Baum durchforstet. Erst wenn ganz am Ende nichts gefunden worden ist, wird das Funktionsergebnis nil.
Code: Alles auswählen
// Suche den Node im gesamten Tree, der den angegebenen Text als Caption hat
function TForm1.FindNode(ACaption: String; ANode: TTreeNode): TTreeNode;
var
sibling, child: TTreeNode;
begin
if ANode = nil then begin
if TreeView1.Items.Count = 0 then begin
Result := nil;
exit;
end else
ANode := TreeView1.Items[0];
end;
// Prüfe den Node selbst
if ANode.Text = ACaption then begin
Result := ANode;
exit;
end;
// Prüfe alle "Kinder" von ANode
child := ANode.GetFirstChild;
if child <> nil then begin
Result := FindNode(ACaption, child); // child prüft seine eigenen Kinder und Geschwister und immer so weiter
if Result <> nil then exit;
end;
// Prüfe Geschwister
sibling := ANode.GetNextSibling;
if sibling <> nil then begin
Result := FindNode(ACaption, sibling); // sibling prüft seine eigenen Kinder und die folgenden Geschwister
if Result <> nil then
exit;
end;
// Nichts gefunden
Result := nil;
end;
Um die bereits existierenden Nodes zu berücksichtigen, musst du also "FindNode" aufrufen. Das Ergebnis nimmst du als Parent für den nächsten Teilstring des Memos, bzw. falls der Node nicht gefunden wurde, musst du ihn wie oben erläutert neu erzeugen:
Code: Alles auswählen
procedure TForm1.MemoToTree;
var
i: Integer;
arr: TStringArray;
node1, node2, node3, node4: TTreeNode;
begin
for i:=0 to Memo1.Lines.Count-1 do begin
arr := String(Memo1.Lines[i]).Split(' ');
node1 := FindNode(arr[0], nil);
if node1 = nil then
node1 := TreeView1.Items.AddChild(nil, arr[0]);
node2 := FindNode(arr[1], node1);
if node2 = nil then
node2 := TreeView1.items.AddChild(node1, arr[1]);
node3 := FindNode(arr[2], node2);
if node3 = nil then
node3 := TreeView1.Items.AddChild(node2, arr[2]);
node4 := FindNode(arr[3] + ' ' + arr[4], node3);
if node4 = nil then
node4 := TreeView1.Items.AddChild(node3, arr[3] + ' ' + arr[4]);
end;
TreeView1.FullExpand;
end;
Es gibt sicher noch andere Herangehensmöglichkeiten. Zwangsläufig wirst du immer auf eine rekursive Funktion, also eine Funktion, die sich immer wieder mit geänderten Parametern selbst aufruft. Bei rekursiven Funktionen habe ich immer das Gefühl, jemand würde mein Gehirn umdrehen... Aber diese Dinger sind sehr elegant und gerade bei Bäumen unerlässlich.