VBAの条件付きコンパイル引数で全モジュールを切り替える
コンパイラ定数のモジュール内限定とプロジェクト全体の切り替えを整理する
Copyright © 2026 LWP 山中 一弘
本資料は、出典を明記いただければ、商用・非商用を問わず、ご自由に複製・改変・再配布していただけます。なお、著作権表示は改変せず、そのまま記載してご利用くださいますようお願いいたします。
記事要約
VBAには、実行時の If とは別に、コンパイル時にコードを含めるかどうかを切り替える条件付きコンパイルがあります。代表的な例は、64bit対応のAPI宣言で見る #If VBA7 Then です。この仕組みを使うと、開発時だけログを出す、Excel用とAccess用でコードを分ける、古い機能を一時的に無効にする、といった切り替えができます。
ただし、独自に #Const DEBUG_MODE = 1 のようなコンパイラ定数を書くと、その定数は基本的に書いたモジュール内でしか使えません。全モジュールで同じ切り替えをしたい場合、各モジュールに同じ #Const を書く運用になり、変更漏れが起きやすくなります。
この記事では、Togetter/Posfie上の議論と、参照ブログ、Microsoft Learn、画像に写っていたVBE画面をもとに、#Const と「条件付きコンパイル引数」の違いを整理します。画像内の内容は、画面を見なくても分かるように、操作説明とコード例として本文へ再構成しています。
本記事の対象とゴール
想定読者
VBAで #If VBA7 Then は見たことがあるが、自分で条件付きコンパイルを使ったことは少ない人
#Const を複数モジュールで共有できず困ったことがある人
開発用、本番用、Excel用、Access用などの切り替えをVBAプロジェクト全体で管理したい人
VBEの「条件付きコンパイル引数」が何に使えるのか知りたい人
本記事で得られること
#Const が通常の Const とは違い、#If 用のコンパイラ定数であることが分かります。
モジュール内の #Const と、プロジェクトプロパティの「条件付きコンパイル引数」のスコープ差を説明できます。
DEBUG_MODE = 1 : IsExcel = 1 のように、複数のコンパイラ定数をプロジェクト単位で指定する書き方が分かります。
True / False、0 / 1、未定義定数、型指定まわりで混乱しやすい点を避けられます。
本記事で扱わないこと
すべてのVBAコンパイラ定数の厳密な内部実装
Office全バージョン、全ホストアプリでの網羅的な挙動差
条件付きコンパイルを使った大規模なビルド管理
X/Twitter画像を原寸で再掲すること
先に結論
VBAでプロジェクト全体を条件付きコンパイルで切り替えたい場合、各モジュールへ #Const を書き散らすより、VBEのプロジェクトプロパティにある「条件付きコンパイル引数」を使うほうが集中管理しやすくなります。
たとえば、プロジェクトプロパティの「条件付きコンパイル引数」に次のように書きます。
DEBUG_MODE = 1 : IsExcel = 1すると、プロジェクト内の各モジュールで次のような分岐を書けます。
Sub Sample() #If DEBUG_MODE = 1 Then Debug.Print "debug mode" #Else Debug.Print "release mode" #End IfEnd Sub一方で、モジュール先頭に書く #Const DEBUG_MODE = 1 は、そのモジュールの中で使う局所的な切り替えに向いています。全体を切り替える設定と、モジュール固有の切り替えは分けて考えるべきです。
また、条件付きコンパイル引数では、True / False よりも 1 / 0 のような数値で指定するほうが安全です。0 は偽、0以外 は真として扱う前提で、記事内では明示的に = 1 や = 0 と比較する書き方を基本にします。
第1章 条件付きコンパイルは実行時のIfではない
1.1 `If` と `#If` は働くタイミングが違う
通常の If ... Then は、VBAのコードが実行されるときに分岐します。条件が真ならこちらを実行し、偽なら別の処理へ進む、という実行時の制御です。
一方、#If ... Then は、コンパイル時にどのコードをVBAに読ませるかを切り替えるためのディレクティブです。条件に合わない側のコードは、実行されないだけでなく、そもそもコンパイル対象から外れます。
この違いは、文法的に壊れたコードをわざと片側に置くと分かりやすくなります。
#Const IsExcel = 1#If IsExcel = 0 Then この行はVBAとしては文法エラーになる文字列です#End IfSub Test() MsgBox "Hello"End SubIsExcel = 1 であれば、文法エラーになる行はコンパイル対象から外れます。したがって、Test は実行できます。これは通常の If ではできません。通常の If は実行時に分岐するだけなので、プロシージャ外に文法的に不正な行があれば、実行前にコンパイルエラーになります。
1.2 代表例は `#If VBA7 Then`
VBAで条件付きコンパイルを見かける場面として多いのは、WinAPI宣言の32bit/64bit対応です。
#If VBA7 Then Private Declare PtrSafe Function GetTickCount Lib "kernel32" () As Long#Else Private Declare Function GetTickCount Lib "kernel32" () As Long#End Ifここで使っている VBA7 は、VBA側が用意している組み込みのコンパイラ定数です。Microsoft Learnでは、VBAのバージョンや実行環境に応じたコンパイラ定数が説明されています。
重要なのは、VBA7 が普通の変数ではないことです。Debug.Print VBA7 のように実行時の値として使うものではありません。#If の条件式で使うための名前です。
1.3 コンパイラ定数はコードを読む前のスイッチである
コンパイラ定数は、コードの実行中に参照する値ではなく、コードをコンパイル対象に含めるかどうかを決めるスイッチです。
このため、次のような通常の変数確認とは違います。
#Const DEBUG_MODE = 1Sub Test() #If DEBUG_MODE = 1 Then Debug.Print "debug" #End IfEnd SubDEBUG_MODE は Debug.Print DEBUG_MODE として表示するための変数ではありません。#If DEBUG_MODE = 1 Then の条件として使うためのコンパイラ定数です。
第2章 `#Const` はモジュール内限定で考える
2.1 `#Const` は宣言領域に書く
独自のコンパイラ定数を作る場合、モジュールの宣言領域に #Const を書きます。
Option Explicit#Const DEBUG_MODE = 1Sub Sample() #If DEBUG_MODE = 1 Then Debug.Print "debug mode" #End IfEnd Subこの書き方は、そのモジュールだけを切り替えたいときには分かりやすいです。たとえば、あるモジュールだけ実験用コードを残したい、特定の処理だけ一時的に有効化したい、という用途には向いています。
2.2 `#Const` は普通の `Const` ではない
見た目は Const に似ていますが、#Const は通常の定数とは別物です。通常の Const はプロシージャ内やモジュールレベルで値として参照できます。一方、#Const は #If などの条件付きコンパイルで使うためのものです。
次のように、#Const の名前を通常の値として表示しようとすると、期待どおりには扱えません。
#Const IsExcel = 1Sub Test() 'これは通常の変数や定数としての参照ではない Debug.Print IsExcelEnd Sub#Const は、VBAコードの実行時に存在する普通の名前ではありません。#If IsExcel = 1 Then のように、コンパイル制御で使います。
2.3 Publicな `#Const` は書けない
通常の Const であれば、Public Const としてプロジェクト内で共有できます。しかし、#Const に Public を付けて全モジュール共有にする書き方はできません。
次のような書き方は避けます。
Public #Const IsExcel = 1#Const Public IsExcel = 1#PublicConst IsExcel = 1#Public Const IsExcel = 1したがって、#Const だけで全モジュール共通の切り替えを作ろうとすると、各モジュールの先頭に同じ定義を書くことになります。これは変更漏れの原因になります。
第3章 全モジュールで使うなら条件付きコンパイル引数を使う
3.1 VBEのプロジェクトプロパティで設定する
全モジュールで同じコンパイラ定数を使いたい場合は、VBEのプロジェクトプロパティを使います。
操作は次の流れです。
VBEのプロジェクトエクスプローラーで対象プロジェクトを右クリックします。
VBAProject のプロパティ を開きます。
全般 タブの 条件付きコンパイル引数 に値を書きます。
OK で保存します。
画像では、この欄に次のような指定が入っていました。
DEBUG_MODE = 1この設定は、ソースコードの各モジュールに #Const DEBUG_MODE = 1 を書いたのと似た効果を持ちます。ただし、ソースコードではなくプロジェクト設定として保存されます。
3.2 プロジェクト全体で同じ `#If` が使える
条件付きコンパイル引数に DEBUG_MODE = 1 を設定すると、どのモジュールでも次のように書けます。
Sub Test() #If DEBUG_MODE = 1 Then Debug.Print "debug mode" #Else Debug.Print "release mode" #End IfEnd Subこの利点は、切り替え点が1か所になることです。各モジュールの #Const を修正して回る必要がありません。開発中は DEBUG_MODE = 1、配布時は DEBUG_MODE = 0 のように、プロジェクト単位で切り替えられます。
3.3 複数指定はコロンで区切る
Microsoft Learnのプロジェクトプロパティ説明では、条件付きコンパイル引数は複数の定数をコロンで区切って指定できるとされています。画像でも、複数指定の例として次の形が確認できました。
DEBUG_MODE = 1 : IsWord = 1実務では、次のような名前を使うと意味が分かりやすくなります。
DEBUG_MODE = 1 : IsExcel = 1 : SPECIAL_MODE = 0この設定に対して、コード側では次のように明示的に比較します。
#If IsExcel = 1 Then 'Excel用の処理#End If#If SPECIAL_MODE = 1 Then '一時的に有効化する処理#End If第4章 `True` / `False` より `1` / `0` で考える
4.1 条件付きコンパイル引数には数値で書く
画像では、条件付きコンパイル引数へ次のように書いた場合に、VBEが構文エラーを出していました。
IsExcel=true記事素材では、条件付きコンパイル引数では True / False ではなく、数値で指定するほうが安全だと整理されています。
IsExcel = 1IsAccess = 0Microsoft Learnのプロジェクトプロパティ説明でも、複数指定の例は conFrenchVersion=-1:conANSI=0 のような数値です。したがって、この記事では、プロジェクトプロパティ側は 1 と 0 を基本にします。
4.2 `0` は偽、`0以外` は真として読む
条件付きコンパイルの条件式では、0 は偽、0以外 は真として扱う前提で読むと理解しやすくなります。
ただし、独自の定数では、次のように比較を省略しないほうが安全です。
#If DEBUG_MODE Then Debug.Print "debug"#End Ifより意図が明確なのは、次の書き方です。
#If DEBUG_MODE = 1 Then Debug.Print "debug"#End IfDEBUG_MODE が 2 でも真として扱われてよいのか、1 のときだけ有効なのかを、コードから読み取れるようにするためです。
4.3 型指定は書かない
画像では、次のようなコードが構文エラーになっていました。
#Const IsExcel = 1 As Integer#Const は通常の変数宣言ではないため、As Integer のような型指定は不要です。条件付きコンパイル引数でも、型を書く場所はありません。
必要なのは、名前と値です。
#Const IsExcel = 1または、プロジェクトプロパティ側で次のように指定します。
IsExcel = 1第5章 未定義定数と見えない設定に注意する
5.1 未定義定数はエラーで知らせてくれない
通常のVBAでは、Option Explicit を書くことで未定義の変数を検出できます。しかし、条件付きコンパイルの定数は通常の変数ではありません。
記事素材では、未定義のコンパイラ定数は実質的に 0 として扱われる挙動が話題になっていました。Microsoft Learnの #If...Then...#Else ディレクティブ説明にも、未定義の定数評価についての説明があります。
このため、次のようなコードは、スペルミスに気づきにくい危険があります。
#If DEBIG_MODE = 1 Then Debug.Print "debug"#End IfDEBUG_MODE と書くつもりで DEBIG_MODE と書いても、通常の変数のようには警告されません。条件が成立せず、そのブロックがコンパイル対象から外れるだけです。
5.2 プロジェクト設定はコード差分に出にくい
条件付きコンパイル引数は便利ですが、ソースコード上には出てきません。つまり、コードだけを見ても、DEBUG_MODE がどこで定義されているか分かりにくくなります。
この性質は、差分管理上は利点にもなります。モジュールコードに #Const を書かないため、環境切り替えでコード差分が出ません。
一方で、保守上は注意が必要です。別PCへブックを渡したとき、開発環境から本番環境へコピーしたとき、誰かがプロジェクトプロパティを知らないと、なぜ分岐が変わるのか追えなくなります。
したがって、条件付きコンパイル引数を使う場合は、README、設計メモ、または管理シートに設定値を明記しておくべきです。
5.3 `#If` を見たらプロジェクトプロパティも見る
VBAレビューで #If DEBUG_MODE = 1 Then のようなコードを見つけたら、まずモジュール先頭の #Const を探します。見つからない場合は、VBEのプロジェクトプロパティを確認します。
特に、全モジュールで同じ名前が使われている場合は、プロジェクトプロパティの条件付きコンパイル引数で定義されている可能性があります。
レビュー時の確認順序は次のとおりです。
組み込みコンパイラ定数か確認する。例: VBA7、Win64、Mac。
モジュール先頭に #Const があるか確認する。
プロジェクトプロパティの条件付きコンパイル引数を確認する。
スペルミスや未定義時の挙動を確認する。
= 1、= 0 のように明示比較されているか確認する。
第6章 実務での使いどころ
6.1 デバッグログの切り替え
最も使いやすい用途は、デバッグログや一時的な確認処理の切り替えです。
Sub ImportData() #If DEBUG_MODE = 1 Then Debug.Print "start import" #End If '通常処理 #If DEBUG_MODE = 1 Then Debug.Print "end import" #End IfEnd Sub開発中は DEBUG_MODE = 1、配布時は DEBUG_MODE = 0 にします。コード自体をコメントアウトしたり戻したりするより、切り替えの意図が明確になります。
6.2 Excel用、Access用、Word用の切り替え
Officeアプリごとに使えるオブジェクトが違う場合も、条件付きコンパイル引数が役に立ちます。
IsExcel = 1 : IsAccess = 0 : IsWord = 0#If IsExcel = 1 Then 'ThisWorkbookを使う処理#ElseIf IsAccess = 1 Then 'CurrentProjectを使う処理#End Ifただし、複数ホスト対応は複雑になりがちです。条件付きコンパイルで隠すだけでなく、入口、出力、依存オブジェクトを設計として分ける必要があります。
6.3 一時機能や危険機能の切り替え
記事素材では、隠し機能や特殊モードの切り替えも例として挙がっていました。たとえば次のような使い方です。
SPECIAL_MODE = 0#If SPECIAL_MODE = 1 Then '一時的な移行処理や検証機能#End Ifこの使い方は便利ですが、危険でもあります。なぜなら、コード上に存在していても、通常はコンパイル対象から外れるため、普段の確認では見落としやすいからです。
一時機能を残す場合は、必ず設定値、用途、削除予定をメモします。条件付きコンパイルは、消し忘れを正当化するための仕組みではありません。
まとめ
VBAの条件付きコンパイルは、実行時の If ではなく、コンパイル時にコードを含めるかどうかを切り替える仕組みです。#If VBA7 Then のような組み込み定数だけでなく、独自のコンパイラ定数を使うことで、開発用・本番用、Excel用・Access用、特殊機能の有効無効を切り替えられます。
モジュール内だけで使うなら #Const で十分です。しかし、全モジュールで同じ切り替えをしたい場合、各モジュールへ #Const を書き散らすのは危険です。その場合は、VBEのプロジェクトプロパティにある「条件付きコンパイル引数」を使い、DEBUG_MODE = 1 : IsExcel = 1 のようにプロジェクト単位で指定します。
実務では、True / False より 1 / 0 を基本にし、コード側では #If DEBUG_MODE = 1 Then のように明示比較するのが読みやすくなります。また、条件付きコンパイル引数はコード上に見えにくいため、READMEや設計メモに設定値を残すことが重要です。
出典メモ
元URL: https://togetter.com/li/1838790
正規URL: https://posfie.com/@hoehoe1234/p/qJSo7Ag
元タイトル: 2022-01-31 VBA 条件付きコンパイル - posfie
取得日: 2026-06-11
主に参考にした投稿:
- @KotorinChunChun: #Const はモジュール内限定であり、プロジェクト全体で切り替えるには条件付きコンパイル引数を使うという指摘。投稿URL: https://x.com/KotorinChunChun/status/1338524834725208065
- @KotorinChunChun: 条件付きコンパイルの利用例として、Excel/Access/Debug/Specialなどのモード名を整理。投稿URL: https://x.com/KotorinChunChun/status/1338526026985455623
- @KotorinChunChun: 参照ブログ「VBAでパブリックなコンパイラ定数を定義して条件付きコンパイル制御を行う方法」。URL: https://www.excel-chunchun.com/entry/20220130-vba-20220130-vba-understanding-conditional-compilation
- @furyutei: Microsoft Learn上の表記、True / False と 1 / 0、条件付きコンパイル引数のコロン区切り、未定義定数の扱いについての補足。投稿URL: https://x.com/furyutei/status/1487986038635401218 / https://x.com/furyutei/status/1487991086358605824 / https://x.com/furyutei/status/1487993774651617284 / https://x.com/furyutei/status/1488124338624950272
- @hoehoe1234: 宣言と定義の言葉の整理、ディレクティブは実行時メモリではなくコンパイル時の指示として読むという補足。投稿URL: https://x.com/hoehoe1234/status/1487991419352776705 / https://x.com/hoehoe1234/status/1487992005024444419
公式参照:
- Microsoft Learn: Compiler constants (VBA) https://learn.microsoft.com/en-us/office/vba/language/concepts/getting-started/compiler-constants
- Microsoft Learn: Project Properties dialog box https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/project-properties-dialog-box
- Microsoft Learn: If...Then...Else ディレクティブ https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/ifthenelse-directive
- Microsoft Learn: Declaring constants (VBA) https://learn.microsoft.com/en-us/office/vba/language/concepts/getting-started/declaring-constants
画像確認:
- 参照ブログ内の主要画像4点を取得して確認した。
- 画像1: VBEのプロジェクトプロパティから 条件付きコンパイル引数 に DEBUG_MODE = 1 を指定する画面。
- 画像2: IsExcel=true を条件付きコンパイル引数に指定すると、定数宣言の構文エラーになる画面。
- 画像3: #Const IsExcel = 1 As Integer がコンパイルエラーになる画面。
- 画像4: DEBUG_MODE = 1 : IsWord = 1 のようにコロン区切りで複数指定する画面。
- X photoページ3件はHTMLから直接画像メタ情報を取得できなかったため、投稿本文、参照ブログ画像、ブログ内コード、公式資料をもとに本文へ再構成した。
