和風スパゲティのレシピ

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

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

ファイルを部分一致検索する方法を解説します。


単純な部分一致であれば、Dir関数にワイルドカード(*または?)を指定するだけで検索できます。

Dir関数だけではできない「文字数や文字種を絞った部分一致」まで行いたい場合は、
候補のファイルすべてをループしてLike演算子で比較します。

Dir関数にワイルドカード(*/?)を指定する方法

ソースコード

Sub ファイル名が売上データから始まるファイルを検索して開く()
    
    Dim 検索フォルダパス As String
    検索フォルダパス = "C:\Users\wfsp\Desktop\検索フォルダ"
    
    Dim 該当ファイル名 As String
    該当ファイル名 = Dir(検索フォルダパス & "\売上データ*.xlsx")
    
    If 該当ファイル名 <> "" Then
        
        Dim 処理ブック As Workbook
        Set 処理ブック = Workbooks.Open(検索フォルダパス & "\" & 該当ファイル名)
        
    End If
    
End Sub

解説

Dir関数はワイルドカードを利用することで、
ループ処理なく部分一致検索を行うことが可能です。


使えるワイルドカードは「*」「?」の2つです。

* 任意の文字列(0文字も含む)
? 任意の1文字

ワイルドカードは文字列中に何度も使用できます。


ワイルドカードによる判定例は以下の通りです。

Dir関数内の記述 判定
○○* 前方一致
*○○ 後方一致
*○○* 中間一致(狭義の部分一致)
○○??? 前方一致かつ文字数指定
○○(*) カッコの中身以外が一致


このように[*?]2つのワイルドカードで表現できる判定であれば、
1回のDir関数だけで検索ができます。



ちなみにDir関数を使用するコード全般に言えることですが、
パスを扱う文字列は細かく変数にしておくとよいです。


以下のような1発指定↓ももちろん可能なのですが、

該当ファイル名 = Dir("C:\Users\wfsp\Desktop\検索フォルダ\売上データ*.xlsx")

この後Openする際に「フォルダパス\ファイル名」が必要で、
そこでもう一度フォルダパスをベタ打ちする羽目になります。


検索対象フォルダの変更時にバグの温床になりますので、
ファイル名とフォルダパスは分けた変数にしておきましょう。

Like演算子による判定を使う方法

[*?]では判定しきれないファイル検索を行う場合は、
対象フォルダ内のすべてのファイル名をLike演算子で判定します。

ソースコード

Sub ファイル名が売上データyyyymmddになっているファイルを検索して開く()
    
    Dim 検索フォルダパス As String
    検索フォルダパス = "C:\Users\wfsp\Desktop\検索フォルダ"
    
    Dim 該当ファイル名 As String
    Dim dirファイル名 As String
    dirファイル名 = Dir(検索フォルダパス & "\*.xlsx")
    Do While dirファイル名 <> ""
        
        If dirファイル名 Like "売上データ########.xlsx" Then
            該当ファイル名 = dirファイル名
            Exit Do
        End If
        
        dirファイル名 = Dir()
    Loop
    
    If 該当ファイル名 <> "" Then
        Dim 処理ブック As Workbook
        Set 処理ブック = Workbooks.Open(検索フォルダパス & "\" & 該当ファイル名)
    End If
    
End Sub

解説

Do WhileステートメントとDir関数による全ファイル検索を行い、
すべてのファイルでLike演算子による判定を行う
コードです。


Like演算子で使用できる条件記法は以下の通りです。

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

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


Dir関数より細かい指定をすることができ、
サンプルコードではyyyymmddに合致するファイルを、
8桁の数値、すなわち「########」で判定しています。


Dir(*/?)では対応しきれない判定はこちらを使用してください。


また、ファイル名条件は「*/?」で十分であっても、
該当ファイルが複数ある場合もこのようなループが必要になります。


「yyyymmddのうち最新日のもの」を取得したい場合は、
対象ファイル名すべてをセルに書き出しそれを並び替えるなど、
ファイルの採用判定を細かく実行してください。

FileSystemObjectを使用した方法

FileSystemObject(以下FSO)を使用した場合のコードも記載します。


FSOにはワイルドカードを使用できるメソッドがありませんので、
必然的にLike演算子を使ったコードになります。


今回の処理におけるFSOとDir関数の違いを簡単に比較すると、

[*?]で事足りる場合は1行で済む分Dir関数に分がありますが、
Like演算子を使う場合はFSOを使用した方がコードが簡潔になります。


また、FSOには「Unicode(≒環境依存)文字も扱える」という特長があります。


よってFSOを勉強するコストを抜きにして考えた場合は、

  • *や?で済む判定ならDir関数
  • 環境依存文字が出てきそうならFSO
  • Like演算子が必要になる場合もFSO

と使い分けるのが良いと思います。

ソースコード

Sub ファイル名が売上データyyyymmddになっているファイルを検索して開く()
    
    Dim FSO As New FileSystemObject
    
    Dim 検索フォルダ As Folder
    Set 検索フォルダ = FSO.GetFolder("C:\Users\wfsp\Desktop\検索フォルダ")
    
    Dim 該当ファイル As File
    Dim ファイル候補 As File
    For Each ファイル候補 In 検索フォルダ.Files
        
        If ファイル候補.Name Like "売上データ########.xlsx" Then
            Set 該当ファイル = ファイル候補
            Exit For
        End If
        
    Next
    
    If Not 該当ファイル Is Nothing Then
        Dim 処理ブック As Workbook
        Set 処理ブック = Workbooks.Open(該当ファイル.Path)
    End If
    
End Sub

解説

コードの流れはLike演算子を使ったコードと全く同じです。

各処理をFSOを使ったコードに書き換えているだけですね。


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


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