はじめに
2027年頃には「VBScript」はデフォルトで無効になり、その少し後には Windows から完全に削除されます。
VBScriptの非推奨範囲はvbscript.dll
のみだとMicrosoft windows-itpro-blogのコメントにありました。
The scope of VBScript deprecation includes only vbscript.dll and no other libraries. This shall not impact any projects that are not dependent on vbscript.dll.
最大の影響はvbscript.dll
内の正規表現(Regular Expressions)です。
つまり、Microsoft VBScript Regular Expressions 5.5を参照してNew RegExp
としたり、CreateObject("VBScript.RegExp")が使用できなくなります。
これは、Excel
とAcccess
の VBA で正規表現を使用する上では参照しています。
そこで代替案として見つけたのが、VBAのみで記述されたオープンソースのvba-regex
になります。
vba-regexの紹介
ExcelでWebスクレイピングする「SeleniumVBA」を久しぶりに見たところ、Creditsに「vba-regex by sihlfall」を見つけました。2024/7/26にInitial commitされています。
VbaRegex は、完全に VBA/VB 6 で記述された正規表現エンジンです。JavaScript正規表現をサポートすることを目的としています。
導入方法
1.上記のGitHubページから、<> Code
ボタンをクリックして「DownLoad ZIP」を選択します。
2.ダウンロードされた「vba-regex-master.zip」ファイルを展開します。
モジュールファイルが複数に分かれているのですが、1つのファイルにまとめる方法も用意されています。よって、2つのパターンを記載します。
複数ファイルをインポート
src
フォルダの中にある下記ファイルをインポートします。
- ArrayBuffer.bas
- RegexAst.bas
- RegexBytecode.bas
- RegexCompiler.bas
- RegexDfsMatcher.bas
- RegexErrors.bas
- RegexIdentifierSupport.bas
- RegexLexer.bas
- RegexNumericConstants.bas
- RegexRanges.bas
- RegexReplace.bas
- RegexUnicodeSupport.bas
- StaticRegex.bas
- StaticStringBuilder.bas
単一ファイルをインポート
複数ファイルは管理など面倒だという方のために、aio
フォルダの中にあるPowerShellスクリプトのmake_aio.ps1
を実行すると、build
フォルダの中に複数ファイルを1つのモジュールに集約したStaticRegexSingle.bas
が作成されます。
Singleの除去
モジュールの名前をSingle
を取りStaticRegex.bas
とします。
メモ帳などでStaticRegex.bas
を開いてVB_Name
からもSingle
を取ります。
Attribute VB_Name="StaticRegexSingle"
↓
Attribute VB_Name="StaticRegex"
このStaticRegex.bas
をインポートします。
Single
を取らない場合、宣言する際にStaticRegexSingle
で定義します。
それだけなので、不要であればSingleの除去なしで使用してください。
例 Dim re As StaticRegexSingle.RegexTy
使用方法
StaticRegexで定義されたままのパターンとVBScript.RegExpのラッパークラスを作成したものを使用するサンプルを提示します。
対象文字列 | 正規表現 |
---|---|
Abc123DEFGH4567ijkl890 | (\D+)(\d+) |
3つのグループ分けの各サブグループを出力する。
Abc
123
DEFGH
4567
ijkl
890
デフォルト
StaticRegexで定義された方法になります。
Dim re As StaticRegex.RegexTy
Dim matcherState As MatcherStateTy
Dim sourceString As String
Dim i As Long
Dim ignoreCase As Boolean, globalFlag As Boolean, multiLine As Boolean
Dim submatchString As String
Dim matchStart As Long, matchLength As Long
globalFlag = True
multiLine = False
ignoreCase = False
StaticRegex.InitializeRegex re, "(\D+)(\d+)", ignoreCase
StaticRegex.InitializeMatcherState matcherState, Not globalFlag, multiLine
sourceString = "Abc123DEFGH4567ijkl890"
Do While StaticRegex.MatchNext(matcherState, re, sourceString)
With matcherState.captures
For i = 0 To .nNumberedCaptures - 1
matchStart = .numberedCaptures(i).start
matchLength = .numberedCaptures(i).Length
submatchString = vbNullString
If matchStart > 0 Then submatchString = Mid$(sourceString, matchStart, matchLength)
Debug.Print submatchString
Next
End With
Loop
RegExラッパー
VBScript.RegExpのラッパークラスになります。
SeleniumVBAのRegExp.twin が元です。twinBASIC用のため、1ファイルに複数クラスが定義されているのですが、Excelでは1ファイル1クラスとなります。筆者の方で分割しました。
1点だけ修正したのが、Global
プロパティの名前です。予約語で使用できなかったため、GlobalFlag
に変更しました。
Dim re As New RegExp
Dim mc As MatchCollection
Dim m As Match
Dim i As Long
re.pattern = "(\D+)(\d+)"
re.globalFlag = True
Set mc = re.Execute("Abc123DEFGH4567ijkl890")
For Each m In mc
For i = 0 To m.SubMatches.Count - 1
Debug.Print m.SubMatches(i)
Next
Next
ソースコード
サンプルコードと、StaticRegex.bas
と RegExpのラッパークラス 4ファイルを筆者の GitHub に配置しました。dist
フォルダに格納してあります。
Attribute NewEnum
もし、For Eachでコンパイルエラーが出るようでしたら、Attribute NewEnum
の定義をプロパティに埋め込む必要があります。GitHub 上のソースコードでは埋め込んであります。
最後に
VBScript の代替は、PowerShell になります。
IE 廃止の時もそうでしたが、ギリギリになってからではバタバタしてしまいます。
まだ2年ありますが、システム改修には時間がかかりますので、今の内に対応しておくといいでしょう。