【VBA】フォルダ内のファイル一覧を取得する(サブフォルダ内を含む)

エクセルVBAで使うコードの備忘録。VBAで指定フォルダ内のファイル数をサブフォルダ内も含めてすべて取得するコード。ちなみにサブフォルダを含まず、指定フォルダ内のみのファイルを取得する場合はこちらをご覧ください。

スポンサーリンク

フォルダ一覧を取得する

下部フォルダも含めたすべてのファイルを取得するには、まず指定フォルダ内に存在するサブフォルダ一覧を取得する必要があります(サブフォルダの一覧を取得するコードについてはこちらをご参照ください)。サブフォルダのパスを全て取得することができてしまえば、あとはそれぞれのフォルダに対してファイル一覧を取得してやればOKです。

当たり前ではありますが、サブフォルダ内も含めて含まれるファイル数がどれだけあるのかを取得したい場合には、下記サンプルコードで取得したフォルダパスの要素数(変数であるfileListの要素数)を取得してやればよいです。

なお、サンプルコードを使用する際はカッコに囲まれた部分([***])を自分のプログラムに合わせて変更してください。

サンプルコード

'--- 指定フォルダ内に含まれるすべてのファイルパスを取得 ---'
Public Sub GetAllFilePath()

    '--- ファイル一覧を取得したいフォルダのパス ---'
    Dim folderPath As String
    folderPath = "[フォルダパス]"
    
    '--- サブフォルダのパス一覧を取得 ---'
    Dim folderList As Variant
    folderList = GetFolderPath(folderPath)
    
    '--- 指定フォルダのファイルパスを取得
    Dim fileList() As String
    fileList = GetFileListFso(folderPath)
    
    '--- ファイル数を保存する変数 ---'
    Dim n As Long
    Dim m As Long

    '--- サブフォルダのファイルパスを取得し順次結合する
    Dim tmpList() As String
    Dim i As Long
    Dim s As Variant
    For Each s In folderList
    
        tmpList = GetFileListFso(CStr(s))
        
        n = GetArrayLength(fileList)
        m = GetArrayLength(tmpList)
        
        If (0 < n + m) Then
            ReDim Preserve fileList(1 To n + m)
            For i = 1 To m
                fileList(n + i) = tmpList(i)
            Next i
        End If
    Next s
    
End Sub

'--- 1次元配列の要素数を取得する関数 ---'
Public Function GetArrayLength(vList As Variant) As Long
    
    Dim n As Long
    
    If (IsEmptyArray(vList)) Then
        n = 0
    Else
        n = UBound(vList)
    End If
    
    GetArrayLength = n
    
End Function

'--- フォルダに含まれる(サブフォルダ除く)のファイル一覧を取得する関数 ---'
Public Function GetFileListFso(folderPath As String) As String()
    
    '--- ファイルシステムオブジェクト ---'
    Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")
    
    '--- ファイル数を格納する変数 ---'
    Dim n As Variant
    n = fso.GetFolder(folderPath).Files.Count
    
    If (0 < n) Then
        '--- ファイル名を格納する配列 ---'
        Dim str() As String
        ReDim str(1 To n)
        
        '--- ファイル名を格納 ---'
        i = 1
        Dim f As Object
        For Each f In fso.GetFolder(folderPath).Files
            str(i) = f.Path
            i = i + 1
        Next f
    End If
    
    GetFileListFso = str

End Function

'--- サブフォルダを再帰的に取得する関数 ---'
Public Function GetFolderPath(folderPath As String) As String()
    
    '--- ファイルシステムオブジェクト ---'
    Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")
    
    '--- フォルダ数を格納する変数 ---'
    Dim n As Variant
    n = fso.GetFolder(folderPath).SubFolders.Count
    
    If (0 < n) Then
        '--- フォルダパスを格納する配列 ---'
        Dim str() As String
        ReDim str(1 To n)
        
        '--- フォルダパスを格納 ---'
        Dim i As Long
        Dim j As Long
        Dim m As Long
        i = 1
        Dim strTmp() As String
        
        'フォルダパスを指定してすべてのサブフォルダを取得
        Dim f As Object
        For Each f In fso.GetFolder(folderPath).SubFolders
            str(i) = f.Path
            
            strTmp = GetFolderPath(str(i))  '再帰的呼び出し
            If (Not IsEmptyArray(strTmp)) Then
                m = UBound(strTmp, 1)
            Else
                m = 0
            End If
            
            'サブフォルダ内にさらにフォルダがあればその分だけ配列を拡張
            n = UBound(str, 1)
            ReDim Preserve str(1 To n + m)
            For j = 1 To m
                str(i + j) = strTmp(j)
            Next j
            
            i = i + m + 1
        Next f
    End If
    
    GetFolderPath = str
    
End Function

'--- 配列が空かどうかを判定する関数 ---'
Public Function IsEmptyArray(arrayTmp As Variant) As Boolean
On Error GoTo ERROR_

    If (0 < UBound(arrayTmp, 1)) Then
        IsEmptyArray = False
    End If
    
    Exit Function

ERROR_:
    
    IsEmptyArray = True
    
End Function