VBA(2007もOK)で,ファイルの再帰検索をしよう (Application.FileSearchで複数のブックを処理)
以前,下記のエントリーで,Excel VBAマクロのよく使うコードを列挙した。
ドキュメント作成を楽にするための,Excel VBA 頻出8パターン
http://language-and-engineering.hatenablog.jp/entry/20090401/p1
その中には,
- シート内の全行のスキャン
- ブック内の全シートのスキャン
などの定型処理が含まれていた。
今回はそれに加えて,
- フォルダ内(子フォルダも含め)の全ブックのスキャン
のサンプルコードを掲載する。
Excel2000, 2002, 2003, 2007で動作。
下記のような処理を行なう。
- フォルダ階層をたどって,存在するすべての.xlsファイルを開く。
- それぞれのブックを開いたら,
- A1セルに計算式を書いて
- 保存して
- 閉じる。
Office2007より前のバージョンで
「hoge」というフォルダ内を検索し,発見したすべての.xlsファイルに書き込み。
Sub 全ブックに書き込み() '検索対象のフォルダ openDir = ThisWorkbook.Path & "\hoge" 'ファイルを検索 Dim TargetBook As Workbook With Application.FileSearch .LookIn = openDir .SearchSubFolders = True ' 再帰検索 .Filename = "*.xls" If .Execute() > 0 Then ' 該当ファイルがあれば For i = 1 To .FoundFiles.Count ' シートを開く bookpath = .FoundFiles(i) 'MsgBox bookpath Set TargetBook = Workbooks.Open(bookpath) ' セルを編集 Range("A1").Formula = "=1+1" ' http://officetanaka.net/excel/vba/cell/cell03.htm ' 保存して閉じる TargetBook.Save TargetBook.Close Next i Else MsgBox "ファイルがありません。" End If End With End Sub
上記のコードは,Excel2003などでは正常に実行できる。
しかしExcel2007では Application.FileSearchの所で「オブジェクトはこの動作をサポートしていません」が出る。
残念ながら,この FileSearch 関数は2007では使えなくなったのだ。
Office2007では
なので2007からは,再帰処理を自分で実装する必要がある。
そこで,Application.FileSearchの2007年版として,FileSearch2007を作り,使いまわす事にしよう。
' Application.FileSearchの2007版。 ' フォルダを再帰検索し,マッチしたファイルのパスをコレクションで返す。 ' ' ※利用時にはVBEでツール>参照設定>Microsoft Scripting Runtime にチェックすること。 ' http://blog.livedoor.jp/excelvbamemo/archives/53397448.html Function FileSearch2007(dir_path, target_extention) ' 再帰探索を開始 Set found_files = New Collection Call FileSearch2007_Repeat(dir_path, found_files, target_extention) ' 参照渡し http://www.k1simplify.com/vba/tipsleaf/leaf340.html ' 返り値 Set FileSearch2007 = found_files End Function ' フォルダの再帰で呼び出される関数 Private Sub FileSearch2007_Repeat(dir_path, found_files, target_extention) Set fso = New FileSystemObject Set target_folder = fso.GetFolder(dir_path) ' サブフォルダに再帰 For Each sub_folder In target_folder.SubFolders Call FileSearch2007_Repeat(sub_folder.Path, found_files, target_extention) Next sub_folder ' ファイル For Each objFile In target_folder.Files With objFile ' 検索条件にマッチするか If ((UCase(fso.GetExtensionName(.Path))) = target_extention) Then ' 登録 found_files.Add Item:=.Path ' コレクション http://www.moug.net/tech/exvba/0150076.htm End If End With Next objFile ' このフォルダと子フォルダの処理が終了 Set fso = Nothing End Sub
冒頭のコメントで書いてあるが,参照設定を忘れずに。
使い方は下記のとおり。
Sub 全ブックに書き込み() ' 探索を開始したいフォルダ dir_path = ThisWorkbook.Path & "\hoge" ' 探索したいファイルの拡張子 target_extention = UCase("xlsx") ' 探索 Set found_files = FileSearch2007(dir_path, target_extention) ' 見つかったファイルに対して found_num = found_files.Count If found_num = 0 Then MsgBox "見つかりません" Else MsgBox found_num & "個見つかりました" For i = 1 To found_num ' シートを開く bookpath = found_files(i) 'MsgBox bookpath Set TargetBook = Workbooks.Open(bookpath) ' 編集 Range("A1").Formula = "=1+1" ' 保存して閉じる TargetBook.Save TargetBook.Close ' Excel2007で保存時にアラートを出さないためには,下記の設定を行なうこと ' http://q.hatena.ne.jp/1231912436 Next i End If End Sub
「探索」のところで,上で定義した FileSearch2007 を呼び出している。
なお,保存時の
プライバシーに関する注意:このドキュメントには、マクロ、ActiveXコントロール、XML拡張パックの情報、またはWebコンポーネントが含まれています。これらにはドキュメント検査機能で削除することができない個人情報が含まれる場合があります。
というアラートを出さないように,コメント中の設定を行なっておくこと。
これらを利用すれば,「作成済みのドキュメントを一括書き換え」なども楽にできるだろう。
例えば,全ブックで所属部署を更新する必要が生じたとか。
手動ではやりたくない作業なので,その手の処理はぜひマクロに任せよう。
関連する記事:
UTF8Nの複数テキストを,一斉に置換するバッチ (JScriptでUTF8Nのファイルを読み書き)
http://language-and-engineering.hatenablog.jp/entry/20090723/p1
CSVをExcelファイルに変換するスクリプト (JScript/WSHで,カンマ区切りCSVファイルから.xlsを生成)
http://language-and-engineering.hatenablog.jp/entry/20090718/p1
Rails と Excel VBA で,XMLファイルを読み書きしよう (MSXMLとREXMLの使い方)
http://language-and-engineering.hatenablog.jp/entry/20100323/p1