仕事で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
に渡した文字列をスクリプトとして解釈して実行してくれる模様。