【ExcelVBA】【再帰処理】サブフォルダ含めて全てのフォルダ名とファイル名を取得するには

この記事では、サブフォルダ含めて全てのフォルダ名とファイル名を取得する方法についてご説明します。

【動画】サブフォルダ含めて全てのフォルダ名とファイル名を取得する実際の動き

本題に入る前に、まずは次の動画をご覧ください。


まずは指定されたパスの配下にあるすべてのフォルダ名とファイル名を取得してシートに出力します。

シートへの出力が終わったら次は、指定されたパス配下にあるサブフォルダの中を参照しに行きます。

フォルダの中を参照しに行く処理は、サブフォルダ含めて全てのフォルダを対象に繰り返し行います。

マクロ作成の流れ

STEP.1
トップのフォルダ配下全てのフォルダからフォルダオブジェクトを取得する
トップのフォルダ配下全てのフォルダからフォルダオブジェクトを取得します。
STEP.2
フォルダ配下の全てのフォルダ名とファイル名を取得するため、再帰処理を使って繰り返し(For Eachステートメントを使用)行う
フォルダ配下の全てのフォルダ名とファイル名を取得するため、再帰処理を使って繰り返し(For Eachステートメントを使用)行います。

Excelファイルのフォームの例

今回は次のExcelファイルを用意しました。

項番、パス、フォルダ名またはファイル名、種類(フォルダかファイルか)の4つの項目を出力する表と、フォルダ名とファイル名を取得するトップフォルダのパスを入力するセル(黄色のセル)、そして実行ボタンが設置されています。

また、今回は「C:¥work¥10_勉強¥10_VBA関連¥0265¥file」を対象に、サブフォルダ含めて全てのフォルダ名とファイル名を取得します。

「C:¥work¥10_勉強¥10_VBA関連¥0265¥file」配下のフォルダとファイルは下の通りに用意しました。

  1. フォルダ「C:¥work¥10_勉強¥10_VBA関連¥0265¥file」にファイル「temp1.txt」
  2. フォルダ「C:¥work¥10_勉強¥10_VBA関連¥0265¥file」にフォルダ「1」
  3. フォルダ「C:¥work¥10_勉強¥10_VBA関連¥0265¥file」にフォルダ「2」
  4. フォルダ「C:¥work¥10_勉強¥10_VBA関連¥0265¥file」にフォルダ「3」
  5. フォルダ「C:¥work¥10_勉強¥10_VBA関連¥0265¥file¥1」にファイル「data10000.csv」
  6. フォルダ「C:¥work¥10_勉強¥10_VBA関連¥0265¥file¥1」にファイル「test.mdb」
  7. フォルダ「C:¥work¥10_勉強¥10_VBA関連¥0265¥file¥2」にファイル「file.mdb」
  8. フォルダ「C:¥work¥10_勉強¥10_VBA関連¥0265¥file¥2」にファイル「info.pdf」
  9. フォルダ「C:¥work¥10_勉強¥10_VBA関連¥0265¥file¥2」にファイル「Setup.exe」
  10. フォルダ「C:¥work¥10_勉強¥10_VBA関連¥0265¥file¥2」にフォルダ「2_1」
  11. フォルダ「C:¥work¥10_勉強¥10_VBA関連¥0265¥file¥2¥2_1」にファイル「sample.csv」
  12. フォルダ「C:¥work¥10_勉強¥10_VBA関連¥0265¥file¥2¥2_1」にファイル「test_bk.docx」
  13. フォルダ「C:¥work¥10_勉強¥10_VBA関連¥0265¥file¥3」にファイル「DBSQbk.msi」
  14. フォルダ「C:¥work¥10_勉強¥10_VBA関連¥0265¥file¥3」にファイル「sample.exe」
  15. フォルダ「C:¥work¥10_勉強¥10_VBA関連¥0265¥file¥3」にファイル「test_data2.xlsm」
  16. フォルダ「C:¥work¥10_勉強¥10_VBA関連¥0265¥file¥3」にフォルダ「3_1」
  17. フォルダ「C:¥work¥10_勉強¥10_VBA関連¥0265¥file¥3¥3_1」にファイル「data0920.accdb」
  18. フォルダ「C:¥work¥10_勉強¥10_VBA関連¥0265¥file¥3¥3_1」にファイル「pc_A.iso」
「C:¥work¥10_勉強¥10_VBA関連¥0265¥file」配下

「C:¥work¥10_勉強¥10_VBA関連¥0265¥file¥1」配下

「C:¥work¥10_勉強¥10_VBA関連¥0265¥file¥2」配下

「C:¥work¥10_勉強¥10_VBA関連¥0265¥file¥2¥2_1」配下

「C:¥work¥10_勉強¥10_VBA関連¥0265¥file¥3」配下

「C:¥work¥10_勉強¥10_VBA関連¥0265¥file¥2¥3_1」配下

C2の黄色のセルにフォルダ名とファイル名を取得するトップフォルダのパスを入力してマクロを実行すると、トップフォルダ配下にあるサブフォルダ含めて全てのフォルダ名またはファイル名(と項番、パス、種類(フォルダかファイルか))がExcelのシートに出力されます。

コードの例

Option Explicit

Private Sub btn_exec_Click()

    Dim FolderPath  As String       'フォルダのパス
    Dim cnt         As Integer      'カウンタ用変数
    Dim ws          As Worksheet    'ワークシート変数
    
    'シートを取得する
    Set ws = Worksheets("work")
        
    'セルをクリアする
    ws.Range("C5:F30").ClearContents
    
    'フォルダとファイルを検索したいフォルダのトップ階層のパスを取得する
    FolderPath = Worksheets("work").Range("dirPath").Value
    
    'カウンタを初期化する
    cnt = 0
    
    'フォルダとファイルを検索するサブルーチンを呼び出す
    Call fileSearch(FolderPath, cnt)
    
End Sub

Sub fileSearch(FolderPath As String, cnt As Integer)

    Dim SubFolder   As Object       'サブフォルダ用変数
    Dim FileItem    As Object       '取得したファイル用変数
    Dim fso         As Object       'FileSystemObjectのインスタンス用変数
    Dim Folder      As Object       'フォルダ用変数
    Dim FolderItem  As Object       '取得したフォルダ用変数
    Dim ws          As Worksheet    'ワークシート変数
    
    Const bgnRPos As Long = 5       'データ開始行
    
    'シートを取得する
    Set ws = Worksheets("work")
        
    'FileSystemObjectのインスタンスを生成する
    Set fso = CreateObject("Scripting.FileSystemObject")
        
    'GetFolderメソッドを使用して、指定したパスのフォルダを取得する
    Set Folder = fso.GetFolder(FolderPath)
    
    'フォルダ内にあるファイルの数分処理を繰り返す
    For Each FileItem In Folder.Files
        
        '項番をCのセルに出力する
        ws.Range("C" & cnt + bgnRPos).Value = cnt + 1
        
        'ファイルのパスをDのセルに出力する
        ws.Range("D" & cnt + bgnRPos).Value = fso.GetParentFolderName(FileItem.path)
        
        'ファイル名をEのセルに出力する
        ws.Range("E" & cnt + bgnRPos).Value = fso.GetFileName(FileItem.path)
        
        'ファイルであることをFのセルに出力する
        ws.Range("F" & cnt + bgnRPos).Value = "ファイル"
                    
        cnt = cnt + 1

    Next FileItem    
    
    'フォルダ内にあるフォルダの数分処理を繰り返す
    For Each FolderItem In Folder.SubFolders
    
        '項番をCのセルに出力する
        ws.Range("C" & cnt + bgnRPos).Value = cnt + 1
        
        'フォルダのパスをDのセルに出力する
        ws.Range("D" & cnt + bgnRPos).Value = fso.GetParentFolderName(FolderItem.path)
        
        'フォルダ名をEのセルに出力する
        ws.Range("E" & cnt + bgnRPos).Value = fso.GetFileName(FolderItem.path)
        
        'フォルダであることをFのセルに出力する
        ws.Range("F" & cnt + bgnRPos).Value = "フォルダ"
    
        cnt = cnt + 1
    
    Next
        
    'パスのサブフォルダを対象にループする
    For Each SubFolder In Folder.SubFolders
        
        '本サブルーチンを再帰呼び出しする
        Call fileSearch(SubFolder.path, cnt)
        
    Next SubFolder
    
End Sub

注目すべきコード①

最初に見て頂きたいのは16行目です。

    'フォルダとファイルを検索したいフォルダのトップ階層のパスを取得する
    FolderPath = Worksheets("work").Range("dirPath").Value

コードの説明

以上のコードは、フォルダとファイルを検索したいフォルダのトップ階層のパスを取得しているコードです。

フォルダとファイルを検索したいフォルダのトップ階層のパスの取得は、C2の黄色のセルに入力された値のパスから取得します。
※C2の黄色のセルには「dirPath」という名前を付けています。

このフォルダとファイルを検索したいフォルダのトップ階層のパスから、サブフォルダ含めて全てのフォルダ名とファイル名を取得します。

注目すべきコード②

次に見て頂きたいのは22行目です。

    'フォルダとファイルを検索するサブルーチンを呼び出す
    Call fileSearch(FolderPath, cnt)

コードの説明

以上のコードは、フォルダとファイルを検索するサブルーチンを呼び出す処理のコードです。

fileSearchでフォルダとファイルを検索する処理を行い、fileSearchを呼び出すにはC2の黄色のセルに入力されたフォルダとファイルを検索したいフォルダのトップ階層のパスを第1引数に、カウンタ用変数を第2引数を指定して呼び出します。

注目すべきコード③

次に見て頂きたいのは41行目から44行目です。

    'FileSystemObjectのインスタンスを生成する
    Set fso = CreateObject("Scripting.FileSystemObject")
        
    'GetFolderメソッドを使用して、指定したパスのフォルダを取得する
    Set Folder = fso.GetFolder(FolderPath)

コードの説明

以上のコードは、FileSystemObjectのインスタンスを生成し、フォルダとファイルを検索したいフォルダのトップ階層のパスのフォルダを取得する処理のコードです。

FileSystemObjectのインスタンスのGetFolderメソッドに、フォルダとファイルを検索したいフォルダのトップ階層のパスを指定して実行することで、パス内のフォルダ名やファイル名を取得できます。

注目すべきコード④

次に見て頂きたいのは47行目から63行目です。

    'フォルダ内にあるファイルの数分処理を繰り返す
    For Each FileItem In Folder.Files
        
        '項番をCのセルに出力する
        ws.Range("C" & cnt + bgnRPos).Value = cnt + 1
        
        'ファイルのパスをDのセルに出力する
        ws.Range("D" & cnt + bgnRPos).Value = fso.GetParentFolderName(FileItem.path)
        
        'ファイル名をEのセルに出力する
        ws.Range("E" & cnt + bgnRPos).Value = fso.GetFileName(FileItem.path)
        
        'ファイルであることをFのセルに出力する
        ws.Range("F" & cnt + bgnRPos).Value = "ファイル"
                    
        cnt = cnt + 1

    Next FileItem

コードの説明

以上のコードは、フォルダ内のファイル名を取得してシートに出力する処理のコードです。

また、ファイル名だけでなく、項番、パス、種類(「ファイル」の文字列)もシートに出力しています。

コードの詳細

47行目のコードは、フォルダ内のファイルの数分だけ処理を繰り返すForです。

50行目のコードでは、項番をC列のセルに出力しています。

53行目のコードでは、ファイルのパスをD列のセルに出力しています。

56行目のコードでは、ファイル名をE列のセルに出力しています。

59行目のコードでは、「ファイル」の文字列をF列のセルに出力しています。

注目すべきコード⑤

次に見て頂きたいのは66行目から82行目です。

    'フォルダ内にあるフォルダの数分処理を繰り返す
    For Each FolderItem In Folder.SubFolders
    
        '項番をCのセルに出力する
        ws.Range("C" & cnt + bgnRPos).Value = cnt + 1
        
        'フォルダのパスをDのセルに出力する
        ws.Range("D" & cnt + bgnRPos).Value = fso.GetParentFolderName(FolderItem.path)
        
        'フォルダ名をEのセルに出力する
        ws.Range("E" & cnt + bgnRPos).Value = fso.GetFileName(FolderItem.path)
        
        'フォルダであることをFのセルに出力する
        ws.Range("F" & cnt + bgnRPos).Value = "フォルダ"
    
        cnt = cnt + 1
    
    Next

コードの説明

以上のコードは、フォルダ内のフォルダ名を取得してシートに出力する処理のコードです。

また、フォルダ名だけでなく、項番、パス、種類(「フォルダ」の文字列)もシートに出力しています。

コードの詳細

66行目のコードは、フォルダ内のフォルダの数分だけ処理を繰り返すForです。

69行目のコードでは、項番をC列のセルに出力しています。

72行目のコードでは、フォルダのパスをD列のセルに出力しています。

75行目のコードでは、フォルダ名をE列のセルに出力しています。

78行目のコードでは、「フォルダ」の文字列をF列のセルに出力しています。

注目すべきコード⑥

次に見て頂きたいのは85行目から90行目です。

    'パスのサブフォルダを対象にループする
    For Each SubFolder In Folder.SubFolders
        
        '本サブルーチンを再帰呼び出しする
        Call fileSearch(SubFolder.path, cnt)
        
    Next SubFolder

コードの説明

以上のコードは、サブフォルダが存在する間は自分自身のサブルーチンを繰り返し呼び出す再帰処理を行っているコードです。

再帰処理とは、サブルーチンの処理が行われている途中で、強制的に自分自身のサブルーチンを呼び出して再度サブルーチンの最初から処理を行わせることを言います。

強制的に自分自身のサブルーチンを呼び出しているのは88行目です。

        '本サブルーチンを再帰呼び出しする
        Call fileSearch(SubFolder.path, cnt)

88行目でfileSearchが呼び出されると、fileSearchの処理の途中で26行目(fileSearchの最初)から強制的に開始されます。

この再帰処理(fileSearch処理中の再呼び出し)は、85行目のFor文内で繰り返し行われますが、このFor文が終わらないかぎりfileSearchが再度呼び出されます。

なお、For文から抜ける条件は、すべてのサブフォルダの参照が終わることです。(引数にサブフォルダを指定してfileSearchを呼び出す)

すべてのサブフォルダを参照すればFor文を抜けます。

For文から抜ければfileSearchが呼び出されることがなくなるので(再帰処理が行われない)、fileSearchのEnd Subまで処理が進みfileSearchの処理を抜けて、fileSearchの呼び出し元の22行目に遷移します。

そのまま24行目のEnd Subに進んで本マクロは終了となります。

動作確認

Excelファイルのフォームの例」をご覧ください。

最後に

この記事では、サブフォルダ含めて全てのフォルダ名とファイル名を取得する方法についてご説明しました。

あるフォルダ配下のサブフォルダ含めて全てのフォルダ名とファイル名を取得したい場合は本記事を参考に試してみてくださいね。

プログラミングのスキルを習得するなら

プログラミングのスキルを習得したい、今のスキルをもっと高めたい、そう考えているなら「プログラミングスクール」がおすすめです。

プログラミングのスキルの基礎を身につけるなら「TechAcademy」で1週間の無料体験があるので、これで「プログラミングの基礎」を学ぶのにおすすめですよ。

→ TechAcademyの「1週間 無料体験」はこちら