この記事でわかること
- Select Caseの基本構文で、If…ElseIfの連続をスッキリ書き直せる
- Case Is(比較演算)・Case To(範囲指定)・Case True(複合条件)の3パターンを使い分けられる
- セルの値に応じて処理を振り分ける実務コードがコピペで動く
対象: Excel 2016以降 / Microsoft 365、Windows 10/11
どんな場面で使う?
- 点数やスコアのランク分け — テストの点数、顧客満足度、品質検査の結果などを自動でS/A/B/C/Dに振り分けたい
- 部門コード・商品コードによる処理分岐 — コードの値に応じて処理区分や担当部署を自動で判定したい
- 月や曜日による四半期・平日/休日の判定 — 日付データから四半期を出したり、平日か休日かを自動で分類したい
- ステータスコードに応じたメッセージ表示 — 「完了」「処理中」「エラー」などの状態に応じて異なるアクションを実行したい
- If…ElseIfが5段以上になったコードの整理 — 既存のIf文の連続を、読みやすく・追加しやすいSelect Caseに書き直したい
—
完成イメージ(Before / After)
Before(If…ElseIfの連続):
If score >= 90 Then
rank = "S"
ElseIf score >= 80 Then
rank = "A"
ElseIf score >= 70 Then
rank = "B"
ElseIf score >= 60 Then
rank = "C"
Else
rank = "D"
End If
After(Select Caseで書き直し):
Select Case score
Case Is >= 90: rank = "S"
Case Is >= 80: rank = "A"
Case Is >= 70: rank = "B"
Case Is >= 60: rank = "C"
Case Else: rank = "D"
End Select
判定対象(score)を1回書くだけ。条件を追加するときもCase行を1行足すだけで済む。
—
自分も以前、If…ElseIfを10個以上並べて条件分岐を書いていた。条件を追加するたびに「ElseIfをどこに挟むか」を探すのが地味にストレスだった。Select Caseに書き換えてからは、条件の追加も削除もCase行を1行足す・消すだけで済むようになった。コードの見通しが格段に良くなって、もっと早く知りたかったと思った。If文の連続で読みにくいコードに悩んでいる人が、この記事でSelect Caseをサクッと使えるようになればうれしい。
Select Caseを使えば、1つの値に対する複数条件の分岐がスッキリ書ける。
なお、Select Case内でエラーが起きた場合の対処は エラー処理(On Error)で止まらないマクロを作る方法 を参照。
—
実行前の準備
バックアップを取る
実務版コードはセルの値を書き換える(C列を上書き)。必ずファイルのコピーを別フォルダに保存してから実行する。
Excelをマクロ有効ブック(.xlsm)で保存する
拡張子が .xlsx のままだとマクロが保存できない。
- 「ファイル」→「名前を付けて保存」
- ファイルの種類を「Excelマクロ有効ブック (*.xlsm)」に変更
- 保存
—
手順(コピペ → 実行まで約5分)
VBE(コードを書く画面)を開く
- Excelで
Alt + F11を押す
標準モジュールを挿入する
- VBEのメニュー →「挿入」→「標準モジュール」
コードを貼り付けて実行する
- コードウィンドウに、下のコードをそのままコピペする
Alt + F8→ マクロ名を選んで「実行」
ボタンに割り当てれば毎回Alt+F8を押さなくて済む。方法は マクロをボタン1つで実行する方法 を参照。
—
コード(基本版)– 点数→評価のランク分け(Select Case Is)
セルA1の点数を読み取り、評価ランクをMsgBoxで表示する。まずはこれで動きを確認する。
'============================================================
' ■ 点数→評価ランクの判定(基本版)
' → セルA1の値を読み取り、S/A/B/C/D にランク分け
'============================================================
Sub JudgeRank()
Dim score As Long
score = CLng(Range("A1").Value) '← セルA1の値を数値に変換
Dim rank As String
Select Case score
Case Is >= 90
rank = "S"
Case Is >= 80
rank = "A"
Case Is >= 70
rank = "B"
Case Is >= 60
rank = "C"
Case Else
rank = "D"
End Select
MsgBox "点数: " & score & vbCrLf & "評価: " & rank, vbInformation
End Sub
書き換えポイント
| 変数 | 説明 | 初期値 |
|---|---|---|
Range("A1") |
点数が入っているセル | A1 |
| 各Caseの閾値 | ランクの境界値 | 90 / 80 / 70 / 60 |
rank の値 |
各ランクの表示文字 | "S" / "A" / "B" / "C" / "D" |
ポイント: Select Caseは上から順に評価し、最初にマッチしたCaseだけ実行する。Case Is >= 90 を先に書くことで、90以上はここで確定し、次の Case Is >= 80 には流れない。これはC言語のswitch文とは違い、break を書かなくても次のCaseに「落ちない」ということだ。この仕組みのおかげで、条件の順序さえ正しければバグが起きにくい。
なぜIf…ElseIfではなくSelect Caseで書くのかというと、判定対象が1つの変数(この例では score)に集中しているからだ。If文だと毎行 score >= 〇〇 と書く必要があるが、Select Caseなら score は先頭で1回書くだけで済む。条件を追加・削除するときもCase行を1行足す・消すだけなので、メンテナンス性が圧倒的に高い。
MsgBoxの使い方の詳細は MsgBoxでユーザーに確認ダイアログを出す方法 を参照。
—
コード(応用版)– 文字列パターンマッチ+範囲指定
パターン1: 範囲指定(Case 値1 To 値2)
月を入力して四半期を判定する例。
'============================================================
' ■ 月→四半期の判定(応用版: Case To)
' → セルA1の月(1〜12)を読み取り、四半期を表示
'============================================================
Sub JudgeQuarter()
Dim mon As Long
mon = CLng(Range("A1").Value)
Dim quarter As String
Select Case mon
Case 4 To 6
quarter = "Q1(4〜6月)"
Case 7 To 9
quarter = "Q2(7〜9月)"
Case 10 To 12
quarter = "Q3(10〜12月)"
Case 1 To 3
quarter = "Q4(1〜3月)"
Case Else
quarter = "該当なし(1〜12の値を入力してください)"
End Select
MsgBox mon & "月 → " & quarter, vbInformation
End Sub
パターン2: カンマ区切りで複数値(Case 値1, 値2, 値3)
曜日コード(1〜7)で平日・土日を判定する例。
'============================================================
' ■ 曜日コード→平日/土日の判定(応用版: カンマ区切り)
' → Weekday関数の戻り値(1=日, 2=月, ..., 7=土)で判定
'============================================================
Sub JudgeDayType()
Dim wDay As Long
wDay = Weekday(Date) '← 今日の曜日コード
Dim dayType As String
Select Case wDay
Case 2, 3, 4, 5, 6 '← 月〜金
dayType = "平日"
Case 1, 7 '← 日・土
dayType = "休日"
Case Else
dayType = "判定不能"
End Select
MsgBox "今日(" & Format(Date, "yyyy/mm/dd") & ")は " & dayType & " です。", vbInformation
End Sub
日付の書式設定は Format関数で表示形式を整える方法 も参考になる。
パターン3: 複合条件(Select Case True)
1つの変数だけでなく、複数の条件を組み合わせたい場合に使う。セルA1に点数、B1に出席率(0.85 = 85%)が入っている前提。セルが空の場合は基本版で動作確認してから試すとよい。
'============================================================
' ■ 複合条件の判定(応用版: Select Case True)
' → 点数と出席率の両方で総合評価を判定
'============================================================
Sub JudgeComplex()
Dim score As Long
score = CLng(Range("A1").Value) '← 点数
Dim attendance As Double
attendance = CDbl(Range("B1").Value) '← 出席率(例: 0.85 = 85%)
Dim result As String
Select Case True
Case score >= 90 And attendance >= 0.9
result = "優秀"
Case score >= 70 And attendance >= 0.7
result = "合格"
Case score >= 50
result = "条件付き合格"
Case Else
result = "不合格"
End Select
MsgBox "点数: " & score & vbCrLf & _
"出席率: " & Format(attendance, "0%") & vbCrLf & _
"判定: " & result, vbInformation
End Sub
ポイント: Select Case True は「Trueに一致するCaseを探す」仕組み。各Case節に条件式を書けるので、複数の変数を組み合わせた分岐が可能。ただし、単純な1変数の分岐なら通常のSelect Caseの方が読みやすい。
なぜ Select Case True という書き方が必要かというと、通常のSelect Caseは「1つの値」に対する分岐しかできないからだ。score と attendance のように2つの変数を同時に判定したい場合、通常のSelect Caseでは書けない。Select Case True なら各Case節にAnd条件やOr条件を自由に書けるので、If…ElseIfの代替としても使える。ただし、条件式がすべてFalseの場合はCase Elseに入る(Case Elseがなければ何も実行されない)ので、必ずCase Elseを書いておくのが安全だ。
型変換(CLng, CDbl)の詳細は 型変換関数で「型が一致しません」エラーを防ぐ方法 を参照。
—
コード(実務版)– セルの値に応じて処理を振り分け(部門コード→処理分岐)
A列に部門コード、B列に売上が入った一覧表を処理する例。部門コードに応じてC列に「処理区分」を書き込む。
部門コードで処理を振り分けるマクロをSelect Caseで書くようにしてからは、部門が増えてもCase行を1行追加するだけで対応できている。修正依頼にもすぐ対応できるようになった。
コード解説:
この実務版コードは、A列の部門コードを1行ずつ読み取り、Select Caseで処理区分を判定し、C列に結果を書き込む構成だ。Case "A01", "A02", "A03" のようにカンマ区切りで複数コードをまとめられるのがSelect Caseの強みで、If文で書くと If code = "A01" Or code = "A02" Or code = "A03" Then と冗長になる。Case "C01" To "C99" は文字列の範囲指定で、C01からC99までの辞書順の範囲にマッチする。売上額による追加判定(If sales >= 1000000)はSelect Caseの後にIf文で処理しているが、これは「コード判定」と「金額判定」が別軸の条件だからだ。1軸はSelect Case、別軸はIf文という使い分けが実務では多い。
※ C列の既存データは上書きされます。実行前にバックアップを取ってください。
'============================================================
' ■ 部門コード→処理区分の振り分け(実務版)
' → A列: 部門コード、B列: 売上、C列: 処理区分を書き込み
' → 対象シート: アクティブシート
'============================================================
Sub ClassifyByDepartment()
'--- ★書き換えポイント ---
Dim startRow As Long
startRow = 2 '← データの開始行(1行目はヘッダー)
Dim codeCol As Long
codeCol = 1 '← 部門コードの列(A列=1)
Dim salesCol As Long
salesCol = 2 '← 売上の列(B列=2)
Dim resultCol As Long
resultCol = 3 '← 処理区分を書き込む列(C列=3)
'--- ★ここまで ---
Dim ws As Worksheet
Set ws = ActiveSheet
'--- 最終行を取得
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, codeCol).End(xlUp).Row
If lastRow < startRow Then
MsgBox "データがありません。", vbExclamation
Exit Sub
End If
'--- ループで使う変数を事前宣言
Dim r As Long
Dim processCount As Long
Dim code As String
Dim sales As Double
Dim category As String
processCount = 0
For r = startRow To lastRow
code = Trim(CStr(ws.Cells(r, codeCol).Value))
'--- 売上を数値に変換(変換できない場合は0にする)
On Error Resume Next
sales = CDbl(ws.Cells(r, salesCol).Value)
If Err.Number <> 0 Then
sales = 0
Err.Clear
End If
On Error GoTo 0
Select Case code
Case "A01", "A02", "A03"
category = "本社管轄"
Case "B01", "B02"
category = "支社管轄"
Case "C01" To "C99"
category = "工場管轄"
Case "X00"
category = "対象外"
Case ""
category = "(コード未入力)"
Case Else
category = "不明コード: " & code
End Select
'--- 売上が一定額以上なら追加情報を付加
If sales >= 1000000 Then
category = category & "【要確認】"
End If
ws.Cells(r, resultCol).Value = category
processCount = processCount + 1
Next r
MsgBox processCount & " 行の処理区分を書き込みました。", vbInformation
End Sub
書き換えポイント
| 変数 | 説明 | 初期値 |
|---|---|---|
startRow |
データの開始行 | 2(1行目はヘッダー) |
codeCol |
部門コードの列 | 1(A列) |
salesCol |
売上の列 | 2(B列) |
resultCol |
処理区分の書き込み列 | 3(C列) |
| Case節の値 | 部門コードと処理区分の対応 | 自社の部門コードに合わせて変更 |
シート構成の例
| A列(部門コード) | B列(売上) | C列(処理区分)← マクロで書き込み |
|---|---|---|
| A01 | 500000 | 本社管轄 |
| B01 | 1200000 | 支社管轄【要確認】 |
| C15 | 300000 | 工場管轄 |
| X00 | 0 | 対象外 |
| Z99 | 100000 | 不明コード: Z99 |
—
よくある落とし穴5選
1. Case節の範囲が重複して、後のCaseが実行されない
自分もこれでハマった。Case 1 To 100 を先に書いて、その下の Case 1 To 50 が永遠に通らなかった。原因に気づくまで30分は溶かした。
原因: Select Caseは上から順に評価し、最初にマッチしたCaseだけ実行する。範囲が広いCaseを先に書くと、狭い範囲のCaseが評価されない。
対策: 範囲が狭い(条件が厳しい)Caseを先に書く。
' NG: 80〜100がCase 1 To 100に吸い込まれる
Select Case score
Case 1 To 100: rank = "普通"
Case 80 To 100: rank = "優秀" '← ここに来ない
End Select
' OK: 範囲が狭いCaseを先に
Select Case score
Case 80 To 100: rank = "優秀"
Case 1 To 79: rank = "普通"
End Select
2. セルの値が文字列型の数字で、数値比較が意図通りにならない
原因: セルに '100 のように先頭にアポストロフィが付いた値や、CSV取り込み時に文字列として格納された数字は、文字列型になっている。文字列同士の比較は辞書順になるため、"9" > "80" が True になる。
対策: CLng() や CDbl() で数値に変換してからSelect Caseに渡す。
3. Case Elseを書かず、想定外のデータがスルーされる
原因: Case Elseを省略すると、どのCaseにも該当しないデータは何も処理されずに通過する。バグの原因になりやすい。
対策: 必ずCase Elseを書く。想定外のデータが来たことを検知できるようにする。
4. 文字列の大文字・小文字が区別されてしまう
原因: VBAの文字列比較は既定で大文字小文字を区別する(バイナリ比較)。Case "abc" は "ABC" にマッチしない。
対策: モジュールの先頭(Option Explicit の下)に Option Compare Text を追加するか、UCase() や LCase() で統一してからSelect Caseに渡す。
Option Explicit
Option Compare Text '← Option Explicitの下に追加
' これで Case "abc" が "ABC" にもマッチするようになる
5. Select Case Trueで条件式を間違えて全Caseがスルーされる
原因: 各Case節の条件式がすべてFalseの場合、Case Elseに入る(Case Elseがなければ何も実行されない)。条件式のロジックミスに気づきにくい。
対策: Case Elseで「想定外」を検知する。Debug.Print で判定対象の値を出力して確認する。
VBAのSelect Caseが動かない・分岐しないときの対処法
「Select Caseを書いたのに、どのCaseにも入らず何も実行されない」という場合、原因はSelect Caseに渡している値の型と、Case節で比較している値の型が一致していないことが多い。たとえばセルの値が文字列型の "100" なのに Case Is >= 90 で数値比較しようとすると、文字列と数値の比較になり意図通りにマッチしない。対策として、Select Caseに渡す前に CLng() や CDbl() で数値に変換するか、CStr() で文字列に統一する。Case Elseに Debug.Print を入れておくと、想定外の値が来たときにイミディエイトウィンドウで原因を追えるようになる。
VBAのCase条件が一致しないときの対処法
「Case “abc” と書いているのに、セルの値が “ABC” のときマッチしない」という場合、原因はVBAの文字列比較がデフォルトで大文字・小文字を区別する(バイナリ比較)ことだ。対策として、モジュールの先頭(Option Explicit の下)に Option Compare Text を追加すれば、大文字・小文字を区別しない比較になる。もう1つの方法として、Select Caseに渡す前に UCase() や LCase() で統一する手もある。自分はチーム共有のマクロでは Option Compare Text を標準にしていて、入力のブレによるバグを防いでいる。
—
FAQ
Q1: Select CaseとIf…ElseIfはどう使い分ける?
| 使い分け | Select Case | If…ElseIf |
|---|---|---|
| 1つの値に対する複数分岐 | 向いている | 冗長になりがち |
| 複数の変数を組み合わせた条件 | Select Case Trueで可能だが可読性が下がる | 向いている |
| 2〜3個の分岐 | どちらでもOK | If文の方がシンプル |
| 5個以上の分岐 | Select Caseの方が見やすい | ElseIfの連続が長くなる |
結論: 1つの値に対して分岐が5個以上ならSelect Case。2〜3個ならIf文で十分。複数変数の複雑な条件はIf文が向いている。
Q2: Case節にカンマで複数の値を書ける?
書ける。Case 1, 3, 5, 7 のようにカンマ区切りで指定可能。文字列でも Case "A01", "A02", "A03" のように書ける。
Q3: Case IsとCase Toは同じCase節で併用できる?
できる。カンマで区切って併用可能。
Select Case score
Case 1 To 5, Is >= 95 '← 1〜5 または 95以上が対象
MsgBox "特別対応"
Case Else
MsgBox "通常対応" '← 6〜94はここに入る
End Select
Q4: Select Case Trueとは何?
Select Case True は各CaseにBoolean式(条件式)を書く方法。Trueに一致するCaseが実行される。
Select Case True
Case score >= 90 And attendance >= 0.9
result = "優秀"
Case score >= 70
result = "合格"
End Select
複数の変数を組み合わせた分岐に使えるが、単純な分岐には通常のSelect Caseの方が読みやすい。
Q5: Select Caseの中でExit SubやGoToは使える?
使える。Case節の中でExit SubやGoToを書けばその場で処理を抜けられる。ただし、GoToの多用はコードの可読性を下げるので推奨しない。
—
まとめ
- Select Case: 1つの値に対する複数条件の分岐をスッキリ書ける
- Case Is: 比較演算子を使う分岐(
Case Is >= 90) - Case To: 範囲指定の分岐(
Case 1 To 10) - Case カンマ区切り: 複数値の一括指定(
Case 1, 3, 5) - Case Else: 必ず書く。想定外のデータを検知する
- Select Case True: 複合条件の分岐に使えるが、単純なら通常のSelect Caseで
Select Caseは「1つの値に対する複数の条件分岐」をスッキリ書くための構文だ。自分の実感として、If…ElseIfが5行を超えたらSelect Caseへの書き換えを検討する価値がある。コードの見通しが良くなるだけでなく、条件の追加・削除・並び替えが1行単位でできるようになるため、運用フェーズでのメンテナンスが格段にラクになる。まずは基本版の点数ランク分けで動きを確認し、慣れたら実務版の部門コード振り分けに進むのがおすすめだ。
関連記事
- エラー処理(On Error)で止まらないマクロを作る方法 — Select Case内のエラー対策
- MsgBoxでユーザーに確認ダイアログを出す方法 — 分岐結果の表示
- 型変換関数で「型が一致しません」エラーを防ぐ方法 — セルの値の型変換
- セルの値に応じて行を自動色分け — 条件分岐でセルの色を変える応用
- マクロをボタン1つで実行する方法 — 分岐マクロをボタンに割り当て
—
次にやりたくなること
- セルの値に応じて行を自動色分け: Select Caseで判定した結果に応じてセルに色を付けたい場合
- 複数条件でデータを抽出して別シートにまとめる: 条件分岐で振り分けたデータを別シートに抽出したい場合
- Select Caseの判定結果をシート関数として使いたい → ユーザー定義関数(UDF)で独自のワークシート関数を作る方法 で、Select Caseを使った判定ロジックをセルから呼べる関数にできる
- 条件分岐のエラー処理をもっと堅牢にしたい → エラー処理の応用テクニック で、予期しないデータが来たときの対処法を学べる
- 分岐結果を別シートに転記したい → セルの値を別シートに転記する方法 で、判定後のデータを集約する方法を解説している


コメント