はじめに
以前、VBScript.dll
が2027年以降に廃止となることから Microsoft VBScript Regular Expressions 5.5
を参照した正規表現(RegExp)の代替案を書きました。
【VBA】vba-regexを使用した正規表現(VBScript廃止の代替)
Selenium VBA の discussions 158 の中で、別案として .NET Framework の正規表現クラスを利用した方法を提示してくれた方がいます。
この技術の元になる技術が、vb2clr
ライブラリで日本の方が開発しています。
VBA から .NET Frameworkの機能を使用する方法は以前にありましたが、その場合、別途 .NET Framework 3.5のインストールが必要でした。
これは、別の方法を使用しているため、.NET Framework 3.5のインストールは不要となります。
vb2clr の紹介
筆者も以前に記事を読んだことがあったのですが、何か難しいイメージがあってスルーしていたのですが、改めて見直しました。
- https://github.com/jet2jet/vb2clr
- VBからCLR(.NET)を利用する その1[準備編]
- VBからCLR(.NET)を利用する その2[呼び出し編]
- VBからCLR(.NET)を利用する その3[発展編]
vb2clrのライセンスは「修正BSDライセンス」(3条項BSDライセンス; BSD-3-Clause)となっています。
使い方
導入方法
- https://github.com/jet2jet/vb2clr からモジュールを取得します。
- 次に
ExitHandler.bas
とCLRHost.cls
ファイルをプロジェクトにドラッグ&ドロップします。
補足
vb2clrは日本人の方が開発しており、Excel関連ファイルはShift-JISを用いている。
そのため、海外向けとしてUTF-8用に変換されたファイルが用意されている。
- ExitHandler.utf8.bas
- CLRHost.utf8.cls
参照設定
ツールの参照設定から次の2つのライブラリを参照します。
- Common Runtime Language Execution Engine
- mscorlib.dll
どちらも Windows 10 以降の環境であれば標準で搭載されているため、Excelマクロファイルの配布に支障はありません。
プログラム
正規表現は、GitHub上に掲載されているので、それ以外のサンプルプログラムを用意しました。
最初は理解できないで途方に暮れていたのですが、ネット検索しまくったところ中国の掲示板にサンプルプログラムが投稿されており突破口が開かれました。
その中の一部を日本語に書き換えています。
vb2clr 使い方
StringBuilderのテスト
Sub StringbuildTest()
Dim host As New CLRHost
Call host.Initialize(False)
Dim Assem As mscorlib.Assembly, sb As mscorlib.Object, r As Variant
host.CLRLoadAssembly ("System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
Set sb = host.ToObject(host.CLRCreateObject("System.Text.StringBuilder"))
Set sb = host.CLRInvokeMethod(sb, "Append", "The quick brown fox jumped over the lazy dog. ")
Set sb = host.CLRInvokeMethod(sb, "Append", "Mary had a little lamb.")
Debug.Print host.CLRProperty(sb, "Length")
r = host.CLRInvokeMethod(sb, "ToString")
Debug.Print r
Set sb = Nothing
Set host = Nothing
End Sub
SortedListとArrayListのテスト
Sub SortedlistTest()
Dim host As New CLRHost
Call host.Initialize(False)
Dim Assem As mscorlib.Assembly, mySL As Object, Total%, i%, aList As Object, interfacelist As Object
host.CLRLoadAssembly ("System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
Set Assem = host.CLRLoadAssembly("System.Collections, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
Set mySL = host.ToObject(host.CLRCreateObject("System.Collections.SortedList"))
mySL.Add "Third", "!"
mySL.Add "Second", "World"
mySL.Add "First", "Hello"
Total = mySL.Count
Debug.Print "番号:", Total
For i = 0 To Total - 1
Debug.Print mySL.GetKey(i), mySL.GetByIndex(i)
Next
Set mySL = Nothing
Stop
Set aList = host.ToObject(host.CLRCreateObject("System.Collections.ArrayList"))
aList.Add ("Hello")
aList.Add ("World")
aList.Add ("!")
For Each key In aList
Debug.Print key
Next key
Debug.Print aList.IndexOf("!", 0)
Set aList = Nothing
Set host = Nothing
End Sub
SHAハッシュの取得
これは筆者の独自のものになります。
Excelを便利にする250以上の機能を体系化したアドインに「RelaxTools Addin for Excel」があります。
この中で「ハッシュ関数のユーザ定義関数を使用するためには、.Net 3.5をインストールする必要があります。」との記載があります。
これが解決できると思い組んでみました。
Private Sub ComputeSHATest()
Debug.Print "SHA256"
Debug.Print GetSHA256(Range("A1"))
Debug.Print "SHA384"
Debug.Print GetSHA384(Range("A1"))
Debug.Print "SHA512"
Debug.Print GetSHA512(Range("A1"))
End Sub
A1セルに"Hello World"をセット、C#で求めたハッシュ値と同じになりました。
SHA256
a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e
SHA384
99514329186b2f6ae4a1329e7ee6c610a729636335174ac6b740f9028396fcc803d0e93863a7c3d90f86beee782f4f3f
SHA512
2c74fd17edafd80e8447b0d46741ee243b7eb74dd2149a0ab1b9246fb30382f27e853d8585719e0e67cbda0daa8f51671064615d645ae27acb15bfb1447f459b
Option Explicit
Private Const C_SHA256 As Long = 1
Private Const C_SHA384 As Long = 2
Private Const C_SHA512 As Long = 3
'--------------------------------------------------------------
' SHA256算出関数
'--------------------------------------------------------------
Public Function GetSHA256(ハッシュ値算出範囲 As Range) As Variant
Application.Volatile
GetSHA256 = ComputeSHA(C_SHA256, ハッシュ値算出範囲)
End Function
'--------------------------------------------------------------
' SHA384算出関数
'--------------------------------------------------------------
Public Function GetSHA384(ハッシュ値算出範囲 As Range) As Variant
Application.Volatile
GetSHA384 = ComputeSHA(C_SHA384, ハッシュ値算出範囲)
End Function
'--------------------------------------------------------------
' SHA2512算出関数
'--------------------------------------------------------------
Public Function GetSHA512(ハッシュ値算出範囲 As Range) As Variant
Application.Volatile
GetSHA512 = ComputeSHA(C_SHA512, ハッシュ値算出範囲)
End Function
Private Function ComputeSHA(lngType As Long, r As Range) As Variant
Dim host As New CLRHost
Call host.Initialize(False)
host.CLRLoadAssembly ("System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
Dim str As String
'Rangeの文字列結合(ワークシート関数のConcatを流用)
str = Application.WorksheetFunction.Concat(r)
'バイト読み込み
Dim code() As Byte
Dim objUTF8 As mscorlib.Object
Set objUTF8 = host.ToObject(host.CLRCreateObject("System.Text.UTF8Encoding"))
code = host.CLRInvokeMethod(objUTF8, "GetBytes", str)
Set objUTF8 = Nothing
'ハッシュ値計算
Dim hashValue() As Byte
Dim objSHA As mscorlib.Object
Select Case lngType
Case C_SHA256
Set objSHA = host.ToObject(host.CLRCreateObject("System.Security.Cryptography.SHA256Managed"))
Case C_SHA384
Set objSHA = host.ToObject(host.CLRCreateObject("System.Security.Cryptography.SHA384Managed"))
Case C_SHA512
Set objSHA = host.ToObject(host.CLRCreateObject("System.Security.Cryptography.SHA512Managed"))
End Select
hashValue = host.CLRInvokeMethod(objSHA, "ComputeHash", code)
Set objSHA = Nothing
'16進数へ変換
Dim description As String
description = ""
Dim i As Long
For i = LBound(hashValue()) To UBound(hashValue())
description = description & Right("0" & Hex(hashValue(i)), 2)
Next i
'return
ComputeSHA = LCase(description)
Set host = Nothing
End Function
注意点
CLRHostクラスのインスタンスを利用し終わった場合は、必ずインスタンスを解放する
技術的な補足
COMベースではない
VB や VBA は COMベースでプログラムが実行されるため、COM相互運用をサポートした.NETアセンブリであれば直接利用することができますが、System.Xml
などサポートしていないアセンブリは利用することができませんでした。
また、.NET Framework 4.5 からは、.NET型をCOMインターフェイスとして公開することを停止してしまいました。このため、.Net Framework 3.5をインストールする必要がありました。
vb2clrライブラリでは、COMベースではないため、ほぼすべての.NETアセンブリを利用可能になります。
mscorlib とは
mscorlib
というのは何なのかというと、.NET Framework の標準ライブラリのコードを含むアセンブリ(DLL)のうち最も重要なものになります。
System.Object
型やSystem.String
型などの定義はすべてこの中にあります。
ちなみに「Multilanguage Standard Common Object Runtime Library」の略です。
mscorlib.dll
にはSystem.String
の他に、.NETフレームワークの基本となる多くのクラスや機能が定義されています。
公開キートークン
.NET Frameworkライブラリーを使用するのに公開キートークンを知る必要がある。
host.CLRLoadAssembly ("System.IO, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
調べ方
VS 2022用開発者コマンドプロンプトを起動します。
ネイティブx64バージョン([ x64 Native Tools Command Prompt for VS 2022 ] )を選択してください。
例として、「System.dll」を調べます。
cd "C:\Windows\Microsoft.NET\Framework64\v4.0.30319"
C:\Windows\Microsoft.NET\Framework64\v4.0.30319>SN.exe -T "System.dll"
Microsoft(R) .NET Framework Strong Name Utility バージョン 4.0.30319.0
Copyright (c) Microsoft Corporation. All rights reserved.
公開キー トークン b77a5c561934e089
よく使用するもの
アセンブリにより同じ公開トークン(PublicKeyToken)を使用している。
モジュール | 公開トークン |
---|---|
System | System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 |
System.IO.Compression.FileSystem | System.IO.Compression.FileSystem, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 |
System.IO | System.IO, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a |
System.Text.Encoding | System.Text.Encoding, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a |
System.Drawing | System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a |
どのアセンブリを使っているのか
例えば、「System.Security.Cryptography.SHA256Managed」は、どのdllなのか?
マイクロソフトのdotnetのapiサイトで検索、バージョンを「.NET Framework 4.8.1」を指定する。
SHA256Managed クラスのところに、アセンブリ:mscorlib.dll と記載されている。
https://learn.microsoft.com/ja-jp/dotnet/api/system.security.cryptography.sha256managed?view=netframework-4.8.1
SN.exe -T "mscorlib.dll"
公開キー トークン b77a5c561934e089
System.dll と同じなので、下記を使用すればよい。
Dim Assem As mscorlib.Assembly
host.CLRLoadAssembly ("System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
最後に
この方法を使えば、 .NET Framework 4の多くの機能を利用出来るようになります。
2018年頃に公開されたライブラリですが、遅ればせながら紹介させて頂きました。
Excel には Mac版もあるので、あくまで Windows限定になります。
vb2clr の他に vb2net ライブラリがあり、これは .NET(旧.NET Core)を利用できるようになっています。これなら Mac版でも動作するかも知れませんね。
VBから.NET(旧.NET Core)を利用してみる