フォルダが存在するか判定する際に使用する、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演算子を使ってストレートに部分一致判定を行いましょう。