スポンサーリンク
Dir関数とワイルドカードを使ってファイル名を書き出す
前回の記事で述べたが、Excel VBAのDir関数は、たとえば
Dir(“D:\ダウンロード\普通のファイル.xlsx“)
としたなら「普通のファイル.xlsx」とファイル(・フォルダ)名そのものを返すものだ。
そして、指定したファイル・フォルダが存在しなかったら空文字列を返す。
だから、ファイル・フォルダの名前を指定して、それが本当に存在するのかを調べるという用途に使える。
VBAの中で、特定のファイル名とかを指定する時に、それの存在を事前チェックするのに使えるわけだ。
ワイルドカードを使った検索
しかしDir関数が力を発揮するのは、
*(長さゼロも含む任意の文字)
?(1文字)
という、ワイルドカードを使った検索だろう。
?の方を使うことは私はほぼ無いので、*の方に絞って話を進める。
たとえば
Dir(“D:\ダウンロード\*.xls“)
とすると、「D:\ダウンロード\」フォルダの中にある拡張子「.xls」のファイルが何か見付かる。
(なんか以前のExcelでは、xlsという3文字の拡張子を指定すると、xlsxとかxlsmとか4文字の拡張子まで検索に引っかかったらしいが、今はそんな挙動は確認できなかった)
何か見付かるという書き方をしたわけだが、本当に何か1つのファイル・フォルダが見付かるだけなので、それで終わっても何の役にも立たないだろう。
このワイルドカード*を使った検索は、フォルダやファイルを片っ端から全部検索していくといった用途に使えるものであり、そのためにはループ処理を掛けることになる。
Dir関数の特性を生かしたループ処理
そこで大事なことだが、Dir関数は、最初の1回は引数を指定する必要があるが、2回目以降は引数を指定すれば直前の検索動作を繰り返し実行するということだ。
たとえば
Debug.Print Dir
Debug.Print Dir
Debug.Print Dir
Debug.Print Dir
とすると、2行目以降の単なるDirは、1行目の
Debug.Print Dir(“D:\ダウンロード\*.xlsx”)
を繰り返し実行していることになり、拡張子xlsxのファイルを繰り返し検索しているわけだ。
そしてDir関数では、全てのExcelファイルを検索したいといった使い道が多いはずなので、Dir関数でそういう目的のファイルが見付からなくなるまでループを掛けるという処理を記述すれば良い。
VBAのループ文となると通常はForだが、このDir関数については、検索結果が品切れするまで繰り返すということなのでDo~Loopで良いだろう。
だから、「D:\ダウンロード\」フォルダ内のExcelファイル=拡張子に「xls」文字を含むファイルを全て書き出すマクロとなると、次のような感じになる。
1 2 3 4 5 6 7 8 9 10 11 12 |
Dim str As String Dim i As Long 'フォルダ内のExcelファイルを検索 str = Dir("D:\ダウンロード\*.xls*") Do While str <> "" i = i + 1 Cells(i, 1).Value = str '最初に実行したDir処理を繰り返す str = Dir Loop |
サブフォルダを書き出してみる
同様に、フォルダを片っ端から検索する場合には、Dir関数の属性にvbDirectoryを指定すれば良いのだが、ファイルの場合とは違う点がある。
ファイル検索の時と同様に
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Dim str As String Dim i As Long '検索するフォルダのパスを指定 Const strMainFolder As String = "D:\ダウンロード\" 'フォルダを検索 str = Dir(strMainFolder, vbDirectory) Do While str <> "" i = i + 1 Cells(i, 1).Value = str '最初に実行したDir処理を繰り返す str = Dir Loop |
とすれば全てのフォルダを検索できるのだが、フォルダだけでなくファイルまで全て検索されてしまうのは前回述べた通りだ。
しかもこの場合、「.」「..」という訳の分からない2つのものも抽出されてしまう。
これは以前の記事で少し述べたが、
「.」なら自フォルダ
「..」なら1つ上のフォルダ
を示す。
もちろん、こんな妙なものは普通は排除しなければならない。
ということで、まずファイル・フォルダが両方見付かる中から「フォルダ」属性のものを見付けるが、これは以前に紹介したGetAttr関数で行う。
そして「.」「..」の2つを除く処理はストレートに記述する。
以上をまとめると、サブフォルダを一覧に書き出すマクロは次のようになる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
Dim str As String Dim i As Long Dim attr As Long '検索するフォルダのパスを指定 Const strMainFolder As String = "D:\ダウンロード\" 'フォルダを検索 str = Dir(strMainFolder, vbDirectory) Do While str <> "" '属性取得 attr = GetAttr(strMainFolder & str) If (attr And vbDirectory) = vbDirectory Then 'フォルダか If str <> "." And str <> ".." Then '自フォルダ・1つ上のフォルダでないか i = i + 1 Cells(i, 1).Value = str End If End If '最初に実行したDir処理を繰り返す str = Dir Loop |
うん、とても面倒だ。
Dir関数はこのように、属性を指定できる割に別途GetAttr関数を併用しないといけなかったりで、どうにも不便なことが大きい。
これなら、FileSystemObjectというやつが、多機能で便利なことが多いんじゃないかと思う。
FileSystemObjectについては、内容が多くなるけど、また今度書いてみようと思う。
Dir関数も、前回述べたようなファイルの有無を調べる簡易的用途なら、普通に使えるんだけどね。
スポンサーリンク