Delphi-PRAXiS
Seite 1 von 2  1 2   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi StringGrid in Treeview zeigen (https://www.delphipraxis.net/91307-stringgrid-treeview-zeigen.html)

DavidKlimas 3. Mai 2007 08:21


StringGrid in Treeview zeigen
 
Hallo,

ich brauche mal wieder Hilfe zum Treeview. Ich habe ein StringGrid mit n einträgen (manchmal 5, manchmal 500) und ich möchte dieses in einem Treeview abbilden. Jede spalte des StringGrids soll ein neuer "Child" der vorhergehenden Spalte sein. Das Prinzip :

Zeile1-1.Spalte
...Zeile1-2.Spalte
......Zeile1-3.Spalte
Zeile2-1.Spalte
...Zeile2-1.Spalte
Zeile3-1.Spalte
...Zeile3-2.Spalte
......Zeile3-3.Spalte

usw.

Ich bedanke mich für jegliche Hilfe...

messie 3. Mai 2007 09:46

Re: StringGrid in Treeview zeigen
 
Du musst Deine Einträge aus dem StringGrid als Textdatei oder Stream speichern und dann ins TreeView einlesen. Jede untergeordnete Ebene wird dann durch ein oder mehrere führende Tabs zugeordnet.
Bau Dir mal ein TreeView und speichere es mit TreeView.SaveToFile ab, dann sieht man gleich wie es funktioniert.
Delphi-Quellcode:
var
  sl : TStringList;
  sg : TStringGrid;
  i,j,k : integer;
  s : string;
begin
  for i := 1 to sg.RowCount do
  begin
    s := '';
    s := sg.Cells[i,1];  
    sl.Add(s);
    for j := 2 to sg.ColCount do
    begin
      s := '';
      for k := 1 to j-1 do
      begin
        s := s + #9;
      end;
      s := s + sg.Cells[i,j];
    end;
  end;
  sl.SaveToFile('irgendwas');//und die dann laden
end;
Grüße, Messie

Bernhard Geyer 3. Mai 2007 09:50

Re: StringGrid in Treeview zeigen
 
Falls ein paar € investiert werden können. Diverse Grids wie z.B. vom ElPack können sowas

marabu 3. Mai 2007 10:55

Re: StringGrid in Treeview zeigen
 
Hallo David,

wenn es wirklich nur um die Übernahme von Griddaten gehen sollte, dann geht das auch ohne Zwischenspeicherung:

Delphi-Quellcode:
procedure AddSubTree(tv: TTreeView; s: TStrings; iSkip: Integer);
var
  i: Integer;
  tn: TTreeNode;
begin
  tn := nil;
  for i := iSkip to Pred(s.Count) do
    tn := tv.Items.AddChild(tn, s[i]);
end;

procedure TDemoForm.ButtonClick(Sender: TObject);
var
  iRow: Integer;
begin
  with StringGrid do
    for iRow := FixedRows to Pred(RowCount) do
      AddSubTree(TreeView, Rows[iRow], FixedCols);
end;
Allerdings kann ich aufgrund deiner Beschreibung nicht erkennen, warum eine TreeView deine Daten besser visualisieren sollte als ein Grid.

Grüße vom marabu

DavidKlimas 3. Mai 2007 11:20

Re: StringGrid in Treeview zeigen
 
Eigentliches ziel ist es Zeilen des Stringgrids , die gleich anfangen zusammenzufügen. Als Beispiel :

ICE-Abfahrten mit Stationen im Stringgrid

Hamburg - Hannover - Kassel - Frankfurt
Berlin - Hannover - Düsseldorf - Köln - Saarbrücken
Hamburg - Bremen - Osnabrück
München - Nürnberg - Würzburg - Frankfurt
Berlin - Hannover - Düsseldorf - Osnabrück - Bremen

Das ist mein Stringgrid aktuell. Im Treeview will ich jetzt folgendes :

Hamburg
..+Hannover
.....+Kassel
........-Frankfurt
..+Bremen
.....-Osnabrück
Berlin
..+Hannover
.....+Düsseldorf
........+Köln
...........-Saarbrücken
........+Osnabrück
...........-Bremen
München
..+Nürnberg
.....+Würzburg
........-Frankfurt

hoika 3. Mai 2007 11:25

Re: StringGrid in Treeview zeigen
 
Hallo,

das sollte der virtual treeview von Lischke auch können.
Einfach mal googlen und sich die demos ansehen.


Heiko

Lannes 3. Mai 2007 13:10

Re: StringGrid in Treeview zeigen
 
Hallo,

die Funktion AddTreeNodePathDupIgnore aus der Delphi-Library der Entwickler-Ecke hilft Dir.

Auslesen des StringGrids und Aufruf der Funktion:
Delphi-Quellcode:
var z,i : Integer;
    ReNode : TTreeNode;
    s : String;
begin
  TreeView1.Items.BeginUpdate;
  TreeView1.Items.Clear;
  for z := 1 to Pred(StringGrid1.RowCount) do
    begin
    i := 0;
    while StringGrid1.Cells[i,z] <> '' do
      begin
      s := s + StringGrid1.Cells[i,z]+ #09;
      inc(i);
      end;
    AddTreeNodePathDupIgnore(TreeView1,s,#09,ReNode,AddSort);
    s := '';
    end;
  TreeView1.Items.EndUpdate;

DavidKlimas 3. Mai 2007 19:21

Re: StringGrid in Treeview zeigen
 
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...

Lannes 3. Mai 2007 20:02

Re: StringGrid in Treeview zeigen
 
Hallo,

ob ich das richtig verstanden habe :gruebel:
Teste mal folgendes:
-der Funktion AddTreeNodePathDupIgnore den letzten Eintrag nicht mit übergeben
-die Funktion liefert Dir im Parameter ReNode den eingefügten bzw. gefundenen Knoten
-an diesen hängst Du dann Deinen letzten Eintrag aus der Row des Grids
Delphi-Quellcode:
//...
  TreeView.Items.AddChild(ReNode,DerLetzteAusDemGrid);
//...
Funkioniert nicht?
Eventuell mal Beispiel-Daten aus dem Grid und die beispielhafte Umsetzung als Tree dazu hier posten damit man Dein Vorhaben besser verstehen kann.

DavidKlimas 3. Mai 2007 20:08

Re: StringGrid in Treeview zeigen
 
Du hast es richtig verstanden. Leider ist das program ziemlich komplex und das StringGrid hat mehrere Tausend einträge, deswegen muss ich hier improvisieren, was manchmal recht unverständlich ist. Ich dachte daran, den letzten eintrag einfach abzuhängen und später einfach dazuzunehmen... Werd das mal probieren...


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:45 Uhr.
Seite 1 von 2  1 2   

Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf