【PR】を含みます。

プログラミング

【VBA】ファイル一覧を取得する方法

VBA ファイル一覧を取得する方法

VBAでフォルダ内のファイル一覧を自動取得したいと考えたことはありませんか?

たとえば「PDFの請求書だけ集めたい」「画像だけ抽出したい」といった場面で、手作業の確認は地味に時間がかかります。

この記事では、ファイル一覧を配列で取得する関数と、拡張子で絞り込む方法(ドット有り/無し両対応)をサンプル付きで解説します。

【コピペOK】フォルダ内のファイル一覧を取得するget_files関数

拡張子の指定(フィルタリング)に対応した、フォルダ内ファイル取得用の関数です。

拡張子の指定は "xlsx"".xlsx" のどちらでもOKです。

extensionsを省略(Empty)したり、False / "*" / ""を指定した場合は、拡張子で絞り込まずに全ファイルを取得する設定になります。

「とりあえず全部取得したい」という意図を明確にできるので、指定ミスによる取りこぼしを防げて安心です。

※拡張子を指定する場合は "xlsx" のように「ドット無し」で統一すると分かりやすいです(".xlsx" でもOK)。

Copyをクリックするとコピーできます。

VBA
Copy
Public Function get_files( _
    ByVal folderPath As String, _
    Optional ByVal extensions As Variant = Empty, _
    Optional ByVal getPath As Boolean = True _
) As Variant
    ' folderPath : 対象フォルダのパス
    ' extensions : 取得対象の拡張子(省略/False/"*"/"" なら全件)
    ' getPath : True=フルパス / False=ファイル名のみ
    ' 戻り値 : 取得結果を配列で返す(0件なら Array())
    ' 例外が起きても処理を止めず、最後に Array() を返すためのエラーハンドリング
    On Error GoTo ErrHandler
    Dim fso As Object
    Dim folder As Object
    Dim file As Object
    Set fso = CreateObject("Scripting.FileSystemObject")
    ' フォルダが存在しない場合は空配列を返して終了
    If Not fso.FolderExists(folderPath) Then
        Debug.Print "get_files: Folder not found -> " & folderPath
        get_files = Array()
        Exit Function
    End If
    Set folder = fso.GetFolder(folderPath)
    ' filterEnabled : True=拡張子で絞り込み / False=全件取得
    Dim filterEnabled As Boolean
    ' extDict : 指定された拡張子を格納する辞書(高速に Exists で判定できる)
    Dim extDict As Object
    Set extDict = CreateObject("Scripting.Dictionary")
    extDict.CompareMode = vbTextCompare
    ' 大文字/小文字の違いを無視して比較(JPG と jpg を同じ扱い)
    ' extensions の指定を整形し、絞り込み有無(filterEnabled)と辞書(extDict)を作る
    NormalizeExtensions extensions, filterEnabled, extDict
    ' 取得結果を一時的に入れるバッファ(可変長配列を自前で拡張)
    Dim buffer() As String
    Dim capacity As Long
    Dim count As Long
    capacity = 32
    ReDim buffer(0 To capacity - 1)
    count = 0
    Dim fileExt As String
    For Each file In folder.Files
        If Not filterEnabled Then
            ' 全件取得:パス/ファイル名を条件に応じて追加
            AppendToBuffer buffer, capacity, count, CStr(IIf(getPath, file.Path, file.Name))
        Else
            ' 絞り込み:ファイルの拡張子を取り出す(例:test.xlsx → xlsx)
            fileExt = fso.GetExtensionName(file.Name)
            ' 指定拡張子の辞書に存在するものだけ追加
            If extDict.Exists(fileExt) Then
                AppendToBuffer buffer, capacity, count, CStr(IIf(getPath, file.Path, file.Name))
            End If
        End If
    Next file
    ' 0件なら空配列、1件以上ならサイズをピッタリにして返す
    If count = 0 Then
        get_files = Array()
    Else
        ReDim Preserve buffer(0 To count - 1)
        get_files = buffer
    End If
CleanExit:
    ' オブジェクト解放
    On Error Resume Next
    Set file = Nothing
    Set folder = Nothing
    Set fso = Nothing
    Exit Function
ErrHandler:
    ' エラー時も空配列を返して落ちないようにする
    Debug.Print "get_files error " & Err.Number & ": " & Err.Description & " (folderPath=" & folderPath & ")"
    get_files = Array()
    Resume CleanExit
End Function
Private Sub NormalizeExtensions( _
    ByVal extensions As Variant, _
    ByRef filterEnabled As Boolean, _
    ByVal extDict As Object _
)
    ' 初期値は「絞り込みする」想定(条件によって False に切り替える)
    filterEnabled = True
    ' extensions が省略(Empty)なら全件取得
    If IsEmpty(extensions) Then
        filterEnabled = False
        Exit Sub
    End If
    ' True/False が渡された場合(False なら全件取得として扱う)
    If VarType(extensions) = vbBoolean Then
        If extensions = False Then
            filterEnabled = False
        End If
        Exit Sub
    End If
    ' 配列が渡された場合:要素を1つずつ辞書に追加
    If IsArray(extensions) Then
        Dim v As Variant
        For Each v In extensions
            AddExtensionToDict v, extDict
        Next v
        ' 有効な拡張子が1つも無ければ全件取得に切り替える
        If extDict.Count = 0 Then
            filterEnabled = False
        End If
        Exit Sub
    End If
    ' 文字列が渡された場合辞書に追加
    AddExtensionToDict extensions, extDict
    If extDict.Count = 0 Then
        filterEnabled = False
    End If
End Sub
Private Sub AddExtensionToDict(ByVal extValue As Variant, ByVal extDict As Object)
    ' 空/Null は無視(意味のある拡張子だけを登録する)
    If IsEmpty(extValue) Then Exit Sub
    If IsNull(extValue) Then Exit Sub
    Dim s As String
    s = Trim$(CStr(extValue))
    If s = "" Then Exit Sub
    If s = "*" Then Exit Sub
    ' ".xlsx" のようにドット付きなら外す(辞書は "xlsx" で統一)
    If Left$(s, 1) = "." Then
        s = Mid$(s, 2)
    End If
    s = Trim$(s)
    If s = "" Then Exit Sub
    ' 重複登録を避ける
    If Not extDict.Exists(s) Then
        extDict.Add s, True
    End If
End Sub
Private Sub AppendToBuffer( _
    ByRef buffer() As String, _
    ByRef capacity As Long, _
    ByRef count As Long, _
    ByVal value As String _
)
    ' 配列がいっぱいなら2倍に拡張してから追加
    If count >= capacity Then
        capacity = capacity * 2
        ReDim Preserve buffer(0 To capacity - 1)
    End If
    ' 末尾に追加して件数を増やす
    buffer(count) = value
    count = count + 1
End Sub

get_files関数の使用方法

第一引数のfolderPathにフォルダパスを指定することで、ファイル一覧を配列で取得できます。

第二引数のextensions(拡張子)と第三引数のgetPath(ファイルパスの取得可否)は任意で指定できます。

対象のフォルダにファイルが存在しない場合は、空の配列Array()を返します。

各引数について

  1. folderPath (必須)
    ファイルが格納されているフォルダパスを指定します。

  2. extensions (省略可)
    取得したいファイルの拡張子を指定します。

    複数の拡張子を指定する場合、配列で拡張子を指定します。
    ひとつの拡張子を指定する場合、配列か文字列で拡張子を指定します。
    引数を省略(Empty)した場合は、すべての拡張子が対象となります。
    また "jpg"".jpg" のように、ドット有り/無しはどちらでもOKです。

  3. getPath (省略可)
    ファイル一覧をパスで取得するか、ファイル名のみで取得するかを指定することができます。
    パスで取得する場合、Trueを指定します。
    ファイル名のみを取得する場合、Falseを指定します。
    引数を省略した場合、ファイル一覧をパスで取得します。

【サンプル】get_files関数でフォルダ内のファイル名を取得する

デスクトップの「test」フォルダに格納してあるファイルの一覧を取得してみます。

get_files は、対象が見つからない場合でも Array()(空の配列)を返す設計なので、サンプル側では「文字列が空かどうか」で判定しています。

※ 取得結果が0件の場合は、メッセージ表示のみ行います(結果がある場合のみ一覧を表示します)。

「test」フォルダには以下のファイルが格納されています。

  • test.html
  • test.jpg
  • test.txt
  • test.xlsx
testフォルダファイル一覧

【サンプルコード】ファイル名一覧のパスを取得する

以下のVBAコードを実行することで、指定したフォルダ内のファイルパスを一括で取得できます。

この例では、get_files関数にフォルダパスのみを指定し、すべての拡張子のファイルを取得しています。

  • C:\Users\test\Desktop\test\test.html
  • C:\Users\test\Desktop\test\test.jpg
  • C:\Users\test\Desktop\test\test.txt
  • C:\Users\test\Desktop\test\test.xlsx

Copyをクリックするとコピーできます。

VBA
Copy
Sub sample_get_file_paths()
    'フォルダパス
    Dim folderPath As String
    folderPath = "C:\Users\test\Desktop\test"
    'ファイル一覧を配列で取得(全件)
    Dim fileList As Variant
    fileList = get_files(folderPath)
    '配列で取得したファイル一覧を文字列に変換
    Dim str As String
    Dim file As Variant
    For Each file In fileList
        str = str & file & vbCrLf
    Next file
    '何もなければ表示しない(=見つからない)
    If str = "" Then
        MsgBox "ファイルが見つかりませんでした", vbExclamation
        Exit Sub
    End If
    'ファイル一覧をメッセージボックスに表示
    MsgBox str
End Sub

【サンプルコード】ファイル名のみを取得する

以下のVBAコードを実行することで、指定したフォルダ内のファイル名を簡単に取得できます。

get_files関数の第一引数にフォルダパスを指定、第二引数指定なし、第三引数にFalseを指定しています。

VBA
Copy
Sub sample_get_file_names()
    'フォルダパス
    Dim folderPath As String
    folderPath = "C:\Users\test\Desktop\test"
    'ファイル名のみ取得
    Dim fileList As Variant
    fileList = get_files(folderPath, , False)
    Dim str As String
    Dim file As Variant
    For Each file In fileList
        str = str & file & vbCrLf
    Next file
    If str = "" Then
        MsgBox "ファイルが見つかりませんでした", vbExclamation
        Exit Sub
    End If
    MsgBox str
End Sub

【サンプルコード】拡張子でフィルタリングしファイル名を取得する

以下のVBAコードを実行することで、指定した特定の拡張子を持つファイル名を一度に取得できます。

たとえば、プロジェクトのフォルダ内にあるすべての画像ファイルやHTMLファイルを取得する場合に非常に便利です。

get_files関数の第一引数にフォルダパスを指定、第二引数に複数の拡張子(html、jpg)を配列で指定しています。

  • C:\Users\test\Desktop\test\test.html
  • C:\Users\test\Desktop\test\test.jpg

Copyをクリックするとコピーできます。

VBA
Copy
Sub sample_filter_extensions()
    'フォルダパス
    Dim folderPath As String
    folderPath = "C:\Users\test\Desktop\test"
    '拡張子リスト("jpg" / ".jpg" どちらでもOK)
    Dim extensionList As Variant
    extensionList = Array("html", ".jpg")
    'ファイル一覧を配列で取得(パスで返す)
    Dim fileList As Variant
    fileList = get_files(folderPath, extensionList, True)
    Dim str As String
    Dim file As Variant
    For Each file In fileList
        str = str & file & vbCrLf
    Next file
    If str = "" Then
        MsgBox "ファイルが見つかりませんでした", vbExclamation
        Exit Sub
    End If
    MsgBox str
End Sub

まとめ

今回ご紹介したVBAコードを使えば、フォルダ内のファイル一覧を簡単に取得できます。

拡張子の指定やファイル名・パスの取得方法も柔軟に対応できるので、さまざまな業務で活用できるはずです。

ぜひご自身の作業に合わせてアレンジしてみてください。

-プログラミング
-, ,