1. はじめに
Excel VBAは導入しやすく、実務でも使用しやすい言語です。
そして比較的ゆるい言語でもあります。
その「ゆるさ」は、
少ない記述で動くという意味では優しさですが、
実務では結果が安定しない不具合を生みやすい原因にもなります。
本記事では、
VBAに慣れ始めたユーザーが使用するグローバル変数の危険性について整理します。
2. グローバル変数とは
VBAでは、標準モジュールの先頭でDimで宣言した変数は、
そのモジュール全体で有効となるグローバル変数として扱われます。
またPublicで宣言された変数はプロジェクト全体で有効となります。
Public gCount As Long
この変数は
- 標準モジュール
- シートモジュール
- ユーザーフォーム
- クラスモジュール
など、どこからでも参照・変更可能です。
3. なぜグローバル変数は使われがちなのか
グローバル変数は、次の理由で使われがちです。
- 引数で渡すのが面倒
- 複数の処理で値を共有したい
- 変数を増やしたくない
Dim gCount As Long
Sub SumpleA()
gCount = 10
End Sub
Sub SumpleB()
MsgBox gCount
End Sub
確かにこのコードは、短く・簡単に動きます。
しかし、問題はここからです。
4. 問題① 値がどこで変わったか分からない
グローバル変数の最大の問題は、値の変更箇所を追いにくいことです。
-
どの プロシージャで変更したのか
-
フォームなのか
-
イベントなのか
コードを見ただけでは分かりません。
結果として、「気づかないうちに値が変わっている」という状態になります。
5. 問題② 初期化タイミングが不明確
グローバル変数が いつ初期化されるかは、コードからは分かりません。
実際には、
- VBAプロジェクトがロードされたとき
- Excelを再起動したとき
- プロジェクトがリセットされたとき
など、ExcelやVBAの状態に依存します。
つまり、「前回の値が残ることもあれば、突然消えることもある」
という不安定な状態になります。
6. 問題③ 実行のたびに結果が変わる可能性
ここが、実務で最も深刻な問題です。
グローバル変数を使うと、同じマクロを実行しても、
実行順や直前の操作によって結果が変わる可能性があります。
具体例
Public Count As Long
Sub Main()
Count = Count + 1
MsgBox Count
End Sub
このコードはエラーで停止することはありませんが、
グローバル変数であるCountが初期化されないため、
実行するたびに表示される値が1ずつ増加するという現象が起こります。
その上、Publicで宣言しているため、別モジュールの影響を受ける可能性もあります。
つまり、過去の実行履歴が、次の実行結果に影響するコードになります。
7. よくある事故パターン
「Excelを再起動したら直った」
「さっきまでは動いていた」
「人によって再現しない」
これらの多くは、VBAプロジェクトがリセットされ、
グローバル変数が初期化されただけ、というケースです。
8 . グローバル変数の活用
実務では、用途を限定すれば使えるケースもありますが、
- 読み取り専用の設定値
- アプリケーション全体で不変の情報
といった「実行中に変わらない値」での使用になるので、
定数(Const/Public Const) の使用が主になるでしょう。
どうしても使用したい場合は、起動時・終了時両方に必ず変数初期化を行い、
使用する領域を意識的に制限する(使いまわしをしない)のが無難です。
Dim IsSuccess As Boolean
Dim Count As Long
Sub Main()
Call Reset_GlobalVariables
Call SubProcess'グローバル変数を使用する処理
Call Reset_GlobalVariables
End Sub
Sub Reset_GlobalVariables()
'変数初期化プロシージャ
IsSuccess = False
Count = 0
End Sub
9 . まとめ
-
グローバル変数は状態を保持する
-
初期化タイミングを制御できない
-
実行順や過去の履歴で結果が変わる
結論として、
- グローバル変数は極力使わない
- 使用するのならば起動 / 終了時に初期化の処理を加え、使用領域を制御する
これが、
Excel VBAを安定して運用するための重要な原則です。