条件分岐 (If / Select Case)

にメンテナンス済み

VBA でプログラムの処理を「条件に応じて切り替える」には、条件分岐を使用します。「もし○○なら△△する、そうでなければ□□する」という、プログラミングにおいて最も基本的かつ重要な制御構文です。

VBA には主に If 文Select Case 文の2種類の条件分岐があります。この記事では、それぞれの構文と使い方、そして場面に応じた使い分けの基準まで詳しく解説します。

条件分岐が必要となるシチュエーション

実務では、以下のような場面で条件分岐が必要になります:

  • データの分類: 売上金額に応じてランクを振り分ける
  • 入力チェック: ユーザーが入力した値が有効かどうかを判定する
  • エラー処理: 処理結果に応じてエラーメッセージを表示する
  • 条件付き書式: 値に基づいてセルの色やフォントを変更する
  • フロー制御: 状況に応じて実行する処理を切り替える

比較演算子と論理演算子

条件分岐を学ぶ前に、条件式で使用する演算子を理解しておきましょう。

比較演算子

演算子意味使用例結果(A=10の場合)
=等しいA = 10True
<>等しくないA <> 10False
>より大きいA > 5True
<より小さいA < 5False
>=以上A >= 10True
<=以下A <= 10True
Likeパターンマッチング"ABC" Like "A*"True
Isオブジェクト比較obj Is Nothing-

論理演算子

演算子意味使用例結果
Andかつ(両方 True)A > 0 And A < 100両方の条件を満たすとき True
Orまたは(どちらか)A = 0 Or A = 100いずれかの条件を満たすとき True
Not否定(反転)Not (A = 10)条件の True/False を反転
Xor排他的論理和A > 0 Xor B > 0どちらか一方のみ True のとき True
operators_example.bas
Sub OperatorsExample()
    Dim score As Long
    score = 75

    ' 比較演算子
    Debug.Print score > 60     ' => True
    Debug.Print score = 100    ' => False
    Debug.Print score <> 0     ' => True

    ' 論理演算子
    Debug.Print score >= 60 And score < 80  ' => True(60以上80未満)
    Debug.Print score = 100 Or score = 0    ' => False(100でも0でもない)
    Debug.Print Not (score < 60)            ' => True(60未満ではない)
End Sub

If 文の基本

単純な If 文

最もシンプルな条件分岐は、条件が True のときだけ処理を実行するパターンです。

if_basic.bas
Sub IfBasic()
    Dim score As Long
    score = 80

    If score >= 60 Then
        Debug.Print "合格です"
    End If
End Sub

構文:

if_syntax.bas
If 条件式 Then
    ' 条件が True のときに実行される処理
End If

1行で書く If 文

処理が1行の場合は、End If を省略して1行で書くこともできます。

if_oneline.bas
Sub IfOneLine()
    Dim score As Long
    score = 80

    If score >= 60 Then Debug.Print "合格です"
End Sub
チェック

1行形式は短い処理の場合こそ便利ですが、可読性の観点から複数行形式(End If あり)を使うのが一般的です。

If…Else 文

条件が True の場合と False の場合で、異なる処理を実行します。

if_else.bas
Sub IfElse()
    Dim score As Long
    score = 45

    If score >= 60 Then
        Debug.Print "合格です"
    Else
        Debug.Print "不合格です"
    End If
End Sub
' => 不合格です

If…ElseIf…Else 文

3つ以上の条件で分岐する場合は ElseIf を使用します。

if_elseif.bas
Sub IfElseIf()
    Dim score As Long
    score = 85

    If score >= 90 Then
        Debug.Print "評価: A"
    ElseIf score >= 80 Then
        Debug.Print "評価: B"
    ElseIf score >= 70 Then
        Debug.Print "評価: C"
    ElseIf score >= 60 Then
        Debug.Print "評価: D"
    Else
        Debug.Print "評価: F(不合格)"
    End If
End Sub
' => 評価: B
ElseIf の評価順序に注意

ElseIf上から順に評価され、最初に True になった条件のブロックだけが実行されます。それ以降の条件は評価されません。

例えば score = 95 の場合、score >= 90 が True になるため “評価: A” が表示され、score >= 80 以降の条件は評価されません。条件の順序は厳しい条件を先に書くのが基本です。

If 文の応用

複数条件の組み合わせ(And / Or)

if_multiple_conditions.bas
Sub IfMultipleConditions()
    Dim age As Long
    Dim hasLicense As Boolean
    age = 20
    hasLicense = True

    ' And: 両方の条件を満たすとき
    If age >= 18 And hasLicense = True Then
        Debug.Print "運転できます"
    End If

    ' Or: いずれかの条件を満たすとき
    Dim day As String
    day = "土曜日"
    If day = "土曜日" Or day = "日曜日" Then
        Debug.Print "週末です"
    End If

    ' 複雑な条件の組み合わせ
    Dim score As Long
    Dim attendance As Long
    score = 75
    attendance = 90

    If (score >= 60 And attendance >= 80) Or score >= 90 Then
        Debug.Print "単位取得"
    Else
        Debug.Print "単位不可"
    End If
End Sub
チェック

複雑な条件を組み合わせる場合は、括弧 () を使って意図を明確にすることをお勧めします。VBA では AndOr より優先されますが、括弧を使えば評価順序が一目で分かります。

If 文のネスト(入れ子)

If 文の中にさらに If 文を書くことをネスト(入れ子)と呼びます。

if_nested.bas
Sub IfNested()
    Dim department As String
    Dim sales As Long
    department = "営業部"
    sales = 1500000

    If department = "営業部" Then
        If sales >= 2000000 Then
            Debug.Print "目標達成!ボーナス支給"
        ElseIf sales >= 1000000 Then
            Debug.Print "もう少しで目標達成"
        Else
            Debug.Print "頑張りましょう"
        End If
    Else
        Debug.Print "営業部以外の部署です"
    End If
End Sub
' => もう少しで目標達成
ネストは浅く保つ

ネストが深くなると(3段階以上)コードの可読性が著しく低下します。ネストが深くなる場合は、以下の対策を検討しましょう:

  • 条件を反転して早期に Exit Sub する(ガード節)
  • 処理を別のプロシージャに分割する
  • Select Case 文で書き直す

ガード節パターン(早期リターン)

ネストを減らすテクニックとして、ガード節(条件を満たさない場合に早期に抜ける)パターンがあります。

guard_clause.bas
' × ネストが深い書き方
Sub ProcessData_Bad()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Sheets("データ")

    If ws.Range("A1").Value <> "" Then
        If IsNumeric(ws.Range("A1").Value) Then
            If ws.Range("A1").Value > 0 Then
                ' 本来の処理
                Debug.Print "処理を実行: " & ws.Range("A1").Value
            End If
        End If
    End If

    Set ws = Nothing
End Sub

' ○ ガード節で読みやすい書き方
Sub ProcessData_Good()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Sheets("データ")

    Dim cellValue As Variant
    cellValue = ws.Range("A1").Value

    ' 条件を満たさない場合は早期に抜ける
    If cellValue = "" Then Exit Sub
    If Not IsNumeric(cellValue) Then Exit Sub
    If cellValue <= 0 Then Exit Sub

    ' 本来の処理(ネストなし)
    Debug.Print "処理を実行: " & cellValue

    Set ws = Nothing
End Sub

空文字列・Null・Empty のチェック

セルの値を判定する際によく使うパターンです。

if_empty_check.bas
Sub CheckEmptyValues()
    Dim cellValue As Variant
    cellValue = Range("A1").Value

    ' セルが空かどうかの判定方法

    ' 方法1: 空文字列との比較
    If cellValue = "" Then
        Debug.Print "セルは空です(方法1)"
    End If

    ' 方法2: IsEmpty 関数を使用
    If IsEmpty(cellValue) Then
        Debug.Print "セルは空です(方法2)"
    End If

    ' 方法3: Len 関数で長さを確認
    If Len(cellValue) = 0 Then
        Debug.Print "セルは空です(方法3)"
    End If

    ' 数値かどうかの判定
    If IsNumeric(cellValue) Then
        Debug.Print "数値です: " & cellValue
    End If

    ' 日付かどうかの判定
    If IsDate(cellValue) Then
        Debug.Print "日付です: " & cellValue
    End If
End Sub

Select Case 文

Select Case の基本

Select Case 文は、一つの値に対して複数の候補と照合する条件分岐です。If...ElseIf の連鎖をよりすっきり書けます。

select_case_basic.bas
Sub SelectCaseBasic()
    Dim rank As String
    rank = "B"

    Select Case rank
        Case "A"
            Debug.Print "最優秀"
        Case "B"
            Debug.Print "優秀"
        Case "C"
            Debug.Print "普通"
        Case "D"
            Debug.Print "要改善"
        Case Else
            Debug.Print "評価なし"
    End Select
End Sub
' => 優秀

構文:

select_case_syntax.bas
Select Case 評価する式
    Case 値1
        ' 値1 に一致する場合の処理
    Case 値2
        ' 値2 に一致する場合の処理
    Case Else
        ' どの値にも一致しない場合の処理
End Select

複数の値を1つの Case にまとめる

カンマ区切りで複数の値を指定できます。

select_case_multiple.bas
Sub SelectCaseMultiple()
    Dim day As String
    day = "土曜日"

    Select Case day
        Case "月曜日", "火曜日", "水曜日", "木曜日", "金曜日"
            Debug.Print "平日です"
        Case "土曜日", "日曜日"
            Debug.Print "休日です"
        Case Else
            Debug.Print "不明な曜日です"
    End Select
End Sub
' => 休日です

範囲指定(To キーワード)

To キーワードを使って、値の範囲を指定できます。

select_case_to.bas
Sub SelectCaseTo()
    Dim score As Long
    score = 85

    Select Case score
        Case 90 To 100
            Debug.Print "評価: A"
        Case 80 To 89
            Debug.Print "評価: B"
        Case 70 To 79
            Debug.Print "評価: C"
        Case 60 To 69
            Debug.Print "評価: D"
        Case 0 To 59
            Debug.Print "評価: F(不合格)"
        Case Else
            Debug.Print "スコアが範囲外です"
    End Select
End Sub
' => 評価: B

比較演算子の使用(Is キーワード)

Is キーワードを使って、比較演算子による条件を指定することもできます。

select_case_is.bas
Sub SelectCaseIs()
    Dim temperature As Long
    temperature = 35

    Select Case temperature
        Case Is >= 35
            Debug.Print "猛暑日です"
        Case Is >= 30
            Debug.Print "真夏日です"
        Case Is >= 25
            Debug.Print "夏日です"
        Case Is >= 0
            Debug.Print "通常の気温です"
        Case Is < 0
            Debug.Print "氷点下です"
    End Select
End Sub
' => 猛暑日です

複合条件の組み合わせ

ToIs、複数値を1つの Case で組み合わせることもできます。

select_case_combined.bas
Sub SelectCaseCombined()
    Dim month As Long
    month = 8

    Select Case month
        Case 3, 4, 5
            Debug.Print "春"
        Case 6 To 8
            Debug.Print "夏"
        Case 9, 10, 11
            Debug.Print "秋"
        Case 12, 1, 2
            Debug.Print "冬"
        Case Else
            Debug.Print "不正な月です"
    End Select
End Sub
' => 夏

Select Case で文字列を扱う

select_case_string.bas
Sub SelectCaseString()
    Dim extension As String
    extension = LCase(Right("report.xlsx", Len("report.xlsx") - InStrRev("report.xlsx", ".")))

    Select Case extension
        Case "xlsx", "xls", "xlsm"
            Debug.Print "Excel ファイルです"
        Case "docx", "doc"
            Debug.Print "Word ファイルです"
        Case "pptx", "ppt"
            Debug.Print "PowerPoint ファイルです"
        Case "pdf"
            Debug.Print "PDF ファイルです"
        Case "csv", "txt"
            Debug.Print "テキストファイルです"
        Case Else
            Debug.Print "その他のファイル形式です"
    End Select
End Sub
' => Excel ファイルです
チェック

Select Case で文字列を比較する場合、VBA は既定で大文字・小文字を区別します。事前に LCaseUCase で統一しておくと安全です。モジュールの先頭に Option Compare Text を記述すると、大文字・小文字を区別しない比較になります。

If 文と Select Case の使い分け

比較表

特徴If 文Select Case
判定対象複数の変数・式を自由に判定1つの式の値に対して判定
複雑な条件○ And/Or で柔軟に組み合わせ△ 単一の値に対する比較が中心
値の列挙ElseIf の繰り返しが必要○ カンマ区切りで簡潔に書ける
範囲指定>= <= で指定可能To キーワードで簡潔に指定
可読性(分岐が多い場合)△ 長くなりがち○ 構造化されて読みやすい
パフォーマンスほぼ同等ほぼ同等

使い分けの基準

If 文が適しているケース:

  • 複数の異なる変数を条件に含む場合
  • AndOr で複雑な条件を組み合わせる場合
  • True/False の2択の場合
  • オブジェクトの状態(Is Nothing など)を判定する場合

Select Case が適しているケース:

  • 1つの値に対して3つ以上の分岐がある場合
  • 値の列挙で判定する場合(曜日、月、ランク等)
  • 数値の範囲で分岐する場合
  • コードの可読性を重視する場合
when_to_use_if.bas
' ○ If 文が適しているケース:複数の変数を条件に含む
Sub WhenToUseIf()
    Dim age As Long
    Dim income As Currency
    Dim isStudent As Boolean
    age = 25
    income = 3000000
    isStudent = False

    If age < 18 Then
        Debug.Print "未成年プラン"
    ElseIf isStudent Then
        Debug.Print "学生プラン"
    ElseIf income >= 5000000 Then
        Debug.Print "プレミアムプラン"
    Else
        Debug.Print "標準プラン"
    End If
End Sub
when_to_use_select.bas
' ○ Select Case が適しているケース:1つの値に対する複数分岐
Sub WhenToUseSelect()
    Dim statusCode As Long
    statusCode = 404

    Select Case statusCode
        Case 200
            Debug.Print "成功"
        Case 301
            Debug.Print "リダイレクト"
        Case 400
            Debug.Print "リクエストエラー"
        Case 401
            Debug.Print "認証エラー"
        Case 403
            Debug.Print "アクセス禁止"
        Case 404
            Debug.Print "ページが見つかりません"
        Case 500 To 599
            Debug.Print "サーバーエラー"
        Case Else
            Debug.Print "不明なステータスコード: " & statusCode
    End Select
End Sub

実践的な活用例

例1:セルの値に応じた色分け

practical_color_formatting.bas
Option Explicit

Sub ColorByScore()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Sheets("成績表")

    Dim lastRow As Long
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

    Dim i As Long
    For i = 2 To lastRow  ' 2行目から(1行目はヘッダー)
        Dim score As Variant
        score = ws.Cells(i, 2).Value  ' B列がスコア

        If Not IsNumeric(score) Then
            ' 数値でない場合はスキップ
            ws.Cells(i, 2).Interior.Color = RGB(200, 200, 200)  ' グレー
        Else
            Select Case CLng(score)
                Case 90 To 100
                    ws.Cells(i, 2).Interior.Color = RGB(144, 238, 144)  ' 緑
                Case 70 To 89
                    ws.Cells(i, 2).Interior.Color = RGB(173, 216, 230)  ' 水色
                Case 60 To 69
                    ws.Cells(i, 2).Interior.Color = RGB(255, 255, 153)  ' 黄色
                Case 0 To 59
                    ws.Cells(i, 2).Interior.Color = RGB(255, 182, 193)  ' ピンク
            End Select
        End If
    Next i

    Set ws = Nothing
End Sub

例2:入力値のバリデーション

practical_validation.bas
Option Explicit

Sub ValidateInput()
    Dim userName As String
    Dim userAge As Variant
    Dim userEmail As String

    userName = InputBox("名前を入力してください")
    userAge = InputBox("年齢を入力してください")
    userEmail = InputBox("メールアドレスを入力してください")

    ' 名前のチェック
    If userName = "" Then
        MsgBox "名前が入力されていません", vbExclamation
        Exit Sub
    End If

    ' 年齢のチェック
    If Not IsNumeric(userAge) Then
        MsgBox "年齢は数値で入力してください", vbExclamation
        Exit Sub
    End If

    If CLng(userAge) < 0 Or CLng(userAge) > 150 Then
        MsgBox "正しい年齢を入力してください", vbExclamation
        Exit Sub
    End If

    ' メールアドレスの簡易チェック
    If InStr(userEmail, "@") = 0 Or InStr(userEmail, ".") = 0 Then
        MsgBox "正しいメールアドレスを入力してください", vbExclamation
        Exit Sub
    End If

    ' すべてのチェックを通過
    MsgBox "登録完了!" & vbCrLf & _
           "名前: " & userName & vbCrLf & _
           "年齢: " & userAge & vbCrLf & _
           "メール: " & userEmail, vbInformation
End Sub

例3:月末処理の判定

practical_month_end.bas
Option Explicit

Sub MonthEndProcess()
    Dim targetDate As Date
    targetDate = Date  ' 今日の日付

    Dim currentMonth As Long
    currentMonth = Month(targetDate)

    ' 四半期末かどうかの判定
    Dim isQuarterEnd As Boolean
    Select Case currentMonth
        Case 3, 6, 9, 12
            isQuarterEnd = True
        Case Else
            isQuarterEnd = False
    End Select

    ' 処理の分岐
    If isQuarterEnd Then
        Debug.Print "四半期末処理を実行します"
        ' 四半期レポートの生成など

        If currentMonth = 3 Then
            Debug.Print "→ 年度末処理も実行します"
            ' 年度末固有の処理
        End If
    Else
        Debug.Print "通常の月末処理を実行します"
    End If
End Sub
日付関数
VBAで日付を操作する際に必須となる関数群について、基本から実践まで詳しく解説します。DateAdd、DateDiff、DateSerial、Year、Month、Day、Weekday等の関数を使いこなして、効率的な日付処理を実現しましょ

注意点とよくある間違い

1. 等価比較の演算子は === ではない)

他のプログラミング言語から来た方が間違いやすいポイントです。VBA では等価比較に = を使います。

common_mistake_equals.bas
' ○ 正しい
If score = 100 Then Debug.Print "満点"

' × 間違い(VBA ではエラーになる)
' If score == 100 Then Debug.Print "満点"

2. 文字列比較と大文字・小文字

VBA の文字列比較は既定で大文字・小文字を区別します。

string_comparison.bas
Sub StringComparison()
    Dim answer As String
    answer = "Yes"

    ' 大文字・小文字を区別するため、以下は False
    If answer = "yes" Then
        Debug.Print "一致"  ' 実行されない
    End If

    ' 対策1: LCase で統一してから比較
    If LCase(answer) = "yes" Then
        Debug.Print "一致(LCase)"  ' => 一致(LCase)
    End If

    ' 対策2: UCase で統一してから比較
    If UCase(answer) = "YES" Then
        Debug.Print "一致(UCase)"  ' => 一致(UCase)
    End If
End Sub
チェック

モジュールの先頭に Option Compare Text を記述すると、そのモジュール内の文字列比較がすべて大文字・小文字を区別しなくなります。

3. Nothing の比較には Is を使う

オブジェクト変数が Nothing かどうかを判定する場合は、= ではなく Is を使用します。

nothing_comparison.bas
Sub NothingComparison()
    Dim ws As Worksheet
    Set ws = Nothing

    ' ○ 正しい
    If ws Is Nothing Then
        Debug.Print "シートが設定されていません"
    End If

    ' × 間違い(実行時エラーになる)
    ' If ws = Nothing Then
End Sub

4. Select Case での落とし穴

select_case_pitfall.bas
Sub SelectCasePitfall()
    Dim value As Variant
    value = "100"  ' 文字列の "100"

    ' 文字列と数値は別物!
    Select Case value
        Case 100
            Debug.Print "数値の100"      ' マッチしない場合がある
        Case "100"
            Debug.Print "文字列の100"    ' こちらにマッチ
    End Select

    ' 型を統一してから比較するのが安全
    If IsNumeric(value) Then
        Select Case CLng(value)
            Case 100
                Debug.Print "確実に数値の100"
        End Select
    End If
End Sub

練習問題

次のコードの実行結果として正しいものはどれですか?
Dim x As Long
x = 15

If x > 20 Then
    Debug.Print "A"
ElseIf x > 10 Then
    Debug.Print "B"
ElseIf x > 5 Then
    Debug.Print "C"
Else
    Debug.Print "D"
End If
正解は「B」です。x = 15 の場合、x > 20 は False、x > 10 は True です。ElseIf は最初に True になった条件のブロックだけを実行するため、“B” のみが出力されます。x > 5 も True ですが、すでに x > 10 で分岐しているため評価されません。
次の Select Case 文で、month = 7 のときの出力はどれですか?
Select Case month
    Case 3, 4, 5
        Debug.Print "春"
    Case 6 To 8
        Debug.Print "夏"
    Case 9 To 11
        Debug.Print "秋"
    Case 12, 1, 2
        Debug.Print "冬"
End Select
正解は「夏」です。month = 7Case 6 To 8(6以上8以下)に該当するため、“夏” が出力されます。To キーワードを使うと、範囲の両端を含む指定ができます。
以下の場面で、If 文より Select Case 文が適しているのはどれですか?
正解は「都道府県コード(1〜47の数値)に応じて地方名を表示する」です。Select Case は一つの値に対して多くの分岐がある場合に適しています。都道府県コードは Case 1 To 7 で北海道・東北、Case 8 To 14 で関東、のように To キーワードと組み合わせて簡潔に書けます。他の選択肢は複数の変数や Is Nothing を使うため、If 文が適しています。

まとめ

  • If 文は VBA で最も基本的な条件分岐。If...Then...End If の構文を基本にする
  • ElseIf で3つ以上の分岐が可能。条件は上から順に評価される
  • Select Case は1つの値に対して複数の分岐がある場合に使用し、To(範囲)、Is(比較)、カンマ区切り(複数値)を組み合わせて柔軟に条件を指定できる
  • 比較演算子=<>><)と論理演算子AndOrNot)を使いこなすことが条件分岐の鍵
  • ネストが深くなる場合はガード節パターンExit Sub を使い、可読性を保つ
  • 文字列比較では大文字・小文字の区別に注意する(LCase/UCase で統一)
  • オブジェクトの Nothing 判定には = ではなく Is を使用する
変数宣言とデータ型
VBAの変数宣言(Dim)とデータ型(Integer, Long, String, Boolean等)の使い方を初心者向けに徹底解説。Option Explicitによる宣言の強制、変数のスコープ(Public/Private/Dim)、型
ループ処理 (For / Do)
VBAのループ処理(For Next、For Each、Do While、Do Until)の書き方を初心者向けに徹底解説。繰り返し処理の基本構文から、Exit文によるループ脱出、ネスト、パフォーマンス最適化まで、実践的なコード例とともに紹
Sub と Function の違い
VBAのSubプロシージャとFunctionプロシージャの違いを初心者向けに徹底解説。戻り値の有無、引数の渡し方(ByRef・ByVal)、スコープ(Public・Private)、呼び出し方法まで、実践的なコード例とともに紹介します。
VBAにおけるTry-Catch-Finallyの実装
一般的にエラー処理は、各関数では最低限行い、後は呼び出し元にThrowするのが一般的かと思いますが、VBAではそれを簡単には実装できません。エラーハンドラを作ってしまうとエラーを握りつぶしてしまい、そこから再度Err.Raiseしようとする
Forループのスキップ(Continue)
VBAのForループ内で次のループへスキップする方法を紹介します。GoToコマンドを使うことで、Forループ内で次のループへスキップすることができます。
#VBA #条件分岐 #If文 #Select Case #制御構文 #初心者向け