繰り返しや判断、分岐などは昔からあるBASICと同じ。

開発者でも最近のVisual系ツールをメインにしている方は、コンピュータの基本となるロジックを知らなかったり、知っていても要求に応じての組み立てができない人を良く見かけます。むしろ実質ロジックを知っている「現場」の方が「これ」を理解すれば間違いのない仕組みが早期にできると思います。

■繰り返し処理

For」〜「Next」による繰り返し
繰り返しを操作するインデックスと取りうる値の範囲が決まっている場合の繰り返し処理。
  • Excelシートの行範囲など、繰り返す範囲が明確な繰り返し。
    
    '*******************************************************************************
    '   単純なループ処理のサンプル
    '
    '   作成者:井上治  URL:http://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
    '*******************************************************************************
    Option Explicit
    
    '*******************************************************************************
    ' 単純なインデックスの繰り返し
    '*******************************************************************************
    Sub TEST1()
        Dim GYO As Long
    
        ' 行が2〜101までbA列にセットする
        For GYO = 2 To 101
            ' 行から1を引いた値をA列にセットする
            Cells(GYO, 1).Value = (GYO - 1)
        Next GYO
    End Sub
    
    '*******************************************************************************
    ' インデックス加減算順位を明示する
    '*******************************************************************************
    Sub TEST2()
        Dim GYO As Long
    
        ' 一番後ろの入力セルを探す
        For GYO = 65536 To 1 Step -1
            ' A列にデータが見つかったら抜ける(Exit For)
            If Cells(GYO, 1).Value <> "" Then Exit For
        Next GYO
        ' 最終行の表示
        MsgBox "最終行は" & GYO & "行です"
    End Sub
    
    '*******************************************************************************
    ' シート初期化
    '*******************************************************************************
    Sub TEST3()
        Rows("1:65536").ClearContents
        ActiveWindow.ScrollRow = 1
        Range("$A$1").Select
    End Sub
    
    '--------------------------------<< End of Source >>----------------------------
    
    上のサンプルは、「GYO」というインデックス値を「2」から「101」まで1ずつカウントアップしながら繰り返すという単純ループです。
    下のサンプルは、カウントアップする「増分(Step)」を指定する方法で、サンプルでは「-1」と減算する例です。(上のサンプルには「Step」が記述されていませんが、省略時は「Step 1」として作用します。)
  • インデックスではなくオブジェクトを取り扱う例。
    
    '*******************************************************************************
    '   ワークシートを順次取得するループ処理
    '
    '   作成者:井上治  URL:http://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
    '*******************************************************************************
    Option Explicit
    
    '*******************************************************************************
    ' このワークブックのシート名を順次表示する
    '*******************************************************************************
    Sub TEST3()
        Dim objSH As Worksheet
    
        ' ワークシートオブジェクトを順次取得する(あるだけ全て)
        For Each objSH In ThisWorkbook.Worksheets
            ' シート名を表示
            MsgBox "シート名=" & objSH.Name
        Next objSH
    End Sub
    
    '--------------------------------<< End of Source >>----------------------------
    
    このサンプルは自分のExcelワークブック(ThisWorkbook)内の全シートを順次ループします。先に「objSH」はワークシートオブジェクトとして宣言しており、「For EachIn 〜」構文でオブジェクトとして順次存在する限り繰り返します。
  • 繰り返し中の任意脱出(1件目のサンプルの「TEST2」で使用)
    ForNextは、繰り返しを操作するインデックス等を組み合わせて用いますが、その繰り返し動作中に処理上の判断で繰り返しから脱出することができます。
    脱出させる場合は、Exit Forと記述します。但し、ForNextが2重3重に処理されているような場合は、Exit Forを記述したレベルのみしか脱出できません。

Do」〜「Loop」による繰り返し
For」〜「Nextが繰り返しを操作するインデックスやオブジェクトを用いるのに対し、脱出(又は脱出しない)条件だけを指定するのがDo」〜「Loopです。
  • 上記のFor」〜「Nextのサンプルと同様の機能の処理サンプルです。
    
    '*******************************************************************************
    '   単純なループ処理のサンプル
    '
    '   作成者:井上治  URL:http://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
    '*******************************************************************************
    Option Explicit
    
    '*******************************************************************************
    ' 単純なインデックスの繰り返し
    '*******************************************************************************
    Sub TEST1()
        Dim GYO As Long
    
        ' 行が2〜101までbA列にセットする
        GYO = 2
        Do While GYO <= 101
            ' 行から1を引いた値をA列にセットする
            Cells(GYO, 1).Value = (GYO - 1)
            ' 行のカウントアップ
            GYO = GYO + 1
        Loop
    End Sub
    
    '*******************************************************************************
    ' インデックス加減算順位を明示する
    '*******************************************************************************
    Sub TEST2()
        Dim GYO As Long
    
        ' 一番後ろの入力セルを探す
        GYO = 65536
        Do While GYO >= 1
            ' A列にデータが見つかったら抜ける(Exit Do)
            If Cells(GYO, 1).Value <> "" Then Exit Do
            ' 行のカウントダウン
            GYO = GYO - 1
        Loop
        ' 最終行の表示
        MsgBox "最終行は" & GYO & "行です"
    End Sub
    
    '*******************************************************************************
    ' シート初期化
    '*******************************************************************************
    Sub TEST3()
        Rows("1:65536").ClearContents
        ActiveWindow.ScrollRow = 1
        Range("$A$1").Select
    End Sub
    
    '--------------------------------<< End of Source >>----------------------------
    
    機能は、For」〜「Nextの上のサンプルと同じです。
    Do」〜「Loop」は、それ自身でカウントアップ等の機能がないので、操作するインデックスは自分でカウントアップ/カウントダウンしなければなりません。
  • While」で条件を記述すると「脱出しない条件」となり、「Until」で条件を記述すると「脱出する条件」となります。
  • While」や「Until」は、「Do」の右、又は「Loop」の右に記述することもできます。
    Do」の右に書いた場合は、ループに入る前に条件判定されるため、ループに入らないケースがあります。逆に「Loop」の右に書いた場合は、ロープに入る前の条件にかかわらずロープには入ってしまいます。
  • Do」〜「Loop」で、「While」や「Until」を書かないこともできます。この場合はループ内部で「Exit Do」記述で脱出しない限り、ループから脱出しません。

■判断・分岐処理

If」「Then」〜「Else」〜「End If」による判断・分岐
このサンプルは、ワークシート側で選択されている行が「奇数か偶数か」と「3で割り切れるか」を二重にしたサンプルです。

'*******************************************************************************
'   判断文のサンプル
'
'   作成者:井上治  URL:http://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'*******************************************************************************
Option Explicit

Sub TEST4()
    Dim GYO As Long
    Dim strMSG As String

    ' 現在の行を取得する
    GYO = ActiveCell.Row
    ' GYOは奇数か(Modは剰余を算出)
    If (GYO Mod 2) <> 0 Then
        strMSG = "この行は奇数、"
        ' さらに3で割り切れるか
        If (GYO Mod 3) <> 0 Then
            strMSG = strMSG & "でも3で割り切れない"
        Else
            strMSG = strMSG & "しかも3で割り切れる"
        End If
    Else
        strMSG = "この行は偶数、"
        ' さらに3で割り切れるか
        If (GYO Mod 3) <> 0 Then
            strMSG = strMSG & "でも3で割り切れない"
        Else
            strMSG = strMSG & "けれど3で割り切れる"
        End If
    End If
    MsgBox strMSG
End Sub

'--------------------------------<< End of Source >>----------------------------
単純なIfでは説明するまでもないでしょうから、二重にしてみただけですが、サンプルで適当な行っを選択して「マクロ」を実行してみて下さい。
If_Elseサンプル2
(この画像をクリックするとサンプルが起動します。)
メッセージはあえてIfの中で表示させず、「3で割り切れるか」の結果をメッセージ文に追加してから最後に表示しています。
VBEでは、デフォルトでTabキー1回につき4カラム字下げします。今までの例でもFor」〜「NextDoLoopの中身は字下げしていますし、ここでも内側のIfは字下げし、Ifの判断後の処理も字下げして判りやすくします。
後で理解できるように「コメント」は適切に入れて下さい。
  • Else」を書かない場合は、否定条件では何も処理を行ないません。また、「Else」を書かない条件でかつ肯定側処理の記述が1行記述の場合は、If」〜「Thenから続けて肯定処理を記述しても構いません。
    この場合は「End If」は書いてはなりません。この場合を除くと「End If」は必須です。

If」「Then」〜「Else」〜「End If」に「And」や「Or」を組み合わせる。また、「ElseIf」を使う。
効率の善し悪しは別として、上のサンプルを別の形で表示します。

'*******************************************************************************
'   判断・分岐処理のサンプル
'
'   作成者:井上治  URL:http://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'*******************************************************************************
Option Explicit

Sub TEST5()
    Dim GYO As Long
    Dim strMSG As String

    ' 現在の行を取得する
    GYO = ActiveCell.Row
    ' GYOは奇数かさらに3で割り切れるか(Modは剰余を算出)
    If (((GYO Mod 2) <> 0) And ((GYO Mod 3) <> 0)) Then
        ' 奇数でかつ3で割り切れない
        strMSG = "この行は奇数、でも3で割り切れない"
    ElseIf (((GYO Mod 2) <> 0) And ((GYO Mod 3) = 0)) Then
        ' 奇数でかつ3で割り切れる
        strMSG = "この行は奇数、しかも3で割り切れる"
    ElseIf (((GYO Mod 2) = 0) And ((GYO Mod 3) <> 0)) Then
        ' 偶数でかつ3で割り切れない
        strMSG = "この行は偶数、けれど3で割り切れない"
    Else
        ' 偶数でかつ3で割り切れる
        strMSG = "この行は偶数、でも3で割り切れる"
    End If
    ' メッセージ表示
    MsgBox strMSG
End Sub

'--------------------------------<< End of Source >>----------------------------
動作結果はすぐ上のサンプルと同じになるはずです。上から最初の「If」の判断、続いて2カ所の「ElseIf」の判断があり、どれにも該当しないと最後の「Else」は「以外全て」なのでこれに合致したことになります。
Else」がない場合は、そのまま「End If」以降に進みます。

Select Case」による判断・分岐
Select Caseは、1つの比較対象に対してIf」「ThenElseのように正誤だけの判断ではなく、複数の判断での処理に分かれる場合に使います。

'*******************************************************************************
'   判断・分岐処理(多分岐)のサンプル
'
'   作成者:井上治  URL:http://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'*******************************************************************************
Option Explicit

Sub TEST6()
    ' A1セルに評価点を入れる
    Select Case Cells(1, 1).Value
        Case 100:       MsgBox "満点です。おめでとう!!"
        Case 99:        MsgBox "ほとんど満点です。おめでとう!!"
        Case Is >= 95:  MsgBox "おしい!!次でがんばろう!"
        Case Is >= 90:  MsgBox "上出来です。今度はもっとがんばろう!"
        Case Is >= 80:  MsgBox "一応、上位ですが「天狗」にならないように"
        Case Is >= 50:  MsgBox "中くらいです。"
        Case Is >= 30:  MsgBox "良くありません。"
        Case Else:      MsgBox "やり直してきなさい!"
    End Select
End Sub

'--------------------------------<< End of Source >>----------------------------
Cells(1, 1).Value」のSelect Caseサンプルなので、A1セルの値によって処理(この場合は表示されるメッセージ)が変わります。
この他分岐判定では、上から順に判定してその条件に合致したらその指示処理だけ行ない、処理後は以降の判定は行ないません。
  • 上の「If」で「Case」の分を「Else If」を繰り返しても同様の結果が得られますが、「IfElseIf」で記述すると「Cells(1, 1).Value」を何回も書くことになります。処理効率に触れた書物ではSelect Caseの方が「効率が良い」とされているようです。
  • Case 100」「Case 99」は単一の値の判定です。(「:」は同一行に他の処理ステートを置く場合のセパレータで、行を換えたのと同じことです)
  • Case Is >= 95」は、「値が95以上」の場合の判定です。上記でも説明した通り、「値が95以上」は「100」や「99」が含まれますが、「100」と「99」は上の「Case」で判定されるため、この行の対象は「98以下」となります。
  • Case Is >= 30」までの判定にかからない分は、全て「Case Else」の判定で合致します。「上記以外全て」の意です。「Case Else」以降に他の「Case」があっても意味を持ちません。
    Case Else」を書かない場合は、「上記以外」は何もせずにこのSelect Caseの判定を抜けます。
1つの「Case」から次の「Case」まで(又は「End Select」までがその「Case」の判定に合致した場合の処理となります。

ついでですが、先ほどの「奇数/偶数」と「3で割り切れるか」の他分岐判断を無理矢理ですが「Select Case」で記述することもできます。

'*******************************************************************************
'   判断・分岐処理のサンプル
'
'   作成者:井上治  URL:http://www.ne.jp/asahi/excel/inoue/ [Excelでお仕事!]
'*******************************************************************************
Option Explicit

Sub TEST5_2()
    Dim GYO As Long
    Dim strMSG As String

    ' 現在の行を取得する
    GYO = ActiveCell.Row
    ' GYOは奇数かさらに3で割り切れるか(Modは剰余を算出)
    Select Case True
        Case (((GYO Mod 2) <> 0) And ((GYO Mod 3) <> 0))
            ' 奇数でかつ3で割り切れない
            strMSG = "この行は奇数、でも3で割り切れない"
        Case (((GYO Mod 2) <> 0) And ((GYO Mod 3) = 0))
            ' 奇数でかつ3で割り切れる
            strMSG = "この行は奇数、しかも3で割り切れる"
        Case (((GYO Mod 2) = 0) And ((GYO Mod 3) <> 0))
            ' 偶数でかつ3で割り切れない
            strMSG = "この行は偶数、けれど3で割り切れない"
        Case Else
            ' 偶数でかつ3で割り切れる
            strMSG = "この行は偶数、でも3で割り切れる"
    End Select
    ' メッセージ表示
    MsgBox strMSG
End Sub

'--------------------------------<< End of Source >>----------------------------
このような記述は、この前の「Select Case」で同一変数の参照を一度にまとめるような効率改善にはなりませんが、多少「見やすい」のかも知れません。

■判断・分岐と繰り返しの組み合わせ

判断・分岐と繰り返しの組み合わせの例題を挙げてみます。
簡単な例題です。   結果だけ求めるなら、計算式と条件付き書式の組み合わせで実現できることですが、これをあえてマクロで考えてみて下さい。 計算式をセルに設定したり条件付き書式を使わずに、A列の2行目から101行目まで一連番号をセルに登録し、その番号が偶数でかつ3で割り切れる場合はそのセルを黄色で塗りつぶして下さい。
どうでしょうか。この下に回答例のコードを書いてありますが、見ないで作ってみて下さい。
前のページから「判断・分岐と繰り返し」を説明していながら、このページでは「繰り返し」のコード例を先に説明しています。ここからの例題にはその方が都合良いのですが、いかがでしょう。 上に挙げてあるサンプルコードを少し変えて組み合わせるだけで実現できることなのです。
説明していないのは「セルを黄色で塗りつぶし」ですが、例えばA1セルを黄色で塗りつぶすには、

    Range("A1").Interior.ColorIndex = 6
とか、

    Range("A1").Interior.Color = vbYellow
このように記述すれば良いです。このようなプロパティは実際の操作をマクロの記録を動かしてやれば掴めるものです。

では、マクロを作成してみましょう。
A列の2行目から101行目まで一連番号をセルに登録」というのは、このページの最初のサンプルの

'*******************************************************************************
' 単純なインデックスの繰り返し
'*******************************************************************************
Sub TEST1()
    Dim GYO As Long

    ' 行が2〜101までbA列にセットする
    For GYO = 2 To 101
        ' 行から1を引いた値をA列にセットする
        Cells(GYO, 1).Value = (GYO - 1)
    Next GYO
End Sub
このプロシージャがそのまま使えます。

「その番号が偶数でかつ3で割り切れる場合は」の判断は、ここから少し上の「TEST5」プロシージャが近いサンプルです。但し、判断する番号は「GYO」ではなく「GYO - 1」ですね。 まずはこの「GYO - 1」が何回も出てきてしまうようなので、最初に求めて別の変数に入れておくことにしましょう。

'*******************************************************************************
' 単純なインデックスの繰り返し(組み合わせの前段階)
'*******************************************************************************
Sub TEST7_1()
    Dim GYO As Long
    Dim BANGOU As Long

    ' 行が2〜101までbA列にセットする
    For GYO = 2 To 101
        ' 行から1を引いた値をA列にセットする
        BANGOU = GYO - 1
        Cells(GYO, 1).Value = BANGOU
    Next GYO
End Sub

次に、この「BANGOU」の値が「その番号が偶数でかつ3で割り切れる場合は」の判断をします。

    ' BANGOUは偶数でかつ3で割り切れるか(Modは剰余を算出)
    If (((BANGOU Mod 2) = 0) And ((BANGOU Mod 3) = 0)) Then
この判断を上記の繰り返し処理の中に埋め込んで、その判断が肯定の時に塗りつぶします。

'*******************************************************************************
' 繰り返しと判断・分岐の組み合わせ処理
'*******************************************************************************
Sub TEST7_2()
    Dim GYO As Long
    Dim BANGOU As Long

    ' 行が2〜101まで一連番号をA列にセットする
    For GYO = 2 To 101
        ' 行から1を引いた値(一連番号)をA列にセットする
        BANGOU = GYO - 1
        Cells(GYO, 1).Value = BANGOU
        ' 一連番号が偶数でかつ3で割り切れるか(Mod関数は剰余を算出)
        If (((BANGOU Mod 2) = 0) And ((BANGOU Mod 3) = 0)) Then
            ' 割り切れる時は黄色で塗りつぶし
            Cells(GYO, 1).Interior.ColorIndex = 6
        End If
    Next GYO
End Sub
結果はこのようなコードになると思いますが、いかがでしょうか。実行すると、
繰り返しと判断・分岐の組み合わせサンプル
このようになります。

※業務の仕様要件い対して、コードの組み立てを考えていくことは自分で問題を作成して回答を作ることでもあり難しいことですが、その段階まで来ている人は「仕様要件からコードの組み立てを考える。」をご覧下さい。