条件付きコンパイラ定数はオーバーライドできる
条件付きコンパイラ定数 (conditional compiler constant) とは、プログラムの実行前(コンパイル時)にのみ用いることのできる定数です。実行時には参照することはできません。組み込みで初めから定義されていたり、#Const
などで定義できます。
条件付きコンパイラ定数を#If...Then...#Else
ディレクティブの式に用いることで、ソースコードの有効無効を切り替えることができます。
ほとんど知られていないようですが、条件付きコンパイラ定数はオーバーライド(あるいはシャドー)できます。広いスコープを持つ条件付きコンパイラ定数をより狭いスコープを持つ条件付きコンパイラ定数でオーバーライドできます。狭いスコープを持つ条件付きコンパイラ定数を定義することで広いスコープを持つ条件付きコンパイラ定数をシャドーできると言い換えることもできます。
ビルトインスコープ(Built-in Scope)
プロジェクトスコープの特殊な例です。 厳密にはプロジェクトスコープですが、どのプロジェクトからでも参照してよく、最も広いスコープのように見えます。 アプリケーションの環境(VBAのバージョン・実行環境のビット数・OSなど)によって、あらかじめ組み込みで定義されます。具体的には VBA7
, Win32
などが該当します。
パブリックモジュールレベルのスコープ (Public Module Scope)
単にパブリックスコープと呼んだり、グローバルスコープ、プロジェクトスコープと呼ぶこともあります。プロジェクトプロパティダイアログボックス (Alt + T, E) の条件付きコンパイル引数テキストボックスで設定できます。
プライベート モジュール レベルのスコープ (Private Module Scope)
単にモジュールスコープと呼ばれることもあります。#Const
ディレクティブで条件付きコンパイル引数を定義できます。
条件付きコンパイラ定数のオーバーライドの方法と例
- ビルトインスコープの
VBA7
はVBA7 = 1
と評価されます。古い環境ではVBA7 = 0
と評価されることもあります。 -
プロジェクトプロパティダイアログボックスの条件付きコンパイル引数テキストボックスに
VBA7 = 2
を入れると 2 と評価されます。 - モジュールのソースコードで
#Const VBA7 = 3
とすると 3 と評価されます。
コード例
Option Explicit
' #Const VBA7 = 3
Sub Main()
#If VBA7 = 1 Then
Debug.Print "VBA7 = 1 ' ビルトイン"
#End If
#If VBA7 = 2 Then
Debug.Print "VBA7 = 2 ' プロジェクトプロパティでオーバーライド"
#End If
#If VBA7 = 3 Then
Debug.Print "VBA7 = 3 ' #Const でオーバーライド"
#End If
End Sub
出力はそれぞれ、通常時は
VBA7 = 1 ' ビルトイン
プロジェクトプロパティダイアログボックスを使うと
VBA7 = 2 ' プロジェクトプロパティでオーバーライド
コメントを外して #Const VBA7 = 3
を有効化すると
VBA7 = 3 ' #Const でオーバーライド
うまく上書きできて切り替わっていますね。
条件付きコンパイラ定数の使用におけるベストプラクティス
ビルトインスコープのオーバーライドの潜在的リスク
通常、ビルトインスコープの条件付きコンパイル引数をオーバーライドするべきではありません。他人や将来の自分が想定外の動作に困ることがあります。
- コンパイルエラーが起きるかも。条件付きコンパイラ定数を不適切にオーバーライドすると、コンパイル時にエラーが発生する可能性があります。原因の発見が難しいかもしれません。
- 実行時エラーが起きるかも。実行中に予期しない状況が発生する可能性があります。オーバーライドされた定数が異なるモジュールやプロジェクト間で不整合を引き起こして問題が起きるかもしれません。
- 実行時に想定外の動作するかも。プログラムが意図した通りに動作しない場合があります。これは、オーバーライドされた定数のために、特定のコードブロックが予期せずに実行される、または実行されないといった問題を引き起こすかもしれません。
一方で、テストや実験の時には非常に有用なケースがあります。うまく使いましょう。
プロジェクトレベルでのコンパイル引数の有効活用
プロジェクトプロパティダイアログボックスを使った条件付きコンパイル引数を#Const
でオーバーライドするのは非常に有用です。
プロジェクトプロパティダイアログボックスを使った条件付きコンパイル引数を使えば、
- プロジェクト単位でデバッグバージョンとリリースバージョンの切り替え
- テストを実行するかどうかの切り替え
- ログあり無しの切り替え
- 事前バインディング有り無しの切り替え
などができます。条件付きコンパイル引数はCONST_VAR = 1
のように= 整数
の形で定義できます。複数定義するときはCONST_VAR1 = 1 : CONST_VAR2 = 1
のようにコロン(:
)で区切ります。
その上で、特定のモジュールのみ個別に動作を変えるために#Const
で条件付きコンパイル引数をオーバーライドすることができます。