VBScriptでfor文をマスターする

VBScript

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

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

構文

for…next文

指定した回数分処理を繰り返す場合に使用されます。

「Step 増減の値」は、任意で指定することができます。

指定しない場合は、[開始番号]が1ずつ増加していきますので注意してください。

For [開始番号] To [終了番号] Step [増減の値]
    '繰り返す処理を中に記述
Next

for each…next文

コレクションの要素分処理を繰り返す場合に使用されます。

複数の要素(値)を持った配列やList、Dictionaryといったデータの集まりを指します。

若い要素番号から順番に取得し、処理を繰り返します。

For Each [要素] In [コレクション]
    '繰り返す処理を中に記述
Next

サンプルコード

文字列の桁数、配列の要素、Listの要素、Dictionaryの要素、ファイル数などよく使用されていそうな記述例をご紹介し、解説していきます。

数値の繰り返し処理

For i = 1 To 5
    MsgBox "Count: " & i
Next

「i」の「1」が「5」になるまで繰り返すことで5回繰り返して処理を行います。

ステップ値の指定

For i = 1 To 10 Step 2
    MsgBox "Count: " & i
Next

iの「1」が2ずつ増加され、iが「1」「3」「5」「7」「9」のとき繰り返し処理を行います。

逆順の繰り返し処理

For i = 10 To 1 Step -1
    MsgBox "Count: " & i
Next

i」の「10」が「1」になるまで繰り返すことで10回繰り返して処理を行います。

文字列の桁数分ループ

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

'文字列の桁数分ループする
For i = Len(aiueo) To 1 Step -1
	'結果:お → い → う → え → お
	Msgbox Mid(aiueo,i,1)
Next

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

「i」が5の状態で一度、中の処理が実行されます。Mid関数により、変数「aiueo」(引数1)の5桁目(引数2)を1桁分(引数3)抽出し、文字「お」がメッセージに表示されます。

次に、Stepの「-1」によって、「 i + -1」されて「i」が「5」から「4」になります。中の処理が実行され、「え」がメッセージに表示されます。

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

配列の要素分ループ

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

'配列の要素分ループする
For Each index In aryMozi
	'結果:要素1 → 要素2 → 要素3
    msgbox index
Next

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

若い要素番号から順番に取得されるため、「要素1 → 要素2 → 要素3」の順番でメッセージが表示されています。

Listの要素分ループ

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

'リストの要素分ループする
For Each index In objList
	'結果:要素1 → 要素2 → 要素3
    msgbox index
Next

'後始末
Set objList = Nothing

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

若い要素番号から順番に取得されるため、「要素1 → 要素2 → 要素3」の順番でメッセージが表示されています。

Dictionaryの要素分ループ

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

'Dictionaryの要素分ループする
For Each key In objDic.keys
	'結果:キー1値1 → キー2値2 → キー3値3
    msgbox key & objDic(key)
Next

'後始末
Set objDic = Nothing

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

若い要素番号から順番に取得されるため、「キー1値1 → キー2値2 → キー3値3」の順番でメッセージが表示されています。

ファイル数分ループ

'ファイル操作用のオブジェクトを作成
Dim objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject")
'このvbsのフルパスを取得
Dim fullPath : fullPath = objFSO.GetAbsolutePathName(WScript.ScriptName)
'フルパスからフォルダー名を取得
Dim dirPath : dirPath = objFSO.GetParentFolderName(fullPath)
'フォルダー内のオブジェクトを取得
Dim objDir : Set objDir = objFSO.GetFolder(dirPath)

'ファイル数分ループする
For Each file In objDir.Files
	'結果:実行したvbsファイルと同階層のファイル名が表示される
    msgbox objFSO.GetFileName(file)
Next

'後始末
Set objDir = nothing
Set objFSO = nothing

ファイル操作を行うためのオブジェクト「Scripting.FileSystemObject」を作成し、セットします。

次に、実行されたvbsファイルの絶対パス(フルパス)を取得します。

フルパスからファイル名を除いたフォルダーのパスを取得します。

最後に、取得したフォルダーのパスにあるオブジェクトを取得します。

最後に取得したオブジェクトからファイルのオブジェクトだけを指定します(objDir.Filesの部分)。

ファイル名の昇順で取得され、メッセージが表示されます。

ネストされたFor文

for文をネスト(入れ子)させることで、多重ループを作成することができます。

For i = 1 To 3
    For j = 1 To 3
        MsgBox "i: " & i & ", j: " & j
    Next
Next

ループ処理を終了させる

for文のループ(繰り返す)処理を強制的に終了させたい場合があると思います。

for文の中で「Exit For」を記述するだけで、ループ処理を終了することができます。

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

'文字列の桁数分ループする
For i = 1 To Len(aiueo)
	'文字列から1文字を取得
	Dim chrTmp : chrTmp = Mid(aiueo,i,1) 

	'forから抜ける
	If chrTmp = "い" Then Exit For Else
	
    '結果を確認 → あ
	Msgbox chrTmp
Next

Len関数により、変数「aiueo」の文字数(5)を取得し、変数「i」が1、2、3、4、5の5回分繰り返し処理されます。

「i」が1の時、Mid関数により変数「aiueo」(引数1)の1桁目(引数2)を1桁分(引数3)抽出し、文字「あ」を変数「chrTmp」にセットしています。

次に、if文で変数「chrTmp」が「い」の場合、for文を抜けますが、変数「chrTmp」は「あ」のため、スルーされます。

次に、変数「chrTmp」の「あ」がメッセージボックスで出力されます。

一連の処理が終わり、次のループへ行きます。

forの「Step 増減値」がない場合は、1ずつ増加されるので「 i + 1」されて「i」が「1」から「2」になります。

「i」が2の時、Mid関数により文字「い」を変数「chrTmp」にセットしています。

次に、if文で変数「chrTmp」が「い」なので、for文を抜けます。

結果、メッセージボックスで出力されたのは「あ」のみです。

次のループへスキップする

次のループ処理へスキップする方法は、2パターンあります。「for文の中にif文」または「for文の中にfor文」です。それぞれご紹介します。

for文の中にif文

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

'文字列の桁数分ループする
For i = 1 To Len(aiueo)
	'文字列から1文字を取得
	Dim chrTmp : chrTmp = Mid(aiueo,i,1) 

	'お以外は、次のループへスキップする
	If chrTmp = "お" Then
		'結果を確認 → お
		Msgbox chrTmp
	Else
	End If
Next

Len関数により、変数「aiueo」の文字数(5)を取得し、変数「i」が1、2、3、4、5の5回分繰り返し処理されます。

「i」が1の時、Mid関数により変数「aiueo」(引数1)の1桁目(引数2)を1桁分(引数3)抽出し、文字「あ」を変数「chrTmp」にセットしています。

次に、if文で変数「chrTmp」が「お」の場合、メッセージを表示します。

それ以外の場合は、何もしないので結果的に次のループへスキップされます。

そのため、変数「chrTmp」が「あ」「い」「う」「え」のときのメッセージの表示は、スキップされ「お」のみがメッセージで表示されます。

つまり、スキップしたい処理をif文で囲むことで実装できます。

for文の中にfor文

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

'文字列の桁数分ループする
For i = 1 To Len(aiueo)
	'文字列から1文字を取得
	Dim chrTmp : chrTmp = Mid(aiueo,i,1) 

	'次のループへスキップするためにループ処理を1回行う
	For j = 1 To 1
		'次のループへスキップ
		If chrTmp <> "お" Then Exit For Else
		
		'結果を確認 → お
		Msgbox chrTmp
	Next
Next

「for文の中にif文」で解説した内容とほとんど同じで、変数「chrTmp」が「お」以外の場合に2個目のfor文から抜けることで結果的に次のループへスキップされます。

そのため、変数「chrTmp」が「あ」「い」「う」「え」のときのメッセージの表示は、スキップされ「お」のみがメッセージで表示されます。

つまり、スキップしたい処理をfor文で囲み「Exit For」することで実装できます。

また、「for文の中にfor文」ではなく「for文の中にdo loop文」でも実装できます。

やっていることは同じなので省略します。

おすすめ

私は、「for文の中にif文」の方法をおすすめします。

for文やdo loop文は、そもそも処理を繰り返したいときに使用するものなので、次のループへスキップする処理として少し意味合いが異なります。

一般的に第三者がコードを見たときに、for文よりif文で記述された方がわかりやすいです。

「for文の中にif文」で書く方が無難でしょう。

for文とwhile文の違い

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

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のFor文を使いこなすことで、繰り返し処理を効率的に行うことができます。

カウンター変数や範囲、ステップ値を適切に設定し、必要に応じてネストやExit For文を使って柔軟にループを制御しましょう。