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