{"id":55001585,"date":"2026-04-01T00:00:00","date_gmt":"2026-03-05T20:24:41","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=1585"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\/","title":{"rendered":"Mit Ordnern und Dateien im TreeView arbeiten, Teil 1"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg01.met.vgwort.de\/na\/7ea7dc3080954ce994e0d50e06c64415\" width=\"1\" height=\"1\" alt=\"\"><b>Im Artikel  &#8222;Ordner und Dateien in Access-Tabellen einlesen&#8220; (www.access-im-unternehmen.de\/1583) haben wir gezeigt, wie wir schnell Ordner und Dateien in Tabellen speichern, in  &#8222;Dateien schnell im TreeView-Steuerelement anzeigen&#8220; (www.access-im-unternehmen.de\/1584) haben wir Techniken vorgestellt, mit denen wir die Daten dieser Tabellen performant in einem TreeView-Steuerelement pr&auml;sentieren. Im vorliegenden Artikel schauen wir uns nun an, wie man in diesem TreeView-Steuerelement mit den Ordnern und Dateien arbeiten kann: Wie zeigen wir einen Ordner direkt im Windows-Explorer an? Wie &ouml;ffnen wir eine Datei direkt per Doppelklick? Wie k&ouml;nnen wir Kopieren, Ausschneiden und Einf&uuml;gen im TreeView nutzen? Wie benennen wir Ordner und Dateien um? Und schlie&szlig;lich: Wie &uuml;bertragen wir diese &Auml;nderungen direkt auf das Dateisystem?<\/b><\/p>\n<h2>Voraussetzung<\/h2>\n<p>Wir bauen in diesem Artikel auf dem Beispielformular <b>frmDateienImTreeView<\/b> auf, das wir im Artikel <b>Dateien schnell im TreeView-Steuerelement anzeigen<\/b> (<b>www.access-im-unternehmen.de\/1584<\/b>) bereits vorgestellt haben (siehe Bild 1).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_02\/pic_1585_005.png\" alt=\"TreeView-Steuerelement mit den Eintr&auml;gen, mit denen wir arbeiten wollen\" width=\"549,6265\" height=\"467,607\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: TreeView-Steuerelement mit den Eintr&auml;gen, mit denen wir arbeiten wollen<\/span><\/b><\/p>\n<h2>Ordner oder Dateien direkt im Windows Explorer anzeigen<\/h2>\n<p>Als Erstes wollen wir uns um die Anzeige eines Ordners oder einer Datei direkt im Windows Explorer k&uuml;mmern und f&uuml;r diesen Zweck die ben&ouml;tigten Funktionen programmieren. Diese Funktionen werden wir sp&auml;ter in verschiedenen Kontexten aufrufen &#8211; das Anzeigen eines Ordners &uuml;ber das Kontextmen&uuml; und das Anzeigen einer Datei im Windows Explorer &uuml;ber das Kontextmen&uuml; oder per Doppelklick auf das jeweilige Datei-Element im <b>TreeView<\/b>-Steuerelement.<\/p>\n<h2>Ordner direkt im Windows Explorer anzeigen<\/h2>\n<p>Die Prozedur zum Anzeigen eines Ordners im Windows Explorer ist denkbar einfach. Wir m&uuml;ssen nur die Anwendung <b>Explorer.exe <\/b>aufrufen und dieser den Pfad des anzuzeigenden Ordners &uuml;bergeben. Au&szlig;erdem k&ouml;nnen wir noch angeben, in welchem Fenstermodus der Windows Explorer ge&ouml;ffnet werden soll &#8211; hier w&auml;hlen wir standardm&auml;&szlig;ig die normale Ansicht. Die Prozedur <b>OpenFolderInExplorer <\/b>nimmt den Pfad des anzuzeigenden Ordners als Parameter entgegen:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>OpenFolderInExplorer(strPath<span style=\"color:blue;\"> As String<\/span>)\r\n    Shell \"explorer.exe \"\"\" & strPath & \"\"\"\", _\r\n        vbNormalFocus\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Sie ruft die VBA-Funktion <b>Shell<\/b> auf und &uuml;bergibt den in Anf&uuml;hrungszeichen eingefassten Pfad als Parameter. Wenn wir etwa den Pfad des aktuellen Datenbankverzeichnisses anzeigen wollen, rufen wir die Prozedur beispielsweise wie folgt auf:<\/p>\n<pre><span style=\"color:blue;\">Call<\/span> OpenFolderInExplorer(CurrentProject.Path)<\/pre>\n<h2>Datei direkt im Windows Explorer anzeigen<\/h2>\n<p>Wir k&ouml;nnen noch einen Schritt weitergehen und direkt eine Datei im Windows Explorer markieren. Die entsprechende Prozedur nennen wir <b>ShowFileInExplorer<\/b>:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>ShowFileInExplorer(strPath<span style=\"color:blue;\"> As String<\/span>)\r\n    Shell \"explorer.exe \/select,\"\"\" & strPath & \"\"\"\", _\r\n        vbNormalFocus\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Sie verwendet vor der Angabe des Pfades zu der zu markierenden Datei den Parameter <b>\/select<\/b>. Diese Prozedur rufen wir beispielsweise f&uuml;r die aktuelle Datenbankdatei wie folgt auf:<\/p>\n<pre><span style=\"color:blue;\">Call<\/span> ShowFileInExplorer(CurrentDb.name)<\/pre>\n<h2>Datei mit der jeweiligen Anwendung &ouml;ffnen<\/h2>\n<p>Die Prozedur, mit der wir eine Datei direkt in der jeweiligen Anwendung &ouml;ffnen k&ouml;nnen, hei&szlig;t <b>OpenFile<\/b> und verwendet die Methode <b>FollowHyperlink <\/b>des <b>Application<\/b>-Objekts:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>OpenFile(strPath<span style=\"color:blue;\"> As String<\/span>)\r\n    Application.FollowHyperlink strPath\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Um zum Beispiel eine Bilddatei aus dem aktuellen Datenbankverzeichnis anzuzeigen, nutzen wir den folgenden Aufruf:<\/p>\n<pre><span style=\"color:blue;\">Call<\/span> OpenFile(CurrentProject.Path & \"\\pic005.png\")<\/pre>\n<h2>Angeklicktes Node-Element ermitteln<\/h2>\n<p>F&uuml;r verschiedene Aktionen m&uuml;ssen wir zuvor das angeklickte <b>Node<\/b>-Element referenzieren &#8211; zum Beispiel, wenn wir eine Aktion beim Doppelklick darauf ausf&uuml;hren wollen.<\/p>\n<p>Also deklarieren wir im Kopf des Klassenmoduls eine Variable, um das aktuelle Element zu referenzieren:<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>objCurrentNode<span style=\"color:blue;\"> As <\/span>MSComctlLib.Node<\/pre>\n<p>Wenn der Benutzer auf ein <b>Node<\/b>-Element klickt, soll dieses mit <b>objCurrentNode <\/b>referenziert werden. Wenn der Benutzer auf einen freien Bereich im <b>TreeView<\/b>-Steuerelement klickt, soll die Objektvariable <b>objCurrentNode <\/b>geleert werden.<\/p>\n<p>Das erledigen wir mit der Ereignisprozedur, die beim Herunterdr&uuml;cken der Maustaste ausgel&ouml;st wird. Wir legen die entsprechende Prozedur an, indem wir im Codefenster im linken Auswahlfeld den Eintrag <b>ctlTreeView <\/b>ausw&auml;hlen und im rechten Auswahlfeld <b>MouseDown<\/b>. Die so angelegte Prozedur f&uuml;llen wir mit den folgenden Anweisungen:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>ctlTreeView_MouseDown( _\r\n        ByVal Button<span style=\"color:blue;\"> As Integer<\/span>, ByVal Shift<span style=\"color:blue;\"> As Integer<\/span>, _\r\n        ByVal x<span style=\"color:blue;\"> As Long<\/span>, ByVal y<span style=\"color:blue;\"> As Long<\/span>)\r\n    <span style=\"color:blue;\">Set<\/span> objCurrentNode = ctlTreeView.Object.HitTest(x, y)\r\n    <span style=\"color:blue;\">If <\/span>objCurrentNode Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n        Me.ctlTreeView.Object.SelectedItem = Nothing\r\n    <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Die Prozedur erh&auml;lt mit den Parametern <b>X <\/b>und <b>Y <\/b>die beim Klicken mit der Maus g&uuml;ltigen Koordinaten des Mauszeigers. Diese werten wir mit der Eigenschaft <b>HitTest <\/b>aus.<\/p>\n<p>Wenn der Benutzer ein <b>Node<\/b>-Element angeklickt hat, wird ein Verweis darauf zur&uuml;ckgeliefert. Wenn nicht, ist nicht nur <b>objCurrentNode<\/b> leer, sondern wir wollen dann auch den aktuell markierten Eintrag abw&auml;hlen. Dazu stellen wir die Eigenschaft <b>SelectedItem <\/b>auf <b>Nothing <\/b>ein.<\/p>\n<h2>Aktuell markierte Datei per Doppelklick &ouml;ffnen<\/h2>\n<p>Wenn wir die Funktion <b>OpenFile<\/b> per Doppelklick auf einen der Datei-Eintr&auml;ge im <b>TreeView<\/b>-Steuerelement aufrufen wollen, ben&ouml;tigen wir das Ereignis <b>DblClick<\/b>.  Dieses liefert keinerlei Parameter, die Informationen &uuml;ber das angeklickte <b>Node<\/b>-Element enthalten.<\/p>\n<p>Deshalb haben wir die zuvor erl&auml;uterte Ereignisprozedur angelegt. Klicken wir nun doppelt auf eines der Elemente, erhalten wir den Verweis auf das angeklickte <b>Node<\/b>-Element &uuml;ber die Objektvariable <b>objCurrentNode<\/b>. Wenn der Benutzer einen Doppelklick au&szlig;erhalb der <b>Node<\/b>-Elemente durchgef&uuml;hrt hat, ist <b>objCurrentNode <\/b>leer.<\/p>\n<p>Diese Variable werten wir in der folgenden Ereignisprozedur aus. Nur wenn <b>objCurrentNode <\/b>nicht <b>Nothing <\/b>ist, ermitteln wir den Key aus der <b>Key<\/b>-Eigenschaft und lesen danach mit <b>Left <\/b>das erste Zeichen aus, das entweder <b>f <\/b>(<b>Folder<\/b>) oder <b>i <\/b>(<b>File<\/b>) lautet.<\/p>\n<p>Der Doppelklick soll nur etwas bewirken, wenn wir eine Datei angeklickt haben &#8211; im Falle eines Doppelklicks auf einen Ordner soll nur das Standardverhalten ausgel&ouml;st werden, in diesem Fall das Aufklappen der untergeordneten Elemente.<\/p>\n<p>Wir haben in den Tabellen <b>tblFolders <\/b>und <b>tblFiles <\/b>nur die Namen des jeweiligen Ordners oder der Datei gespeichert, nicht den vollst&auml;ndigen Pfad zum entsprechenden Element.<\/p>\n<p>Deshalb m&uuml;ssen wir, um die doppelt angeklickte Datei zu &ouml;ffnen, erst den Pfad ermitteln. Dazu nutzen wir die Funktion <b>GetFilePath<\/b>, der wir die ID der Datei aus dem Key &uuml;bergeben. Nachdem wir damit den Pfad ermittelt haben, k&ouml;nnen wir die Funktion <b>OpenFile <\/b>aufrufen und mit dieser die Datei mit dem entsprechenden Pfad &ouml;ffnen:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>ctlTreeView_DblClick()\r\n    <span style=\"color:blue;\">Dim <\/span>strPath<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strKey<span style=\"color:blue;\"> As String<\/span>\r\n    \r\n    <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> objCurrentNode Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n        strKey = objCurrentNode.Key\r\n        Select Case <span style=\"color:blue;\">Left<\/span>(strKey, 1)\r\n            <span style=\"color:blue;\">Case <\/span>\"i\"\r\n                strPath = GetFilePath(<span style=\"color:blue;\">Mid<\/span>(strKey, 2))\r\n                <span style=\"color:blue;\">Call<\/span> OpenFile(strPath)\r\n        <span style=\"color:blue;\">End Select<\/span>\r\n    <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Pfad zu einer Datei ermitteln<\/h2>\n<p>Die Funktion <b>GetFilePath <\/b>erwartet die ID der Datei aus der Tabelle <b>tblFiles<\/b> (siehe Listing 1).<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>GetFilePath(ByVal lngFileID<span style=\"color:blue;\"> As Long<\/span>)<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>lngFolderID<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strPath<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strFolder<span style=\"color:blue;\"> As String<\/span>\r\n    lngFolderID = Nz(DLookup(\"ParentID\", \"tblFiles\", \"FileID = \" & lngFileID), 0)\r\n    strPath = Nz(DLookup(\"Filename\", \"tblFiles\", \"FileID = \" & lngFileID), 0)\r\n    <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> lngFolderID = 0\r\n        strFolder = Nz(DLookup(\"Foldername\", \"tblFolders\", \"FolderID = \" & lngFolderID), 0)\r\n        strPath = strFolder & \"\\\" & strPath\r\n        lngFolderID = Nz(DLookup(\"ParentID\", \"tblFolders\", \"FolderID = \" & lngFolderID), 0)\r\n    <span style=\"color:blue;\">Loop<\/span>\r\n    \r\n    strPath = DLookup(\"Basispfad\", \"tblOptionen\") & \"\\\" & strPath\r\n    GetFilePath = strPath\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Die Funktion GetFilePath holt den Pfad zu dem Ordner oder der Datei mit der angegebenen ID.<\/span><\/b><\/p>\n<p>Sie liest zun&auml;chst die ID des &uuml;bergeordneten Ordners aus dem Feld <b>ParentID <\/b>der Tabelle <b>tblFiles <\/b>aus.<\/p>\n<p>Dann tr&auml;gt sie in die Variable <b>strPath <\/b>zun&auml;chst nur den Dateinamen dieser Datei ein.<\/p>\n<p>In der folgenden <b>Do While<\/b>-Schleife, die so lange durchlaufen wird, bis es keinen &uuml;bergeordneten Ordner mehr gibt (<b>lngFolder = 0<\/b>) liest die Prozedur zun&auml;chst den Namen des &uuml;bergeordneten Ordners aus der Tabelle <b>tblFolders <\/b>in die Variable <b>strFolder <\/b>ein.<\/p>\n<p>Dann f&uuml;gt sie diesen Namen, getrennt durch einen Backslash, vorn an den Inhalt der Variablen <b>strPath <\/b>an und speichert das Ergebnis wieder in <b>strPath<\/b>.<\/p>\n<p>Au&szlig;erdem ermittelt sie nun die ID des &uuml;bergeordneten Elements f&uuml;r diesen Ordner aus der Tabelle <b>tblFolders<\/b> und schreibt diese in <b>lngFolderID<\/b>.<\/p>\n<p>Auf diese Weise entsteht ein Pfad wie <b>Dir03\\Dir0303\\Test030303.txt<\/b>. Da wir die Ordner und Dateien immer von dem im Feld <b>Basisordner <\/b>der Tabelle <b>tblOptionen <\/b>aus in den Tabellen <b>tblFolders <\/b>und <b>tblFiles <\/b>speichern, m&uuml;ssen wir nun nur noch den dort gespeicherten Pfad hinzuf&uuml;gen, um den vollst&auml;ndigen Pfad zu erhalten.<\/p>\n<p>Diesen gibt die Funktion als Ergebnis zur&uuml;ck.<\/p>\n<h2>Kontextmen&uuml; im TreeView-Steuerelement anzeigen<\/h2>\n<p>Wenn wir nicht nur Dateien &ouml;ffnen, sondern diese und auch Ordner im Windows Explorer anzeigen wollen, ben&ouml;tigen wir ein Kontextmen&uuml;. Allein mit Klick-Befehlen l&auml;sst sich dies nicht so realisieren, dass es f&uuml;r den Benutzer noch intuitiv ist. Also f&uuml;gen wir ein Kontextmen&uuml; hinzu, das je nach Position des Klicks unterschiedliche Optionen haben soll.<\/p>\n<p>Beim Klick auf einen Ordner sollen folgende Befehle erscheinen. Alle Befehle sollen sp&auml;ter mit dem Pendant f&uuml;r die entsprechende Aktion im &#8222;echten&#8220; Dateisystem ausgestattet werden:<\/p>\n<ul>\n<li><b>Neuer Ordner<\/b>: Legt einen neuen Ordner-Node namens <b>Neuer Ordner <\/b>an und aktiviert direkt das Umbenennen des neuen Ordners.<\/li>\n<li><b>Ordner l&ouml;schen<\/b>: L&ouml;scht den Ordner-Node.<\/li>\n<li><b>Ordner kopieren<\/b>: Kopiert den Ordner-Node.<\/li>\n<li><b>Ordner ausschneiden<\/b>: Kopiert den Ordner-Node und l&ouml;scht diesen, sobald er an anderer Stelle eingef&uuml;gt wurde.<\/li>\n<li><b>Einf&uuml;gen<\/b>: F&uuml;gt einen zuvor kopierten oder ausgeschnittenen Ordner- oder Datei-Node in diesem Ordner ein.<\/li>\n<li><b>Ordner im Windows Explorer &ouml;ffnen<\/b>: &Ouml;ffnet den Ordner im Windows-Explorer.<\/li>\n<li><b>Dateipfad kopieren<\/b>: Kopiert den Dateipfad des Ordners in die Zwischenablage.<\/li>\n<li><b>Ordner umbenennen<\/b>: Versetzt das Element in den Umbenennen-Modus<\/li>\n<\/ul>\n<p>Beim Klick auf eine Datei sind diese Befehle vorgesehen:<\/p>\n<ul>\n<li><b>Datei l&ouml;schen<\/b>: L&ouml;scht den Node.<\/li>\n<li><b>Datei kopieren<\/b>: Kopiert den Node in die Zwischenablage.<\/li>\n<li><b>Datei ausschneiden<\/b>: Kopiert den Node in die Zwischenablage und l&ouml;scht ihn, sobald dieser an anderer Stelle eingef&uuml;gt wurde.<\/li>\n<li><b>Datei im Explorer &ouml;ffnen<\/b>: Zeigt die Datei im Explorer an.<\/li>\n<li><b>Datei in Zielanwendung &ouml;ffnen<\/b>: &Ouml;ffnet die Datei in der f&uuml;r diese festgelegten Standardanwendung.<\/li>\n<\/ul>\n<p>Und beim Klick auf den leeren Raum au&szlig;erhalb der <b>Node<\/b>-Elemente bieten wir diese Befehle an:<\/p>\n<ul>\n<li><b>Neuer Ordner<\/b>: Legt einen neuen Ordner namens <b>Neuer Ordner <\/b>an und aktiviert den Umbenennen-Modus.<\/li>\n<\/ul>\n<h2>Kontextmen&uuml;s anlegen<\/h2>\n<p>Kontextmen&uuml;s legen wir auf dem herk&ouml;mmlichen Wege &uuml;ber die <b>CommandBars<\/b>-Auflistung an. Um diese anzuzeigen, verwenden wir die <b>MouseDown<\/b>-Eigenschaft des <b>TreeView<\/b>-Steuerelements. Dazu erweitern wir die bereits vorhandene Ereignisprozedur wie in Listing 2.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>ctlTreeView_MouseDown(ByVal Button<span style=\"color:blue;\"> As Integer<\/span>, ByVal Shift<span style=\"color:blue;\"> As Integer<\/span>, ByVal x<span style=\"color:blue;\"> As Long<\/span>, ByVal y<span style=\"color:blue;\"> As Long<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>strTyp<span style=\"color:blue;\"> As String<\/span>\r\n    \r\n    <span style=\"color:blue;\">Set<\/span> objCurrentNode = ctlTreeView.Object.HitTest(x, y)\r\n    \r\n    <span style=\"color:blue;\">If <\/span>objCurrentNode Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n        Me.ctlTreeView.Object.SelectedItem = Nothing\r\n    <span style=\"color:blue;\">End If<\/span>\r\n    Select Case Button\r\n        <span style=\"color:blue;\">Case <\/span>acRightButton\r\n            <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> objCurrentNode Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n                strTyp = <span style=\"color:blue;\">Left<\/span>(objCurrentNode.Key, 1)\r\n                Select Case strTyp\r\n                    <span style=\"color:blue;\">Case <\/span>\"f\"\r\n                        <span style=\"color:blue;\">Call<\/span> CreateCommandBarFolder()\r\n                    <span style=\"color:blue;\">Case <\/span>\"i\"\r\n                        <span style=\"color:blue;\">Call<\/span> CreateCommandBarFile()\r\n                <span style=\"color:blue;\">End Select<\/span>\r\n            <span style=\"color:blue;\">Else<\/span>\r\n                <span style=\"color:blue;\">Call<\/span> CreateCommandBarOther\r\n            <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">End Select<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Prozedur zum Aufruf der verschiedenen Kontextmen&uuml;s<\/span><\/b><\/p>\n<p>Das Ergebnis soll beispielsweise f&uuml;r Ordner-Elemente wie in Bild 2 aussehen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_02\/pic_1585_006.png\" alt=\"Anzeigen des Kontextmen&uuml;s f&uuml;r einen Ordner\" width=\"574,6265\" height=\"497,5302\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Anzeigen des Kontextmen&uuml;s f&uuml;r einen Ordner<\/span><\/b><\/p>\n<p>Wir ermitteln hier nach wie vor das aktuell markierte <b>Node<\/b>-Element. Dann pr&uuml;fen wir, ob der Benutzer die rechte Maustaste bet&auml;tigt hat (<b>acRightButton<\/b>). Ist das der Fall, pr&uuml;fen wir, ob aktuell ein <b>Node<\/b>-Element markiert ist.<\/p>\n<p>Falls ja, lesen wir aus der <b>Key<\/b>-Eigenschaft das erste Zeichen aus. Im Falle von <b>f <\/b>(<b>Folder<\/b>) rufen wir die Prozedur <b>CreateCommandBarFolder <\/b>auf. Lautet der Buchstabe <b>i <\/b>(<b>File<\/b>), rufen wir <b>CreateCommandBarFile <\/b>auf. Falls gerade kein <b>Node<\/b>-Element markiert ist, rufen wir die Prozedur <b>CreateCommandBarOther <\/b>auf.<\/p>\n<h2>Kontextmen&uuml; f&uuml;r Ordner anzeigen<\/h2>\n<p>Die Prozedur <b>CreateCommandBarFolder <\/b>soll das Kontextmen&uuml; f&uuml;r einen Ordner anzeigen (siehe Listing 3).<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>CreateCommandBarFolder()\r\n    <span style=\"color:blue;\">Dim <\/span>strKey<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>cbr<span style=\"color:blue;\"> As <\/span>Office.CommandBar\r\n    strKey = objCurrentNode.Key\r\n    On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n    CommandBars(\"Ordner\").Delete\r\n    <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n    <span style=\"color:blue;\">Set<\/span> cbr = CommandBars.Add(\"Ordner\", msoBarPopup, False, <span style=\"color:blue;\">True<\/span>)\r\n    <span style=\"color:blue;\">With<\/span> cbr.Controls.Add(msoControlButton)\r\n        .Caption = \"Ordner kopieren\"\r\n        .OnAction = \"=OrdnerKopieren(''\" & strKey & \"'')\"\r\n        .FaceId = 1667\r\n    End <span style=\"color:blue;\">With<\/span>\r\n    <span style=\"color:blue;\">With<\/span> cbr.Controls.Add(msoControlButton)\r\n        .Caption = \"Ordner ausschneiden\"\r\n        .OnAction = \"=OrdnerAusschneiden(''\" & strKey & \"'')\"\r\n        .FaceId = 1669\r\n    End <span style=\"color:blue;\">With<\/span>\r\n    <span style=\"color:blue;\">With<\/span> cbr.Controls.Add(msoControlButton)\r\n        .Caption = \"Ordner einf&uuml;gen\"\r\n        .OnAction = \"=OrdnerEinfuegen(''\" & strKey & \"'')\"\r\n        .FaceId = 22\r\n    End <span style=\"color:blue;\">With<\/span>\r\n    <span style=\"color:blue;\">With<\/span> cbr.Controls.Add(msoControlButton)\r\n        .Caption = \"Ordner l&ouml;schen\"\r\n        .OnAction = \"=OrdnerLoeschen(''\" & strKey & \"'')\"\r\n        .FaceId = 2500\r\n    End <span style=\"color:blue;\">With<\/span>\r\n    <span style=\"color:blue;\">With<\/span> cbr.Controls.Add(msoControlButton)\r\n        .Caption = \"Neuer Ordner\"\r\n        .OnAction = \"=NeuerOrdner(''\" & strKey & \"'')\"\r\n        .FaceId = 1755 ''4088 ''4274 ''2031 ''\r\n    End <span style=\"color:blue;\">With<\/span>\r\n    <span style=\"color:blue;\">With<\/span> cbr.Controls.Add(msoControlButton)\r\n        .Caption = \"Ordner im Windows Explorer anzeigen\"\r\n        .OnAction = \"=OrdnerExplorer(''\" & strKey & \"'')\"\r\n        .FaceId = 32\r\n    End <span style=\"color:blue;\">With<\/span>\r\n    <span style=\"color:blue;\">With<\/span> cbr.Controls.Add(msoControlButton)\r\n        .Caption = \"Pfad des Ordners kopieren\"\r\n        .OnAction = \"=OrdnerPfadKopieren(''\" & strKey & \"'')\"\r\n        .FaceId = 19\r\n    End <span style=\"color:blue;\">With<\/span>    \r\n    <span style=\"color:blue;\">With<\/span> cbr.Controls.Add(msoControlButton)\r\n        .Caption = \"Ordner umbenennen\"\r\n        .OnAction = \"=OrdnerUmbenennen(''\" & strKey & \"'')\"\r\n        .FaceId = 2512\r\n    End <span style=\"color:blue;\">With<\/span>\r\n    cbr.ShowPopup\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Prozedur zum Anzeigen des Kontextmen&uuml;s f&uuml;r Ordner<\/span><\/b><\/p>\n<p>Sie nimmt den Verweis auf das <b>Node<\/b>-Element entgegen, f&uuml;r welches das Kontextmen&uuml; angezeigt werden soll. Dann liest es die ID des Elements aus, f&uuml;r das es angezeigt werden soll.<\/p>\n<p>Falls das Kontextmen&uuml; bereits vorhanden ist, l&ouml;schen wir es bei deaktivierter Fehlerbehandlung zun&auml;chst mit der <b>Delete<\/b>-Methode.<\/p>\n<p>Danach legen wir ein neues Kontextmen&uuml; namens <b>Ordner <\/b>an und legen den Typ auf <b>msoBarPopup <\/b>fest. Au&szlig;erdem stellen wir den Parameter <b>Temporary <\/b>auf <b>True <\/b>ein, damit es beim Beenden der Access-Session anschlie&szlig;end wieder gel&ouml;scht wird<\/p>\n<p>Anschlie&szlig;end f&uuml;hren wir f&uuml;r die zu erstellenden Kontextmen&uuml;-Eintr&auml;ge jeweils &auml;hnliche Befehle aus. Wir haben uns hier aus Platzgr&uuml;nden entschieden, nicht wie sonst &uuml;blich f&uuml;r jeden Kontextmen&uuml;-Eintrag eine eigene Variable zu deklarieren, die man normalerweise zum anschlie&szlig;enden Zuweisen der Eigenschaften nutzt. Stattdessen nutzen wir die <b>With<\/b>-Anweisung direkt mit dem neu erstellten Element und weisen damit die drei Eigenschaften zu:<\/p>\n<ul>\n<li><b>Caption<\/b>: Erwartet die Beschriftung des Kontextmen&uuml;-Eintrags.<\/li>\n<li><b>OnAction<\/b>: Hier hinterlegen wir die beim Anklicken auszuf&uuml;hrende Funktion, die wir in einem Standardmodul als &ouml;ffentliche Funktion anlegen m&uuml;ssen.<\/li>\n<li><b>FaceID<\/b>: Erwartet einen Zahlenwert f&uuml;r ein eingebautes Men&uuml;symbol.<\/li>\n<\/ul>\n<p>F&uuml;r die Eigenschaft <b>OnAction <\/b>legen wir jeweils eine Zeichenkette fest, die den Funktionsnamen enth&auml;lt sowie den Key des aktuell markierten <b>Node<\/b>-Elements aus der Variablen <b>strKey<\/b>, zum Beispiel:<\/p>\n<pre>.OnAction = \"=OrdnerKopieren(''\" & strKey & \"'')\"<\/pre>\n<p>Schlie&szlig;lich zeigen wir das Kontextmen&uuml; mit der Methode <b>ShowPopup <\/b>an.<\/p>\n<h2>Funktionen f&uuml;r das Ordner-Kontextmen&uuml;<\/h2>\n<p>Das waren die einfachen Aufgaben. Nun folgen die einzelnen Funktionen, die beim Anklicken der Kontextmen&uuml;-Eintr&auml;ge ausgel&ouml;st werden sollen.<\/p>\n<p>Diese legen wir im Standardmodul <b>mdlKontextmenues<\/b> nach dem folgenden Schema an &#8211; hier f&uuml;r das Kopieren eines Ordners:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>OrdnerKopieren(strKey<span style=\"color:blue;\"> As String<\/span>)\r\n    <span style=\"color:blue;\">MsgBox<\/span> \"Ordner kopieren\"\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Wie wir diese Funktionen f&uuml;llen, sehen wir in den folgenden Abschnitten.<\/p>\n<h2>Ordner und Datei ausschneiden, kopieren und einf&uuml;gen<\/h2>\n<p>Was genau soll beim Ausschneiden, Kopieren und Einf&uuml;gen von Ordnern geschehen? Wir wollen zun&auml;chst auf der Ebene des <b>TreeView<\/b>-Steuerelements arbeiten. Das Nachziehen der Vorg&auml;nge im Dateisystem f&uuml;gen wir sp&auml;ter hinzu.<\/p>\n<p>Beim Ausschneiden und Kopieren m&uuml;ssen wir uns eigentlich nur die ID des jeweiligen Elements merken, da die eigentliche Aktion erst durchgef&uuml;hrt wird, wenn wir den Ordner an anderer Stelle einf&uuml;gen.<\/p>\n<p>Wie ben&ouml;tigen also eine &ouml;ffentlich deklarierte Variable, in der wir uns merken, welches Element ausgeschnitten oder kopiert werden soll. Dazu speichern wir am besten einfach den <b>Key <\/b>des Elements in dieser Variablen.<\/p>\n<p>Au&szlig;erdem m&uuml;ssen wir kenntlich machen, ob das Element mit diesem Key ausgeschnitten oder kopiert werden soll. Wir k&ouml;nnen dazu jeweils eine Variable wie <b>strKeyOrdnerAusgeschnitten <\/b>und <b>strKeyOrdnerKopiert <\/b>anlegen.<\/p>\n<p>Dann m&uuml;ssten wir, wenn wir einen Ordner kopieren, den Key in die Variable <b>strKeyOrdnerKopiert<\/b> schreiben und die Variable <b>strKeyOrdnerAusgeschnitten <\/b>leeren und umgekehrt &#8211; wir k&ouml;nnen schlie&szlig;lich nur einen Einf&uuml;gevorgang durchf&uuml;hren, also m&uuml;ssen wir wissen, ob gerade ein Ordner zum Ausschneiden oder Kopieren markiert wurde.<\/p>\n<p>Alternativ k&ouml;nnten wir einfach eine Variable namens <b>strKeyAusgeschnittenOderKopiert<\/b> anlegen und eine weitere <b>Boolean<\/b>-Variable, die angibt, ob ein Ordner ausgeschnitten oder kopiert werden soll. Wir entscheiden uns f&uuml;r die erste Variante:<\/p>\n<pre><span style=\"color:blue;\">Public <\/span>strKeyOrdnerAusgeschnitten<span style=\"color:blue;\"> As String<\/span>\r\n<span style=\"color:blue;\">Public <\/span>strKeyOrdnerKopiert<span style=\"color:blue;\"> As String<\/span><\/pre>\n<p>Folglich hinterlegen wir f&uuml;r die beiden Kontextmen&uuml;-Funktionen die folgenden Anweisungen:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>OrdnerKopieren(strKey<span style=\"color:blue;\"> As String<\/span>)\r\n    strKeyOrdnerKopiert = strKey\r\n    strKeyOrdnerAusgeschnitten = \"\"\r\n<span style=\"color:blue;\">End Function<\/span>\r\n    \r\n<span style=\"color:blue;\">Public Function <\/span>OrdnerAusschneiden(strKey<span style=\"color:blue;\"> As String<\/span>)\r\n    strKeyOrdnerKopiert = \"\"\r\n    strKeyOrdnerAusgeschnitten = strKey\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<h2>Einf&uuml;gen eines ausgeschnittenen Ordners<\/h2>\n<p>Wenn wir mit der n&auml;chsten Funktion den Einf&uuml;gevorgang durchf&uuml;hren wollen, ben&ouml;tigen wir Zugriff auf die <b>TreeView<\/b>-Objektvariable. Diese ziehen wir daher vom Klassenmodul in das Modul <b>mdlGlobal<\/b> und stellen die Sichtbarkeit auf <b>Public <\/b>ein:<\/p>\n<pre><span style=\"color:blue;\">Public <\/span>objTreeview<span style=\"color:blue;\"> As <\/span>MSComctlLib.TreeView<\/pre>\n<p>Wir beginnen mit dem Einf&uuml;gen eines ausgeschnittenen Ordners, weil dies deutlich einfacher ist &#8211; auch wenn man es nicht glauben mag, denn das Ausschneiden besteht schlie&szlig;lich, oberfl&auml;chlich betrachtet, aus zwei Schritten und das Kopieren scheinbar nur aus einem. Tats&auml;chlich besteht das Ausschneiden aber nur im &#8222;Umh&auml;ngen&#8220; des Nodes an einen anderen Parent-Node.<\/p>\n<p>An dieser Stelle k&ouml;nnte man annehmen, dass wir uns das Anzeigen der Elemente im <b>TreeView<\/b>-Steuerelement durch Setzen der Eigenschaft <b>Sorted <\/b>auf den Wert <b>True <\/b>erleichtern k&ouml;nnten.<\/p>\n<p>Das ist jedoch nicht der Fall, denn wir haben noch eine weitere Sortierungsebene: Es sollen zuerst die Verzeichnisse in aufsteigender Reihenfolge angezeigt werden und erst dann die Dateien, ebenfalls aufsteigend sortiert.<\/p>\n<p>Wir m&uuml;ssen uns also selbst um die korrekte Reihenfolge k&uuml;mmern. Beim erstmaligen Anzeigen ist das noch einfach, denn wir f&uuml;gen die Elemente einfach in der entsprechenden Sortierung hinzu.<\/p>\n<p>Beim sp&auml;teren Ausschneiden oder Kopieren und Einf&uuml;gen m&uuml;ssen wir uns allerdings mit einem selbst gebauten Mechanismus behelfen, um neu eingef&uuml;gte Elemente an der richtigen Stelle einzuf&uuml;gen.<\/p>\n<p>Schlie&szlig;lich m&uuml;ssen wir auch noch den Key des neuen &uuml;bergeordneten Elements f&uuml;r den ausgeschnittenen und eingef&uuml;gten Ordner-Datensatz in der Tabelle <b>tblFolder <\/b>definieren.<\/p>\n<p>Die beim Aufrufen des Kontextmen&uuml;-Befehls <b>Einf&uuml;gen<\/b> ausgel&ouml;ste Prozedur finden wir in Listing 4. Sie nimmt den Key des Zielelements als Parameter entgegen und pr&uuml;ft, ob es ein kopiertes Element in <b>strKeyOrdnerAusgeschnitten <\/b>gibt.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>OrdnerEinfuegen(strKeyZiel<span style=\"color:blue;\"> As String<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>objNodeAusgeschnittenOderKopiert<span style=\"color:blue;\"> As <\/span>MSComctlLib.Node\r\n    <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">Len<\/span>(strKeyOrdnerAusgeschnitten) = 0<span style=\"color:blue;\"> Then<\/span>\r\n        <span style=\"color:blue;\">Set<\/span> objNodeAusgeschnittenOderKopiert = objTreeview.Nodes(strKeyOrdnerAusgeschnitten)\r\n        <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> objNodeAusgeschnittenOderKopiert Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n            <span style=\"color:blue;\">If <\/span>FS_OrdnerVerschieben(<span style=\"color:blue;\">Mid<\/span>(strKeyOrdnerAusgeschnitten, 2), <span style=\"color:blue;\">Mid<\/span>(strKeyZiel, 2)) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n                <span style=\"color:blue;\">Call<\/span> ParentInOrdnertabelleAendern(<span style=\"color:blue;\">Mid<\/span>(objNodeAusgeschnittenOderKopiert.Key, 2), <span style=\"color:blue;\">Mid<\/span>(strKeyZiel, 2))\r\n                <span style=\"color:blue;\">Set<\/span> objNodeAusgeschnittenOderKopiert.Parent = objTreeview.Nodes(strKeyZiel)\r\n            <span style=\"color:blue;\">Else<\/span>\r\n                <span style=\"color:blue;\">MsgBox<\/span> \"Ordner konnte im Dateisystem nicht verschoben werden.\", vbOKOnly + <span style=\"color:blue;\">vbCr<\/span>itical, \"Fehler\"\r\n            <span style=\"color:blue;\">End If<\/span>\r\n        <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">Else<\/span>\r\n        ''... Kopierten Ordner einf&uuml;gen\r\n    <span style=\"color:blue;\">End If<\/span>\r\n    objTreeview.Sorted = <span style=\"color:blue;\">True<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Prozedur zum Einf&uuml;gen eines Ordners<\/span><\/b><\/p>\n<p>Ist das der Fall, referenziert sie das entsprechende Element &uuml;ber den Key und pr&uuml;ft abermals, ob dieses Element vorhanden ist. Falls ja, ruft sie die weiter unten beschriebene Funktion <b>FS_OrdnerVerschieben <\/b>auf und &uuml;bergibt dieser die IDs des zu verschiebenden Ordners und des Zielordners. <b>FS_OrdnerVerschieben<\/b> gibt den Wert <b>True<\/b> zur&uuml;ck, wenn das Verschieben im Dateisystem erfolgreich war.<\/p>\n<p>In diesem Fall ruft <b>OrdnerEinfuegen <\/b>die Prozedur <b>ParentInOrdnertabelleAendern <\/b>auf und &uuml;bergibt dieser die ID des ausgeschnittenen Elements und die des neuen Parent-Elements als Parameter.<\/p>\n<p>Au&szlig;erdem stellt sie die Eigenschaft <b>Parent <\/b>des verschobenen Elements auf das neue &uuml;bergeordnete Element ein.<\/p>\n<p>Die Prozedur <b>ParentInOrdnertabelleAendern <\/b>nimmt die ID des zu verschiebenden Elements sowie die ID des neuen Parent-Elements entgegen und &auml;ndert den Datensatz der Tabelle <b>tblFolders <\/b>f&uuml;r den betroffenen Datensatz, indem sie den Wert des Feldes <b>ParentID <\/b>auf die ID des neuen &uuml;bergeordneten Elements einstellt:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>ParentInOrdnertabelleAendern(lngID<span style=\"color:blue;\"> As <\/span>_\r\n        Long, lngParentIDNeu<span style=\"color:blue;\"> As Long<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n    <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n    db.Execute \"UPDATE tblFolders SET ParentID = \" _\r\n        & lngParentIDNeu & \" WHERE FolderID = \" & lngID, _\r\n        dbFailOnError\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Einf&uuml;gen eines kopierten Ordners<\/h2>\n<p>Dahingegen ist das Einf&uuml;gen eines kopierten Ordners komplizierter, denn wir m&uuml;ssen die komplette Struktur unterhalb dieses Ordners neu anlegen.<\/p>\n<p>Und nicht nur das: Mit dem Neuanlegen geht auch das Eintragen neuer Ordner und Dateien in den Tabellen <b>tblFolders <\/b>und <b>tblFiles <\/b>einher sowie das Vergeben neuer Keys f&uuml;r diese Elemente &#8211; wir d&uuml;rfen keinen Key erneut anlegen.<\/p>\n<p>Wenn wir die Elemente jedoch zuerst in der Datenbank neu anlegen, erhalten diese automatisch eine neue ID, aus der sich wiederum ein Key ableiten l&auml;sst.<\/p>\n<p>In der Prozedur <b>OrdnerEinfuegen <\/b>f&uuml;gen wir nun den Code f&uuml;r den <b>Else<\/b>-Zweig hinzu (siehe Listing 5). Hier pr&uuml;fen wir, ob <b>strKeyOrdnerKopiert <\/b>eine ID f&uuml;r den zu kopierenden Ordner enth&auml;lt. Falls ja, referenzieren wir das entsprechende <b>Node<\/b>-Element und pr&uuml;fen, ob dieses tats&auml;chlich vorhanden ist.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>OrdnerEinfuegen(strKeyZiel<span style=\"color:blue;\"> As String<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>objNodeAusgeschnittenOderKopiert<span style=\"color:blue;\"> As <\/span>MSComctlLib.Node\r\n    <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">Len<\/span>(strKeyOrdnerAusgeschnitten) = 0<span style=\"color:blue;\"> Then<\/span>\r\n        ''... Ausgeschnittenen Ordner einf&uuml;gen\r\n    <span style=\"color:blue;\">Else<\/span>\r\n        <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">Len<\/span>(strKeyOrdnerKopiert) = 0<span style=\"color:blue;\"> Then<\/span>\r\n            <span style=\"color:blue;\">Set<\/span> objNodeAusgeschnittenOderKopiert = objTreeview.Nodes(strKeyOrdnerKopiert)\r\n            <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> objNodeAusgeschnittenOderKopiert Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n                <span style=\"color:blue;\">If <\/span>FS_OrdnerKopieren(<span style=\"color:blue;\">Mid<\/span>(strKeyOrdnerKopiert, 2), <span style=\"color:blue;\">Mid<\/span>(strKeyZiel, 2)) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n                    <span style=\"color:blue;\">Call<\/span> OrdnerInTabelleKopieren(<span style=\"color:blue;\">Mid<\/span>(objNodeAusgeschnittenOderKopiert.Key, 2), <span style=\"color:blue;\">Mid<\/span>(strKeyZiel, 2))\r\n                <span style=\"color:blue;\">Else<\/span>\r\n                    <span style=\"color:blue;\">MsgBox<\/span> \"Ordner konnte im Dateisystem nicht kopiert werden.\", vbOKOnly + <span style=\"color:blue;\">vbCr<\/span>itical, \"Fehler\"\r\n                <span style=\"color:blue;\">End If<\/span>\r\n            <span style=\"color:blue;\">End If<\/span>\r\n        <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">End If<\/span>\r\n    objTreeview.Sorted = <span style=\"color:blue;\">True<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: Prozedur zum Einf&uuml;gen eines Ordners, hier f&uuml;r das Kopieren<\/span><\/b><\/p>\n<h2>Kopieren des Ordners selbst<\/h2>\n<p>In diesem Fall rufen wir zuerst die Funktion <b>FS_OrdnerKopieren<\/b> auf, die wir weiter unten beschreiben und die den Ordner im Dateisystem kopiert.<\/p>\n<p>Ist das erfolgreich, ruft die Prozedur <b>OrdnerEinfuegen <\/b>die Prozedur <b>OrdnerInTabelleKopieren <\/b>auf und &uuml;bergibt die ID des zu kopierenden Ordners sowie die ID des neuen Zielordners (siehe Listing 6).<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>OrdnerInTabelleKopieren(lngID<span style=\"color:blue;\"> As Long<\/span>, lngParentIDNeu<span style=\"color:blue;\"> As Long<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n    <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n    <span style=\"color:blue;\">Dim <\/span>lngFolderIDNeu<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strFoldernameNeu<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n    <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM tblFolders WHERE FolderID = \" & lngID, dbOpenSnapshot)\r\n    ''Hauptordner neu einf&uuml;gen\r\n    strFoldernameNeu = rst!Foldername\r\n    db.Execute \"INSERT INTO tblFolders(Foldername, ParentID) VALUES(''\" & strFoldernameNeu & \"'', \" & lngParentIDNeu _\r\n        & \")\", dbFailOnError\r\n    ''ID des neuen Hauptordners ermitteln\r\n    lngFolderIDNeu = db.OpenRecordset(\"SELECT @@IDENTITY\", dbOpenSnapshot).Fields(0)\r\n    AddNodeAlphanumerical \"f\" & lngParentIDNeu, tvwChild, \"f\" & lngFolderIDNeu, strFoldernameNeu, \"folder\"\r\n    ''Unterelemente kopieren\r\n    <span style=\"color:blue;\">Call<\/span> UnterelementeInTabelleKopieren(lngID, lngFolderIDNeu)\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 6: Prozedur zum Einf&uuml;gen eines Ordners in die Tabelle, hier f&uuml;r das Kopieren<\/span><\/b><\/p>\n<p>Die Prozedur erstellt ein Recordset, das nur den zu kopierenden Datensatz der Tabelle <b>tblFolders <\/b>enth&auml;lt. Aus diesem entnehmen wir den Namen des zu kopierenden Ordners und speichern ihn in der Variablen <b>strFoldernameNeu<\/b>.<\/p>\n<p>Damit f&uuml;gen wir per <b>Execute<\/b>-Anweisung und <b>INSERT INTO<\/b>-Befehl einen neuen Datensatz zur Tabelle <b>tblFolders <\/b>hinzu, der den Ordnernamen und als <b>ParentID <\/b>die ID des Zielordners enth&auml;lt. Die ID des neu angelegten Datensatzes ermitteln wir mit <b>SELECT @@IDENTITY<\/b> und speichern sie in <b>lngFolderIDNeu<\/b>.<\/p>\n<p>Dann f&uuml;gen wir den neuen Ordner zum <b>TreeView<\/b>-Steuerelement hinzu. Dazu verwenden wir die <b>Add<\/b>-Methode und &uuml;bergeben dieser den Key des &uuml;bergeordneten Elements sowie die ID und den Namen des neuen Elements sowie als <b>Image <\/b>den Wert <b>folder<\/b>. Schlie&szlig;lich rufen wir die Prozedur <b>UnterelementeInTabelleKopieren <\/b>auf, die sich um das Einf&uuml;gen der &uuml;brigen untergeordneten Ordner und Dateien k&uuml;mmert.<\/p>\n<h2>Kopieren der Unterordner und Dateien<\/h2>\n<p>Die Prozedur <b>UnterelementInTabelleKopieren<\/b> ist rekursiv definiert und nimmt die ID des zu kopierenden Ordners sowie die Parent-ID dieses Ordners entgegen (siehe Listing 7).<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>UnterelementeInTabelleKopieren(ByVal lngFolderID<span style=\"color:blue;\"> As Long<\/span>, ByVal lngParentID<span style=\"color:blue;\"> As Long<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n    <span style=\"color:blue;\">Dim <\/span>rstFolders<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n    <span style=\"color:blue;\">Dim <\/span>rstFiles<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n    <span style=\"color:blue;\">Dim <\/span>lngFolderIDNeu<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strFoldernameNeu<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strFilenameNeu<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>lngFileIDNeu<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n    \r\n    ''Alle Unterordner\r\n    <span style=\"color:blue;\">Set<\/span> rstFolders = db.OpenRecordset(\"SELECT * FROM tblFolders WHERE ParentID = \" & lngFolderID, dbOpenDynaset)\r\n    <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rstFolders.EOF\r\n        strFoldernameNeu = rstFolders!Foldername\r\n        db.Execute \"INSERT INTO tblFolders(Foldername, ParentID) VALUES(''\" & strFoldernameNeu & \"'', \" & lngParentID _\r\n            & \")\", dbFailOnError\r\n        lngFolderIDNeu = db.OpenRecordset(\"SELECT @@IDENTITY\", dbOpenSnapshot).Fields(0)\r\n        AddNodeAlphanumerical \"f\" & lngParentID, tvwChild, \"f\" & lngFolderIDNeu, strFoldernameNeu, \"folder\"\r\n        <span style=\"color:blue;\">Call<\/span> UnterelementeInTabelleKopieren(rstFolders!FolderID, lngFolderIDNeu)\r\n    \r\n        rstFolders.Move<span style=\"color:blue;\">Next<\/span>\r\n    <span style=\"color:blue;\">Loop<\/span>\r\n    \r\n    ''Alle enthaltenen Dateien\r\n    <span style=\"color:blue;\">Set<\/span> rstFiles = db.OpenRecordset(\"SELECT * FROM tblFiles WHERE ParentID = \" & lngFolderID, dbOpenDynaset)\r\n    <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rstFiles.EOF\r\n        strFilenameNeu = rstFiles!Filename\r\n        db.Execute \"INSERT INTO tblFiles(Filename, ParentID) VALUES(''\" & strFilenameNeu & \"'', \" _\r\n            & lngParentID & \")\", dbFailOnError\r\n        lngFileIDNeu = db.OpenRecordset(\"SELECT @@IDENTITY\", dbOpenSnapshot).Fields(0)\r\n        AddNodeAlphanumerical \"f\" & lngParentID, tvwChild, \"i\" & lngFileIDNeu, strFilenameNeu, \"book\"\r\n        rstFiles.Move<span style=\"color:blue;\">Next<\/span>\r\n    <span style=\"color:blue;\">Loop<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 7: Prozedur zum rekursiven Kopieren von Ordnern und Dateien<\/span><\/b><\/p>\n<p>Mit dem Recordset <b>rstFolders <\/b>holt sie alle Eintr&auml;ge der Tabelle <b>tblFolders<\/b>, die dem mit dem Parameter <b>lngFolderID <\/b>angegebenen Ordner untergeordnet sind. <\/p>\n<p>Diese durchl&auml;uft sie in einer <b>Do While<\/b>-Schleife.  Mit der <b>Execute<\/b>-Methode f&uuml;gt sie f&uuml;r jeden dieser Ordner einen neuen Ordner zur Tabelle <b>tblFolders <\/b>hinzu und gibt dabei den Namen des zu kopierenden Ordners aus dem Recordset sowie den &uuml;bergeordneten Ordner aus <b>lngParentID <\/b>an.<\/p>\n<p>Danach ermittelt sie die ID des angelegten Ordners mit der Abfrage <b>SELECT @@IDENTITY <\/b>und speichert das Ergebnis in der Variablen <b>lngFolderIDNeu<\/b>.<\/p>\n<p>Au&szlig;erdem f&uuml;gt sie das neue Element direkt dem <b>TreeView<\/b>-Steuerelement hinzu. Mit der aktuellen <b>FolderID <\/b>aus dem Recordset und der neuen ID aus <b>lngFolderIDNeu <\/b>ruft sie sich selbst erneut auf und f&uuml;hrt die gleiche Aktion f&uuml;r die untergeordneten Ordner aus.<\/p>\n<p>Danach definiert sie ein weiteres Recordset, das alle Eintr&auml;ge der Tabelle <b>tblFiles <\/b>enth&auml;lt, die dem Ordner mit der ID aus <b>lngFolderID <\/b>untergeordnet sind.<\/p>\n<p>Diese durchl&auml;uft sie ebenfalls in einer <b>Do While<\/b>-Schleife und f&uuml;gt der Tabelle <b>tblFiles <\/b>jeweils einen Datensatz hinzu, wobei sie den Namen der Datei aus dem Feld <b>Filename <\/b>und den Wert f&uuml;r das Feld <b>ParentID <\/b>aus der Variablen <b>lngFolderIDNeu<\/b>, also der zuvor angelegten ID des neuen Ordners entnimmt.<\/p>\n<p>Auch hier f&uuml;gt sie gleich das neue Element zum <b>TreeView<\/b>-Steuerelement hinzu. Auf diese Weise kopieren wir alle Ordner und Dateien unterhalb des zu kopierenden Ordners.<\/p>\n<h2>Elemente in richtiger Reihenfolge einf&uuml;gen<\/h2>\n<p>Wir stellen allerdings schnell fest, dass die Elemente trotz gesetzter <b>Sorted<\/b>-Eigenschaft ans Ende der Liste angeh&auml;ngt werden. Also m&uuml;ssen wir das Einf&uuml;gen noch anpassen.<\/p>\n<p>Dazu kommt noch, dass wir gar nicht alle Elemente einfach alphanumerisch sortieren k&ouml;nnen &#8211; dann w&uuml;rden n&auml;mlich Ordner und Dateien munter vermischt werden.<\/p>\n<p>All dies l&ouml;sen wir mit der Funktion <b>AddNodeAlphanumerical<\/b> (siehe Listing 8). Diese erwartet genau die gleichen Parameter wie die <b>Add<\/b>-Methode der <b>Nodes<\/b>-Auflistung, weshalb wir in den oben beschriebenen Funktionen einfach nur <b>objTreeView.Nodes.Add <\/b>durch <b>AddNodeAlphanumerical <\/b>ersetzen m&uuml;ssen. Sie unterscheidet zun&auml;chst danach, ob das neue Element unter einem Parent-Element angelegt werden soll oder nicht.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>AddNodeAlphanumerical(<span style=\"color:blue;\">Optional<\/span> strRelative<span style=\"color:blue;\"> As String<\/span>, <span style=\"color:blue;\">Optional<\/span> intRelationship<span style=\"color:blue;\"> As Integer<\/span>, _\r\n        <span style=\"color:blue;\">Optional<\/span> strKey<span style=\"color:blue;\"> As String<\/span>, <span style=\"color:blue;\">Optional<\/span> strText<span style=\"color:blue;\"> As String<\/span>, <span style=\"color:blue;\">Optional<\/span> strImage<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As <\/span>MSComctlLib.Node\r\n    <span style=\"color:blue;\">Dim <\/span>objParentNode<span style=\"color:blue;\"> As <\/span>MSComctlLib.Node\r\n    <span style=\"color:blue;\">Dim <\/span>objChildNode<span style=\"color:blue;\"> As <\/span>MSComctlLib.Node\r\n    <span style=\"color:blue;\">Dim <\/span>objNeuerNode<span style=\"color:blue;\"> As <\/span>MSComctlLib.Node\r\n    <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">Len<\/span>(strRelative) = 0<span style=\"color:blue;\"> Then<\/span>\r\n        <span style=\"color:blue;\">Set<\/span> objParentNode = objTreeView.Nodes(strRelative)\r\n        <span style=\"color:blue;\">Set<\/span> objChildNode = objParentNode.Child\r\n        <span style=\"color:blue;\">If <\/span>objChildNode Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n            <span style=\"color:blue;\">Set<\/span> objNeuerNode = objTreeView.Nodes.Add(strRelative, intRelationship, strKey, strText, strImage)\r\n            <span style=\"color:blue;\">Exit Function<\/span>\r\n        <span style=\"color:blue;\">End If<\/span>\r\n        <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> objChildNode Is Nothing\r\n            <span style=\"color:blue;\">If <\/span>StrComp(<span style=\"color:blue;\">Left<\/span>(objChildNode.Key, 1) & objChildNode.Text, <span style=\"color:blue;\">Left<\/span>(strKey, 1) & strText, vbTextCompare) &gt; 0<span style=\"color:blue;\"> Then<\/span>\r\n                <span style=\"color:blue;\">Exit Do<\/span>\r\n            <span style=\"color:blue;\">End If<\/span>\r\n            <span style=\"color:blue;\">Set<\/span> objChildNode = objChildNode.<span style=\"color:blue;\">Next<\/span>\r\n        <span style=\"color:blue;\">Loop<\/span>\r\n        <span style=\"color:blue;\">If <\/span>objChildNode Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n            <span style=\"color:blue;\">Set<\/span> objNeuerNode = objTreeView.Nodes.Add(strRelative, intRelationship, strKey, strText, strImage)\r\n        <span style=\"color:blue;\">Else<\/span>\r\n            <span style=\"color:blue;\">Set<\/span> objNeuerNode = objTreeView.Nodes.Add(objChildNode.Key, tvwPrevious, strKey, strText, strImage)\r\n        <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">Else<\/span>\r\n        <span style=\"color:blue;\">Set<\/span> objChildNode = objTreeView.Nodes(1)\r\n        <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> objChildNode Is Nothing\r\n            <span style=\"color:blue;\">If <\/span>StrComp(<span style=\"color:blue;\">Left<\/span>(objChildNode.Key, 1) & objChildNode.Text, <span style=\"color:blue;\">Left<\/span>(strKey, 1) & strText, vbTextCompare) &gt; 0<span style=\"color:blue;\"> Then<\/span>\r\n                <span style=\"color:blue;\">Exit Do<\/span>\r\n            <span style=\"color:blue;\">End If<\/span>\r\n            <span style=\"color:blue;\">Set<\/span> objChildNode = objChildNode.<span style=\"color:blue;\">Next<\/span>\r\n        <span style=\"color:blue;\">Loop<\/span>\r\n        <span style=\"color:blue;\">If <\/span>objChildNode Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n            <span style=\"color:blue;\">Set<\/span> objNeuerNode = objTreeView.Nodes.Add(, , strKey, strText, strImage)\r\n        <span style=\"color:blue;\">Else<\/span>\r\n            <span style=\"color:blue;\">Set<\/span> objNeuerNode = objTreeView.Nodes.Add(objChildNode.Key, tvwPrevious, strKey, strText, strImage)\r\n        <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">Set<\/span> AddNodeAlphanumerical = objNeuerNode\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 8: Prozedur zum Einf&uuml;gen eines neuen Elements in alphanumerischer Reihenfolge<\/span><\/b><\/p>\n<p>Im ersten Fall holt die Prozedur mit <b>objParentNode <\/b>eine Referenz auf das mit <b>strRelative <\/b>&uuml;bergebene Element &#8211; dies ist das &uuml;bergeordnete Objekt, in dem wir das neue <b>Node<\/b>-Element anlegen wollen. Dann liest sie in <b>objChildNode <\/b>das erste untergeordnete Element ein.<\/p>\n<p>Wenn <b>objChildNode <\/b>danach <b>Nothing <\/b>ist, gibt es noch keine Unterelemente und wir k&ouml;nnen das neue Element einfach mit der <b>Add<\/b>-Methode und den &uuml;bergebenen Parametern hinzuf&uuml;gen. Anschlie&szlig;end verlassen wir die Prozedur.<\/p>\n<p>In allen anderen F&auml;llen durchlaufen wir in einer <b>Do While<\/b>-Schleife alle untergeordneten Elemente des mit <b>objParentNode <\/b>gelieferten Elements. <b>objChildNode <\/b>zeigt zurzeit auf das erste Child-Element. Die Schleife l&auml;uft so lange, bis <b>objChildNode <\/b>leer ist.<\/p>\n<p>In einer <b>If&#8230;Then<\/b>-Bedingung pr&uuml;fen wir nun, ob das hinzuzuf&uuml;gende Element alphanumerisch hinter dem Element aus <b>objChildNode <\/b>liegt. Hier ber&uuml;cksichtigen wir auch den Elementtyp. Nur zu Vergleichszwecken stellen wir n&auml;mlich den ersten Vergleichsausdruck aus dem Buchstaben der <b>Key<\/b>-Eigenschaft und dem angezeigten Text zusammen, beim zweiten machen wir es genauso.<\/p>\n<p>Wenn wir zum Beispiel den Ordner <b>Dir1 <\/b>mit der Datei <b>Datei1 <\/b>vergleichen, stellen wir tats&auml;chlich <b>fDir1 <\/b>und <b>iDatei1 <\/b>gegen&uuml;ber.<\/p>\n<p>Da wir <b>f <\/b>f&uuml;r <b>Folders <\/b>und <b>i <\/b>f&uuml;r <b>Files <\/b>verwendet haben, passt es zuf&auml;llig &#8211; sonst h&auml;tten wir noch anderweitig passende Zeichen voranstellen m&uuml;ssen.<\/p>\n<p>Wenn das Ergebnis der Funktion <b>StrComp <\/b>einen Wert gr&ouml;&szlig;er als <b>0 <\/b>liefert, liegt der Text des hinzuzuf&uuml;genden Elements alphanumerisch vor dem Element aus <b>objChildNode <\/b>und wir verlassen die <b>Do While<\/b>-Schleife.<\/p>\n<p>Ist das Ergebnis <b>0<\/b>, durchlaufen wir die Schleife erneut &#8211; dieses Mal f&uuml;r das n&auml;chste <b>Child<\/b>-Element, das wir mit <b>objChildNode.Next <\/b>ermitteln.<\/p>\n<p>Bei den untergeordneten Elementen des <b>TreeView<\/b>-Steuerelements gibt es keine Auflistung, die wir durchlaufen k&ouml;nnten, daher m&uuml;ssen wir immer mit der <b>Next<\/b>-Methode des Elements selbst das n&auml;chste Element referenzieren.<\/p>\n<p>So durchlaufen wir alle Elemente, bis wir ein Element finden, dessen Text hinter dem des einzuf&uuml;genden Elements liegt.<\/p>\n<p>Verlassen wir die Schleife, verweist <b>objChildNode <\/b>auf das Element, das sich alphanumerisch hinter dem einzuf&uuml;genden Element befindet.<\/p>\n<p>Im <b>Else<\/b>-Teil erledigen wir das Gleiche f&uuml;r Elemente, die in der obersten Ebene des <b>TreeView<\/b>-Steuerelements eingef&uuml;gt werden sollen.<\/p>\n<h2>Ordner und Dateien umbenennen<\/h2>\n<p>Die Funktion <b>OrdnerUmbenennen<\/b>, die wir mit dem Kontextmen&uuml;-Befehl <b>Ordner umbenennen <\/b>aufrufen, ist schnell abgehakt.<\/p>\n<p>Sie muss einfach nur die Methode <b>StartLabelEdit <\/b>des <b>TreeView<\/b>-Objekts aufrufen:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>OrdnerUmbenennen()\r\n    objTreeview.StartLabelEdit\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Allerdings folgt hier noch der eigentliche Vorgang zum Umbenennen. Das Umbenennen l&ouml;st das Ereignis <b>AfterLabelEdit<\/b> aus, das wir in Listing 9 implementieren. Die Prozedur referenziert das aktuell markierte <b>Node<\/b>-Element mit <b>objNode<\/b>.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>ctlTreeView_AfterLabelEdit(Cancel<span style=\"color:blue;\"> As Integer<\/span>, NewString<span style=\"color:blue;\"> As String<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n    <span style=\"color:blue;\">Dim <\/span>strType<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>lngID<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>objRename<span style=\"color:blue;\"> As <\/span>MSComctlLib.Node\r\n    <span style=\"color:blue;\">Dim <\/span>objParent<span style=\"color:blue;\"> As <\/span>MSComctlLib.Node\r\n    <span style=\"color:blue;\">Dim <\/span>strKey<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strImage<span style=\"color:blue;\"> As String<\/span>    \r\n    <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n    strType = <span style=\"color:blue;\">Left<\/span>(ctlTreeView.Object.SelectedItem.Key, 1)\r\n    lngID = <span style=\"color:blue;\">Mid<\/span>(ctlTreeView.Object.SelectedItem.Key, 2)    \r\n    Select Case strType\r\n        <span style=\"color:blue;\">Case <\/span>\"f\"\r\n            <span style=\"color:blue;\">If <\/span>FS_OrdnerUmbenennen(lngID, NewString) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n                db.Execute \"UPDATE tblFolders SET Foldername = ''\" & NewString & \"'' WHERE FolderID = \" & lngID, dbFailOnError\r\n                <span style=\"color:blue;\">Set<\/span> objRename = Me.ctlTreeView.Object.SelectedItem\r\n                <span style=\"color:blue;\">Set<\/span> objParent = objRename.Parent\r\n                strKey = objRename.Key\r\n                lngID = <span style=\"color:blue;\">Mid<\/span>(strKey, 2)\r\n                strImage = objRename.Image\r\n                Me.ctlTreeView.Object.Nodes.Remove objRename.Key\r\n                <span style=\"color:blue;\">If <\/span>objParent Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n                    <span style=\"color:blue;\">Set<\/span> objRename = AddNodeAlphanumerical(, , strKey, NewString, strImage)\r\n                <span style=\"color:blue;\">Else<\/span>\r\n                    <span style=\"color:blue;\">Set<\/span> objRename = AddNodeAlphanumerical(objParent.Key, tvwChild, strKey, NewString, strImage)\r\n                <span style=\"color:blue;\">End If<\/span>\r\n                <span style=\"color:blue;\">Call<\/span> BuildTreePartial(lngID)\r\n            <span style=\"color:blue;\">End If<\/span>\r\n        <span style=\"color:blue;\">Case <\/span>\"i\"\r\n            <span style=\"color:blue;\">If <\/span>FS_DateiUmbenennen(lngID, NewString) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n                db.Execute \"UPDATE tblFiles SET Filename = ''\" & NewString & \"'' WHERE FileID = \" & lngID, dbFailOnError\r\n            <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">End Select<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 9: Prozedur zum &Uuml;bertragen einer Umbenennung in die entsprechende Tabelle<\/span><\/b><\/p>\n<p>Au&szlig;erdem referenziert es dessen &uuml;bergeordnetes Element mit <b>objParentNode<\/b>. Dann ermittelt es den Typ (<b>f <\/b>oder <b>i<\/b>) und die ID des Elements.<\/p>\n<p>Dann entfernt die Prozedur das umzubenennende <b>Node<\/b>-Element. Warum das? Weil wir es nach dem Umbenennen wieder alphanumerisch einsortieren m&uuml;ssen, was wir mit der Prozedur <b>AddNodeAlphanumerical <\/b>erledigen, die immer das <b>Node<\/b>-Element neu anlegt.<\/p>\n<p>Anschlie&szlig;end rufen wir die Prozedur <b>BuildTreePartial<\/b> auf und &uuml;bergeben die ID des soeben angepassten <b>Folder<\/b>-Nodes, damit die untergeordneten Elemente aus den Tabellen <b>tblFolders <\/b>und <b>tblFiles <\/b>ausgelesen und wieder hinzugef&uuml;gt werden.<\/p>\n<p>Danach wird im Falle des Typs <b>f<\/b> der entsprechende Datensatz in der Tabelle <b>tblFolders <\/b>angepasst, im Falle von <b>i <\/b>in der Tabelle <b>tblFiles<\/b>. Damit wird der Wert aus dem Parameter <b>NewString <\/b>als neuer Name des Elements in der jeweiligen Tabelle eingetragen.<\/p>\n<p>Schlie&szlig;lich f&uuml;gen wir dann mit <b>AddNodeAlphanumerical <\/b>das Element erneut ein, wobei wir die entsprechenden Parameter &uuml;bergeben. <\/p>\n<h2>L&ouml;schen eines Ordners<\/h2>\n<p>Der Kontextmen&uuml;-Eintrag <b>Ordner l&ouml;schen <\/b>ruft die Funktion <b>OrdnerLoeschen <\/b>auf. Auch beim L&ouml;schen arbeiten wir wieder auf zwei Ebenen: Wir entfernen das Element aus dem <b>TreeView<\/b>-Steuerelement und schlie&szlig;lich auch noch aus der Datenbank. Allerdings ist es damit eventuell nicht getan, denn ein zu l&ouml;schender Ordner kann auch Unterordner und Dateien enthalten, die wir ebenfalls l&ouml;schen m&uuml;ssen. Die Funktion <b>OrdnerLoeschen <\/b>nimmt den Key des zu l&ouml;schenden Elements entgegen und ermittelt daraus die ID des zu l&ouml;schenden Datensatzes.<\/p>\n<p>Dann pr&uuml;ft sie, ob in den <b>tblFolders <\/b>oder <b>tblFiles <\/b>untergeordnete Elemente zu dem zu l&ouml;schenden Ordner vorliegen.<\/p>\n<p>Falls ja, zeigt sie ein Meldungsfenster an und fragt den Benutzer, ob der Ordner samt Unterelementen gel&ouml;scht werden soll. Falls nicht, wird <b>bolNichtLoeschen <\/b>auf <b>True <\/b>eingestellt.<\/p>\n<p>Hat <b>bolNichtLoeschen <\/b>anschlie&szlig;end den Wert <b>False<\/b>, ruft die Funktion die rekursive Prozedur <b>UntergeordneteElementeLoeschen <\/b>auf und &uuml;bergibt dieser die ID des zu l&ouml;schenden Ordners (siehe Listing 10).<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>UntergeordneteElementeLoeschen(lngID<span style=\"color:blue;\"> As Long<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n    <span style=\"color:blue;\">Dim <\/span>rstFolders<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n    <span style=\"color:blue;\">Dim <\/span>rstFiles<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n    <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n    \r\n    <span style=\"color:blue;\">Set<\/span> rstFolders = db.OpenRecordset(\"SELECT * FROM tblFolders WHERE ParentID = \" & lngID, dbOpenDynaset)\r\n    <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rstFolders.EOF\r\n        UntergeordneteElementeLoeschen rstFolders!FolderID\r\n        rstFolders.Delete\r\n        rstFolders.Move<span style=\"color:blue;\">Next<\/span>\r\n    <span style=\"color:blue;\">Loop<\/span>\r\n    \r\n    <span style=\"color:blue;\">Set<\/span> rstFiles = db.OpenRecordset(\"SELECT * FROM tblFiles WHERE ParentID = \" & lngID, dbOpenDynaset)\r\n    <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rstFiles.EOF\r\n        rstFiles.Delete\r\n        rstFiles.Move<span style=\"color:blue;\">Next<\/span>\r\n    <span style=\"color:blue;\">Loop<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 10: Prozedur zum rekursiven L&ouml;schen von Ordnern und Dateien<\/span><\/b><\/p>\n<p>Nachdem diese Funktion alle untergeordneten Elemente gel&ouml;scht hat, entfernt die Funktion <b>OrdnerLoeschen <\/b>schlie&szlig;lich noch das eigentlich zu l&ouml;schende Element per <b>DELETE<\/b>-Abfrage (siehe Listing 11).<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>OrdnerLoeschen(strKey<span style=\"color:blue;\"> As String<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n    <span style=\"color:blue;\">Dim <\/span>lngID<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>bolNichtLoeschen<span style=\"color:blue;\"> As Boolean<\/span>\r\n    <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n    lngID = <span style=\"color:blue;\">Mid<\/span>(strKey, 2)\r\n    \r\n    If DCount(\"FileID\", \"tblFiles\", \"ParentID = \" & lngID) &gt; 0 Or DCount(\"FolderID\", \"tblFolders\", \"ParentID = \" _\r\n            & lngID) &gt; 0 Then\r\n        <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">MsgBox<\/span>(\"Der Ordner ist nicht leer. Dennoch l&ouml;schen?\", vbYesNo + vbExclamation, \"Ordner l&ouml;schen\") = vbNo<span style=\"color:blue;\"> Then<\/span>\r\n            bolNichtLoeschen = <span style=\"color:blue;\">True<\/span>\r\n        <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">If <\/span>bolNichtLoeschen = <span style=\"color:blue;\">False<\/span><span style=\"color:blue;\"> Then<\/span>\r\n        <span style=\"color:blue;\">Call<\/span> UntergeordneteElementeLoeschen(lngID)\r\n        db.Execute \"DELETE FROM tblFolders WHERE FolderID = \" & lngID, dbFailOnError\r\n        objTreeview.Nodes.Remove strKey\r\n    <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 11: Kontextmen&uuml;-Funktion zum L&ouml;schen eines Ordners<\/span><\/b><\/p>\n<p>Die Prozedur <b>UntergeordneteElementeLoeschen <\/b>nimmt die ID des Eintrags der Tabelle <b>tblFolder <\/b>entgegen und erstellt als Erstes ein Recordset auf Basis dieser Tabelle, wobei nur die Datens&auml;tze zur&uuml;ckgegeben werden, deren Feld <b>ParentID <\/b>dem Wert des Parameters <b>lngID<\/b>, also des &uuml;bergeordneten Datensatzes, entspricht.<\/p>\n<p>Beim Durchlaufen dieser Datens&auml;tze ruft die Prozedur sich selbst wieder zuerst auf, damit vor dem L&ouml;schen eines Ordners zuerst die untergeordneten Ordner und Dateien gel&ouml;scht werden k&ouml;nnen.<\/p>\n<p>Nachdem dies f&uuml;r alle untergeordneten Elemente geschehen ist, wird schlie&szlig;lich der aktuelle Datensatz selbst mit der <b>Delete<\/b>-Methode des <b>Recordset<\/b>-Objekts gel&ouml;scht und der Datensatzzeiger zum n&auml;chsten Datensatz bewegt.<\/p>\n<p>Nach dem L&ouml;schen der Ordner-Datens&auml;tze der untersten Ebene in der Tabelle <b>tblFolder <\/b>werden eventuell vorhandene Eintr&auml;ge aus der Tabelle <b>tblFiles <\/b>entfernt, bevor die Funktion wieder zur aufrufenden Funktion zur&uuml;ckkehrt und sich dann um die dar&uuml;ber liegende Ebene k&uuml;mmert. Auf diese Weise entfernen wir alle Unterelemente eines Ordners aus den Tabellen <b>tblFolders <\/b>und <b>tblFiles<\/b>.<\/p>\n<h2>Neuen Ordner anlegen<\/h2>\n<p>W&auml;hlt der Benutzer im Kontextmen&uuml; den Eintrag <b>Neuer <\/b>Ordner aus, soll ein neues Element hinzugef&uuml;gt und direkt in den Umbenennen-Modus versetzt werden &#8211; so, wie man es auch vom Windows Explorer kennt.<\/p>\n<p>Das erledigen wir mit der Funktion <b>NeuerOrdner<\/b> (siehe Listing 12). Diese liest die ID des Ordners, dem ein neuer Unterordner hinzugef&uuml;gt werden soll, in die Variable <b>lngParentID <\/b>ein.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>NeuerOrdner(strKey<span style=\"color:blue;\"> As String<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n    <span style=\"color:blue;\">Dim <\/span>lngParentID<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>lngFolderID<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strNeuerOrdner<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As Integer<\/span>\r\n    \r\n    lngParentID = <span style=\"color:blue;\">Mid<\/span>(strKey, 2)\r\n    <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n    \r\n    strNeuerOrdner = \"Neuer Ordner\"\r\n    For i = 1 To 999\r\n        <span style=\"color:blue;\">If <\/span>FS_OrdnerVorhanden(lngParentID, strNeuerOrdner)<span style=\"color:blue;\"> Then<\/span>\r\n            strNeuerOrdner = \"Neuer Ordner (\" & i & \")\"\r\n        <span style=\"color:blue;\">Else<\/span>\r\n            <span style=\"color:blue;\">Exit For<\/span>\r\n        <span style=\"color:blue;\">End If<\/span>\r\n    <span style=\"color:blue;\">Next<\/span> i\r\n    \r\n    <span style=\"color:blue;\">If <\/span>FS_NeuerOrdner(lngParentID, strNeuerOrdner) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n        db.Execute \"INSERT INTO tblFolders(Foldername, ParentID) VALUES(''\" & strNeuerOrdner & \"'', \" _\r\n            & lngParentID & \")\", dbFailOnError\r\n        lngFolderID = db.OpenRecordset(\"SELECT @@IDENTITY\", dbOpenSnapshot).Fields(0)\r\n        AddNodeAlphanumerical \"f\" & lngParentID, tvwChild, \"f\" & lngFolderID, strNeuerOrdner, \"folder\"\r\n        objTreeview.Nodes(strKey).Expanded = <span style=\"color:blue;\">True<\/span>\r\n        <span style=\"color:blue;\">Set<\/span> objTreeview.SelectedItem = objTreeview.Nodes(\"f\" & lngFolderID)\r\n        objTreeview.StartLabelEdit\r\n    <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 12: Anlegen eines neuen Ordners per Kontextmen&uuml;<\/span><\/b><\/p>\n<p>Au&szlig;erdem ermitteln wir den vorl&auml;ufigen Namen des neuen Ordners, so wie es auch im Windows Explorer funktioniert.<\/p>\n<p>Wir gehen zun&auml;chst vom Namen <b>Neuer Ordner <\/b>aus und pr&uuml;fen, ob bereits ein Ordner mit diesem Namen im Zielverzeichnis vorhanden ist. Das erledigen wir innerhalb einer <b>For&#8230;Next<\/b>-Schleife, die wir so lange durchlaufen, bis wir einen noch nicht vergebenen Ordnernamen finden.<\/p>\n<p>Das untersuchen wir mit der Funktion <b>FS_OrdnerVorhanden<\/b>, der wir die ID des Zielordners und den Namen des neuen Ordners &uuml;bergeben.<\/p>\n<p>Diese Funktion holt mit der Funktion <b>GetFolderPath <\/b>den Pfad zu der &uuml;bergebenen ID.<\/p>\n<p>Danach pr&uuml;ft sie mit der Funktion <b>FolderExists <\/b>der <b>FileSystemObject<\/b>-Klasse, ob der Ordner bereits vorhanden ist.<\/p>\n<p>Ist das der Fall, liefert sie den Wert <b>True <\/b>zur&uuml;ck:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>FS_OrdnerVorhanden(lngZielID<span style=\"color:blue;\"> As Long<\/span>, _\r\n        strOrdner<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Boolean<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>objFSO<span style=\"color:blue;\"> As <\/span>Scripting.FileSystemObject\r\n    <span style=\"color:blue;\">Dim <\/span>strZielpfad<span style=\"color:blue;\"> As String<\/span>\r\n    <span style=\"color:blue;\">Set<\/span> objFSO = <span style=\"color:blue;\">New<\/span> Scripting.FileSystemObject\r\n    strZielpfad = GetFolderPath(lngZielID) & \"\\\" _\r\n        & strOrdner & \"\\\"\r\n    <span style=\"color:blue;\">If <\/span>objFSO.FolderExists(strZielpfad)<span style=\"color:blue;\"> Then<\/span>\r\n        FS_OrdnerVorhanden = <span style=\"color:blue;\">True<\/span>\r\n    <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Andernfalls stellen wir einen neuen Ordnernamen zusammen, der im ersten Schleifendurchlauf beispielsweise <b>Neuer Ordner (1) <\/b>lautet.<\/p>\n<p>Auf diese Weise finden wir den n&auml;chsten freien Ordnernamen. Danach legt die Funktion zun&auml;chst den neuen Datensatz f&uuml;r diesen Ordner in der Tabelle <b>tblFolders <\/b>an.<\/p>\n<p>Anschlie&szlig;end ermittelt sie die ID des neu angelegten Datensatzes und schreibt diese in die Variable <b>lngFolderID<\/b>.<\/p>\n<p>Damit rufen wir nun die bereits weiter oben vorgestellte Prozedur <b>AddNodeAlphanumerical <\/b>auf.<\/p>\n<p>Diese legt das neue <b>Node<\/b>-Element an und positioniert es direkt an der richtigen Stelle. Schlie&szlig;lich erweitert die Prozedur das &uuml;bergeordnete Element, also den Ordner, dem wir den neuen Ordner hinzugef&uuml;gt haben, selektiert das neue Element und startet dann mit <b>StartLabelEdit <\/b>den Umbenennen-Modus.<\/p>\n<p>Wenn der Benutzer die Daten nach seinen W&uuml;nschen umbenannt hat, wird wieder die bereits beschriebene Ereignisprozedur <b>ctlTreeView_AfterLabelEdit <\/b>ausgel&ouml;st, welche die &Auml;nderungen in der Tabelle <b>tblFolders <\/b>speichert. <\/p>\n<h2>Ordner im Explorer anzeigen<\/h2>\n<p>Um einen Ordner per Kontextmen&uuml; im Windows Explorer anzuzeigen, verwenden wir die folgende Funktion:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>OrdnerExplorer(strKey<span style=\"color:blue;\"> As String<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>lngID<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strPath<span style=\"color:blue;\"> As String<\/span>\r\n    lngID = <span style=\"color:blue;\">Mid<\/span>(strKey, 2)\r\n    strPath = GetFolderPath(lngID)\r\n    <span style=\"color:blue;\">Call<\/span> OpenFolderInExplorer(strPath)\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Die Routine nutzt die Funktion <b>GetFolderPath<\/b>, die wir weiter oben bereits beschrieben haben, um den Pfad zu der ID des Ordners zu ermitteln.<\/p>\n<p>Dann verwendet sie die Prozedur <b>OpenFolderInExplorer<\/b>, um den Explorer mit diesem Pfad zu &ouml;ffnen.<\/p>\n<h2>Pfad des Ordners in die Zwischenablage kopieren<\/h2>\n<p>Die Funktion <b>OrdnerPfadKopieren <\/b>ermittelt aus dem Key des zu ermittelnden Pfades die ID des Eintrags in der Tabelle <b>tblFolders<\/b>.<\/p>\n<p>Diese nutzt sie als Parameter der Funktion <b>GetFolderPath<\/b>, um den Pfad zu ermitteln. Diesen speichert sie anschlie&szlig;end in der Zwischenablage:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>OrdnerPfadKopieren(strKey<span style=\"color:blue;\"> As String<\/span>)\r\n    <span style=\"color:blue;\">Dim <\/span>lngID<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>strPath<span style=\"color:blue;\"> As String<\/span>\r\n    lngID = <span style=\"color:blue;\">Mid<\/span>(strKey, 2)\r\n    strPath = GetFolderPath(lngID)\r\n    Inzwischenablage strPath\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<h2>&Uuml;bertragen von &Auml;nderungen in das Dateisystem<\/h2>\n<p>In vielen der bisher vorgestellten Prozeduren haben wir bereits Funktionen verwendet, um die &Auml;nderungen im <b>TreeView<\/b>-Steuerelement auch tats&auml;chlich in das Dateisystem zu &uuml;bertragen.<\/p>\n<p>Die dazu ben&ouml;tigten Funktionen haben wir im Modul <b>mdlDateisystem<\/b> angelegt. Diese werden wir im zweiten Teil dieses Beitrags ausf&uuml;hrlich erl&auml;utern und damit diese L&ouml;sung abrunden.<\/p>\n<p>Es handelt sich um die folgenden Funktionen:<\/p>\n<ul>\n<li><b>FS_OrdnerVorhanden<\/b>: Pr&uuml;ft, ob ein Ordner bereits vorhanden ist.<\/li>\n<li><b>FS_OrdnerKopieren<\/b>: Kopiert einen Ordner in ein anderes Zielverzeichnis.<\/li>\n<li><b>FS_OrdnerVerschieben<\/b>: Verschiebt einen Ordner in ein anderes Zielverzeichnis.<\/li>\n<li><b>FS_OrdnerLoeschen<\/b>: L&ouml;scht einen Ordner.<\/li>\n<li><b>FS_NeuerOrdner<\/b>: Legt einen neuen Ordner an.<\/li>\n<li><b>FS_OrdnerUmbenennen<\/b>: Benennt einen Ordner um.<\/li>\n<li><b>FS_DateiUmbenennen<\/b>: Benennt eine Datei um.<\/li>\n<li><b>FS_DateiLoeschen<\/b>: L&ouml;scht eine Datei.<\/li>\n<li><b>FS_DateiVerschieben<\/b>: Verschiebt eine Datei in einen anderen Ordner.<\/li>\n<li><b>FS_DateiKopieren<\/b>: Kopiert eine Datei in einen anderen Ordner.<\/li>\n<\/ul>\n<p>In der L&ouml;sung befindet sich auch ein Kontextmen&uuml; mit den Befehlen f&uuml;r die Dateien &#8211; L&ouml;schen, Kopieren, Ausschneiden, Umbenennen und &Ouml;ffnen.<\/p>\n<p>Diese beschreiben wir nicht im Detail, da die Funktionen &auml;hnlich denen sind, die wir bereits f&uuml;r die Verzeichnisse beschrieben haben.<\/p>\n<h2>Downloads zu diesem Beitrag<\/h2>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>OrdnerUndDateienInAccessEinlesen.accdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/E0EE482B-9FBB-435A-B933-7CA802F31ABB\/aiu_1585.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Im Artikel  &#8222;Ordner und Dateien in Access-Tabellen einlesen&#8220; (www.access-im-unternehmen.de\/1583) haben wir gezeigt, wie wir schnell Ordner und Dateien in Tabellen speichern, in  &#8222;Dateien schnell im TreeView-Steuerelement anzeigen&#8220; (www.access-im-unternehmen.de\/1584) haben wir Techniken vorgestellt, mit denen wir die Daten dieser Tabellen performant in einem TreeView-Steuerelement pr&auml;sentieren. Im vorliegenden Artikel schauen wir uns nun an, wie man in diesem TreeView-Steuerelement mit den Ordnern und Dateien arbeiten kann: Wie zeigen wir einen Ordner direkt im Windows-Explorer an? Wie &ouml;ffnen wir eine Datei direkt per Doppelklick? Wie k&ouml;nnen wir Kopieren, Ausschneiden und Einf&uuml;gen im TreeView nutzen? Wie benennen wir Ordner und Dateien um? Und schlie&szlig;lich: Wie &uuml;bertragen wir diese &Auml;nderungen direkt auf das Dateisystem?<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[66022026,662026,44000052,44000026],"tags":[],"class_list":["post-55001585","post","type-post","status-publish","format-standard","hentry","category-66022026","category-662026","category-Formulare_und_Steuerelemente","category-Interaktiv"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.4) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Mit Ordnern und Dateien im TreeView arbeiten, Teil 1 - Access im Unternehmen<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/access-im-unternehmen.de\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Mit Ordnern und Dateien im TreeView arbeiten, Teil 1\" \/>\n<meta property=\"og:description\" content=\"Im Artikel &quot;Ordner und Dateien in Access-Tabellen einlesen&quot; (www.access-im-unternehmen.de\/1583) haben wir gezeigt, wie wir schnell Ordner und Dateien in Tabellen speichern, in &quot;Dateien schnell im TreeView-Steuerelement anzeigen&quot; (www.access-im-unternehmen.de\/1584) haben wir Techniken vorgestellt, mit denen wir die Daten dieser Tabellen performant in einem TreeView-Steuerelement pr&auml;sentieren. Im vorliegenden Artikel schauen wir uns nun an, wie man in diesem TreeView-Steuerelement mit den Ordnern und Dateien arbeiten kann: Wie zeigen wir einen Ordner direkt im Windows-Explorer an? Wie &ouml;ffnen wir eine Datei direkt per Doppelklick? Wie k&ouml;nnen wir Kopieren, Ausschneiden und Einf&uuml;gen im TreeView nutzen? Wie benennen wir Ordner und Dateien um? Und schlie&szlig;lich: Wie &uuml;bertragen wir diese &Auml;nderungen direkt auf das Dateisystem?\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2026-03-05T20:24:41+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg01.met.vgwort.de\/na\/7ea7dc3080954ce994e0d50e06c64415\" \/>\n<meta name=\"author\" content=\"Andr\u00e9 Minhorst\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andr\u00e9 Minhorst\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"34\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Mit Ordnern und Dateien im TreeView arbeiten, Teil 1\",\"datePublished\":\"2026-03-05T20:24:41+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\\\/\"},\"wordCount\":5223,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg01.met.vgwort.de\\\/na\\\/7ea7dc3080954ce994e0d50e06c64415\",\"articleSection\":[\"2\\\/2026\",\"2026\",\"Formulare und Steuerelemente\",\"Interaktiv\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\\\/\",\"name\":\"Mit Ordnern und Dateien im TreeView arbeiten, Teil 1 - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg01.met.vgwort.de\\\/na\\\/7ea7dc3080954ce994e0d50e06c64415\",\"datePublished\":\"2026-03-05T20:24:41+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg01.met.vgwort.de\\\/na\\\/7ea7dc3080954ce994e0d50e06c64415\",\"contentUrl\":\"http:\\\/\\\/vg01.met.vgwort.de\\\/na\\\/7ea7dc3080954ce994e0d50e06c64415\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Mit Ordnern und Dateien im TreeView arbeiten, Teil 1\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"name\":\"Access im Unternehmen\",\"description\":\"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access\",\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/access-im-unternehmen.de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\",\"name\":\"Andr\u00e9 Minhorst Verlag\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"contentUrl\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"width\":370,\"height\":111,\"caption\":\"Andr\u00e9 Minhorst Verlag\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\",\"name\":\"Andr\u00e9 Minhorst\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"caption\":\"Andr\u00e9 Minhorst\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Mit Ordnern und Dateien im TreeView arbeiten, Teil 1 - Access im Unternehmen","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/access-im-unternehmen.de\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\/","og_locale":"de_DE","og_type":"article","og_title":"Mit Ordnern und Dateien im TreeView arbeiten, Teil 1","og_description":"Im Artikel \"Ordner und Dateien in Access-Tabellen einlesen\" (www.access-im-unternehmen.de\/1583) haben wir gezeigt, wie wir schnell Ordner und Dateien in Tabellen speichern, in \"Dateien schnell im TreeView-Steuerelement anzeigen\" (www.access-im-unternehmen.de\/1584) haben wir Techniken vorgestellt, mit denen wir die Daten dieser Tabellen performant in einem TreeView-Steuerelement pr&auml;sentieren. Im vorliegenden Artikel schauen wir uns nun an, wie man in diesem TreeView-Steuerelement mit den Ordnern und Dateien arbeiten kann: Wie zeigen wir einen Ordner direkt im Windows-Explorer an? Wie &ouml;ffnen wir eine Datei direkt per Doppelklick? Wie k&ouml;nnen wir Kopieren, Ausschneiden und Einf&uuml;gen im TreeView nutzen? Wie benennen wir Ordner und Dateien um? Und schlie&szlig;lich: Wie &uuml;bertragen wir diese &Auml;nderungen direkt auf das Dateisystem?","og_url":"https:\/\/access-im-unternehmen.de\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\/","og_site_name":"Access im Unternehmen","article_published_time":"2026-03-05T20:24:41+00:00","og_image":[{"url":"http:\/\/vg01.met.vgwort.de\/na\/7ea7dc3080954ce994e0d50e06c64415","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"34\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Mit Ordnern und Dateien im TreeView arbeiten, Teil 1","datePublished":"2026-03-05T20:24:41+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\/"},"wordCount":5223,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\/#primaryimage"},"thumbnailUrl":"http:\/\/vg01.met.vgwort.de\/na\/7ea7dc3080954ce994e0d50e06c64415","articleSection":["2\/2026","2026","Formulare und Steuerelemente","Interaktiv"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\/","url":"https:\/\/access-im-unternehmen.de\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\/","name":"Mit Ordnern und Dateien im TreeView arbeiten, Teil 1 - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\/#primaryimage"},"thumbnailUrl":"http:\/\/vg01.met.vgwort.de\/na\/7ea7dc3080954ce994e0d50e06c64415","datePublished":"2026-03-05T20:24:41+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\/#primaryimage","url":"http:\/\/vg01.met.vgwort.de\/na\/7ea7dc3080954ce994e0d50e06c64415","contentUrl":"http:\/\/vg01.met.vgwort.de\/na\/7ea7dc3080954ce994e0d50e06c64415"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Mit_Ordnern_und_Dateien_im_TreeView_arbeiten_Teil_1\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Mit Ordnern und Dateien im TreeView arbeiten, Teil 1"}]},{"@type":"WebSite","@id":"https:\/\/access-im-unternehmen.de\/#website","url":"https:\/\/access-im-unternehmen.de\/","name":"Access im Unternehmen","description":"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access","publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/access-im-unternehmen.de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/access-im-unternehmen.de\/#organization","name":"Andr\u00e9 Minhorst Verlag","url":"https:\/\/access-im-unternehmen.de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/","url":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","contentUrl":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","width":370,"height":111,"caption":"Andr\u00e9 Minhorst Verlag"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f","name":"Andr\u00e9 Minhorst","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","caption":"Andr\u00e9 Minhorst"}}]}},"_links":{"self":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001585","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/comments?post=55001585"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001585\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55001585"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55001585"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55001585"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}