正規表現(RegExp)

にメンテナンス済み

VBA で文字列処理を行う際、単純な検索や置換では対応できない複雑なパターンマッチングが必要になることがあります。そんなときに威力を発揮するのが 正規表現(RegExp) です。

正規表現を使えば、メールアドレスの形式チェック、電話番号の抽出、特定パターンの文字列置換など、高度な文字列操作を効率的に実現できます。

この記事では、VBA で正規表現を使用するための RegExp オブジェクト について、基本から実践的な活用例まで詳しく解説します。

正規表現が必要となるシチュエーション

実務では、以下のような場面で正規表現が威力を発揮します:

  • 入力値の検証: メールアドレス、電話番号、郵便番号などの形式チェック
  • データの抽出: HTML やテキストから特定パターンの文字列を取得
  • 複雑な置換: 特定のパターンに一致する部分だけを別の形式に変換
  • ログファイルの解析: 日付や IP アドレスなど特定形式のデータを抽出
  • データクレンジング: 不要な文字や空白を一括削除
チェック

正規表現は、InStr や Replace 関数では難しい「パターンに基づくマッチング」を可能にします。

RegExp オブジェクトの基本

RegExp オブジェクトの生成方法

VBA で正規表現を使用するには、VBScript.RegExp オブジェクトを生成します。生成方法は 2 つあります。

方法 1:参照設定を使用する方法(事前バインディング)

VBA エディタで「ツール」→「参照設定」から Microsoft VBScript Regular Expressions 5.5 にチェックを入れます。

regexp_early_binding.bas
Sub RegExpEarlyBinding()
    ' 参照設定が必要
    Dim re As RegExp
    Set re = New RegExp

    re.Pattern = "\d+"
    Debug.Print re.Test("abc123")  ' True
End Sub

方法 2:CreateObject を使用する方法(遅延バインディング)

参照設定なしで使用できる方法です。汎用性が高いため、こちらが推奨されます。

regexp_late_binding.bas
Sub RegExpLateBinding()
    ' 参照設定不要
    Dim re As Object
    Set re = CreateObject("VBScript.RegExp")

    re.Pattern = "\d+"
    Debug.Print re.Test("abc123")  ' True
End Sub
チェック

CreateObject を使用する方法は、参照設定が不要なため、他の環境でマクロを共有する際にも問題が起きにくいです。

RegExp の主要プロパティ

RegExp オブジェクトには、以下の重要なプロパティがあります。

プロパティ説明既定値
Pattern検索する正規表現パターンなし
Global文字列全体を検索するかFalse
IgnoreCase大文字小文字を区別しないかFalse
MultiLine複数行モードを有効にするかFalse

Pattern プロパティ

検索に使用する正規表現パターンを指定します。

pattern_example.bas
Sub PatternExample()
    Dim re As Object
    Set re = CreateObject("VBScript.RegExp")

    ' 数字のパターン
    re.Pattern = "\d+"
    Debug.Print re.Test("Order123")  ' True

    ' メールアドレスのパターン
    re.Pattern = "[\w\.-]+@[\w\.-]+\.\w+"
    Debug.Print re.Test("[email protected]")  ' True
End Sub

Global プロパティ

GlobalTrue に設定すると、文字列全体を検索して すべての一致 を返します。False(既定値)の場合は 最初の一致 のみを返します。

global_example.bas
Sub GlobalExample()
    Dim re As Object
    Set re = CreateObject("VBScript.RegExp")

    re.Pattern = "\d+"

    ' Global = False(既定):最初の一致のみ
    re.Global = False
    Dim matches As Object
    Set matches = re.Execute("abc123def456ghi789")
    Debug.Print "Global=False: " & matches.Count & " 件"  ' 1 件

    ' Global = True:すべての一致
    re.Global = True
    Set matches = re.Execute("abc123def456ghi789")
    Debug.Print "Global=True: " & matches.Count & " 件"  ' 3 件
End Sub

IgnoreCase プロパティ

IgnoreCaseTrue に設定すると、大文字小文字を区別せずに検索します。

ignorecase_example.bas
Sub IgnoreCaseExample()
    Dim re As Object
    Set re = CreateObject("VBScript.RegExp")

    re.Pattern = "hello"

    ' IgnoreCase = False(既定):大文字小文字を区別
    re.IgnoreCase = False
    Debug.Print re.Test("HELLO")  ' False

    ' IgnoreCase = True:大文字小文字を区別しない
    re.IgnoreCase = True
    Debug.Print re.Test("HELLO")  ' True
End Sub

RegExp の主要メソッド

RegExp オブジェクトには、3 つの主要なメソッドがあります。

メソッド説明戻り値
Testパターンが一致するかチェックBoolean
Execute一致した文字列を取得MatchCollection
Replace一致した文字列を置換String

Test メソッド:パターンの一致をチェック

Test メソッドは、文字列がパターンに一致するかどうかを True または False で返します。入力値の検証に最適です。

test_method.bas
Sub TestMethodExample()
    Dim re As Object
    Set re = CreateObject("VBScript.RegExp")

    ' 電話番号の形式チェック(例:090-1234-5678)
    re.Pattern = "^0\d{1,4}-\d{1,4}-\d{4}$"

    Debug.Print re.Test("090-1234-5678")  ' True
    Debug.Print re.Test("03-1234-5678")   ' True
    Debug.Print re.Test("1234567890")     ' False
    Debug.Print re.Test("abc-defg-hijk")  ' False
End Sub

Execute メソッド:一致した文字列を取得

Execute メソッドは、パターンに一致した文字列を MatchCollection オブジェクト として返します。各一致は Match オブジェクト として格納されています。

execute_method.bas
Sub ExecuteMethodExample()
    Dim re As Object
    Set re = CreateObject("VBScript.RegExp")

    re.Pattern = "\d+"
    re.Global = True

    Dim text As String
    text = "商品A: 1500円、商品B: 2300円、商品C: 980円"

    Dim matches As Object
    Set matches = re.Execute(text)

    Dim m As Object
    For Each m In matches
        Debug.Print "一致: " & m.Value & " (位置: " & m.FirstIndex & ")"
    Next m

    ' 出力:
    ' 一致: 1500 (位置: 5)
    ' 一致: 2300 (位置: 16)
    ' 一致: 980 (位置: 27)
End Sub

Match オブジェクトのプロパティ

プロパティ説明
Value一致した文字列
FirstIndex一致した位置(0 始まり)
Length一致した文字列の長さ
SubMatchesキャプチャグループに一致した文字列集合

Replace メソッド:文字列の置換

Replace メソッドは、パターンに一致した部分を指定した文字列で置換します。

replace_method.bas
Sub ReplaceMethodExample()
    Dim re As Object
    Set re = CreateObject("VBScript.RegExp")

    re.Pattern = "\s+"  ' 連続する空白
    re.Global = True

    Dim text As String
    text = "これは    テスト   文字列   です"

    ' 連続する空白を単一の空白に置換
    Dim result As String
    result = re.Replace(text, " ")

    Debug.Print result  ' "これは テスト 文字列 です"
End Sub

置換での後方参照

キャプチャグループを使用して、一致した部分を置換文字列で再利用できます。$1$2 などで参照します。

replace_backreference.bas
Sub ReplaceBackreferenceExample()
    Dim re As Object
    Set re = CreateObject("VBScript.RegExp")

    ' 日付形式の変換:YYYY/MM/DD → YYYY年MM月DD日
    re.Pattern = "(\d{4})/(\d{2})/(\d{2})"
    re.Global = True

    Dim text As String
    text = "期日: 2025/07/02、締切: 2025/12/31"

    Dim result As String
    result = re.Replace(text, "$1年$2月$3日")

    Debug.Print result  ' "期日: 2025年07月02日、締切: 2025年12月31日"
End Sub

よく使う正規表現パターン

実務でよく使用する正規表現パターンをまとめました。

数値関連

patterns_numbers.bas
' 整数
re.Pattern = "^\d+$"

' 小数(正の数)
re.Pattern = "^\d+(\.\d+)?$"

' 負の数を含む整数
re.Pattern = "^-?\d+$"

' 3桁カンマ区切りの数値
re.Pattern = "^\d{1,3}(,\d{3})*$"

連絡先関連

patterns_contact.bas
' メールアドレス
re.Pattern = "^[\w\.-]+@[\w\.-]+\.\w+$"

' 電話番号(ハイフンあり)
re.Pattern = "^0\d{1,4}-\d{1,4}-\d{4}$"

' 郵便番号
re.Pattern = "^\d{3}-\d{4}$"

日付・時刻関連

patterns_datetime.bas
' 日付(YYYY/MM/DD または YYYY-MM-DD)
re.Pattern = "^\d{4}[/-]\d{2}[/-]\d{2}$"

' 時刻(HH:MM:SS)
re.Pattern = "^\d{2}:\d{2}:\d{2}$"

' 日時(YYYY/MM/DD HH:MM:SS)
re.Pattern = "^\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}$"

実践的な活用例

例 1:メールアドレスの検証関数

validate_email.bas
Function IsValidEmail(email As String) As Boolean
    Dim re As Object
    Set re = CreateObject("VBScript.RegExp")

    ' メールアドレスのパターン
    re.Pattern = "^[\w\.-]+@[\w\.-]+\.[a-zA-Z]{2,}$"
    re.IgnoreCase = True

    IsValidEmail = re.Test(email)
End Function

Sub TestEmailValidation()
    Debug.Print IsValidEmail("[email protected]")      ' True
    Debug.Print IsValidEmail("[email protected]")  ' True
    Debug.Print IsValidEmail("invalid-email")         ' False
    Debug.Print IsValidEmail("@example.com")          ' False
End Sub

例 2:テキストから URL を抽出

extract_urls.bas
Sub ExtractURLs()
    Dim re As Object
    Set re = CreateObject("VBScript.RegExp")

    ' URL パターン
    re.Pattern = "https?://[\w\-\.]+(/[\w\-\./?%&=]*)?"
    re.Global = True
    re.IgnoreCase = True

    Dim text As String
    text = "参考サイト: https://www.example.com/page1 と " & _
           "http://sub.example.org/path?id=123 をご覧ください。"

    Dim matches As Object
    Set matches = re.Execute(text)

    Debug.Print "検出された URL:"
    Dim m As Object
    For Each m In matches
        Debug.Print "  " & m.Value
    Next m

    ' 出力:
    ' 検出された URL:
    '   https://www.example.com/page1
    '   http://sub.example.org/path?id=123
End Sub

例 3:個人情報のマスキング

mask_personal_info.bas
Function MaskPhoneNumber(text As String) As String
    Dim re As Object
    Set re = CreateObject("VBScript.RegExp")

    ' 電話番号パターン(最後の4桁をマスク)
    re.Pattern = "(0\d{1,4}-\d{1,4}-)(\d{4})"
    re.Global = True

    MaskPhoneNumber = re.Replace(text, "$1****")
End Function

Function MaskEmail(text As String) As String
    Dim re As Object
    Set re = CreateObject("VBScript.RegExp")

    ' メールアドレスのユーザー名部分をマスク
    re.Pattern = "([\w\.-]{1,3})([\w\.-]*)(@[\w\.-]+\.\w+)"
    re.Global = True

    MaskEmail = re.Replace(text, "$1***$3")
End Function

Sub TestMasking()
    Dim text As String

    ' 電話番号のマスキング
    text = "連絡先: 090-1234-5678、自宅: 03-9876-5432"
    Debug.Print MaskPhoneNumber(text)
    ' 出力: 連絡先: 090-1234-****、自宅: 03-9876-****

    ' メールアドレスのマスキング
    text = "メール: [email protected]、予備: [email protected]"
    Debug.Print MaskEmail(text)
    ' 出力: メール: tan***@example.com、予備: yam***@mail.co.jp
End Sub

例 4:CSV データの整形

clean_csv.bas
Sub CleanCSVData()
    Dim re As Object
    Set re = CreateObject("VBScript.RegExp")

    Dim text As String
    text = "  田中,  東京都新宿区  ,  090-1234-5678  "

    ' 1. 項目前後の空白を削除
    re.Pattern = "\s*,\s*"
    re.Global = True
    text = re.Replace(text, ",")

    ' 2. 先頭・末尾の空白を削除
    re.Pattern = "^\s+|\s+$"
    text = re.Replace(text, "")

    Debug.Print text  ' "田中,東京都新宿区,090-1234-5678"
End Sub
チェック

VBScript.RegExp の廃止予定について

Microsoft は VBScript の廃止を発表しており、将来的に VBScript.RegExp も使用できなくなる可能性があります。Office 365 の VBA では新しい正規表現機能がサポートされていますが、買い切り版 Office では未対応の場合があります。

現時点では VBScript.RegExp が最も広く使われている方法ですが、長期的なプロジェクトでは代替手段の検討も必要です。

正規表現のパフォーマンスに関する注意点

正規表現は強力ですが、使い方によってはパフォーマンスに影響する場合があります。

RegExp オブジェクトの再利用

同じパターンを繰り返し使用する場合は、RegExp オブジェクトを使い回すことで効率が向上します。

reuse_regexp.bas
' 非効率な例:毎回 RegExp を生成
Sub IneffientExample()
    Dim i As Long
    For i = 1 To 10000
        Dim re As Object
        Set re = CreateObject("VBScript.RegExp")  ' 毎回生成
        re.Pattern = "\d+"
        ' ... 処理
    Next i
End Sub

' 効率的な例:RegExp を再利用
Sub EfficientExample()
    Dim re As Object
    Set re = CreateObject("VBScript.RegExp")  ' 一度だけ生成
    re.Pattern = "\d+"

    Dim i As Long
    For i = 1 To 10000
        ' re を再利用
        ' ... 処理
    Next i
End Sub
チェック

大量のデータを処理する場合は、RegExp オブジェクトをモジュールレベルの変数として定義し、複数のプロシージャで共有することも検討してください。

まとめ

VBA の正規表現(RegExp)について、以下の内容を解説しました。

  • RegExp オブジェクトの生成方法: CreateObject("VBScript.RegExp") による遅延バインディングが推奨
  • 主要プロパティ: PatternGlobalIgnoreCaseMultiLine
  • 主要メソッド: Test(検証)、Execute(抽出)、Replace(置換)
  • 実践的な活用例: メールアドレス検証、URL 抽出、個人情報マスキング、データ整形

正規表現を使いこなすことで、複雑な文字列操作を効率的に行えるようになります。最初は難しく感じるかもしれませんが、よく使うパターンを覚えて少しずつ応用範囲を広げていくことで、VBA での文字列処理の幅が大きく広がります。

#VBA #正規表現 #RegExp #パターンマッチング