このサイトの記事内では「アフィリエイト広告」などの広告を掲載している場合があります。
消費者庁が問題としている「誇大な宣伝や表現」とならないよう配慮しコンテンツを制作しておりますのでご安心ください。
問題のある表現が見つかりましたらお問い合わせよりご一報いただけますと幸いです。

【VBA】正規表現(RegExp)を繰り返すときの注意事項

VBAで正規表現(RegExp)を使う際、見落としがちなのが「オブジェクト生成コスト」です。
特に繰り返し処理の中で使う場合、書き方によってはかなり動作が遅くなるかもしれません。

今回は、よくないNGパターンと改善方法を解説します。

VBAが難しいと感じたら
ココナラにてVBAの作成依頼を受け付けています。
ご依頼・ご相談はこちらから

よくあるNGパターン(サブプロシージャ化)

Function HasNumber(text As String) As Boolean
    ' NGパターン

    Dim reg As Object
    Set reg = CreateObject("VBScript.RegExp")
    
    reg.Pattern = "\d+"
    reg.Global = True
    
    HasNumber = reg.Test(text)

End Function


Sub SampleNG()
    ' 呼び出す側

    Dim i As Long
    For i = 1 To 10000
        If HasNumber("abc123") Then
            ' 何か処理
        End If
    Next i
End Sub

この書き方の問題はシンプルで、

「HasNumberプロシージャが呼ばれるたびに RegExp を生成している」

という点です。

例えば、1万回ループすると1万回 CreateObjectされます。
そして、毎回COMオブジェクト生成はかなり重たい処理です。

結果として、

  • 処理速度が大幅に低下
  • 無駄なメモリ使用

につながります。

改善方法:モジュールレベルで使い回す

正規表現オブジェクトは「1回作って使い回す」が基本です。

' モジュールレベル
Private reg As Object

Function HasNumber(text As String) As Boolean
    ' OKパターン
    ' このプロシージャ内ではCreateObjectしない
    
    reg.Pattern = "\d+"
    reg.Global = True
    
    HasNumber = reg.Test(text)

End Function


Sub SampleOK()
    ' 呼び出す側

    ' 最初に1回だけCreateObjectする
    Set reg = CreateObject("VBScript.RegExp")

    Dim i As Long
    For i = 1 To 10000
        If HasNumber("abc123") Then
            ' 何か処理
        End If
    Next i
End Sub

このプログラムでは、呼び出す側で1回だけCreateObjectをしています。

regはモジュールレベルの変数にしているので、HasNumberプロシージャから参照することができます。

これならば何度もCreateObjectをすることなく、1度だけCreateObjectするので、処理速度の低下やメモリ使用を避けることができます。

正規表現(RegExp)で処理が遅いと感じたら、このポイントを確認してみてください。

《VBA上級者になりたい人へ》
VBA上級者を目指したい人にはパーフェクトExcel VBA一択です。
この本を読み切れば間違いなくVBA上級者になれます。

VBAが難しいと感じたら
ココナラにてVBAの作成依頼を受け付けています。
ご依頼・ご相談はこちらから

VBA

Posted by やろまい