DatenbankManufaktur

Anwendungen so individuell wie Ihr Unternehmen   –   Office- und VBA-Erfahrung seit 1995

FSO gegen Dir(): Und der Gewinner ist

Vor einer Weile habe ich für einen Kunden eine Funktion geschrieben, mit der PDF-Dateien, die bestimmte Nummern im Dateinamen enthalten, in einem nicht indizierten Netzwerkordner ermittelt und an eine Mail anhängt werden. Mit dem FileSystem-Objekt wurden die Dateien im Verzeichnis durchlaufen und der Dateiname auf das Vorkommen der Nummern geprüft. Bei Übereinstimmung wurden sie an die Mail angehängt.

Mit der Zeit gab es immer mehr Dateien im Ordner und die Funktion wurde entsprechend langsamer. Also musste ich mir die Funktion noch einmal angesehen. Die Prüfung auf die Nummern erfolgte (zugegebenermaßen nicht sehr elegant) mit zwei langsamen InStr(). Ich habe sie auf ein wenig Arithmetik und die Left()-Funktion umgestellt. Das hat die Wartezeit immerhin fast halbiert.

Da der weitere Zuwachs an Dateien aber vorhersehbar war und die Suchzeit relativ zur Anzahl ansteigt, musste eine andere Lösung her. Mit einer Suche mit Platzhalterzeichen (Wildcards) könnten die Dateien schnell gefunden werden, aber das FSO kann das leider nicht.

Die allgemein nicht mehr sehr geschätzte Dir()-Funktion kann aber mit Platzhaltern arbeiten. Also habe ich versuchsweise die Suchschleife auf Dir() umgestellt und konnte die Suchzeit drastisch verringern. Erst nach dem Vergrößern des Ordners auf über 5.000 Dokumente konnte ich die Differenz in Sekunden messen: Statt der 46 Sekunden des FSO brauchte die Dir()-Funktion mit Platzhaltersuche nur noch eine Sekunde.

Mein sehr geschätzter Access-Stammtischbruder Martin Asal schreibt im VBA-Tutorial bei "Dateien und Verzeichnisse" z. B.: "Diese Befehle sind eigentlich veraltet. Für einen moderneren, objektbasierten Zugriff gibt es das FileSystemObject.". Dem kann ich jetzt guten Gewissens hinzufügen: Aber unterschätzt mir nicht die guten alten, einfachen Funktionen, denn diese sind manchmal deutlich schneller. Vielleicht sogar, weil Sie nicht so modern und objektorientiert sind?

Und nun zur Anfangsfrage: Was ist nun besser, FSO oder Dir()? Dazu gibt es eine ganz klare Antwort: Es kommt immer darauf an!

Code

Hier der (stark vereinfachte) Code mit etwas vereinfachten Dokumentennamen und ohne Variablen. Der Iif dient im eigentlichen Programm dazu, evtl. angehängte Versionsnummern zu erkennen (die Variable ist im Beispiel – wie anderen Variablen auch – durch eine fixe Zahl ersetzt), da immer nur die neueste Version ermittelt werden soll.

Public Function DirTest()

   Dim objFSO As Object
   Dim objFolder As Object
   Dim objFile As Object
   Dim FolderName As String
   Dim FileName As String
   Dim i As Integer
   Dim j As Integer
   Dim d As Date
   
   ' FSO 1
   d = Now()

   Set objFSO = CreateObject("Scripting.FileSystemObject")
   Set objFolder = objFSO.GetFolder("G:\Test\Dokumente\")
      
   For Each objFile In objFolder.Files
      j = j + 1
      If InStr(objFile.Name, "12345" & IIf(1 = 0, "", "_1")) > 0 _
      And InStr(objFile.Name, "123") > 0 Then
         i = i + 1
      End If
   Next objFile

   Debug.Print "FSO: " & i & " von " & j & " Dateien in " & Format(Now() - d, "nn:ss")
   
   ' Reset
   i = 0
   j = 0
   
   ' FSO 2
   d = Now()
      
   For Each objFile In objFolder.Files
      j = j + 1
      If Left(objFile.Name, Len("123-12345" & IIf(1 = 0, "", "_1"))) _
         = "123-12345" & IIf(1 = 0, "", "_1") Then
         i = i + 1
      End If
   Next objFile

   Debug.Print "FSO: " & i & " von " & j & " Dateien in " & Format(Now() - d, "nn:ss")
   
   ' Reset
   i = 0
   j = 0
   
   ' Dir
   d = Now()

   FolderName = "G:\Test\Dokumente\"
   FileName = Dir(FolderName & "103-64885" & IIf(1 = 0, "", "_1") & "*.pdf")

   Do While FileName <> ""
      i = i + 1
      j = j + 1
      Debug.Print FileName
      FileName = Dir()
   Loop

   Debug.Print "Dir(): " & i & " von " & j & " Dateien in " & Format(Now() - d, "nn:ss")

End Function

Und das ist das Ergebnis:

FSO 1: 4 von 5412 Dateien in 00:46
FSO 2: 4 von 5412 Dateien in 00:28
Dir(): 4 von 4 Dateien in 00:01