文字列の抽出と計算 3.VBA:パターンに着目する ②
今回のテーマ
前回と同じテーマです。
一つのセルに、3桁の数字が3つあります。これらは、半角スペースで区切られています。この数字について、真ん中のグループの和を求めてみましょう。
パターンが繰り返されることに着目した文字の抽出
数字の塊が3つだと分かっていれば、前回のパターンで対応できます。
myReg.Pattern = "(^\d+)[\s_・と](\d+)[\s_・と](\d+)"
入力ルールが崩壊した現場の例。
しかし以下の場合には、対応できていません。
- 数字の塊が幾つあるか判らない。
- 未知の区切り文字に対応できない。
そこで今回、パターンを次のように変更します。
「数字の塊+数字ではないもの」
さらに、条件に合うものがある限り検索し続けることにします。
コードは以下の通りです。
Sub myCalc() Dim i As Long Dim iMax As Long Dim str As String Dim myReg As New RegExp Dim matchCase As MatchCollection ' 最終行番号の取得 iMax = Cells(Rows.Count, 1).End(xlUp).Row - 1 ' 正規表現のパターン定義 myReg.Pattern = "(\d+)\D?" ' 正規表現の検索条件 ※ひとつ見つけても検索を止めない myReg.Global = True ' 合計セルの初期化 Cells(iMax + 1, 2) = 0 ' 各行の値抽出と足し算 For i = 2 To iMax ' 半角と全角が混在するため、一旦全て半角化 str = StrConv(Cells(i, 1), vbNarrow) ' パターンにマッチする場合、True が返る If myReg.test(str) = True Then ' パターンマッチした結果を、マッチコレクションに格納する Set matchCase = myReg.Execute(str) ' 取り出した結果で足し算 Cells(iMax + 1, 2) = Cells(iMax + 1, 2) + matchCase(1).SubMatches(0) End If Next End Sub
myReg.Global = True とすることで、繰り返し検索しています(初期値は False )。
また、[\s_・と]は、\D? に簡略化しました。
[\s_・と]
- \s 半角スペース
- _ アンダーバー
- ・ 半角の中黒
_と 平仮名の「と」
\D?
- \D 数字以外の全ての文字
- ? 直前の文字が0回または1回
一番最後の塊は、その後ろに何もないため、「?」としています。
\D? は、\D{0, 1} でも同じ意味です。この {0, 1} は、0~1回という意味になります。
今回のパターンに当てはめると、「123 456 789」は次のようになります。
matchCase(0)=「123 」※半角スペース付き
matchCase(1)=「456 」※半角スペース付き
matchCase(2)=「789」
従って目的の値は 456 は、「matchCase(1).SubMatches(0)」で取り出すことが出来るわけです。
注意点として、数字の塊が1つしかない場合、2つ目の数字を抜き出すよう指示しているのでエラーになります。回避策として、matchCase が2個以上あることを条件に追加する、などがあります。
' 取り出した結果で足し算 If matchCase.Count >= 2 Then Cells(iMax + 1, 2) = Cells(iMax + 1, 2) + matchCase(1).SubMatches(0) End If End If
「正規表現」「VBA」で検索すると、多くの検索結果がヒットします。大変インパクトのあるスキルですので、ぜひ習得して、大いに業務効率を向上させましょう。
おわりに
今回の方法に対する評価(私見)は、以下の通りです。
メリット :
- 区切り文字の変則性と、文字群数の変動に、さらに柔軟に対応できるようになった。
デメリット:
- 相変わらず理解しにくい
- 実は、小数点を含む数値や負の数値に対応できていない
実務への応用においては、さらに作りこみが必要になると思います。
(おわり)