3-2 条件分岐のマクロ例
マクロを作成する過程において、ある条件を判断して「こちらの処理」または「あちらの処理」を実行した
いケースが必ずでてきます。ここではその条件分岐についてマクロ例を使って説明します。
条件式には表1で示すような種類があります
【表1 比較演算子】
演算子 説明 If文例 結果
< 小さい 7 < 4 If 7 < 4 Then MsgBox "True" Else MsgBox "Fales" Fales
<= 以下 4 <= 7 If 4 <= 7 Then MsgBox "True" Else MsgBox "Fales" True
> 大きい 7 > 4 If 7 > 4 Then MsgBox "True" Else MsgBox "Fales" Fales
>= 以上 4 >= 7 If 4 >= 7 Then MsgBox "True" Else MsgBox "Fales" Fales
= 等しい 4 = 7 If 4 = 7 Then MsgBox "True" Else MsgBox "Fales" Fales
<> 等しくない 4 <> 7 If 4 <> 7 Then MsgBox "True" Else MsgBox "Fales" True



(1)If・・・Then・・・Else ステートメント
条件式を満たした場合は「Then」の後を実行し、満たさなかった場合は
「Else」以降を実行します。
 
Sub 分岐1_1()
Dim aa As Integer
    aa = ThisWorkbook.Sheets("Sheet1").Cells(2, 2)
        If aa > 85 Then
            ThisWorkbook.Sheets("Sheet1").Cells(2, 3) = "優"
        End If
End Sub
--------------------------------------------------
Sub 分岐1_2()
Dim aa As Integer
    aa = ThisWorkbook.Sheets("Sheet1").Cells(2, 2)
        If aa > 85 Then
            ThisWorkbook.Sheets("Sheet1").Cells(2, 3) = "優"
        Else
            ThisWorkbook.Sheets("Sheet1").Cells(2, 3) = "並"
        End If
End Sub
--------------------------------------------------
Sub 分岐1_3()
Dim aa As Integer
    aa = ThisWorkbook.Sheets("Sheet1").Cells(2, 2)
        If aa > 85 Then
            ThisWorkbook.Sheets("Sheet1").Cells(2, 3) = "優"
        ElseIf aa > 60 Then
            ThisWorkbook.Sheets("Sheet1").Cells(2, 3) = "良"
        Else
            ThisWorkbook.Sheets("Sheet1").Cells(2, 3) = "可"
        End If
End Sub




(2)Select Caseテートメント
If文のElseIf を使用すれば複雑な条件分岐もできますが、条件が1つの変数で分岐条件が多い場合は、
「Select Case」を使用した方が簡単で見やすくなります。

 
Sub 分岐2_1()
Dim aa As Integer
    aa = ThisWorkbook.Sheets("Sheet1").Cells(2, 2)
    Select Case aa
        Case Is > 85
            ThisWorkbook.Sheets("Sheet1").Cells(2, 3) = "優"
        Case Is > 60
            ThisWorkbook.Sheets("Sheet1").Cells(2, 3) = "良"
        Case Else
            ThisWorkbook.Sheets("Sheet1").Cells(2, 3) = "可"
    End Select
End Sub
-----------------------------------------------------------
Sub 分岐2_2()
Dim aa As Integer
    aa = ThisWorkbook.Sheets("Sheet1").Cells(2, 2)
    Select Case aa
        Case 86 To 100
            ThisWorkbook.Sheets("Sheet1").Cells(2, 3) = "優"
        Case 61 To 85
            ThisWorkbook.Sheets("Sheet1").Cells(2, 3) = "良"
        Case Else
            ThisWorkbook.Sheets("Sheet1").Cells(2, 3) = "可"
    End Select
End Sub
-----------------------------------------------------------
Sub 分岐2_3()
Dim bb As String
    bb = ThisWorkbook.Sheets("Sheet1").Cells(4, 2)
    Select Case bb
        Case "優"
            ThisWorkbook.Sheets("Sheet1").Cells(4, 3) = "86〜100点"
        Case "良"
            ThisWorkbook.Sheets("Sheet1").Cells(4, 3) = "61〜85点"
        Case "可"
            ThisWorkbook.Sheets("Sheet1").Cells(4, 3) = "60点以下"
        Case Else
             ThisWorkbook.Sheets("Sheet1").Cells(4, 3) = "指定文字以外"
    End Select
End Sub




(3)If文のその他の記述方法例

[1]If文は1行形式でも記述できます
  一般的にはThen以降を行を1段下げ、Else以降も行を変えて「分岐3_1」マクロのように数ステータスに
分けて記述しましが、「分岐3_1a」マクロのように1行形式でも記述できます。

Sub 分岐3_1()
Dim aa As Integer
    aa = Cells(2, 2)
        If aa > 85 Then
            Cells(2, 3) = "優"
        Else
            Cells(2, 3) = " 並"
        End If
End Sub
---------------------------------------------------------
Sub 分岐3_1a()
Dim aa As Integer
    aa = Cells(2, 2)
        If aa > 85 Then Cells(2, 3) = "優" Else Cells(2, 3) = " 並"
End Sub


[2]Case では条件を2個記述できます
一般的には、Caseの条件別に「分岐3_2」マクロのように行を分けて記述します。
しかし2個の分岐先が同じであれば、「分岐3_2a」マクロのように2条件を1行に記載することができます。

Sub 分岐3_2()
Dim cc As String
    cc = UCase(ThisWorkbook.Sheets("Sheet1").Cells(16, 2))
        If cc = "A" Then
            ThisWorkbook.Sheets("Sheet1").Cells(16, 3) = "優1"
        ElseIf cc = "B" Then
            ThisWorkbook.Sheets("Sheet1").Cells(16, 3) = "優2"
        ElseIf cc = "C" Then
            ThisWorkbook.Sheets("Sheet1").Cells(16, 3) = "良"
        ElseIf cc = "D" Then
            ThisWorkbook.Sheets("Sheet1").Cells(16, 3) = "可"
        Else
            ThisWorkbook.Sheets("Sheet1").Cells(16, 3) = "不可"
        End If
End Sub
---------------------------------------------------------
Sub 分岐3_2a()
Dim cc As String
    cc = UCase(ThisWorkbook.Sheets("Sheet1").Cells(16, 2))
    Select Case cc
        Case "A", "B"
            ThisWorkbook.Sheets("Sheet1").Cells(16, 3) = "優"
        Case "C", "D"
            ThisWorkbook.Sheets("Sheet1").Cells(16, 3) = "並"
        Case Else
             ThisWorkbook.Sheets("Sheet1").Cells(16, 3) = "指定文字以外"
    End Select
End Sub


[3]参照するオブジェクトがないかチェック例
FindメソッドはNothingという特別な戻り値ですが、一致がない場合は「True」であり記述は「分岐3_3」
マクロ例のようになります。この分岐は「If (actv Is Nothing) = Fales Then」でOKです。

Sub 分岐3_3()
suzi = InputBox("数字を入力して下さい", "A列検索", "")
Columns("A:A").Select
Set actv = Selection.Find(suzi, , , xlWhole, xlByColumns, xlNext, True)
        If actv Is Nothing Then
            MsgBox "指定の数字はありません"
        Else
            actv.Activate
            MsgBox suzi & "は「" & ActiveCell.Address & "」に有ります"
            End If
       Range("A1").Select
End Sub


[4]IF文で「True」は省略できます
条件式が真(True)となった場合「True」できます。なおNotを使って「False」を「True」にするテクニックもあり
ます。前述の例をNotを使うと、「If Not actv Is Nothing Then」で「False」を反転させ「True」を省略できる。

Sub 分岐3_4a()
    If "abcd" Like "abcd" = True Then
        MsgBox "文字が一致しています"
    End If
End Sub
---------------------------------------------------------
Sub 分岐3_4b()
    If "abcd" Like "abcd" Then
        MsgBox "文字が一致しています"
    End If
End Sub
---------------------------------------------------------
Sub 分岐3_4c()
    If "abcd" Like "zyxw" = False Then
        MsgBox "文字が不致です"
    End If
End Sub
---------------------------------------------------------
Sub 分岐3_4d()
    If Not "abcd" Like "zyxw" Then
        MsgBox "文字が不致です"
    End If
End Sub


[5]ブランク文字の判定例
条件としてブランクかチェックして処理しようとしたら、意外と手こずった経験があり、ブランク判定の
各種ケースを以下に記述しました。

Sub 分岐3_5a()
    If Cells(1, 1) = "" Then
        MsgBox "空白セルです"
    Else
        MsgBox "セルに[&H" & Hex(Asc(Cells(1, 1))) & "]・・のデータがあります"
    End If
End Sub
---------------------------------------------------------
Sub 分岐3_5b()
    If Cells(1, 1) = "" Or Cells(1, 1) = " " Or Cells(1, 1) = " " Then
        MsgBox "空白セルです"
    Else
        MsgBox "セルに[&H" & Hex(Asc(Cells(1, 1))) & "]・・のデータがあります"
    End If
End Sub
---------------------------------------------------------
Sub 分岐3_5c()
    If IsEmpty(Cells(1, 1)) Then
        MsgBox "空白セルです"
    Else
        MsgBox "セルに[&H" & Hex(Asc(Cells(1, 1))) & "]・・のデータがあります"
    End If
End Sub
---------------------------------------------------------
Sub 分岐3_5d()
    If Len(Cells(1, 1)) = 0 Then
        MsgBox "空白セルです"
    Else
        MsgBox "セルに[" & Len(Cells(1, 1)) & "]文字のデータがあります"
    End If
End Sub




(4)条件式に使用する5種類の論理演算子の使用例一覧表
論理演算子には5種類ありますが、その意味および使用方法(使用例)を判りやすく表2の一覧表にまとめました。

【表2 論理演算子】





(5)条件分岐で引数のどちらか1つを返すIif関数の使用例
Iif関数は、式の評価結果により、2つの引数のうちどちらか1つを返します。
使用例およびそのステータスの実行結果を判りやすく表3にまとめました。

【表3 IIif関数の使い方】

Sub Macro8a()
su = 64
    chk = IIf(su > 80, "優", "並")
 
End Sub




3-3 繰り返し操作のマクロ化
同じ処理を繰り返すマクロには、「For・・・Nextステートメント」「For Each・・・Nextステートメント」
「Do・・・Loopステートメント」があります。それぞれの特徴を理解すれは効率の良いマクロを作成できます。




(1)For・・・Nextステートメント
ループ回数が初めから判っている場合はFor・・・Nextステートメントを使用します。ループカウンターの
変数は0から指定できます。また カウンター数を減少させながらのループ処理もできます。
For・・・Nextステートメントのサンプルマクロ実行結果を画面12に示します。

画面12サンプルマクロ実行結果


Sub 繰返し1_1()
Dim i As Integer
    For i = 1 To 9
        Cells(i, 1).Value = "ループ" & i & "実行"
    Next i
End Sub
----------------------------------------------------------
Sub 繰返し1_2()
Dim i As Integer
    For i = 1 To 9 Step 2
        Cells(i, 2).Value = "ループ" & i & "実行"
    Next
End Sub
----------------------------------------------------------
Sub 繰返し1_3()
Dim i As Integer
Dim ia As Integer
    ia = 1
    For i = 9 To 1 Step -1
        Cells(i, 3).Value = "ループ" & ia & "実行"
        ia = ia + 1
    Next
End Sub
----------------------------------------------------------
Sub 繰返し1_4()
Dim i As Integer
    For i = 1 To 9
        Cells(i, 4).Value = "ループ" & i & "実行"
        If i = 5 Then
            Exit For
        End If
    Next
End Sub


[1]For文で使用できる最終回数(最終セル)抽出例
最終回数として最終セルがよく使用されますが、代表的な最終セル取得方法には以下があります。

'[1] End(xlUp)で読み取り
Sub 最終行1()
Dim endr As Integer
    endr = Range("B10000").End(xlUp).Row
    MsgBox "このシートのデータ最終行は:" & endr
End Sub
----------------------------------------------------
[2]End(xlDown)で読み取り
Sub 最終行2()
Dim endr As Integer
    endr = Range("B3").End(xlDown).Row
    MsgBox "このブロックの最終セル:" & endr
End Sub
----------------------------------------------------
[3]UsedRange最終を読み取り
Sub 最終行3()
Dim endr As Integer
    ActiveSheet.UsedRange.Select
    endr =  Selection.Rows.Count
  MsgBox "このシートのデータ最終行は:" & endr
End Sub
----------------------------------------------------
[4]SpecialCells(xlLastCell)で最終を読み取り
Sub 最終行4()
Dim endr As Integer
    ActiveSheet.Cells.SpecialCells(xlLastCell).Select
        endr = ActiveCell.Row
        endc = ActiveCell.Column
   MsgBox "このシートの最終行[" & endr & "] 最終列[" & endc & "]"
End Sub
----------------------------------------------------
[5]SpecialCells(CurrentRegion)で空白行まで選択
Sub 最終行5()
Dim endr As Integer
    Range("A9").Select
      Selection.CurrentRegion.Select
      endr = Selection.Rows.Count
    Range("A1").Select
 MsgBox "このシートの最終セル:" & endr + 8
End Sub
※[5]はシート内の一部のデータベース(表)を指定するとき使用できて便利です。
 


【参考331】 不要行削除は最終行から若番行に実行する
「空白行削除1」マクロでFor文で下から上方向へ削除例を記述しましたが、同じFor文使用でも行の
上から削除すると下記の問題点があります。

・不要な行を削除しするが、その時次の項目が一段上に上がるがその項目はまだチェックしていない。
 したがって、対策として1行削除した場合はNextで「i」が1個増えても再度同じRowをチェックさせるため
  「i = i - 1」が必要です。

・行を削除しても最終実行回数の指定(本例では変数[cedr])は同じであり最後の方で 不要行の削除
 が終了しても余分な動作をします。対策としては空白行 (本例ではセル(i,1)チェック)になっ
 たら"Exit For"の強制終了で余分な動作を解除できる。

Sub 削除上から()
Dim i As Integer, endr As Integer
Application.ScreenUpdating = False
ThisWorkbook.Sheets("Sheet1").Select
endr = Range("A31000").End(xlUp).Row + 1
 
For i = 3 To endr
    If Cells(i, 1) = "" Then
        Exit Sub
    End If
    If IsNumeric(Cells(i, 1)) = False Then
       Rows(i).Delete Shift:=xlUp
       i = i - 1
    End If
Next
---------------------------------------------------------------------
Sub 削除下から()
Dim i As Integer, endr As Integer
Application.ScreenUpdating = False
ThisWorkbook.Sheets("Sheet1").Select
endr = Range("A31000").End(xlUp).Row + 1
 
For i = endr To 3 Step -1
    If IsNumeric(Cells(i, 1)) = False Then
       Rows(i).Delete Shift:=xlUp
    End If
Next
End Sub


【参考332】 Nextステートメントのあとのカウンタ変数は省略可能
For ・・・ Nextステートメントの「Next i」のように後に付ける変数「i」はカウンタ変数ですが省略可能です
同様にFor Each ・・・Next ステートメントの「Next myobj」などの変数「myobj」はオブジェクト変数ですが
省略できます。一般的に何方のマクロを見ても省略していますが、特に問題はありません。
 
ただし、入れ子(For ・・・Nextステートメントの中に更に別のFor ・・・Nextを入れる)の場合は、どの
ループに対応しているのか明確にしてマクロを判りやすくする意味もあり「Next 」の後のカウンタ変数を
記入した方が良い。




(2)For Each・・・Nextステートメント
コレクションに含まれるオブジェクト数を意識することなく、コレクションを対象
For Each・・・Nextステートメントの使用が適しています。
Sub 繰返し2_1()
Dim sel As Range
    ThisWorkbook.Sheets("ループ").Select
        Cells(4, 1).Select
    Selection.CurrentRegion.Select
    '
    For Each sel In Selection
            If sel.Value > 0.05 Then sel.Interior.ColorIndex = 6
    Next sel
    Cells(1, 1).Select
End Sub
-----------------------------------------------------------
Sub 繰返し2_2()
Dim myrang As Range, sel As Range
    ThisWorkbook.Sheets("ループ").Select
    endr = Range("A1000").End(xlUp).Row
Set myrang = Range(Cells(3, 1), Cells(endr, 1))
    '
    For Each sel In myrang
            sel.Interior.ColorIndex = xlNone
    Next
    Cells(1, 1).Select
End Sub
-----------------------------------------------------------
Sub 繰返し2_3()
Dim sel As Worksheet
    For Each sheet_name In Worksheets
            If Sheets.Count = 1 Then Exit For
        sh = sheet_name.Name
        Worksheets(sh).Select
        aaa = ActiveSheet.UsedRange.Address
        If aaa = "$A$1" And Cells(1, 1) = "" Then
            Application.DisplayAlerts = False
                ActiveWindow.SelectedSheets.Delete
            Application.DisplayAlerts = True
        End If
    Next
End Sub


【参考333】 For Each・・Next が For・・Nextより高速の訳
For Each文は、ループに入るタイミングで、あらかじめ作業対象のコレクション(オブジェクトの集合)を、
メモリに読み込みます。そして、その読み込まれた集合に対して処理をします。これはメモリー上での
処理であり高速になります。
 
一方For文の方は、ループの中にセルを読み取る指示があればそのつどその場所を探して読み取る
ので、メモリー上で処理するFor Each文より処理が遅くなります。
 
なお、覚えると便利なFor Each・・Nextステートメントですが、なじみの薄い方も多いようなので、3-3節で
マクロ例を紹介済みですが、以下に文章で詳しく再説明します。
 
For Each文ではまず、コレクション内の個々のメンバを格納するためにDimステートメントでの変数を
宣言します。変数はバリアントまたはオブジェクトの型を指定します。
次にブック内の全シート名を読取たいのであれば、例えば、オブジェクト変数myobj を使ってWorksheets
コレクションに対して繰り返し処理を行いたいのであれば、「For Each myobj In Worksheets」となり
ForとNextの間に繰り返し処理を記述します。
オブジェクト変数には、処理が実行されるたびに順番にコレクション内のメンバが格納されるので
「myobj.Name」のように格納されたメンバーの名前を読み取れば、1回目の処理では1枚目の
ワークシート名、2回目の処理では2枚目のワークシート名・・・となり全シート名
を読み取ることができます。
なお、コレクション内から取り出される要素の順番を制御することはできません。




(3)Do・・・Loopステートメント
ある条件が満たせれている間、または満たされるまでループ処理を繰り返します。指定する条件が少
なく柔軟性の高い命令ですが、ループから抜ける条件設定に不備があると無限ループになることがあ
ります。条件設定のみ注意すれば使いやすいコマンドです。ループ条件には以下の4種類があります。


[1]ループ前に条件を判断するケース
条件判断を処理の実行前におこなうので、場合によっては処理は一度も
実行されないこともあます。
Sub 繰返し3_1()
Dim i As Integer
i = 1
     Do Until Cells(i, 1) = ""
          If Cells(i, 1) > 100 Then
             Cells(i, 1).Interior.ColorIndex = 6
          End If
         i = i + 1
      Loop
End Sub
-----------------------------------------------------------
Sub 繰返し3_2()
Dim i As Integer
i = 1
     Do While Cells(i, 1) <> ""
          If Cells(i, 1) > 100 Then
             Cells(i, 1).Interior.ColorIndex = 8
          End If
         i = i + 1
      Loop
End Sub


[2]ループ後に条件を判断するケース
条件判断を処理の実行後におこなうので、処理は必ず一度は実行されます。

Sub 繰返し3_3()
Dim i As Integer
i = 1
     Do
        If Cells(i, 1) > 100 Then
             Cells(i, 1).Interior.ColorIndex = 4
        End If
        i = i + 1
      Loop Until Cells(i, 1) = ""
End Sub
------------------------------------------------------------
Sub 繰返し3_4()
Dim i As Integer
i = 1
     Do
        If Cells(i, 1) > 100 Then
             Cells(i, 1).Interior.ColorIndex = 7
        End If
        i = i + 1
      Loop While Cells(i, 1) <> ""
End Sub


[3]条件判断をループの中で行うケース
ループ実行中に条件を判断してループを抜けます

 
Sub 繰返し3_5()
Dim i As Integer
i = 1
    Do
       If Cells(i, 1) > 100 Then
             Cells(i, 1).Interior.ColorIndex = 3
        End If
        i = i + 1
        If Cells(i, 1) = "" Then Exit Do
    Loop
End Sub



【戻る】    【Top画面】   【HPへ】