先ほどの例のように、配列を操作するときは似たような行が連続することが多い。このような繰り返し(ループ)をまとめて記述するためのステートメントが、VBScriptにはいくつか用意されている。そのうち、For 〜 NextステートメントおよびFor Each 〜 Nextステートメントをここで紹介しよう。
まずはFor 〜 Nextステートメントを用いて先ほどのスクリプトを書き直すと次のようになる。
Option Explicit
Dim intNumbers(4) 'サイズ5の配列を宣言
'配列の各要素に値を代入
Dim intCounter 'ループカウンタ用変数
For intCounter = 0 To 4 Step 1 '0から4まで、1ずつ変化させる
'配列に、インデックスの倍の値を代入
intNumbers(intCounter) = intCounter * 2
Next
'3つ目の値を参照
MsgBox "3つ目の値は" & intNumbers(2) & "です。"
For 〜 Nextステートメントは、ForとNextの間に記述したステートメントを繰り返し実行するというものである。実行する回数は、「For ループカウンタ用変数 = 開始数 To 終了数 Step 間隔」のように記述する。ここでは「For intCounter = 0 To 4 Step 1」と指定しているので、ループカウンタ用変数intCounterを0から4まで、1ずつ加算させて繰り返す、という意味になる。その結果、For 〜 Nextの間に含まれるステートメント「intNumbers(intCounter) = intCounter * 2」が、intCounterの値を0、1、2、3、4と5回変化させながら実行されるわけである。結果として配列要素に1行ずつ代入していたときと同じ結果が得られる。なお、Stepが1の場合は“Step 1”を省略可能である。大きい数から減少させる場合はStepに負の値を指定する。
このスクリプトでは配列の1要素しか表示していない。そこで、配列のすべての内容を参照するコードを考える。For 〜 Nextステートメントを用いても可能だが、ここでは配列の各要素について繰り返しを行う、For Each 〜 Nextステートメントを使ってみよう。
Option Explicit
Dim intNumbers(4) 'サイズ5の配列を宣言
'配列の各要素に値を代入
Dim intCounter 'ループカウンタ用変数
For intCounter = 0 To 4 '0から4まで、1ずつ変化させる
'配列に、インデックスの倍の値を代入
intNumbers(intCounter) = intCounter * 2
Next
Dim intTemp, strMessage
strMessage = ""
For Each intTemp In intNumbers '全要素に対して繰り返す
',で文字列をつなげる
strMessage = strMessage & intTemp & ","
Next
MsgBox strMessage
このスクリプトを実行すると、次のように配列の中身が“,”で区切られて表示される。
For Each 〜 Nextステートメントも、ForとNextの間の行を繰り返し実行するという意味になるが、For Eachでは配列の各要素に対して繰り返し操作を行う。この例では「For Each intTemp In intNumbers」としているので、配列変数intNumbersの各要素に対して繰り返し実行するということになる。intNumbersの各要素はループが繰り返されるたびにintTempという変数に代入される。
なお、For 〜 NextステートメントおよびFor Each 〜 Nextステートメントにおいて、ある条件を満たしたときにループから抜けたい場合は、ExitステートメントをIfステートメントなどの中に記述する。例えば、1から順番に1ずつ増やした数値を足していったとき(1 + 2 + 3 + 4 + 5 + ……)、初めて1000を超えるときの値とその和を求めるには次のようにする。
Option Explicit
Dim intNumber '和を格納する変数
intNumber = 0
Dim intCounter
For intCounter = 1 To 100
intNumber = intNumber + intCounter
'ループを抜ける
If intNumber > 1000 Then Exit For
Next
MsgBox "1から" & intCounter & "までの総和は" & _
intNumber & "で、このとき最初に1000を超えます。"
このスクリプトを実行すると次のようになる。
このように、ループを抜けるときにはExitステートメントを用い、Exit Forと記述する。この場合、intCounterが45になった時点でintNumberが1000を超えるので、ループを抜ける。intCounterが46〜100までは実行されない。
ここで1つ、For 〜 Nextステートメントを使った例題を出そう。0〜99までの数値がランダムに並んだ文字列を取得することを考える。ただし、同じ数値が2回以上出現してはいけないという条件を付ける。このため、単にRnd関数を用いるだけでは駄目ということになる。Rnd関数を使うと指定範囲の乱数を得ることができるが、その乱数は呼び出すたびに必ず違う値を返すというわけではなく、重複することもあるからだ(Rnd関数については第4回の「数値演算関数 その3(乱数)」を参照)。この問題を解決するには、まず配列に0〜99までの数値を格納しておき、その後、配列を適当な回数シャッフルすればよい。シャッフルとは、配列からランダムに2つの要素を取り出し、その値を交換することである。単に値を入れ換えているだけなので、これならば同じ数が重複することはない。
マーカーで隠れたところを選択してチェックしてみよう。
Option Explicit
Randomize
Dim intNumbers(99) 'サイズ100の配列intNumbersを宣言
'配列に0〜99の値を格納
Dim intCounter
'0〜99まで繰り返す
For intCounter = 0 To 99
intNumbers(intCounter) = intCounter
Next
'1000回配列をシャッフルする
Dim intTemp, intIndex1, intIndex2
For intCounter = 1 To 1000
'ランダムなインデックス値を2つ取得
intIndex1 = Int((99 - 0 + 1) * Rnd + 0)
intIndex2 = Int((99 - 0 + 1) * Rnd + 0)
'配列要素を交換
intTemp = intNumbers(intIndex1)
intNumbers(intIndex1) = intNumbers(intIndex2)
intNumbers(intIndex2) = intTemp
Next
'結果の出力
Dim strResult
strResult = ""
'0〜99まで繰り返す
For intCounter = 0 To 99
strResult = strResult & intNumbers(intCounter) & " "
If (intCounter + 1) Mod 10 = 0 Then
'整形のため、10要素ごとに改行コードを入れる
strResult = strResult & vbCrLf
End If
Next
MsgBox strResult
このスクリプトを実行すると、例えば次のように表示される。
少々長いスクリプトになったが、順を追っていけば理解することはそれほど困難ではないだろう。
このように、配列とFor 〜 Nextステートメントを併用することで一括処理ができるだけでなく、値の並べ替えなども可能になる。
Copyright© Digital Advantage Corp. All Rights Reserved.