office.notes@misora05

本館ブログのうち,Office・Windwsがらみのネタ+@を抜き出したもの.月水金更新予定.

正規表現関数を作ってみよう!@Excel (3)

前回に引き続き,正規表現関数を作成してみましょう.

ただ,VBAで使うRegExpオブジェクトに用意されているメソッド・プロパティの都合上,前回のようには単純にはいかなくなってしまいます.

指定した正規表現パターンに一致した個数を数える.

Execute メソッドを実行すると,Match オブジェクトを格納した Matches コレクションが返されるので,その個数を数えましょう.

Public Function RegEx_Count(ByVal Subject As String _
                          , ByVal Pattern As String _
                          , Optional ByVal IgnoreCase As Boolean = False) As Long
    
    With re
        .Pattern = Pattern
        .IgnoreCase = IgnoreCase
        .Global = True
        
        Dim mtcc As MatchCollection
        Set mtcc = .Execute(Subject)
        
        RegEx_Count = mtcc.Count
    End With
    
End Function

Global プロパティは必ず TRUE に設定しましょう.これは以下の項でも同様です.

指定した正規表現パターンに,n 番目に一致した場所を得る.

たとえば,「"hoge fuga piyo" という文字列の 2 番目の "a" または "e" の場所を得たい」という場合に必要になります.

この場合は,先述のExecute メソッドで取得した Matches コレクションの,n - 1 番目の Match オブジェクトの FirstIndex プロパティを取得しましょう.

Public Function RegEx_Position(ByVal Subject As String _
                             , ByVal Pattern As String _
                             , ByVal Index As Long _
                             , Optional ByVal IgnoreCase As Boolean = False) As Variant
    
    With re
        .Pattern = Pattern
        .IgnoreCase = IgnoreCase
        .Global = True
        
        Dim mtcc As MatchCollection
        Set mtcc = .Execute(Subject)
        
        If mtcc.Count < Index Then
            RegEx_Position = CVErr(xlErrNA)
        Else
            RegEx_Position = mtcc.Item(Index - 1).FirstIndex + 1
        End If
    End With
    
End Function

このとき,文字列の先頭の文字を 0 としてカウントするので,最後に 1 を加算した方が直感的な動作になると思います.

なお,指定したパターンに一致する部分が n 個未満しか存在しない場合は,エラー値 #N/A を返すようにしています.これは次の項も同様です.

指定した正規表現パターンに,n 番目に一致した箇所の値を得る.

たとえば,「"hoge65 fuga43 piyo21" という文字列で,5 番目に出現した数字は何か」を調べる場合に必要になります.

この場合は,上の項で述べた,n - 1 番目の Match オブジェクトの Value プロパティを取得しましょう.

Public Function RegEx_Value(ByVal Subject As String _
                          , ByVal Pattern As String _
                          , ByVal Index As Long _
                          , Optional ByVal IgnoreCase As Boolean = False) As Variant
    
    With re
        .Pattern = Pattern
        .IgnoreCase = IgnoreCase
        .Global = True
        
        Dim mtcc As MatchCollection
        Set mtcc = .Execute(Subject)
        
        If mtcc.Count < Index Then
            RegEx_Value = CVErr(xlErrNA)
        Else
            RegEx_Value = mtcc.Item(Index - 1).Value
        End If
    End With
    
End Function

これで,業務に必要な関数は大方揃うのではないかと思います.
でも,もしかしたら続く‥かも?