IT系/VBA/基本/条件分岐

Last-modified: 2020-07-19 (日) 08:00:15

目次


概要

条件分岐に関するVBAのTIPS。

条件分岐

条件分岐については、If...Then...Else ステートメントによる分岐処理と、Select Case ステートメントによる分岐処理がある。
また、VBA関数を使った簡易な分岐処理も可能である。

If...Then...Else ステートメント

  • 条件に一致するとき (Then) や、しないとき (Else) だけ処理を実行する。
  • ElseIf で複数の分岐にしたり And や Or を使用して複数の条件を指定できる。ElseIfは複数指定可能*1
    If 条件式1 Then
        条件式1を満たした場合(Trueである場合)の処理
    ElseIf 条件式2 Then
        条件式2を満たした場合(Trueである場合)の処理
    Else
        条件式1と条件式2を満たさなかった場合(Falseである場合)の処理
    End If
  • 条件式には、比較演算子、論理演算子を使用した条件を記載する他、Boolean型(True,False)の判定結果を返す式を指定する。
    演算子、判定については「IT系/VBA/基本/判定」参照。
    なお、True,Falseの実態は、-1,0の数値であり*2、また0ならFalse、0以外はTrueと判定されるため、厳密にはBoolean型の結果でなくても判定可能であるが、あえて数値を使用するメリットはない。
  • If文の例
    If a = 0 Then
        Debug.Print "aは0"
    Elseif a = 1 Then
        Debug.Print "aは1"
    Else
        Debug.Print "aは0,1以外"
    End If
  • ElseのないIf文は、1行で書くことも可能。
    条件が複雑な場合、可読性が悪くなりやすいことから推奨はされない。
    If a = 0 Then Debug.Print "aは0"
    If a = 1 Then Debug.Print "aは1"

Select Case ステートメント

  • 複数の条件により処理を分岐させたい場合はSelect Caseステートメントを使用する。
  • 「Select Case 変数」の形式で式を評価し、Case以下の条件に合致(式を評価した結果がtrueであるとき)だけその次の文を実行する。
    条件がtrueでないときは、次のCase以下の条件を評価する。
    どのCase以下の条件にも当てはまらない場合はCase Else以下の文を実行する。
  • 最初に合致した条件の処理のみが行われる。
  • Case 条件を追加して簡単な入力でいくらでも条件を増やせるため、If 文に比べて、複数の条件で処理を分岐させたい場合に向くとされる。
  • Select Case文の例
    Select Case value
        Case 1
         myColor = 3 '赤
       Case 2
         myColor = 6 '黄
       Case 3,4
         myColor = 8 '水色
       Case Else
         myColor = 10 '緑
    End Select
  • 比較値には、次のような指定ができる。
    この値と等しいか判定。
    To数値や文字列の範囲に含まれているか判定。左側に小さい値を、右側に大きい値を指定。
    Is比較演算子を使用して条件を指定。
    ,上記の比較値を Or 条件として判定。
    Elseすべての条件が満たされないか判定。
    Dim i As Integer
    Select Case i
        Case 0
            Debug.Print("0") ' i が 0 のとき
        Case 1 To 3
            Debug.Print("1") ' i が 1 ~ 3 のとき
        Case Is >= 4
            Debug.Print("2") ' i が 4 以上のとき
        Case 0, 2 To 3, Is > 5
            Debug.Print("3") ' i が 0 または 2 ~ 3 または 5 より大きいとき
        Case Else
            Debug.Print("4") ' それ以外のとき
    End Select

To を使った文字列の比較

  • To を使って文字列の範囲を指定するときは、大文字より小文字が大きい値として扱われる。
    大文字が何文字あっても小文字 1 文字より小さい値とされる。
    Dim s As String
    s = "ABC"
    Select Case s
        Case "AAA" To "ZZZ"
            Debug.Print("0") ' 大文字 3 文字のとき
        Case "aaa" To "zzz"
            Debug.Print("1") ' 小文字 3 文字のとき
        Case "AAA" To "zzz"
            Debug.Print("2") ' 区別しないで 3 文字のとき
        Case "A" To "zzz"
            Debug.Print("3") ' 区別しないで 1 ~ 3 文字のとき
    End Select
  • 先頭の文字から判定されるので、文字数を指定することはできず、BBB~ は BBB より大きく BBC より小さい値として扱われる動きをするため、意図しない動作になる。
    このため To を使用するときは、数値に限定した方がよい、とされる。

Select Case True

値に True を指定することで、複数の変数を条件に指定できる。

Dim i As Integer
i = 10
Dim s As String
s = "Tips"
Select Case True
    Case i >= 10
        Debug.Print("0") ' i が 10 以上のとき
    Case s = "Tips"
        Debug.Print("1") ' s が Tips のとき
    Case i > 20, s = "found"
        Debug.Print("1") ' i が 20 より大きい または s が found のとき
    Case Else
        Debug.Print("2") ' それ以外のとき
End Select

VBA関数による分岐

VBA関数による分岐はIIf 関数Choose 関数Switch 関数がある。
IIF関数は、他言語の3項演算子の代替のイメージがあるが、あくまで関数であるため、関数に渡される引数は必ず評価(実行)後に渡されるから、ショートサーキットは行われない。
そのため、3項演算子と同等の動きにはならない。これは、Choose 関数、Switch 関数も同様である。

IIf 関数

  • IIf 関数
    IIf(Expr, Truepart, Falsepart)
    Dim ret As Integer
    ret = MsgBox("景気はどうだい?", vbYesNo)
    MsgBox IIf(ret = vbYes, "ならば良し!", "さようか…")
  • 前述のとおり、あくまで関数であるため短絡評価にはならない。
    よって、エラーを回避するために処理の分岐をさせる、というような使い方は不可。
    myVal = IIf(myVal = 0, 0, 1 / myVal) ' 0以外の場合には、myValの逆数を計算するつもり ⇒  0で除算によるエラー発生

Choose 関数

  • Choose 関数
    Choose(Index, Choice-1, Choice-2, ... , Choice-n)
    Dim myVal As Integer
    myVal = Application.InputBox(Prompt:="1~5の範囲で数値を入力してください", Type:=1)
    MsgBox Choose(myVal, "ひとつ", "ふたつ", "みっつ", "よっつ", "いつつ")
  • Choose関数は、引数Indexの値に基づいて選択肢のリストから値を返す。
  • 引数Indexが1の場合はリストに含まれる最初の選択肢を返し、引数indexが2の場合は、2番目の選択肢を返す。
  • 上記の場合、選択肢のインデックスに存在しない値が与えられた場合には、Choose関数はNull値を返すため、MsgBox関数はエラーとなる。
  • 列挙型で開始を1始まりに指定したものを引数にとると、親和性がよさそう。

Switch 関数

  • Switch 関数
    Switch(Expr-1, Value-1, Expr-2, Value-2 ... , Expr-n,Value-n)
    Dim myH As Integer
    myH = Hour(Now)
    MsgBox Switch(myH <= 4, "早く寝ましょう", myH <= 6, "早起きですね", _
              myH <= 9, "おはようございます", myH <= 11, "こんにちは", _
              myH <= 13, "お昼は食べましたか", myH <= 15, "おやつにしましょう", _
              myH <= 17, "そろそろ仕事も終わりですか", myH <= 19, "お疲れ様でした", _
              myH <= 21, "今日も楽しかったですか", myH <= 23, "おやすみなさい")
  • Switch関数は、式のリストを評価し、リストの中でTrueとなる最初の式に関連付けられたバリアント型 (Variant)の値または式を返す。
  • 式とそれに対応する値はペアで指定する。
  • 式はリストの左から評価され、最初にTrueを返した式に対応する値が採用される。
  • IIF関数と同様、エラーを回避するために処理の分岐をさせる、というような使い方は不可。

ショートサーキットについて

VB.netのOrElse演算子、AndAlso演算子、Javaの||演算子、&&演算子のような短絡評価(ショートサーキット)を行う演算子はVBAにはない。

 

ただ、Select Case文のCase条件では、ショートサーキットが行われるケースがある。
Select Case文のCase条件は、カンマで区切ることで複数記入することができ、一つでも条件を満たせばCaseにマッチする仕組みになっている。
左から順に評価され、マッチした時点で残りの条件は評価されなくなる。すなわち、ショートサーキットが行われる。

 

例えば、以下のperformanceが「2」の場合、「Case 2, 3」の「3」と一致するかは評価されない。

Function Bonus(performance, salary)
    Select Case performance
        Case 1
            Bonus = salary * 0.1
        Case 2, 3
            Bonus = salary * 0.09
        Case Else
            Bonus = 0
    End Select
End Function
 

これは、おそらく以下のように解釈されているということなのだろう。

Function Bonus(performance, salary)
    Select Case performance
        Case 1
            Bonus = salary * 0.1
        Case 2
            Bonus = salary * 0.09
        Case 3                     ' 分解するとこうなる。
            Bonus = salary * 0.09  ' Case 2, 3は同じものをまとめているだけ。
        Case Else
            Bonus = 0
    End Select
End Function

TIPS

別ページの一覧を入れる。

'IT系/VBA/基本/条件分岐/' には、下位層のページがありません。

リンク集

重複を恐れないリンク集。

動画

その他メモ



*1 上限はない…はず
*2 Excelシート上では、True=1,False=0