TL;DR —
Const VAT_RATE As Double = 0.19は、固定した値に、コンパイル 時に固定される名前を与えます。変数が中身を入れ替えられる箱だとすれば、 定数は塗りつけられたラベルです — どこからでも読めますが、マクロの実行中は どこからも塗り直せません。その不変性こそが肝心な点です:8 つの数式に 散らばったマジックナンバーを、1 つの権威ある出典に変えるのです。Constを 再代入しようとするのはコンパイルエラー(「定数には値を代入できません」)です — そしてそのエラーは、制約ではなく機能です。関連する固定値の一族 (ステータス、列番号)には、多数の別々のConstではなくEnumを使い ましょう。
Const VAT_RATE As Double = 0.19 ' 1 か所、1 つの真実
Const MAX_ROWS As Long = 10000
Const REPORT_TAB As String = "Summary"
Sub ShowRate()
Debug.Print "VAT is " & VAT_RATE * 100 & "%" ' -> VAT is 19%
End Sub
どのマクロも、リテラル値であふれています:税率、見出しの行番号、シート名、
しきい値。インラインで打ち込むと、それぞれがマジックナンバーになります —
意味を推測しなければならず、変わったときには値を探し回らなければならない、
むき出しの 0.19 や 7 です。Const はその治療薬であり、マクロに施せる
最も安上がりな品質向上の 1 つです。
この記事で学べること
- マジックナンバーがなぜ保守の罠なのか、そして
Constがどうそれを 1 か所で直すのか Constの再代入がなぜコンパイルエラーなのか — そしてそれがなぜ、まさに望むものなのか- コンパイル時のルール:
Constはリテラルにはなれるが、関数呼び出しやセルの値にはなれない - プロジェクト全体で共有する値のための
Public Const - 多数の
Constから 1 つのEnumへ卒業すべきとき
考え方の軸:定数は塗りつけられたラベルで、中身を入れ替える箱ではない
変数と定数は似て見えますが、正反対の振る舞いをします。変数は箱です:値を 入れ、後で別の値に入れ替えられます。定数は、コンパイルする瞬間に値の上に 塗りつけられたラベルです。スコープ内なら誰でもどこからでもラベルを読めます が — コードの実行中は何もそれを塗り直せません。値は凍結されています。
その凍結は、回避すべき制約ではありません。それは、あなたが買っている保証です。
Const VAT_RATE = 0.19 と書くとき、あなたはコンパイラにも次の読み手にもこう
告げています:この数値には 1 つの意味があり、1 か所に住み、あなたの知らない
うちに変わることはない、と。定数についての良いことはすべて、その約束から
流れ出ます。
元を取るルール:マジックナンバーはずれるが、定数はずれない
Const が解決する問題がこれです。0.2 — VAT の税率 — が、マクロじゅうの
8 つの異なる数式に直接打ち込まれているとします:
' マジックナンバー 0.2 があちこちに散らばっている — 税率変更は 8 か所すべてを探すこと
gross = net * 1.2
vat = net * 0.2
' ...あと 6 か所、それぞれにむき出しの 0.2...
さて、税率が 0.19 に変わります。あなたは一つひとつを見つけて編集しなければ
なりません。1 か所でも見落とせば、無言の間違った合計が出ます — エラーは
なく、ただ数字が合わないだけ、しかもあるレポートでは合い、別のレポートでは
合わない。そして半年後の読み手には、その 0.2 が VAT なのか、割引なのか、
手数料なのか、見当もつきません。
1 つの定数が、それをすべて直します:
Const VAT_RATE As Double = 0.19 ' ここで一度変えれば、すべての箇所が更新される
gross = net * (1 + VAT_RATE)
vat = net * VAT_RATE
値はちょうど 1 か所に住み、名前がその意味を記録し、税率変更は中途半端に
できない 1 行の編集になります。複数回現れるリテラル、あるいは文脈から
意味が明らかでないリテラルは、すべて Const にすべきです。
実は機能であるルール:Const には代入できない
定数を変えようとすると、VBA は拒否します — コンパイル時に、マクロが走り出す 前に:
Const TAX As Double = 0.2
Sub Oops()
TAX = 0.25 ' コンパイルエラー:定数には値を代入できません
End Sub
初心者は、そのエラーを VBA が意地悪しているのだと読むことがあります。逆です:
これはコンパイラが値を決して変わらないと保証していることであり、それこそが
あなたが定数を宣言した全理由です。もし再代入したくなっているなら、それは
初めから定数ではなかったのです — 実行時に変わる変数なので、Dim で宣言
しましょう。この区別が、判断のすべてです:この値はマクロの実行中に変わるか?
変わるなら Dim。変わらないなら Const。
人を驚かせるルール:Const はコンパイル時に評価される
ラベルはコンパイルするときに塗りつけられるので、定数はコンパイラがすでに 知っているものにしか設定できません:リテラル、または他の定数から組み立てた 式です。関数呼び出し、ワークシートの値、あるいはマクロの実行中に計算される ものにはなれません。
' 動く — リテラル、またはリテラルや他の定数の式
Const PI As Double = 3.14159
Const TWO_PI As Double = 2 * PI
Const HEADER As String = "Report — " & "2026"
' 失敗する — 実行時の評価が必要なので、変数でなければならない
Const TODAY As Date = Date ' コンパイルエラー:定数式が必要です
Const RATE As Double = Range("A1").Value ' コンパイルエラー
値がマクロの実行中にしか分からないなら — 今日の日付、セルの現在の中身、
関数の結果 — それは Const ではなく、実行時に代入する Dim 変数に属します。
スコープ:ローカルな Const と Public Const
Const は Dim と同じスコープのルールに従います。Sub の内側に書けば、その
手続きにローカルです。モジュールの一番上に Public を付けて書けば、すべての
モジュールが読めるプロジェクト全体の定数になります:
' "Config" というモジュールの、どの手続きよりも上に:
Public Const APP_NAME As String = "Monthly Close"
Public Const DATA_SHEET As String = "Raw"
Public Const HEADER_ROW As Long = 1
規模に応じて効いてくるイディオムは、アプリ全体の定数をすべて収めた 1 つの
Config モジュールです — シート名、しきい値、アプリのタイトル — 何かを変える
必要があるとき、見る場所がちょうど 1 か所になるように。手続き固有の定数は
ローカルに保ち、本当に共有されるものだけを昇格させましょう。
1 つの値では足りないとき:一族には Enum を使う
関連する定数のグループ — 注文ステータス、列の位置、レポートの種類 — が
あるとき、別々の Const の山でも動きますが、読みにくくなります。Enum は
それらを 1 つの集合として名付け、1 つの型の下にまとめ、IntelliSense と軽い
型チェックを与えてくれます:
Enum OrderStatus
Pending = 1
Paid = 2
Shipped = 3
Cancelled = 4
End Enum
Sub Demo()
Dim s As OrderStatus
s = Paid
If s = Cancelled Then Exit Sub
End Sub
目安はこうです:単独の値には Const、まとまって属する関連値の一族には
Enum。 Enum は意図も示します — As OrderStatus と型付けされた
パラメーターは、読み手(そしてエディター)に、どの値が正当かを正確に伝えます。
ExcelMaster の活用
定数、スコープの規律、そして Enum は、育っていくマクロを保守可能に保つ
習慣です — そして、本当に気にかけているロジックにたどり着くずっと前から、
プロジェクトごとに背負う諸経費でもあります。
ExcelMaster
を使えば、配管を組む代わりにルールを述べられます:「D 列に 19% の VAT を適用、
Cancelled ステータスのものに印を付け、合計を Summary シートに書いて」。それを、
税率とステータス値を 1 か所にまとめた、動くロジックに変えてくれます。だから
変更は、8 つの数式を探し回ることではなく、説明への変更で済みます。制御が
欲しいところでは、これからも手書きのマクロで Const を宣言するでしょう。
日々の作業では、ルールを説明する方が、その裏のマジックナンバーを保守するより
勝るのです。
よくある質問
VBA の定数とは何ですか?
定数とは、コンパイル時に固定され、マクロの実行中は変わらない、名前付きの値です。
Const で宣言します。例:Const VAT_RATE As Double = 0.19。散らばった
「マジックナンバー」を、1 つの名前付きの出典に置き換えるので、値は 1 か所に住み、
その意味は名前によって記録されます。
Const と Dim の違いは何ですか?
Dim は変数 — 実行時に値を変えられる箱 — を宣言します。Const は定数 —
コンパイル時に固定され、再代入できない値 — を宣言します。マクロの実行中に決して
変わらないもの(税率、シート名、しきい値)には Const を、変わるものには Dim を
使いましょう。
実行時に Const を変えられますか?
いいえ。定数に新しい値を代入するのはコンパイルエラー(「定数には値を代入
できません」)であり、その保証こそが定数を使う理由です。マクロの実行中に値を
変える必要があるなら、それは定数ではありません — Dim で変数として宣言
しましょう。
なぜ Const x = Range("A1").Value は失敗するのですか?
Const はコンパイル時に評価されるので、リテラルか他の定数の式にしか設定
できません — 決して、セルの値、関数の結果、Date のような実行時に計算される
ものには設定できません。それらには、マクロの実行中に代入する Dim 変数を
使いましょう。
VBA の Enum とは何で、Const の代わりにいつ使うべきですか?
Enum は、関連する名前付き定数の一族を 1 つの型の下に定義します。例:注文
ステータスや列番号。単独の値には複数の Const を使いますが、値が 1 つの集合と
してまとまって属するときは Enum に手を伸ばしましょう — それらをグループ化し、
IntelliSense を有効にし、パラメーターをその列挙型として As で型付けして、どの
値が正当かを記録できます。
検証環境
検証環境: Excel 365(Windows 11)、VBA 7.1 — 最終確認 2026-07-31。
関連ガイド: VBA Dim · VBA Data Types · VBA Sub · VBA Function · VBA If Then Else
