【VBA】Enumで定数グループを定義してコードを読みやすくする方法(コピペOK)

VBA
スポンサーリンク

記事ID: 095
タイトル: Enumで定数グループを定義してコードを読みやすくする方法
カテゴリ: シート操作
一次キーワード: VBA Enum 定数 一覧
想定読者: VBAで条件分岐を使い始めた初心者〜初級者。コード中にマジックナンバーが増えて管理しづらくなっている人。
検索意図: VBAのEnum(列挙型)の書き方と使い方を知りたい。定数をグループ化してコードの可読性を上げたい。
読者の悩み(1文): コードの中に意味不明な数値(1, 2, 3...)が散らばっていて、後から見ると何の値か分からなくなる。
読了後にできること(1文): Enumで定数グループを定義し、マジックナンバーを意味のある名前に置き換えて、読みやすく保守しやすいコードが書ける。
前提条件:
  - Excel版: Excel 2016以降 / Microsoft 365
  - OS: Windows 10/11
  - 保存形式: .xlsm(マクロ有効ブック)
  - 貼り付け場所: 標準モジュール
  - 実行方法: Alt+F8 → マクロ実行 / ボタン割り当て
更新日: 2026-03-18

スポンサーリンク
  1. この記事でわかること
  2. どんな場面で使う?
  3. 完成イメージ(Before / After)
  4. 実行前の準備
    1. バックアップを取る
    2. Excelをマクロ有効ブック(.xlsm)で保存する
  5. 手順(コピペ → 実行まで約5分)
    1. VBE(コードを書く画面)を開く
    2. 標準モジュールを挿入する
    3. コードを貼り付けて実行する
  6. コード(基本版)– Enumでステータスコードを定義して分岐する
    1. 書き換えポイント
  7. Enumの基本ルール(これだけ押さえればOK)
    1. 構文
    2. ルール一覧
    3. 自動採番の例
  8. コード(実務版)– Enum × Select Case × RGB色でセル処理
    1. 書き換えポイント
    2. シート構成の例
  9. よくある落とし穴5選
    1. 1. Enumメンバー名に予約語を使ってコンパイルエラー
    2. 2. 値を省略して0始まりになり、業務コードとずれる
    3. 3. 別のEnumで同名メンバーを作って名前衝突
    4. 4. シートモジュールにEnumを書いて他から参照できない
    5. 5. Enum型変数に範囲外の値を入れてもエラーにならない
    6. VBAのEnumでコンパイルエラーが出るときの対処法
    7. VBAのEnum値がシート間で共有できないときの対処法
  10. FAQ
    1. Q1: EnumとConstはどう使い分ける?
    2. Q2: Enumの値に文字列は使える?
    3. Q3: VBAの組み込み定数(vbOK, vbRedなど)もEnum?
    4. Q4: Enumのメンバーを後から追加しても大丈夫?
    5. Q5: Enumの全メンバーをループで取得できる?
  11. まとめ
    1. 関連記事
  12. 次にやりたくなること

この記事でわかること

  • VBAのEnum(列挙型)で、関連する定数をグループにまとめて定義できる
  • If status = 1 のようなマジックナンバーを If status = stActive に置き換えて読みやすくできる
  • Enum × Select Caseで実務の分岐処理をスッキリ書ける

対象: VBAで条件分岐を使い始めた人。コードの数値が何を意味するか分からなくなった経験がある人。

所要時間: コピペ → 実行まで約5分

どんな場面で使う?

  • ステータスコード(承認済み・差し戻し・未処理など)をマジックナンバーでなく名前で管理したい
  • Select Caseの分岐条件を数値でなく意味のある定数名で書いて可読性を上げたい
  • 複数のConst定数をグループ化してまとめて管理したい
  • セルの色分け処理で色定数をEnumにまとめて管理したい—

完成イメージ(Before / After)

Before(マジックナンバーだらけのコード):


If status = 1 Then
    MsgBox "有効"
ElseIf status = 2 Then
    MsgBox "休止"
ElseIf status = 3 Then
    MsgBox "終了"
End If

1, 2, 3 が何を意味するのか、コードだけでは分からない。

After(Enumで名前を付けたコード):


If status = stActive Then
    MsgBox "有効"
ElseIf status = stSuspended Then
    MsgBox "休止"
ElseIf status = stClosed Then
    MsgBox "終了"
End If

stActive, stSuspended, stClosed で意味が一目でわかる。

自分も以前、Select CaseやIfの分岐で Case 1, Case 2 のように数値を直接書いていた。3か月後に見返したとき「この1って何だっけ?」と自分のコードなのに意味が分からなくなった。正直しんどかった。Enumで定数に名前を付けてからは、コードを読み返すときに一瞬で意味が分かるようになった。修正も怖くなくなった。マジックナンバーだらけのコードで苦しんでいる人が、この記事でEnumを知ってスッキリ書けるようになればうれしい。

Enumを使えば、関連する定数をグループにまとめて名前を付けられる。マジックナンバーが消えて、コードの可読性が格段に上がる。

なお、Select Caseの基本的な書き方は Select Caseで複数条件の分岐をスッキリ書く方法 を参照。この記事はその発展として、Enumで定数を管理する方法を扱う。

実行前の準備

バックアップを取る

実務版コードはセルの値を書き換える。必ずファイルのコピーを別フォルダに保存してから実行する。

Excelをマクロ有効ブック(.xlsm)で保存する

拡張子が .xlsx のままだとマクロが保存できない。

  1. 「ファイル」→「名前を付けて保存」
  2. ファイルの種類を「Excelマクロ有効ブック (*.xlsm)」に変更
  3. 保存

手順(コピペ → 実行まで約5分)

VBE(コードを書く画面)を開く

  1. Excelで Alt + F11 を押す

標準モジュールを挿入する

  1. VBEのメニュー →「挿入」→「標準モジュール」

コードを貼り付けて実行する

  1. コードウィンドウに、下のコードをそのままコピペする
  2. Alt + F8 → マクロ名を選んで「実行」

重要: Enum定義はSubプロシージャの外(モジュールの先頭付近)に書く。Sub の中には書けない。

補足: 基本版と実務版を同じモジュールに貼る場合、Option Explicit は先頭に1回だけ書く(重複するとエラーになる)。

コード(基本版)– Enumでステータスコードを定義して分岐する

まずはこれで動きを確認する。ステータスコード(1=有効, 2=休止, 3=終了)をEnumで定義し、セルA1の値に応じてMsgBoxで表示する。

セルA1に数値(1, 2, 3のいずれか)を入力してから実行してください。 空セルや文字列が入っているとエラーになる。


Option Explicit

'============================================================
' ■ ステータスコードのEnum定義
'   → 関連する定数をグループにまとめる
'   → Subの外(モジュールレベル)に書く
'============================================================
Public Enum StatusCode
    stActive = 1        '有効
    stSuspended = 2     '休止
    stClosed = 3        '終了
End Enum

'============================================================
' ■ ステータス判定(基本版)
'   → セルA1の値をEnum定数で分岐してMsgBox表示
'============================================================
Sub JudgeStatus()

    Dim currentStatus As StatusCode
    currentStatus = CLng(Range("A1").Value)  '← セルA1の値を取得

    Select Case currentStatus
        Case stActive
            MsgBox "ステータス: 有効", vbInformation
        Case stSuspended
            MsgBox "ステータス: 休止", vbExclamation
        Case stClosed
            MsgBox "ステータス: 終了", vbInformation
        Case Else
            MsgBox "不明なステータス: " & currentStatus, vbCritical
    End Select

End Sub

書き換えポイント

変数 説明 初期値
Range("A1") ステータスコードが入っているセル A1
stActive = 1 有効のコード番号 1
stSuspended = 2 休止のコード番号 2
stClosed = 3 終了のコード番号 3

ポイント: Select Case currentStatus で分岐すると、Case節にEnumメンバー名が並ぶので意味が一目でわかる。Case 1, Case 2 と書くよりはるかに読みやすい。

MsgBoxの使い方の詳細は MsgBoxで確認ダイアログを出して処理を分岐する方法 を参照。

Enumの基本ルール(これだけ押さえればOK)

構文


Public Enum 列挙型名
    メンバー名1 [= 値]
    メンバー名2 [= 値]
    ...
End Enum

ルール一覧

ルール 内容
値の型 Long型のみ(文字列は不可)
自動採番 値を省略すると、最初のメンバーが0、以降+1
明示指定 メンバー名 = 値 で好きな数値を指定できる
スコープ 標準モジュールでPublic(既定)なら全モジュールから参照可能
入力補完 Enum型変数に対してIntelliSense(Ctrl+Space)で候補が出る
定義場所 Subの外(モジュールレベル)に書く。Subの中には書けない

自動採番の例


Public Enum Priority
    prLow           '← 0(自動)
    prMedium        '← 1(自動)
    prHigh          '← 2(自動)
    prCritical = 10 '← 10(明示指定)
    prEmergency     '← 11(10の次で自動)
End Enum

コード(実務版)– Enum × Select Case × RGB色でセル処理

Enumで色定数をまとめてからは、RGB値を毎回調べる手間がなくなった。月次報告の部門別集計で使っていて、チームにマクロを渡すときも「ここのEnum定義を見れば色が分かる」と説明できるようになった。

A列に部門コード(数値)が入った一覧表を処理する。部門コードをEnumで定義し、Select Caseで分岐して、B列に部門名を書き込み、セルの背景色をEnum定義した色で設定する。

※ B列の既存データとセルの背景色は上書きされます。実行前にバックアップを取ってください。


Option Explicit

'============================================================
' ■ 部門コードのEnum定義
'============================================================
Public Enum DeptCode
    deptSales = 1       '営業部
    deptAdmin = 2       '管理部
    deptFactory = 3     '製造部
    deptQuality = 4     '品質管理部
End Enum

'============================================================
' ■ セル背景色のEnum定義(RGB値をLong型で格納)
'   → VBAのRGB関数は R + G*256 + B*65536 でLong値を返す
'   → そのLong値をEnumメンバーの値として定義する
'============================================================
Public Enum CellColor
    clrLightBlue = 16237469     'RGB(157, 195, 247) — 薄い青
    clrLightGreen = 11002054    'RGB(198, 224, 167) — 薄い緑
    clrLightOrange = 10277626   'RGB(250, 210, 156) — 薄いオレンジ
    clrLightPurple = 16233433   'RGB(217, 179, 247) — 薄い紫
    clrLightGray = 14277081     'RGB(217, 217, 217) — 薄いグレー
    clrWhite = 16777215         'RGB(255, 255, 255) — 白
End Enum

'============================================================
' ■ 部門コード→部門名+色設定(実務版)
'   → A列: 部門コード(数値)
'   → B列: 部門名を書き込み、セル背景色を設定
'   → 対象シート: アクティブシート
'============================================================
Sub ClassifyDepartment()

    '--- ★書き換えポイント ---
    Dim startRow As Long: startRow = 2          '← データ開始行
    Dim codeCol As Long: codeCol = 1            '← 部門コード列(A列)
    Dim nameCol As Long: nameCol = 2            '← 部門名書き込み列(B列)
    '--- ★ここまで ---

    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 "データがありません。A列に部門コードを入力してください。", vbExclamation
        Exit Sub
    End If

    '--- エラー処理 ---
    On Error GoTo ErrHandler

    Dim r As Long
    Dim processCount As Long: processCount = 0
    Dim rawValue As Variant
    Dim dept As DeptCode
    Dim deptName As String
    Dim bgColor As CellColor

    For r = startRow To lastRow

        rawValue = ws.Cells(r, codeCol).Value

        '--- 空セル・非数値はスキップして次の行へ ---
        If IsEmpty(rawValue) Or Not IsNumeric(rawValue) Then
            ws.Cells(r, nameCol).Value = "(コード未入力)"
            ws.Cells(r, nameCol).Interior.Color = clrLightGray
            GoTo NextRow
        End If

        dept = CLng(rawValue)

        '--- Enum × Select Case で分岐 ---
        Select Case dept
            Case deptSales
                deptName = "営業部"
                bgColor = clrLightBlue
            Case deptAdmin
                deptName = "管理部"
                bgColor = clrLightGreen
            Case deptFactory
                deptName = "製造部"
                bgColor = clrLightOrange
            Case deptQuality
                deptName = "品質管理部"
                bgColor = clrLightPurple
            Case Else
                deptName = "不明(コード: " & dept & ")"
                bgColor = clrWhite
        End Select

        ws.Cells(r, nameCol).Value = deptName
        ws.Cells(r, nameCol).Interior.Color = bgColor
        processCount = processCount + 1

NextRow:
    Next r

    MsgBox processCount & " 行の部門名と背景色を設定しました。", vbInformation
    Exit Sub

ErrHandler:
    MsgBox "エラーが発生しました。" & vbCrLf & _
           "行: " & r & vbCrLf & _
           "エラー: " & Err.Description, vbCritical
End Sub

エラー処理の基本は エラー処理(On Error)で止まらないマクロを作る方法 を参照。

書き換えポイント

変数 説明 初期値
startRow データの開始行 2(1行目はヘッダー)
codeCol 部門コードの列 1(A列)
nameCol 部門名の書き込み列 2(B列)
DeptCode のメンバー 部門コードの番号 自社のコード体系に合わせて変更
CellColor のメンバー 背景色のRGB値 好みの色に変更(VBAのイミディエイトウィンドウで ?RGB(R,G,B) を実行するとLong値がわかる)

シート構成の例

A列(部門コード) B列(部門名)← マクロで書き込み
1 営業部(薄い青)
2 管理部(薄い緑)
3 製造部(薄いオレンジ)
4 品質管理部(薄い紫)
9 不明(コード: 9)(白)

RGB色の操作方法の詳細は セルの背景色・文字色をRGBで自由に操作する方法 を参照。

Enumで定義した部門コードを引数にして別のマクロに渡すこともできる。やり方は マクロから別のマクロを呼び出して処理を分割する方法 を参照。

よくある落とし穴5選

1. Enumメンバー名に予約語を使ってコンパイルエラー

自分もこれでハマった。Enumのメンバー名に「End」と付けたら予約語と衝突して コンパイルエラー: 構文エラー になった。エラーメッセージには「予約語です」とは出ないので、原因に気づくまで20分は溶かした。

症状 原因 対策
コンパイルエラー: 構文エラー メンバー名にVBA予約語(End, Sub, If, For, Type, Setなど)を使った プレフィックスを付ける(stEndstCompleted)か別の単語に変える

2. 値を省略して0始まりになり、業務コードとずれる

症状 原因 対策
Enumの値と業務コードが合わない 値を省略すると最初のメンバーが0から始まる 業務コードに合わせて メンバー = 値 で明示的に指定する

' NG: 0始まりで業務コード(1始まり)とずれる
Public Enum DeptCode
    deptSales       '← 0 になる(期待は1)
    deptAdmin       '← 1 になる(期待は2)
End Enum

' OK: 明示的に値を指定
Public Enum DeptCode
    deptSales = 1
    deptAdmin = 2
End Enum

3. 別のEnumで同名メンバーを作って名前衝突

症状 原因 対策
コンパイルエラー、または意図しないメンバーが参照される Public Enumのメンバーはグローバルスコープで公開される メンバー名にプレフィックスを付ける(clrRed, deptSales

4. シートモジュールにEnumを書いて他から参照できない

症状 原因 対策
他のモジュールからEnumメンバーを使うとコンパイルエラー シートモジュールのEnumは暗黙的にPrivateになる Enumは標準モジュールに書く

5. Enum型変数に範囲外の値を入れてもエラーにならない

症状 原因 対策
未定義の値(例: 999)が入ってもエラーなく動いてしまう VBAのEnumは内部的にLong型で、型チェックが緩い Select CaseのCase Elseで想定外の値を検知する

VBAのEnumでコンパイルエラーが出るときの対処法

「Enum定義を書いたらコンパイルエラーになる」という場合、原因はメンバー名にVBAの予約語(Error, Name, Typeなど)を使っていることが多い。予約語と重複しない名前(例:errStatus → StatusError)に変更すること。

VBAのEnum値がシート間で共有できないときの対処法

「シートモジュールにEnumを定義したら他のモジュールから参照できない」という場合、原因はシートモジュールに定義したEnumはそのモジュール内でしか使えないためだ。全体で共有するEnumは標準モジュールの先頭に定義すること。

FAQ

Q1: EnumとConstはどう使い分ける?

使い分け Enum Const
用途 関連する定数をグループ化 単独の定数を定義
値の型 Long型のみ 文字列・数値・日付など
入力補完 Enum型変数にドットでメンバー候補が出る 補完なし
おすすめ場面 状態コード、部門コード、色コードなど ファイルパス、シート名など

結論: 「意味的にグループになる数値定数」はEnum、「単独の設定値や文字列定数」はConst。

Q2: Enumの値に文字列は使える?

使えない。VBAのEnumはLong型の整数のみ。文字列定数を定義したい場合は Const を使う。


' これはNG(文字列は指定できない)
Public Enum SheetName
    shMain = "メイン"  '← コンパイルエラー
End Enum

' 文字列はConstで定義する
Public Const SHEET_MAIN As String = "メイン"

Q3: VBAの組み込み定数(vbOK, vbRedなど)もEnum?

そのとおり。VBAに最初から入っている定数の多くはEnumで定義されている。

  • vbOK = 1, vbCancel = 2VbMsgBoxResult Enum
  • vbRed, vbBlueColorConstants Enum
  • xlUp, xlDownXlDirection Enum

自分で作るEnumも、これらと同じ仕組み。

Q4: Enumのメンバーを後から追加しても大丈夫?

大丈夫。End Enumの手前に新しいメンバー行を追加するだけ。既存のコードが壊れることはない(Case Elseを入れておけば、新しい値が来ても想定外として検知できる)。

Q5: Enumの全メンバーをループで取得できる?

VBAにはEnum全メンバーを動的に列挙する機能がない(VB.NETの Enum.GetValues のような機能は非対応)。対策は2つ。

  1. Enum定義にコメントで一覧を書いておく
  2. メンバーの最小値・最大値を定義してForループで回す

Public Enum DeptCode
    deptMin = 1         '← ループ用の最小値
    deptSales = 1       '← deptMinと同じ値でもOK(動作に問題なし)
    deptAdmin = 2
    deptFactory = 3
    deptQuality = 4
    deptMax = 4         '← ループ用の最大値
End Enum

' ループで全メンバーを処理
Dim d As Long
For d = deptMin To deptMax
    Debug.Print d
Next d

まとめ

  • Enum: 関連する定数をグループにまとめて名前を付けられる
  • マジックナンバーの排除: Case 1Case stActive で意味が一目でわかる
  • Select Caseとの相性: Enum × Select Caseで分岐処理がスッキリ書ける
  • 値はLong型のみ: 文字列定数はConstを使う
  • Case Elseは必須: Enum型変数に範囲外の値が入ってもエラーにならないため、自分で検知する

もっと早く知りたかったと思う機能の1つ。Enumを使い始めると、マジックナンバーだらけだった過去の自分のコードが別物に見える。

関連記事

次にやりたくなること

コメント

タイトルとURLをコピーしました