VBScriptでwhile文をマスターする

VBScript

どのプログラミング言語でも基礎として使用される「while文」ですが、プログラミング初心者がはじめに学習するべきステートメントの1つです。

当記事では、while文の使い方について初心者の方にもわかるようサンプルのコードと一緒にご紹介します。

while文とは

whileホワイルは「その間」という英単語で、条件がTrueまたはFalseの間、処理を繰り返すステートメントです。

While文を使いこなすことで、柔軟なループ処理を実現することができます。

使用頻度が高いため、知らない方は当記事で学んでしっかり身につけましょう。

構文

While…Wend文

条件がTrueの間、処理を繰り返します。

While [条件]
    '繰り返す処理を中に記述
Wend

Do While…Loop文

最初に条件をチェックし、条件がTrueの間、処理を繰り返します。

While…Wend文と同等の動きになります。

Do While [条件]
    '繰り返す処理を中に記述
Loop

Do…Loop While文

1度処理を行ってから、条件がTrueの間、処理を繰り返します。

Do
    '繰り返す処理を中に記述
Loop While [条件]

Do Until…Loop文

最初に条件をチェックし、条件がFalseの間、処理を繰り返します。

Do Until [条件]
    '繰り返す処理を中に記述
Loop

Do…Loop Until文

1度処理を行ってから、条件がFalseの間、処理を繰り返します。

Do
    '繰り返す処理を中に記述
Loop Until [条件]

サンプルコード

よく使用されていそうな記述例をご紹介します。

数値の繰り返し処理

Dim counter
counter = 1

While counter <= 5
    MsgBox "Count: " & counter
    counter = counter + 1
Wend

数値を基準にした繰り返し処理を行う場合は、カウンター変数とWhile文を組み合わせます。

無限ループ

Dim counter
counter = 1

While True
    MsgBox "Count: " & counter
    counter = counter + 1
    If counter > 5 Then
        Exit While
    End If
Wend

While文を使って無限ループを作成することもできます。

無限ループは、特定の条件が満たされるまで続く処理が必要な場合に使用されます。

無限ループを終了させるには、Exit While文を使用します。

入力に基づく繰り返し処理

Dim userInput
userInput = ""

While userInput <> "exit"
    userInput = InputBox("Type something (type 'exit' to quit):")
    MsgBox "You typed: " & userInput
Wend

ユーザーからの入力に基づいて繰り返し処理を行う場合もWhile文が便利です。

文字列の桁数分ループ

'変数の宣言と初期化
Dim aiueo : aiueo = "あいうえお"
Dim i : i = Len(aiueo)

'文字列の桁数分ループする
Do while i > 0
	'うしろから順番に文字を取得 → おいうえお
	Msgbox Mid(aiueo,i,1)
	'デクリメントする
	i = i - 1 
Loop

Len関数により、変数「aiueo」の文字数(5)を取得し、変数「i」にセットしています。

「i」が5で0より大きいため、中の処理が実行されます。Mid関数により、変数「aiueo」の5桁目を1桁分抽出し、文字「お」がメッセージに表示されます。

次に、変数「i」が「-1」加算され、「5」から「4」になります。

「i」が4で0より大きいため、中の処理が実行されます。Mid関数により、変数「aiueo」の5桁目を1桁分抽出し、文字「え」がメッセージに表示されます。

次に、変数「i」が「-1」加算され、「4」から「3」になります。

これを「i」が「0」になるまで繰り返すことで「お → え → う → い → あ」の順番でメッセージが表示されています。

配列の要素分ループ

'変数の宣言と初期化
Dim aryMozi: aryMozi = Array("要素1","要素2","要素3")
Dim i : i = 0

'配列の要素分ループする
Do while i < UBound(aryMozi) + 1
	'結果:要素1 → 要素2 → 要素3
    Msgbox aryMozi(i)
	'インクリメントする
	i = i + 1 
Loop

変数「aryMozi」に配列を代入し、変数「i」を0で初期化しています。

UBound関数は、配列の最大要素番号を取得できます。そのため、UBound(aryMozi)は最大要素番号である2を取得しています。

aryMoziは、1番目の要素であるaryMozi(0)に”要素1″が入っていて、aryMozi(1)に”要素2″、aryMozi(2)に”要素3″が入っている状態です。

変数「i」が0で3より小さいので「要素1」のメッセージが出力されます。

変数「i」が「0+1」されて1になり、3より小さいので「要素2」のメッセージが出力されます。

これを繰り返すことで「要素1 → 要素2 → 要素3」の順番でメッセージが表示されています。

Listの要素分ループ

'変数の宣言
Dim objList : Set objList = CreateObject("System.Collections.ArrayList")
Dim i : i = 0
'追加
objList.Add "要素1"
objList.Add "要素2"
objList.Add "要素3"

'リストの要素分ループする
Do while i < objList.Count
	'結果:要素1 → 要素2 → 要素3
    Msgbox objList(i)
	'インクリメントする
	i = i + 1 
Loop

'後始末
Set objList = Nothing

変数「objList」に作成したリストをセットし、”要素1″、”要素2″、”要素3″の文字列を追加します。

「objList.Count」で要素数の3を取得します。

変数「i」が0で3より小さいので「要素1」のメッセージが出力されます。

変数「i」が「0+1」されて1になり、3より小さいので「要素2」のメッセージが出力されます。

これを繰り返すことで「要素1 → 要素2 → 要素3」の順番でメッセージが表示されています。

Dictionaryの要素分ループ

'変数の宣言
Dim objDic : Set objDic = CreateObject("Scripting.Dictionary")
Dim i : i = 0
'追加
objDic.Add "キー1", "値1"
objDic.Add "キー2", "値2"
objDic.Add "キー3", "値3"

'キーとアイテムをセット
Dim keys : keys = objDic.keys
Dim items : items = objDic.Items

'Dictionaryのキーの数だけループする
Do while i < objDic.Count
	'結果:キー1値1 → キー2値2 → キー3値3
    Msgbox keys(i) & items(i)
	'インクリメントする
	i = i + 1 
Loop

'後始末
Set objDic = Nothing

変数「objDic」に作成したDictionaryをセットし、キーと値の文字列を追加します。

キーの要素、アイテムの要素をそれぞれ取得します。

変数「keys」は、1番目の要素であるkeys(0)に”キー1″が入っていて、keys(1)に”キー2″、keys(2)に”キー3″が入っている状態です。

変数「items」は、1番目の要素であるitems(0)に”値1″が入っていて、items(1)に”値2″、items(2)に”値3″が入っている状態です。

「objDic.Count」は、キーの数(アイテムの数)である3を取得します。

変数「i」が0で3より小さいので「キー1値1」のメッセージが出力されます。

変数「i」が「0+1」されて1になり、3より小さいので「キー2値2」のメッセージが出力されます。

これを繰り返すことで「キー1値1 → キー2値2 → キー3値3」の順番でメッセージが表示されています。

for文とwhile文の違い

for文とwhile文は、どちらも繰り返し処理を行うためとても似ていて、なんとなくで使い分けている方も多くいらっしゃるのではないでしょうか。

for文は、繰り返す回数が決まっている場合に使用します。

while文は繰り返す回数が決まっていない場合に使用します。

ここまで紹介した配列の要素数分ループするといった処理は、while文でもインクリメント用の変数を用意することで実装することは可能です。

しかし、while文の中でインクリメントする処理を記述し忘れたまま実行すると、処理が終わらない「無限ループ」に陥ります。

無限ループは、ものすごい数の処理が繰り返されるため、PCに強い負荷がかかり、フリーズ(アプリが固まる)します。

最悪の場合、PCの故障の原因にもつながるため可能であれば、for文を使用することをオススメします。

for文とwhile文はどちらが速いか

for文とwhile(do loop)文は、どちらも繰り返し処理を行います。

繰り返す回数が決まっている場合は、どちらでも実装できます。

しかし、プログラムは処理が速いほど処理時間が短くなるので、処理速度をみなさん意識していると思います。

そこでどちらが速いか検証しましたので、参考にしてください。差し支えなければ、下記2つのコードをみなさんも試して速い方を教えてください。

'変数を定義
Dim sumVal : sumVal = 0			'計測値の合計値
Dim ROOP_SU : ROOP_SU = 1000	'計測回数

'計測回数分ループする
For i = 1 To ROOP_SU
	'計測開始時間
	Dim t1 : t1 = Timer

	'計測する処理
	For j = 0 To 1000000
		test = "test"
	Next
	
	'計測終了時間を加算
	sumVal = sumVal + (Timer - t1)
Next

'ファイルシステムオブジェクトの作成
Set fso = CreateObject("Scripting.FileSystemObject")
'結果を出力
Set file = fso.OpenTextFile(".\for:平均" & (sumVal / ROOP_SU) & "秒.txt", 8, True)

'ファイルを閉じる
file.Close
'後始末
Set fso = Nothing

'お知らせ
msgbox "処理完了"
'変数を定義
Dim sumVal : sumVal = 0			'計測値の合計値
Dim ROOP_SU : ROOP_SU = 1000	'計測回数

'計測回数分ループする
For i = 1 To ROOP_SU
	'計測開始時間
	Dim t2 : t2 = Timer
	
	'計測する処理
	Dim cnt1 : cnt1 = 0
	Do while cnt1 <= 1000000
		test = "test"
		cnt1 = cnt1 + 1
	Loop
	
	'計測終了時間を加算
	sumVal = sumVal + (Timer - t2)
Next 

'ファイルシステムオブジェクトの作成
Set fso = CreateObject("Scripting.FileSystemObject")
'結果を出力
Set file = fso.OpenTextFile(".\while:平均" & (sumVal / ROOP_SU) & "秒.txt", 8, True)

'ファイルを閉じる
file.Close
'後始末
Set fso = Nothing

'お知らせ
msgbox "処理完了"

for文は平均約0.17秒で、while(do loop)文は、平均約0.30秒になりました。

for文の方が処理が速いです。

しかし、あくまでもVBScriptでの結果です。

プログラミング言語によってはwhile文の方が速い場合もあるようです。

また、パソコンのスペックによっても計測結果が変わりますのでご理解ください。

まとめ

VBScriptのWhile文を使いこなすことで、条件に応じた柔軟なループ処理を実現することができます。

基本的な使い方から無限ループ、条件に基づく繰り返し処理までを理解し、さまざまなシナリオでWhile文を効果的に利用しましょう。