こんにちは、Ryoです。
普段何気なく扱うファイルやフォルダですが、用途によっては特定のフォルダに対してサブフォルダ内も含めてすべてのファイル名を取得したいようなケースもあるかと思います。この場合はSubFoldersプロパティを利用することで対応できますので、今回はその内容について書いていきます。
1.サンプル概要
サンプルとして以下画像のフォルダを準備しています。「Sample1」フォルダ内にサブフォルダとして「SampleFolder1(5ファイル)」「SampleFolder2(5ファイル)」「SampleFolder3(5ファイル)」、その他テキストファイルが50あります。
同フォルダ内に実行ファイルも保存していますので、その実行ファイルと自動生成されるbakファイルを合わせて「Total 67ファイル」あります。

このSample1フォルダに対し、サブフォルダを含む全ファイルを取得してファイル総数表示とファイル名をセルに書込みます。

また、取得したファイル名からパス情報を除いて書込みたいこともあると思いますので、その手段についても書いていきます。

以上がサンプル概要になります。
2.サンプルコード
'取得したファイル名を保存するコレクション:Fname
Private Fname As Collection
Sub Sample1()
Dim i As Long
'コレクションを作成する
Set Fname = New Collection
'この実行ファイル(ブック)が保存されている
'フォルダ内のファイル名を取得する
' ⇒Sub GetFileList(ByVal fPath As String)
GetFileList ThisWorkbook.Path
'取得したファイル名を現在アクティブなSheetへ
'セルA1から順次下方向へ書込む
For i = 1 To Fname.Count
Cells(i, 1).Value = Fname.Item(i)
Next i
'書込み終了後、総ファイル数をメッセージ表示
MsgBox "総ファイル数:" & Fname.Count
End Sub
Sub GetFileList(ByVal fPath As String)
Dim FSO As Object
Dim tgtFolder As Object
Dim sFolder As Object
Dim fFile As Object
'FileSystemObjectオブジェクトを作成して変数に代入
Set FSO = CreateObject("Scripting.FilesystemObject")
'指定フォルダをFolderオブジェクトとして変数に代入
Set tgtFolder = FSO.GetFolder(fPath)
'全てのフォルダに対して処理を実行する
For Each sFolder In tgtFolder.SubFolders
'取得したフォルダに対しGetFileListを再度実行
GetFileList sFolder.Path
Next
'ファイル名の取得処理
'全てのファイルに対する処理
For Each fFile In tgtFolder.Files
'ファイル名をコレクションに追加する
Fname.Add Item:=fFile.Path
Next
Set FSO = Nothing
End Sub
このサンプルコードでは指定したフォルダ内、及びサブフォルダ内すべてのファイル名を取得しますが、サブフォルダを取得するにはSubFoldersプロパティを利用します。
構文:オブジェクト.SubFolders
このSubFoldersプロパティは指定したフォルダのサブフォルダを取得することができますので、サンプルコードではGetFileListプロシージャ内でPath指定した「Sample1フォルダ(=tgtFolder)」に対して使用することでサブフォルダ「SampleFolder1~3」を取得しています。
サンプルコードの流れとしては、先ず当該モジュールのプロシージャ間で共有するのでPrivateで変数を宣言(Private Fname As Collection)します。
Sample1プロシージャでは保存用のコレクション作成(Set Fname = New Collection)とファイルを取得したPathを指定してGetFileListプロシージャを実行(GetFileList ThisWorkbook.Path)します。
GetFileListプロシージャでは指定されたPathがfPathに引き渡され、その情報を元に指定フォルダをFolderオブジェクトとして変数にセットします。
Set FSO = CreateObject(“Scripting.FilesystemObject”)
Set tgtFolder = FSO.GetFolder(fPath)
後は全てのサブフォルダに対して順次実行していきますので、取得したフォルダ毎に再度GetFileListプロシージャを実行する再起処理を行うことで全てのファイル名を取得しています。
For Each sFolder In tgtFolder.SubFolders
GetFileList sFolder.Path
Next
For Each fFile In tgtFolder.Files
Fname.Add Item:=fFile.Path
Next
GetFileListプロシージャ実行後に再度Sample1プロシージャに戻り、取得したファイル数分繰り返し処理を行いながらセルへ書込んでからメッセージボックスで総ファイル数を表示しています。
For i = 1 To Fname.Count
Cells(i, 1).Value = Fname.Item(i)
Next i
MsgBox “総ファイル数:” & Fname.Count
◆参考:取得したファイル名からパス情報を除く
上のサンプルコードではフルパスで書き込むので視認性が悪いこともありますから、その部分を省きたいような場合はReplace関数を利用します。
Sub Sample2()
'取得したファイル名からPathを除外する
Dim i As Long
Set Fname = New Collection
GetFileList ThisWorkbook.Path
For i = 1 To Fname.Count
'Replace関数を利用
'取得したファイル名(fName)に含まれるPath情報
'(ThisWorkbook.Path & "\")を""(なし)に置換
Cells(i, 1).Value = Replace(Fname.Item(i), _
ThisWorkbook.Path & "\", "")
Next i
'メッセージボックスで除外したPath情報、
'総ファイル数を表示
MsgBox "総ファイル数:" & Fname.Count & vbLf _
& "取得したファイル名から" & vbLf & "「 " & _
ThisWorkbook.Path & "\ 」" & vbLf & _
"を除いてセルに書込んでいます。", vbInformation
End Sub
コメントにも記述していますが、取得したファイル名に含まれるPath情報を””に置換することで除くことが可能です。
その後のメッセージ表示の処理はなくても問題ありませんが、何を除外したかをわかるように表示しているものです。
この辺りの方法を知っておくと何かと役に立つ場面も多いと思います。
3.まとめ
私の場合ですが、意外とファイル名に必要な情報があったりしますので、その対象が膨大な数であったり、複数のフォルダに跨っている場合等では今回のような処理を使ってファイル名の取得や整理を行っています。
この辺りの処理は実際に動作させてみると理解しやすいと思いますので、機会があれば活用などをご検討くださいませ。
以上、サブフォルダを含むすべてのファイルを取得する方法についてでした!今回の記事が何かの参考になれば幸いです。
Ryo

