VBA入門
変数の適用範囲(スコープ,Private,Public)

ExcelマクロVBAの基本と応用、エクセルVBAの初級・初心者向け解説
公開日:2013年5月以前 最終更新日:2021-11-16

第108回.変数の適用範囲(スコープ,Private,Public)


変数には、その変数をVBA内で使う事ができる範囲が決められています。
マクロVBAで変数の使える範囲を、適用範囲(スコープ)と言います。


適用範囲とは、宣言した変数を使う事のできる範囲です。
変数を宣言した場所と宣言方法によって、その変数を使える場所が違ってきます。

まずVBAの大きな区分けといいますか、書く場所についてですが、

・シートモジュール ・・・ シート毎に存在します
・ブックモジュール ・・・ ブックで1つだけ
・フォームモジュール ・・・ 作ったフォームの数だけ
・標準モジュール ・・・ 好きなだけ作れます
・クラス

ここでは、クラスの説明は省略します、この段階ではまだ難しいので。

それぞれの中に、

・Subプロシージャー
・Functionプロシージャー

これらが、複数入る事になります。

以下では、標準モジュールを例に説明します。
ブックやシートのモジュールでも、適用範囲(スコープ)は同じ規則になります。


プロシージャーレベル変数 ・・・ プロシージャー内でのみ使用可能

Sub sample1()
  Dim i
  ・・・
End Sub
Sub sample2()
  Dim i
  ・・・
End Sub

この場合、
変数iは、それぞれのプロシージャーの中でのみ有効です。
これが最も良く使われる変数定義になります。
1つのプロシージャーの中では、変数名は重複できません。

引数リストの変数
Sub sub1(arg1, arg2)
  ・・・
End Sub 

このarg1とarg2は、そのプロシージャー内でのみ有効です。
つまり、
Dimで宣言する変数と同じです。
従って、Dimで同じ名前の変数は宣言できません。


モジュールレベル変数 ・・・ モジュール内でのみ使用可能

Dim i
Sub sample1()
  Dim j
  ・・・
End Sub
Sub sample2()
  Dim j
  ・・・
End Sub

このように、モジュールの先頭(最初のSubまたはFunctionより前)に書くと、
モジュール全体で使用できる変数になります。

この先頭の変数宣言する部分は、「宣言セクション」と呼びます。
宣言セクションで宣言した変数は、そのモジュール内のすべてのプロシージャーで使用できます。

このような変数を「モジュールレベル変数」と呼びます。

上記の場合、変数iは、sample1でもsample2でも使用できます。
この、Dim は、Private と書いても同じです。
むしろ、Privateと書くほうが一般的な記述となります。


パブリック変数 ・・・ 全てのモジュールの全てのプロシージャーで使用可能

モジュール先頭に書いた変数でも、
DimやPrivateで宣言した変数は、他のモジュールでは使用できません。
他のモジュールで使用できるようにするためには、

Public i
Sub sample1()
  Dim j
  ・・・
End Sub
Sub sample2()
  Dim j
  ・・・
End Sub

上記のように、Publicで宣言します。
こうする事で、変数iは、他のモジュールでも使用できます。

Dim ・・・ そのモジュールのみ
Private ・・・ そのモジュールのみ
Public ・・・ 全てのモジュール

VBAではあまり言わないようですが、他のプログラミング言語では、
グローバル変数
と言う言い方もします。

モジュールとは
モジュールの種類は以下になります。
・標準モジュール
・ブックモジュール
・シートモジュール
・ユーザーフォーム
・クラスモジュール


変数の適用範囲について簡単にまとめてると

プロシージャー内で宣言した変数と引数は、そのプロシージャー内のみ使用可能
モジュールの先頭でDimまたはPrivateで宣言した変数は、そのモジュール内でのみ使用可能
モジュールの先頭でPublicで宣言した変数は、全てのモジュールで使用可能


定数(Const)の適用範囲について

Constステートメント

[ Public | Private ] 定数名 [ As データ型 ] = 値

PublicおよびPrivateは、宣言セクションでのみ使用できます。
Constの既定はPrivateになります。

プロシージャー内で宣言した定数は、そのプロシージャー内のみ使用可能
モジュールの先頭でPrivateで宣言した定数は、そのモジュール内でのみ使用可能
モジュールの先頭でPublicで宣言した定数は、全てのモジュールで使用可能


変数の重複について

変数の宣言において難しい問題があります。
もし、宣言が重複してしまった場合です。

Dim i
Sub sample1()
  Dim i
  i = 1
  Module1.i = 2
  MsgBox i
  MsgBox Module1.i
End Sub
Sub sample2()
  Dim i
  ・・・
End Sub

上記の、sample1を実行すると、 1 2 の順にメッセージ表示されます。
つまり、何も指定しなければ、自身の中で定義した変数が使われます。

Module1.i
こののように、モジュール名で修飾することで、「モジュールレベル変数」を指定して使う事が出来ます。

上記は、ちょっと極端な例で、説明の為に無理やり書いたものです。
同一モジュール内で、変数が重複するような使い方は、絶対にダメです。
ただ、指定方法はこれが全てです。

複数のモジュールにある「モジュールレベル変数」が重複している場合は、
上記のように、モジュール名で修飾して使います。
ただし、これとて決して良いことでは無く、
「モジュールレベル変数」は、全てのモジュールで一意にしておく事が望ましいです。

もっとも望ましい事を言えば、
「モジュールレベル変数」は、あまり使わないことに越したことはありません。
どうしても、「可読性」も悪く、「堅牢性」も落ちます。
出来る限り、プロシージャーをCallする場合は、引数で渡すようにします。


変数は、極力狭いスコープで使う事が望ましいとされます。

これは、変数の値を変更したことによる影響範囲は、なるべく狭い方が良いという考えです。
いくつものプロシージャーを作り、それぞれをCallしている場合、
意図しない変数の推移となってしまう事を避けるためです。
つまりは、バグを減らす為の工夫になります。

※昨今の論議として少し極端な話があります。
「変数宣言はその変数を使う直前で宣言したほうが良い。」
というものです。

変数のスコープを狭くというのは、何もそういう事ではありません。
変数を使う直前で宣言しておきながら、パプリック変数を多用している事も多々見受けられます。
完全に言葉の意味を勘違いしています。

1,000行もあるプロシージャーなら分かりますが、
たかが数十行のプロシージャーにおいて、3行目に宣言しようが8行目に宣言しようが、
何の違いがありますか?という事です。
そして、そもそも、あまり長いプロシージャーは作らないと言うのが基本です。

もちろん、
使用する直前で宣言することを否定しているわけではなく、それにこだわる必要はなく、
臨機応変に記述して構わないということを申し上げています。
ただし、
組織においてコーディング規約があるのであれば、それに従う事が優先されるのは言うまでもないことです。




同じテーマ「マクロVBA入門」の記事

第105回.Callステートメント

・Callステートメント ・Callステートメントの使用例 ・同じことは2度書かない ・プロシージャーの分割について
第106回.Functionプロシージャー
プログラム(マクロVBA)内で特定の処理を実行し値を返すプロシージャーです。これはつまり、Functionプロシージャーで独自の関数をつくれるということです。Subプロシージャーとの違いは、値を返すか返さないかの違いです。
第107回.プロシージャーの引数
・引数の構文 ・引数の使用例 ・引数について
第108回.変数の適用範囲(スコープ,Private,Public)
第100回.InputBoxメソッド(インプットボックス)
・InputBoxメソッド ・InputBoxメソッドの使用例 ・最後に
第101回.Midステートメント
・Midステートメント ・MidBステートメント ・Midステートメントの使用例 ・Midステートメントの必要性 ・実践での使用例
第102回.Intersectメソッド
・Intersectメソッド ・Intersectの使用例 ・Intersectメソッドの最後に
第103回.UnionメソッドとAreasプロパティ
・Unionメソッド ・Areasプロパティ ・Unionメソッドで連結した結果のRangeオブジェクトの状態について ・Unionメソッドの使用例 ・Unionメソッドの実践例
第104回.GetPhoneticメソッドとSetPhoneticメソッド(フリガナ)
・GetPhoneticメソッド ・GetPhoneticメソッドの使用例 ・SetPhoneticメソッド ・SetPhoneticメソッドの使用例
第109回.列挙型(列挙体)Enum
・Enumステートメント ・列挙型(Enumステートメント)の使用例 ・列挙型(Enumステートメント)の活用について
第110回.ユーザー定義型・構造体(Type)
・Typeステートメントの構文 ・ユーザー定義型の使い方 ・ユーザー定義型の使用例 ・ユーザー定義型の制限 ・最後に


新着記事NEW ・・・新着記事一覧を見る

無効な前方参照か、コンパイルされていない種類への参照です。|エクセル雑感(2024-02-17)
初級脱出10問パック|VBA練習問題(2024-01-24)
累計を求める数式あれこれ|エクセル関数応用(2024-01-22)
複数の文字列を検索して置換するSUBSTITUTE|エクセル入門(2024-01-03)
いくつかの数式の計算中にリソース不足になりました。|エクセル雑感(2023-12-28)
VBAでクリップボードへ文字列を送信・取得する3つの方法|VBA技術解説(2023-12-07)
難しい数式とは何か?|エクセル雑感(2023-12-07)
スピらない スピル数式 スピらせる|エクセル雑感(2023-12-06)
イータ縮小ラムダ(eta reduced lambda)|エクセル入門(2023-11-20)
PIVOTBY関数(縦軸と横軸でグループ化して集計)|エクセル入門(2023-11-19)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.RangeとCellsの使い方|VBA入門
3.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
4.繰り返し処理(For Next)|VBA入門
5.変数宣言のDimとデータ型|VBA入門
6.ブックを閉じる・保存(Close,Save,SaveAs)|VBA入門
7.並べ替え(Sort)|VBA入門
8.条件分岐(IF)|VBA入門
9.マクロとは?VBAとは?VBAでできること|VBA入門
10.セルのクリア(Clear,ClearContents)|VBA入門




このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。



このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
本文下部へ