概要
VBScriptは「コンパイラが要らない」「実行環境はWindowsがあればいい」、その上「Windowsの動作なら大抵のことが出来る」とちょっとしたプログラムを書くのなら今なお使える言語ですがデバッグが大変です。
そこでOfficeについてくる Visual Basic Editor(VBE)を工夫して使うことで、お手軽にデバッグする方法をご紹介します。
VBScriptは使える子だけど、デバッグが難しい
VBScript(以下VBS)のプログラムは簡単に作れます。メモ帳やサクラエディタなどのエディタで、例えば、msgbox "test"
と入力し、拡張子を".vbs"で保存すれば動くのです。凄い手軽。簡単すぎ!
筆者は非プログラマーの方に「プログラミングってこうやるんです」と説明する時に使ったりします。「ね?簡単でしょ?」って。
しかしながら「書く」のと「実行する」のは簡単でもデバッグするのが難しいです。やはり開発をするにはデバッガーがないと大変です。万能ソースコードエディタである Visual Studio Codeに VBScript用のデバッガーがあればいいのになと思いますが、今のところ無いようです。「無いのなら、自分で作ろうプログラム」が信条ですが生憎と作り方を知りません。どうやって作るんだろ?
VBE(Visual Basic Editor)を使う
そこでVisual Basic Editor(以下VBE)が代用できないかと考えました。
ExcelやWordといったOfficeには、Visual Basic For Application(以下VBA)用のエディタVBEが用意されています。VBSとVBAは親戚みたいなものですから、これを使うのがいいでしょう。
VBAとVBSの差を吸収する
VBAとVBSは親戚のようなものと言ってもそれなりに違いがあります。
- VBSでは変数の型指定ができない。
- VBSでは実行するためのメインコードが必要ないが、VBAには必要になる。
- VBSでは使えず、VBAで使える機能がある
- VBAでは使えず、VBSでは使える機能がある。
- VBSでは
WScript
が使える - VBScript の機能で VBA に含まれていない機能
- VBSでは
これらを次のやり方で解決します。(一部解決できていません)
- VBAでも型指定せずに宣言する。例:
Dim a As String
ではなく、Dim a
と記述する。 - VBAには
Sub Main()
を作り、VBSではトップでMain()
を呼び出すようにする。 - VBAでしか使えない機能は使わないよう気を付ける1。
- VBSの機能をVBAでも使えるようにする。
- VBAで
WScript
に相当する機能をエミュレートする。 - RegExpは
CreateObject("VBScript.RegExp")
で呼び出す。 -
Eval()
とExecute()
については残念ながらエミュレート方法は分かりませんでした2。別のモジュールにEval()
とExecute()
の名前だけのプロシージャを作っておけばコンパイルは通るのでデバッグ自体は別の方法で行う必要があります。
- VBAで
WScript機能をVBAでエミュレートとする
WScriptをエミュレートするWScriptObjを作成します。全部作る必要はなく必要になった機能を実装していくのいいでしょう。下記の例では、Sleep()
, ScriptFullName()
,ScriptName()
,Quit()
を実装しています。
なお、このエミュレート機能をモジュールではなく、クラスで作っているのはモジュールで作ってしまうとモジュール名なしで実行できてしまうからです。
Option Explicit
Public Sub Sleep(ByVal time)
Dim tempDate As Date
time = time / 1000
tempDate = DateAdd("s", time, Now)
Do
DoEvents
Loop While Now < tempDate
End Sub
Public Function ScriptFullName()
ScriptFullName = ThisWorkbook.FullName
End Function
Public Function ScriptName()
ScriptName = ThisWorkbook.Name
End Function
Public Sub Quit()
End
End Sub
WScriptObjを作成したところのキャプチャ画面は次の通りです。
VBEでのVBSの開発例
次のコードはVBEでの開発しているVBSのコード例です。VBEでデバッグできることを確認してみてください。トップでエミュレート用のオブジェクトとして、Dim WScript As New WScriptObj
を宣言しています。
Dim WScript As New WScriptObj ' VBAの場合に使用
' Main ' VBSの場合に使用
' メインを実行
Public Sub Main()
Dim a
Dim b
Dim c
a = 1
b = 2
c = a + b
MsgBox c
'VBS特有の機能をVBAで使用する
Dim RetStr, regEx, Match, Matches ' 変数を作成します。
Set regEx = CreateObject("VBScript.RegExp") ' 正規表現を作成します。
regEx.Pattern = "aiu" ' パターンを設定します。
regEx.IgnoreCase = True ' 大文字と小文字を区別しないように設定します。
regEx.Global = True ' 文字列全体を検索するように設定します。
Set Matches = regEx.Execute("aiueo") ' 検索を実行します。
For Each Match In Matches ' Matches コレクションに対して繰り返し処理を行います。
RetStr = RetStr & "一致する文字列が見つかった位置は、"
RetStr = RetStr & Match.FirstIndex & " です。一致した文字列は、"
RetStr = RetStr & Match.Value & " です。" & vbCrLf
Next
MsgBox RetStr '正規表現結果を出力する
WScript.Sleep 3000 ' 3秒待機
MsgBox WScript.ScriptName ' 自身の名前を呼び出す
WScript.Quit ' 終了する
MsgBox "ここは実行されない"
End Sub
VBSとして保存する
作成したスクリプトを拡張子.vbsにして保存します。1行目をコメントアウトし、2行目をコメントから外します。
'Dim WScript As New WScriptObj ' VBAの場合に使用
Main ' VBSの場合に使用
これでVBEで作ったVBSが動くようになります。
まとめ
- VBScript は使える子だけどデバッグが難しい。VBA用のエディタを使用するのが一番お手軽でしょう。
- VBA特有の機能は使用しないようにして、VBS特有の機能はVBAでエミュレートして解決します。
- ただし、
Eval()
とExecute()
のエミュレートは残念ながら私にはできなかったので別のデバッグ方法が必要です。
-
もし使ってしまったとしてもVBSとして実行する時にエラーが発生するので、適宜確認しながら作っていければ気づけるはずです。これは
Dim a As String
と書いてしまった時も有効です。 ↩ -
Eval()
はAccessに似たような機能があるので参照設定で呼び出して使用できないかと考えましたが、文字中に変数があると出来ないです。Execute()
は動的プログラミング(VBAで動的にコード生成&実行)で解決できそうかと思いましたが、実行するプロシージャが事前に存在しないとVBEのコンパイルが通らないので無理っぽいです。動的プログラミングを使って、Eval()
の中身を一度関数化する方法も考えましたが、やはり変数がネックになってどうにも……。 ↩