こちらの記事(VBAの変数宣言について)では、変数宣言を行う3つの目的のうち、次の2点について解説しました。
- 変数名(解説済み)
- 変数のデータ型(解説済み)
今回は、残りの3点目である「変数の適用範囲(スコープ)」について解説します。
変数を正しく使いこなすうえで非常に重要なポイントですので、ぜひ押さえておきましょう。
変数の適用範囲(スコープ)とは
VBAでは、変数をどこで・どのように宣言するかによって、その変数の使える範囲が決まります。
この「使える範囲」のことを「適用範囲(スコープ)」と呼びます。
変数は「入れ物」ということで、イメージしやすいように身近な例に置き換えてみます。
- 部屋の中にあるロッカー…その部屋にいる人だけが使える
→プロシージャ内変数(ローカル変数) - 建物全体にある共有ロッカー…建物内のどこからでも使える
→モジュールレベル変数(モジュール全体で有効) - 町全体にある倉庫…町のどこからでも使える
→グローバル変数(プロジェクト全体で有効)
このように、変数の「置き場所(宣言場所)」と「宣言のステートメント」によって、使える範囲が変わるのです。
なお、モジュールやプロシージャといったVBAの用語については、こちら↓の記事で詳しく解説していますので、参考にしてみてください。
適用範囲(スコープ)の種類と宣言ステートメント
こちらの記事(VBAの変数宣言について)では「変数宣言はDimステートメントを使う」という説明を行っています。もちろんDimステートメントは最も基本的で使用頻度の高い宣言ステートメントですが、実は宣言ステートメントはDimだけではありません。
宣言場所によって、使えるステートメントは以下のとおりです。
| 宣言場所 | ステートメント |
|---|---|
| プロシージャ内 | DimステートメントStaticステートメント |
| 宣言セクション | PrivateステートメントDimステートメント |
| 標準モジュールの宣言セクション | Publicステートメント |
それぞれ解説します。
プロシージャ内で宣言(Dim、Static)
プロシージャ内で変数宣言した変数を「プロシージャ内変数」といいます。
宣言場所

プロシージャ内(Private Sub ※※※ ~ End Subの間)にDimステートメント又はStaticステートメントを使い、変数宣言を行います。
適用範囲(スコープ)
プロシージャ内で宣言した変数の適用範囲は、そのプロシージャ内のみです。

有効期間
変数の有効期間は、DimステートメントとStaticステートメントで異なります。
| ステートメント | 有効期間 |
|---|---|
Dimステートメント | プロシージャ終了後は破棄される |
Staticステートメント | プロシージャ終了後も値を保持 |
Dim ステートメントで宣言した変数は、プロシージャが終了(End Sub に到達)した時点で値がリセットされます。
一方、Static ステートメントで宣言した変数は、プロシージャ終了後もそのまま値を保持します。
以下のコードを例に、違いを確認してみましょう。
Sub Test()
Dim MyID As String
MyID = InputBox("IDを入力してください",,MyID)
If MyID <> "" then
MsgBox MyID & "さんが入力されました"
End If
End Sub
【Dimステートメントの場合】
コードを実行すると、InputBox 関数の入力ダイアログが表示されます。
たとえば「中田」と入力すると「中田さんが入力されました」というメッセージが表示されます。
再度コードを実行すると、同じように入力ダイアログが表示され、入力待機状態となります。
なお、InputBox 関数の引数に既定値として MyID 変数を指定していますが、Dim で宣言された変数はプロシージャ終了時に初期化されるため、ダイアログボックスには何も表示されません。
【Staticステートメントの場合】
3行目の変数宣言を Static に変更して実行してみましょう。
入力ダイアログに「中田」と入力すると、同じようにメッセージが表示されます。
再度コードを実行すると、ダイアログボックスの既定値に先ほど入力した「中田」が表示されます。
このように、Static で宣言した変数は、プロシージャ終了後も値を保持し続けることがわかります。
宣言セクション(Private、Dim)
宣言セクションで変数宣言した変数を「モジュールレベル変数」といいます。
宣言場所

宣言セクションは、VBEでモジュールの先頭に位置し、最初のプロシージャ(SubやFunction)よりも前に記述される領域です(上図参照)
適用範囲(スコープ)
モジュールの先頭にDimやPrivateで宣言すると、同じモジュール内のすべてのプロシージャから参照できます。

上記例では宣言セクションで変数mCountを宣言していますが、この変数はSub1及びSub2両方のプロシージャで有効です。Sub1実行で変数に1を格納し、Sub2実行でメッセージボックスに1を表示する処理となります。
有効期間
モジュールレベル変数の値は、プロシージャを抜けても保持され、Accessを終了するか、またはVBAプロジェクトがリセットされるまで有効です。
標準モジュールの宣言セクション(Public)
標準モジュールの宣言セクションにおいて、Publicを用いて変数宣言した変数を「グローバル変数」といいます。
宣言場所

前述した2つの宣言場所は、フォーム/レポートモジュールのプロシージャ内及び宣言セクションでしたが、こちらは標準モジュールの宣言セクションです。
適用範囲(スコープ)
標準モジュールにPublicで宣言すると、プロジェクト全体(全てのモジュール)から利用できます。
前述「宣言場所」で例示した図を解説すると、標準モジュールの宣言セクションで宣言した変数UserNameについて、モジュール①のプロシージャで文字列アクセス太郎を格納。モジュール②のプロシージャを実行すると、メッセージボックスにアクセス太郎が表示されます。
このように、どのモジュールからでも、変数の値にアクセスすることができます。
有効期間
グローバル変数の値は、プロシージャを抜けても保持され、Accessを終了するか、またはVBAプロジェクトがリセットされるまで有効です。
モジュールレベル変数/グローバル変数の主な使用場面
値を保持し続けるモジュールレベル変数やグローバル変数は、使用に関するメリット/デメリットがあります。ここでは主な使用場面をご紹介します。
主な使用例
| 使用例 | 内容 |
|---|---|
| ログインユーザ情報 | ツール全体で使うユーザーID、ユーザー名、権限レベルなど。 どのフォーム・レポートからでも参照したい場合。 |
| 環境状態の一元管理 | たとえば「現在編集中の顧客ID」や「現在選択されている年度」など、 画面間をまたいで使うもの。 |
| 一時的なキャッシュ | 計算負荷の高いデータを一度取得して、複数のプロシージャで再利用 したい場合。 |
使用しない(プロシージャ内変数を使う)場面
| 例 | 内容 |
|---|---|
| 一時的にしか使わない値 | プロシージャ内で処理が完結する場合。プロシージャ内変数の使用が無難。 |
| 状態が頻繁に変わる値 | 処理の途中で変数が書き換えられやすいため、追跡が難しくバグの原因 になりやすい。 |
| モジュール間で複数人が 開発する場合 | グローバル変数が多いと、誰がどこで使っているか分からなくなり、チーム 開発時に不具合が増える。 |
使用イメージ的には、以下の感覚で区別すると、自然にスコープ管理がしやすくなります
- 「ツール全体の設定や環境」=グローバル/モジュールレベルでOK
- 「処理に一時的に使うだけの値」=プロシージャ内変数
まとめ
今回の記事要点のまとめです
・スコープとは
変数が「どこから参照できるか(使える範囲)」を指す概念。宣言場所と宣言方法によって変わる。
・宣言ステートメントごとの違いDim:一般的な宣言。プロシージャ内ならローカル、モジュール先頭ならモジュールレベルStatic:プロシージャ内で使う宣言で、プロシージャを抜けても値を保持できる。Private:モジュールレベル用。宣言したモジュール内でのみ有効。 Public:標準モジュールの宣言で使う。プロジェクト全体で変数を共有。
・変数の使いどころ:モジュール/グローバル vs ローカル
<使ってよい場面>
ログインユーザ情報、環境設定、共通設定値など、複数モジュールからアクセスする必要がある値に対してはモジュールレベル/グローバル変数が有効。
<避けるべき場面>
単一プロシージャで完結する処理や、途中で値が変わりやすく追跡しにくい変数は、プロシージャ内変数を使うのが安全。グローバル変数を多用すると、どこで値を変更したか追いにくくなり、バグの原因になりやすい。



