正規表現検索
複雑な「パターンで探す・抽出する・置換する」なら正規表現が最短で強力。メール、電話番号、郵便番号、コード形式、日付の抽出や検証を、初心者向けに安全テンプレと例題でまとめます。
事前準備(2つの使い方)
- 手早い方法(Late Binding):参照設定不要
Dim re As Object Set re = CreateObject("VBScript.RegExp")- そのまま動く。配布に向く。
- 補完が効く方法(Early Binding):参照設定あり
- VBEの「ツール」→「参照設定」→「Microsoft VBScript Regular Expressions 5.5」にチェック。
Dim re As RegExp Set re = New RegExp - 基本プロパティ(よく使うだけ)
Pattern: 正規表現文字列IgnoreCase: 大文字小文字を無視(True/False)Global: 全件取得・置換(True)、最初の1件のみ(False)- 主な関数:
Test(一致有無)、Execute(一致一覧)、Replace(置換)
最短テンプレ(一致判定・抽出・置換)
'1) 一致判定(Test)
Sub Regex_Test()
Dim re As Object: Set re = CreateObject("VBScript.RegExp")
re.Pattern = "^[A-Z]{3}-\d{4}$" '例:ABC-1234
re.IgnoreCase = False: re.Global = False
If re.Test("ABC-1234") Then
MsgBox "一致しました"
Else
MsgBox "不一致です"
End If
End Sub
'2) 全ヒット抽出(Execute)
Sub Regex_Execute_All()
Dim re As Object, ms As Object, m As Object
Set re = CreateObject("VBScript.RegExp")
re.Pattern = "\b\d{3}-\d{4}\b" '例:郵便番号 123-4567
re.Global = True: re.IgnoreCase = True
Set ms = re.Execute("住所:123-4567 他 987-6543")
For Each m In ms
Debug.Print m.Value 'ヒット文字列
Next
End Sub
'3) 置換(Replace)
Sub Regex_Replace_Mask()
Dim re As Object: Set re = CreateObject("VBScript.RegExp")
re.Pattern = "(\d{3})-(\d{4})"
re.Global = True
Dim s As String
s = "郵便:123-4567, 987-6543"
Debug.Print re.Replace(s, "$1-****") '→ 123-****, 987-****
End Sub
VB- ポイント:
^(先頭)、$(末尾)、\d(数字)、\w(英数下線)、{n}(回数)、[](文字クラス)、()(グループ)、|(OR)を覚えると実務は大体いけます。- 置換の
$1は1番目のグループ参照。
セル範囲を正規表現で検索(全件列挙)
Sub Regex_FindAll_InRange()
Dim re As Object: Set re = CreateObject("VBScript.RegExp")
re.Pattern = "\bERROR\d{3}\b" '例:ERROR123 のようなタグ
re.IgnoreCase = True: re.Global = False
Dim last As Long, r As Long, s As String
last = Cells(Rows.Count, "A").End(xlUp).Row
For r = 2 To last
s = CStr(Cells(r, "A").Value)
If re.Test(s) Then
Cells(r, "A").Font.Color = vbRed
End If
Next
End Sub
VB- ポイント: 全件抽出(Execute)で部分ごと取りたい場合は、各セルで
re.Execute(s)を回してFor Each m In msで拾う。
抽出シートへコピー(複数ヒット対応)
Sub Regex_ExtractToSheet()
Dim re As Object: Set re = CreateObject("VBScript.RegExp")
re.Pattern = "\b[A-Z]{3}-\d{4}\b" 'コードABC-1234
re.Global = True: re.IgnoreCase = False
Dim last As Long: last = Cells(Rows.Count, "A").End(xlUp).Row
Dim out As Worksheet: Set out = Worksheets("抽出")
Dim outRow As Long: outRow = 2
Dim r As Long, s As String, ms As Object, m As Object
For r = 2 To last
s = CStr(Cells(r, "A").Value)
Set ms = re.Execute(s)
If ms.Count > 0 Then
For Each m In ms
out.Cells(outRow, 1).Value = m.Value
out.Cells(outRow, 2).Value = r '元の行番号
outRow = outRow + 1
Next
End If
Next
End Sub
VB- ポイント: 1セルに複数パターンがあるケースにも強い。
代表パターン集(コピペOK)
- メールアドレス(ゆるめ)
re.Pattern = "^[\w\.\-]+@[\w\.\-]+\.\w{2,}$"
VB- 電話番号(ハイフン区切り 2-4-4 または 3-3-4)
re.Pattern = "\b(?:\d{2,4}-\d{2,4}-\d{4})\b"
VB- 郵便番号(123-4567)
re.Pattern = "\b\d{3}-\d{4}\b"
VB- 日付(YYYY/MM/DD または YYYY-MM-DD)
re.Pattern = "\b\d{4}[-/]\d{1,2}[-/]\d{1,2}\b"
VB- 英大字3-数字4(ABC-1234)
re.Pattern = "\b[A-Z]{3}-\d{4}\b"
VB- 備考: 厳密検証が必要なら月/日の妥当性チェックを追加で行う(例:分岐または後段でDateValueをTry)。
グループで部分取り(キャプチャを使う)
Sub Regex_CaptureGroups()
Dim re As Object, ms As Object, m As Object
Set re = CreateObject("VBScript.RegExp")
re.Pattern = "(\d{3})-(\d{4})"
re.Global = True
Set ms = re.Execute("郵便:123-4567 他 987-6543")
For Each m In ms
Debug.Print "全部=" & m.Value & ", 前半=" & m.SubMatches(0) & ", 後半=" & m.SubMatches(1)
Next
End Sub
VB- ポイント:
SubMatches(index)で括弧の中身が取れる。
高速・安全ラップ(大量処理の基本)
Sub Regex_SafeWrap_Start()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
End Sub
Sub Regex_SafeWrap_End()
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
VB- 使い方: 前後に挟むだけで体感速度が段違い。エラー時は
On Errorで必ず復帰。
よくある落とし穴と対策
- 改行をまたぐ一致が取れない
- 対策: 1セルに改行がある場合は正規表現では行頭・行末の扱いが変わる。必要なら文字列を事前に
Replace(s, vbCrLf, " ")などで正規化。
- 対策: 1セルに改行がある場合は正規表現では行頭・行末の扱いが変わる。必要なら文字列を事前に
- 日本語と記号の混在で過剰ヒット
- 対策: 境界
\bは英数字境界中心。日本語混在時は前後を記号・空白で囲うパターンにする、または(^|[^A-Za-z0-9])…([^A-Za-z0-9]|$)のように明示境界を定義。
- 対策: 境界
- 大文字小文字で漏れる
- 対策:
IgnoreCase=True。厳密に区別したい列だけ False に。
- 対策:
- 最初の1件しか取れない
- 対策:
Global=Trueを忘れない。全件抽出や全置換は必須設定。
- 対策:
- 過度に複雑なパターンで遅い
- 対策: まず範囲を絞る(対象列やフィルタで)→正規表現を簡素化→前処理で正規化(空白や記号除去)すると速く安定。
例題で練習
'例1:A列からメールを抽出して「抽出」シートへ一覧
Sub Example_ExtractEmails()
Dim re As Object: Set re = CreateObject("VBScript.RegExp")
re.Pattern = "[\w\.\-]+@[\w\.\-]+\.\w{2,}"
re.Global = True: re.IgnoreCase = True
Dim last As Long: last = Cells(Rows.Count, "A").End(xlUp).Row
Dim out As Worksheet: Set out = Worksheets("抽出")
Dim outRow As Long: outRow = 2
Dim r As Long, s As String, ms As Object, m As Object
For r = 2 To last
s = CStr(Cells(r, "A").Value)
Set ms = re.Execute(s)
For Each m In ms
out.Cells(outRow, 1).Value = m.Value
out.Cells(outRow, 2).Value = r
outRow = outRow + 1
Next
Next
End Sub
'例2:A列の電話番号を「市外局番-****-****」でマスク
Sub Example_MaskPhones()
Dim re As Object: Set re = CreateObject("VBScript.RegExp")
re.Pattern = "(\d{2,4})-(\d{2,4})-(\d{4})"
re.Global = True
Dim last As Long: last = Cells(Rows.Count, "A").End(xlUp).Row
Dim r As Long, s As String
For r = 2 To last
s = CStr(Cells(r, "A").Value)
Cells(r, "A").Value = re.Replace(s, "$1-****-****")
Next
End Sub
'例3:行内の「YYYY/MM/DD」を検証後、B列へ日付型で格納
Sub Example_ExtractDateToB()
Dim re As Object: Set re = CreateObject("VBScript.RegExp")
re.Pattern = "(\d{4})[-/](\d{1,2})[-/](\d{1,2})"
re.Global = False
Dim last As Long: last = Cells(Rows.Count, "A").End(xlUp).Row
Dim r As Long, s As String, ms As Object, m As Object, y As Integer, mth As Integer, d As Integer
For r = 2 To last
s = CStr(Cells(r, "A").Value)
Set ms = re.Execute(s)
If ms.Count > 0 Then
Set m = ms(0)
y = CInt(m.SubMatches(0)): mth = CInt(m.SubMatches(1)): d = CInt(m.SubMatches(2))
On Error Resume Next
Cells(r, "B").Value = DateSerial(y, mth, d) '妥当でない日付はエラーでスキップ
On Error GoTo 0
End If
Next
End Sub
VB