前回はFileSystemObjectを利用して1つのフォルダ内のファイルを検索するコードを検証してみた。
今回は再帰処理を利用して指定フォルダ内だけでなくフォルダ内フォルダの検索を実現してみようと思う。
再帰処理でフォルダ内検索
Dir関数のときと同じように当初は1つだったプロシージャを3つに分割して機能を実現している。
・FileSearch・・・前処理や検索結果のセルへの転記を行う
・FSOSearch・・・前処理やDictionaryオブジェクトに蓄積した検索結果を配列へ変換する
・FSO_Search・・・FSOSearch内で呼び出される。実際のFileSystemObjectでの検索を行う。
FileSearch
Option Explicit Sub FileSearch() Cells.Clear Dim myVar As Variant myVar = FSOSearch("C:\Users\ユーザー名\OneDrive\ドキュメント\", True) If UBound(myVar) <> -1 Then Range("A1").Resize(UBound(myVar), 1).Value = myVar End If End Sub
ここでは次に紹介するFSOSearch関数を呼び出して、検索開始フォルダとサブフォルダ内検索の有無を指定している。
FSOSearch関数は検索結果に関わらず、返り値として配列を返すようにしている。
FSOSearch関数の返り値に対してUbound関数を使用し、返り値が-1(空配列)であれば検索結果が0であるため処理無しとする。
何らかの検索結果がある場合は2次元配列が返ってきているので、セルサイズを合わせて一括で転記している。
FSOSearch関数
'----------------------------------------------------------------------------------- Rem FSOSearch関数 Rem 第1引数 FolderPath:検索対象とするフォルダパスを指定する Rem 第2引数 SubFolderSearch:フォルダ内のサブフォルダ内を検索対象とするかどうか Rem 返り値 見つかったファイルのフルパス一覧を2次元配列として返す。 Rem 1件もファイルが見つからなかった場合は空配列を返す。 Rem 関数内sub FSO_Searchが溜め込んだ検索結果Dictionaryを配列へ転記する '----------------------------------------------------------------------------------- Function FSOSearch(FolderPath As String, SubFolderSearch As Boolean) As Variant Dim myDic As Dictionary Set myDic = New Dictionary FSO_Search FolderPath, SubFolderSearch, myDic Dim myItem As Variant If myDic.Count = 0 Then FSOSearch = Array() Else Dim myVar As Variant Dim i As Long: i = 1 ReDim myVar(1 To myDic.Count, 1 To 1) For Each myItem In myDic.Keys myVar(i, 1) = myItem i = i + 1 Next FSOSearch = myVar End If End Function
FSOSearch関数は次に紹介するFSO_SearchがDictionaryオブジェクトに蓄積した検索結果を配列へと変換して外部へ返す役割を担っている。
FSO_Search
Private Sub FSO_Search(FolderPath As String, SubFolderSearch As Boolean, ByRef FileDictionary As Dictionary) Dim myFSO As FileSystemObject Dim myFolderDic As Dictionary Dim myFile As Variant Set myFSO = New FileSystemObject Set myFolderDic = New Dictionary For Each myFile In myFSO.GetFolder(FolderPath).Files FileDictionary.Add myFile, "" Next Rem サブフォルダー内検索処理 Dim myFolder As Variant If SubFolderSearch = True Then For Each myFolder In myFSO.GetFolder(FolderPath).SubFolders FSO_Search myFolder & "\", SubFolderSearch, FileDictionary Next End If End Sub
本件の中核となるFSO_Search。
実際にFileSystemObjectでファイル・フォルダの検索を行い検索結果をDictionaryオブジェクトへ蓄積していく。
Dir関数とちがい、FolderオブジェクトのFilesプロパティで抽出されたものはファイルであるので、ファイル属性の判定は必要ない。
サブフォルダ以内の検索はFSO_Search内からFSO_Search自身を呼び出す再帰処理で実現している。
まとめ
コード内容についてはファイル属性の判定以外はDir関数を使用したときと何ら変わりがない内容で実現できる。
ファイル属性の判定については現在テストを行っているフォルダでは問題ないが、なにか特殊なフォルダを検索対象にした際に重要な要素になってくるかもしれない。
が、現時点では割愛。
次回はDir関数でもFileSystemObjectでもない別のファイル検索の方法を検証してみようと思います。