怠日記

写真・金魚・昆虫・プログラミングの趣味を語るサイトです。似たようなことをnoteにも書いたり書いてなかったり。

VBScript - 文字列の式を評価したりステートメントを実行したりする | Eval 関数, Execute/ExecuteGlobal ステートメント

文字列で指定した式を評価するには Eval 関数を使う。

文字列で指定したステートメントを実行するには Execute または ExecuteGlobal ステートメントを使う。

Eval 関数

[result = ]Eval(expression)

文字列で指定された式 expression を評価した結果を返す。


次のスクリプトは、現在の時刻が午前なら “AM” を、午後なら “PM” を出力する。

If Eval("Hour(Now) < 12") Then
    WScript.Echo "AM"
Else
    WScript.Echo "PM"
End If
Execute statement

指定された statement を実行する。
statement には1つ以上のステートメントを指定する。
複数のステートメントを指定する場合、ステートメントをコロンまたは改行で区切る。

Sub/Function ステートメントでプロシージャを作成した場合、そのプロシージャはグローバルとなる。
作成元のプロシージャのスコープを継承するわけではない。
ただし、作成されたプロシージャを実行できるのは、Execute ステートメントを実行したプロシージャ内だけである点は注意が必要である。

'グローバル変数 var を宣言
Dim var
var = "Global"
Sub Main
    'ローカル変数 var を宣言
    Dim var
    var = "Local"
    '変数 var を出力するプロシージャを作る
    '作成されたプロシージャ内では、グローバルスコープの変数を参照する
    Execute "Sub Proc: WScript.Echo var: End Sub"
    '作成したプロシージャを実行する
    '  →"Global" が出力される
    Proc
End Sub
'Main プロシージャを実行する
Main
'Proc プロシージャは実行できない →実行時エラー
'  Main プロシージャ内で作成されたプロシージャなので、そのプロシージャ内でしか実行できない
Proc

ExecuteGlobal ステートメント

ExecuteGlobal statement 

スクリプトのグローバルスコープで、指定された statement を実行する。
そのほかの動きは Execute ステートメントと同じである。

(ExecuteGlobal ステートメントは、グローバルスコープで Execute ステートメントを実行した場合と同じと覚えておくといい)

'グローバル変数 var を宣言
Dim var
var = "Global"
Sub Main
    'ローカル変数 var を宣言
    Dim var
    var = "Local"
    '変数 var を出力するプロシージャを作る
    'グローバルに作られるので Main プロシージャを抜けても呼び出せる
    ExecuteGlobal "Sub Proc: WScript.Echo var: End Sub"
    '作成したプロシージャを実行する
    '  →"Global" が出力される
    Proc
End Sub
'Main プロシージャを実行する
Main
'Proc プロシージャを実行する
'  →"Global" が出力される
Proc

複数のステートメントをコロンまたは改行で区切る例

'コロン区切り
Execute "Sub Proc1: WScript.Echo ""Hello World!"": End Sub"
'改行区切り
Execute "Sub Proc2" & vbCrLf & _
        "WScript.Echo ""Hello World!""" & vbCrLf & _
        "End Sub"
'上記で作成されたプロシージャを実行する
Proc1
Proc2

既存のグローバル変数や関数を上書きする危険性がある

実行するステートメントの内容によっては、既存のグローバル変数や関数を上書きしてしまう可能性もある。

たとえば次のスクリプトは、既存の WScript オブジェクトを WScript プロシージャで上書きするサンプルである。

Sub Main
    'WScript という名前のプロシージャを作る
    '  →既存の WScript オブジェクトが上書きされてしまう
    ExecuteGlobal "Sub WScript: MsgBox ""Hello World!"": End Sub"
End Sub
'Main プロシージャを実行する
Main
'WScript.Echo() は実行時エラーになる
'WScript オブジェクトは WScript プロシージャとして上書きされてしまったため
On Error Resume Next
WScript.Echo "Hello World!"
'  → 実行時エラー 13: 型が一致しません。
On Error GoTo 0
'作成された WScript プロシージャを実行する
'  →メッセージボックスで "Hello World!" と表示される
WScript

Execute ステートメントも同様。
グローバルスコープで実行すると既存の内容を上書きしてしまう。

'WScript という名前のプロシージャを作る
'  →既存の WScript オブジェクトが上書きされてしまう
Execute "Sub WScript: MsgBox ""Hello World!"": End Sub"
'WScript.Echo() は実行時エラーになる
'  →WScript オブジェクトは WScript プロシージャとして上書きされてしまったため
On Error Resume Next
WScript.Echo "Hello World!"
'  → 実行時エラー 13: 型が一致しません。
On Error GoTo 0
'作成された WScript プロシージャを実行する
'  →メッセージボックスで "Hello World!" と表示される
WScript

Eval 関数と Execute/ExecuteGlobal ステートメントの違い

x = y の解釈が異なる。

Eval 関数は、x と y の値が等しいかどうかを評価する。
Execute ステートメントは、y の値を x に代入する。