[ 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円から受け付けています。よろしくお願いします!