【入門編】VBAの「スコープ」を完全理解:Public, Private, Staticの使い分けで大規模開発を制御する – Excel VBA解析バイブル

スポンサーリンク

こんにちは!Excel VBAの世界へようこそ。
マクロの記録ボタンを押してコードが自動生成されたとき、「すごい魔法みたい!」って感動しましたよね。でも、自分で少しずつコードを書くようになると、こんな壁にぶぶつかりませんか?

  • 「あっちのプロシージャで使った変数のせいで、こっちの計算がおかしくなった…」
  • 「どこで値が書き換わったのか、何千行もあるコードから探すの無理!」
  • 「変数名が被っちゃって、エラーが出るんだけど!」

これ、VBA初心者のあなたが悪いわけではありません。原因は「スコープ(変数の有効範囲)」をコントロールできていないことにあります。

ここをクリアすれば、あなたも「ただ動くコードを書く人」から「意図通りにシステムを制御できるエンジニア」へ一歩を踏み出せます。大丈夫、私が優しく、かつ本質的な部分まで徹底的に解説しますね。

1. スコープ(Scope)ってなに? 隠れ家と公開広場の違い

プログラミングにおける「スコープ」とは、一言でいうと「その変数やプロシージャが、どこから見えて、どこから使えるか」という生存・可視範囲のことです。

Excelの標準モジュールを「街」だと想像してください。
街のど真ん中に大きな掲示板(誰からでも見える変数)を置いたら便利ですが、個人の日記帳(自分だけが見たい変数)をそこに置いたら大変なことになりますよね。

VBAでは、主に次の3つのキーワードを使って、この「公開範囲」を厳密にコントロールします。

1. `Private`(プライベート): 自分のお部屋(モジュール内)だけで使う。外からは見えない。
2. `Public`(パブリック): 街の広場にドーンと置く。ブック全体(すべてのモジュール)からアクセスできる。
3. `Static`(スタティック): プロシージャが終わっても記憶を失わない。秘密の金庫。

それぞれの使い分けを、実務で使えるコードと一緒に見ていきましょう!

2. Private:基本の「キ」にして最強の安全装置

大規模なマクロを作るとき、すべての変数を`Public`にしたり、適当に`Dim`だけで宣言したりするのは、時限爆弾を抱えて歩くようなものです。

基本原則は、「必要最小限の範囲に閉じ込める(カプセル化)」こと。モジュール内でしか使わない変数は、必ず`Private`(またはモジュールレベルの`Dim`)で宣言します。

悪い例:すべてが丸見えのカオス

‘ 標準モジュール「Module1」
Public 顧客名 As String ‘ どこからでも書き換え可能…恐怖!

Sub 処理A()
顧客名 = “株式会社A”
‘ 何千行かのコード…
End Sub

Sub 処理B()
‘ うっかり顧客名を書き換えてしまうバグが発生しやすい
MsgBox 顧客名
End Sub

良い例:お互いに干渉しない安全設計

‘ 標準モジュール「Module1」

‘ モジュールレベル変数(このモジュールの中だけで共有する)
Private ws As Worksheet

Sub 業務データ集計()
‘ このモジュール内でのみ有効な安全な変数
Set ws = ActiveSheet

Call データをきれいにする
Call データを集計する

MsgBox “集計完了しました!”, vbInformation
End Sub

Private Sub データをきれいにする()
‘ wsは上のプロシージャと共有できるが、他のモジュールからは一切触れない
ws.Range(“A1”).Value = “整理済み”
End Sub

Private Sub データを集計する()
‘ ここでも安全にwsを使える
MsgBox ws.Name & ” を集計中…”
End Sub

ここがポイント:
`Private`をつけることで、「この変数はこのファイル(モジュール)のこの仕事でしか使わないよ」とVBAに宣言できます。これにより、他のプログラムからうっかり値を書き換えられるミスを完全防衛できます。

3. Public:全モジュール共有の「諸刃の剣」

「複数のシートや、複数のマクロから、どうしても共有したい設定値がある!」
そんなときに使うのが `Public` です。

ただし、エンジニアの世界では「Public変数はできるだけ使うな」という鉄則があります。なぜなら、どこで値が書き換わったのか追跡するのが非常に難しくなる(スパゲッティコードの原因になる)からです。

どうしても使う場合は、「変更されない定数(Const)」や、「アプリケーション全体で1つだけ保持する設定値」に限定するのがスマートです。

Publicの正しい使い方(定数としての活用)

‘ 標準モジュール「GlobalConfig」
‘ ブック全体で共有する設定
Public Const 会社名 As String = “株式会社テック・フロンティア”
Public Const 限界行数 As Long = 10000

Sub 確認()
‘ どこからでも呼び出せる
MsgBox 会社名 & ” のマクロを実行します。”
End Sub

変数の値をあちこちで書き換えるのではなく、「読むだけ(Read-only)」の状態で`Public`を使うのが、大規模開発を破綻させないプロの技です。

4. Static:記憶喪失にならない不思議な変数

プロシージャ(SubやFunction)の中で宣言した普通の変数は、そのプロシージャが終わった瞬間(`End Sub`の瞬間)、メモリから消去され、記憶を失います。

しかし、`Static`を使って宣言された変数は、プロシージャが終了しても、その値を保持し続けます。

これ、めちゃくちゃ便利ですよ!例えば、「マクロが何回実行されたかを数えるカウンター」を作ってみましょう。

Staticの驚くべき挙動

Sub 実行回数を数える()
‘ 通常の Dim だと、終わるたびにリセットされる
‘ Static なら、前回の記憶を保持する!
Static カウンター As Long

カウンター = カウンター + 1

MsgBox “このマクロは、今回で ” & カウンター & ” 回目の実行です。”, vbInformation
End Sub

このマクロを数回実行してみてください。メッセージボックスの数字が「1、2、3……」と増えていくのが分かります。グローバル変数(Public)を使わなくても、特定のプロシージャの中に「自分だけの記憶装置」を持たせることができるのです。

5. スコープ制御のまとめ(早見表)

ここまでの内容を、開発現場で即座に使えるように整理しておきましょう。

| 宣言キーワード | 有効範囲(見える場所) | 寿命(消えるタイミング) | 主な用途 |
| :— | :— | :— | :— |
| Dim (プロシージャ内) | そのプロシージャ内のみ | プロシージャ終了時 | 一時的な計算、ループのカウンタ |
| Private (モジュール内) | そのモジュール内のみ | ブックを閉じるまで | モジュール内で共有するワークシートや状態管理 |
| Public | ブック全体(全モジュール) | ブックを閉じるまで | 全体で共有する設定値や定数(最小限に!) |
| Static | そのプロシージャ内のみ | ブックを閉じるまで | 状態を保持し続けたいカウンターやキャッシュなど |

先輩エンジニアからのエール

「どのスコープを使えばいいか迷う……」というときは、次の黄金ルールを思い出してください。

> 「できるだけ狭く(PrivateやDim)、どうしても必要なときだけ広く(Public)」

この意識を持つだけで、あなたが書くVBAコードの品質は劇的に向上し、エラーの起きない堅牢なマクロに生まれ変わります。最初は難しく感じるかもしれませんが、意識して書き続ければ自然と手が覚えていきますよ。

ここをクリアしたあなたなら、もう「マクロの記録」を卒業した立派なVBAエンジニアです。
日々の自動化ライフを、もっと楽しく、もっとスマートにしていきましょう!

タイトルとURLをコピーしました