和風スパゲティのレシピ

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

フォルダを部分一致(ワイルドカード)で検索する

フォルダを部分一致で検索する方法を解説します。

FileSystemObject+Like演算子による検索

フォルダを部分一致検索するには、
FileSystemObject(以下FSO)を使うのがおすすめです。


これがフォルダではなくファイルを部分一致で判定したい場合は、

対象ファイル名 = Dir(検索フォルダパス & "\*.xlsx")

と、Dir関数にワイルドカード*を渡す方法が簡単です。


しかし同じようにフォルダの部分一致判定を行おうとすると、

  • 1回目の実行が相対パスを意味する「.」を返してしまう
  • 引数にvbDirectoryを指定してもファイルも検索してしまう

という問題が発生してしまい、コードが複雑になります。


FSOの方がコードが短く、またFSOは環境依存文字にも強いため、
今回の処理にはFSOを採用しましょう。

ソースコード

Sub フォルダ名が売上データ○○になっているフォルダを取得する()
    
    Dim FSO As New FileSystemObject
    
    Dim 検索フォルダ As Folder
    Set 検索フォルダ = FSO.GetFolder("C:\Users\○○\Desktop\検索フォルダ")
    
    Dim 該当フォルダ As Folder
    Dim フォルダ候補 As Folder
    For Each フォルダ候補 In 検索フォルダ.SubFolders
        
        If フォルダ候補.Name Like "売上データ*" Then
            Set 該当フォルダ = フォルダ候補
            Exit For
        End If
        
    Next
    
    If Not 該当フォルダ Is Nothing Then
        MsgBox "該当フォルダのパス:" & 該当フォルダ.Path
    End If
    
End Sub

解説

フォルダ内にあるすべての子フォルダ(SubFolders)を調べ、
1つずつLike演算子による判定を行う
コードです。


まず判定のメインとなるLike演算子ですが、
任意の文字列を表す*以外にも以下の条件記法が使えます。

条件記法 判定
* 任意の文字列(0文字も含む)
? 任意の1文字
# 任意の数字1文字
[A-Z] A~Zの内の1文字
[!A-Z] A~Zでない1文字

※ A,Zには好きな文字を指定可能


Dir関数より細かい指定をすることができ、
例えば「yyyymmdd」に合致するフォルダを探したいときは、
「########」とすることで8桁の数値を判定できます。


かなり細かい条件まで指定できますが、「yyyymmddの中で一番最近のもの」のようにこれでも絞り切れない条件が必要な場合は、フォルダ名をセルに書き出してソートするなど細かく対応してください。



続いてFileSystemObjectに関する部分ですが、
こちらはSubFoldersで全ての子フォルダを取得する基本に忠実なコードです。


FSOのSetには事前バインディングを使用していますので、
このコードを実行する場合は「Scripting Runtime」を参照設定をしてください。


FileSystemObjectの各プロパティに関する詳しい解説はここでは省略します。
以下の一覧ページよりお探しください。
www.limecode.jp

Dir関数を利用する方法

一応ですが、Dir関数を使用する方法も置いておきます。

前述の通りFSOはUnicode(環境依存)文字を扱えるというメリットがあり、
またLike演算子に比べてDir関数は*と?しか条件に使用できないため、
Dir関数を使用したコードで書く意味は特にありません。


Dir(vbDirectory)の仕様の参考にでもしてください。

ソースコード

Sub フォルダ名が売上データ○○になっているフォルダを取得する()
    
    Dim 検索フォルダパス As String
    検索フォルダパス = "C:\Users\○○\Desktop\検索フォルダ"
    
    Dim 該当フォルダパス As String
    Dim dir結果値 As String
    dir結果値 = Dir(検索フォルダパス & "\売上データ*", vbDirectory)
    Do While dir結果値 <> ""
        
        Dim dir結果パス As String
        dir結果パス = 検索フォルダパス & "\" & dir結果値
        
        If GetAttr(dir結果パス) And vbDirectory Then
            該当フォルダパス = dir結果パス
            Exit Do
        End If
        
        dir結果値 = Dir()
    Loop
    
    If 該当フォルダパス <> "" Then
        MsgBox "該当フォルダのパス:" & 該当フォルダパス
    End If
    
End Sub

解説

FSOと違いDir関数は直接ワイルドカードを扱えるため、
Like演算子を使用しなくても、

dir結果値 = Dir(検索フォルダパス & "\売上データ*", vbDirectory)

という指定で部分一致検索を行うことができます。


このおかげで「ファイル名」の検索はDir関数で1発なのですが、
前述の通り「フォルダ名」の検索はこれではうまくいきません。


なぜならDir(パス, vbDirectory)という書き方は、
フォルダまたはファイルを探す処理」になってしまうためです。
(詳しい解説はここでは省きます)


よって上記のコードは「売上データ○○.xlsx」をひっかける可能性があり、
これを防ぐためにパスがフォルダかどうかを、

If GetAttr(dir結果パス) And vbDirectory Then

このコードをループ内に記載して判定する必要があります。


そのせいでフォルダ/ファイルすべてをチェックするDo文が必要になり、
FSOよりも長く読みづらいコードになってしまいますね。


Dir関数はフォルダの検索が少々苦手なため、
FSOを使用した方がスッキリかける場合が多いです。

複雑なフォルダ管理を求められるマクロが必要になったら、
FileSystemObjectの習得をおすすめいたします。