先日お話ししました
指定したフォルダ内のサブフォルダのフォルダ名を全部取得(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 fd As String 'フォルダ名 Dim s_fd As Object 'サブフォルダ fd = Dir(pt & "\" , vbDirectory) '変数fdに1個目のフォルダ名を格納 Do While fd <> "" 'fdが空になるまでDo While内の処理を続ける If GetAttr(pt & "\" & fd) And vbDirectory Then '標準ファイルを取得しないために必要 If fd <> "." And fd <> ".." Then 'ナゾの「.」と「..」を取得しないために必要 ws.Cells(t_row, 1) = fd 'Cells(t_row, 1)にフォルダ名を書き出し t_row = t_row + 1 'フォルダ名を書き出すセルの行番号+1(一つ下の行番号) End If End If fd = Dir() '変数fdに次のフォルダ名を格納(対象データが無い場合は空欄になる) Loop Set FSO = CreateObject("Scripting.FileSystemObject") 'FileSystemObjectのインスタンス化 For Each s_fd In FSO.GetFolder(pt).SubFolders '変数s_fdに対象フォルダ内のサブフォルダを順に取得 Call フォルダ名一覧取得(s_fd.Path, ws, t_row) '再帰処理 ’・・・④ Next s_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 フォルダ名一覧取得(s_fd.Path, ws, t_row) ‘再帰処理・・・④
↓
Sub フォルダ名一覧取得(pt As String, ws As Worksheet, t_row As Long)・・・③
↓
Call フォルダ名一覧取得(s_fd.Path, ws, t_row) ‘再帰処理・・・④
・
・
・
といった具合に、「 For Each s_fd In FSO.GetFolder(pt).SubFolders」で受け取ったサブフォルダが無くなるまでフォルダパスを変更しながら、③→④→③→④→③→④と「自分自身」の処理を繰り返すのです。
フォルダの処理順
今回のフォルダの処理順は下記の通りです。
フォルダ図の丸番号と下記「プロシージャ内の処理順と処理対象フォルダのパス」の丸番号の意味は異なります。
プロシージャ内の処理順と処理対象フォルダのパス
「↓↓↓」は、処理対象フォルダのパスです。
「★」はフォルダ名取得処理です。
文中の丸番号は、上記プロシージャに記載している丸番号のことです。
Sub 指定したフォルダ内のサブフォルダ名全部取得()・・・①
Call フォルダ名一覧取得(pt, ws, t_row) ‘・・・②
↓↓↓ 「pt」→C:\VBA\第1階層→「pt」として受け取り
Sub フォルダ名一覧取得(pt As String, ws As Worksheet, t_row As Long) ‘・・・③
★ C:\VBA\第1階層 内のサブフォルダ「第2階層1」「第2階層2」「第2階層3」を取得
Call フォルダ名一覧取得(s_fd.Path, ws, t_row) ‘再帰処理 ’・・・④
↓↓↓「s_fd.Path」→C:\VBA\第1階層\第2階層1→「pt」として受け取り
Sub フォルダ名一覧取得(pt As String, ws As Worksheet, t_row As Long) ‘・・・③
★C:\VBA\第1階層\第2階層1 内のサブフォルダ「第3階層1」を取得
Call フォルダ名一覧取得(s_fd.Path, ws, t_row) ‘再帰処理 ’・・・④
↓↓↓「s_fd.Path」→C:\VBA\第1階層\第2階層1\第3階層1→「pt」として受け取り
Sub フォルダ名一覧取得(pt As String, ws As Worksheet, t_row As Long) ‘・・・③
★C:\VBA\第1階層\第2階層1\第3階層1 内にフォルダが無いため何も取得せず
↓↓↓「第3階層1」以下にサブフォルダが無いため終了
End Sub ‘・・・⑤
↓↓↓「pt」→C:\VBA\第1階層\第2階層1(ひとつ前の処理の For Each に戻る)
End Sub ‘・・・⑤
↓↓↓「pt」→C:\VBA\第1階層(ひとつ前の処理の For Each に戻る)
Call フォルダ名一覧取得(s_fd.Path, ws, t_row) ‘再帰処理 ’・・・④
↓↓↓「s_fd.Path」→C:\VBA\第1階層\第2階層2→「pt」として受け取り
Sub フォルダ名一覧取得(pt As String, ws As Worksheet, t_row As Long) ‘・・・③
★ C:\VBA\第1階層\第2階層2 内のサブフォルダ「第3階層2」を取得
Call フォルダ名一覧取得(s_fd.Path, ws, t_row) ‘再帰処理 ’・・・④
↓↓↓「s_fd.Path」→C:\VBA\第1階層\第2階層2\第3階層2→「pt」として受け取り
Sub フォルダ名一覧取得(pt As String, ws As Worksheet, t_row As Long) ‘・・・③
★C:\VBA\第1階層\第2階層2\第3階層2 内にフォルダが無いため何も取得せず
↓↓↓「第3階層2」以下にサブフォルダが無いため For Each を抜ける
End Sub ‘・・・⑤
↓↓↓「pt」→C:\VBA\第1階層\第2階層2(ひとつ前の処理の For Each に戻る)
End Sub ‘・・・⑤
↓↓↓「pt」→C:\VBA\第1階層(ひとつ前の処理の For Each に戻る)
Call フォルダ名一覧取得(s_fd.Path, ws, t_row) ‘再帰処理 ’・・・④
↓↓↓「s_fd.Path」→C:\VBA\第1階層\第2階層3→「pt」として受け取り
Sub フォルダ名一覧取得(pt As String, ws As Worksheet, t_row As Long) ‘・・・③
★C:\VBA\第1階層\第2階層3内 のサブフォルダ「第3階層3」を取得
Call フォルダ名一覧取得(s_fd.Path, ws, t_row) ‘再帰処理 ’・・・④
↓↓↓「s_fd.Path」→C:\VBA\第1階層\第2階層3\第3階層3→「pt」として受け取り
Sub フォルダ名一覧取得(pt As String, ws As Worksheet, t_row As Long) ‘・・・③
★C:\VBA\第1階層\第2階層3\第3階層3 内にフォルダが無いため何も取得せず
↓↓↓「第3階層3」以下にサブフォルダが無いため For Each を抜ける
End Sub ‘・・・⑤
↓↓↓「pt」→C:\VBA\第1階層(ひとつ前の処理の For Each に戻る)
End Sub ‘・・・⑤
End Sub ‘・・・⑥
長い道のりでしたね。
【参考】
指定したフォルダ内のファイル名全てを取得(Excel VBA)
変数でよく使われる「buf」「tmp」の意味
Dir関数が取得するファイルの順番
指定したフォルダ内のフォルダ名全てをGetAttrを使って「エラー53 ファイルが見つかりません。」を出さずに取得(Excel VBA)
GetAttrとは?「= vbDirectory」ではなく「And vbDirectory」となるビット演算の疑問
フォルダ名だけを取得したい時に出てくる 「.」 と 「..」 とは?
指定したフォルダ内とサブフォルダ内全てのファイル名を取得(Excel VBA)
CreateObject(“Scripting.FileSystemObject”) を使ってサブフォルダを取得
再帰処理とは?フォルダ内とサブフォルダ内全てのファイル名を取得(Excel VBA)
指定したフォルダ内のサブフォルダのフォルダ名を全部取得(Excel VBA)
再帰処理とは?フォルダ内のサブフォルダのフォルダ名を全部取得(Excel VBA)
参照渡し「ByRef」と値渡し「ByVal」の違い(Excel VBA)
ファイルのフルパスからファイル名のみを取得 InStrRev関数(Excel VBA)
指定したフォルダの全ての階層のフォルダ名・サブフォルダ名・ファイル名を取得(Excel VBA)
FileSystemObjectとは?CreateObject 関数 FolderExists・GetFolderの使い方
FileSystemObject CreateObject関数を使う方法・ 参照設定を使う方法 違いを理解してエラー防止
再帰処理とは?指定したフォルダの全ての階層のフォルダ名・サブフォルダ名・ファイル名を取得(Excel VBA)
ファイルのフルパスからファイル名のみを取得 Split関数(Excel VBA)
Callステートメントとは 引数 括弧()の使い方(Excel VBA)
指定したフォルダ内から「特定の文字を含まないファイル名」を取得(Excel VBA)
ワイルドカードとは。使い方いろいろ。(Excel)
Dir関数の使い方。ファイル名やフォルダ名の取得方法。(Excel VBA)
指定したフォルダのファイル名を取得し、そのファイル名を一括で変換(Excel VBA)
Excel起動時に「コンパイルエラー」。64ビット システムで Declareステートメントに、PtrSafe属性を設定(Excel VBA )
「ファイルを開く」ダイアログボックス から ファイル名を取得(Excel VBA)
「ファイルを開く」ダイアログボックス から 複数 ファイル名を取得(Excel VBA)
指定フォルダ内のサブフォルダ全てをフォルダ構成のみ(空フォルダ)を別フォルダにコピー(Excel VBA)
再帰処理とは?指定フォルダ内のサブフォルダ全てをフォルダ構成のみ(空フォルダ)を別フォルダにコピー(Excel VBA)