VBAテクニック集 VBA一覧 変数・知識 文法・構文

【VBA】ローカル変数・グローバル変数の違い|スコープを完全理解する徹底ガイド

Excel VBA を学んでいくと、多くの人がつまずくポイントが 「ローカル変数とグローバル変数の違い」 です。変数はプログラムにとって最も重要な要素のひとつですが、「どこで使えるのか(スコープ)」を正しく理解していないと、思わぬバグを生んだり、処理がうまく動かなかったり、値が初期化されたりとさまざまなトラブルが発生します。

特に Excel VBA の実務現場では、複数の Sub や Function を組み合わせた構造のマクロを使うことが多く、変数スコープの理解は必須です。ローカル変数・グローバル変数を正しく使い分けられるようになると、マクロが安定し、保守性が高まり、エラーも大幅に減らせます。

この記事では、初心者から実務者まで役立つように、例・コード・図解的説明・注意点・応用テクニックを交えながら 変数スコープを完全に理解できる内容 を体系的に整理しました。

目次

✅ ローカル変数とは?(Sub/Functionの内部だけで使える変数)

・ローカル変数の基本

ローカル変数とは、宣言したプロシージャ(Sub or Function)の内部でのみ有効な変数 のことです。

Sub Sample()
    Dim x As Long   ' ローカル変数
    x = 10
    Debug.Print x
End Sub

この x「Sample 内だけ」 で使用できます。他の Sub や Function からは参照できません。


・ローカル変数の特徴

  • Sub/Function が終わると自動的に破棄される
  • 同じ名前の変数を別の Sub の中で使っても問題にならない
  • メモリ使用量が少ない
  • 安全性が高い(外部から変更できない)
  • 予期せぬ上書きのリスクが少ない

・実務でのメリット

ローカル変数は「その処理の中だけで必要な値」を扱うため、
実務では基本的にローカル変数が最も安全です。

例:カウンタ、セルの値、行番号、列番号、範囲、ループの値 など。


・ローカル変数の典型例(初心者がよく使うパターン)

Sub CountRows()
    Dim lastRow As Long
    lastRow = Cells(Rows.Count, 1).End(xlUp).Row
    Debug.Print lastRow
End Sub

lastRow はこの Sub 内のみで利用されます。

参考:【VBA】ByVal と ByRef の違いと使い方


❗ ローカル変数でも「Static」を付けると動作が変わる

Static count As Long
count = count + 1
Debug.Print count

Static 変数は Sub を抜けても値が保持されます。

  • 通常のローカル:Sub が終わる → 値が消える
  • Static ローカル:Sub が終わっても値が残る

カウンタや状態管理に使われますが、濫用注意。


✅ グローバル変数(パブリック変数)とは?

・グローバル変数の基本

グローバル変数とは:

  • モジュールの先頭に
  • Public または Global を付けて宣言
  • プロジェクト全体、どの Sub/Function からも参照できる

という非常に強力な変数です。

Public total As Long   ' グローバル変数

すべてのモジュールから参照できます。


・グローバル変数が有効になる範囲(スコープ)

  • Excel ブック(VBAプロジェクト)全体
  • 任意のモジュール
  • 任意のSub・Function

つまり、どこからでもアクセスできてしまいます。


・グローバル変数のメリット

  • 値を複数の Sub で共有できる
  • データの受け渡しが不要(引数無しでOK)
  • 状態管理が容易(フラグ管理など)

・グローバル変数のデメリット

  • 外部から簡単に書き換えられる
  • 値の変化がどこで起きたか追いづらい
  • マクロ全体が複雑になる
  • 名前の競合・予期しない上書きが起きる
  • デバッグが困難になる

特に、大規模化するとバグの温床になります。

参考:【VBA】Variant型とは?便利だが危険な理由と使いどころ|実務で失敗しないための徹底ガイド




❗ 実務でグローバル変数を使うと起こる典型的トラブル

・トラブル①:思わぬSubで値が書き換わる

複数の人が書いたVBAでは頻発。


・トラブル②:同じ名前の変数と干渉

例:ローカル変数と同名だと混乱する。


・トラブル③:値が初期化されて処理が止まる

Excel がクラッシュ → 再計算 → 値が空になる。


・トラブル④:Option Explicitと相性が悪い場合がある

誤って同名のローカルを宣言すると意図しない動作。


✅ 実務での正しい使い分け(最重要)

✔ 原則:ローカル変数を優先する

ほとんどの処理はローカルで完結します。


✔ グローバル変数を使うべき例は非常に少ない

  • 設定値(環境変数)
  • デバッグ中のフラグ
  • ユーザーフォーム間での値共有
  • あるいは「明確な意図」のあるデータ保持

その他はできる限り 引数と戻り値で処理すべき です。


✅ ローカル変数・グローバル変数のコード比較

・良くない例(グローバル依存)

Public count As Long

Sub A()
    count = count + 1
End Sub

Sub B()
    count = count + 1
End Sub

どこから変更されたか分からなくなる。


・良い例(ローカル変数と引数で処理)

Sub Main()
    Dim count As Long
    count = AddOne(count)
    count = AddOne(count)
End Sub

Function AddOne(ByVal i As Long) As Long
    AddOne = i + 1
End Function

処理構造が明確で安全。


❗ スコープを視覚的に理解する(図解イメージ)

  • ローカル変数:箱の中だけ(Subの中)で有効
  • グローバル変数:建物全体(プロジェクト全体)で有効

ローカルは閉じた世界、グローバルは開かれた世界です。


✔ 変数スコープを決めるキーワード一覧

キーワードスコープ説明
Dimプロシージャ内部ローカル変数
Staticプロシージャ内部で保持値が保持される特別なローカル
Privateモジュール内モジュールレベル変数
Publicプロジェクト全体グローバル変数
Globalプロジェクト全体Publicとほぼ同じ(古い用法)

✓ Private変数も理解すべき(中級者向け)

Private x As Long
  • モジュール内だけ
  • ローカルより少し広いスコープ
  • Public より安全

とても便利で実務でも多用されます。


✅ Sub間の値受け渡しは “引数” を使うのが最適

Sub Main()
    Dim total As Long
    total = GetTotal(10, 20)
    Debug.Print total
End Sub

Function GetTotal(a As Long, b As Long) As Long
    GetTotal = a + b
End Function

グローバル変数に頼らなくても、安全にデータを渡せます。


❗ グローバル変数を使わざるを得ないケース

  • 設定情報(ログ保存先、初期ディレクトリ)
  • ユーザーフォームと標準モジュール間の値共有
  • 大規模Excelアプリでの状態管理
  • 他モジュールへの通知(イベント的用途)

ただし、使う場合は 名前ルールの徹底 が必要です。


✔ グローバル変数の命名規則(実務向け)

Public gUserName As String
Public gSettingFolder As String
Public gFlgDebug As Boolean

先頭に「g」を付けると識別しやすいです。


❗ RPA(UiPath/PAD)と連携する場合の注意点

  • 値が意図せずリセットされるとフローが停止
  • Variant/Empty の扱いで誤作動
  • Excelの再計算で値初期化
  • マクロ呼び出し時にスコープが乱れる

RPA連携では ローカル変数+引数 にすることが推奨です。


✔ ChatGPT でマクロ作成する場合も注意

AI が書くコードはよく:

  • グローバル変数を多用
  • Dim を省略
  • 変数スコープを明示しない

という問題があります。

記事を読んだ読者は、
「AIが作成したコードの改善ポイント」も理解できるようになります。


🧪 実務でよくあるスコープミス例と改善版

▼誤った例

Public lastRow As Long

Sub A()
    lastRow = Cells(Rows.Count, 1).End(xlUp).Row
End Sub

Sub B()
    MsgBox lastRow
End Sub

他の処理で書き換えられると、結果が大きく狂う。


▼改善例

Sub Main()
    Dim lastRow As Long
    lastRow = GetLastRow
    MsgBox lastRow
End Sub

Function GetLastRow() As Long
    GetLastRow = Cells(Rows.Count, 1).End(xlUp).Row
End Function

関数で返す形にすると安全。


🧠 変数スコープを理解するとコードは劇的に改善する

  • マクロが壊れにくくなる
  • 他の人と共同開発しやすくなる
  • 影響範囲が見えるためバグが減る
  • 大規模化に耐えられる

中級者に進む上で避けて通れない知識です。


✅ まとめ:ローカル変数・グローバル変数は“使う場所”が重要

最後にこの記事の内容を整理します。

● ローカル変数

  • Sub/Function 内でのみ有効
  • 最も安全で推奨
  • 基本はすべてローカルで書くべき

● グローバル変数(Public)

  • プロジェクト全体で参照できる
  • 強力だが危険
  • 設定値など限定用途でのみ使用推奨

● 使い分けの原則

  • 基本はローカル
  • 必要な時だけPublic
  • 値の受け渡しは引数が最良
  • Staticは状態保持にのみ使用

スコープを正しく理解すると、
あなたのVBAコードは安全性・再利用性・保守性が一気に向上します。

    -VBAテクニック集, VBA一覧, 変数・知識, 文法・構文