「半角・全角が混ざった文字列を整えたい」「メールアドレスが正しい形式か一発でチェックしたい」。VBAでデータ処理をしていると、こんな場面によく出くわしますよね。
TRIMやSUBSTITUTE、LEFTやMIDなどの文字列関数を組み合わせれば、簡単な処理ならなんとかなります。でも「数字3桁+ハイフン+数字4桁」のような「形のパターン」を扱おうとすると、とたんに数式が長く複雑になります。書いた本人すら後で読めなくなる、なんてこともありますよね。
そんな複雑な文字列処理を一気にシンプルにしてくれるのが、VBAの正規表現(RegExp)です。「特定の形に一致するか」「一致した部分だけ取り出す」「一致した部分だけ置き換える」といった処理を、短いパターン文字列で表現できます。
この記事では、VBAで正規表現を使う方法を、準備から実務パターンまで丁寧に解説します。コピペで使えるサンプルコード5本と、ブックマークしておくと便利なメタ文字の早見表も用意しました。正規表現に触れたことがない方でも、読み終わるころには自分のマクロに組み込めるようになりますよ。
VBAで正規表現が必要になる場面
正規表現は「文字列の形(パターン)」を表現するための記法です。たとえば「数字が3桁続く」「先頭が0で始まる電話番号」といったルールを、短い記号の並びで書き表せます。
VBAでは標準の文字列関数も豊富に用意されています。ではなぜ、わざわざ正規表現を使うのでしょうか。それは、文字列関数だけでは「形のパターン」を扱うのが苦手だからです。
ここでは、正規表現が本当に役立つ場面を整理します。逆に言えば、ここで挙げる悩みがなければ無理に使う必要はありません。適材適所で使い分けるのがコツですよ。
TRIM・SUBSTITUTEでは対処できないケースとは
VBAの文字列関数は「決まった位置」や「決まった文字」を扱うのは得意です。たとえば前後の空白を消すならTRIM、特定の文字を別の文字に置き換えるならSUBSTITUTE(Replace関数)で十分です。
ところが、次のようなケースになると一気に難しくなります。
- 「数字が3桁、ハイフン、数字が4桁」のように、文字の「並び方のルール」で判定したい
- セルの中に紛れ込んだ郵便番号や電話番号だけを取り出したい
- 全角の英数字が混ざっているかどうかを検出したい
- 複数種類の記号をまとめて一括削除したい
たとえば「文字列がメールアドレスの形式か」を文字列関数だけで判定するとします。アットマークの有無、ドットの位置、前後の文字種など、無数のIf文が必要になります。考えただけで気が遠くなりますよね。
これを正規表現なら、たった1行のパターンで表現できます。「形のルールで判定・抽出・置換したい」という場面こそ、正規表現の出番なのです。
Like演算子との使い分け基準
VBAには正規表現に似た機能として、Like演算子があります。If 文字列 Like "A*" のように、ワイルドカードを使った曖昧な比較ができる演算子です。
Like演算子は手軽で、参照設定も不要です。「Aで始まる」「数字を1文字含む」程度の単純な判定なら、Like演算子のほうが速く書けます。
ただしLike演算子には限界があります。「数字が3桁以上連続する」のような繰り返し回数の指定や、一致した部分の抽出はできません。複雑なパターンになるほど、正規表現に軍配が上がります。
ざっくりした使い分けの目安は次のとおりです。
| 用途 | おすすめ |
|---|---|
| 「〜で始まる」「〜を含む」程度の単純判定 | Like演算子 |
| 繰り返し回数や文字種の細かい指定 | 正規表現(RegExp) |
| 一致した部分を取り出したい(抽出) | 正規表現(RegExp) |
| パターンに一致する全箇所を置換したい | 正規表現(RegExp) |
Like演算子の詳しい使い方は、VBA Like演算子の使い方|ワイルドカード5種で文字列を曖昧比較する方法で解説しています。「Likeでは難しいな」と感じたら正規表現へ、と覚えておくとスムーズですよ。
RegExpオブジェクトの準備
VBAの正規表現は、RegExpという専用のオブジェクトを使って動かします。このRegExpは、もともとVBScript用に作られた正規表現エンジンです。Windowsに標準で組み込まれているCOMコンポーネントなので、Excel VBAから呼び出して使えます。
RegExpオブジェクトを用意する方法は2つあります。1つは「参照設定」をする方法(早期バインディング)、もう1つはCreateObject関数で呼び出す方法(遅延バインディング)です。
どちらでも同じことができますが、メリットが異なります。まずは両方の手順を見て、最後に使い分けの基準を整理しますね。なお、この記事のコードはExcel 2019・2021・Microsoft 365のいずれでも動作します。
参照設定あり(早期バインディング)の手順
参照設定をしておくと、コードの記述が少しスッキリし、入力補助(IntelliSense)も効くようになります。手順は次のとおりです。
まずVBE(Visual Basic Editor)を開きます。ExcelでAlt + F11キーを押すか、開発タブの「Visual Basic」ボタンから開けます。開発タブが表示されていない場合は、ファイル → オプション → リボンのユーザー設定で「開発」にチェックを入れてください。
VBEが開いたら、メニューの「ツール」→「参照設定」を選びます。一覧から「Microsoft VBScript Regular Expressions 5.5」を探してチェックを入れ、OKを押します。これで準備完了です。
!_images/excel-vba-regexp-howto/01_screenshot_vbe-reference-setting.png
参照設定をした場合、RegExpオブジェクトは次のように宣言します。
Sub RegExp早期バインディング例()
Dim re As New RegExp '参照設定でRegExp型が使えるようになる
re.Pattern = "d{3}" 'パターン: 数字が3桁連続
re.Global = True '一致する全箇所を対象にする
MsgBox re.Test("商品コード123") '「123」を含むのでTrueが返る
End Sub
Dim re As New RegExp のように型名を直接書ける点が、参照設定のメリットです。入力中に候補が出るので、プロパティ名のタイプミスも防げますよ。
CreateObjectあり(遅延バインディング)の手順
もう1つの方法が、CreateObject関数を使う遅延バインディングです。参照設定が不要なので、マクロを他の人に配布するときに便利です。
宣言と作成は次のように書きます。
Sub RegExp遅延バインディング例()
Dim re As Object '型は汎用のObjectで宣言する
Set re = CreateObject("VBScript.RegExp") 'RegExpを実行時に生成
re.Pattern = "d{3}" 'パターン: 数字が3桁連続
re.Global = True '一致する全箇所を対象にする
MsgBox re.Test("商品コード123") '「123」を含むのでTrueが返る
End Sub
ポイントは2つです。1つ目は、変数を As Object で宣言すること。2つ目は、Set re = CreateObject("VBScript.RegExp") でオブジェクトを生成することです。
参照設定をしていない環境でもそのまま動くので、社内の複数のパソコンでマクロを共有する場合はこちらが安心です。「あれ、参照設定し忘れた」というトラブルが起きませんよ。
早期 vs 遅延 どちらを選ぶか比較表
早期バインディングと遅延バインディングは、それぞれ得意な場面が違います。次の比較表で整理しました。
| 比較項目 | 早期バインディング(参照設定) | 遅延バインディング(CreateObject) |
|---|---|---|
| 参照設定 | 必要 | 不要 |
| 宣言の書き方 | Dim re As New RegExp | Dim re As Object + CreateObject |
| 入力補助(IntelliSense) | 効く | 効かない |
| 実行速度 | 速い | やや遅い |
| 配布マクロへの向き | 配布先でも参照設定が必要 | 環境を選ばず動く |
Microsoftは、可能な限り早期バインディングを使うことを公式に推奨しています。自分専用のマクロや、速度を重視したい処理では早期バインディングが向いています。
一方で、配布先の環境がわからない場合や、複数バージョンのExcel間で使い回したい場合は、遅延バインディングが安全です。「自分用は早期、配布用は遅延」と覚えておくと迷いませんよ。
なお、この記事のサンプルコードは、どちらの方式でもそのまま動くように書いていきます。
RegExpの3つのプロパティと3つのメソッド
RegExpオブジェクトは、3つのプロパティと3つのメソッドさえ押さえれば使いこなせます。覚えることが少ないのは、うれしいポイントですよね。
プロパティは「どう探すか」の設定で、Pattern・Global・IgnoreCaseの3つです。メソッドは「何をするか」の動作で、Test・Replace・Executeの3つです。
ここからは、それぞれを順番に見ていきます。この6つを理解すれば、後半の実務パターンもすんなり読めるようになりますよ。
Pattern・IgnoreCase・Globalの設定方法
まずは3つのプロパティです。RegExpオブジェクトを作ったあと、探す前に設定しておきます。
Sub プロパティの設定例()
Dim re As Object
Set re = CreateObject("VBScript.RegExp")
re.Pattern = "[a-z]+" '探したいパターンを指定する(必須)
re.IgnoreCase = True '大文字小文字を区別しない(既定はFalse)
re.Global = True '一致する全箇所を対象にする(既定はFalse)
MsgBox re.Test("Hello") 'IgnoreCase=TrueなのでTrueが返る
End Sub
3つのプロパティの役割をまとめます。
- Pattern:探す正規表現のパターンを文字列で指定します。これがないと始まりません。
- IgnoreCase:Trueにすると、大文字と小文字を区別せず一致を判定します。既定値はFalseです。
- Global:Trueにすると、一致する箇所をすべて対象にします。既定値のFalseだと、最初の1件だけが対象です。
特に注意したいのがGlobalです。既定はFalseなので、置換や抽出で「全部のはずなのに1件しか処理されない」というときは、たいていGlobalの設定漏れですよ。
Test:パターン一致チェック
Testメソッドは、文字列がパターンに一致する箇所を含むかどうかを判定します。戻り値はTrueまたはFalseのブール値です。
Sub Testメソッドの例()
Dim re As Object
Set re = CreateObject("VBScript.RegExp")
re.Pattern = "d+" '数字が1文字以上続く
MsgBox re.Test("注文番号A100") 'True(100が一致する)
MsgBox re.Test("注文番号なし") 'False(数字がない)
End Sub
「一致するものが含まれていればTrue」という単純な動きです。入力チェックやバリデーションにぴったりですね。
文字列全体が完全に一致するかを判定したいときは、パターンの先頭に ^、末尾に $ を付けます。^ は文字列の先頭、$ は末尾を表すアンカーです。この使い方は実務パターンのメールアドレス検証で詳しく見ていきます。
このTestメソッドは、Microsoft 365のワークシート関数REGEXTESTと同じ役割を果たします。数式で完結させたいか、マクロで処理したいかで使い分けるとよいですよ。
Replace:パターン一致部分の置換
Replaceメソッドは、パターンに一致した部分を別の文字列に置き換えて返します。Replace(対象文字列, 置換後の文字列) の形で呼び出します。
Sub Replaceメソッドの例()
Dim re As Object
Set re = CreateObject("VBScript.RegExp")
re.Pattern = "s+" '空白文字(スペース・タブなど)が1文字以上
re.Global = True '全箇所を対象にする
Dim result As String
result = re.Replace("山田 太郎 さん", "") '空白をすべて削除
MsgBox result '「山田太郎さん」が返る
End Sub
この例では、半角の空白をまとめて削除しています。s は半角スペースやタブなどの空白文字を表すので、種類を気にせず一括で消せるのが便利です。なお全角スペースの扱いには注意が必要で、これは後述の早見表でくわしく補足します。
置換後の文字列に空文字("")を指定すると、一致部分の「削除」になります。不要な記号の一括削除でよく使うテクニックですよ。なお、一致部分を残したまま前後に文字を足したい場合は、キャプチャグループと後方参照($1 など)を使います。
ワークシート関数のREGEXREPLACEも同じ置換処理を担当します。大量データをループ処理するならVBA、セル単位で完結させるなら関数、という選び方がおすすめです。
Execute:マッチ結果のコレクション取得
Executeメソッドは、一致した箇所の情報をまとめたコレクション(MatchCollection)を返します。「一致したものを取り出したい(抽出したい)」ときに使います。
Sub Executeメソッドの例()
Dim re As Object
Set re = CreateObject("VBScript.RegExp")
re.Pattern = "d+" '数字が1文字以上続く
re.Global = True '全箇所を取り出す
Dim matches As Object, m As Object
Set matches = re.Execute("価格は1200円、送料は500円")
Dim msg As String
For Each m In matches
msg = msg & m.Value & vbCrLf '一致した文字列を取り出す
Next m
MsgBox msg '「1200」と「500」が改行区切りで表示される
End Sub
Executeが返すMatchCollectionは、For Eachで1件ずつ取り出せます。matches.Count で一致件数も取得できます。
取り出したMatchオブジェクトには、主に3つのプロパティがあります。
- Value:一致した文字列そのもの
- FirstIndex:一致が始まった位置(0から数える)
- Length:一致した文字列の長さ
抽出処理は、ワークシート関数のREGEXEXTRACTに対応します。複数件をまとめてループ処理したいときは、VBAのExecuteが力を発揮しますよ。
よく使うメタ文字と正規表現パターン早見表
正規表現は、記号(メタ文字)を組み合わせてパターンを作ります。最初は呪文のように見えますが、よく使う記号は限られています。
このセクションは早見表としてまとめました。コードを書いていて「あの記号なんだっけ」となったとき、ここに戻ってくれば大丈夫です。ブックマークしておくと便利ですよ。
メタ文字一覧(記号・意味・使用例)
VBScript RegExpの正規表現は、Perl由来のフレーバーです。基本的なメタ文字は他の言語とほぼ共通です。よく使うものを一覧にしました。
| 記号 | 意味 | 使用例 | ||
|---|---|---|---|---|
^ | 文字列の先頭 | ^A → Aで始まる | ||
$ | 文字列の末尾 | 円$ → 円で終わる | ||
b | 単語境界 | bcatb → 単語catだけ | ||
B | 単語境界以外 | Bcat → 単語の途中のcat | ||
. | 改行以外の任意1文字 | a.c → axcなど | ||
w | 半角英数字とアンダースコア([a-zA-Z_0-9]) | w+ → 英数字の連続 | ||
W | w以外の文字 | W → 記号や空白 | ||
d | 数字([0-9]) | d{4} → 数字4桁 | ||
D | 数字以外の文字 | D+ → 数字以外の連続 | ||
s | 空白文字(スペース・タブ・改行など) | s+ → 空白の連続 | ||
S | 空白以外の文字 | S+ → 空白でない連続 | ||
[xyz] | x・y・zのいずれか1文字 | [abc] → a/b/c | ||
[^xyz] | x・y・z以外の1文字 | [^0-9] → 数字以外 | ||
* | 直前の0回以上の繰り返し | a* → 空文字やaaa | ||
+ | 直前の1回以上の繰り返し | a+ → a、aaa | ||
? | 直前の0または1回 | colou?r → colorとcolour | ||
{n} | ちょうどn回 | d{3} → 数字ちょうど3桁 | ||
{n,} | n回以上 | d{2,} → 数字2桁以上 | ||
{n,m} | n回以上m回以下 | d{2,4} → 数字2〜4桁 | ||
(abc) | グループ化・キャプチャ | (d{3})-(d{4}) | ||
| `a | b` | aまたはb | `cat | dog` → catかdog |
1 2 | 後方参照 | 1番目のグループの再利用 |
ここで1つ大事な注意点があります。w や d は、半角の英数字にしか一致しません。日本語(ひらがな・カタカナ・漢字)や全角の英数字には一致しないのです。
日本語を扱いたいときは、文字コードの範囲を直接指定します。たとえばひらがなは [ぁ-ゖ]、カタカナは [ァ-ヺ] のように書きます。全角英数字の扱いは、後半の実務パターンで具体的に解説しますよ。
実務でよく使うパターン集8選
実務でそのまま使えるパターンを8つ厳選しました。Patternプロパティに貼り付けて使えます。コピペ用にどうぞ。
| 用途 | パターン | |
|---|---|---|
| メールアドレス形式(完全一致) | ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,}$ | |
| 電話番号(ハイフン区切り) | ^0d{1,4}-d{1,4}-d{4}$ | |
| 郵便番号(3桁-4桁) | d{3}-d{4} | |
| 半角数字のみ | ^d+$ | |
| URL(httpまたはhttps) | https?://[w./%#&?=-]+ | |
| 全角英数字の検出 | [A-Za-z0-9]+ | |
| 日付(YYYY/MM/DD形式) | d{4}/d{1,2}/d{1,2} | |
| 前後の空白(全角・半角) | `^[s ]+ | [s ]+$` |
最後の空白パターンにある は全角スペースです。VBScript RegExpの s は半角スペースやタブを対象とし、全角スペース(U+3000)には一致しません。全角も確実に対象にしたいときは、このように全角スペースを文字クラスへ明示的に含めると安心ですよ。
それでは、これらのパターンを使った実務コードを次のセクションで見ていきましょう。
実務パターン5選:コピペで使えるサンプルコード
ここからは、実務でそのまま使える5つのパターンを、完成コードとして紹介します。すべてコピペして動かせるように書いています。
5つのパターンは次のとおりです。
- メールアドレス形式チェック
- 電話番号ハイフン統一
- 郵便番号抽出
- 全角英数字→半角変換
- 不要な記号一括削除
それぞれ「どんな場面で使うか」と「コードの中で何が起きているか」を添えています。自分の業務に合わせてパターンを書き換えれば、応用も簡単ですよ。
なお、これらのコードを保存するときは、必ずマクロ有効ブック(.xlsm)形式で保存してください。通常の.xlsx形式ではマクロが保存されず、次に開いたときに消えてしまいます。
①メールアドレス形式チェック
入力された文字列が、メールアドレスの形式として正しいかを判定するコードです。フォーム入力や名簿のチェックで活躍します。
Sub メールアドレス形式チェック()
Dim re As Object
Set re = CreateObject("VBScript.RegExp")
'メールアドレスの形式パターン(完全一致のため^と$で囲む)
re.Pattern = "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,}$"
re.IgnoreCase = True '大文字小文字を区別しない
Dim 対象 As String
対象 = Range("A1").Value 'A1セルの値をチェック対象にする
If re.Test(対象) Then
Range("B1").Value = "OK" '形式が正しい
Else
Range("B1").Value = "形式エラー" '形式が不正
End If
End Sub
パターンを前から読み解いてみます。^[A-Za-z0-9._%+-]+ はアットマークの前の部分で、英数字や一部記号が1文字以上。@ でアットマーク。[A-Za-z0-9.-]+ がドメイン名。.[A-Za-z]{2,}$ で、最後にドットと2文字以上のアルファベットが来て終わる、という意味です。
^ と $ で囲むことで「文字列全体がこの形か」を判定しています。これがないと、余計な文字が混じっていても一致してしまうので注意してくださいね。
なお、このパターンは厳密なRFC準拠ではありません。ただ、実務上のチェックとしては十分な精度がありますよ。
②電話番号ハイフン統一
ハイフンが入っていたり省略されていたりとバラバラな電話番号を、判定するコードです。まずは「正しいハイフン区切りになっているか」をチェックします。
Sub 電話番号フォーマットチェック()
Dim re As Object
Set re = CreateObject("VBScript.RegExp")
'0始まり、ハイフン区切りの電話番号パターン
re.Pattern = "^0d{1,4}-d{1,4}-d{4}$"
Dim i As Long
Dim 最終行 As Long
最終行 = Cells(Rows.Count, 1).End(xlUp).Row 'A列の最終行を取得
For i = 1 To 最終行
If re.Test(Cells(i, 1).Value) Then
Cells(i, 2).Value = "OK" '形式が正しい
Else
Cells(i, 2).Value = "要確認" 'ハイフンの位置が不正
End If
Next i
End Sub
パターンの ^0d{1,4} は、0で始まり数字が1〜4桁続く市外局番の部分です。-d{1,4} が市内局番、-d{4}$ が末尾の4桁を表します。固定電話と携帯電話の両方をカバーできる、ゆるめのパターンです。
ハイフンを除去して数字だけに統一したい場合は、Replaceメソッドを使います。次のように1行で書けますよ。
Sub 電話番号からハイフン削除()
Dim re As Object
Set re = CreateObject("VBScript.RegExp")
re.Pattern = "-" 'ハイフンを対象にする
re.Global = True '全箇所を削除する
Range("C1").Value = re.Replace(Range("A1").Value, "")
'例: 03-1234-5678 → 0312345678
End Sub
ちなみに、このパターンは「+81」で始まる国際電話番号の形式には対応していません。国内の番号を前提としていますので、海外の連絡先を扱うときは別途調整してくださいね。
③郵便番号抽出
住所が1つのセルにまとめて入力されていて、その中から郵便番号だけを取り出したいケースです。Executeメソッドで抽出します。
Sub 郵便番号を抽出()
Dim re As Object
Set re = CreateObject("VBScript.RegExp")
re.Pattern = "d{3}-d{4}" '数字3桁-数字4桁
re.Global = True '複数あれば全部取り出す
Dim matches As Object
Set matches = re.Execute(Range("A1").Value) 'A1から抽出
If matches.Count > 0 Then
Range("B1").Value = matches(0).Value '最初に見つかった郵便番号
Else
Range("B1").Value = "見つかりません"
End If
End Sub
d{3}-d{4} というパターンで、「数字3桁・ハイフン・数字4桁」という郵便番号の形を表しています。matches(0).Value で、最初に見つかった郵便番号を取り出しています。
matches.Count で一致件数を確認してから処理しているのがポイントです。1件も見つからないときに matches(0) へアクセスするとエラーになるので、この件数チェックでガードしています。
複数の郵便番号が含まれる文字列なら、For Eachループですべて取り出せます。Executeは抽出処理の万能選手ですよ。
④全角英数字→半角変換
全角で入力された「ABC123」のような英数字を、半角の「ABC123」に変換するコードです。RegExpとStrConv関数を組み合わせます。
ここで大事なのは、RegExp単体では全角から半角への「変換」はできない、という点です。RegExpは「全角英数字の場所を見つける」役割、実際の変換はVBA標準のStrConv関数が担当します。役割分担で乗り切ります。
Sub 全角英数字を半角に変換()
Dim re As Object
Set re = CreateObject("VBScript.RegExp")
re.Pattern = "[A-Za-z0-9]+" '全角の英大文字・英小文字・数字
re.Global = True '全箇所を対象にする
Dim 元 As String
元 = Range("A1").Value
Dim matches As Object, m As Object
Set matches = re.Execute(元)
Dim 結果 As String
結果 = 元
For Each m In matches
'見つけた全角部分をStrConvで半角に変換し、置き換える
結果 = Replace(結果, m.Value, StrConv(m.Value, vbNarrow))
Next m
Range("B1").Value = 結果 '例: ABC123 → ABC123
End Sub
処理の流れを整理します。まずExecuteで全角英数字のかたまりを見つけます。次に、見つけた1つひとつを StrConv(m.Value, vbNarrow) で半角に変換します。そして、VBA標準のReplace関数で元の全角部分を半角に置き換えています。
vbNarrow は「全角を半角に変換する」というStrConvの定数です。逆に半角を全角にしたいときは vbWide を使います。
文字列の中の英数字だけを半角に揃えたいときに重宝します。日本語の住所や氏名はそのまま残して、英数字だけ整える、といった処理にぴったりですよ。
⑤不要な記号一括削除
文字列に紛れ込んだ全角記号などを、まとめて削除するコードです。コピペで持ち込んだデータに余計な装飾記号が付いている、なんてときに使えます。
Sub 不要な記号を一括削除()
Dim re As Object
Set re = CreateObject("VBScript.RegExp")
'削除したい全角記号を明示的に列挙する(誤削除を防ぐため)
re.Pattern = "[★☆※→←【】「」()・]+"
re.Global = True 'すべての一致箇所を削除する
Range("B1").Value = re.Replace(Range("A1").Value, "")
'例: 【重要】★お知らせ → 重要お知らせ
End Sub
re.Replace(対象, "") のように置換後を空文字にすることで、一致した記号をすべて削除しています。GlobalをTrueにしているので、何個あっても一度で消えます。
ここでのポイントは、削除したい記号を [★☆※→…] のように1つずつ明示的に列挙していることです。[!-/] のような広い範囲指定もできますが、範囲指定は思わぬ文字まで巻き込んで消してしまうリスクがあります。
大切なデータを扱うときほど、「消したい記号だけを並べる」やり方が安全です。少し手間でも、誤削除を防げると考えれば安いものですよ。
エラー処理:不正パターン入力時の対策
正規表現は便利ですが、パターンの書き方を間違えると実行時エラーになります。特に、パターンをユーザー入力やセルの値から動的に組み立てる場合は要注意です。
たとえば閉じカッコのない (d+ のような不正なパターンをセットするとします。TestやExecuteの実行時にエラーが発生して、マクロが止まってしまいます。
こうした事故を防ぐために、エラー処理を組み込んでおきましょう。マクロを安全に動かすための、最後のひと工夫です。
On Error GoToでRegExpエラーを捕捉する
VBAでエラーを捕捉する基本は、On Error GoToステートメントです。エラーが起きたら指定したラベルへジャンプし、メッセージを出して安全に処理を終えられます。
Sub エラー処理つきパターン判定()
Dim re As Object
Set re = CreateObject("VBScript.RegExp")
On Error GoTo エラー処理 'エラー発生時はラベルへジャンプ
re.Pattern = Range("A1").Value 'セルからパターンを取得(不正かもしれない)
Dim 結果 As Boolean
結果 = re.Test(Range("B1").Value) '判定を実行
MsgBox "判定結果: " & 結果
Exit Sub '正常終了(エラー処理を通らないようExit)
エラー処理:
MsgBox "パターンが不正です: " & Err.Description '原因を表示
End Sub
On Error GoTo エラー処理 を宣言しておくと、その後でエラーが起きた瞬間に「エラー処理:」ラベルへ飛びます。Err.Description には、エラーの内容が文字列で入っているので、原因の確認に役立ちます。
注意したいのが、正常終了の直前に置いた Exit Sub です。これがないと、エラーがなくてもそのままエラー処理ラベルの中身まで実行してしまいます。「成功したのにエラーメッセージが出る」という妙な動きを防ぐための、お約束のひと言ですよ。
On Errorの3つの形式(GoToラベル・Resume Next・GoTo 0)の使い分けは、VBAのエラーハンドリング完全ガイド|On Error GoToとResume Nextの使い分けで詳しく解説しています。あわせて読むと理解が深まりますよ。
パターン検証関数を作っておくと安全
同じエラー処理を何度も書くのは面倒ですよね。そこで、「このパターンは有効か」を判定する関数を1つ作っておくと、使い回せて便利です。
'パターンが有効ならTrue、不正ならFalseを返す関数
Function パターンは有効か(ByVal pat As String) As Boolean
Dim re As Object
Set re = CreateObject("VBScript.RegExp")
On Error GoTo 不正 'エラーが出たら不正ラベルへ
re.Pattern = pat
re.Test "テスト" '実際に試して動くか確認する
パターンは有効か = True '問題なければTrue
Exit Function
不正:
パターンは有効か = False 'エラーが出たらFalse
End Function
この関数を使えば、本処理の前に If パターンは有効か(パターン文字列) Then のように安全確認ができます。不正なパターンが来ても、マクロが止まらず分岐で対処できるわけです。
ユーザーが自由にパターンを入力できるツールを作るときは、この検証関数が頼りになります。「まず安全確認、それから本処理」の流れを習慣にしておくと安心ですよ。
ワークシート関数との使い分け
ここまでVBAの正規表現を見てきましたが、実はMicrosoft 365には正規表現を使えるワークシート関数もあります。REGEXTEST・REGEXREPLACE・REGEXEXTRACTの3つです。
「じゃあ関数とVBA、どっちを使えばいいの」と迷いますよね。それぞれ得意な場面が違うので、ここで整理しておきます。
結論から言うと、セル単位で完結する処理は関数、繰り返しや条件分岐を含む処理はVBA、という分け方が基本です。
REGEXTEST・REGEXREPLACE・REGEXEXTRACTとの違い
ワークシート関数の3つは、VBAのRegExpメソッドとほぼ対応しています。対応関係を表にまとめました。
| やりたいこと | ワークシート関数 | VBA RegExp |
|---|---|---|
| パターン一致チェック | REGEXTEST | Testメソッド |
| パターン一致部分の置換 | REGEXREPLACE | Replaceメソッド |
| パターン一致部分の抽出 | REGEXEXTRACT | Executeメソッド |
ワークシート関数の大きな利点は、数式を入れるだけで使える手軽さです。プログラミングの知識がなくても、セルに =REGEXTEST(A1,"d+") と書くだけで判定できます。
ただし、ワークシート関数はMicrosoft 365専用です。Excel 2019や2021では使えません。一方、VBAのRegExpはどのバージョンでも動くという強みがあります。
それぞれの関数の詳しい使い方は、REGEXTEST関数・REGEXREPLACE関数・REGEXEXTRACT関数の各記事を参考にしてくださいね。
VBA RegExpを選ぶべきシーン
では、どんなときにVBAの正規表現を選ぶべきでしょうか。次のような場面ではVBAが向いています。
- 数百行・数千行をまとめて一括処理したいとき(ループ処理が速い)
- 「一致したらこのシートへ転記」のように条件分岐を伴うとき
- 全角→半角変換のように、StrConvなど他の関数と組み合わせたいとき
- Microsoft 365以外(Excel 2019・2021)の環境で正規表現を使いたいとき
- ボタン一発で実行する定型業務に組み込みたいとき
逆に、1つのセルの判定や置換で済むなら、わざわざマクロを書く必要はありません。ワークシート関数のほうが手早く片付きます。
ちなみに、Googleスプレッドシートにも正規表現を使える関数があります。スプレッドシートでの置換はスプレッドシートのREGEXREPLACE関数で解説していますので、Sheetsを使う方はそちらもどうぞ。
ツールに応じて使い分ければ、文字列処理の悩みはほとんど解決できますよ。
まとめ
VBAの正規表現(RegExp)について、準備から実務パターンまで解説してきました。最後に要点を振り返ります。
- 正規表現は「形のパターン」での判定・抽出・置換が得意で、TRIMやSUBSTITUTEでは難しい処理を一気にシンプルにできる
- RegExpオブジェクトは「参照設定(早期バインディング)」か「CreateObject(遅延バインディング)」で用意する。自分用は早期、配布用は遅延が目安
- 覚えるのは3つのプロパティ(Pattern・Global・IgnoreCase)と3つのメソッド(Test・Replace・Execute)だけ
- 日本語や全角文字は
wやdに一致しないので、文字コード範囲で指定する - 不正なパターンに備えて、On Error GoToや検証関数でエラー処理を入れておくと安全
- セル単位の処理はワークシート関数、ループや条件分岐を伴う処理はVBAと使い分ける
正規表現は最初こそ記号の羅列に見えますが、よく使うパターンは限られています。この記事の早見表とサンプルコード5本を手元に置いておけば、実務の文字列処理でつまずくことはぐっと減りますよ。
まずは身近なデータで、メールアドレスチェックや郵便番号抽出から試してみてください。一度コツをつかめば、これまで手作業でやっていた面倒なクレンジングが、ボタン一発で片付くようになりますよ。
