こんにちは、blueです。
前回は実践編の三回目として365日分のファイルを作成する方法について説明しました。
前回の記事はこちら
今回は再帰処理を使ってフォルダ内の全てのファイルを取得する方法を紹介します。
この方法を使えばフォルダ内の全てのファイルパスを簡単に取得することができ、エクセルの検索機能を使ってファイルを探すことも容易になります
(検索ソフトにあるようなファイルインデックスを取得するような感じです)
なおコード自体は理解しづらいのでできる限り図を使って説明します。理解の助けになれば幸いです。
今回の流れ
今回のコードをフローチャートにすると以下のようになります。
この中の繰り返し作業を「再帰処理」という手法を使って処理していくのが今回のポイントです。
再帰処理とは
再帰処理とは、ある処理の中で「自分自身を呼び出す処理をいれる」ことを指します。
先ほどのループが自分自身の処理を入れていることになります。
普通のループ処理と違うのは
- 自分自身を処理に入れる
- 終了条件を入れる
- 終了条件に向かって処理が進む
ことで少ないコードで深いところまで見れることになります。
この再帰処理はFSO、特にSubFoldersコレクションと相性がよく、次のコードで実行することができます。
実コード
実際のコードは以下になります。
Scripting.Runtimeの参照設定さえしておけばコピペでも可能です。
Dim tRow As Long
Private Sub getFilePath()
Dim FD As FileDialog
Dim FolderName As String
Dim FSO As Scripting.FileSystemObject
Dim objFolder As Scripting.Folder
'グローバル変数の初期化
tRow = 0
'フォルダを作成する場所を指定する(FileDialogとGetFolder)
Set FD = Application.FileDialog(msoFileDialogFolderPicker)
If FD.Show = True Then
FolderName = FD.SelectedItems(1)
Set FSO = New Scripting.FileSystemObject
Set objFolder = FSO.getFolder(FolderName)
Else
Exit Sub
End If
Call getFolder(objFolder)
End Sub
Private Sub getFolder(objFolder As Scripting.Folder)
Dim objFile As Scripting.File
Dim objSubFolder As Scripting.Folder
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1")
For Each objFile In objFolder.Files
ws.Cells(tRow + 1, 1).Value = objFile.Path
tRow = tRow + 1
Next
For Each objSubFolder In objFolder.SubFolders
Call getFolder(objSubFolder)
Next
End Sub
コードの詳細は以降で詳しく説明します。
コードの説明
今回のコードは2つのプロシージャに分かれています。
- (起点となる)フォルダオブジェクトを取得するプロシージャ(Private Sub getFilePath())
- 再帰処理を使って中のファイルとサブフォルダを取得するプロシージャ(Private Sub getFolder(objFolder As Scripting.Folder)
1のパートについてはこれまですでに説明をしました。
フォルダオブジェクトの取得に関する詳しい説明はこちら
2つ目のパートを図で説明すると以下になります。
2つ目のプロシージャはファイルを取得する部分とサブフォルダを取得する部分に分かれています。
この中に自分自身を呼び出す処理としてCall~が入っています。
この処理を繰り返すのが再帰処理になりますが、実際の処理は以下のようになります。
順序は以下の通りです。
- まず⓪(呼び出されたフォルダ=起点となるフォルダに)についてファイルの情報を取得します。
- 次にサブフォルダ①を取得し、「自分自身」を呼び出します。ここで新しいプロシージャが作られていることに注目ください。このプロシージャはもともとあったものとは別のものです。
- 次にこのプロシージャ内で①のフォルダ内のファイル情報を取得するとともにサブフォルダ②を取得します。
- その後「自分自身」を再度呼び出し、サブフォルダ②内のファイルの情報を取得します。②のサブフォルダがなければ、一度①に戻ります。
- その後サブフォルダ③を取得し、また「自分自身」を呼び出します。
その後③のフォルダ、④のフォルダ・・・とサブフォルダがなくなるまで続けて終了となります。
ここでのポイントはSubFoldersコレクションを使って下層のフォルダ情報を取得していることと、そのフォルダに対して処理を繰り返していることです。
これがFSOを使った再帰処理になります。
まとめ
今回は 再帰処理を使ってフォルダ内の全てのファイルを取得する方法を紹介しました 。
コードは少し難しいですが、この方法を使うことでフォルダ内の全てのファイルを簡単に取得することができます。
パスが取得できればエクセルの検索機能を使ってファイルを探すことも容易になるので、業務効率も大きく上がると思います。
次回はこのコードを少し改良して「階層構造化」と「リンクを付与」するようにしていきます。
コメント