目次
目的
- パソコン内に指定ファイルが存在しているかどうかを調べる。
下記のような場合は「再帰処理」を使用した方が良いかもしれません。
- 検索対象のフォルダが多数。
- サブフォルダ(フォルダの中のフォルダ)まで検索したい。
- ツリーのトップのフォルダ(ルートフォルダ)を指定して、ツリー全体を検索対象にしたい。
「vba 再帰処理 ファイル」「vba 再帰処理 fso」などのキーワードで検索すると目的の情報を得られると思います。
その一例
- パソコンのデスクトップの「folder1」フォルダに、いくつかのファイルが入っている状態でテストしてみます。
「C:¥Users¥xxx¥デスクトップ¥folder1」。xxx の部分は伏せ字になっています。ユーザーによって異なります。 「folder1」にいくつかのファイルが入っています。 - 「folder1」に存在するファイルを検索してみます。
Sub 存在するファイルを検索()
Debug.Print """" & Dir("C:¥Users¥xxx¥デスクトップ¥folder1¥file1.txt") & """"
End Sub - 「folder1」に存在しないファイルを検索してみます。
Sub 存在しないファイルを検索()
Debug.Print """" & Dir("C:¥Users¥xxx¥デスクトップ¥folder1¥file0.txt") & """"
End Sub - ワイルドカードで同じ拡張子のファイルを検索してみます。私が Dir 関数の動作をよく分かっていないので、その理解のために、Dir 関数を何回か実行してみます。
Sub Dir関数の動作理解のために同じ拡張子のファイルを検索()
Debug.Print """" & Dir("C:¥Users¥xxx¥デスクトップ¥folder1¥*.txt") & """" 'Dir 関数実行 1 回目
Debug.Print """" & Dir & """" '2 回目
Debug.Print """" & Dir & """" '3 回目
Debug.Print """" & Dir & """" '4 回目
Debug.Print """" & Dir & """" '5 回目 'エラー発生
Debug.Print """" & Dir & """" '6 回目
End Sub- 「Dir 関数実行 1 回目」
1 回目は検索条件を指定しています。 - 「*.txt」
ワイルドカードのアスタリスク「*」はその位置に複数の文字があることを表現しています。クエスチョンマーク「?」で何かの 1 文字を表現出来ます。 - 「2 回目」
同じ検索条件で再検索する場合は Dir のみで実行します。 - 「3 回目」
3 回目まではファイル名が出力されます。
Dir 3 回目までの結果。 - 「4 回目」
3 回目までで検索条件に一致する全てのファイルを取得したので、 4 回目は、長さ 0 の文字列が返ってきます。
4 回目は長さ 0 の文字列。 - 「5 回目」
5 回目でエラーが発生してマクロが中断されました。
実行時エラー'5' プロシージャの呼び出し、または引数が不正です。
- 「Dir 関数実行 1 回目」
- ワイルドカード+ループ処理で同じ拡張子のファイルを検索してみます。
Sub ループ処理で同じ拡張子のファイルを検索()
Dim a
a = Dir("C:¥Users¥xxx¥デスクトップ¥folder1¥*.txt") '実行順 1
Do While a <> "" '2,6,10,14
Debug.Print """" & a & """" '3,7,11
a = Dir '4,8,12
Loop '5,9,13
End Sub '15 - ワイルドカードを「*.*」にしてフォルダ内の全てのファイルを検索してみます。
Sub ループ処理で全てのファイルを検索()
Dim a
a = Dir("C:¥Users¥xxx¥デスクトップ¥folder1¥*.*")
Do While a <> ""
Debug.Print """" & a & """"
a = Dir
Loop
End Sub
フォルダを検索
Dir 関数はフォルダも検索できるようです。
- 上記で出てきた「folder1」の中に、いくつかのフォルダを追加してテストしてみます。
「C:¥Users¥xxx¥デスクトップ¥folder1」。xxx の部分は伏せ字になっています。ユーザーによって異なります。 「folder2」「folder3」「folder4」を追加しました。 - Dir 関数の第二引数に「vbDirectory」を指定してみます。
Sub 第二引数にvbDirectoryを指定_フォルダを検索()
Dim a
a = Dir("C:¥Users¥xxx¥デスクトップ¥folder1¥folder2", vbDirectory)
Debug.Print """" & a & """"
End Sub - ループ処理でフォルダを検索してみます。
Sub ループ処理_フォルダを検索()
Dim a
a = Dir("C:¥Users¥xxx¥デスクトップ¥folder1¥*", vbDirectory)
Do While a <> ""
Debug.Print """" & a & """"
a = Dir
Loop
End Sub - フォルダ名のみ抽出する方法は、下記 Dir 関数のヘルプページに載っていました。
下記ページの使用例のコメント部分は英語になっていますが、 VBE で Dir 関数のヘルプを見ると日本語のコメントが付いていました。
- 私の場合、上記ヘルプページに載っている以外の方法を知らないので、ヘルプそのままのようになってしまいますが、良ければご覧ください。
Sub ループ処理_フォルダ名のみ抽出()
Dim a
a = Dir("C:¥Users¥xxx¥デスクトップ¥folder1¥", vbDirectory)
Do While a <> ""
If a <> "." And a <> ".." Then
If (GetAttr("C:¥Users¥xxx¥デスクトップ¥folder1¥" & a) And vbDirectory) = vbDirectory Then
Debug.Print """" & a & """"
End If
End If
a = Dir
Loop
End Sub - GetAttr 関数のテストも行ってみました。まずはファイルの属性を取得してみます。
Sub GetAttr関数でファイルの属性取得()
Debug.Print GetAttr("C:¥Users¥xxx¥デスクトップ¥folder1¥file1.txt")
End Sub- 「GetAttr」
GetAttr 関数は「属性の値」の合計値を返すようです。「属性の値」は、フォルダ属性「16」、アーカイブ属性「32」のように定数で決まっているようです。
- GetAttr 関数 (Visual Basic for Applications) | Microsoft Learn
- https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/getattr-function
- 実行結果は以下のようになりました。
32 は「アーカイブ」属性を持っているという意味のようです。
- 「GetAttr」
- 次はフォルダの属性を取得してみます。
Sub GetAttr関数でフォルダの属性取得()
Debug.Print GetAttr("C:¥Users¥xxx¥デスクトップ¥folder1¥folder2")
End Sub - And 演算子でビット単位の比較というものを行うと「16」が取得できるようです。私の場合、ビット単位の比較というのが分かっていません。
Sub And_vbDirectoryを付加_GetAttr関数でフォルダの属性取得()
Debug.Print GetAttr("C:¥Users¥xxx¥デスクトップ¥folder1¥folder2") And vbDirectory
End Sub
テスト結果ストック


実行したマクロ
Private Sub 呼出し関数(path)
'vbNormal 0 標準
'vbReadOnly 1 読み取り専用
'vbHidden 2 隠しファイル
'vbSystem 4 システムファイル。Mac 使用不可
'vbDirectory 16 フォルダ
'vbArchive 32 前回バックアップ以降変更有。Mac 使用不可
'vbAlias 64 Mac のみ
Debug.Print "path="; path
Debug.Print "GetAttr="; GetAttr(path)
Debug.Print "vbNormal="; GetAttr(path) And vbNormal
Debug.Print "vbReadOnly="; GetAttr(path) And vbReadOnly
Debug.Print "vbHidden="; GetAttr(path) And vbHidden
Debug.Print "vbSystem="; GetAttr(path) And vbSystem
Debug.Print "vbDirectory="; GetAttr(path) And vbDirectory
Debug.Print "vbArchive="; GetAttr(path) And vbArchive
Debug.Print "vbAlias="; GetAttr(path) And vbAlias
End Sub
Sub GetAttr関数で属性を調べる()
Const a = "C:¥Users¥xxx¥デスクトップ¥folder10"
呼出し関数 (a & "¥ReadOnly-Hidden.txt")
呼出し関数 (a & "¥ReadOnly.txt")
呼出し関数 (a & "¥Normal.txt")
呼出し関数 (a & "¥Hidden.txt")
呼出し関数 (a & "¥Directory")
End Sub
実行結果を表にまとめたもの
path |
GetAttr |
vb Normal 定数=0 |
vb ReadOnly 定数=1 |
vb Hidden 定数=2 |
vb System 定数=4 |
vb Directory 定数=16 |
vb Archive 定数=32 |
vb Alias 定数=64 |
ReadOnly-Hidden.txt | 35 | 0 | 1 | 2 | 0 | 0 | 32 | 0 |
ReadOnly.txt | 33 | 0 | 1 | 0 | 0 | 0 | 32 | 0 |
Normal.txt | 32 | 0 | 0 | 0 | 0 | 0 | 32 | 0 |
Hidden.txt | 34 | 0 | 0 | 2 | 0 | 0 | 32 | 0 |
Directory | 16 | 0 | 0 | 0 | 0 | 16 | 0 | 0 |
「Directory」の GetAttr の結果が 16 になっています。上記ではフォルダの GetAttr の結果は 48 と出てきました。 48 を再現しようとしてみましたが、なぜか出来ないままです。
テスト環境
- Windows 10(64 ビット)
- Microsoft Office Excel 2003
以上、閲覧ありがとうございました。