仕事でVBScriptを沢山触って色々悩んだことをメモ。
じわじわ増やします。
配列
固定長配列
Dim Array(5)ってやると添字0~5までの 要素数6 の配列ができる。
添字を普通のカッコで括るというのと、思っているよりも要素数が1個多いところに注意。
「要素数5の配列をつくる」じゃなくて「添字5までの配列をつくる」ってことかな。
動的配列
VBSでは、ReDimステートメントを使って配列の拡張ができる。
ただし、ReDimが使えるのは 要素数を指定せずに宣言した配列 のみ。
Array(5)はNGで、Array()はOK。
ただReDimとやると、元の配列の中身は消えてしまう。
配列の中身を残したまま拡張がしたい場合、Preserveをつける。
Dim Fruits()
ReDim Fruits(1)
Fruits(0) = "Apple"
Fruits(1) = "Grape"
WScript.Echo Join(Fruits) ' => Apple Grape
ReDim Preserve Fruits(2)
Fruits(2) = "Orange"
WScript.Echo Join(Fruits) ' => Apple Grape Orange
ReDim Fruits(3)
Fruits(3) = "Melon"
WScript.Echo Join(Fruits) ' => Melon 拡張前の中身が消えた!
Array関数でつくる
Array関数に値のリストを渡すと、配列を返してくれる。
バリアント型の変数で受ける。配列では受けられない。
Fruits = Array("Apple","Grape","Orange","Melon")
WScript.Echo Fruits(1) ' => Grape
WScript.Echo Fruits(3) ' => Melon
WScript.Echo Join(Fruits) ' => Apple Grape Orange Melon
代入
代入のときにSetを付けるか付けないか。
単純な値の代入は付けない。
オブジェクトを扱うときなど、参照を代入したいときはSetを付ける。
プロシージャ
FunctionとSub
戻り値を返すFunctionと返さないSubの2種類がある。Subはサブルーチンのことかな?
全部Functionで書けばいいんじゃね?と思いがちだけど、戻り値を受け取ってあげないとエラーで止まるので、やっぱり使い分けが必要。
呼び出しかた
Callを付けて呼び出すことも、省略することも出来る。
ただし、Callを省略した場合、引数を囲うカッコも省略しないといけない。中途半端は許されない。
引数の値渡しと参照渡し
プロシージャの宣言のときに引数名の前にByVal・ByRefを付けると渡し方を指定できる。
ByValが値渡しで、ByRefが参照渡し。
strText = "ABC"
SubByVal strText
WScript.Echo strText ' => ABC
SubByRef strText
WScript.Echo strText ' => GHI
SubDefault strText
WScript.Echo strText ' => JKL
Sub SubByVal(ByVal Arg) ' 値渡し
Arg = "DEF"
End Sub
Sub SubByRef(ByRef Arg) ' 参照渡し
Arg = "GHI"
End Sub
Sub SubDefault(Arg) ' 参照渡し
Arg = "JKL"
End Sub
注意しないといけないのが、 省略すると参照渡しになる ところ。
上の例のように、引数で貰った変数をそのまま中の処理で使い回したりすると、呼び出し元にも影響を与えるので大変危険。
VBSでInclude
VBSには外部ファイルをインクルード・インポートする仕組みがないのですが、ExecuteGlobalを使えばそれっぽいことができます。
Include "Library.vbs" ' 外部ファイル「Library.vbs」を取込み
Sub Include(ByVal strFile)
Dim objFSO , objStream , strDir
Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
strDir = objFSO.GetFile(WScript.ScriptFullName).ParentFolder
Set objStream = objFSO.OpenTextFile(strDir & "\" & strFile, 1)
ExecuteGlobal objStream.ReadAll()
objStream.Close
Set objStream = Nothing
Set objFSO = Nothing
End Sub
ExecuteGlobalに渡した文字列をスクリプトとして解釈して実行してくれる模様。