Es gibt verschiedene Varianten, eine Datei oder ein Verzeichnis per Dateidialog auszuwählen. Wer jedoch schon einmal mit einer Linux-Shell oder auch mit dem MS-Dos-Fenster gearbeitet hat, weiß, dass sich Verzeichnisse und Dateien auch rein tastaturgesteuert eingeben lassen. Was liegt da näher, als eine effiziente und schnelle Möglichkeit zum Auswählen von Verzeichnis- und Dateinamen zu bauen, die ausschließlich per Tastatur bedient werden kann Dieser Beitrag zeigt, wie Sie ein herkömmliches Kombinationsfeld zur Dateiauswahl einsetzen.
Datei- und Verzeichnisauswahl mit einem Kombinationsfeld – wie soll das denn funktionieren Nun, es ist ganz einfach: Der Benutzer kann für das jungfräuliche Kombinationsfeld eines der vorhanden Laufwerke auswählen (s. Bild 1). Das erledigt er, indem er entweder einen der Einträge des Kombinationsfeldes auswählt oder indem er den Anfangsbuchstaben eintippt (beispielsweise c) und dann die Tabulator-Taste betätigt.
Bild 1: Die Auswahl eines der Laufwerke des aktuellen Rechners …
Daraufhin wird der Laufwerkspfad vervollständigt (auf c:\) und die Liste neu gefüllt – diesmal mit allen in der ersten Ebene unterhalb dieses Pfades enthaltenen Verzeichnissen und Dateien (s. Bild 2).
Bild 2: … führt zur Anzeige aller untergeordneten Verzeichnisse und Dateien.
Der Benutzer kann nun die Anfangsbuchstaben des gewünschten Eintrags eintippen oder auch mit den Nach oben– und Nach unten-Tasten einen der Listeneinträge auswählen. Gibt er einen oder mehrere Buchstaben ein, springt die Markierung in der Liste automatisch zum nächsten passenden Eintrag – dies ist Standardverhalten des Kombinationsfeldes. Wählt er mit den Cursortasten oder mit der Maus einen der Listeneinträge aus, wird dieser als aktueller Text des Kombinationsfeldes eingetragen.
Als Folge der Auswahl eines weiteren Unterordners werden wiederum die darin enthaltenen Verzeichnisse angezeigt – bis Sie irgendwann beim Zielordner angekommen, zum Beispiel im Access-Add-In-Verzeichnis (s. Bild 3).
Bild 4: Ausstattung eines Kombinationsfeldes mit einer Wertliste
Wenn Sie mal über das Ziel hinausgeschossen sind und ein oder mehrere Verzeichnisebenen weiter nach oben gelangen möchten, haben Sie zwei Möglichkeiten:
- Sie wählen gerade mit den Cursortasten einen Eintrag der Liste aus, dann wird der aktuelle Wert komplett markiert. Ein Klick auf die Löschen-Taste führt zum Löschen des zuletzt hinzugefügten Verzeichnisses.
- Oder Sie befinden sich gerade im Eingabemodus des Kombinationsfeldes. Dann können Sie entweder mit der Löschen-Taste zeichenweise oder mit Strg + Löschen elementweise löschen (jeweils etwa bis zum nächsten Leerzeichen oder Backslash).
Programmierung des Kombinationsfeldes
Den Startpunkt und die einfachste Hürde auf dem Weg zu einem Kombinationsfeld mit dieser Sonderausstattung ist die Anzeige der Laufwerke beim Öffnen des Formulars. Dies erledigen wir in der Prozedur, die durch das Ereignis Beim Laden des Formulars ausgelöst wird. Die Prozedur liest mit der Funktion GetDrives die Liste aller Laufwerke ein und weist diese dem Kombinationsfeld als Recordset zu:
Private Sub Form_Load() Set Me!cboDateiname.Recordset = GetDrives End Sub
Kombinationsfeld füllen
Wenn Sie ein Kombinationsfeld auf Basis von Daten füllen möchten, die nicht aus einer Tabelle oder Abfrage stammen, haben Sie mehrere Möglichkeiten. Die erste und naheliegendste ist die Verwendung einer Wertliste. Dies bedeutet, dass Sie die Eigenschaft Herkunftsart des Kombinationsfeldes auf den Wert Wertliste einstellen (s. Bild 4) und per VBA eine Zeichenkette zusammenstellen, deren einzelne Einträge durch das Semikolon voneinander getrennt werden. Diese Vorgehensweise haben wir beim Erstellen dieser Lösung auch lange verwendet, bis sich irgendwann einmal der große Nachteil beim Einsatz von Wertlisten als Datenherkunft bemerkbar machte: Die Anzahl der enthaltenen Zeichen ist nämlich begrenzt. Aufgefallen ist dies beim Einlesen der Dateien eines Verzeichnis mit den Fotografien von 2010 – und mehr als 1.000 Dateinamen inklusive Pfadangaben waren dann doch etwas viel für eine Wertliste.
Bild 3: Mit dem Kombinationsfeld arbeiten Sie sich bis in tiefste Verzeichnisebenen vor.
Zum Glück gibt es noch weitere Varianten, zum Beispiel die Verwendung eines ADODB-Recordsets. Dieses kann man im Gegensatz zu DAO-Recordsets auch ohne Datenherkunft definieren und quasi in der Luft mit Daten füllen.
Es gibt dabei auch nicht besonders viel zu beachten – Sie müssen nur die Eigenschaft LockType des zu erstellenden Recordset-Objekts auf den Wert adLockOptimistic einstellen. Aus unerfindlichen Gründen zeigt das Kombinationsfeld nur dann Werte an!
Laufwerke einlesen
Das Zusammenstellen der Liste der Laufwerke übernimmt die Funktion GetDrives. Diese sieht wie in Listing 1 aus.
Listing 1: Zusammenstellen der Liste aller Laufwerke des aktuellen Rechners
Private Function GetDrives() As adodb.Recordset Dim objDrive As Scripting.Drive Set rst = New adodb.Recordset With rst .LockType = adLockOptimistic .Fields.Append "Pfad", adVarWChar, 500 .Open For Each objDrive In objFSO.Drives .AddNew !Pfad = objDrive.DriveLetter & ":\" .Update Next objDrive End With Set GetDrives = rst End Function
Die Funktion erstellt zunächst ein neues Objekt des Typs ADODB.Recordset. Die Objektvariable hierfür wird im Kopf des Moduls wie folgt deklariert:
Dim rst As ADODB.Recordset
Nach der Erzeugung des Objekts mit der New-Methode stellt die Prozedur die besagte Eigenschaft LockType auf adLockOptimistic ein. Außerdem hängt es das Feld Pfad an die Tabelle an. Das Feld hat den Datentyp adVarWChar und soll maximal 500 Zeichen lang sein (wenn Sie längere Pfade erwarten, vergrößern Sie diesen Wert entsprechend). Dann öffnet es die Datensatzgrupp und durchläuft alle Elemente der Drives-Auflistung des FileSystemObject-Objekts (weitere Informationen siehe Beitrag Dateisystem im Griff mit dem FileSystemObject, www.access-im-unternehmen.de/794).
Dabei wird jeweils ein neuer Datensatz mit AddNew erzeugt, das Feld Pfad mit dem Namen des aktuellen Laufwerkbuchstabens gefüllt (ergänzt um die Zeichenfolge :\) und der Datensatz gespeichert. Der Verweis auf die Datensatzgruppe wird schließlich als Rückgabewert der Funktion festgelegt.
FileSystemObject bereitstellen
Das in dieser Funktion verwendete Objekt objFSO wird nicht global deklariert und beim Laden des Formulars instanziert, sondern durch eine Funktion bereitgestellt. Zunächst einmal wird eine Objektvariable zum Zwischenspeichern des FileSystemObject-Objekts im Kopf der Prozedur deklariert:
Dim m_FSO As FileSystemObject
Die Funktion objFSO prüft zunächst, ob m_FSO nicht leer ist und somit bereits instanziert wurde. Falls nicht (oder falls die Objektvariable etwa durch einen nicht behandelten Laufzeitfehler gelöscht wurde), instanziert Sie das Objekt erneut und weist es der Variablen m_FSO zu. Egal, ob frisch erstellt oder noch vorhanden, wird dieses dann dem Rückgabewert objFSO der gleichnamigen Funktion zugewiesen:
Function objFSO() As FileSystemObject If m_FSO Is Nothing Then Set m_FSO = New FileSystemObject End If Set objFSO = m_FSO End Function
Verzeichnis auswählen
Wenn der Benutzer nun einen entsprechenden Buchstaben in das Kombinationsfeld eintippt, zeigt die Liste alle Einträge an, die mit diesem Buchstaben beginnen (im schlechtesten Fall also gar keinen). Natürlich kann der Benutzer das Kombinationsfeld auch einfach durch einen Klick auf die Schaltfläche rechts oder mit der Schaltfläche F4 öffnen.
Um direkt die in diesem Laufwerk enthaltenen Verzeichnisse anzuzeigen, muss der Benutzer entweder einen konkreten Eintrag der Kombinationsfeldliste auswählen oder aber den Laufwerksbuchstaben eingeben und die Tabulatortaste betätigen.
Die Eingabe einzelner Zeichen soll unberücksichttigt bleiben, lediglich auf das Löschen von Zeichen reagiert die Lösung. Dies ist wichtig, damit die Datensatzherkunft des Kombinationsfeldes aktualisiert wird, wenn der Benutzer eine Verzeichnisebene komplett löscht: Das Recordset des Kombinationsfeldes muss dann aktualisiert werden. Das gleiche soll auch passieren, wenn der Benutzer einzelne Zeichen bis zum vorherigen Backslash löscht. Sobald das Backslash-Zeichen erreicht ist, soll das Kombinationsfeld entsprechend aktualisiert werden, sodass es die Unterverzeichnisse des nun angegebenen Verzeichnisses anzeigt.
Die hier wichtigen Ereignisse, also das Betätigen der Tab-Taste oder der Löschen-Taste, fangen wir mit einer Prozedur ab, die durch das Ereignis Bei Taste ab ausgelöst wird (s. Listing 2).
Listing 2: Reagieren auf das Betätigen der Tabulator- oder der Löschen-Taste
Private Sub cboDateiname_KeyDown(KeyCode As Integer, Shift As Integer) Dim strFolder As String Dim bolAllesMarkiert As Boolean Dim bolBackslashErreicht As Boolean Select Case KeyCode Case 8 ''Löschen With Me!cboDateiname If Len(.Text) > 0 Then bolAllesMarkiert = .SelLength = Len(.Text) bolBackslashErreicht = .SelStart = Len(.Text) And InStrRev(.Text, "\") = Len(.Text) - 1 If bolAllesMarkiert Then .Text = Mid(.Text, 1, InStrRev(Left(.Text, Len(.Text) - 1), "\")) .SelLength = Len(.Text) If Len(.Text) > 0 Then Set .Recordset = GetFoldersAndFiles(.Text) .Dropdown End If KeyCode = 0 Else If bolBackslashErreicht Then .Text = Mid(.Text, 1, InStrRev(Left(.Text, Len(.Text) - 1), "\")) .SelLength = Len(.Text) If Len(.Text) > 0 Then Set .Recordset = GetFoldersAndFiles(.Text) .Dropdown End If KeyCode = 0 End If End If End If End With Case 9 ''Tabulator With Me!cboDateiname If Len(.Text) > 0 Then strFolder = .Text .SelStart = Len(.Text) If objFSO.FolderExists(strFolder) Then If Not Right(strFolder, 1) = "\" Then strFolder = strFolder & "\" End If Else strFolder = Left(strFolder, InStrRev(strFolder, "\")) End If .SelStart = Len(strFolder) If objFSO.FolderExists(strFolder) Then Set .Recordset = GetFoldersAndFiles(strFolder) .Dropdown KeyCode = 0 End If Else Set .Recordset = GetDrives .Dropdown End If End With End Select End Sub
Diese Prozedur prüft in einem Select Case-Konstrukt, ob eine der beiden Tasten mit dem Wert 8 (Löschen) oder 9 (Tabulator) für den Parameter Keycode betätigt wurde.
Reagieren auf die Tabulator-Taste
Wenn der Benutzer die Tabulator-Taste betätigt, soll immer der aktuelle Wert ergänzt werden – soweit es sich dabei um einen gültigen Verzeichnisnamen handelt. Wenn Sie also wie Bild 6. Dazu prüft die Prozedur Form_KeyDown im Select Case-Zweig mit dem Wert 9 zunächst, ob das Kombinationsfeld überhaupt einen Wert enthält. Falls nicht, soll das Kombinationsfeld einfach mit den Laufwerken gefüllt und aufgeklappt werden.
Bild 5: Bei Betätigen der Tabulator-Taste soll dieser Wert ausgewählt werden und das Kombinationsfeld die Einträge der folgenden Ebene anzeigen.
Bild 6: Die Auswahlliste nach Betätigen der Tabulator-Taste
Die Prozedur speichert dann zunächst den aktuell angezeigten Text in der Variablen strFolder und prüft, ob dieser Wert bereits einem vorhandenen Verzeichnis entspricht. Falls ja, testet die Prozedur noch, ob der Ausdruck von einem Backslash beendet wird. Falls nicht, wird dieses Zeichen noch an den aktuellen Ausdruck angehängt. Dieser Ausdruck dient dann als Kriterium für das Erweitern der Liste des Kombinationsfeldes.
Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...
den kompletten Artikel im PDF-Format mit Beispieldatenbank
diesen und alle anderen Artikel mit dem Jahresabo