Excel VBAで正規表現を使うとき、特にサブマッチを使うとき、
書かなければいけないことが多くて面倒なので、
簡単に使えるようにクラス化してみました。
ツール > 参照設定 > microsoft vbscript regular expressions
Option Explicit Public Function iterator() As IIterator End Function
Option Explicit Public Function hasNext() As Boolean End Function Public Function nextItem() As Object End Function
Option Explicit Implements IAggregate 'ツール > 参照設定 > microsoft vbscript regular expressions Private regEx As New RegExp Private regMc As MatchCollection Private regMatch As Match '------------------------------------------------------------------------------- ' デストラクタ '------------------------------------------------------------------------------- Private Sub Class_Terminate() Set regEx = Nothing Set regMc = Nothing Set regMatch = Nothing End Sub '------------------------------------------------------------------------------- ' iterator '------------------------------------------------------------------------------- Public Function IAggregate_iterator() As IIterator Dim res As New RegExpIterator Call res.init(Me) Set IAggregate_iterator = res End Function '------------------------------------------------------------------------------- ' 【処 理 名】プロパティ設定 ' 【引 数】isGlobal[Boolean] :True 文字列全体に検索が適用 ' False 最初の一致だけに検索が適用 ' isIgnoreCase[Boolean]:True 検索時に大文字と小文字を区別する ' False 検索時に大文字と小文字を区別しない ' 【返 却 値】なし ' 【処理概要】RegExpオブジェクトのプロパティを設定。 '------------------------------------------------------------------------------- Public Sub setProperties(ByVal isGlobal As Boolean, ByVal isIgnoreCase As Boolean) With regEx .Global = isGlobal .IgnoreCase = isIgnoreCase End With End Sub '------------------------------------------------------------------------------- ' 【処 理 名】検索 ' 【引 数】target[String] :検索対象文字列 ' pattern[String]:検索する文字列(正規表現パターン) ' 【返 却 値】なし ' 【処理概要】指定された文字列を正規表現で検索 '------------------------------------------------------------------------------- Public Sub execute(ByVal target As String, ByVal pattern As String) regEx.pattern = pattern Set regMc = regEx.execute(target) End Sub '------------------------------------------------------------------------------- ' 【処 理 名】パターン一致判定 ' 【引 数】target[String] :検索対象文字列 ' pattern[String]:検索する文字列(正規表現パターン) ' 【返 却 値】なし ' 【処理概要】指定された文字列を正規表現で検索し、パターンに一致する文字列が ' 検索されたかどうかを示すブール (Boolean) 値を返却。 '------------------------------------------------------------------------------- Public Function test(ByVal target As String, ByVal pattern As String) As Boolean regEx.pattern = pattern test = regEx.test(target) End Function '------------------------------------------------------------------------------- ' 【処 理 名】置換 ' 【引 数】target[String]:検索および置換の対象となるテキスト文字列 ' before[String]:検索する文字列(正規表現パターン) ' after[String] :置換するテキスト文字列 ' 【返 却 値】置換後文字列 ' 【処理概要】正規表現による検索で見つかったテキストを置換します。 '------------------------------------------------------------------------------- Public Function Replace(ByVal target As String, ByVal before As String, ByVal after As String) As String regEx.pattern = before Replace = regEx.Replace(target, after) End Function '------------------------------------------------------------------------------- ' 【処 理 名】マッチ件数取得 ' 【引 数】なし ' 【返 却 値】検索マッチ件数 ' 【処理概要】executeメソッドで検索したマッチ件数を返却 '------------------------------------------------------------------------------- Public Function getCount() As Long getCount = regMc.Count End Function '------------------------------------------------------------------------------- ' 【処 理 名】マッチ文字列取得 ' 【引 数】index[Long]:検索でマッチした結果のインデックス ' 【返 却 値】マッチ ' 【処理概要】executeメソッドで検索したマッチした該当indexのマッチを返却 '------------------------------------------------------------------------------- Public Function getRegMatchAt(ByVal index As Long) As Object Set getRegMatchAt = regMc.Item(index) End Function
Option Explicit Implements IIterator Private reg As New RegExpAggregate Private index As Long '------------------------------------------------------------------------------- ' 【処 理 名】次エレメント存在チェック ' 【引 数】なし ' 【返 却 値】ブール値 ' 【処理概要】collectionに次のエレメントがあるのブール (Boolean) 値を返却。 '------------------------------------------------------------------------------- Public Function IIterator_hasNext() As Boolean If index < reg.getCount Then IIterator_hasNext = True Else IIterator_hasNext = False End If End Function '------------------------------------------------------------------------------- ' 【処 理 名】次エレメント取得 ' 【引 数】なし ' 【返 却 値】エレメント ' 【処理概要】collectionのエレメントを返却。 '------------------------------------------------------------------------------- Public Function IIterator_nextItem() As Object Set IIterator_nextItem = reg.getRegMatchAt(index) index = index + 1 End Function '------------------------------------------------------------------------------- ' 【処 理 名】初期化 ' 【引 数】RegExpAggregate[IAggregate] ConcreteAggregate ' 【返 却 値】なし ' 【処理概要】イテレータを初期化する '------------------------------------------------------------------------------- Public Sub init(ByVal RegExpAggregate As IAggregate) Set reg = RegExpAggregate index = 0 End Sub
こんな感じで使う
Option Explicit Public Sub main() Dim sql As String Dim ptn As String Dim reg As New RegExpAggregate Dim it As New IIterator Dim regMatch As Match sql = "SELECT HOGE, FUGA FROM TBL_A;SELECT FUGA, HOGE FROM TBL_B;" ptn = "(SELECT)\s+(.*?)\s+FROM\s+(.*?);" Call reg.setProperties(True, True) If reg.test(sql, ptn) Then Debug.Print "True" Else Debug.Print "False" End If Call reg.execute(sql, ptn) Set it = reg.IAggregate_iterator Do While (it.hasNext) Set regMatch = it.nextItem Debug.Print regMatch.SubMatches(2) 'サブマッチを使わない場合はregMatch.valueで値を取得できる Loop Call reg.Replace(sql, "TBL_A", "TBL_C") End Sub
setProperties()を設定しなければ、regExpオブジェクトのデフォルトで検索します。
Regular Expression オブジェクトのプロパティ
Global | 検索文字列全体についてのパターンとの一致を検索するか、最初の一致だけを検索するかを示すブール (Boolean) 値を設定します。 | True | 文字列全体に検索が適用 |
False | 最初の一致だけに検索が適用 | ||
IgnoreCase |
パターン検索で大文字と小文字を区別するかどうかを示すブール (Boolean) 値を設定します。 |
True | 検索するときに大文字と小文字を区別する |
False | 検索するときに大文字と小文字を区別しない | ||
Pattern | 検索される正規表現のパターンを設定します。値の取得も可能です。 | 正規表現のパターンの記述には、特別な文字およびエスケープ シーケンスが使用されます。 |
クラスのテキストファイルを固めといたので、良かったらどうぞー。
【Excel VBA】正規表現クラス
1 ファイル 2.55 KB
そのまま使えるようなクラス名で命名すべきだったなあ。
ダサい。後で直そう。