【Excelマクロ】変数のスコープ(使える範囲)を正しく理解しよう

スコープとは? 〜変数の“使える範囲”を知ろう〜

VBAを学び始めたとき、多くの人がなんとなく避けてしまうのが「使える範囲」を認識せずに使っていることです。専門的にいうとスコープと言います。

同じ名前の変数なのに、動き方がまったく変わることがあります。

そもそも「スコープ」ってなに?

スコープ(scope)とは、変数が使える範囲のことです。

たとえば、次のような質問に答えられるでしょうか?

  • その変数、別のプロシージャでも使える?
  • その変数、モジュールをまたいで使える?
  • その変数、マクロの実行が終わった後も残ってる?

こうした疑問に明確に答えるには、「スコープ」の理解が必要です。

スコープの種類と宣言の仕方

VBAでは、変数を宣言する際に使うキーワードとして主に DimStaticPublic があります。それぞれの違いも押さえながら、スコープとの関係を見ていきましょう。

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

この場合、msgTest1 の中だけで使える変数です。
他の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の「スコープ」について基本から実務的な観点まで丁寧に解説してきました。

ポイント

  • スコープとは、変数がどこで使えるかという“使える範囲”のこと
  • DimStaticPublic で変数の使い方と寿命が変わる
  • ローカル→モジュール→パブリックの順にスコープが広くなる
  • スコープを明示的に管理することで、バグが減り、保守性(メンテナンスのしやすさ)が上がる

「変数がどこからどこまで使えるのか」を明確にすることは、信頼できるマクロづくりの土台になります。

まずはローカル変数から、徐々にモジュール変数、必要に応じてパブリック変数へと広げていく構成が、長く使えるコードへの第一歩です。

コメント