Lektionen/Werkzeugkasten

Dateien & Ordner mit dem FileSystemObject

Fortgeschritten10 Min. Lesezeit

Früher oder später muss deine Access-Anwendung raus aus der Datenbank und ran ans Dateisystem: einen Exportordner anlegen, eine CSV einlesen, ein Backup kopieren, alte Protokolldateien wegräumen. Das komfortabelste Werkzeug dafür ist das FileSystemObject (kurz FSO) aus der Microsoft Scripting Runtime.

Verweis setzen oder spät binden

Es gibt zwei Wege, das FSO zu nutzen.

Früh gebunden (mit Verweis) — im VBE unter Extras → Verweise → „Microsoft Scripting Runtime" anhaken. Dann bekommst du IntelliSense und kannst sauber typisieren:

Dim fso As Scripting.FileSystemObject
Set fso = New Scripting.FileSystemObject

Spät gebunden (ohne Verweis) — kein Häkchen nötig, dafür kein IntelliSense. Ideal, wenn du die Datenbank an viele Rechner weitergibst:

Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")

Für weitergegebene Datenbanken ist CreateObject die robustere Wahl: Ein fehlender oder verschobener Verweis führt sonst beim Kunden zu „Fehler beim Kompilieren". In den Beispielen unten nutzen wir späte Bindung.

Existiert das schon? FileExists und FolderExists

Bevor du etwas anlegst, kopierst oder löschst, prüfst du die Existenz — das erspart dir Laufzeitfehler:

Public Sub PruefePfade()
    Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")

    If fso.FolderExists("C:\Export") Then
        Debug.Print "Ordner ist da."
    Else
        Debug.Print "Ordner fehlt."
    End If

    If fso.FileExists("C:\Export\kunden.csv") Then
        Debug.Print "Datei gefunden."
    End If

    Set fso = Nothing
End Sub

Ordner anlegen

CreateFolder erzeugt einen Ordner. Achtung: Es legt nur eine Ebene an und wirft einen Fehler, wenn der Ordner schon existiert — deshalb immer vorher prüfen:

Public Sub OrdnerSicherstellen(ByVal pfad As String)
    Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")

    If Not fso.FolderExists(pfad) Then
        fso.CreateFolder pfad
        Debug.Print "Angelegt: "; pfad
    End If

    Set fso = Nothing
End Sub

Kopieren, Verschieben, Löschen

Drei Methoden decken den Alltag ab. Alle arbeiten direkt mit Pfaden:

Public Sub DateiOperationen()
    Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")

    ' Kopieren – letzter Parameter True = vorhandene Datei überschreiben
    fso.CopyFile "C:\Daten\quelle.xlsx", "C:\Backup\quelle.xlsx", True

    ' Verschieben (= umbenennen, wenn nur der Name anders ist)
    fso.MoveFile "C:\Export\temp.csv", "C:\Export\fertig.csv"

    ' Löschen – zweiter Parameter True = auch schreibgeschützte Dateien
    If fso.FileExists("C:\Export\alt.log") Then
        fso.DeleteFile "C:\Export\alt.log", True
    End If

    Set fso = Nothing
End Sub

MoveFile und DeleteFile scheitern mit Laufzeitfehler, wenn die Zieldatei gesperrt ist (z. B. in Excel geöffnet) oder nicht existiert. In Produktivcode gehört hier eine On Error-Behandlung dazu.

Textdatei schreiben

Zum Schreiben öffnest du einen TextStream. CreateTextFile legt eine neue Datei an (zweiter Parameter True = überschreiben), WriteLine schreibt eine Zeile inklusive Zeilenumbruch:

Public Sub LogSchreiben()
    Dim fso As Object, ts As Object
    Set fso = CreateObject("Scripting.FileSystemObject")

    Set ts = fso.CreateTextFile("C:\Export\log.txt", True)
    ts.WriteLine "Start: " & Now
    ts.WriteLine "Datensätze verarbeitet: 42"
    ts.Close                       ' Puffer leeren – Datei erst dann vollständig

    Set ts = Nothing
    Set fso = Nothing
End Sub

Willst du an eine bestehende Datei anhängen statt zu überschreiben, nutzt du OpenTextFile mit dem Modus 8 (ForAppending):

' 8 = ForAppending, True = anlegen falls nicht vorhanden
Set ts = fso.OpenTextFile("C:\Export\log.txt", 8, True)
ts.WriteLine "Weiterer Eintrag: " & Now
ts.Close

Textdatei zeilenweise lesen

Zum Lesen öffnest du die Datei im Modus 1 (ForReading) und läufst mit ReadLine bis AtEndOfStream durch:

Public Sub CsvEinlesen()
    Dim fso As Object, ts As Object
    Set fso = CreateObject("Scripting.FileSystemObject")

    If Not fso.FileExists("C:\Export\kunden.csv") Then Exit Sub

    Set ts = fso.OpenTextFile("C:\Export\kunden.csv", 1)  ' 1 = ForReading

    Do Until ts.AtEndOfStream
        Dim zeile As String
        zeile = ts.ReadLine

        Dim felder() As String
        felder = Split(zeile, ";")
        Debug.Print "Name: " & felder(0) & " | Ort: " & felder(1)
    Loop

    ts.Close
    Set ts = Nothing
    Set fso = Nothing
End Sub

Die drei Öffnungsmodi im Überblick:

KonstanteWertBedeutung
ForReading1Lesen
ForWriting2Neu schreiben (überschreibt)
ForAppending8Anhängen

Über alle Dateien eines Ordners iterieren

Mit GetFolder bekommst du ein Ordner-Objekt, dessen Files-Auflistung du durchläufst. Jedes File-Objekt kennt Name, Path, Size und DateLastModified:

Public Sub AlleCsvVerarbeiten()
    Dim fso As Object, ordner As Object, f As Object
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set ordner = fso.GetFolder("C:\Export")

    For Each f In ordner.Files
        If LCase(fso.GetExtensionName(f.Name)) = "csv" Then
            Debug.Print f.Name; " – "; f.Size; " Bytes – "; f.DateLastModified
        End If
    Next f

    Set ordner = Nothing
    Set fso = Nothing
End Sub

Analog gibt dir ordner.SubFolders alle Unterordner.

Die schlanke Alternative: Dir()

Für einfache Fälle brauchst du das FSO gar nicht — die eingebaute Funktion Dir() liefert Dateinamen passend zu einem Muster. Beim ersten Aufruf übergibst du den Pfad, danach rufst du Dir() ohne Argument für den nächsten Treffer auf:

Public Sub DirBeispiel()
    Dim datei As String
    datei = Dir("C:\Export\*.csv")

    Do While datei <> ""
        Debug.Print datei
        datei = Dir            ' nächster Treffer
    Loop
End Sub

Dir() ist schnell und verweisfrei, kennt aber keine Datei-Eigenschaften wie Größe oder Änderungsdatum und lässt sich nicht schachteln. Sobald du mehr willst als reine Namen, greifst du zum FileSystemObject.

Zusammengefasst

  • FSO per CreateObject("Scripting.FileSystemObject") (spät gebunden, robust) oder per Verweis auf Microsoft Scripting Runtime (mit IntelliSense).
  • Vor jeder Aktion mit FileExists/FolderExists prüfen — das verhindert Laufzeitfehler.
  • CopyFile, MoveFile, DeleteFile für Dateioperationen; CreateFolder legt nur eine Ebene an.
  • Textdateien über OpenTextFile/CreateTextFile mit ReadLine/WriteLine; Modi 1/2/8 für Lesen/Schreiben/Anhängen, und immer Close nicht vergessen.
  • Über GetFolder(...).Files iterierst du samt Eigenschaften; Dir() ist die schlanke Alternative für reine Namenslisten.
Nächste Lektion
DAO-Recordsets: Daten lesen & schreiben