正規表現で数字を抽出
文字列から数字のみを抽出する方法にはいくつか考えられます。
Excelのワークシート関数を組み合わせて抽出する方法、VBAで1文字ずつ数字かどうかを判別する方法、そして、正規表現で数字を判別する方法などです。
ネットでは1文字ずつ判別する方法が紹介されていることが多いのですが、その方法では、ループ処理、文字判別処理、文字列連結処理、という3段階が必要になります。
しかし正規表現を利用すればループ処理と文字列連結処理は不要になり、文字判別処理だけで単純になります。そして、一番高速に動作します。
ここではその正規表現での方法を紹介します。ちなみに正規表現が分からなくてもコピペで利用できます。
事前設定
以下のVBAコードは事前に正規表現の参照設定をしておく必要があります。
VBAの画面でツールメニュー→参照設定のダイアログを開き、「Microsoft VBScript Regular Expressions 5.5」にチェックを付けることで正規表現のRegExpクラスが利用できるようになります。
文字列から数字を抽出する関数
正規表現を利用しているためコードがとても単純になります。
ただし、少し工夫したコードになっています。
単純に数字を検索する方法であれば、「0から9を検索し、それらを全て抽出する」というコードになります。
しかしそれではコードが長くなるため、「数字以外の文字を””の空文字に置き換えて数字だけを残す」という方法にしています。
なお、この関数は半角数字のみを抽出します。全角と半角の両方を抽出したい場合は7行目の[^0-9]を[^0-90-9]にコピペで書き換えてください。ブラウザでは分かりにくい場合もあるのですが後ろに追加している0-9の数字は全角です。
1 2 3 4 5 6 7 8 9 10 11 12 |
'// 引数1:対象文字列 '// 引数2:検索結果 Sub FindNumberRegExp(s, result) Dim reg As New RegExp '// 正規表現クラスオブジェクト '// 検索条件=数字以外を抽出 reg.Pattern = "[^0-9]" '// 文字列の最後まで検索する reg.Global = True '// 指定セルの数字以外の文字を空文字に置き換える result = reg.Replace(s, "") End Sub |
文字列から数字を抽出する関数(参考版)
なお、参考として、[^0-9](数字以外を検索)ではなく[0-9](数字を検索)とした場合は以下のコードになります。実際に使う場合は上の関数をお勧めします。
コードが長くなっている理由は、文字列の中のどこに数字があるのか事前に分からないため、数字を検索して見つかった全ての結果を連結するための処理が必要になるためです。
上のコードでは必要ありませんでしたが、文字列の中に数字が点在している場合を考慮する必要があるため、MatchCollectionクラスとMatchクラスで検索結果が複数発生している場合への対応をしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
'// 引数1:対象文字列 '// 引数2:検索結果 Sub FindNumberRegExp2(s, result) Dim reg As New RegExp '// 正規表現クラスオブジェクト Dim oMatches As MatchCollection '// RegExp.Execute結果 Dim oMatch As Match '// 検索結果オブジェクト Dim i '// ループカウンタ Dim iCount '// 検索一致件数 '// 検索範囲=文字列の最後まで検索 reg.Global = True '// 検索条件=数字を検索 reg.Pattern = "[0-9]" '// 検索実行 Set oMatches = reg.Execute(s) '// 検索一致件数を取得 iCount = oMatches.Count result = "" '// 検索一致件数だけループ For i = 0 To iCount - 1 '// コレクションの現ループオブジェクトを取得 Set oMatch = oMatches.Item(i) '// 検索一致文字列 result = result & oMatch.Value Next End Sub |
処理速度の違い
同じ処理を行う関数が2つありますが、処理速度は1つ目の方が速いです。
実際にマイクロ秒単位で計測してみました。それぞれ10000回実行した結果、[^0-9]のコードの方が[0-9]のコードより1.4倍ほど高速でした。
1.42601401660067 (1つ目のFindNumberRegExpを1万回実行した秒数)
1.99070118405507 (2つ目のFindNumberRegExp2を1万回実行した秒数)
処理速度が異なる一番の理由は文字列の連結処理があるかないかの差です。
VBAに限らずどのプログラミング言語も同様ですが文字列の連結処理は時間が掛かる処理です。
利用方法
上のFindNumberRegExp関数を利用するサンプルコードです。
引数に「abc123あああ55667899」と入力されているA1セルと抽出結果を返す変数を渡します。
1 2 3 4 5 6 |
Sub FindNumberCallTest() Dim result Call FindNumberRegExp(Range("A1").Value, result) Debug.Print result End Sub |
実行結果
12355699