目次

目的

  • パソコン内に指定ファイルが存在しているかどうかを調べる。

下記のような場合は「再帰処理」を使用した方が良いかもしれません。

  • 検索対象のフォルダが多数。
  • サブフォルダ(フォルダの中のフォルダ)まで検索したい。
  • ツリーのトップのフォルダ(ルートフォルダ)を指定して、ツリー全体を検索対象にしたい。

「vba 再帰処理 ファイル」「vba 再帰処理 fso」などのキーワードで検索すると目的の情報を得られると思います。

目次まで戻る

その一例

  1. パソコンのデスクトップの「folder1」フォルダに、いくつかのファイルが入っている状態でテストしてみます。
    「C:¥Users¥xxx¥デスクトップ¥folder1」。xxx の部分は伏せ字になっています。ユーザーによって異なります。
    「C:¥Users¥xxx¥デスクトップ¥folder1」。xxx の部分は伏せ字になっています。ユーザーによって異なります。
    「folder1」にいくつかのファイルが入っています。
    「folder1」にいくつかのファイルが入っています。
  2. 「folder1」に存在するファイルを検索してみます。
    Sub 存在するファイルを検索()
    Debug.Print """" & Dir("C:¥Users¥xxx¥デスクトップ¥folder1¥file1.txt") & """"
    End Sub
    1. 「Dir("C:¥Users¥xxx¥デスクトップ¥folder1¥file1.txt")」
      Dir( 検索条件 ) の書式になっています。
    2. """"
      文字の始まりと終わりが分かりやすいように、ダブルクォーテーション「"」で囲んでいます。
      「"」二つで「"」を出力出来ます。「""」を「"」で囲んで「""""」としています。
    3. 実行結果は以下のようになりました。
      ファイル名を取得出来ました。
      ファイル名を取得出来ました。
  3. 「folder1」に存在しないファイルを検索してみます。
    Sub 存在しないファイルを検索()
    Debug.Print """" & Dir("C:¥Users¥xxx¥デスクトップ¥folder1¥file0.txt") & """"
    End Sub
    1. 「file0.txt」
      file0.txt は存在していません。ファイルが存在しない場合、長さ 0 の文字列が返ってくるようです。
    2. 実行結果は以下のようになりました。
      長さ 0 の文字列が返ってきました。
      長さ 0 の文字列が返ってきました。
  4. ワイルドカードで同じ拡張子のファイルを検索してみます。私が 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
    1. 「Dir 関数実行 1 回目」
      1 回目は検索条件を指定しています。
    2. 「*.txt」
      ワイルドカードのアスタリスク「*」はその位置に複数の文字があることを表現しています。クエスチョンマーク「?」で何かの 1 文字を表現出来ます。
    3. 「2 回目」
      同じ検索条件で再検索する場合は Dir のみで実行します。
    4. 「3 回目」
      3 回目まではファイル名が出力されます。
      Dir 3 回目までの結果。
      Dir 3 回目までの結果。
    5. 「4 回目」
      3 回目までで検索条件に一致する全てのファイルを取得したので、 4 回目は、長さ 0 の文字列が返ってきます。
      4 回目は長さ 0 の文字列。
      4 回目は長さ 0 の文字列。
    6. 「5 回目」
      5 回目でエラーが発生してマクロが中断されました。
      実行時エラー'5' プロシージャの呼び出し、または引数が不正です。
      実行時エラー'5' プロシージャの呼び出し、または引数が不正です。
  5. ワイルドカード+ループ処理で同じ拡張子のファイルを検索してみます。
    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
    1. 「Do ... Loop」
      私が苦手とする Do Loop ステートメントを使用していますが、 Dir 関数のヘルプに載っていた制御構造です。
    2. 「実行順 1 ... 15」
      処理の順番です。実行順 12 で長さ 0 の文字列が返ってきます。そのまま 13 へ進みますが、 14 で「Do While a <> ""」の条件に一致しないので Do Loop を抜けます。
    3. 実行結果は以下のようになりました。
      長さ 0 の文字列は出力されていません。
      長さ 0 の文字列は出力されていません。
  6. ワイルドカードを「*.*」にしてフォルダ内の全てのファイルを検索してみます。
    Sub ループ処理で全てのファイルを検索()
    Dim a
    a = Dir("C:¥Users¥xxx¥デスクトップ¥folder1¥*.*")
    Do While a <> ""
    Debug.Print """" & a & """"
    a = Dir
    Loop
    End Sub
    1. 実行結果は以下のようになりました。
      9 個のファイル名が出力されました。
      9 個のファイル名が出力されました。

目次まで戻る

フォルダを検索

Dir 関数はフォルダも検索できるようです。

  1. 上記で出てきた「folder1」の中に、いくつかのフォルダを追加してテストしてみます。
    「C:¥Users¥xxx¥デスクトップ¥folder1」。xxx の部分は伏せ字になっています。ユーザーによって異なります。
    「C:¥Users¥xxx¥デスクトップ¥folder1」。xxx の部分は伏せ字になっています。ユーザーによって異なります。
    「folder2」「folder3」「folder4」を追加しました。
    「folder2」「folder3」「folder4」を追加しました。
  2. Dir 関数の第二引数に「vbDirectory」を指定してみます。
    Sub 第二引数にvbDirectoryを指定_フォルダを検索()
    Dim a
    a = Dir("C:¥Users¥xxx¥デスクトップ¥folder1¥folder2", vbDirectory)
    Debug.Print """" & a & """"
    End Sub
    1. 「vbDirectory」
      vbDirectory は VBA.VbFileAttribute に入っている定数のようです。値は「16」と定義されているようです。
    2. 実行結果は以下のようになりました。
      フォルダ名を取得出来ました。
      フォルダ名を取得出来ました。
    3. 第二引数指定なしの場合、長さ 0 の文字列が返ってきました。
      長さ 0 の文字列。
      長さ 0 の文字列。
  3. ループ処理でフォルダを検索してみます。
    Sub ループ処理_フォルダを検索()
    Dim a
    a = Dir("C:¥Users¥xxx¥デスクトップ¥folder1¥*", vbDirectory)
    Do While a <> ""
    Debug.Print """" & a & """"
    a = Dir
    Loop
    End Sub
    1. 実行結果は以下のようになりました。フォルダ名のみ取得されると思っていましたが、ファイル名、ピリオドの記号も取得されています。
      ピリオド、ファイル名、フォルダ名が取得されている。
      ピリオド、ファイル名、フォルダ名が取得されている。
    2. 上記結果のピリオド「.」は現在のフォルダ(カレントフォルダというらしいです)を示す表記のようです。ピリオド 2 つの「..」は親フォルダという意味のようです。
    3. 「folder1¥*」
      「folder1¥」でも同じ結果になりました。
  4. フォルダ名のみ抽出する方法は、下記 Dir 関数のヘルプページに載っていました。
    下記ページの使用例のコメント部分は英語になっていますが、 VBE で Dir 関数のヘルプを見ると日本語のコメントが付いていました。
  5. 私の場合、上記ヘルプページに載っている以外の方法を知らないので、ヘルプそのままのようになってしまいますが、良ければご覧ください。
    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
    1. 「If a <> "." And a <> ".." Then」
      現在のフォルダ「.」と親フォルダ「..」以外の場合。
    2. 「GetAttr() And vbDirectory) = vbDirectory」
      フォルダの属性を取得して、定数 vbDirectory(=16)と一致しているか判定。
    3. 実行結果は以下のようになりました。
      フォルダ名のみになっている。
      フォルダ名のみになっている。
  6. GetAttr 関数のテストも行ってみました。まずはファイルの属性を取得してみます。
    Sub GetAttr関数でファイルの属性取得()
    Debug.Print GetAttr("C:¥Users¥xxx¥デスクトップ¥folder1¥file1.txt")
    End Sub
    1. 「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
    2. 実行結果は以下のようになりました。
      32 は「アーカイブ」属性を持っているという意味のようです。
      32 は「アーカイブ」属性を持っているという意味のようです。
  7. 次はフォルダの属性を取得してみます。
    Sub GetAttr関数でフォルダの属性取得()
    Debug.Print GetAttr("C:¥Users¥xxx¥デスクトップ¥folder1¥folder2")
    End Sub
    1. 結果は以下のようになりました。
      48。おそらく 16+32 だと思います。フォルダ属性+アーカイブ属性を持っているようです。
      48。おそらく 16+32 だと思います。フォルダ属性+アーカイブ属性を持っているようです。
  8. And 演算子でビット単位の比較というものを行うと「16」が取得できるようです。私の場合、ビット単位の比較というのが分かっていません。
    Sub And_vbDirectoryを付加_GetAttr関数でフォルダの属性取得()
    Debug.Print GetAttr("C:¥Users¥xxx¥デスクトップ¥folder1¥folder2") And vbDirectory
    End Sub
    1. 実行結果は以下のようになりました。
      16 を取得できました。定数 vbDirectory の値と一致しています。
      16 を取得できました。定数 vbDirectory の値と一致しています。
    2. 「And vbDirectory」の部分を「And vbArchive」に変更すると以下の結果になりました。
      32。アーカイブ属性も持っているようです。
      32。アーカイブ属性も持っているようです。

テスト結果ストック

デスクトップに作成した「folder10」
デスクトップに作成した「folder10」
folder10 の中にあるファイル、フォルダ。読み取り専用(ReadOnly)、隠しファイル(Hidden)、標準(Normal)、フォルダ(Directory)
folder10 の中にあるファイル、フォルダ。読み取り専用(ReadOnly)、隠しファイル(Hidden)、標準(Normal)、フォルダ(Directory)

実行したマクロ

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

以上、閲覧ありがとうございました。

目次まで戻る

同じカテゴリの投稿(Excel VBA)

前後の投稿