PR

【VBA】再帰処理により同処理の繰り返しを行う

これで楽に!?VBA活用
記事内に広告が含まれています。

こんにちは、Ryoです。
今回は繰り返し処理における参考例になりますがプロシージャ内で自身のプロシージャを呼び出す処理(=再帰処理)を利用すると同処理を繰り返すような場合は完結に処理できるケースもありますので、その内容について書いていこうと思います。

スポンサーリンク

1.サンプル概要

比較的活用する機会が多いと思われるサブフォルダを含むフォルダ内のファイル名を検索し抽出する簡易的なサンプルになります。

「SampleFolder」内に「Sample01.txt~Sample10.txt」のテキストファイル10ヶ、サブフォルダーの「SubFolderA」「SubFolderB」があります。

「SubFolderA」内には「A_sub01.txt~A_sub10.txt」のテキストファイル10ヶがあります。

「SubFolderB」内にも同様にテキストファイルが10ヶ「B_sub01.txt~B_sub10.txt」を準備しています。

指定フォルダ、及びその指定フォルダ内にある各サブフォルダ毎にファイル検索と抽出を繰り返し、アクティブシートのセル上にそれぞれの結果を書込むサンプルになります。

今回は再帰処理についてなので、上記サンプルのように同じような処理を繰り返す際での扱い方について以下に書いていきます。

2.サンプルコード

Sample1プロシージャで対象フォルダのパスを定数として設定し、FunctionプロシージャSample2に引数として渡します。

Sub Sample1()

 '指定するフォルダのアドレスを定数設定
  Const Path As String = _
  "D:\デスクトップ\SampleFolder"
 
  '結果出力するシートの初期化
  '(数式や文字列のクリア)
  Cells.ClearContents

  'Sample2()の実行
  Call Sample2(Path)
  
End Sub

Sample2ファンクションプロシージャでは渡された引数のPathに対して処理を実行していきます。

Function Sample2(ByVal Path As String)

  Dim buf As String
  Dim fso As Object
  
  '変数bufに指定パス内にあるファイル名を取得
  buf = Dir(Path & "\*.*")
  'アクティブシートのセル左上端を選択
  Cells(1, 1).Select
  
  '取得ファイルが空になるまで繰り返し処理
  Do While buf <> ""
     Do While ActiveCell.Value <> ""
       '入力開始先頭行へ移動
        ActiveCell.Offset(0, 1).Select
     Loop
     'アクティブセルへ取得ファイル名書込み
     ActiveCell.Value = buf
     '下の行へ移動
     ActiveCell.Offset(1, 0).Select
     'Dir関数の引数を省略し次のファイルを検索
     buf = Dir()
  Loop
  
  'FileSystemObjectのGetFolderメソッドを使用
  With CreateObject("Scripting.FileSystemObject")
    '指定フォルダ内のサブフォルダ個々に対して処理
    For Each fso In .GetFolder(Path).SubFolders
       'アクティブシートへの取得サブフォルダー名書込み
       ActiveCell.Offset(1, 1).Value = _
       "↑" & fso.Name
       '取得したサブフォルダーアドレスを引数として
       '自身(Sample2)を呼び出して実行 ※再帰処理
       Sample2 fso.Path
    Next
  End With
  
End Function

最初はSample1より渡されたPathのフォルダ「SampleFolder」に対してDir関数でファイル名を検索・取得して、Do while~Loop文でセルへの書込みを実行しています。

次にサブフォルダを取得していきますので、FileSystemObjectのGetFolderメソッドを使用して指定されたPath内にあるサブフォルダーを取得します。

With CreateObject(“Scripting.FileSystemObject”)
For Each fso In .GetFolder(Path).SubFolders

ここで使用しているFor Each ~は個々のオブジェクトを取り出して処理していくもので、全ての要素に対して処理が終わればループも終了します。またFor Eachのループ終了は再帰処理から抜け出す条件でもあります。

取り出されたオブジェクトのパス情報(サブフォルダーのアドレス)を現在処理を実行しているSample2の引数として設定し、自身を呼び出して再度処理を行っていきます。このようにFunctionプロシージャ内で自分自身のプロシージャを呼び出すことで「再帰処理」を行うことができます。

Sample2 fso.Path

自身を呼び出した次の処理ではサブフォルダーのパス情報になっているので、そのサブフォルダに対して同様の処理が行われ、全てのサブフォルダに対して処理が完了すればFunctionプロシージャSample2が終了⇒Sample1へ制御が戻り、その後終了となります。

一連の動作を簡易的に表すと以下のような流れになります。

3.まとめ

再帰処理を使用することで記述を比較的簡潔に済ますことができることも多いですから、このような手段もあることを知っておくと何かと役に立つことがあります。



今回のサンプルのようなフォルダ/サブフォルダ内の検索に限らず、累計処理や集計処理での繰り返しなどにも利用できると思いますので、何か活用の機会があればご検討くださいませ。

以上、再帰処理により同処理の繰り返し作業を実施する方法についてでした!今回の記事が何かの参考になれば幸いです。

Ryo

タイトルとURLをコピーしました