ループの種類と使い方、それぞれの違いについてご説明します。
ループを使えるとVBAも、出来る事、自動化の幅がかなり広くなります。
ループと一言でいっても、VBAにはいくつかのループ方法があります。
指定した回数でカウンター式のループや、指定したオブジェクト内を全てループする方法、条件を達成もしくは未達成するまでループさせる方法などです。
それぞれサンプルデータと、コードを使用して説明します。
ループとセットで覚えると便利なIF文については「IF文の使い方と分岐方法」をご覧下さい。
ループの種類
ループの種類は大きく分けて、以下の3つです。
- For~Next
- For Each In~Next
- Do~Loop
3つのループをそれぞれSampleコードでご説明します。
基本的には上の2つを覚えたら大抵の処理には対応出来ます。
For~Next
For〜Nextの使い方
この「For~Next」は利用頻度が高いループです。
カウントアップやカウントダウンで変数に数字を格納して処理をする際に使用します。
「For~Next」は「For 変数 = 開始値 To 終了値 Step 増減数」と記述します。
開始値と終了値は数値となり、Stepはループの増減数を数値で指定します。
Stepは省略可能で、省略した場合はデフォルトで1増加となります。
-1などマイナスを指定すると、指定数分減少します。
また、ループに使用する変数の「Next 変数」の変数も省略可能です。
記述方法
「For~Next」は以下のように記述します。
カウントアップ
「For i = 2 To 8 Step 1」のように「For 変数 = 開始値 To 終了値 Step 増数」と記述し、「Next 変数」で終わります。
ForからNextの間に処理したい内容を記述します。
「Step 1」は省略可能で、省略するとデフォルトで1増加となり、「Next i」の「i」も省略可能です。
Sub Sample1()
Dim i As Long '数値型
For i = 2 To 8 Step 1
'処理
Next i
End Sub
カウントダウン
「For i = 8 To 2 Step -1」のように「For 変数 = 開始値 To 終了値 Step 減数」と記述し、「Next 変数」で終わります。
カウントアップと大きく違うところは、「8 To 2 Step -1」と大きい数字から、小さい数字へと指定して、Step -1と減少させることです。
Sub Sample2()
Dim i As Long '数値型
For i = 8 To 2 Step -1 '指定した値から値まで1ずつ減少してループする
'処理
Next i
End Sub
サンプルコード
行をループする
次のようなデータを用意しました。
こちらのデータのB列の値をループで合計したいと思います。
Sub Sample3()
Dim i As Long '数値型
Dim mySum As Long
For i = 2 To 8 Step 1 '2行目から8行目まで1ずつ増加してループする
mySum = mySum + Cells(i, 2) 'mySumという変数にB列のデータを順に加算していきます。
Next i
Cells(9, 2) = mySum 'すべて合計したらB9に出力します。
End Sub
B9に合計が算出されました。
Stepを指定する
次はStepを2にしてみた場合です。
Sub Sample4()
Dim i As Long '数値型
Dim mySum As Long
For i = 2 To 8 Step 2 '2行目から8行目まで2ずつ増加してループする
mySum = mySum + Cells(i, 2) 'mySumという変数にB列のデータを順に加算していきます。
Next i
Cells(9, 2) = mySum 'すべて合計したらB9に出力します。
End Sub
2,4,6,8行目のみ加算した結果がB9に出力されました。
列をループする
もちろん列のループも可能です。
次のデータは先程のデータを行と列を入れ替えたデータです。
Sub Sample5()
Dim i As Long '数値型
Dim mySum As Long
For i = 2 To 11 Step 1 '2列目から11列目まで1ずつ増加してループする
mySum = mySum + Cells(2, i) 'mySumという変数に2行目のデータを順に加算していきます。
Next i
Cells(2, 12) = mySum 'すべて合計したらL2に出力します。
End Sub
Cellsの行に使用していた変数「i」を列と入れ替えると列のループになります。
3.For Each In~Next
For Each In~Nextの使い方
「For Each In~Next」はFor~Nextの変数のカウンタ方法とは違い、配列やコレクション(オブジェクトの集まり)をループします。
配列やコレクションとは、一つのグループといったイメージです。
グループ内をまとめてループしたい時に使用します。
サンプルコード
図のようにSheet1~7まで用意したデータがあり、このシートをループさせます。
データの各シートのA1には「これはシート〇です。」と入力されています。
シートをループしてシート名を取得する
Sheet1からSheet7をループして、シート名を順番に取得します。
Sub Sample1()
Dim mySh As Worksheet 'ワークシートを変数で宣言
For Each mySh In Worksheets 'ワークシートコレクションをループ
MsgBox mySh.Name 'Sheet1~7まで順番にシート名をダイアログに出力
Next
End Sub
シートをループしてセルの値を取得する
各シートのA1を取得して、ダイアログボックスへ表示させるコードです
Sub Sample2()
Dim mySh As Worksheet 'ワークシートを変数で宣言
For Each mySh In Worksheets 'ワークシートコレクションをループ
'シート1~7のA1を順番にダイアログに出力
MsgBox mySh.Cells(1, 1) 'cells(1,1)はRange("A1")でも同じです。
Next
End Sub
For〜Nextで同じループをする
これはFor~Nextで書くことも可能で、シート名を取得するには、次のようなコードになります。
Sub Sample3()
Dim i As Long '整数で宣言
For i = 1 To Worksheets.Count 'ワークシートコレクションをループ
MsgBox Worksheets(i).Name 'Sheet1~7まで順番にシート名をダイアログに出力
Next
End Sub
ワークシートは1、2、3と左から順番に番号で指定可能です。
Sheet1であればWorksheets(1)の様に記載します。
※Sheet1だから1ではなく、左から1つ目のシート=1です。
シート数(最後のシート)はWorksheets.Countで取得することが出来ます。
4.Do~Loop
「Do~Loop」は「For~Next」や「For Each In Next」とは異なり、少し複雑です。
「条件を満たすまで」や、「条件を満たしていない間」ループすると言ったループになります。
ゆえに、コードの書き方次第では、ループを離脱するためのコードを、意図的に組み込まないと、無限ループに陥ったりします。
Do~Loopの記載方法は「Do~Loop」のみと、WhileとUntilを記載する方法で分かれます。
さらには、WhileとUntilを記載する位置でも分かれます。
ややこしいですね・・・。
順番にご説明致します。
Do~Loopのみ
WhileもUntilも書かずにループします。
この方法は条件がないため、ループを離脱するコードがないと無限ループします。
「Exit Do」でループを離脱できます。
Sub Sample4()
Dim i As Long
'セルに変数が100未満の間はループする
'予めiに1を代入
'(※セルは1から始まるため代入しないと0から始まりエラーになる)
i = 1
Do
Cells(i, 1) = i 'セルにiを入力
i = i + 1 'iに+1増加させる
If i = 100 Then 'iが100になったら離脱
Exit Do
End If
Loop
End Sub
While文
「Do While 条件式」もしくは、最後に「Do While 条件式」の形式で条件を指定します。
条件式がTrueの間、処理が実行されます。
Whileが最初にある
1回目から条件判定を行い、最初からFalseだと実行されません。
条件がTrueの間ループします。
Sub Sample5()
Dim i As Long
'セルに変数が100未満の間はループする
'予めiに1を代入
'(※セルは1から始まるため代入しないと0から始まりエラーになる)
i = 1
Do While i < 100 'iが100未満の条件式
Cells(i, 1) = i 'セルにiを入力
i = i + 1 'iに+1増加させる
Loop
End Sub
最初から条件がFalseなのでループが実行されません。
Sub Sample6()
Dim i As Long
'セルに変数が100未満の間はループする
'予めiに100を代入
'条件が最初からFalseなので処理が実行されない
i = 100
Do While i < 100
Cells(i, 1) = i
i = i + 1
Loop
End Sub
Sample5の結果で、Sample6は実行されません。
Whileが最後にある
1回目は条件判定を行なわず、実行されます。
条件がTrueの間ループします。
Sub Sample7()
Dim i As Long
'セルに変数が100未満の間はループする
'予めiに1を代入
i = 1
Do
Cells(i, 1) = i
i = i + 1
Loop While i < 100
End Sub
最初から条件はFalseですが、最初の1回は条件判定が無いためループが実行されて、離脱します。
Sub Sample8()
Dim i As Long
'セルに変数が100未満の間はループする
'予めiに100を代入
'最初に条件式がないため1回だけ処理が実行される
i = 100
Do
Cells(i, 1) = i
i = i + 1
Loop While i < 100
End Sub
Sample7の結果です。
Sanmple8の結果で、100しか反映されていません。
Until文
最初に「Until 条件式」もしくは、最後に「Do Until」の形式で条件を指定します。
条件式がTrueになるまでの間、処理が実行されます。
処理の中で条件式がfalseになるように、中断するような文を記述します。
Untilが最初にある
1回目から条件判定を行い、最初からTrueだと実行されません。
条件がFalseの間ループします。
Sub Sample9()
Dim i As Long
'セルに変数が100になるまでループする
'予めiに1を代入
'(※セルは1から始まるため代入しないと0から始まりエラーになる)
i = 1
Do Until i = 100 '「iが100になるまで」の条件式
Cells(i, 1) = i 'セルにiを入力
i = i + 1 'iに+1増加させる
Loop
End Sub
最初から条件がTrueのためループが実行されません。
Sub Sample10()
Dim i As Long
'セルに変数が100になるまでループする
'予めiに100を代入
'条件が最初からTrueなので処理が実行されない
i = 100
Do Until i = 100
Cells(i, 1) = i
i = i + 1
Loop
End Sub
Sample9の結果で、Sample10は実行されません。
Untilが最後にある
1回目は条件判定を行なわず、実行されます。
条件がFalseの間ループします。
Sub Sample11()
Dim i As Long
'セルに変数が100になるまでループする
'予めiに1を代入
i = 1
Do
Cells(i, 1) = i
i = i + 1
Loop Until i = 100
End Sub
Sample11の結果です。
Sub Sample12()
Dim i As Long
'セルに変数が100になるまでループする
'最初に条件式がないため1回だけ処理が実行される
i = 99 'このケースは100から指定すると最終行までループしてエラーになる
Do
Cells(i, 1) = i
i = i + 1
Loop Until i = 100
End Sub
Sample12の結果です。
Sample12はi=100では一度も100にならずエラーになるため99と指定しています。
5.まとめ
「For~Next」は変数のカウンタで増減値を指定してループさせます。
書き方次第では大抵のループに対応出来ます。
「For Each In~Next」は変数やコレクションをループさせる時に使用します。
主にワークシートや、コントロールなどをループするときに使用します。
「Do~Loop」は明確な条件がある時のループで使用します。
扱いが難しく、個人的には監視ツールなどの無限ループしたい時に使ってます。
一番説明が長い割に頻度が低いです。