[ VBA ] 指定フォルダ以下の全フォルダに含まれるファイルの一覧を取得したい

VBAで、あるフォルダの中にあるファイルの一覧を取得したい場合に、どう書けばいいかを解説します。VBAでフォルダの操作をすることはちょくちょくあるのですが、すぐに忘れてしまう自分へのメモです。

事前準備

VBAでフォルダやファイルを扱う場合、FileSystemObjectオブジェクトを使います。まずは、これを扱いやすくするために、参照設定を行います。

Visual Basic Editorを立ち上げ(Alt+F11)、メニューのツール⇒参照設定を選択します。そこから「Microsoft Scripting Runtime」を探し出してチェックを入れます。すると、scrrun.dllへのパスが表示され、参照設定が完了です。

フォルダ内のファイル一覧を取得する

まずは、フォルダを指定したときに、そこに含まれるファイルの一覧を取得してみます。

Sub getFileList()

    Dim fso As New FileSystemObject, myFile As File, myCount As Long

    For Each myFile In fso.GetFolder("C:\").Files

        myCount = myCount + 1
        Cells(myCount, 1) = myFile.Name

    Next

End Sub

この数行で、Cドライブ直下にあるファイル一覧が、A列に表示されます。

Dim fso As New FileSystemObject

の部分で、FileSystemObjectオブジェクトを使えるようにしているんですね。「fso.GetFolder("C:\")」では、GetFolderを使って、指定したフォルダのFolderオブジェクトを取得しています。そして、For Eachの中で各ファイルの名前を取得しています。

なお、参照設定をしていなかった場合は、変数宣言のところを次のように変えないといけません。

Sub getFileList2()

    Dim fso As Object, myFile As Object, myCount As Long

    Set fso = CreateObject("Scripting.FileSystemObject")

    For Each myFile In fso.GetFolder("C:\").Files

        myCount = myCount + 1
        Cells(myCount, 1) = myFile.Name

    Next

End Sub

型がただのObjectになっています。コード補完などが効かないので、不便です。参照設定をするほうが楽になることが分かりますね。

ダイアログで指定したフォルダの中のファイル一覧を取得する

コード内でフォルダを指定するのではなく、マクロを実行するたびにフォルダを選択したいという場合もあるでしょう。そういうときはこのようにします。

Sub getFileListFromDialog()

    Dim fso As New FileSystemObject, myFile As File, myCount As Long

    With Application.FileDialog(msoFileDialogFolderPicker)

        If Not .Show Then Exit Sub

        For Each myFile In fso.GetFolder(.SelectedItems(1)).Files

            myCount = myCount + 1
            Cells(myCount, 1) = myFile.Name

        Next

    End With

End Sub

違っているのは、

With Application.FileDialog(msoFileDialogFolderPicker)

の部分などですね。こう書くと、フォルダを指定するためにダイアログが開きます。このダイアログでフォルダが指定されれば、そのフォルダのパスを「.SelectedItems(1)」で取得し、先ほどと同じ要領でファイルの一覧を取得していきます。

ダイアログでキャンセルボタンが押されたときは、「.Show」に0が返されるので、そのときは「Exit Sub」、つまり、終了するようにしています。

フォルダ一覧も欲しい

フォルダに含まれるファイル名だけでなく、その直下にあるフォルダの一覧も欲しいという場合には、次のようにします。

Sub getFolderAndFileListFromDialog()

    Dim fso As New FileSystemObject, myFolder As Folder, myFile As File, myCount As Long

    With Application.FileDialog(msoFileDialogFolderPicker)

        If Not .Show Then Exit Sub

        For Each myFolder In fso.GetFolder(.SelectedItems(1)).SubFolders

            myCount = myCount + 1
            Cells(myCount, 1) = myFolder.Name

        Next

        For Each myFile In fso.GetFolder(.SelectedItems(1)).Files

            myCount = myCount + 1
            Cells(myCount, 1) = myFile.Name

        Next

    End With

End Sub

追加したところで重要なのは、

For Each myFolder In fso.GetFolder(.SelectedItems(1)).SubFolders

ですね。フォルダ内のフォルダは、「SubFolders」を使って取得します。

指定フォルダ以下の全フォルダに含まれるファイルの一覧を取得したい

あるフォルダ内のファイルだけでなく、そのフォルダに含まれるすべてのフォルダについて、ファイルの一覧が欲しいという場合もあるでしょう。フォルダの数が多いと時間がかかりすぎて固まる可能性があるので注意が必要ですが、次のように書いて「getFolderAndFileListFromDialogMain」を実行すればやりたいことが実現できます。

Sub getFolderAndFileListFromDialogMain()

    With Application.FileDialog(msoFileDialogFolderPicker)

        If Not .Show Then Exit Sub

        Call getFolderAndFileListFromDialogSub(folderPath:=.SelectedItems(1))

    End With

End Sub

Sub getFolderAndFileListFromDialogSub( _
        folderPath As String, Optional myCount As Long = 0)

    Dim fso As New FileSystemObject, myFolder As Folder, myFile As File

    For Each myFile In fso.GetFolder(folderPath).Files

        myCount = myCount + 1
        Cells(myCount, 1) = myFile.Path

    Next

    For Each myFolder In fso.GetFolder(folderPath).SubFolders

        Call getFolderAndFileListFromDialogSub(myFolder.Path, myCount)

    Next

End Sub

サブフォルダ内のファイルリストを作成するために、「フォルダを指定したら、ファイル一覧を作成する」という機能(Subの方)を作りました。これを各サブフォルダごとに呼び出す、という方法をとっています。再帰的にファイル一覧の作成を行っているということです。Mainの方は、リストを作る出発地点のフォルダを指定するのが主な役割となっています。

サブフォルダも対象にするとなると、ファイル名ではなくてファイルのパスまで見ないと意味がなくなってくるので、「myFile.Name」は「myFile.Path」に変えています。

まとめ

書き方自体は難しくなく、決まったことしか書かないのですが、使う場面が限られているのでなかなか覚えられません。ただ、たいていのことはこの記事に書いたことを応用すればできるんじゃないかと思います。

さて、今、ココナラというサービスで、エクセルやVBAの相談を受けつけています。案件によりますが、500円から受け付けています。よろしくお願いします!

エクセルマクロ、エクセル関数のこと、ご相談ください!

前の記事:
[wordpress] 管理画面でカスタム投稿タイプの一覧を「順序」でソートできるようにする
次の記事:
windowsでmecab-pythonを入れるのがとても大変だった(64bit win10, Python 3.6, MeCab 0.996, VC2017)追記あり