VBAの変数バグの多くは「宣言漏れ・型の不一致・初期化忘れ」の3パターンに集約されます。Option Explicit を設定し、型を明示し、使う前に値を確認する習慣をつけるだけで、大半のバグは未然に防げます。
この記事では、次の内容を順番に解説します。
- Option Explicitで宣言漏れ・スペルミスを防ぐ方法
- 型の不一致が原因の不具合と対処法
- 初期化忘れによる誤動作の防ぎ方
- 変数バグを見つけるデバッグの手順
宣言漏れとスペルミスを防ぐには?
VBAはデフォルトでは変数を宣言しなくても動きます。これが「スペルミスに気づかない」という落とし穴になります。
'Option Explicitなし → スペルミスに気づけない
Sub BadExample()
Dim total As Long
total = 100
totla = total + 50 '← "totla"はスペルミスだが新しい変数として処理される
MsgBox totla '→ 50が表示されてしまう(totalの100は無視)
End Sub
Option Explicit をモジュールの先頭に書くと、未宣言の変数を使った時点でコンパイルエラーになります。
Option Explicit 'モジュールの先頭に記述する
Sub GoodExample()
Dim total As Long
total = 100
totla = total + 50 '← コンパイルエラーになるので気づける
End Sub
自動で追加する設定:VBEのメニュー「ツール」→「オプション」→「編集」タブで「変数の宣言を強制する」にチェックを入れると、新しいモジュールを作るたびに自動で Option Explicit が追加されます。
型の不一致による不具合を防ぐには?
変数の型を指定しないと Variant 型になり、どんな値も受け入れてしまいます。計算で使う変数に文字列が入ってもエラーにならず、意図しない結果になることがあります。
'型を指定しない場合の問題
Sub TypeExample()
Dim qty As Variant
qty = "10" '文字列として入っている
MsgBox qty * 2 '→ 20と表示されるが、型が文字列のまま計算されている
MsgBox qty & "個" '→ "10個" と表示される(意図どおり?)
End Sub
型を明示することで、意図しない値が入ったときにすぐエラーとして気づけます。
| よく使う型 | 用途 | 例 |
|---|---|---|
Long | 整数(行番号・件数など) | Dim i As Long |
Double | 小数を含む数値(金額・率など) | Dim rate As Double |
String | 文字列 | Dim name As String |
Boolean | True/Falseの2値 | Dim flg As Boolean |
Date | 日付・時刻 | Dim d As Date |
Variant | 型が不確定なとき(なるべく避ける) | Dim v As Variant |
セルから値を読み込む場合は、IsNumeric・IsDate で事前確認してから型変換します。
Dim qty As Long
If IsNumeric(Cells(2, 1).Value) Then
qty = CLng(Cells(2, 1).Value)
Else
MsgBox "数値を入力してください。", vbExclamation
Exit Sub
End If
初期化忘れによる誤動作を防ぐには?
VBAの変数には宣言直後に型ごとの初期値が自動で入ります。しかしループ内で使う変数や、意図して初期化すべき変数を忘れると、前回の値が残って誤動作の原因になります。
| 型 | VBAの初期値 | 注意が必要な場面 |
|---|---|---|
Long・Integer | 0 | 合計・カウンターの計算 |
Double | 0 | 累積計算 |
String | “”(空文字) | 文字列の連結処理 |
Boolean | False | フラグ管理(意図して初期化を) |
Date | 1899/12/30(シリアル値0) | 日付比較(0と比較される危険あり) |
特にループ内で合計や文字列連結をしている場合、ループに入る前に初期化を明示します。
Sub SumLoop()
Dim i As Long
Dim total As Long
total = 0 '明示的に初期化(0が自動初期値だが意図を示すために書く)
For i = 2 To 10
total = total + Cells(i, 1).Value
Next i
MsgBox "合計:" & total
End Sub
Date型の初期化忘れは特に注意が必要です。
'初期化忘れの危険なコード
Sub DateBug()
Dim t As Date
If t > TimeValue("09:00") Then '← tは0(1899/12/30 00:00)と比較される
MsgBox "遅刻"
End If
End Sub
'正しいコード(値が入っているか確認してから使う)
Sub DateSafe()
Dim t As Date
If Cells(2, 1).Value = "" Then
MsgBox "時間が未入力です。", vbExclamation
Exit Sub
End If
t = CDate(Cells(2, 1).Value)
If t > TimeValue("09:00") Then
MsgBox "遅刻"
Else
MsgBox "定時以内"
End If
End Sub
変数バグを見つけるデバッグの手順を知るには?
変数が原因のバグを見つけるには、変数の中身を確認する方法を使います。
| 方法 | 使い方 | 向いている場面 |
|---|---|---|
| Debug.Print | Debug.Print "total=" & total でイミディエイトウィンドウに出力 | ループ中の変数の変化を追いたいとき |
| MsgBox | MsgBox "total=" & total でポップアップ表示 | 特定の箇所の値を素早く確認したいとき |
| ウォッチウィンドウ | VBEで変数を登録してリアルタイム監視 | どのタイミングで値が変わるか追いたいとき |
| ローカルウィンドウ | VBEメニュー「表示」→「ローカルウィンドウ」で全変数を確認 | どの変数が怪しいか絞れていないとき |
まとめ
Option Explicitをモジュール先頭に書くとスペルミス・宣言漏れをコンパイル時に発見できる- 変数には 型を明示(Long・String・Boolean など)し、Variantは必要な場合だけ使う
- セルから読み込む値は
IsNumeric・IsDateで確認してから型変換する - ループ前や処理開始前に 変数を明示的に初期化する習慣をつける
- 動作がおかしいときはまず変数を疑い、Debug.Print・ウォッチウィンドウで値を確認する
よくある質問
Option Explicitを設定してもスペルミスが検出されません
Option Explicit はモジュールの先頭(一番上の行)に書く必要があります。Subの中に書いても効果がありません。また、既存のモジュールには自動では追加されないため、手動で各モジュールの先頭に記述してください。
Variant型はなぜ避けた方がいいですか?
Variant型はどんな値も受け入れるため、型の不一致でエラーにならず、意図しない計算や文字列操作が起きやすくなります。また型チェックが行われないため、デバッグが難しくなります。型が確定している場合は必ず明示的な型を使いましょう。
CLng・CDate などの型変換関数はいつ使えばいいですか?
セルから読み込んだ値はExcelが判断した型(多くはVariant)で返ってきます。それをVBAの変数に格納するときに型を揃えるために使います。例えば CLng(Cells(1,1).Value) でセルの値をLong型に変換します。変換前に IsNumeric で確認すると安全です。
変数名のタイプミスはOption Explicit以外で防ぐ方法はありますか?
VBEの「自動メンバー表示」(インテリセンス)を活用すると、変数名を途中まで入力すると候補が表示され、タイプミスを減らせます。また変数名を短くしすぎず、意味のある名前(i の代わりに rowIdx など)にすると、スペルミスが起きにくくなります。
バグが再現しない場合はどう調べればいいですか?
再現しないバグの多くは初期化タイミングやデータの状態に依存します。Debug.Print でループ中の変数の変化をすべて記録し、どのデータのときに問題が起きるかを絞り込むのが有効です。また処理の最初に MsgBox TypeName(変数名) で型を確認すると、予期しない型が入っていることを発見できることがあります。
動画で学びたい方へ
「記事を読んでも、実際に自分で書けるか不安…」という方には、動画で基礎からじっくり学べる講座がおすすめです。
VBAが初めての方を前提に、つまずきやすいポイントを先回りして解説しています。サンプル動画は無料でご覧いただけます。



