プログラミングをしていると、同じような処理を何度も行いたい場合がよくあります。
ここではサイコロを10回振ってシートに結果を出力するケースを考えます。
これは以下のように簡単に書くことができます。
'サイコロを10回振って結果をセルに書き込むプログラム
Sub dice1()
Randomize
Cells(1, 1) = Fix(Rnd * 6) + 1
Cells(2, 1) = Fix(Rnd * 6) + 1
Cells(3, 1) = Fix(Rnd * 6) + 1
Cells(4, 1) = Fix(Rnd * 6) + 1
Cells(5, 1) = Fix(Rnd * 6) + 1
Cells(6, 1) = Fix(Rnd * 6) + 1
Cells(7, 1) = Fix(Rnd * 6) + 1
Cells(8, 1) = Fix(Rnd * 6) + 1
Cells(9, 1) = Fix(Rnd * 6) + 1
Cells(10, 1) = Fix(Rnd * 6) + 1
End Sub
まず、randomizeはVBAに組み込まれた疑似乱数を発生させる関数(rnd関数)を初期化する関数です。
rnd関数は呼び出すと0以上1未満の小数(単精度小数点型・single型)を返す関数で、これを6倍した値をfix関数を使って整数にする(小数点以下を切り捨てる)ことで、0から5までの整数をランダムに取得することができます。最後に1を足しているのは、サイコロを振った結果ということで、1~6の整数値を得るためです。
実行してみるとサイコロ10回分の出目は取得できましたが、このコードには問題があります。
例えばサイコロを振る回数を100回にしたくなった場合、どうすればよいでしょうか。……このような繰り返し処理にはループ構文という制御構文が用意されています。
同じ処理を繰り返すプログラムを作成する場合にはループ構文を使うことで、シンプルに書くことができます。
for文
for文は『for ~ 処理 ~ next』のように書き、カウンタ変数を利用した繰り返し処理を表します。
'forループの例
Sub dice2()
Randomize
Dim i As Long
For i = 1 To 10
Cells(i, 1) = Fix(Rnd * 6) + 1
Next
End Sub
for文を使って最初の例を書き直したのが上記のコードです。
i は繰り返し回数を数えるためのカウンタ変数です。上の例だと、i = 1から始めて、forループ内の処理を行って next に到達するたびに i を1ずつ加算し、 i が10になるまで(10を含む)、『for ~ next』までの処理を繰り返します。
もし繰り返し回数を100回にしたくなった場合、forループを使用していればカウンタの上限を10から100に書き換えるだけで済みます。
for文のカウンタについての補足
VBAのfor文では加算法則を指定することができます。
上記例のように普通に書くと(というか何も書かないと)カウンタはnextで+1ずつ加算されますが、『for i = 1 to 10 step 2』と書くと、2ずつ加算されることになります。
また、『for i = 10 to 1 step -1』のように、カウンタを減算させることもできます。
注意すべき点として、for文中にカウンタの値を上書きしてしまうと、繰り返し回数が分からなくなって正しく処理が続行できないことがありますので、カウンタに使った変数を書き換えることはできるだけ避けた方が無難です(絶対に書き換えるのがいけないわけではありません)。
ちなみにループの途中で中断することもできますが、これは後ほど(if文によるループの打ち切り)で説明します。
while文
wihle文の構文は『While(条件) ~ 処理 ~ Wend』で、繰り返し用のカウンタではなく条件判定を利用して繰り返し処理を行います。
'whileループの例
Sub dice3()
Randomize
Dim i As Long
i = 2
While (i >= 2)
Cells(i, 1) = Fix(Rnd * 6)
i = Cells(i, 1)
Wend
End Sub
上の例ではwhile文の内部の処理を実行するための判定条件として(i >= 2)を指定しています。while文ではこの条件が満たされている(条件式の判定結果がtrueである)限り、whileループ内部の処理を繰り返行います。
1回目の処理が条件から外れないように i に予め2をセットしていますが、1回目の処理を必ず実行させたい場合には『Do ~ 処理 ~ Loop While』を使うこともできます。
カウンタを自動更新してくれるfor文と異なり、内部の処理中に条件式の値を更新するように(いつかは条件が満たされるように)しないとwhile文から抜けられなくなってしまう(無限ループになる)場合があるので注意が必要です。
少しひねったループに向いているかもしれませんが、基本的にはfor文で代用できることが多いです。
For Each文
ループ構文の一つとして、For Each文があります。
これは初心者には嫌われがちなやや難しい構文で、forのようにカウンタを使ったり、whileのように終了条件を判定しないでループ処理を行うのが特徴です。
それではどうやってループの終了を判定するのかというと、対象の要素全てに対する処理が終わったときです。
実際、for文で代用できるケースは多く、入門としては必須の構文ではありませんが、ある集合に対してそれぞれ同じ処理を行いたい場合には便利なため、余裕があれば覚えておきたい構文です。
For Eachの詳細は配列を説明した後(For Eachの解説)で解説します。