プログラミング初心者向けのVBA入門講座第14回です。
→過去の入門講座目次はこちら
前回、前々回に引き続き繰り返し処理のステートメントを紹介します。
今回は Do..Loop ステートメントです。
Do..Loop ステートメントの基本
Do..Loop ステートメントは繰り返しの条件を指定して Do と Loop に囲まれた範囲の処理を繰り返し実行するステートメントです。
条件はDoの後に記述する方法とLoopの後に記述する方法があります。
Do 条件
処理
Loop
または
Do
処理
Loop 条件
「Do 条件」の場合はすでに条件を満足していたら一度も中の処理が実行されることはありません。
一方、「Loop 処理」では少なくとも一回は処理が実行されます。
条件は
While 条件式
と
Until 条件式
という書き方があります。
Whileは「~の間」という意味で条件式が成立(True)している間は処理を繰り返し、不成立(False)になったら繰り返しをやめます。
Untilは「~まで」という意味で条件式が不成立(False)の間は処理を繰り返し、成立(True)したら繰り返しをやめます。
例えば
While Range(“A1”).Value < 10
とするとセルA1の値が10より小さい間は処理を繰り返します。
(10以上になったら繰り返しをやめます)
例えばセルA1の値が「1→3→5→7→9」と変化している間は繰り返し、「→11」となったら繰り返しをやめます。
Until Range(“A1”).Value < 10
ではセルA1の値が10より小さくなるまで処理を繰り返します。
(10以上のときは処理を繰り返します)
例えばセルA1の値が「19→17→15→13→11」と変化している間は繰り返し、「→9」となったら繰り返しをやめます。
多くの場合「While 条件式」と「Until 条件式」はお互いに置き換えることが可能です。
先の例でいうと
While Range(“A1”).Value < 10
は
Until Range(“A1”).Value >= 10
と同じ動きになります。
Until Range(“A1”).Value < 10
も
While Range(“A1”).Value >= 10
と置き換えられます。

可読性が同等であればどちらで記述しても構いません。自分がイメージしやすいほうで記述すればよいでしょう。
まとめるとDo..Loopステートメントの書き方は次の4つのパターンがあります。
・パターン1
Do While 条件
処理
Loop
・パターン2
Do Until 条件
処理
Loop
・パターン3
Do
処理
Loop While 条件
・パターン4
Do
処理
Loop Until 条件
実際に使ってみよう
それでは実際にDo..Loopステートメントを用いたマクロを作ってみましょう。
次のマクロではサイコロをふってでた目をA列に記述していきます。「1」の目がでるまで繰り返し「1」がでたら終了します。
Sub sample1()
Dim n As Long
Cells.ClearContents
Do
n = n + 1
Cells(n, 1).Value = Int(Rnd * 6 + 1)
Loop Until Cells(n, 1).Value = 1
End Sub
Cells.ClearContents でシートのすべてのセルの数式と値をクリアします。
Rnd関数は0以上1未満の値をランダムで返します。
Int関数は小数点以下を切り捨てて得られる整数を返します。
よって「Int(Rnd * 6 + 1)」で1~6の整数をランダムで返します。その値をA列のn行目のセルに代入しています。
「Loop Until Cells(n, 1).Value = 1」によってA列 n行目の値が「1」になるまで繰り返します。
もうひとつ事例を紹介します。
次のマクロは実行するとセルA1に10から1秒後ごとにカウントダウンを表示し、値が0になったらビープ音とともにメッセージを表示します。これを応用すればマクロでタイマー的のようなものも作成可能です。
Sub sample2()
Dim sTime As Double
Dim pTime As Double
sTime = Timer
Do
pTime = Timer - sTime
Range("A1").Value = 10 - Int(pTime)
Loop While pTime < 10
MsgBox "時間です", vbInformation
End Sub
Timer関数は午前0時からの経過秒数を返します。スタート時の秒数を変数 sTimeに格納してから、変数 pTime で sTime からの経過秒数を計算しています。
先ほどの事例でも登場したInt関数で変数 pTime の小数点以下を切り捨てた整数を返し、それを10からマイナスした値をセルA1に表示させます。
「Loop While pTime < 10」でマクロスタートからの経過時間が10より小さい間は繰り返します。
10秒経過して繰り返しを終了するとMsgBox関数で用意したメッセージを表示させます。
応用
For..Next ステートメントや For Each..Next ステートメントが「Exit For」でループを抜け出せるのと同じく、Do..Loop ステートメントでも「Exit Do」を使うことでループを抜け出すことができます。
先ほどの sample2マクロを応用すると時間のかかる処理を繰り返し実行する場合に、処理時間が〇秒以上経過したら強制的に処理を中断させることもできます。
Dim sTime As Double
sTime = Timer
Do Until 条件
処理
If Timer – sTime > 5 Then
MsgBox “5秒経過したので処理を中断します”, vbExclamation
Exit Do
End If
Loop
Do..Loop ステートメントではループを抜ける条件が成立しないと無限ループに陥ることがあるので注意が必要です。その場合Excelを強制終了せざるを得なくなることもあります。
条件の記述に間違いがないか十分注意する必要がありますが、便利な小技としてDoEvents関数を使う方法があります。
DoEvents関数はOSに制御を渡す関数です。
Do 条件
処理
DoEvents
Loop
このようにDoとLoopの間にDoEvents関数を入れておくと繰り返し処理の都度制御がOSに渡されるので途中でマウスやキーボードを操作してVBEのマクロ停止ボタンから手動でマクロを中断することもできるようになります。
最初にDoEvents関数を入れておいてからマクロを試運転して、条件の記述が間違いないことが検証できてからDoEvents関数を削除することで安全にマクロをテストすることができます。

もちろん処理時間のかかるマクロによってはDoEvents関数を残しておいていつでも繰り返し処理中にOSを制御できるようにしてもよいです。
ただしDoEvents関数そのものも都度OSに制御を渡すために処理時間を遅延させる要因となるので乱用は避けたほうがいいでしょう。
まとめ
前回、前々回と今回の3回にわたってFor..Next, For Each..Next, Do..Loopの3つの繰り返し処理のステートメントを紹介しました。
VBAでの繰り返し処理についてはこの3つを理解しておけば問題ないでしょう。
それぞれ適した用途で使い分けられるといいですが、まずは簡単なコードを作ってそれぞれのステートメントを使うことに慣れていくようにしましょう。
コメント