【VBAスタンダード対策】変数のスコープ(有効範囲)の構造を攻略!
変数は、宣言する場所によってその「見える範囲(スコープ)」が異なります。プロシージャの中で宣言する「プロシージャレベル変数」と、外で宣言する「モジュールレベル変数」の構造的違いを、実行結果から読み解きましょう。
1. 問題:同名の変数が存在する場合の実行結果
【 問題 】 下記のコードを実行して Main プロシージャを呼び出した際、メッセージボックスに表示される数値はいくつでしょうか?
Sub Main()
Dim num As Integer ' --- (B) プロシージャレベル変数
num = 100
ShowValue
End Sub
Sub ShowValue()
MsgBox num
End Sub
① 0
② 100
③ エラーになる
④ どちらのnumか選択するダイアログが出る
2. 正解:変数のスコープと優先順位に関する正解
正解: ① 0
3. 解説:なぜ「100」ではなく「0」なのか?
この問題の核心は、「名前は同じでも、メモリ上では全く別の箱(構造)である」という点にあります。VBAでは、より狭い範囲(プロシージャ内)で宣言された変数がその中では優先されますが、他のプロシージャからはその中身は見えません。
■ 標準モジュール全体のエリア
│ [箱A] num (モジュールレベル) -> 初期値 0
│
│ Sub Main()
│ │ [箱B] num (プロシージャレベル) -> 100 を代入
│ │ ※Main内では[箱B]が[箱A]を隠す(シャドウイング)
│ End Sub
│
│ Sub ShowValue()
│ │ MsgBox num -> このプロシージャからは[箱A]しか見えない!
│ End Sub
1. ここが試験に出る!: スタンダード試験では、このように「わざと変数の名前を重複させたコード」で、変数の寿命と有効範囲の理解度を試してきます。Main で代入した num = 100 は、あくまで Main の中だけで有効な「プロシージャレベル変数」に対する操作です。別のプロシージャである ShowValue は、モジュールの先頭で宣言され、初期化(0)されたままの「モジュールレベル変数」を参照するため、答えは 0 になります。
2. エンジニアの視点: Java 17などのフィールド変数とローカル変数の関係と同じ構造です。実務でこの構造的なミス(意図しない0の参照)を防ぐには、モジュールレベル変数には m_num のように接頭辞を付けるのが、デバッグの手間を減らす理系NEOな設計です。
4. まとめ
「自分に近い方の変数が優先されるが、プロシージャをまたけば見え方が変わる」。このスコープの構造を正しく把握することで、変数の値が予期せず変わったり、逆に反映されなかったりするバグを確実に防ぐことができます。減数分裂において各細胞が独自の役割を維持するように、VBAも変数の有効範囲を厳密に分離することで、プログラムの整合性を保つのです。