Verzeichnis mit Unterordnern auslesen und in ComboBox anzeigen

  • Excel

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von ftzdOp.

    Verzeichnis mit Unterordnern auslesen und in ComboBox anzeigen

    Hallo zusammen,
    ich möchte mittels VBA diverse Unterordner durchsuchen und mir die in diesen Unterordnern befindlichen Excel-Arbeitsmappen in einer ComboBox anzeigen lassen.
    Dazu habe ich folgenden Code eingetragen:

    Visual Basic-Quellcode

    1. Private Sub UserForm_Activate()
    2. Const Dat_PATH As String = "D:\Daten\"
    3. Dim Datei_such As String
    4. ComboBox1.Clear
    5. Datei_such = Dir(Dat_PATH & "\*.xlsx")
    6. Do While Datei_such <> ""
    7. ComboBox1.AddItem sDatei
    8. Datei_such = Dir
    9. Loop
    10. end sub


    Leider bekomme ich so nur die Datein im D:\Daten angezeigt, aber nicht die .xlsx in den Unterordnern.

    Vorab vielen Dank!!!
    Ansatz:
    Du musst den Ordner rekursiv durchsuchen

    Visual Basic-Quellcode

    1. ​Sub Test()
    2. FindFiles "w:\temp", "*.tmp"
    3. End Sub
    4. Sub FindFiles(ByVal Path As String, Optional ByVal Filter As String = "*")
    5. Dim File As Object, Folder As Object, SubFolder As Object
    6. Static FS As Object
    7. If FS Is Nothing Then Set FS = CreateObject("Scripting.FileSystemObject")
    8. Set Folder = FS.GetFolder(Path)
    9. For Each File In Folder.Files
    10. If File.Name Like Filter Then Debug.Print File.Path
    11. Next
    12. For Each SubFolder In Folder.SubFolders
    13. FindFiles SubFolder.Path, Filter
    14. Next
    15. End Sub
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --

    ThorStein83 schrieb:

    aber es erfolgt keine Ausgabe der Daten


    Doch, im Direktbereich:

    Visual Basic-Quellcode

    1. Debug.Print File.Path


    Das musst Du Dir halt so bauen, wie Du es brauchst. Obiges Beispiel, leicht abgeändert.:

    Visual Basic-Quellcode

    1. Sub Test()
    2. Dim MyText_lcl as String
    3. Dim MySplitText_lcl() as String
    4. FindFiles("w:\temp", "*.tmp", MyText_lcl) ' Nun ist alles in der Variable MyText_lcl
    5. MySplitText_lcl = Split(MyText_lcl, ";")
    6. End Sub
    7. Sub FindFiles(ByVal Path As String, Optional ByVal Filter As String = "*", Optional ByRef Return As String)
    8. ' Eigentlich nicht optional, aber wg. der Parameterreihenfolge jetzt mal nötig.
    9. ' Das geht auch anders, aber so siehst Du gleich mal den Unterschied zwischen ByVal und ByRef
    10. Dim File As Object, Folder As Object, SubFolder As Object
    11. Static FS As Object
    12. Dim Return as String
    13. If FS Is Nothing Then Set FS = CreateObject("Scripting.FileSystemObject")
    14. Set Folder = FS.GetFolder(Path)
    15. For Each File In Folder.Files
    16. If File.Name Like Filter Then Return = Return & ";" & File.Path
    17. Next
    18. For Each SubFolder In Folder.SubFolders
    19. FindFiles SubFolder.Path, Filter, Return
    20. Next
    21. End Sub

    Hilfreiche Antworten als solche zu Kennzeichnen wäre klasse 8-)

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „ftzdOp“ ()

    @ftzdOp
    Bitte nicht mit ByRef arbeiten, wenn es auch mit der Rückgabe über einer Funktion gehen würde.
    @ThorStein83
    Ich hätte nicht erwartet, dass du alles bis ins Detail vorgekaut brauchst.

    Visual Basic-Quellcode

    1. Sub FillCombobox()
    2. Dim File
    3. For Each File In FindFiles("D:\Daten", "*.xlsx")
    4. ComboBox1.AddItem File
    5. Next
    6. End Sub
    7. Function FindFiles(ByVal Path As String, Optional ByVal Filter As String = "*", Optional ByVal Internal As Boolean) As Collection
    8. Dim File As Object, Folder As Object, SubFolder As Object
    9. Static FS As Object, Files As Collection
    10. If Files Is Nothing Or Not Internal Then Set Files = New Collection
    11. If FS Is Nothing Then Set FS = CreateObject("Scripting.FileSystemObject")
    12. Set Folder = FS.GetFolder(Path)
    13. For Each File In Folder.Files
    14. If File.Name Like Filter Then Files.Add File.Path
    15. Next
    16. For Each SubFolder In Folder.SubFolders
    17. FindFiles SubFolder.Path, Filter, True
    18. Next
    19. Set FindFiles = Files
    20. End Function
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „petaod“ ()

    ftzdOp schrieb:

    Wegen des pädagogischen Wertes
    Nicht nur aus pädagogischen Gründen.
    Hauptsächlich weil es ungewohnt ist, dass eine übergebene Variable in der Sub verändert wird.
    ByRef-Übergaben sollte man immer gut dokumentieren, um Verwirrungen zu vermeiden.

    Außerdem hast du deinen Code wahrscheinlich nicht getestet.
    1)

    ftzdOp schrieb:

    FindFiles("w:\temp", "*.tmp", MyText_lcl)
    Sub-Aufrufe müssen ohne Klammern erfolgen.

    2)
    Return ist ein reserviertes Statement und kann als Variable nicht verwendet werden.

    3)

    ftzdOp schrieb:

    Sub FindFiles(ByVal Path As String, Optional ByVal Filter As String = "*", Optional ByRef Return As String)
    Dim Return as String
    Du kannst eine Variable nicht mehrfach deklarieren (als Parameter und intern).
    Die zweite Deklaration ist nicht nur überflüssig, sondern wäre auch kontraproduktiv und würde die Rekursion falsch wiedergeben.
    Vergleiche mit meinem Beispiel, wo Files deswegen Static deklariert ist.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --

    petaod schrieb:

    FindFiles("w:\temp", "*.tmp", MyText_lcl)

    Stimmt, nicht getestet. Call setzte ich sonst immer davor. Ich kann es so besser lesen, wenn die Klammern da sind.

    Sollte heißen: Optional ByRef Return_prm As String und das Deklarieren war noch von meiner ersten Version als Funktionsübergabe.
    Aber Du hast recht, etwas mehr Sorgfalt ist besser.
    Hilfreiche Antworten als solche zu Kennzeichnen wäre klasse 8-)

    ftzdOp schrieb:

    Call setzte ich sonst immer davor
    Ja. Dann passt's.


    [OffTopic]
    Ich mag Call aus unerfindlichen Gründen nicht besonders, würde mir aber wünschen, dass VBA sich irgendwann VB.Net annähert und die Klammern auch bei Sub-Aufrufen vorschreibt.

    Oder gleich VB.Net in Excel einbindet.
    Ich freue mich schon auf die vielen Migrationsprojekte... ;)
    [/OffTopic]
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --

    petaod schrieb:

    ftzdOp schrieb:
    Wegen des pädagogischen Wertes

    Nicht nur aus pädagogischen Gründen.
    Hauptsächlich weil es ungewohnt ist, dass


    Die Idee mit ByRef war, dass der TS, einmal den Unterschied zwischen ByRef und ByVal sehen kann. Static hattest Du ja schon demonstriert.

    OT: Viel Spaß beim Migrieren. Wenn Du einen Sidekick gebrauchen kann, dann gib Bescheid ;)
    Hilfreiche Antworten als solche zu Kennzeichnen wäre klasse 8-)