AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi ListView nach VirtualStringTree
Thema durchsuchen
Ansicht
Themen-Optionen

ListView nach VirtualStringTree

Offene Frage von "Onkelrossie"
Ein Thema von Onkelrossie · begonnen am 7. Aug 2006 · letzter Beitrag vom 9. Aug 2006
Antwort Antwort
Onkelrossie

Registriert seit: 7. Aug 2006
43 Beiträge
 
Delphi 7 Architect
 
#1

ListView nach VirtualStringTree

  Alt 7. Aug 2006, 13:58
Hallo liebe DP'ler ,
ich habe ein großes Problem eine ListView in den VirtualStringTree zu übertragen.
Dabei sollen auch gleich ein paar Details verbessert werden. Das übertragen der
Header funktioniert schon aber der Rest fällt mir sehr schwer da ich mit dem
VirtualStringTree nicht sehr vertraut bin. Ich habe zwar schon ein paar sachen
über VirtualStringTree hier im Forum gelesen, werde aber daraus nicht schlauer bzw.
habe ich kaum etwas gefunden was mir für mein Vorhaben hilft.
Ich kann nur auf euch in der DP hoffen das sich irgend ein VST Guru findet der
mir helfen kann.

Hier erstmal eine Skizze wie es bis jetzt in meiner ListView aussieht und wie es in etwa
dann in dem VirtualStringTree aussehen soll (wegen der Formatierung in Delphi-Tags):

Delphi-Quellcode:
So sieht es jetzt aus in meiner ListView:

Art. Name| Art.Nr. | Preis | Datum    
=========================================
Artikelx | ArtikelNr.1 | 1,00€ | 07.08.06}
Artikely | ArtikelNr.2 | 1,00€ | 07.08.06} Artikelgruppe 1 (weil artikel name gleich anfängt)
Artikelz | ArtikelNr.3 | 1,00€ | 07.08.06}

Ware1 | EAN:1234567 | 2,00€ | 07.08.06}
Ware2a | EAN:7654321 | 2,00€ | 07.08.06} Artikelgruppe 2 ...
Ware2b | EAN:0000000 | 2,00€ | 07.08.06}

So wollte ich es machen im VirtualStringTree:

Art. Name | Art.Nr. | Preis | Datum <---Header einlesen geht schon wunderbar
============================================
+-Artikel |ArtikelNr. |1,00€ |07.08.06 <---RootNode*
| └Artikelx | ArtikelNr.1 | 1,00€ | 07.08.06
| └Artikely | ArtikelNr.2 | 1,00€ | 07.08.06 <---SubNodes**
| └Artikelz | ArtikelNr.3 | 1,00€ | 07.08.06
+-Ware |EAN: |2,00€ |07.08.06
  └Ware1 | EAN:1234567 | 2,00€ | 07.08.06
  └Ware2a | EAN:7654321 | 2,00€ | 07.08.06
  └Ware2b | EAN:0000000 | 2,00€ | 07.08.06
*Der RootNode ergibt sich aus dem ersten Eintrag der jeweiligen Artikelgruppe abzüglich der
unterschiede im Namen. Also z.B. Artikelx, Artikely, Artikelz -> Artikelx ist der
erste Eintrag seiner Artikelgruppe -> Artikelx unterscheidet sich von Artikely und Artikelz
durch das letzte Zeichen im Namen (x) also entferne das x => 'Artikel' als RootNode schreiben.

**Alle einträge der jeweiligen Artikelgruppe aus der Listview übertragen
und als SubNodes der jeweiligen RootNode zuordnen. Also kurz gesagt 1:1 aus der ListView
übernehmen und als SubNodes in den VirtualStringTree schreiben.


Ich hoffe ich konnte Problem verständlich beschreiben.
Für jede Hilfe bin ich sehr Dankbar.


grüße aus Hamburg

Onkelrossie
  Mit Zitat antworten Zitat
Stormy

Registriert seit: 8. Okt 2005
Ort: LPZ
73 Beiträge
 
Delphi 6 Enterprise
 
#2

Re: ListView nach VirtualStringTree

  Alt 7. Aug 2006, 23:21
FC
  Mit Zitat antworten Zitat
Benutzerbild von uligerhardt
uligerhardt

Registriert seit: 19. Aug 2004
Ort: Hof/Saale
1.735 Beiträge
 
Delphi 2007 Professional
 
#3

Re: ListView nach VirtualStringTree

  Alt 8. Aug 2006, 09:23
Hi, onkelrossie,

ich würde das Problem vermutlich so angehen:

Schritt 1: Im Speicher die neue, hierarchische Struktur aufbauen, so wie du's unter * beschrieben hast, z.B ein dynamisches Array, etwa
Delphi-Quellcode:
type
  TSubNodeRecord = record
    // Alles, was du brauchst, um dir auf Zuruf des VT (OnGetText etc.) die Daten zu holen.
    // Hier reicht unter Umständen eine ID, ein Bookmark o.ä., d.h. du benötigst nicht
    // zwangsweise eine Kopie der Daten.
  end;
  TRootNodeRecord = record
    Name: string; // 'Artikel' oder 'Ware'
    SubNodes: array of TSubNodeRecord;
  end;
var
  RootNodes: array of TRootNodeRecord;
Schritt 2: Lerne die Eigenheiten des VT - schau dir z.B. mal das Minimal-Demo an.

Schritt 3: Setze die übliche VT-Litanei um:
  • Definiere ein geeignetes Record für GetNodeData (TMyRec im Demo).
    In deinem Fall vielleicht
    Delphi-Quellcode:
      TNodeData = record
        case IsRootNode: Boolean of // Root- oder SubNode
          True: (pRoot: PRootNodeRecord);
          False: (pSub: PSubNodeRecord);
      end;
    Vergiss nicht, NodeDataSize entsprechend zu initialisieren.
  • Nach dem Aufbereiten deiner Hierarchie setzeVT.RootNodeCount := Length(RootNodes);
  • Im OnInitNode-Handler initialisiere Data gemäß des NodeLevels als Root- oder SubNode.
    Bei RootNodes setze ivsHasChildren in InitialStates.
  • Der OnInitChildren-Handler wird (wegen ivsHasChildren ) für alle RootNodes aufgerufen.
    Hole dir dort per GetNodeData die Daten des Knotens. Setze ChildCount := Length(Data.pRoot^.SubNodes)
  • Schließlich musst du noch OnGetText implementieren ==> Übung für den Leser.

HTH, Uli.
Uli Gerhardt
  Mit Zitat antworten Zitat
Onkelrossie

Registriert seit: 7. Aug 2006
43 Beiträge
 
Delphi 7 Architect
 
#4

Re: ListView nach VirtualStringTree

  Alt 8. Aug 2006, 16:51
Hi uligerhardt,
Danke erstmal für deine umfangreiche Hilfe.
Ich habe bis jetzt noch mit dem VST rum probiert und deine Vorschläge getestet.
Jetzt weiss ich zwar einiges mehr über das erstellen von Nodes und verstehe auch schon langsam die
Funktionsweise von VST, aber meine Aufgabe konnte ich dennoch nicht in die Tat umsetzen.
Manuell habe ich es jetzt ohne Probleme geschafft es so darzustellen wie ich es haben wollte,
aber automatisch bzw. dynamisch will das einfach noch nicht so richtig Funktionieren.
Ich habe auch garkeinen Ansatz wie ich es Realisieren soll das er erkennt wo eine neue
"Artikelgruppe" anfängt und dann die unterschiede in der bezeichnung entfernt und als RootNode schreibt.
Ich habe da irgendwas von PosEx gelesen, weiss aber nicht ob mir das helfen kann.

Ich habe mal das was ich bisher schon hinbekommen habe als Download angehängt (Source und Exe).
Im Source habe ich auch ein paar Kommentare gemacht an der stelle wo ich nicht weiter komme.
Vieleicht trägt das zur verdeutlichung meines Problems bei und Ihr könnt genauer sehen was ich meine.

Ich bitte nochmals um Hilfe, langsam bin ich am verzweifeln.

[Edit]
Ich habe mir eben überlegt das man das mit den Artikelgruppen am besten mit einer ID bewerkstelligen könnte.
Also das man alle Artikel mit gleichem Namen sucht (wie gehabt) und denen dann eine Einzigartige ID zuweist.
Wenn ich nur wüsste wie man das am besten anstellt.
[/Edit]

Hg
Onkelrossie
Angehängte Dateien
Dateityp: rar source_195.rar (12,3 KB, 22x aufgerufen)
Dateityp: rar project1.exe_210.rar (310,0 KB, 24x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von NicNacMan
NicNacMan

Registriert seit: 28. Mai 2004
Ort: Hamburg
98 Beiträge
 
Delphi 2005 Personal
 
#5

Re: ListView nach VirtualStringTree

  Alt 8. Aug 2006, 23:28
Hi Onkelrossie,

da ich bald ein ähnliches Problem vor mir hab (es rückt auf meiner ToDo-List immer weiter nach unten ), hab ich mich mal dran gemacht:
(Ich hab einfach mal deine Prozedur erweitert)
Delphi-Quellcode:
procedure TForm1.LVtoVST;

  function StrCompare(s1, s2: String): Integer;
  // Liefert die Anzahl der maximal übereinstimmenden Zeichen (vom Anfang).
  var
    i, min: Integer;
  begin
    min := Length(s1);
    if (Length(s2) < min) then
      min := Length(s2);
    result := 0;
    for i := min downto 1 do
      if (Copy(s1, 1, i) = Copy(s2, 1, i)) then
      begin
        result := i;
        break;
      end;
  end;

  function FindRootNode(Caption, SubItem: String; var c0, c1: Integer): PVirtualNode;
  // Prüft, ob es schon eine Kategorie gibt, in die der Artikel rein passt.
  // c0 und c1 enthalten die Anzahl der Zeichen, die alle Untereinträge gemeinsam haben.
  var
    Node: PVirtualNode;
    Data: PTreeData;
    c: Integer;
  begin
    c0 := 0;
    result := nil;
    Node := VST.GetFirst;
    while Assigned(Node) do
    begin
      Data := VST.GetNodeData(Node);
      c := StrCompare(Caption, Data.FColumn0);
      if (c > c0) then
      begin
        c0 := c;
        c1 := StrCompare(SubItem, Data.FColumn1);
        result := Node;
      end;
      Node := VST.GetNextSibling(Node);
    end;
  end;

var
  I, c0, c1: Integer;
  TreeData: TTreeData;
  RootNode: PVirtualNode;
  Data: PTreeData;
begin
  CreateCols; //cols erstellen
  VST.NodeDataSize:= SizeOf(TTreeData); //größe zuweisen
  VST.BeginUpdate;
  for I := 0 to ListView1.Items.Count - 1 do //ListView durchlaufen, auslesen
  begin
    with TreeData do
    begin //und in den Record speichern
      FColumn0:= ListView1.Items[i].Caption;
      FColumn1:= ListView1.Items.Item[i].SubItems[0];
      FColumn2:= ListView1.Items.Item[i].SubItems[1];
      FColumn3:= ListView1.Items.Item[i].SubItems[2];
      RootNode := FindRootNode(FColumn0, FColumn1, c0, c1);
    end;
    if (RootNode = nil) then
    begin
      RootNode := AddVSTStructure(VST, nil, TreeData); // Kategorie erstellen
      AddVSTStructure(VST, RootNode, TreeData); // Artikel eintragen
    end
    else
    begin
      AddVSTStructure(VST, RootNode, TreeData); // Artikel eintrage
      Data := VST.GetNodeData(RootNode); // Überschriften anpassen
      Data.FColumn0 := Copy(Data.FColumn0, 1, c0);
      Data.FColumn1 := Copy(Data.FColumn1, 1, c1);
    end;
  end;
  VST.EndUpdate;
end;
Die Idee ist recht einfach: Vor dem eintragen, wird erst geprüft, ob es eine Kategorie gibt, in die der Artikel passt.
Falls nicht, wird erst eine erstellt, die genauso heißt.
Falls ja, werden die ersten beiden Überschriften (ist natürlich auch auf alle vier erweiterbar) so gekürzt, dass sie für alle Untereinträge passen.

lg NicNacMan
The Double-Crunch-Peanuts!
SwapIt:
  Mit Zitat antworten Zitat
Onkelrossie

Registriert seit: 7. Aug 2006
43 Beiträge
 
Delphi 7 Architect
 
#6

Re: ListView nach VirtualStringTree

  Alt 9. Aug 2006, 12:56
Hallo NicNacMan,
Danke für deinen Vorschlag, ich habe ihn auch gleich getestet und anfangs hatt es auch wunderbar Funktioniert.
Wenn nun aber jede Artikelgruppe mit dem gleichen Zeichen anfängt z.B.

Delphi-Quellcode:
Art. Name| Art.Nr. | Preis | Datum
=========================================
1.Artikelx | [ArtikelNr.1] | 1,00€ | 07.08.06} Artikelgruppe 1 (weil bis zum 2. Zeichen alles gleich ist ('1.') und erst dann
1.Artikely | [ArtikelNr.2] | 1,00€ | 07.08.06} Unterschiede auftreten. Artikelname fängt ab dem 3. Zeichen
1.Artikelz | [ArtikelNr.3] | 1,00€ | 07.08.06} gleich an und hört ab da auf, wo wieder unterschiede auftreten)

1.Ware1 | [EAN:1234567] | 2,00€ | 07.08.06}
1.Ware2a | [EAN:7654321] | 2,00€ | 07.08.06} Artikelgruppe 2 ...
1.Ware2b | [EAN:0000000] | 2,00€ | 07.08.06}
dann schreibt er wieder alle zusammen in den gleichen RootNode.
Wie kann ich das verhindern, also das er nur die "wirklichen" Unterschiede der Artikel findet und sie dann vergleicht.

So wie du es gemacht hast prüft er ja nur ob das erste zeichen gleich ist und wenn ja dann nimmt er die jeweiligen Artikel (so hab ich das zumindest verstanden). Was aber wenn nun bei allen Artikeln immer das erste oder z.B. erste und zweite Zeichen gleich ist? Ich habe deine "for-Schleife" noch etwas gändert und dann hatt es schon besser funktioniert, aber das nur weil er halt ab dem 3. zeichen erst anfängt zu vergleichen. Das ist aber auch wieder nur eine Notlösung.
Also wie filtert man die unterschiede zwichen den Artikelgruppen und den einzelnen Artikeln?

Ich bin weiterhin für jede Hilfe Dankbar!


Hg
Onkelrossie
  Mit Zitat antworten Zitat
Benutzerbild von NicNacMan
NicNacMan

Registriert seit: 28. Mai 2004
Ort: Hamburg
98 Beiträge
 
Delphi 2005 Personal
 
#7

Re: ListView nach VirtualStringTree

  Alt 9. Aug 2006, 13:30
Hi Onkelrossie,

die StrCompare() Funktion gibt nich an, ob das erste Zeichen gleich ist, sondern liefert die Anzahl der Zeichen, die beide Strings gemainsam haben.
StrCompare('Artikelx', 'Artikely') liefert also 7.
Änder mal in Zeile 28 den Wert von c0 auf 2.
Dann werden Artikel nur in eine Kategorie gepackt, wenn mindestens die ersten 3 Zeichen übereinstimmen.
Ich gehe mal davon aus, dass du das ganze nicht nur für diese sechs Atikel brauchst, sondern für eine ganze Datenbank. Und da weiß ich nicht, was es alls für Kategorien gibt.
Eine andere Möglichkeit als die ersten x Zeichen zu vergleichen wäre, dass man vorher eine Liste der Kategorien erstellt.
Denn woher soll das Programm wissen, wieviele der Zeichen übereinstimmen müssen, um sie zu gruppieren.

lg NicNacMan
The Double-Crunch-Peanuts!
SwapIt:
  Mit Zitat antworten Zitat
Onkelrossie

Registriert seit: 7. Aug 2006
43 Beiträge
 
Delphi 7 Architect
 
#8

Re: ListView nach VirtualStringTree

  Alt 9. Aug 2006, 14:25
Hallo NicNacMan,
wie du schon richtig erkannt hast geht es um mehrere Daten einer Datenbank.
Ich habe es jetzt nochmal so probiert wie du es gesagt hast (Zeile 28) aber da kommt genau das gleiche raus wie wenn ich die For-Schleife (Zeile 12) ändere. Eine Liste mit den Kategorien zu erstellen wäre auch nicht so optimal da sich die Kategorien auch ändern bzw. neue hinzu kommen können.

Eine Möglichkeit für mich wäre noch, den Text inklusieve Klammern dazwischen zu entfernen. Also wenn wenn ein Artikel diesen Namen hier hätte: 'Artikel(x)Nr.' so zu ändern das er dann so aussieht: 'ArtikelNr.'. Dann könnte ich mehrere Delimiter setzen und das was dann später rausgefiltert werden soll dazwischen einfügen. Dann müsste nur noch die Position der Delimiter gefunden werden und diese inklusieve des Textes dazwischen gelöscht werden. Nur wie stelle ich das am besten in einem VST an?

Vieleicht hast Du oder jemand anderes noch eine Antwort darauf. Dann wäre mir erstmal geholfen für den Moment.


HG
Onkelrossie
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:52 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz