Static変数とは
VBAで変数を宣言するとき、多くの人がまず覚えるのはDimキーワードです。しかしDimで宣言した変数は、プロシージャ(SubやFunction)の処理が終わるたびに値が破棄されてしまいます。「前回実行したときの値を覚えておきたい」というときに使うのが、Staticキーワードです。
Staticで宣言した変数は、プロシージャの処理が終わっても値を保持し続け、次にそのプロシージャが呼び出されたときに、前回の値からそのまま続きを実行できます。この記事では、Static変数の基本的な仕組みから、実務で役立つ具体的な使用例までを解説します。
Dim変数との違い
まずはDimとStaticの違いを、実際のコードで比較してみましょう。
Sub DimCounter()
Dim cnt As Long
cnt = cnt + 1
Debug.Print cnt
End Sub
このマクロを何度実行しても、結果は常に「1」が表示されます。Dimで宣言した変数cntは、プロシージャが終了するたびに初期化されてしまうためです。
Sub StaticCounter()
Static cnt As Long
cnt = cnt + 1
Debug.Print cnt
End Sub
一方こちらは、Staticに変えただけのコードです。実行するたびに「1」「2」「3」と値が増えていきます。プロシージャが終了してもcntの値が保持され続けるため、次に呼び出されたときに前回の値から処理を続けられるのです。
基本構文
Static変数の宣言方法は、Dimとほとんど同じです。
Static 変数名 As データ型
Dimと同様に、複数の変数をまとめて宣言することもできます。
Static count As Long, total As Double
なお、Staticはプロシージャの中でのみ使用できるキーワードで、モジュールの先頭(宣言セクション)で使うことはできません。
使用例
ボタンを押した回数をカウントする
フォームのボタンやシートのボタンをクリックするたびに回数を数えたい場合、Static変数を使うと非常にシンプルに書けます。
Sub CountButtonClick()
Static clickCount As Long
clickCount = clickCount + 1
MsgBox "このボタンは " & clickCount & " 回クリックされました"
End Sub
グローバル変数(モジュールレベル変数)を使わなくても、プロシージャ単体で「実行回数」を管理できるのがStatic変数の大きなメリットです。
連続実行の状態を保持する
複数シートを順番に処理するようなマクロで、「前回どこまで処理したか」を記憶しておきたい場合にも活用できます。
Sub ProcessNextSheet()
Static currentIndex As Long
If currentIndex > Worksheets.Count - 1 Then
currentIndex = 0
MsgBox "全シートの処理が完了しました"
Exit Sub
End If
Dim ws As Worksheet
Set ws = Worksheets(currentIndex + 1)
MsgBox ws.Name & " を処理します"
' ここに実際の処理を記述する
currentIndex = currentIndex + 1
End Sub
このマクロをボタンに割り当てておけば、クリックするたびに1シートずつ処理を進められます。Static変数がなければ、進捗を保持するためにモジュールレベル変数やセルへの書き込みが必要になりますが、Staticを使うことでプロシージャ内だけで完結します。
初回実行時だけ初期化処理を行う
Static変数はブール型(Boolean)の初期値がFalseであることを利用して、「初回だけ実行したい処理」を制御することもできます。
Sub InitializeOnce()
Static initialized As Boolean
If Not initialized Then
Debug.Print "初回のみ実行される初期化処理です"
initialized = True
End If
Debug.Print "通常の処理です"
End Sub
モジュールレベル変数との違い
「値を保持し続ける」という点では、モジュールの宣言セクションでDimやPublicを使って宣言する「モジュールレベル変数」も同じ役割を果たせます。しかし両者には明確な違いがあります。
| Static変数 | モジュールレベル変数 | |
|---|---|---|
| 宣言場所 | プロシージャの中 | モジュールの宣言セクション |
| アクセス範囲 | 宣言したプロシージャ内のみ | 同じモジュール内の全プロシージャ(Publicなら他モジュールからも) |
| 用途 | そのプロシージャ専用の状態管理 | 複数プロシージャで共有するデータ |
他のプロシージャから値を参照したり書き換えたりする必要がなく、あくまで「そのプロシージャ専用のカウンターや状態」を持たせたい場合は、モジュールレベル変数よりもStatic変数を使う方が、変数のスコープが必要最小限に保たれてコードの見通しがよくなります。
注意点
Static変数の値は、Excelを閉じるかVBAプロジェクトをリセット(実行の中断やコードの編集で自動的に発生する場合あり)すると初期化されます。永続的に保存したい値はセルやファイルに書き込む必要があります。Staticはプロシージャ単位で状態を保持するため、同じ変数名でも別のプロシージャで宣言したStatic変数とは完全に独立しています。- モジュール内の全プロシージャに
Staticを付けるStatic Subという書き方もありますが、これはSub内の全変数をStatic扱いにする指定であり、通常はあまり使われません。
まとめ
Static変数を使うと、プロシージャが終了しても値を保持し続けられるため、クリック回数のカウントや連続処理の進捗管理、初回実行時のみの初期化処理など、状態を持たせたい処理をモジュールレベル変数を使わずシンプルに実装できます。「このプロシージャの中だけで完結する状態を持たせたい」と感じたときは、まずStatic変数の利用を検討してみてください。

コメント