みなさん、こんにちは!
タカハシ(@ntakahashi0505)です。
エクセルVBAでファイルやフォルダを取り合う使う方法についてお伝えしています。
前回はこちらの記事。
フォルダ内のファイル一覧を表示する方法についてお伝えしました。
ファイル一覧ができるなら、フォルダ一覧もできるのでは…?
そうなんです、Dir関数を使えばフォルダ一覧の出力もお手のもの。少しファイル一覧よりもテクニックが必要ですが。
ということで、エクセルVBAでDir関数を使ってフォルダ一覧を表示する方法についてお伝えします。
では、行ってみましょう!
Dir関数でフォルダや他の属性ファイルを返す
Dir関数の書き方は
でしたね。
前回の記事では、この属性を省略していたために既定値である標準ファイルのうちパターンマッチしたファイルを返していたんです。
ですから、属性としてフォルダや他の属性ファイルを指定すれば、それらのパターンマッチを返してくれます。
属性に使用できるVB定数には、以下の種類があります。
定数 | 値 | 説明 |
---|---|---|
vbNormal | 0 | 標準ファイル(既定値) |
vbReadOnly | 1 | 読み取り専用ファイル |
vbHidden | 2 | 隠しファイル |
vbSystem | 4 | システム ファイル |
vbVolume | 8 | ボリューム ラベル |
vbDirectory | 16 | フォルダ |
vbAlias | 64 | エイリアス ファイル |
標準ファイル、読み取り専用ファイル、フォルダ以外はあんまり使わないですかね。かろうじて隠しファイルを使うときがあるかも知れませんが。
今回はフォルダが目当てですので、vbDirectoryを使っていきます。
お題:フォルダ内のサブフォルダ一覧を出力したい
例えば、「C:\Users\Noriaki\Dropbox\40_ブログ\vba-file-dir\開くファイル\」内が以下のようなサブフォルダとファイルで構成されているとします。
フォルダは「pdf」「xlsx」の二つですね。
このフォルダたちをイミディエイトウィンドウに出力するプログラムを作っていきたいと思います。
Dir関数でパターンにマッチしたフォルダを表示する
まず、サブフォルダを一つだけイミディエイトウィンドウに出力してみます。
以下のプログラムを実行してみましょう。
Sub Dir関数でフォルダ一覧()
Dim strPattern As String
strPattern = "C:\Users\Noriaki\Dropbox\40_ブログ\vba-file-dir\開くファイル\"
Debug.Print Dir(strPattern, vbDirectory)
End Sub
「C:\Users\Noriaki\Dropbox\40_ブログ\vba-file-dir\開くファイル\」フォルダ内のパターンにマッチした中で最初のフォルダがイミディエイトウィンドウに出力されるはずです。
…おや?
なんでしょう、この豆粒は?
実は、この出力は間違いではないのでご安心下さい。
このピリオド「.」は、その「自分自身のフォルダ」を表していて、カレントフォルダと言います。
Dir関数はパターンマッチしたフォルダとしてカレントフォルダも対象にするんです。ただ、カレントフォルダはサブフォルダではないので、除外しなくてはいけませんね。
Dir関数でパターンにマッチした複数のフォルダを表示する
カレントフォルダのことはいったん置いておいて、続いて以下プログラムを実行してみましょう。
Sub Dir関数でフォルダ一覧()
Dim strPattern As String, strFolder As String
strPattern = "C:\Users\Noriaki\Dropbox\40_ブログ\vba-file-dir\開くファイル\"
strFolder = Dir(strPattern, vbDirectory)
Do While Len(strFolder) > 0
Debug.Print strFolder
strFolder = Dir()
Loop
End Sub
Dir関数を引数なしで繰り返すと、同じパターンマッチの次の対象を返すんでしたね。
これを実行すると、以下のような出力が得られます。
一応目当ての「pdf」「xlsx」が表示されましたが、いくつか問題がありますね。
まず、ピリオド二つ「..」ですが、これはカレントフォルダの一つ上の階層のフォルダを表していて「親フォルダ」といいます。
これもDir関数は対象として返しますが、サブフォルダではないので除外する必要があります。
あと、お呼びではないのですが、標準ファイルたちがごっそり出力されてしまいました。
この理由なのですが、属性を表すVB定数は
- vbNormal:0
- vbDirectory:16
でしたよね。
vbDirectoryを指定すると数値としては16なのですが、VBAはその16という数値を「vbNormal+vbDirectory=16」と解釈しているんですね。
ですからvbDirectoryを指定しても、標準ファイルもパターンマッチの対象となってしまうのです。ややこしいっすね。
標準ファイルを除外する
まず、標準ファイルを除外しましょう。
GetAttr関数でファイルやフォルダの属性を判定する
ファイルやフォルダの属性を判定するときにはGetAttr関数を使います。
書き方は
です。
返り値として、vbNormalやvbDirectoryなどのファイル・フォルダ属性が得られるので、判定をする場合は
If GetAttr(strPattern & strFolder) And vbDirectory Then
'処理
End If
とすればOKです。
なぜAnd演算なのかということなんですが、調べたフォルダまたはファイルのフルパスの属性にVbDirectoryが含まれていれば、以下の表に示すようにTrueになります。
属性 | 10進数 | 2進数 | And演算結果 | 真偽値 |
---|---|---|---|---|
VbDirectory | 16 | 01000 | 01000 | True |
VbNormal | 0 | 00000 | 00000 | False |
VbDirectory + vbHidden | 18 | 01010 | 01000 | True |
なお、Dir関数で出られた文字列strFolderはファイル名またはフォルダ名のみでして、フルパスではありません。パターンであるstrPatternと連結してフルパスにするのを忘れないようにしてくださいね。
カレントフォルダと親フォルダを除外
続いてカレントフォルダと親フォルダを除外します。
これは、普通にIf文で判定します。
If strFolder <> "." And strFolder <> ".." Then
'処理
End If
とすればOKですね。
フォルダ内のサブフォルダ一覧を出力するプログラム
なかなかの工夫を要しましたが、結果として以下プログラムを作りました。
Sub Dir関数でフォルダ一覧()
Dim strPattern As String, strFolder As String
strPattern = "C:\Users\Noriaki\Dropbox\40_ブログ\vba-file-dir\開くファイル\"
strFolder = Dir(strPattern, vbDirectory)
Do While Len(strFolder) > 0
If GetAttr(strPattern & strFolder) And vbDirectory Then
If strFolder <> "." And strFolder <> ".." Then
Debug.Print strFolder
End If
End If
strFolder = Dir()
Loop
End Sub
実行結果はこちらです。
無事にサブフォルダだけの一覧が出力できました。
まとめ
エクセルVBAでDir関数を使ってフォルダ一覧を表示する方法についてお伝えしました。
GetAttr関数はちょっとクセがありますが、2進数のAnd演算がわからなくても使い方だけ覚えておいても良いと思います。
というかフォルダの一覧を取得したいというニーズが多そうであれば、いつでも取り出せるように、定番プロシージャ化しておくと良いですね。
次回は、Dir関数とは別のアプローチで簡単にファイルやフォルダを取り扱うFileSystemオブジェクトについてお伝えします。
どうぞお楽しみに!