スコープとは? 〜変数の“使える範囲”を知ろう〜
VBAを学び始めたとき、多くの人がなんとなく避けてしまうのが「使える範囲」を認識せずに使っていることです。専門的にいうとスコープと言います。
同じ名前の変数なのに、動き方がまったく変わることがあります。
そもそも「スコープ」ってなに?
スコープ(scope)とは、変数が使える範囲のことです。
たとえば、次のような質問に答えられるでしょうか?
- その変数、別のプロシージャでも使える?
- その変数、モジュールをまたいで使える?
- その変数、マクロの実行が終わった後も残ってる?
こうした疑問に明確に答えるには、「スコープ」の理解が必要です。
スコープの種類と宣言の仕方
VBAでは、変数を宣言する際に使うキーワードとして主に Dim
、Static
、Public
があります。それぞれの違いも押さえながら、スコープとの関係を見ていきましょう。
Dim(ディム)とは?
Dim
は最も基本的な宣言方法です。「この変数をここで使いますよ」という意味です。
Dim i As Long
使える範囲(スコープ)は、宣言された場所によって変わります。たとえば、プロシージャ内で宣言すればローカル変数、モジュールの先頭で宣言すればモジュール変数になります。
Static(スタティック)とは?
Static
を使うと、プロシージャ内の変数でも値が保持され続けるようになります。
Static cnt As Long
通常の Dim
変数はプロシージャの実行が終わると値が消えますが、Static
変数は次に実行されたときにも前回の値を保持しています。
Public(パブリック)とは?
Public
を使うと、すべてのモジュール・プロシージャからアクセスできる変数になります。
このような変数のことを「グローバル変数」と呼びます。
グローバル変数とは?
グローバル変数とは、プログラム全体から共通で参照・操作できる変数のことです。
Public total As Long
このように Public
で宣言すれば、どのモジュール、どのSubからでも total
を使えるようになります。
ただし、共通で使えるので、複数の場所から値が変更されてしまうリスクもあるため、慎重に使うべきです。
VBAには、主に3つのスコープがあります。
それぞれの違いを明確にしながら、使い分けを解説します。
1. ローカル変数(プロシージャ内のみ)
Sub Test1()
Dim msg As String
msg = "こんにちは"
MsgBox msg
End Sub
この場合、msg
は Test1
の中だけで使える変数です。
他のSubプロシージャからは使えません。
2. モジュールレベルの変数(モジュール全体)
Dim cnt As Long ' モジュールの先頭で宣言
Sub CountUp()
cnt = cnt + 1
MsgBox cnt
End Sub
Sub ResetCount()
cnt = 0
End Sub
ポイント
- モジュールの先頭で宣言された変数は、同じモジュール内なら複数のSubから使える
- 他のモジュールからは使えない
3. パブリック変数(全体で使える)
Public userName As String ' 標準モジュールの先頭
Sub SetName()
userName = "佐藤"
End Sub
Sub ShowName()
MsgBox userName
End Sub
ポイント
Public
を使えば、他のモジュールでも使える- グローバルに使えるが、誤って上書きされるリスクもある
スコープの違いを体験する
次に、同じ変数名でスコープが異なると何が起きるかを実験してみましょう。
例:ローカルとモジュールレベルの同名変数
Dim result As String ' モジュール先頭
Sub A()
Dim result As String ' ローカル変数
result = "Aの結果"
MsgBox result
End Sub
Sub B()
result = "Bの結果"
MsgBox result
End Sub
解説
A
の中では「ローカルの result」が使われる →"Aの結果"
B
の中では「モジュール変数の result」が使われる →"Bの結果"
このように、スコープが違えば中身もまったく別物になります。
スコープと変数の寿命(ライフサイクル)
スコープと密接に関わるのが、変数の寿命です。
スコープ | 使える場所 | 寿命 |
---|---|---|
ローカル変数 | プロシージャ内 | マクロの実行中だけ |
モジュール変数 | モジュール全体 | マクロが終わるまで |
パブリック変数 | 全プロシージャ・全モジュール | Excelが閉じられるまで |
例:Staticを使うと寿命が変わる
Sub TestStatic()
Static num As Long
num = num + 1
MsgBox num
End Sub
このコードを何度も実行すると、表示される数値が増えていきます。Static
を使うと、プロシージャ内でも「前回の値を保持する」変数になります。
実務でありがちなスコープの落とし穴
ケース1:違うSubで同じ名前を使って意図しない上書き
Public msg As String
Sub Step1()
msg = "準備完了"
End Sub
Sub Step2()
MsgBox msg ' → Step1を実行してないと空のまま
End Sub
グローバル変数に依存した処理は、順番や実行状況によってバグの温床になります。
ケース2:見えない場所で値が変わっていた!
Dim cnt As Long ' モジュール変数
Sub A()
cnt = 1
End Sub
Sub B()
cnt = cnt + 1
End Sub
複数プロシージャで変数が共有されていると、意図せず値が変わることがあります。
スコープを設計するルール
改めて、すぐに実践できる考え方を紹介します。
ルール1:基本は「ローカル変数」
Sub Sample()
Dim txt As String
txt = "Hello"
End Sub
まずは Dim
を使ってその中だけで完結する変数にする。
ルール2:複数のSubで使う場合のみモジュール変数
Dim cnt As Long
Sub A()
cnt = cnt + 1
End Sub
Sub B()
cnt = cnt * 2
End Sub
同じ処理対象で共通した変数が必要なときに使う。
ルール3:Publicはできるだけ避ける
Public flg As Boolean
テスト用や特殊な状況を除き、グローバル変数は混乱の元になります。
特に名前のつけ方に注意。短すぎる名前や一般的すぎるものはNGです。
まとめ
VBAの「スコープ」について基本から実務的な観点まで丁寧に解説してきました。
ポイント
- スコープとは、変数がどこで使えるかという“使える範囲”のこと
Dim
、Static
、Public
で変数の使い方と寿命が変わる- ローカル→モジュール→パブリックの順にスコープが広くなる
- スコープを明示的に管理することで、バグが減り、保守性(メンテナンスのしやすさ)が上がる
「変数がどこからどこまで使えるのか」を明確にすることは、信頼できるマクロづくりの土台になります。
まずはローカル変数から、徐々にモジュール変数、必要に応じてパブリック変数へと広げていく構成が、長く使えるコードへの第一歩です。
コメント