再帰処理とは?フォルダ内のサブフォルダのフォルダ名を全部取得(Excel VBA)

先日お話ししました

指定したフォルダ内のサブフォルダのフォルダ名を全部取得(Excel VBA)

CreateObject(“Scripting.FileSystemObject”) を使ってサブフォルダを取得

の中で、どのようにフォルダの処理を移動していったかをご説明いたします。

使用したプロシージャはこちら。

Sub 指定したフォルダ内のサブフォルダ名全部取得()・・・①
    'アクティブシートから処理対象のフォルダパスを取得し
    'そのフォルダ内のサブフォルダ名を全てアクティブシートに取得
    '【変数】
    Dim ws As Worksheet '処理対象シート
    Dim pt As String '処理対象パス
    Dim t_row As Long 'フォルダ名書出行
    '■変数セット
    Set ws = ActiveSheet '変数ws=アクティブシートをセット
    pt = ws.Range("A3") '変数ptにセルA3のパスをセット
    t_row = 6 'フォルダ名を書き出す初めのセルの行番号をセット
    '■指定したフォルダ内のサブフォルダ名をセルに書き出し
    Call フォルダ名一覧取得(pt, ws, t_row)・・・②
End Sub・・・⑥
Sub フォルダ名一覧取得(pt As String, ws As Worksheet, t_row As Long)・・・③
    Dim FSO As Object 'FileSystemObject
    Dim buf As String 'フォルダ名
    Dim fd As Object 'フォルダ
    buf = Dir(pt & "\" & "*.*", vbDirectory) '変数bufに1個目のフォルダ名を格納
    Do While buf <> "" 'bufが空になるまでDo While内の処理を続ける
        If GetAttr(pt & "\" & buf) And vbDirectory Then '標準ファイルを取得しないために必要
            If buf <> "." And buf <> ".." Then 'ナゾの「.」と「..」を取得しないために必要
                ws.Cells(t_row, 1) = buf 'Cells(t_row, 1)にフォルダ名を書き出し
                t_row = t_row + 1 'フォルダ名を書き出すセルの行番号+1(一つ下の行番号)
            End If
        End If
        buf = Dir() '変数bufに次のフォルダ名を格納(対象データが無い場合は空欄になる)
    Loop
    Set FSO = CreateObject("Scripting.FileSystemObject") 'FileSystemObjectのインスタンス化
    For Each fd In FSO.GetFolder(pt).SubFolders 'サブフォルダ群から1つずつfnに入れて順に処理
        Call フォルダ名一覧取得(fd.Path, ws, t_row) '再帰処理・・・④
    Next fd
    Set FSO = Nothing 'FSOを空っぽにする
End Sub・・・⑤

今回の処理で、指定しているのは「C:\VBA\第1階層」という一番上の階層のパスのみ。

それなのに、サブフォルダ全てのフォルダ名を読み込みにいっています。

それらのことを可能にしているのが「再帰処理」なのです。

「再帰処理」とは、1つのプロシージャが終了していない途中で「自分自身」を呼び出す処理のことなのです。

上記処理でいうと

Sub 指定したフォルダ内のサブフォルダ名全部取得()・・・①

Call フォルダ名一覧取得(pt, ws, t_row)・・・②

Sub フォルダ名一覧取得(pt As String, ws As Worksheet, t_row As Long)・・・③

Call フォルダ名一覧取得(fd.Path, ws, t_row) ‘再帰処理・・・④

Sub フォルダ名一覧取得(pt As String, ws As Worksheet, t_row As Long)・・・③

Call フォルダ名一覧取得(fd.Path, ws, t_row)
‘再帰処理・・・④



といった具合に、「 For Each fd In FSO.GetFolder(pt).SubFolders」で受け取ったサブフォルダが無くなるまでフォルダパスを変更しながら、「自分自身」の処理を繰り返すのです。

■スポンサーリンク

今回のフォルダの処理順は下記の通りです。
(フォルダ図の丸番号と下の説明分の丸番号の意味は異なります。)

「↓↓↓」は、処理対象フォルダのパスです。
文中の丸番号は、上記プロシージャに記載している丸番号のことです。

Sub 指定したフォルダ内のサブフォルダ名全部取得()・・・①

Call フォルダ名一覧取得・・・②

↓↓↓ C:\VBA\第1階層
Sub フォルダ名一覧取得・・・③
 C:\VBA\第1階層内のサブフォルダ「第2階層1」「第2階層2」「第2階層3」を取得

Call フォルダ名一覧取得・・・④
↓↓↓C:\VBA\第1階層\第2階層1

Sub フォルダ名一覧取得・・・③
C:\VBA\第1階層\第2階層1内のサブフォルダ「第3階層1」を取得

Call フォルダ名一覧取得 ・・・④
↓↓↓C:\VBA\第1階層\第2階層1\第3階層1

Sub フォルダ名一覧取得・・・③
C:\VBA\第1階層\第2階層1\第3階層1にフォルダが無いため何も取得せず
↓↓↓「第3階層1」以下にサブフォルダが無いため終了

End Sub・・・⑤
↓↓↓C:\VBA\第1階層\第2階層1(ひとつ前の処理に戻る)

End Sub・・・⑤

↓↓↓C:\VBA\第1階層(ひとつ前の処理に戻る)

Call フォルダ名一覧取得・・・④
↓↓↓C:\VBA\第1階層\第2階層2

Sub フォルダ名一覧取得・・・③
C:\VBA\第1階層\第2階層2内のサブフォルダ「第3階層2」を取得

Call フォルダ名一覧取得・・・④
↓↓↓C:\VBA\第1階層\第2階層2\第3階層2

Sub フォルダ名一覧取得・・・③
C:\VBA\第1階層\第2階層2\第3階層2内にフォルダが無いため何も取得せず
↓↓↓「第3階層2」以下にサブフォルダが無いため終了

End Sub・・・⑤
↓↓↓C:\VBA\第1階層\第2階層2(ひとつ前の処理に戻る)

End Sub・・・⑤

↓↓↓C:\VBA\第1階層(ひとつ前の処理に戻る)

Call フォルダ名一覧取得・・・④
↓↓↓C:\VBA\第1階層\第2階層3

Sub フォルダ名一覧取得・・・③
C:\VBA\第1階層\第2階層3のファイル名を取得

Call フォルダ名一覧取得・・・④
↓↓↓C:\VBA\第1階層\第2階層3\第3階層3

Sub フォルダ名一覧取得・・・③
C:\VBA\第1階層\第2階層3\第3階層3内のサブフォルダ「第3階層3」を取得
↓↓↓「第3階層3」以下にサブフォルダが無いため終了

End Sub・・・⑥

長い道のりでしたね。

【参考】
指定したフォルダ内のファイル名全てを取得(Excel VBA)
変数でよく使われる「buf」「tmp」の意味
Dir関数が取得するファイルの順番
フォルダ内のフォルダ名全てをGetAttrを使って「エラー53 ファイルが見つかりません。」を出さずに取得(Excel VBA)
GetAttrとは?「= vbDirectory」ではなく「And vbDirectory」となるビット演算の疑問
フォルダ名だけを取得したい時に出てくる 「.」 と 「..」 とは?
指定したフォルダ内とサブフォルダ内全てのファイル名を取得(Excel VBA)
CreateObject(“Scripting.FileSystemObject”) を使ってサブフォルダを取得

■スポンサーリンク

■ランキングに参加しています。
↓このブログを気に入っていただけましたら、ポチッとお願いします。
にほんブログ村 IT技術ブログへ
にほんブログ村