和風スパゲティのレシピ

日本語でコーディングするExcelVBA

DirとFSO.FolderExistsの違い

フォルダが存在するか判定する際に使用する、Dir関数(vbDirectory指定)と、
FileSystemObject.FolderExistsメソッドの違いを解説します。

※ FileSystemObjectは以下FSOと略記します。

同じところ

どちらもフォルダが存在するかを判定できます。

以下のコードは実際には同じ動きになります。

If Dir(判定したいフォルダパス, vbDirectory) <> "" Then
    フォルダがあったときの処理
End If
Dim FSO As New FileSystemObject

If FSO.FolderExists(判定したいフォルダパス) Then
    フォルダがあったときの処理
End If

違うところ

まず大きな点として、返り値が異なります。

Dir関数はフォルダがあれば「フォルダ名」、なければ「""」を返すのに対し、
FolderExistsメソッドはフォルダのあるなしをTrue/Falseで返します。


このため判定するIfステートメントの書き方が異なり、
Dir関数で判定する場合は「=""」「<>""」で判定する必要があります。




続いてDir系列ステートメントとFSO全般に言える違いですが、
フォルダ名にUnicode文字が混じった場合にDir関数はうまく動きません。

例えば、

  • ①~⑳のフォルダは正確にフォルダ名を取得可能
  • ㉑~㊿のフォルダは丸数字部分が「?」になってしまう。

という問題が発生します。


一応正確に言うと、「フォルダ名のUnicode文字が?になる」という挙動のため、
「=""」「<>""」で行うフォルダの存在判定自体は(ほぼ)正しく動きます。


とはいえ不具合が起きることももちろんありますし、
他のステートメント(MkDirやRmDirなど)はエラーになります。


Unicode文字を使用する場合はおとなしくFSOを使っておきましょう。



また、Dir関数には「フォルダパスに255文字制限」があります。


といっても、これはWindows標準フォルダの制約と同じであり、
さらにはWorkbook.Openなども同様の制約があります。


FileSystemObjectが256文字以上のファイルパスに耐えたところで、
結局他の部分でエラーになってしまっては意味がありません。


原則フォルダ(ファイル)パスは255文字以内で運用すべきですのでご注意ください。




最後に、Dir関数は「ワイルドカード*を使った部分一致検索」ができますが、
実行が簡単なファイル名と違い、「フォルダ名」の部分一致検索は少々面倒です。


*を使用したDir関数はvbDirectoryを指定してもファイル名も検索してしまうため、
ただ、Dir(親パス & "\*", vbDirectory)と書いても動きません。


例えば「バックアップ○○」というフォルダを探したいときは、

Dim dir結果値 As String
dir結果値 = Dir("C:~~~\バックアップ*", vbDirectory)
Do While dir結果値 <> ""
    Dim 結果パス As String
    結果パス = "C:~~~\" & dir結果値
    If GetAttr(結果パス) And vbDirectory Then
        Debug.Print "見つかったフォルダ名:" & dir結果値
    End If
    dir結果値 = Dir()
Loop

こんなコードを書く必要があります。

If GetAttr(結果パス) And vbDirectory Then

この部分がDir関数の結果が「フォルダ」であったかの判定部分ですね。


これは事実上フォルダ内のすべてのサブフォルダを探すコードを書いており、
それをやるくらいなら、FileSystemObjectを用いた場合のコード

Dim フォルダ As Folder
For Each フォルダ In FSO.GetFolder("C:~~~\").SubFolders
    If フォルダ.Name Like "バックアップ*" Then
        Debug.Print "見つかったフォルダ名:" & フォルダ.Name
    End If
Next

こちらの方がはるかに簡単でしかも読みやすくなります。

比較対象であるFolderExistsは使っていませんけどね。


あいまい検索はDir/FolderExitsどちらも使わず、
FSOの基本的なループ処理に頼った方がよいというのが結論です。

使い分け

フォルダ名にUnicode文字を使用する可能性がある場合は、
FSOのFolderExistsメソッドを使用する必要があります。


そうでない場合はだいたい同じものですので、好きな方を使ってください。

  • 単発で使うなら書くのが楽なDir関数
  • 前後にFSOを使ったコードがあるなら統一感を出すためにFolderExists

あたりで使い分けると良さそうに思います。


そしてフォルダ名を部分一致(ワイルドカード*)で検索したい場合は、
FolderExistsでは不可能ですが、Dir関数でやるのもかなり面倒です。

どちらも使用せず、FSOの「SubFolders」プロパティを使用し、
Like演算子を使ってストレートに部分一致判定を行いましょう。