Dateiauswahl per Kombinationsfeld

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.

pic001.png

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).

pic002.png

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).

pic004.png

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.

pic003.png

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.

pic005.png

Bild 5: Bei Betätigen der Tabulator-Taste soll dieser Wert ausgewählt werden und das Kombinationsfeld die Einträge der folgenden Ebene anzeigen.

pic006.png

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

Schreibe einen Kommentar