Get list of sub-directories in VBA

后端 未结 4 1756
日久生厌
日久生厌 2020-11-22 15:31
  • I want to get a list of all sub-directories within a directory.
  • If that works I want to expand it to a recursive function.

However my initial

4条回答
  •  清歌不尽
    2020-11-22 16:21

    Here is a Simple version without using Scripting.FileSystemObject because I found it slow and unreliable. In particular the .Name method, was slowing everything down. Also I tested this in Excel but I don't think anything I used wouldn't be available in Word.

    First some functions:

    This joins two strings to create a file path, similar to os.path.join in python. It is useful for not needing to remember if you tacked on that "\" at the end of your path.

    Const sep as String = "\"
    
    Function pjoin(root_path As String, file_path As String) As String
        If right(root_path, 1) = sep Then
            pjoin = root_path & file_path
        Else
            pjoin = root_path & sep & file_path
        End If
    End Function
    

    This create a collection of sub items of root directory root_path

    Function subItems(root_path As String, Optional pat As String = "*", _
                      Optional vbtype As Integer = vbNormal) As Collection
        Set subItems = New Collection
        Dim sub_item As String
        sub_item= Dir(pjoin(root_path, pat), vbtype)
        While sub_item <> ""
            subItems.Add (pjoin(root_path, sub_item))
            sub_item = Dir()
        Wend
    End Function
    

    This creates a collection of sub items in directory root_path that including folders and then removes items that are not folders from the collection. And it can optionally remove those nasty . and .. folders

    Function subFolders(root_path As String, Optional pat As String = "", _
                        Optional skipDots As Boolean = True) As Collection
        Set subFolders = subItems(root_path, pat, vbDirectory)
        If skipDots Then
            Dim dot As String
            Dim dotdot As String
            dot = pjoin(root_path, ".")
            dotdot = dot & "."
            Do While subFolders.Item(1) = dot _
            Or subFolders.Item(1) = dotdot
                subFolders.remove (1)
                If subFolders.Count = 0 Then Exit Do
            Loop
        End If
        For i = subFolders.Count To 1 Step -1
            ' This comparison could be replaced by and `fileExists` function
            If Dir(subFolders.Item(i), vbNormal) <> "" Then
                subFolders.remove (i)
            End If
        Next i
    End Function
    

    Finally is the recursive search function based on someone else function from this site that used Scripting.FileSystemObject I haven't done any comparison tests between it and the original. If I find that post again I will link it. Note collec is passed by reference so create a new collection and call this sub to populate it. Pass vbType:=vbDirectory for all sub folders.

    Sub walk(root_path As String, ByRef collec as Collection, Optional pat As String = "*" _
             Optional vbType as Integer = vbNormal)
        Dim subF as Collection
        Dim subD as Collection
        Set subF = subItems(root_path, pat, vbType)
        For Each sub_file In subF
            collec.Add sub_file 
        Next sub_file 
        Set subD = subFolders(root_path)
        For Each sub_folder In subD
            walk sub_folder , collec, pat, vbType
        Next sub_folder 
    End Sub
    

提交回复
热议问题