{"id":55000888,"date":"2013-06-01T00:00:00","date_gmt":"2020-05-22T21:36:06","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=888"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Alle_Datenbanken_einlesen_und_anzeigen","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Alle_Datenbanken_einlesen_und_anzeigen\/","title":{"rendered":"Alle Datenbanken einlesen und anzeigen"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg05.met.vgwort.de\/na\/9ab73511b8574023924e2b529eb5e543\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>F&uuml;r den einen oder anderen Anwendungsfall ben&ouml;tigen Sie einen Datei-&ouml;ffnen-Dialog, um eine Datenbank auszuw&auml;hlen. Dieser Dialog hat den Nachteil, dass er selten direkt die gew&uuml;nschte Datenbank geschweige denn das Verzeichnis anzeigt. Wie w&auml;re es also mit einem speziellen Dialog, der nur die Verzeichnisse einliest, die &uuml;berhaupt Datenbankdateien enthalten, und diese in einem TreeView-Steuerelement zur Auswahl bereith&auml;lt<\/b><\/p>\n<p><b>Ziel <\/b><\/p>\n<p>Das Ziel dieses Beitrags ist es, einen Dialog zu erstellen, der alle Datenbankdateien oder auch nur die in einem bestimmten Unterordner befindlichen anzeigt und zur Auswahl anbietet. Damit sollen die &uuml;blichen Dialoge ersetzt werden, die erstens immer alle Verzeichnisse und Dateien anzeigen und zweitens nie das Verzeichnis liefern, das man gerade ben&ouml;tigt. F&uuml;r die Erstellung eines solchen Dialogs ist eine Menge Vorarbeit n&ouml;tig &#8211; zum Beispiel m&uuml;ssen Sie eine Prozedur programmieren, die alle Verzeichnisse ab dem gew&uuml;nschten Unterordner erfasst und nach Datenbankdateien durchsucht. Diese werden &uuml;ber die Dateiendung erkannt (<b>.mdb<\/b>, <b>.accdb <\/b>&#8230;). Der Dialog soll nur diejenigen Verzeichnisse anzeigen, die direkt oder in einem Unterverzeichnis mindestens eine Datenbankdatei enthalten. Bild 1 zeigt, wie der Dialog ungef&auml;hr aussehen soll. Sie erkennen hier ein Textfeld, in das Sie das beim Einlesen zu verwendende Startverzeichnis eintragen. Dieses l&auml;sst sich mit einem Mausklick auf die Schaltfl&auml;che rechts daneben auch per <b>Verzeichnis ausw&auml;hlen<\/b>-Dialog einlesen. Ein Klick auf die Schaltfl&auml;che <b>Einlesen <\/b>startet den Einlesevorgang, der je nach Umfang der einzulesenden Daten eine Weile dauern kann (auf meiner Festplatte, die zugegebenerma&szlig;en sehr viele Daten enth&auml;lt, etwa acht Minuten &#8211; planen Sie also eine Kaffeepause f&uuml;r diesen Vorgang ein). Wenn Sie einmal ermittelt haben, wo sich die Datenbankdateien befinden, k&ouml;nnen Sie f&uuml;r den n&auml;chsten Einlesevorgang gegebenenfalls einen entsprechenden Unterordner als Startverzeichnis angeben, um Zeit zu sparen. Zu Beginn sollten Sie jedoch einmal die komplette Festplatte einlesen &#8211; ich fand es jedenfalls sehr interessant, an welchen Stellen &uuml;berall Datenbankdateien gespeichert sind.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_03\/DatenbankenAnzeigen-web-images\/pic003.png\" alt=\"pic003.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 1: Dialog zur Anzeige von Datenbankdateien<\/span><\/b><\/p>\n<p>Die erfassten Daten werden in einer Tabelle gespeichert, die wir weiter unten vorstellen. Die Daten sollen dann in einem TreeView-Steuerelement angezeigt werden. Dazu liest die Anwendung die Daten der Tabelle aus und tr&auml;gt sie in das TreeView-Steuerelement ein. Verzeichnisse und Datenbankdateien werden mit entsprechenden Symbolen gekennzeichnet. Vorerst soll das Formular lediglich beim Schlie&szlig;en den Pfad der aktuell ausgew&auml;hlten Datenbankdatei zur&uuml;ckliefern.<\/p>\n<p><b>&Uuml;berlegungen<\/b><\/p>\n<p>Schauen wir uns die Ausgangssituation an. Das Dateisystem enth&auml;lt beliebig tief verschachtelte Verzeichnisstrukturen, von denen nicht alle Access-Dateien speichern. Das zu f&uuml;llende TreeView-Steuerelement soll lediglich die Verzeichnisse anzeigen, in denen sich auch Access-Dateien befinden. Dazu m&uuml;ssen wir alle Verzeichnisse durchlaufen und diejenigen mit Access-Dateien ermitteln. Die Pfade der Verzeichnisse mit Access-Dateien sollen dann vom Laufwerksbuchstaben angefangen &uuml;ber die einzelnen Verzeichnisse im TreeView-Steuerelement abgebildet werden.<\/p>\n<p>Wie erledigen wir dies am einfachsten, wie werden die Daten &uuml;ber die Verzeichnisse und Access-Datenbanken gespeichert, wie f&uuml;llen wir das TreeView-Steuerelement und wie oft soll diese Prozedur wiederholt werden<\/p>\n<p><b>Verzeichnisse und Dateien per FileSystemObject durchlaufen<\/b><\/p>\n<p>Die Werkzeuge zum Einlesen der Verzeichnisse und Dateien liefert das <b>FileSystemObject<\/b>. Es bietet M&ouml;glichkeiten, die Verzeichnisse rekursiv zu durchlaufen und die Dateien auf ihre Dateiendung hin zu untersuchen.<\/p>\n<p><b>Informationen speichern<\/b><\/p>\n<p>Die Tabelle zum Aufnehmen der Informationen muss folgende Felder enthalten und sieht, mit einigen Daten gef&uuml;llt, wie in Bild 2 aus:<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_03\/DatenbankenAnzeigen-web-images\/pic001.png\" alt=\"pic001.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 2: Tabelle zum Speichern der Dateien und Verzeichnisse<\/span><\/b><\/p>\n<ul>\n<li class=\"aufz-hlung\"><b>DateiVerzeichnisID<\/b>: Prim&auml;rschl&uuml;sselfeld der Tabelle, allerdings nicht als Autowert ausgelegt &#8211; mehr dazu sp&auml;ter<\/li>\n<li class=\"aufz-hlung\"><b>DateiVerzeichnisname<\/b>: Name der Datei oder des Verzeichnisses<\/li>\n<li class=\"aufz-hlung\"><b>IstVerzeichnis<\/b>: <b>Ja\/Nein<\/b>-Feld, das angibt, ob es sich bei dem Eintrag um ein Verzeichnis handelt<\/li>\n<li class=\"aufz-hlung\"><b>VerzeichnisID<\/b>: Wert des Feldes <b>DateiVerzeichnisID <\/b>f&uuml;r das &uuml;bergeordnete Verzeichnis<\/li>\n<li class=\"aufz-hlung\"><b>Pfad<\/b>: Speichert den kompletten Pfad des aktuellen Datensatzes.<\/li>\n<li class=\"aufz-hlung\"><b>Expanded<\/b>: F&uuml;r die Darstellung im TreeView f&uuml;gen Sie der Tabelle au&szlig;erdem noch ein Feld zum Speichern des <b>Expanded<\/b>-Zustands hinzu.<\/li>\n<li class=\"aufz-hlung\"><b>Enthaltene Dateien<\/b>: Speichert die Anzahl der im aktuellen Verzeichnis samt Unterverzeichnis enthaltenen Datenbankdateien.<\/li>\n<\/ul>\n<p><b>Dateien einlesen und speichern<\/b><\/p>\n<p>Warum verwenden wir in der Tabelle keinen Autowert f&uuml;r das Prim&auml;rschl&uuml;sselfeld Normalerweise w&uuml;rden wir so vorgehen: Wir lesen das Root-Element ein, also beispielsweise das Verzeichnis <b>c:\\ <\/b>und speichern es in der Tabelle. Dann arbeiten wir uns durch alle untergeordneten Verzeichnisse. Wenn <b>c:\\ <\/b>nun mit dem Wert <b>1 <\/b>im Prim&auml;rschl&uuml;sselfeld gespeichert wurde, w&uuml;rden wir f&uuml;r die untergeordneten Verzeichnisse beziehungsweise Eintr&auml;ge den Wert <b>1 <\/b>im Feld <b>VerzeichnisID <\/b>eintragen. <\/p>\n<p>Dazu m&uuml;ssen wir aber jedes Verzeichnis in der Tabelle anlegen &#8211; auch wenn wir feststellen, dass sich weder in diesem Verzeichnis noch in einem der Unterverzeichnisse eine Access-Datei befindet. Und genau dies wollen wir ja verhindern, um nur die notwendigsten Verzeichnisse und Dateien in der Tabelle zu speichern.<\/p>\n<p>Zur Veranschaulichung liefert Bild 3 einige Verzeichnisse und Dateien. Die Beschriftungen rechts neben den Elementen enthalten die Werte f&uuml;r das Prim&auml;rschl&uuml;sselfeld <b>DateiVerzeichnisID <\/b>(in der Abbildung <b>id<\/b>) und f&uuml;r das Fremdschl&uuml;sselfeld <b>VerzeichnisID <\/b>(in der Abbildung <b>fid<\/b>).<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_03\/DatenbankenAnzeigen-web-images\/pic002.png\" alt=\"pic002.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 3: Indizierung der Verzeichnisse und Dateien<\/span><\/b><\/p>\n<p>Das Speichern des ersten Elements <b>c:\\ <\/b>ist kein Problem &#8211; dieses soll auf jeden Fall gespeichert werden. Es erh&auml;lt als Prim&auml;rschl&uuml;sselwert etwa den Wert <b>1<\/b>. Das Fremdschl&uuml;sselfeld bleibt leer, weil es ja keine &uuml;bergeordneten Verzeichnisse gibt.<\/p>\n<p>Das Unterverzeichnis <b>Verzeichnis 1 <\/b>w&uuml;rde mit dem Prim&auml;rschl&uuml;sselwert <b>2 <\/b>gespeichert. Das Feld <b>VerzeichnisID <\/b>erh&auml;lt den Prim&auml;rschl&uuml;sselwert des &uuml;bergeordneten Verzeichnisses, also <b>1<\/b>. Das Unterverzeichnis <b>Verzeichnis 1-1 <\/b>erh&auml;lt den Prim&auml;rschl&uuml;sselwert <b>3 <\/b>und wird &uuml;ber den Wert <b>2 <\/b>f&uuml;r das Feld <b>VerzeichnisID <\/b>dem Verzeichnis mit dem Prim&auml;rschl&uuml;sselwert <b>2 <\/b>untergeordnet.<\/p>\n<p>Nun folgt die erste Datei, die nach dem g&auml;ngigen Schema den Wert <b>4 <\/b>im Feld <b>DateiVerzeichnisID <\/b>und den Wert <b>3 <\/b>im Fremdschl&uuml;sselfeld <b>VerzeichnisID <\/b>erh&auml;lt.<\/p>\n<p>Wenn alle Verzeichnisse am Ende mindestens eine Datenbankdatei im letzten Verzeichnis enthielten, k&ouml;nnte man die Dateien auf diese Weise anlegen und durchlaufen. Es m&uuml;ssen jeweils die &uuml;bergeordneten Verzeichnisse zuerst angelegt werden, damit den darunter befindlichen Elementen die Prim&auml;rschl&uuml;sselwerte als Fremdschl&uuml;sselwert zugeordnet werden k&ouml;nnen.<\/p>\n<p>Nun gibt es aber Verzeichnisse wie <b>Verzeichnis1-2<\/b>, das leer ist oder nur Dateien enth&auml;lt, die nicht in die Tabelle aufgenommen werden sollen. Wir w&uuml;rden es mit den Werten <b>5 <\/b>im Feld <b>DateiVerzeichnisID <\/b>und <b>2 <\/b>im Feld <b>VerzeichnisID <\/b>speichern. Erst danach w&uuml;rden wir die in diesem Verzeichnis enthaltenen Elemente durchlaufen und schlie&szlig;lich feststellen, dass dort keine Datenbankdatei zu finden ist.<\/p>\n<p>In diesem Fall gibt es kein weiteres untergeordnetes Verzeichnis, sodass die Untersuchung schnell abgeschlossen ist. Was aber nun mit dem Datensatz f&uuml;r das Verzeichnis mit dem Namen <b>Verzeichnis 1-2<\/b> Der Datensatz kann wieder gel&ouml;scht werden, da er ja nicht mehr ben&ouml;tigt wird. Dummerweise gibt es gelegentlich sehr tiefe Verzeichnisstrukturen, in denen sich keine Datenbankdateien finden lassen. Dort w&uuml;rde man erst einige Datens&auml;tze f&uuml;r die Verzeichnisstruktur anlegen und m&uuml;sste diese anschlie&szlig;end wieder l&ouml;schen.<\/p>\n<p>Dies ist der Grund, warum wir keinen Autowert als Prim&auml;rschl&uuml;sselwert verwenden: Damit die Datens&auml;tze f&uuml;r Verzeichnisse ohne untergeordnete Datenbanken gar nicht erst angelegt werden, soll die entsprechende Funktion sich erst rekursiv bis zum Ende der Verzeichnisstruktur bewegen und pr&uuml;fen, ob dort Datenbankdateien vorliegen. Ist dies der Fall, legt die Funktion zun&auml;chst das Element f&uuml;r die Datenbankdatei an und dann die dar&uuml;ber liegenden Verzeichnisse. Sprich: Im Falle von <b>Datei 1 <\/b>w&uuml;rde erst ein Datensatz f&uuml;r die Datei, dann jeweils einer f&uuml;r <b>Verzeichnis 1-1 <\/b>und f&uuml;r <b>Verzeichnis 1 <\/b>angelegt werden.<\/p>\n<p>Dummerweise wissen wir beim Anlegen der untergeordneten Elemente noch nicht, welchen Prim&auml;rschl&uuml;sselwert dessen Verzeichnis in der Tabelle aufweist. Wir m&uuml;ssen beim Navigieren in Richtung untergeordneter Verzeichnisse einen Prim&auml;rschl&uuml;sselwert vorhalten und diesen dann von unten nach oben als Fremdschl&uuml;sselwert des jeweils untergeordneten Elements einf&uuml;gen.<\/p>\n<p>Wenn dabei wie im Fall von <b>Verzeichnis 1-2 <\/b>zun&auml;chst ein Prim&auml;rschl&uuml;sselwert wie etwa <b>5 <\/b>festgelegt wird, sich aber herausstellt, dass dieses Verzeichnis keine Access-Datenbanken enth&auml;lt und somit nicht gespeichert werden soll, kann der Prim&auml;rschl&uuml;sselwert <b>5 <\/b>f&uuml;r das nachfolgend untersuchte Verzeichnis reserviert werden.<\/p>\n<p><b>Rekursive Einlesefunktion<\/b><\/p>\n<p>Wie l&auml;sst sich dies per VBA umsetzen Ganz einfach &#8211; mit einer rekursiv definierten Funktion. Diese besteht im vorliegenden Fall aus einer initialisierenden Funktion, die einen oder mehrere Datens&auml;tze f&uuml;r das angegebene Root-Verzeichnis schreibt und dann die eigentliche rekursive Funktion aufruft.<\/p>\n<p>Schauen wir uns zun&auml;chst die Parameter der Startprozedur <b>DateienEinlesen <\/b>an (s. <span class=\"verweis-ohneumbruch\"><a href=\"#anker-59-anchor\">Listing 1<\/a><\/span>):<\/p>\n<p class=\"listingueberschrift\">Listing 1: Prozedur zum Initiieren des rekursiven Dateieinlese-Vorgangs<\/p>\n<pre>Public Sub DateienEinlesen(Optional strPfad As String, Optional intTiefeMax As Integer)\r\n    Dim objFSO As Scripting.FileSystemObject\r\n    Dim db As DAO.Database\r\n    Dim strVerzeichnisse() As String\r\n    Dim i As Long\r\n    Set objFSO = New Scripting.FileSystemObject\r\n    Set db = CurrentDb\r\n    If Len(strPfad) = 0 Then\r\n         strPfad = &quot;c:\\&quot;\r\n    End If\r\n    strPfad = objFSO.GetFolder(strPfad)\r\n    If Right(strPfad, 1) = &quot;\\&quot; Then\r\n         strPfad = Left(strPfad, Len(strPfad) - 1)\r\n    End If\r\n    db.Execute &quot;SELECT * INTO tblDateienVerzeichnisse_&quot; &amp; Format(Now, &quot;yyyymmdd_hhnnss&quot;) _\r\n        &amp; &quot; FROM tblDateienVerzeichnisse&quot;, dbFailOnError\r\n    db.Execute &quot;DELETE FROM tblDateienVerzeichnisse&quot;, dbFailOnError\r\n    If objFSO.FolderExists(strPfad) Then\r\n         strVerzeichnisse = Split(strPfad, &quot;\\&quot;)\r\n        For i = LBound(strVerzeichnisse) To UBound(strVerzeichnisse)\r\n            If i = 0 Then\r\n                db.Execute &quot;INSERT INTO tblDateienVerzeichnisse(DateiVerzeichnisID,\r\n                DateiVerzeichnisName, IstVerzeichnis) VALUES(&quot; &amp; i + 1 &amp; &quot;, ''&quot; _\r\n                    &amp; strVerzeichnisse(i) &amp; &quot;'', -1)&quot;, dbFailOnError\r\n            Else\r\n                db.Execute &quot;INSERT INTO tblDateienVerzeichnisse(DateiVerzeichnisID,\r\n                DateiVerzeichnisName, IstVerzeichnis, VerzeichnisID) VALUES(&quot; &amp; i + 1 &amp; &quot;, ''&quot; _\r\n                    &amp; strVerzeichnisse(i) &amp; &quot;'', -1, &quot; &amp; i &amp; &quot;)&quot;, dbFailOnError\r\n            End If\r\n        Next i\r\n    End If\r\n    lngAktuellID = i + 1\r\n    DateienEinlesenRek db, objFSO, objFSO.GetFolder(strPfad &amp; &quot;\\&quot;), i, 0, intTiefeMax, 0\r\nEnd Sub<\/pre>\n<ul>\n<li class=\"aufz-hlung\"><b>strPfad<\/b>: Enth&auml;lt die Angabe des Startverzeichnisses f&uuml;r den Einlesevorgang. Wenn Sie den Parameter weglassen, liest die Prozedur das komplette Verzeichnis <b>c:\\ <\/b>ein.<\/li>\n<li class=\"aufz-hlung\"><b>intTiefeMax<\/b>: Dies ist eher ein Parameter, der f&uuml;r Entwicklungstests verwendet wurde. Damit k&ouml;nnen Sie angeben, wie tief die Funktion nach Access-Dateien suchen soll. Wenn Sie den Parameter weglassen, durchsucht die Funktion alle Verzeichnisebenen.<\/li>\n<\/ul>\n<p>Die Prozedur deklariert zun&auml;chst ein Objekt auf Basis von <b>Scripting.FileSystemObject<\/b>. Dieses liefert die Methoden und Eigenschaften, um auf das Dateisystem zuzugreifen. Au&szlig;erdem ben&ouml;tigen wir eine <b>Database<\/b>-Variable, um per <b>Execute<\/b>-Methode SQL-Aktionsabfragen ausf&uuml;hren zu k&ouml;nnen.<\/p>\n<p>Die Prozedur pr&uuml;ft zun&auml;chst, ob der Parameter <b>strPfad <\/b>&uuml;bergeben wurde und ersetzt diesen gegebenenfalls durch das Verzeichnis <b>c:\\<\/b>. Der folgende Aufruf der <b>GetFolder<\/b>-Funktion des <b>FileSystemObjects <\/b>entledigt den Inhalt von <b>strPfad <\/b>eventuell anh&auml;ngender Backslash-Zeichen, aus <b>c:\\Daten\\ <\/b>wird also <b>c:\\Daten<\/b>.<\/p>\n<p>Die folgende Anweisung kopiert den kompletten Inhalt der Tabelle <b>tblDateienVerzeichnisse <\/b>in eine neue Tabelle, die den gleichen Namen erh&auml;lt, jedoch um Datum und Uhrzeit erg&auml;nzt. Dieses Feature war w&auml;hrend der Entwicklung hilfreich, um umfangreiche erfolgreiche Einlesevorg&auml;nge zu sichern, bevor der Code weiter verfeinert wurde.<\/p>\n<p>Danach leert die Tabelle <b>tblDateienVerzeichnisse<\/b>, da diese ja nun neu gef&uuml;llt werden soll. Ist das in <b>strPfad <\/b>angegebene Verzeichnis vorhanden, beginnt die eigentliche Bearbeitung.<\/p>\n<p>Wenn der Benutzer einen Pfad angibt, der aus mehr als nur dem Laufwerksbuchstaben besteht, soll die Prozedur n&auml;mlich f&uuml;r jedes enthaltene Verzeichnis gleich einen Eintrag zur Tabelle <b>tblDateienVerzeichnisse <\/b>hinzuf&uuml;gen &#8211; und zwar verschachtelt. Dazu &uuml;bertr&auml;gt die Prozedur zun&auml;chst mit der <b>Split<\/b>-Funktion alle Verzeichnisse des Pfades in ein Array namens <b>strVerzeichnisse()<\/b>.<\/p>\n<p>Die folgende <b>For&#8230;Next<\/b>-Schleife durchl&auml;uft dazu alle Elemente dieses Arrays und legt jeweils einen neuen Eintrag in der Tabelle <b>tblDateienVerzeichnisse <\/b>an. Dabei gibt es wiederum zwei M&ouml;glichkeiten: Hat die Laufvariable <b>i <\/b>den Wert <b>0<\/b>, wird das erste Element mit einer SQL-Anweisung wie folgt in die Tabelle <b>tblDateienVerzeichnisse <\/b>eingetragen:<\/p>\n<pre>INSERT INTO tblDateienVerzeichnisse(DateiVerzeichnisID, DateiVerzeichnisName, IstVerzeichnis) VALUES(1, ''C:'', -1)<\/pre>\n<p>Das hei&szlig;t, dass das Feld <b>VerzeichnisID <\/b>zum Eintragen der Referenz auf das &uuml;bergeordnete Verzeichnis leer bleibt. F&uuml;r die &uuml;brigen Eintr&auml;ge gibt die Prozedur jeweils das &uuml;bergeordnete Verzeichnis als weiteren Parameter der <b>INSERT INTO<\/b>-Anweisung an:<\/p>\n<pre>INSERT INTO tblDateienVerzeichnisse(DateiVerzeichnisID, DateiVerzeichnisName, IstVerzeichnis, VerzeichnisID) VALUES(2, ''Daten'', -1, 1)<\/pre>\n<p>In diesem Fall referenziert das hier angelegte zweite Element mit dem Prim&auml;rschl&uuml;sselwert <b>2 <\/b>das erste Element mit dem Prim&auml;rschl&uuml;sselwert <b>1 <\/b>&uuml;ber das Feld <b>VerzeichnisID <\/b>mit dem Wert <b>1<\/b>. Wenn Sie mit dem Parameter <b>strPfad<\/b> also beispielsweise den Pfad <b>c:\\Daten\\Fachartikel\\AccessImUnternehmen\\2013\\03\\<\/b> &uuml;bergeben, sieht der Inhalt der Tabelle <b>tblDateienVerzeichnisse <\/b>nach dem Durchlaufen der <b>For&#8230;Next<\/b>-Schleife wie in Bild 4 aus. <\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_03\/DatenbankenAnzeigen-web-images\/pic004.png\" alt=\"pic004.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 4: Datens&auml;tze f&uuml;r den als Parameter &uuml;bergebenen Pfad<\/span><\/b><\/p>\n<p>Damit ist der erste Teil erledigt &#8211; alle Verzeichnisse des &uuml;bergebenen Pfades wurden in der Tabelle angelegt. <\/p>\n<p>Nun geht es mit der eigentlichen rekursiven Funktion weiter, die alle unterhalb dieses Pfades befindlichen Verzeichnisse und Dateien untersucht. Vorher stellt die Prozedur jedoch noch die wie folgt global deklarierte Variable <b>lngAktuellID<\/b> auf den Wert der Laufvariablen <b>i <\/b>ein:<\/p>\n<pre>Dim lngAktuellID As Long<\/pre>\n<p><b>lngAktuellID <\/b>speichert den jeweils zu verwendenden Prim&auml;rschl&uuml;sselwert beim Anlegen eines neuen Datensatzes.<\/p>\n<p><b>Rekursive Funktion<\/b><\/p>\n<p>Die rekursiv definierte Funktion <b>DateienEinlesenRek <\/b>erwartet die folgenden Parameter:<\/p>\n<ul>\n<li class=\"aufz-hlung\"><b>db<\/b>: Verweis auf das <b>Database<\/b>-Objekt f&uuml;r die aktuelle Datenbank<\/li>\n<li class=\"aufz-hlung\"><b>objFSO<\/b>: Verweis auf das <b>FileSystemObject<\/b><\/li>\n<li class=\"aufz-hlung\"><b>objVerzeichnis<\/b>: Verzeichnisse, deren enthaltene Unterverzeichnisse und Dateien in diesem Aufruf untersucht werden sollen<\/li>\n<li class=\"aufz-hlung\"><b>lngVerzeichnisID<\/b>: Wert des Feldes <b>DateiVerzeichnisID <\/b>des &uuml;bergeordneten Verzeichnisses in der Tabelle <b>tblDateienVerzeichnisse<\/b><\/li>\n<li class=\"aufz-hlung\"><b>intTiefe<\/b>: Aktuelle Verzeichnistiefe<\/li>\n<li class=\"aufz-hlung\"><b>intTiefeMax<\/b>: Maximal zu untersuchende Verzeichnistiefe<\/li>\n<li class=\"aufz-hlung\"><b>lngAnzahl<\/b>: R&uuml;ckgabeparameter mit der Anzahl der im zu untersuchenden Unterverzeichnis enthaltenen Datenbankdateien<\/li>\n<\/ul>\n<p>Die Funktion <b>DateienEinlesenRek <\/b>stellt zun&auml;chst die als Parameter &uuml;bergebene Variable <b>lngAnzahl <\/b>auf den Wert <b>0 <\/b>ein (s. <span class=\"verweis-ohneumbruch\"><a href=\"#anker-74-anchor\">Listing 2<\/a><\/span>). Diese Variable soll, sofern das aktuelle Verzeichnis Datenbankdateien enth&auml;lt, entsprechend angepasst werden. Au&szlig;erdem werden noch die in den unterhalb des aktuellen Verzeichnisses befindlichen Datenbankdateien hinzugez&auml;hlt.<\/p>\n<p class=\"listingueberschrift\">Listing 2: Rekursiver Teil der Routinen zum Einlesen der Verzeichnisstruktur und der enthaltenen Dateien<\/p>\n<pre>Public Function DateienEinlesenRek(db As DAO.Database, objFSO As Scripting.FileSystemObject, _\r\n    objVerzeichnis As Scripting.Folder, lngVerzeichnisID As Long, intTiefe As Integer, _\r\n    intTiefeMax As Integer, lngAnzahl As Long) As Boolean\r\n    Dim objUnterverzeichnis As Scripting.Folder\r\n    Dim objDatei As Scripting.File\r\n    Dim lngDateiVerzeichnisID As Long\r\n    Dim bolDiesesVerzeichnisSpeichern As Boolean\r\n    Dim bolVaterverzeichnisSpeichern As Boolean\r\n    Dim lngAnzahlRek As Long\r\n    lngAnzahl = 0\r\n    If (intTiefeMax &gt; 0) And (intTiefe &gt; intTiefeMax) Then\r\n        Exit Function\r\n    End If\r\n    On Error Resume Next\r\n    For Each objDatei In objVerzeichnis.Files\r\n        Select Case objFSO.GetExtensionName(objDatei.Name)\r\n            Case &quot;mdb&quot;, &quot;accdb&quot;, &quot;mda&quot;, &quot;accda&quot;, &quot;mde&quot;, &quot;accde&quot;\r\n                lngAnzahl = lngAnzahl + 1\r\n                db.Execute &quot;INSERT INTO tblDateienVerzeichnisse(DateiVerzeichnisID, &quot; _\r\n                    &amp; &quot;DateiVerzeichnisName, IstVerzeichnis, VerzeichnisID, Pfad) VALUES(&quot; _\r\n                    &amp; lngAktuellID &amp; &quot;, ''&quot; &amp; objDatei.Name &amp; &quot;'', 0, &quot; &amp; lngVerzeichnisID &amp; &quot;, ''&quot; _\r\n                    &amp; objDatei.Path &amp; &quot;'')&quot;, dbFailOnError\r\n                lngAktuellID = lngAktuellID + 1\r\n                DateienEinlesenRek = True\r\n        End Select\r\n    Next objDatei\r\n    bolVaterverzeichnisSpeichern = False\r\n    For Each objUnterverzeichnis In objVerzeichnis.SubFolders\r\n        lngDateiVerzeichnisID = lngAktuellID\r\n        lngAktuellID = lngAktuellID + 1\r\n        bolDiesesVerzeichnisSpeichern = DateienEinlesenRek(db, objFSO, objUnterverzeichnis, _\r\n        lngDateiVerzeichnisID, intTiefe + 1, intTiefeMax, lngAnzahlRek)\r\n        lngAnzahl = lngAnzahl + lngAnzahlRek\r\n        bolVaterverzeichnisSpeichern = bolVaterverzeichnisSpeichern Or bolDiesesVerzeichnisSpeichern\r\n        If bolDiesesVerzeichnisSpeichern = True Then\r\n            db.Execute &quot;INSERT INTO tblDateienVerzeichnisse(DateiVerzeichnisID, &quot; _\r\n                &amp; &quot;DateiVerzeichnisName, IstVerzeichnis, VerzeichnisID, EnthalteneDateien) VALUES(&quot; _\r\n                &amp; lngDateiVerzeichnisID &amp; &quot;, ''&quot; &amp; objUnterverzeichnis.Name &amp; &quot;'', -1, &quot; _\r\n                &amp; lngVerzeichnisID &amp; &quot;, &quot; &amp; lngAnzahlRek &amp; &quot;)&quot;, dbFailOnError\r\n        End If\r\n    Next objUnterverzeichnis\r\n    DateienEinlesenRek = DateienEinlesenRek Or bolVaterverzeichnisSpeichern\r\nEnd Function<\/pre>\n<p><!--30percent--><\/p>\n<p>Dann pr&uuml;ft sie, ob der Benutzer &uuml;berhaupt einen Wert f&uuml;r den Parameter <b>intTiefeMax <\/b>angegeben hat und somit eine maximal zu durchsuchende Verzeichnistiefe. Falls ja, vergleicht sie diesen Wert mit der in <b>intTiefe <\/b>gespeicherten aktuellen Verzeichnistiefe.<\/p>\n<p>Sollte die maximale Tiefe erreicht worden sein, bricht die Funktion sich selbst ab. Danach untersucht die Funktion zun&auml;chst alle Dateien des aktuellen Verzeichnisses, und zwar in einer <b>For Each<\/b>-Schleife &uuml;ber alle Objekte der <b>Files<\/b>-Auflistung des mit <b>objVerzeichnis <\/b>referenzierten aktuellen Verzeichnisses.<\/p>\n<p>Die folgende <b>Select Case<\/b>-Bedingung pr&uuml;ft den Wert der mit der Funktion <b>GetExtensionName <\/b>ermittelten Dateiendung. Hat diese den Wert <b>mdb<\/b>, <b>accdb<\/b>, <b>mda<\/b>, <b>accda<\/b>, <b>mde <\/b>oder <b>accde<\/b>, handelt es sich um eine Datenbankdatei.<\/p>\n<p>Sie k&ouml;nnen an dieser Stelle weitere Dateiendungen hinzuf&uuml;gen oder diese komplett &auml;ndern, um beispielsweise alle Word-Dokumente eines Verzeichnisses zu ermitteln. Wurde eine der angegebenen Dateiendungen gefunden, erh&ouml;ht die Funktion den Wert von <b>lngAnzahl <\/b>um eins. Dann tr&auml;gt sie die gefundene Datenbankdatei in die Tabelle <b>tblDateienVerzeichnisse <\/b>ein, und zwar beispielsweise mit folgender SQL-Anweisung:<\/p>\n<pre>INSERT INTO tblDateienVerzeichnisse(DateiVerzeichnisID, DateiVerzeichnisName, IstVerzeichnis, VerzeichnisID, Pfad)\r\nVALUES(12, ''ABCAnalyse.mdb'', 0, 11, ''C:\\Daten\\...\\ABCAnalyse.mdb'')<\/pre>\n<p>Danach erh&ouml;ht die Funktion den Wert von <b>lngAktuellID <\/b>um eins. Diese Variable hat eine wichtige Aufgabe: Sie liefert den Wert f&uuml;r den jeweils neu anzulegenden Datensatz in der Tabelle <b>tblDateienVerzeichnisse <\/b>&#8211; sowohl beim Anlegen von Dateien als auch bei Verzeichnissen. Weiter oben haben wir ja bereits darauf hingewiesen, dass die Tabelle <b>tblDateienVerzeichnisse <\/b>keinen Autowert f&uuml;r das Prim&auml;rschl&uuml;sselfeld verwendet, daher muss dieser Wert von der Funktion <b>DateienEinlesenRek <\/b>gepflegt werden.<\/p>\n<p>Um <b>lngAktuellID <\/b>nicht immer als Parameter von Aufruf zu Aufruf weiterreichen zu m&uuml;ssen, haben wir diese Variable extern als modulweit g&uuml;ltige Variable deklariert. Sie l&auml;uft also quasi neben den Funktionsaufrufen her und wird darin jeweils erh&ouml;ht, um immer einen eindeutigen Prim&auml;rschl&uuml;sselwert bereitzustellen.<\/p>\n<p>Wenn die Funktion in diesem Durchlauf mindestens eine Datenbankdatei gefunden hat, stellt sie den Wert des R&uuml;ckgabewertes <b>DateienEinlesenRek <\/b>auf <b>True <\/b>ein. Dieser Wert bleibt auch erhalten, bis alle Dateien und Unterverzeichnisse des aktuellen Verzeichnisses durchlaufen wurden, und wird h&ouml;chstens mehrfalls auf <b>True <\/b>eingestellt.<\/p>\n<p>Nachdem alle eventuell vorhandenen Dateien durchlaufen und auf Datenbankdatei-Endungen gepr&uuml;ft wurden, durchl&auml;uft die Funktion die enthaltenen Unterverzeichnisse &#8211; ebenfalls in einer <b>For Each<\/b>-Schleife. Zuvor stellt die Prozedur noch eine Variable namens <b>bolVaterverzeichnisSpeichern <\/b>auf <b>False <\/b>ein &#8211; dazu sp&auml;ter mehr.<\/p>\n<p>F&uuml;r jedes gefundene Verzeichnis speichert die Funktion zun&auml;chst den aktuellen Wert von <b>lngAktuellID<\/b>, unserer Prim&auml;rschl&uuml;sselwert-Quelle, in der Variablen <b>lngDateiVerzeichnisID <\/b>und erh&ouml;ht <b>lngAktuellID <\/b>wiederum um eins.<\/p>\n<p>Bevor das aktuell durchlaufene Verzeichnis gespeichert wird, ruft sich die Funktion zun&auml;chst erneut selbst auf, um die in diesem Verzeichnis enthaltenen Unterverzeichnisse zu untersuchen. Warum das Nun: Wenn Sie das Verzeichnis vorher schon speichern, ohne dass dieses eine Datenbankdatei enth&auml;lt und ohne die Unterverzeichnisse zu durchsuchen, kann es sein, dass dieses Verzeichnis sp&auml;ter wieder gel&ouml;scht werden muss. In unserer Variante des Speicherns der Verzeichnisstruktur durchlaufen wir zun&auml;chst alle Unterverzeichnisebenen und speichern Verzeichnisse erst, wenn mindestens eine Datenbankdatei in einem der Unterverzeichnisse enthalten ist.<\/p>\n<p>Das ist ja der Trick: Die L&ouml;sung soll nur solche Verzeichnisse liefern, die auch Datenbankdateien enthalten. Alles andere w&uuml;rde nur die &Uuml;bersicht verschlechtern.<\/p>\n<p>Zur&uuml;ck zur Funktion: Diese ruft sich wie erw&auml;hnt erneut selbst auf, und zwar so lange, bis keine weiteren Unterverzeichnisse mehr gefunden werden oder bis die maximal zu durchsuchende Verzeichnistiefe erreicht ist. Wenn die Funktion irgendwann w&auml;hrend dieses Vorgangs eine Datenbankdatei gefunden hat, liefert sie als Funktionswert den Wert <b>True <\/b>zur&uuml;ck &#8211; dies geschieht ja bereits weiter oben beim Durchlaufen der im aktuellen Verzeichnis enthaltenen Dateien.<\/p>\n<p>Aber nicht nur das: Beim Aufruf der Funktion <b>DateienEinlesenRek <\/b>liefert der R&uuml;ckgabeparameter <b>lngAnzahlRek <\/b>den in diesem Aufruf ermittelten Wert der Variablen <b>lngAnzahl<\/b>, also die Anzahl der im Verzeichnis gefundenen Datenbankdateien. Dieser durch die Funktion gef&uuml;llte Wert wird zum aktuellen Wert der Variablen <b>lngAnzahl <\/b>hinzuaddiert. Auf diese Weise wird die Anzahl der Datenbankdateien von den untersten Verzeichnisebenen nach oben hin aufkumuliert, sodass f&uuml;r jedes Verzeichnis die insgesamt in allen Unterverzeichnissen enthaltene Anzahl Datenbankdateien gespeichert werden kann.<\/p>\n<p>Eine weitere Variable namens <b>bolVaterverzeichnisSpeichern <\/b>legt fest, ob das &uuml;bergeordnete Verzeichnis entweder wegen einer in diesem Verzeichnis liegenden Datenbankdatei oder wegen einer in den darunter liegenden Verzeichnissen enthaltenen Datenbankdatei gespeichert werden soll. <b>bolVaterverzeichnisSpeichern <\/b>wird beim ersten Auftauchen eines Verzeichnisses mit Datenbankdatei auf <b>True <\/b>eingestellt und Ebene f&uuml;r Ebene in der Hierarchie der Funktionsaufrufe nach oben durchgereicht.<\/p>\n<p>Hat <b>bolDiesesVerzeichnisSpeichern <\/b>den Wert <b>True<\/b>, legt die Prozedur in der Tabelle <b>tblDateienVerzeichnisse <\/b>einen Datensatz f&uuml;r das aktuelle Verzeichnis an.<\/p>\n<p>Das bedeutet, dass bei Durchlaufen eines Pfades wie <b>c:\\Verzeichnis1\\Verzeichnis2\\Verzeichnis3 <\/b>und dem Auffinden einer Datenbankdatei in Verzeichnis 3 die rekursive Funktion zun&auml;chst in das Verzeichnis <b>c:\\Verzeichnis1\\Verzeichnis2\\Verzeichnis3 <\/b>abtaucht und dieses speichert und erst dann <b>c:\\Verzeichnis1\\Verzeichnis2 <\/b>und <b>c:\\Verzeichnis1<\/b>.<\/p>\n<p>Schlie&szlig;lich gibt die Prozedur als Funktionswert den Wert <b>True <\/b>zur&uuml;ck, wenn in diesem oder einen weiteren rekursiven Aufruf mindestens eine Datenbankdatei gefunden werden konnte.<\/p>\n<p>Nach dem Aufruf und dem Abarbeiten der rekursiven Funktion ist die Tabelle <b>tblDateienVerzeichnisse <\/b>mit den gew&uuml;nschten Daten gef&uuml;llt und kann f&uuml;r die Anzeige im TreeView-Steuerelement weiterverwendet werden.<\/p>\n<p><b>Formular erstellen<\/b><\/p>\n<p>Nach den etwas umfangreicheren Vorbereitungen erstellen wir nun das Formular zur Anzeige und Auswahl von Datenbankdateien. Das Formular soll <b>frmDateienVerzeichnisse <\/b>hei&szlig;en. Im Kopf des Formulars legen wir ein Textfeld namens <b>txtStartverzeichnis <\/b>zur Eingabe\/Auswahl des Startverzeichnisses beim Einlesen der Verzeichnisse an. Rechts daneben platzieren wir eine Schaltfl&auml;che, die einen Verzeichnisauswahl-Dialog einblendet und die getroffene Auswahl in das Textfeld <b>txtStartverzeichnis <\/b>&uuml;bertr&auml;gt.<\/p>\n<p>Diese Schaltfl&auml;che verwendet die folgende Prozedur, um eine im Modul <b>mdlTools<\/b> befindliche Funktion zum Ermitteln eines Verzeichnisses aufzurufen:<\/p>\n<pre>Private Sub cmdVerzeichnisWaehlen_Click()\r\n    Me!txtStartverzeichnis = OpenPathName(CurrentProject.Path, &quot;Startverzeichnis ausw&auml;hlen&quot;)\r\nEnd Sub<\/pre>\n<p>Darunter platzieren wir zwei Schaltfl&auml;chen namens <b>cmdEinlesen <\/b>und <b>cmdBaumFuellen<\/b>. Die Schaltfl&auml;che <b>cmdEinlesen <\/b>startet die Prozedur <b>DateienEinlesen <\/b>mit dem im Textfeld angegebenen Verzeichnis:<\/p>\n<pre>Private Sub cmdEinlesen_Click()\r\n    DateienEinlesen Nz(Me!txtStartverzeichnis)\r\nEnd Sub<\/pre>\n<p>Die Schaltfl&auml;che <b>cmdBaumFuellen <\/b>ruft die noch zu erstellende Prozedur <b>BaumFuellen <\/b>auf:<\/p>\n<pre>Private Sub cmdBaumFuellen_Click()\r\n    BaumFuellen\r\nEnd Sub<\/pre>\n<p>Da das Formular nicht an eine Datenherkunft gebunden ist, k&ouml;nnen Sie Eigenschaften wie <b>Navigationsschaltfl&auml;chen<\/b>, <b>Datensatzmarkierer <\/b>und <b>Bildlaufleisten <\/b>auf <b>Nein <\/b>einstellen.<\/p>\n<p><b>Dateien im TreeView-Steuerelement<\/b><\/p>\n<p>Nun soll das TreeView-Steuerelement mit den Daten der Tabelle <b>tblDateienVerzeichnisse <\/b>gef&uuml;llt werden. Das TreeView-Steuerelement soll ein paar aussagekr&auml;ftige Icons anzeigen, es soll sich merken, welche Eintr&auml;ge beim vorherigen Bearbeiten ein- und welche ausgeklappt waren, und es soll folgende Kontextmen&uuml;eintr&auml;ge f&uuml;r die Datenbankeintr&auml;ge bereitstellen (s. Bild 6):<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_03\/DatenbankenAnzeigen-web-images\/pic006.png\" alt=\"pic006.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 5: Diese Abfrage liefert das Root-Element f&uuml;r das TreeView-Steuerelement<\/span><\/b><\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_03\/DatenbankenAnzeigen-web-images\/pic005.png\" alt=\"pic005.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 6: Kontextmen&uuml; eines Datenbankeintrags<\/span><\/b><\/p>\n<ul>\n<li class=\"aufz-hlung\"><b>Zu Verzeichnis wechseln<\/b>: &Ouml;ffnet das Verzeichnis, in dem sich die Datenbank befindet.<\/li>\n<li class=\"aufz-hlung\"><b>Datenbank &ouml;ffnen<\/b>: &Ouml;ffnet Access mit der angegebenen Datenbank.<\/li>\n<li class=\"aufz-hlung\"><b>L&ouml;schen<\/b>: L&ouml;scht die Datenbank nach vorheriger R&uuml;ckfrage.<\/li>\n<\/ul>\n<p>Au&szlig;erdem soll das Textfeld <b>txtDatei <\/b>im unteren Bereich nach einem Klick auf einen der TreeView-Eintr&auml;ge mit dem Namen der jeweiligen Datenbankdatei gef&uuml;llt werden.<\/p>\n<p>Klickt der Benutzer auf ein Verzeichnis, soll das Textfeld geleert werden.<\/p>\n<p>Dies sind bereits einige Anforderungen an ein TreeView-Steuerelement. Grund genug, den TreeViewHandler, den wir zuletzt im Beitrag <b>TreeView-Konfigurator erweitert <\/b>(<b>www.access-im-unternehmen.de\/771<\/b>) vorgestellt haben, einzusetzen.<\/p>\n<p>Mit diesem l&auml;sst sich das TreeView leicht konfigurieren und f&uuml;llen. Au&szlig;erdem bringt der TreeViewHandler einige Funktionen wie das Speichern der <b>Expanded<\/b>-Eigenschaft mit, die Sie sonst selbst programmieren m&uuml;ssten.<\/p>\n<p><b>TreeViewHandler konfigurieren<\/b><\/p>\n<p>Alle f&uuml;r den TreeViewHandler ben&ouml;tigten Komponenten sind bereits in der Beispieldatenbank <b>AlleDatenbankenEinlesen.mdb <\/b>enthalten. Um das Steuerelement zu konfigurieren, &ouml;ffnen Sie das Formular <b>frmTreeViewConf <\/b>der Beispieldatenbank.<\/p>\n<p>Die erste Ebene soll allein den Root-Eintrag der Tabelle <b>tblDateienVerzeichnisse <\/b>anzeigen, also denjenigen, dessen Feld <b>VerzeichnisID <\/b>den Wert <b>Null <\/b>enth&auml;lt. Speziell f&uuml;r diesen Zweck haben wir eine Abfrage namens <b>qryDateienVerzeichnisseRoot<\/b> angelegt (s. Bild 5), das nur den besagten Root-Eintrag liefert.<\/p>\n<p>Im TreeView-Konfigurator legen Sie nun einen neuen Eintrag an und stellen die Eigenschaften wie in Bild 7 ein:<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_03\/DatenbankenAnzeigen-web-images\/pic007.png\" alt=\"pic007.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 7: Eigenschaften f&uuml;r das Root-Element im TreeView-Konfigurator<\/span><\/b><\/p>\n<ul>\n<li class=\"aufz-hlung\"><b>Tabelle\/Abfrage<\/b>: <b>qryDateienVerzeichnisseRoot<\/b><\/li>\n<li class=\"aufz-hlung\"><b>Prim&auml;rschl&uuml;ssel<\/b>: <b>DateiVerzeichnisID<\/b><\/li>\n<li class=\"aufz-hlung\"><b>Schl&uuml;ssel<\/b>: <b>v0<\/b><\/li>\n<li class=\"aufz-hlung\"><b>Elementtext\/Feld<\/b>: <b>DateiVerzeichnisname<\/b><\/li>\n<li class=\"aufz-hlung\"><b>Icon\/Standardwert<\/b>: <b>folder.png<\/b><\/li>\n<li class=\"aufz-hlung\"><b>Expanded-Wert<\/b>: <b>Expanded<\/b><\/li>\n<li class=\"aufz-hlung\"><b>Aktiv<\/b>: <b>Wahr<\/b><\/li>\n<\/ul>\n<p>Zur Eigenschaft <b>Icon <\/b>ist anzumerken, dass wir die verwendeten Bilddateien zun&auml;chst mit dem Tool aus dem Artikel <b>Bilder per Add-In in OLE-Feld speichern <\/b>(<b>www.access-im-unternehmen.de\/890<\/b>) in der Tabelle <b>tblImages <\/b>gespeichert haben. Der TreeView-Konfigurator verwendet eine solche Tabelle, um die Bilddateien f&uuml;r die TreeView- und Kontextmen&uuml;-Icons zu beziehen.<\/p>\n<p>Wir wollen diesen einen Eintrag zun&auml;chst im TreeView-Steuerelement erscheinen lassen. Dazu f&uuml;gen Sie dem Formular <b>frmDateienVerzeichnisse <\/b>ein <b>ImageList<\/b>-Steuerelement namens <b>ctlImageList <\/b>und ein <b>TreeView<\/b>-Steuerelement namens <b>ctlTreeView <\/b>hinzu.<\/p>\n<p>Dazu legen Sie zun&auml;chst eine Objektvariable f&uuml;r die TreeViewHandler-Klasse im Kopf des Klassenmoduls <b>Form_frmDateienVerzeichnisse <\/b>an:<\/p>\n<pre>Dim WithEvents objTreeViewHandler As clsTreeViewHandler<\/pre>\n<p>F&uuml;gen Sie dann eine Ereignisprozedur hinzu, die durch das Ereignis <b>Beim Laden <\/b>des Formulars ausgel&ouml;st wird. Diese enth&auml;lt aktuell nur eine einzige Anweisung:<\/p>\n<pre>Private Sub Form_Load()\r\n    BaumFuellen\r\nEnd Sub<\/pre>\n<p>Die hier aufgerufene Prozedur <b>BaumFuellen <\/b>sieht wie folgt aus:<\/p>\n<pre>Private Sub BaumFuellen()\r\n    Set objTreeViewHandler = New clsTreeViewHandler\r\n    With objTreeViewHandler\r\n        Set .TreeViewInst = Me!ctlTreeview.Object\r\n        Set .ImageListInst = Me!ctlImageList.Object\r\n        .InitTreeView (7)\r\n        .Style = tvwTreelinesPlusMinusPictureText\r\n        .LineStyle = tvwRootLines\r\n        .Indentation = 5\r\n        .FontName = &quot;Calibri&quot;\r\n        .FontSize = 10\r\n        .LabelEdit = tvwManual\r\n        .FillTree\r\n    End With\r\nEnd Sub<\/pre>\n<p>Die Prozedur instanziert ein neues Objekt auf Basis der Klasse <b>clsTreeViewHandler <\/b>und stellt dessen Eigenschaften ein. Unter anderem weist sie ihr zun&auml;chst Objektverweise auf das zu verwendende <b>ImageList<\/b>&#8211; und das <b>TreeView<\/b>-Steuerelement zu.<\/p>\n<p>Dann stellt sie mit der <b>InitTreeView<\/b>-Methode die ID der zu verwendenden <b>TreeView<\/b>-Konfiguration aus dem Formular <b>frmTreeViewConf <\/b>ein &#8211; in diesem Fall lautet diese <b>7 <\/b>(sieht <b>frmTreeViewConf<\/b>, oben links unter <b>Aktuelle ID<\/b>).<\/p>\n<p>Danach legt die Prozedur einige optische Eigenschaften fest und f&uuml;llt das <b>TreeView<\/b>-Steuerelement schlie&szlig;lich mit der <b>FillTree<\/b>-Methode. Im ersten Versuch sieht dies wie in Bild 8 aus.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_03\/DatenbankenAnzeigen-web-images\/pic008.png\" alt=\"pic008.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 8: Das TreeView-Steuerelement zeigt zun&auml;chst nur das Root-Element an.<\/span><\/b><\/p>\n<p class=\"zwischen-berschrift-oberer-spaltenrand\">Weitere Verzeichnisse anzeigen<\/p>\n<p>Nun folgt ein weiterer Eintrag im TreeView-Konfigurator, der f&uuml;r die erste Ebene unter dem Root-Element verantwortlich ist.<\/p>\n<p>Auch f&uuml;r diesen legen wir wieder eine spezielle Datenherkunft an &#8211; sie sieht wie in Bild 9 aus und hei&szlig;t <b>qryVerzeichnisseBaum<\/b>. Das zweite Feld dieser Abfrage mit dem Namen <b>DateiVerzeichnis <\/b>enth&auml;lt den folgenden Ausdruck:<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_03\/DatenbankenAnzeigen-web-images\/pic009.png\" alt=\"pic009.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 9: Datenherkunft f&uuml;r die zweite und die folgenden Ebenen im TreeView-Steuerelement<\/span><\/b><\/p>\n<pre>DateiVerzeichnis: [DateiVerzeichnisname] &amp; Wenn([EnthalteneDateien];&quot; (&quot; &amp; [EnthalteneDateien] &amp; &quot;)&quot;;&quot;&quot;)<\/pre>\n<p>Dieser erg&auml;nzt den Verzeichnisnamen gegebenenfalls um die in Klammern eingefasste Anzahl der in diesem Verzeichnis enthaltenen Datenbankdateien.<\/p>\n<p>F&uuml;r das Feld <b>IstVerzeichnis <\/b>haben wir als Kriterium <b>Wahr <\/b>eingestellt und f&uuml;r das Fremdschl&uuml;sselfeld <b>VerzeichnisID <\/b>das Kriterium <b>Ist Nicht Null<\/b>. Auf diese Weise werden nur Verzeichnisse erfasst, und nur solche, die Unterverzeichnis eines anderen Verzeichnisses sind.<\/p>\n<p>Im TreeView-Konfigurator stellen Sie die folgenden Eigenschaften f&uuml;r den neuen Eintrag f&uuml;r diese Ebene ein:<\/p>\n<ul>\n<li class=\"aufz-hlung\"><b>Tabelle\/Abfrage<\/b>: <b>qryVerzeichnisseBaum<\/b><\/li>\n<li class=\"aufz-hlung\"><b>&Uuml;bergeordnete Tabelle<\/b>: <b>qryDateienVerzeichnisseRoot<\/b><\/li>\n<li class=\"aufz-hlung\"><b>Prim&auml;rschl&uuml;ssel<\/b>: <b>DateiVerzeichnisID<\/b><\/li>\n<li class=\"aufz-hlung\"><b>Fremdschl&uuml;ssel<\/b>: <b>VerzeichnisID<\/b><\/li>\n<li class=\"aufz-hlung\"><b>Schl&uuml;ssel<\/b>: <b>vv<\/b><\/li>\n<\/ul>\n<p>Die &uuml;brigen Eigenschaften entsprechen denen des &uuml;bergeordneten Elements.<\/p>\n<p>Durch diesen Eintrag werden in der zweiten Ebene des TreeViews alle Eintr&auml;ge der Abfrage <b>qryVerzeichnisseBaum <\/b>eingef&uuml;gt, deren Fremdschl&uuml;sselfeld <b>VerzeichnisID <\/b>dem Prim&auml;rschl&uuml;sselfeld des Elements der ersten Ebene entspricht.<\/p>\n<p><b>Weitere Verzeichnisebenen<\/b><\/p>\n<p>Nun wollen wir nicht jede Ebene einzeln anlegen (das w&auml;re auch kompliziert, da wir nicht wissen, wie viele Ebenen es gibt).<\/p>\n<p>Aber wir wissen ja, dass die Tabelle <b>tblDateienVerzeichnisse <\/b>mit sich selbst verkn&uuml;pfte Elemente enth&auml;lt.<\/p>\n<p>Und da der TreeView-Konfigurator auch reflexive Daten unterst&uuml;tzt, legen wir dort als weitere Ebene eine solche an. Die Eigenschaften sehen so aus:<\/p>\n<ul>\n<li class=\"aufz-hlung\"><b>Tabelle\/Abfrage<\/b>: <b>qryVerzeichnisseBaum<\/b><\/li>\n<li class=\"aufz-hlung\"><b>&Uuml;bergeordnete Tabelle<\/b>: <b>qryVerzeichnisBaum<\/b><\/li>\n<li class=\"aufz-hlung\"><b>Prim&auml;rschl&uuml;ssel<\/b>: <b>DateiVerzeichnisID<\/b><\/li>\n<li class=\"aufz-hlung\"><b>Fremdschl&uuml;ssel<\/b>: <b>VerzeichnisID<\/b><\/li>\n<li class=\"aufz-hlung\"><b>Schl&uuml;ssel<\/b>: <b>vr<\/b><\/li>\n<\/ul>\n<p>Die Elemente f&uuml;r diesen Eintrag referenzieren also Elemente der gleichen Tabelle, deren Prim&auml;rschl&uuml;sselfeld den Wert des Fremdschl&uuml;sselfelds des aktuellen Datensatzes aufweist. Auf diese Weise werden die folgenden Verzeichnisebenen rekursiv angelegt. Das Zwischenergebnis sieht wie in Bild 10 aus.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_03\/DatenbankenAnzeigen-web-images\/pic011.png\" alt=\"pic011.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 11: Datenherkunft f&uuml;r die Datei-Ebene im TreeView-Steuerelement<\/span><\/b><\/p>\n<p><b>Dateien im TreeView<\/b><\/p>\n<p>Nun fehlen nur noch die Dateien der jeweiligen Verzeichnisse. Dazu legen Sie eine vierte und letzte Ebene im TreeView-Konfigurator an. Auch diese basiert wieder auf einer eigens zu diesem Zweck erzeugten Abfrage. Sie hei&szlig;t <b>qryDateienBaum<\/b> und sieht wie in Bild 11 aus. Die Besonderheit dieser Abfrage liegt darin, dass sie ausschlie&szlig;lich solche Datens&auml;tze liefert, deren Feld <b>IstVerzeichnis <\/b>den Wert <b>Falsch <\/b>enth&auml;lt.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_03\/DatenbankenAnzeigen-web-images\/pic010.png\" alt=\"pic010.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 10: Rekursiv angelegte Verzeichnisstruktur<\/span><\/b><\/p>\n<p>Die Eigenschaften f&uuml;r den entsprechenden Eintrag im TreeView-Konfigurator lauten wie folgt:<\/p>\n<ul>\n<li class=\"aufz-hlung\"><b>Tabelle\/Abfrage<\/b>: <b>qryDateienBaum<\/b><\/li>\n<li class=\"aufz-hlung\"><b>&Uuml;bergeordnete Tabelle<\/b>: <b>qryVerzeichnisseBaum<\/b><\/li>\n<li class=\"aufz-hlung\"><b>Prim&auml;rschl&uuml;ssel<\/b>: <b>DateiVerzeichnisID<\/b><\/li>\n<li class=\"aufz-hlung\"><b>Fremdschl&uuml;ssel<\/b>: <b>VerzeichnisID<\/b><\/li>\n<li class=\"aufz-hlung\"><b>Schl&uuml;ssel<\/b>: <b>dd<\/b><\/li>\n<li class=\"aufz-hlung\"><b>Icon\/Standard <\/b>(abweichend von den Verzeichnis-Eintr&auml;gen): <b>data_16.png<\/b><\/li>\n<\/ul>\n<p>Beim n&auml;chsten Anzeigen des Formulars <b>frmDateienVerzeichnisse <\/b>erscheinen nun auch die Eintr&auml;ge f&uuml;r die Datenbankdateien im TreeView-Steuerelement.<\/p>\n<p><b>Kontextmen&uuml;eintr&auml;ge<\/b><\/p>\n<p>F&uuml;r die im TreeView angezeigten Dateien fehlen noch die Kontextmen&uuml;-Eintr&auml;ge. Diese f&uuml;gen Sie ebenfalls &uuml;ber den TreeView-Konfigurator hinzu. Dazu tragen Sie im unteren Bereich einfach die Bezeichnungen ein und geben die Bilddateien an (s. Bild 12).<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_03\/DatenbankenAnzeigen-web-images\/pic012.png\" alt=\"pic012.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 12: Konfiguration f&uuml;r die Dateieintr&auml;ge samt Kontextmen&uuml;-Eintr&auml;gen<\/span><\/b><\/p>\n<p>Au&szlig;erdem k&ouml;nnen Sie unter <b>ContextmenuParameter <\/b>noch einen Parameter eintragen, der beim Anklicken eines der Kontextmen&uuml;-Eintr&auml;ge an die dadurch ausgel&ouml;ste Ereignisprozedur weitergeleitet wird. Die Eintr&auml;ge sehen wie folgt aus:<\/p>\n<ul>\n<li class=\"aufz-hlung\"><b>Zu Verzeichnis wechseln<\/b>: Parameter <b>ShowFolder<\/b>, Image <b>folder.png<\/b><\/li>\n<li class=\"aufz-hlung\"><b>Datenbank &ouml;ffnen<\/b>: Parameter <b>OpenDatabase<\/b>, Image <b>data_16.png<\/b><\/li>\n<li class=\"aufz-hlung\"><b>L&ouml;schen<\/b>: Parameter <b>Delete<\/b>, Image <b>delete.png<\/b><\/li>\n<\/ul>\n<p>Nun fehlen nur noch ein paar Ereignisprozeduren.<\/p>\n<p><b>Ereignisprozeduren des TreeView-Steuerelements<\/b><\/p>\n<p>Schauen wir uns zun&auml;chst die Prozedur an, die durch das Bet&auml;tigen der Kontextmen&uuml;-Eintr&auml;ge ausgel&ouml;st wird. Diese f&uuml;gen Sie dem Klassenmodul <b>Form_frmDateienVerzeichnisse <\/b>&uuml;ber die Kombinationsfelder oben im Code-Fenster hinzu (links <b>objTreeViewHandler <\/b>ausw&auml;hlen, rechts <b>ShortcutMenuClick<\/b>).<\/p>\n<p>Die nun erscheinende Prozedur erg&auml;nzen Sie wie in <span class=\"verweis-ohneumbruch\"><a href=\"#anker-68-anchor\">Listing 3<\/a><\/span>. Die Prozedur ermittelt zun&auml;chst per <b>DLookup<\/b>-Funktion den Pfad der Datei, die der Benutzer mit der rechten Maustaste angeklickt hat.<\/p>\n<p class=\"listingueberschrift\">Listing 3: Ereignisprozedur, die durch das Anklicken eines Kontextmen&uuml;-Eintrags ausgel&ouml;st wird<\/p>\n<pre>Private Sub objTreeViewHandler_ShortcutMenuClick(objNode As MSComctlLib.Node, _\r\n        strParameter As String, strThistable As String, strTableBase As String, strPKID As String, dblPKIDValue As Double)\r\n    Dim strDateiname As String\r\n    strDateiname = DLookup(&quot;Pfad&quot;, &quot;tblDateienVerzeichnisse&quot;, &quot;DateiVerzeichnisID = &quot; &amp; dblPKIDValue)\r\n    Select Case strParameter\r\n        Case &quot;Delete&quot;\r\n            If MsgBox(&quot;Datei ''&quot; &amp; strDateiname &amp; &quot;'' l&ouml;schen&quot;, vbYesNo + vbExclamation, &quot;Datei l&ouml;schen&quot;) = vbYes Then\r\n                Kill strDateiname\r\n                objTreeViewHandler.DeleteCurrentNode\r\n            End If\r\n        Case &quot;OpenDatabase&quot;\r\n            Shell &quot;Explorer.exe &quot; &amp; strDateiname, vbNormalFocus\r\n        Case &quot;ShowFolder&quot;\r\n            strDateiname = Left(strDateiname, InStrRev(strDateiname, &quot;\\&quot;))\r\n            Shell &quot;Explorer.exe &quot; &amp; strDateiname, vbNormalFocus\r\n    End Select\r\nEnd Sub<\/pre>\n<p>Sie erh&auml;lt au&szlig;erdem &uuml;ber den Parameter <b>strParameter <\/b>den f&uuml;r <b>ContextMenuParameter <\/b>festgelegten Ausdruck, also entweder <b>Delete<\/b>, <b>OpenDatabase <\/b>oder <b>ShowFolder<\/b>. In Abh&auml;ngigkeit davon f&uuml;hrt die Prozedur einen der drei Zweige der <b>Select Case<\/b>-Bedingung aus.<\/p>\n<p>Der erste l&ouml;scht die aktuelle Datenbankdatei nach vorheriger R&uuml;ckfrage, der zweite &ouml;ffnet den Windows Explorer und navigiert dort gleich zum Verzeichnis, in dem sich die Datenbank befindet, und der dritte &ouml;ffnet die Datenbank mit Access.<\/p>\n<p><b>Bei Klick Dateipfad anzeigen<\/b><\/p>\n<p>Eine weitere Ereignisprozedur wird durch einen Mausklick auf einen beliebigen Eintrag im TreeView-Steuerelement ausgel&ouml;st. Die Prozedur hei&szlig;t <b>objTreeViewHandler_NodeClick <\/b>und liefert beispielsweise den Prim&auml;rschl&uuml;sselwert des angeklickten Elements.<\/p>\n<p>Damit ermittelt die Ereignisprozedur den passenden Dateinamen aus der Tabelle <b>tblDateienVerzeichnisse <\/b>und zeigt diesen im Textfeld <b>txtDatei <\/b>an, den wir noch unterhalb des TreeView-Steuerelements einf&uuml;gen (s. <span class=\"verweis-ohneumbruch\"><a href=\"#anker-70-anchor\">Listing 4<\/a><\/span>).<\/p>\n<p class=\"listingueberschrift\">Listing 4: Ereignisprozedur, die durch das Anklicken eines Datei-Eintrags ausgel&ouml;st wird<\/p>\n<pre>Private Sub objTreeViewHandler_NodeClick(objNode As MSComctlLib.Node, strTable As String, _\r\n        strTableBase As String, strPKID As String, dblPKID As Double)\r\n    Me!txtDatei = DLookup(&quot;Pfad&quot;, &quot;tblDateienVerzeichnisse&quot;, &quot;DateiVerzeichnisID = &quot; &amp; dblPKID)\r\nEnd Sub<\/pre>\n<p><b>R&uuml;ckgabe des gew&auml;hlten Verzeichnisnamens<\/b><\/p>\n<p>Der Sinn des Formulars besteht unter anderem darin, zu bestimmten Gelegenheiten zu erscheinen, die Auswahl einer Datenbankdatei zu erlauben und diese dann weiterzuverarbeiten. Dies gelingt mit ein paar Erweiterungen der aktuellen Version.<\/p>\n<p>Die Funktion aus <span class=\"verweis-ohneumbruch\"><a href=\"#anker-71-anchor\">Listing 5<\/a><\/span> &ouml;ffnet das Formular als modalen Dialog und wartet, bis dieses wieder geschlossen wird. Da Sie einem geschlossenen Formular keine gew&auml;hlten Werte mehr entlocken k&ouml;nnen, wird es nicht direkt geschlossen, sondern unsichtbar gemacht &#8211; so l&auml;uft der aufrufende Code weiter und kann direkt auf die Steuerelemente des Formulars zugreifen.<\/p>\n<p class=\"listingueberschrift\">Listing 5: Aufruf des Formulars mit R&uuml;ckgabe der gew&auml;hlten Datenbankdatei<\/p>\n<pre>Public Function DatenbankErmitteln(strPfad As String)\r\n    DoCmd.OpenForm &quot;frmDateienVerzeichnisse&quot;, WindowMode:=acDialog, OpenArgs:=strPfad\r\n    If IstFormularGeoeffnet(&quot;frmDateienVerzeichnisse&quot;) Then\r\n        DatenbankErmitteln = Forms!frmDateienVerzeichnisse!txtDatei\r\n        DoCmd.Close acForm, &quot;frmDateienVerzeichnisse&quot;\r\n    End If\r\nEnd Function<\/pre>\n<p>Im Formular realisieren wir das Verstecken des Formulars durch eine <b>OK<\/b>-Schaltfl&auml;che mit folgender Ereignisprozedur:<\/p>\n<pre>Private Sub cmdOK_Click()\r\n    Me.Visible = False\r\nEnd Sub<\/pre>\n<p>Nach dem Schlie&szlig;en liest die Funktion <b>DatenbankErmitteln <\/b>den Inhalt des Textfeldes <b>txtDatei <\/b>aus und schlie&szlig;t das Formular dann endg&uuml;ltig.<\/p>\n<p>Damit das Formular direkt das gew&uuml;nschte Startverzeichnis anzeigt, erlaubt die Funktion <b>DatenbankErmitteln <\/b>die Angabe einer entsprechenden Zeichenkette. Diese leitet die Funktion per <b>OpenArgs<\/b>-Parameter an das zu &ouml;ffnende Formular weiter.<\/p>\n<p>Beim &Ouml;ffnen des Formulars wertet die erweiterte Fassung der <b>Form_Load<\/b>-Prozedur das &Ouml;ffnungsargument aus und schreibt es in die Variable <b>strAktuellesVerzeichnis<\/b>.<\/p>\n<p>Nun ist es so, dass es nicht gerade trivial ist, genau das gew&uuml;nschte Element im TreeView-Steuerelement aufzuklappen.<\/p>\n<p>Deshalb ben&ouml;tigen wir dazu eine eigene Prozedur namens <b>ZielverzeichnisAusklappen<\/b>. Diese erwartet das gew&uuml;nschte Verzeichnis sowie eine weitere Variable, welche den Wert der Eigenschaft <b>Key <\/b>des resultierenden Elements zur&uuml;ckliefert. Dieses verarbeitet die Prozedur weiter, indem sie genau dieses Element mit der <b>ClickNode<\/b>-Methode des <b>TreeViewHandler<\/b>-Objekts markiert:<\/p>\n<pre>Private Sub Form_Load()\r\n    Dim strKey As String\r\n    Dim strAktuellesVerzeichnis As String\r\n    strAktuellesVerzeichnis = Nz(Me.OpenArgs)\r\n    If Len(strAktuellesVerzeichnis) &gt; 0 Then\r\n        ZielverzeichnisAusklappen strAktuellesVerzeichnis, strKey\r\n    End If\r\n    BaumFuellen\r\n    If Len(strKey) &gt; 0 Then\r\n        objTreeViewHandler.ClickNode , , strKey\r\n    End If\r\nEnd Sub<\/pre>\n<p>Die Prozedur <b>ZielverzeichnisAusklappen <\/b>wirkt sich nicht direkt auf die Anzeige der Elemente im TreeView-Steuerelement aus.<\/p>\n<p>Daher ist vor dem Markieren des Zielelements noch die Anzeige mit der Prozedur <b>BaumFuellen <\/b>zu aktualisieren.<\/p>\n<p><b>Direktes Anzeigen eines Verzeichnisses beim &Ouml;ffnen<\/b><\/p>\n<p>Das Arbeitstier beim Ausklappen eines gew&uuml;nschten Zielverzeichnisses ist die Prozedur <b>ZielverzeichnisAusklappen <\/b>mit ihrer rekursiven Erg&auml;nzung <b>ElementMarkierenRek<\/b> (s. <span class=\"verweis-ohneumbruch\"><a href=\"#anker-77-anchor\">Listing 6<\/a><\/span>). Die erstgenannte Prozedur erwartet die genannten Parameter und ermittelt zun&auml;chst einen Eintrag aus der Tabelle <b>tblDateienVerzeichnisse<\/b>, dessen Pfad dem mit <b>strVerzeichnis <\/b>&uuml;bergebenen nahekommt. Mit dessen Prim&auml;rschl&uuml;sselwert ermittelt die Prozedur dann den &uuml;bergeordneten Eintrag. Ist dieser vorhanden, ruft die Prozedur die rekursive Funktion <b>ElementMarkierenRek <\/b>auf.<\/p>\n<p class=\"listingueberschrift\">Listing 6: Prozedur, die alle Elemente bis zum angegebenen Verzeichnis ausklappt<\/p>\n<pre>Private Sub ZielverzeichnisAusklappen(strVerzeichnis As String, strKey As String)\r\n    Dim lngDateiVerzeichnisID As Long\r\n    Dim lngVerzeichnisID As Long\r\n    Dim db As DAO.Database\r\n    Set db = CurrentDb\r\n    lngDateiVerzeichnisID = Nz(DLookup(&quot;DateiVerzeichnisID&quot;, &quot;tblDateienVerzeichnisse&quot;, _\r\n        &quot;Pfad LIKE ''&quot; &amp; strVerzeichnis &amp; &quot;*''&quot;), 0)\r\n    lngVerzeichnisID = Nz(DLookup(&quot;VerzeichnisID&quot;, &quot;tblDateienVerzeichnisse&quot;, _\r\n        &quot;DateiVerzeichnisID = &quot; &amp; lngDateiVerzeichnisID), 0)\r\n    If Not lngVerzeichnisID = 0 Then\r\n        ElementMarkierenRek db, lngDateiVerzeichnisID, Len(strVerzeichnis) - _\r\n            Len(Replace(strVerzeichnis, &quot;\\&quot;, &quot;&quot;)) + 1, strKey\r\n    End If\r\nEnd Sub<\/pre>\n<p>Bevor wir diese ansehen, ein Ausblick auf das, was nun geschieht: Wir haben in der Tabelle <b>tblDateienVerzeichnisse <\/b>den Datensatz ermittelt, der dem Pfad zu dem zu markierenden Element im TreeView entspricht. Nun wollen wir daf&uuml;r sorgen, dass dieses angezeigt wird. Dazu m&uuml;ssen wir den Wert des Feldes <b>Expanded <\/b>f&uuml;r diesen Datensatz und f&uuml;r alle Datens&auml;tze, die diesem direkt &uuml;bergeordnet sind, auf den Wert <b>True <\/b>einstellen. Wenn wir dann das TreeView-Steuerelement neu f&uuml;llen, sollten alle Elemente bis zum Zielelement ausgeklappt sein und das Zielelement kann markiert werden.<\/p>\n<p><b>Die Funktion ElementMarkierenRek<\/b><\/p>\n<p>Zum Einstellen des Feldes <b>Expanded <\/b>auf den Wert <b>True <\/b>arbeiten wir uns St&uuml;ck f&uuml;r St&uuml;ck in der Hierarchie nach oben. Dazu ben&ouml;tigen wir eine rekursiv definierte Funktion, in diesem Fall <b>ElementMarkierenRek<\/b> (s. <span class=\"verweis-ohneumbruch\"><a href=\"#anker-72-anchor\">Listing 7<\/a><\/span>). Diese erwartet als Parameter einen Verweis auf das aktuelle <b>Database<\/b>-Objekt, die ID des zu untersuchenden Elements, eine Variable zum &Uuml;bergeben der Verzeichnistiefe (ermittelt aus der Anzahl der Backslash-Zeichen des Verzeichnisses) und die Variable <b>strKey<\/b>, welche die <b>Key<\/b>-Eigenschaften der einzelnen Elemente bis zum Zielverzeichnis auflistet.<\/p>\n<p class=\"listingueberschrift\">Listing 7: Rekursiver Teil der Funktion zum Ausklappen bis zu einem bestimmten Verzeichnis<\/p>\n<pre>Private Sub ElementMarkierenRek(db As DAO.Database, lngVerzeichnisID As Long, intLevel As Integer, _\r\n        Optional ByRef strKey As String)\r\n    Dim lngDateiVerzeichnisID As Long\r\n    lngDateiVerzeichnisID = lngVerzeichnisID\r\n    lngVerzeichnisID = Nz(DLookup(&quot;VerzeichnisID&quot;, &quot;tblDateienVerzeichnisse&quot;, &quot;DateiVerzeichnisID = &quot; &amp; lngVerzeichnisID), 0)\r\n    If Not lngVerzeichnisID = 0 Then\r\n        lngDateiVerzeichnisID = lngVerzeichnisID\r\n        db.Execute &quot;UPDATE tblDateienVerzeichnisse SET Expanded = True WHERE DateiVerzeichnisID = &quot; _\r\n            &amp; lngDateiVerzeichnisID, dbFailOnError\r\n        Select Case intLevel\r\n        Case 1\r\n            strKey = &quot;|v0&quot; &amp; lngDateiVerzeichnisID &amp; strKey\r\n        Case 2\r\n            strKey = &quot;|vv&quot; &amp; lngDateiVerzeichnisID &amp; strKey\r\n        Case Else\r\n            strKey = &quot;|vr&quot; &amp; lngDateiVerzeichnisID &amp; strKey\r\n        End Select\r\n        ElementMarkierenRek db, lngVerzeichnisID, intLevel - 1, strKey\r\n        If Left(strKey, 1) = &quot;|&quot; Then\r\n            strKey = Mid(strKey, 2)\r\n        End If\r\n    End If\r\nEnd Sub<\/pre>\n<p>Dazu m&uuml;ssen Sie wissen, dass der TreeView-Konfigurator den Wert der Eigenschaft <b>Key <\/b>hierarchisch anlegt. Das bedeutet, dass das Root-Element <b>v01 <\/b>hei&szlig;t, das erste untergeordnete Element <b>v01|vv1<\/b>, das n&auml;chste <b>v01|vv1|vr1 <\/b>und so weiter. Wenn wir also am Ende das gew&uuml;nschte Verzeichnis-Element markieren m&ouml;chten, m&uuml;ssen wir die <b>Key<\/b>-Eigenschaft genau zusammenstellen.<\/p>\n<p>Und hier folgt auch der Grund, warum die Eigenschaft als rekursive Funktion ausgelegt ist und nicht einfach als <b>Do While<\/b>-Schleife, die bis zum Erreichen des Root-Elements l&auml;uft: Die Funktion navigiert vom Ziel-Element nach oben bis zum Root-Element und stellt derweil das <b>Expanded<\/b>-Feld f&uuml;r alle durchlaufenen Elemente auf <b>True <\/b>ein.<\/p>\n<p>Hinter dem Aufruf der rekursiven Funktion folgt jedoch immer noch eine Anweisung, die den <b>Key <\/b>aus dem in <b>strKey <\/b>gelieferten bisherigen <b>Key<\/b>-Ausdruck und dem aktuellen <b>Key<\/b>-Wert zusammensetzt.<\/p>\n<p>Die Funktion speichert den Prim&auml;rschl&uuml;sselwert des aktuellen Elements in <b>lngDateiVerzeichnisID<\/b> zwischen und ermittelt dann per <b>DLookup <\/b>den Prim&auml;rschl&uuml;sselwert des &uuml;bergeordneten Elements.<\/p>\n<p>Solange die Prozedur noch nicht beim Root-Element angekommen ist (<b>lngVerzeichnisID = 0<\/b>), &auml;ndert sie die Eigenschaft des Feldes <b>Expanded <\/b>f&uuml;r den &uuml;bergeordneten Datensatz auf <b>Wahr<\/b>. Au&szlig;erdem ermittelt sie anhand der in <b>intLevel <\/b>gespeicherten Verzeichnisebene, ob die Funktion gerade die erste, zweite oder eine andere Ebene beackert.<\/p>\n<p>Die ersten beiden werden gem&auml;&szlig; Konfiguration des TreeViews mit den <b>Key<\/b>-Pr&auml;fixen <b>v0 <\/b>und <b>vv <\/b>versehen, die &uuml;brigen mit <b>vr<\/b>. Dies ist wichtig f&uuml;r das Zusammenstellen des <b>Key<\/b>-Wertes f&uuml;r den sp&auml;ter zu markierenden Datensatz.<\/p>\n<p>Neben den Pr&auml;fixen besteht der <b>Key<\/b>-Wert &uuml;brigens aus dem Prim&auml;rschl&uuml;sselwert des jeweiligen Datensatzes.<\/p>\n<p>Nach dem rekursiven Aufruf der Funktion f&uuml;r die n&auml;chsth&ouml;here Ebene erweitert die Funktion noch den Inhalt von <b>strKey <\/b>um den aktuellen <b>Key<\/b>-Wert.<\/p>\n<p>Auf diese Weise stellt die Prozedur die <b>Expanded<\/b>-Eigenschaft f&uuml;r alle Elemente des Pfades auf <b>True<\/b> ein und markiert nach dem Neuf&uuml;llen des TreeView-Steuerelements das angegebene Verzeichnis.<\/p>\n<p><b>Zusammenfassung und Ausblick<\/b><\/p>\n<p>Mit der hier vorgestellten L&ouml;sung erweitern Sie Anwendungen um die M&ouml;glichkeit, Datenbankdateien komfortabel auszuw&auml;hlen. Vielleicht m&ouml;chten Sie die Datenbank auch als Basis f&uuml;r eigene Add-Ins verwenden, um beispielsweise Datenbanken f&uuml;r den Export oder Import von Daten auszuw&auml;hlen.<\/p>\n<p>Grunds&auml;tzlich ist dies eine einfache M&ouml;glichkeit, um schnell nur auf die Datenbankdateien im Dateisysten zuzugreifen.<\/p>\n<h3>Downloads zu diesem Beitrag<\/h3>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>AlleDatenbankenEinlesen.mdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/{15BDA350-21F5-4376-A6BB-527240DE246C}\/aiu_888.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>F&uuml;r den einen oder anderen Anwendungsfall bent&ouml;igen Sie einen Datei &ouml;ffnen-Dialog, um eine Datenbank auszuw&auml;hlen. Diese Dialog hat den Nachteil, dass er selten direkt die gew&uuml;nschte Datenbank geschweige denn das Verzeichnis anzeigt. Wie w&auml;re es also mit einem speziellen Dialog, der nur die Verzeichnisse einliest, die &uuml;berhaupt Datenbankdateien enthalten und diese in einem TreeView-Steuerelement zur Auswahl bereith&auml;lt<\/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":[662013,66032013,44000027],"tags":[],"class_list":["post-55000888","post","type-post","status-publish","format-standard","hentry","category-662013","category-66032013","category-Loesungen"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Alle Datenbanken einlesen und anzeigen - 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\/Alle_Datenbanken_einlesen_und_anzeigen\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Alle Datenbanken einlesen und anzeigen\" \/>\n<meta property=\"og:description\" content=\"F&uuml;r den einen oder anderen Anwendungsfall bent&ouml;igen Sie einen Datei &ouml;ffnen-Dialog, um eine Datenbank auszuw&auml;hlen. Diese Dialog hat den Nachteil, dass er selten direkt die gew&uuml;nschte Datenbank geschweige denn das Verzeichnis anzeigt. Wie w&auml;re es also mit einem speziellen Dialog, der nur die Verzeichnisse einliest, die &uuml;berhaupt Datenbankdateien enthalten und diese in einem TreeView-Steuerelement zur Auswahl bereith&auml;lt\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Alle_Datenbanken_einlesen_und_anzeigen\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2020-05-22T21:36:06+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg05.met.vgwort.de\/na\/9ab73511b8574023924e2b529eb5e543\" \/>\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\\\/Alle_Datenbanken_einlesen_und_anzeigen\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Alle_Datenbanken_einlesen_und_anzeigen\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Alle Datenbanken einlesen und anzeigen\",\"datePublished\":\"2020-05-22T21:36:06+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Alle_Datenbanken_einlesen_und_anzeigen\\\/\"},\"wordCount\":5767,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Alle_Datenbanken_einlesen_und_anzeigen\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg05.met.vgwort.de\\\/na\\\/9ab73511b8574023924e2b529eb5e543\",\"articleSection\":[\"2013\",\"3\\\/2013\",\"L\u00f6sungen\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Alle_Datenbanken_einlesen_und_anzeigen\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Alle_Datenbanken_einlesen_und_anzeigen\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Alle_Datenbanken_einlesen_und_anzeigen\\\/\",\"name\":\"Alle Datenbanken einlesen und anzeigen - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Alle_Datenbanken_einlesen_und_anzeigen\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Alle_Datenbanken_einlesen_und_anzeigen\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg05.met.vgwort.de\\\/na\\\/9ab73511b8574023924e2b529eb5e543\",\"datePublished\":\"2020-05-22T21:36:06+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Alle_Datenbanken_einlesen_und_anzeigen\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Alle_Datenbanken_einlesen_und_anzeigen\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Alle_Datenbanken_einlesen_und_anzeigen\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg05.met.vgwort.de\\\/na\\\/9ab73511b8574023924e2b529eb5e543\",\"contentUrl\":\"http:\\\/\\\/vg05.met.vgwort.de\\\/na\\\/9ab73511b8574023924e2b529eb5e543\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Alle_Datenbanken_einlesen_und_anzeigen\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Alle Datenbanken einlesen und anzeigen\"}]},{\"@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":"Alle Datenbanken einlesen und anzeigen - 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\/Alle_Datenbanken_einlesen_und_anzeigen\/","og_locale":"de_DE","og_type":"article","og_title":"Alle Datenbanken einlesen und anzeigen","og_description":"F&uuml;r den einen oder anderen Anwendungsfall bent&ouml;igen Sie einen Datei &ouml;ffnen-Dialog, um eine Datenbank auszuw&auml;hlen. Diese Dialog hat den Nachteil, dass er selten direkt die gew&uuml;nschte Datenbank geschweige denn das Verzeichnis anzeigt. Wie w&auml;re es also mit einem speziellen Dialog, der nur die Verzeichnisse einliest, die &uuml;berhaupt Datenbankdateien enthalten und diese in einem TreeView-Steuerelement zur Auswahl bereith&auml;lt","og_url":"https:\/\/access-im-unternehmen.de\/Alle_Datenbanken_einlesen_und_anzeigen\/","og_site_name":"Access im Unternehmen","article_published_time":"2020-05-22T21:36:06+00:00","og_image":[{"url":"http:\/\/vg05.met.vgwort.de\/na\/9ab73511b8574023924e2b529eb5e543","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\/Alle_Datenbanken_einlesen_und_anzeigen\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Alle_Datenbanken_einlesen_und_anzeigen\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Alle Datenbanken einlesen und anzeigen","datePublished":"2020-05-22T21:36:06+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Alle_Datenbanken_einlesen_und_anzeigen\/"},"wordCount":5767,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Alle_Datenbanken_einlesen_und_anzeigen\/#primaryimage"},"thumbnailUrl":"http:\/\/vg05.met.vgwort.de\/na\/9ab73511b8574023924e2b529eb5e543","articleSection":["2013","3\/2013","L\u00f6sungen"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Alle_Datenbanken_einlesen_und_anzeigen\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Alle_Datenbanken_einlesen_und_anzeigen\/","url":"https:\/\/access-im-unternehmen.de\/Alle_Datenbanken_einlesen_und_anzeigen\/","name":"Alle Datenbanken einlesen und anzeigen - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Alle_Datenbanken_einlesen_und_anzeigen\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Alle_Datenbanken_einlesen_und_anzeigen\/#primaryimage"},"thumbnailUrl":"http:\/\/vg05.met.vgwort.de\/na\/9ab73511b8574023924e2b529eb5e543","datePublished":"2020-05-22T21:36:06+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Alle_Datenbanken_einlesen_und_anzeigen\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Alle_Datenbanken_einlesen_und_anzeigen\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Alle_Datenbanken_einlesen_und_anzeigen\/#primaryimage","url":"http:\/\/vg05.met.vgwort.de\/na\/9ab73511b8574023924e2b529eb5e543","contentUrl":"http:\/\/vg05.met.vgwort.de\/na\/9ab73511b8574023924e2b529eb5e543"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Alle_Datenbanken_einlesen_und_anzeigen\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Alle Datenbanken einlesen und anzeigen"}]},{"@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\/55000888","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=55000888"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55000888\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55000888"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55000888"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55000888"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}