Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Treeviewzugriff: Neuen Datensatz erstellen im Treeview (https://www.delphipraxis.net/52714-treeviewzugriff-neuen-datensatz-erstellen-im-treeview.html)

IngoH 2. Sep 2005 09:53

Datenbank: Access 2000 • Zugriff über: ADOConnection

Treeviewzugriff: Neuen Datensatz erstellen im Treeview
 
Hallo,

ich habe einen Treeview der super funktioniert erstellt.
Icons funktionieren (selected) auch und es klappt auch das Einlesen der Master-Table in den Baum.
Felder: ID, ParentID, FolderName

Ich will jetzt eine Datei anlegen. Das klappt auch im ensprechenden Unterverzeichniss.

Nur welche Werte muss ich der ADOTable in die Felder (ItemID, ParentID, ItemName, memFeld) übergeben und wie lese ich die Daten in den Child-Knoten wieder zurück?

Konkret: ParentID= Index des Knoten
ItemID=Autowert
ItemName=DateiName
memFeld=(Inhalt der Datei als XML-File)

Ich muss irgendwie den Index des Elternknoten ermitteln, als ParentID für die Client-Table speichern und dann eine Prozedur finden um die Items(Dateien) wieder in den Master-Knoten einzulesen. :gruebel:

Schon mal Danke für die Hilfe.
Gruß
Ingo

IngoH 2. Sep 2005 16:20

Re: Treeviewzugriff: Neuen Datensatz erstellen im Treeview
 
Hier mal ein Stück vom Code...


Delphi-Quellcode:

...

type
  TMyRecords = Record
    FolderID   : Integer;
    ParentID   : Integer;
    FolderName : String;
    ItemName   : String;
  end;

...


procedure TfrmMainProg.TreeViewInit;

  procedure MoveToParentNode(TheNode: TTreeNode);
    var x : Integer;
    begin
      for x := 0 to TreeView1.Items.Count-1 do begin
        if Assigned(TreeView1.Items[x].Data) then begin
          if PView(TreeView1.Items[x].Data).FolderID = PView(TheNode.Data).ParentID then begin
            TheNode.MoveTo(TreeView1.Items[x], naAddChild);
            Break;
          end;
        end;
      end;
    end;

var
  Root,AktNode : TTreeNode;
  i : Integer;
   
begin
  ADOTable1.First;
  TreeView1.Items.BeginUpdate;
  Root := TTreeNode.Create(TreeView1.Items);
  Root.Text := 'Root Dir';
  Root.ImageIndex := IMG_NODE_ROOT;
  //Root.Data := nil;

  While NOT ADOTable1.eof do
    begin
      AktNode := TTreeNode.Create(TreeView1.Items);
      AktNode.Data := new(PView);
      PView(AktNode.Data).FolderID  := ADOTable1.FieldByName('ID').AsInteger;
      PView(AktNode.Data).ParentID  := ADOTable1.FieldByName('ParentID').AsInteger;
      PView(AktNode.Data).FolderName := ADOTable1.FieldByName('FolderName').AsString;

      PView(AktNode.Data).ItemName := tblItems.FieldByName('ItemName').AsString;


      /// Folder einlesen ...
      with TreeView1.Items.Add(AktNode, PView(AktNode.Data).FolderName) do
        begin
          Data:=AktNode.Data;
          ImageIndex := IMG_NODE_FOLDER_CLOSED;
          SelectedIndex := IMG_NODE_FOLDER_OPEN;
        end;


   {    /// Das hier funzt irgendwie nicht, ///Files einlesen
        with TreeView1.Items.AddChild(AktNode, PView(AktNode.Data).ItemName) do
        begin
          Data:=AktNode.Data;
          ImageIndex := IMG_NODE_FILE_CLOSED;
          SelectedIndex := IMG_NODE_FILE_OPEN;
        end;
      tblItems.Next;
    }
     
      ADOTable1.Next;
    end;


    for i := 0 to TreeView1.Items.Count -1 do
      begin
        if Assigned(TreeView1.Items[i].Data) then
          begin
            if PView(TreeView1.Items[i].Data).ParentID <> 0 then
              MoveToParentNode(TreeView1.Items[i]);
          end;
      end;

   
  TreeView1.FullCollapse;
  TreeView1.Items.EndUpdate;
end;

Und die Procedure um eine neue Datei anzulegen und in die Datenbank zu schreiben lautet:
Delphi-Quellcode:
procedure TDataModule1.InsertFile (sFile :string; iFileID :integer);
begin
  With ADOQuery1 do
    begin
      Insert;
      FieldByName('FolderName').AsString := sFile;
      FieldByName('ParentID').AsInteger := iFileID;
      //FieldByName('memFeld').xxxxxxxx??? ///hier die xml-Datei als Stream??? :wall:
      Post;
    end;
end;
Woher nehme ich den Wert für iFileID (Das Node, das ich gerade angelegt habe)? Welchen Wert also Index?

marabu 2. Sep 2005 17:32

Re: Treeviewzugriff: Neuen Datensatz erstellen im Treeview
 
Hallo Ingo,

unabhängig von deinen anderen Problemen - du produzierst jede Menge Speicherlöcher, wenn du mit TTreeNode.Create() arbeitest.
Lies mal hier: klick

Grüße vom marabu

IngoH 2. Sep 2005 18:01

Re: Treeviewzugriff: Neuen Datensatz erstellen im Treeview
 
Ja, die Knoten werden doch korrekt angefügt.

Delphi-Quellcode:
/// Folder einlesen ...
      with TreeView1.Items.Add(AktNode, PView(AktNode.Data).FolderName) do
        begin
          Data:=AktNode.Data;
          ImageIndex := IMG_NODE_FOLDER_CLOSED;
          SelectedIndex := IMG_NODE_FOLDER_OPEN;
        end;
Klicke ich auf das Folder-Image öffnet es sich.

Vielleicht anders initalisieren?

marabu 2. Sep 2005 18:17

Re: Treeviewzugriff: Neuen Datensatz erstellen im Treeview
 
Mein Hinweis bezieht sich auf diese Stelle in deinem Code:

Delphi-Quellcode:
...
while not ADOTable1.Eof do begin
  AktNode := TTreeNode.Create(TreeView1.Items);
...
Der von dir an dieser Stelle erzeugte Knoten AktNode verschwindet in den Untiefen des Speichermanagements. Mit dem Link wollte ich dir die Augen öffnen.

marabu

PS: Du möchtest XML-Dokumente aus einem Dateisystem in einer Access-Datenbank verwalten - verstehe ich das richtig?

IngoH 2. Sep 2005 18:50

Re: Treeviewzugriff: Neuen Datensatz erstellen im Treeview
 
Zitat:

Zitat von marabu
PS: Du möchtest XML-Dokumente aus einem Dateisystem in einer Access-Datenbank verwalten - verstehe ich das richtig?

Ja ist nicht ganz richtig.

Ich will die Reports von FastReport (die ähnlich einem Text/bzw. XML-Dokument sind) in einem BLOB-Feld meiner ACCESS-Datenbank ablegen.
Das müsste eigentlich sehr gut gehen, da es sich nur um Text-Dokumente handelt.

Delphi-Quellcode:
ms:=TMemoryStream.Create;
try
Report.SaveToStream(ms);
ms.Position:=0;
Conn.Connected:=true;
Qry.SQL.Text:=Format('SELECT FROM WHERE', []);
Qry.Open;
try
BlobField:=TBlobField(Qry.Fields[xxx]);
if Qry.RecordCount=0 then Qry.Append else Qry.Edit;
BlobField.LoadFromStream(ms);
Qry.Post;
finally
Qry.Close;
Conn.Connected:=false;
end;
finally
if ms<>nil then ms.Free;
if Qry.Active then Qry.Close;
if Conn.Connected then Conn.Connected:=false;
end;
Vielleicht so.

Aber dazu muss ich erstmal die Reports in der Client-Tabelle vernüftig mit meinem Folder im Treeview verknüpfen. Und das klappt noch nicht.
Bzw. schaffe ich es nicht die ID des TreeView dem entsprechendem Folder beim Speichern zuzuordnen.
Das Laden in den Tree klappt dann ganz gut wieder, wenn ich die Werte von Hand in die Tabelle eintrage.

Gruß
Ingo

marabu 2. Sep 2005 19:05

Re: Treeviewzugriff: Neuen Datensatz erstellen im Treeview
 
Verständnisfragen:

Die Knoten deines Baumes tragen die Namen von Ordnern im Dateisystem?
Die Ordnung in deinem Baum ist alphabetisch?
ID ist automatisch erzeugter Primärschlüssel deiner Tabelle?
PARENTID ist ein Fremdschlüssel auf die gleiche (selbstrekursive) Tabelle?
Müssen nicht mehrere XML-Dateien mit einem Knoten / Folder verknüpft werden?

marabu

IngoH 2. Sep 2005 19:20

Re: Treeviewzugriff: Neuen Datensatz erstellen im Treeview
 
Nein es handelt sich lediglich um ein "virtuelles Dateisystem".

Der Anwender kann Ordner anlegen, Unterordne, Unter-unter-Ordner usw.
Dort speichert er dann den Report in einem Memofeld. (das habe ich im Code noch nicht implementiert).


SELECT [ID], [ParentID], [FolderName], [Report]
FROM DBTree;

Report ist da MEMO-Feld, wo der FR abgelegt werden soll.

Nur weiss ich nicht wie ich der Tabelle dbTree den Speicherort des Reports im Tree (Hier: ParentID) übergeben soll.

Index.selected ?? Irgendwie. Aber das geht nicht.

Pseudo-Code
Delphi-Quellcode:
dmReport.DataModule1.InsertFile(sFolderName, TreeView1.Selected.SelectedIndex+1, TextAlsMemo);
Ich weiss, klingt kompliziert. Ist aber eine gute Idee. Besser, als das der Anwedner selbst die Festplatte nach den Reports durchsuchen muss.

Gruß
Ingo

marabu 2. Sep 2005 20:30

Re: Treeviewzugriff: Neuen Datensatz erstellen im Treeview
 
Dein virtuelles Filesystem heißt bei mir Gliederung. Die anderen Fragen hast du noch nicht beantwortet. Üblich ist eine selbstrekursive Tabelle für die Gliederung (Outline). Dazu würde ich dann eine Tabelle Reports verwenden, in der jedem (leaf-)node beliebig viele Reports zugeordnet werden können.

Der folgende Code zeigt dir sinngemäß das rekursive Aufbauen einer Gliederung aus einer Tabelle:

Delphi-Quellcode:
const
  SEL_NODES
    = 'select id, folder, outline_id '
    + 'from outline '
    + 'order by outline_id, folder '
    ;

  SEL_REPORT
    = 'select report from reports '
    + 'where outline_id = %d';

function TMainForm.TreeNodes: TTreeNodes;
begin
  Result := TreeView.Items;
end;

procedure TMainForm.LoadNodes(nParent: TTreeNode; iParent: integer; recursive: boolean = true);
var
  i, id: integer;
  folder: string;
  bm: TBookmark;
  n: TTreeNode;
begin
  with QOutline do
  begin
    if Locate('outline_id', iParent, []) then
      while FieldValues['outline_id'].AsInteger = iParent do
      begin
        id := FieldValues['id'].AsInteger;
        n := TreeNodes.AddChildObject(nParent, folder, Pointer(id));
        if recursive then begin
          bm := GetBookmark;
          LoadNodes(n, id, recursive);
          GotoBookmark(bm);
          FreeBookmark(bm);
        end;
        Next;
      end;
  end;
end;

procedure TMainForm.miLoadClick(Sender: TObject);
begin
  // QOutline.SQL.Text := SEL_NODES;
  // QOutline.Open;
  LoadNodes(nil, 0);
  // QOutline.Close;
end;
Jetzt wäre interessant zu wissen, ob du deine Reports als Unterknoten im Baum visualisieren willst, oder lieber bei einer Knotenart (folder) bleibst und die reports in einer ListView anzeigst (explorer style - mein Favorit).

marabu

IngoH 3. Sep 2005 00:02

Re: Treeviewzugriff: Neuen Datensatz erstellen im Treeview
 
Ja, richtig. Soll in einem Listview dargestellt werden. Die Synchronisation funzt auch schon.

Aber leider nicht dein Beispiel. Vieleicht habe ich die Falschen Tabellen angelgt.
Jetzt schmeiss ich bald die Flinte in Korn.

Delphi-Quellcode:
while FieldValues['outline_id'].AsInteger = iParent do
Ungültige Variant-Operation.

Gruß
Ingo


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:34 Uhr.
Seite 1 von 2  1 2      

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