あるフォルダ内のフォルダ一覧、つまりサブフォルダの一覧を取得したいときは、Dir関数が便利です。
ここから先の説明はめちゃくちゃ長いので、先に結論を書いておきます。
こう書きます。
Dim 戻り値 As String
Dim 属性 As Integer
戻り値 = Dir(“C:\Users\ユーザー名\Desktop\*”,vbDirectory)
Do While 戻り値 <> “”
‘戻り値の内、余計なフォルダは対象から外す
IF (戻り値 <>”.” And 戻り値 <>”..”) Then
‘戻り値の属性を取得
属性 = GetAttr(“C:\Users\ユーザー名\Desktop\” & 戻り値)
‘フォルダ属性のもののみ処理する
If ( 属性 AND vbDirectory)>0 Then
‘ここに処理を書く
End If
End If
‘次のフォルダ名を取得する
戻り値= Dir()
Loop
では、長くなりますが1つずつ説明していきます。
Dir関数の考え方
別のページで書きましたが、フォルダがあるか・ないか調べるときは、Dir関数が使えます。
・指定したフォルダがある場合⇒そのフォルダ名を返す
・指定したフォルダがない場合⇒””(長さ0の文字列)を返す
これを応用して、このページの本題である「サブフォルダ一覧を取得する」を考えていきます。
Dir関数で、サブフォルダ名一覧を取得する方法
サブフォルダ名に「ワイルドカード(*)」を使う
例えば、Desktop内に「売上」フォルダがあるか・ないか、調べたいときは、こう書きます。
Dir(“C:\Users\ユーザー名\Desktop¥売上”,vbDirectory)
これを応用します。
Dir(“C:\Users\ユーザー名\Desktop¥*”,vbDirectory)
「売上」を「*」(ワイルドカード)に変えました。
「*」は、その部分は”どんな文字でも”・”何文字でも”OK、という意味です。
つまり、
Desktopフォルダにある、どんな名前でも何文字の名前でもいいから、全てのフォルダを取ってきてね、という意味になるのです。
まず1番目のフォルダを取得する
では、Dir関数が取ってきたフォルダ名を、変数に入れてみます。
戻り値 = Dir(“C:\Users\ユーザー名\Desktop\*”)
ここで返ってくるフォルダ名は、Desktopフォルダ内の”最初”のフォルダ名です。
Dir関数で返ってくるフォルダの順番
”最初”とあえて書いたのには、
”最初”の意味が、フォルダのあるディスク(CドライブとかDドライブとか)のファイルシステムによって違うからです。
詳しくはこの記事を見てください。
Windowsの場合は、ほぼ「フォルダ名の昇順」に返ってくると覚えていて問題ないかと思います。
同じ条件で2番目のフォルダを取得する
さて、”最初”の意味が少しややこしかったですが、
Desktopフォルダ内の1番目のフォルダは、無事に取得することができました。
でも、今回のテーマは、”全てのフォルダ”を取得することです。
2番目、3番目、・・・そして、最後のフォルダまで、全てのフォルダを取得したいのです。
そこで、次にお話するのは、Dir関数のちょっと変わった使いかたです。
Dir()
フォルダ名を書き忘れているわけではありません、これで正解なんです!
実は、()の中に何も書かない場合、直前に書いた()と同じ条件でフォルダを探し、次に見つかったフォルダを返してくれます。
具体例を見てみましょう。
Dim 戻り値2 As String
変数1 = Dir(“C:\Users\ユーザー名\Desktop\*”,vbDirectory)
変数2 = Dir()
”戻り値2 = Dir()”は、”戻り値2 = Dir(“C:\Users\ユーザー名\Desktop\*”,vbDirectory)” と、同じ意味です。
つまり、戻り値1には、Desktopフォルダの1番目のフォルダ名が、
そして、戻り値2には、Desktopフォルダの2番目のフォルダ名が入ります。
同じ条件で3番目以降のフォルダも取得する
これで、Desktopフォルダ内のサブフォルダのうち、1番目も2番目も、無事に取得することができました。
でも、今回のテーマは、”全てのフォルダ”を取得することです。
しつこいですが、
3番目、4番目、・・・そして、最後のフォルダまで、全てのフォルダを取得したい・・・のです。
フォルダの数だけ変数を作って、フォルダの数だけDir()を繰り返す??
フォルダの数を先に調べないといけない??
それは面倒なので、こんな風に書いてみます。
Dim 戻り値 As String
戻り値 = Dir(“C:\Users\ユーザー名\Desktop\*”,vbDirectory)
Do While 戻り値 <> “”
‘ここに、やりたい処理を書く
‘次のフォルダ名を取得する
戻り値= Dir()
Loop
戻り値= Dir()によって、Desktopフォルダ内にフォルダがある限り、戻り値にはフォルダ名が入ります。
そして、「Do While 戻り値 <> “”」 の、「戻り値 <> “”」は、戻り値にフォルダ名が入る限り繰り返す、という意味なので、
Desktopフォルダ内のサブフォルダの数分、繰り返し処理をすることができます。
いざ実行してみる
Desktopフォルダに、次のようなファイルやフォルダがあるとします。
Aフォルダ
Bフォルダ
この状態でさっきのコードを実行すると、
こんな一覧がDir関数から返ってきます。
..
ファイル1.xlsx
Aフォルダ
Bフォルダ
「Aフォルダ」「Bフォルダ」だけを取りたかったんですが・・・。
問題その1:余計なフォルダが返ってきてしまう
見慣れない「.」「..」があります・・・。
「.」はカレントフォルダ(つまりフォルダ)、そして「..」はカレントフォルダの親フォルダ(これもフォルダ)、のことです。
Dir関数で全てのフォルダを取ろうとすると、こんな不要なものまで取ってきてしまいます。
エクスプローラーとか目では見えないけど、実はそんなフォルダを隠し持っているんです。
そういうものだと思ってください。
だから、これらは処理対象から外す必要があります。
問題その2:フォルダだけでなくファイルも返ってきてしまう
Dir(“C:\Users\ユーザー名\Desktop¥*”,vbDirectory)
こんな風に、2番目の引数に「vbDirectory」を指定しましたよね。
フォルダのみを取ってきて欲しいから「vbDirectory」を指定しているわけですが、
実はこれ、フォルダのみではなくファイルも取ってきてしまうんです!!
何のために指定するんだ!と思ってしまいますが、そういうものなので仕方ありません。
なので、Dir関数の戻り値をさらにチェックして、フォルダかどうか確認する必要があります。
問題1・2を解決するコード
というわけで、
・戻り値の内、余計なフォルダは対象から外す
・戻り値の内、フォルダ属性のもののみ処理する
という2つの対応をすると、こうなります。
Dim 戻り値 As String
Dim 属性 As Integer
戻り値 = Dir(“C:\Users\ユーザー名\Desktop\*”,vbDirectory)
Do While 名前 <> “”
‘戻り値の内、余計なフォルダは対象から外す
IF (戻り値 <>”.” And 戻り値 <>”..”) Then
‘戻り値の属性を取得
属性 = GetAttr(“C:\Users\ユーザー名\Desktop\” & 戻り値)
‘フォルダ属性のもののみ処理する
If ( 属性 AND vbDirectory)>0 Then
‘ここに処理を書く
End If
End If
‘次のフォルダ名を取得する
戻り値= Dir()
Loop
「If ( 属性 AND vbDirectory)>0 Then」の部分は、ビット演算です。もし難しければ、こういうものだと思ってください。
これでようやく完成です!
長かったですね、お疲れ様でした(^^)/