Excelのマクロを実行しようとしたとき、いきなり「コンパイルエラー: 変数が定義されていません。」というダイアログが表示されて処理が止まってしまう——このエラーに出会ったことはありませんか?

特に、他の人が作ったファイルを引き継いだときインターネットからコピーしたコードをVBEに貼り付けたときに突然このエラーが出ることが多く、「自分は何も変えていないのに」と戸惑う方が少なくありません。

このエラーは「Option Explicit」というステートメントによって変数の宣言が強制されているモジュールで、宣言されていない変数を使おうとしたときに発生するコンパイルエラーです。発生の仕組みを正しく理解すれば、対処はシンプルです。本記事では、Microsoft公式ドキュメント(Office VBA リファレンス)や信頼性の高い情報をもとに、原因・解決方法・Option Explicitの正しい設定・変数スコープの考え方まで体系的に解説します。

目次

  1. 「変数が定義されていません」コンパイルエラーとは何か
  2. Option Explicitとは何か——その役割と重要性
  3. 原因1:Dimで変数を宣言せずに使っている
  4. 原因2:変数名のスペルミスで未定義の変数が参照される
  5. 原因3:グローバル変数の宣言場所が間違っている
  6. 原因4:スコープを超えた変数の参照
  7. 原因5:Function名と戻り値代入名が異なる
  8. 原因6:Option Explicitのないモジュールから引き継いだコード
  9. 解決方法:変数を正しく宣言する
  10. Option Explicitを自動挿入する設定方法(VBE設定)
  11. 変数のスコープ(有効範囲)完全ガイド
  12. 「Option Explicitを削除すれば解決」は絶対NG
  13. コンパイルエラーと実行時エラーの違い
  14. 解決方法チェックリスト
  15. よくある質問(FAQ)

1. 「変数が定義されていません」コンパイルエラーとは何か

「コンパイルエラー: 変数が定義されていません。」は、変数の宣言を強制しているモジュールで、宣言されていない変数が使われたときにVBAが発生させるコンパイルエラーです。Microsoftの公式ドキュメント(Option Explicit ステートメントのリファレンス)では、「宣言されていない変数名を使用しようとすると、コンパイル時にエラーが発生します。」と明確に定義されています。

このエラーの特徴は2点あります。

  • マクロを実行する前(コンパイル段階)に検出されるため、エラーが発生した変数名が青くハイライトされてVBE上に表示される
  • 発生原因は「変数の未宣言」または「変数名のスペルミス」のいずれかであることがほとんど

また、このエラーが出る大前提としてモジュールの先頭に Option Explicit が記述されていることが必要です。Option Explicitがないモジュールでは、変数を宣言せずに使ってもエラーにはなりません(ただしそれは危険な状態です。詳しくは後述します)。

2. Option Explicitとは何か——その役割と重要性

Option Explicitは、モジュール内のすべての変数を明示的に宣言することを強制するステートメントです。Microsoftの公式ドキュメントでは、「Option Explicit を使用すると、既存の変数の名前を入力する場合の誤入力や、コード内で変数のスコープが明確でない場合の混乱を避けることができます。」と説明されています。

Option Explicitの記述ルールは以下のとおりです。

  • モジュールレベルでのみ使用できる(プロシージャの中には書けない)
  • どのプロシージャよりも前——モジュールの先頭(宣言セクション)に記述する
  • 標準モジュール・クラスモジュール・フォームモジュールそれぞれに個別に記述が必要
  • VBEのデフォルト設定ではオフ(自動挿入されない)
Option Explicit   ' ← モジュールの一番先頭に記述する(これより上には何も書かない)

Sub Sample()
    Dim i As Long
    Dim name As String
    ' ...処理...
End Sub

Option Explicitがない場合に何が起きるか

Option Explicitが書かれていないモジュールでは、宣言されていない変数はすべてVariant型として扱われます。Variant型は数値・文字列・日付など何でも格納できる万能型ですが、スペルミスで全く別の変数名を使ってしまっても、VBAはそれを新しいVariant型の変数として初期値(数値なら0、文字列なら空文字)で自動生成してしまいます。結果として、エラーが出ないのにデータが空だったり、ゼロ除算エラーになるなど、原因の特定が非常に困難なバグが生まれます。

' Option Explicitなしの場合の危険な例
Sub DangerExample()
    ' Option Explicitなし → 変数を宣言しなくても動いてしまう

    Dim fileName As String
    fileName = "売上データ.xlsx"

    ' スペルミス:fileNameをfileNaemと書き間違えた
    ' Option Explicitがないと fileNaem は空文字のVariantとして生成される
    ' エラーは出ないが、処理結果がおかしくなる
    MsgBox "開くファイル: " & fileNaem   ' → 空白が表示される(バグに気づきにくい)
End Sub
Option Explicit  ' これがあれば...

Sub SafeExample()
    Dim fileName As String
    fileName = "売上データ.xlsx"

    ' スペルミス:fileNaemと書き間違えると即コンパイルエラー
    ' → 実行前に気づける
    MsgBox "開くファイル: " & fileNaem   ' コンパイルエラー「変数が定義されていません」
End Sub

3. 原因1:Dimで変数を宣言せずに使っている

最も基本的な原因です。Option Explicitが記述されたモジュールで、Dimなどの宣言ステートメントを使わずにいきなり変数に値を代入したり参照したりすると、このエラーが発生します。

Option Explicit

' NG例:変数を宣言せずに使っている
Sub Sample_NG1()
    result = 10 * 3      ' エラー:変数 result が宣言されていない
    MsgBox result
End Sub
Option Explicit

' OK例:Dimで変数を宣言してから使う
Sub Sample_OK1()
    Dim result As Long   ' 宣言してから使う
    result = 10 * 3
    MsgBox result        ' → 30が表示される
End Sub

主な変数宣言のキーワード一覧

Microsoftの公式ドキュメントでは、Option Explicit が存在するモジュールでは、Dim・Private・Public・ReDim・Static のいずれかを使って変数を宣言する必要があると定義されています。

キーワード使用場所有効範囲(スコープ)値の保持
Dimプロシージャ内 / モジュール先頭プロシージャ内 / モジュール内(Private相当)プロシージャ終了時にリセット
Privateモジュール先頭のみ同一モジュール内のみマクロ実行中は保持
Publicモジュール先頭のみプロジェクト内のすべてのモジュールマクロ実行中は保持
Staticプロシージャ内のみ同一プロシージャ内のみプロシージャを抜けても値を保持し続ける
ReDimプロシージャ内のみ動的配列の再定義に使用ReDimのみでの変数宣言は非推奨

4. 原因2:変数名のスペルミスで未定義の変数が参照される

Option Explicitを正しく使っているにもかかわらずエラーが発生する場合、変数名のスペルミスが原因のことがほとんどです。変数宣言の名前と、実際に使っている場所での名前が1文字でも違えばエラーになります。

Option Explicit

' NG例:宣言と使用でスペルが異なる
Sub Sample_NG2()
    Dim totalCount As Long
    totalCount = 100

    ' 「Count」を「Cont」とミスタイプ
    Debug.Print totalCont  ' コンパイルエラー「変数が定義されていません」
End Sub
Option Explicit

' OK例:宣言と使用の変数名を一致させる
Sub Sample_OK2()
    Dim totalCount As Long
    totalCount = 100
    Debug.Print totalCount  ' 正しい名前 → エラーなし
End Sub

スペルミスを防ぐための実践テクニック

  • Ctrl + Space:VBEの入力補完機能。変数名を途中まで打ち、Ctrl+Spaceを押すと候補が表示される。一覧から選択することでタイプミスを防げる
  • コピー&ペースト:変数名を何度も手入力するのは避け、最初に宣言した変数名をそのままコピーして使う
  • 短すぎる変数名を避ける:「i」「n」「s」のような1文字変数は他の変数と衝突しやすく、スコープを誤って参照するリスクがある。ループカウンタ程度には許容できるが、意味のある名前をつけることでスペルミスも減らせる

5. 原因3:グローバル変数の宣言場所が間違っている

複数のプロシージャで共有する変数(グローバル変数)を宣言する際、宣言の位置がプロシージャの中に入ってしまっているケースがあります。モジュールレベルの変数(Public / Private)は、必ずモジュール先頭の宣言セクション(Option Explicitと最初のSubの間)に記述しなければなりません。

Option Explicit

' NG例:グローバル変数の宣言がプロシージャの中にある
Sub Sample_NG3()
    Private gbStr As String  ' エラー:Privateはプロシージャ内では使えない
    gbStr = "こんにちは"
    MsgBox gbStr
End Sub
Option Explicit

' OK例:グローバル変数はモジュール先頭(宣言セクション)に記述する
Private gbStr As String   ' ← ここに書く(Subよりも上)

Sub Sample_OK3a()
    gbStr = "こんにちは"
    Call Sample_OK3b
End Sub

Sub Sample_OK3b()
    MsgBox gbStr  ' 同一モジュール内ならどのプロシージャからも参照できる
End Sub

6. 原因4:スコープを超えた変数の参照

Microsoftの公式ドキュメント(スコープと可視性について)では、変数のスコープには「プロシージャレベル」「プライベートなモジュールレベル」「パブリックなモジュールレベル」の3種類があると定義されています。スコープ(有効範囲)を超えた場所から変数を参照しようとすると、Option Explicitが有効なモジュールでは「変数が定義されていません」エラーになります。

'=== Module1 ===
Option Explicit

Private m_cnt As Long   ' Module1のみで使えるモジュールレベル変数

Sub Sub_A()
    m_cnt = 10
    Debug.Print m_cnt    ' OK:同じモジュール内なのでアクセス可
End Sub
'=== Module2 ===
Option Explicit

Sub Sub_B()
    ' NG:Module1のPrivate変数 m_cnt には他モジュールからアクセスできない
    Debug.Print m_cnt    ' コンパイルエラー「変数が定義されていません」
End Sub
'=== Module1(修正版) ===
Option Explicit

' 解決方法:プロジェクト全体で使う変数はPublicで宣言する
Public g_cnt As Long   ' 全モジュールから参照可能

Sub Sub_A()
    g_cnt = 10
End Sub
'=== Module2(修正版) ===
Option Explicit

Sub Sub_B()
    Debug.Print g_cnt    ' OK:PublicなのでModule2からも参照できる
End Sub

また、プロシージャ内でDim宣言した変数は、そのプロシージャの中でしか使えません。別のプロシージャから参照しようとしても、「変数が定義されていません」エラーになります。

7. 原因5:Function名と戻り値代入名が異なる

これは見落としやすいパターンです。VBAでFunctionプロシージャを作成するとき、戻り値はFunctionの名前に代入することで返します。この名前を1文字でもミスタイプすると、「変数が定義されていません」エラーになります。

Option Explicit

' NG例:Function名は「CalcTaxIncluded」なのに、戻り値代入は「CalcTaxInclude」(末尾のdが欠落)
Function CalcTaxIncluded(taxExcluded As Long) As Long
    Const TAX_RATE As Long = 10
    CalcTaxInclude = taxExcluded / 100 * (100 + TAX_RATE)  ' コンパイルエラー発生
End Function
Option Explicit

' OK例:Function名と戻り値代入名を一致させる
Function CalcTaxIncluded(taxExcluded As Long) As Long
    Const TAX_RATE As Long = 10
    CalcTaxIncluded = taxExcluded / 100 * (100 + TAX_RATE)  ' 正しい
End Function

Sub TestCalc()
    Dim price As Long
    price = CalcTaxIncluded(1000)
    MsgBox "税込価格: " & price  ' → 1100
End Sub

このケースの厄介な点は、Option Explicitを外すとコンパイルエラーが消えてしまい、代わりに関数の戻り値が常に0(Long型の初期値)になるという点です。Option Explicitがあってこそ、このミスをコンパイル時に検出できます。

8. 原因6:Option Explicitのないモジュールから引き継いだコード

他の人が作成したファイルやインターネットからコピーしたコードを自分のVBAプロジェクトに貼り付けたとき、元のコードにはOption Explicitがなく変数宣言もされていなかったが、貼り付け先のモジュールにはOption Explicitがあるために一気にエラーが発生するケースです。

Option Explicit

' 貼り付け元(Option Explicitなし)で書かれていたコード
' 変数宣言がまったくない状態のまま貼り付けてしまった
Sub PastedCode()
    x = 10           ' エラー:x が宣言されていない
    y = 20           ' エラー:y が宣言されていない
    total = x + y    ' エラー:total が宣言されていない
    MsgBox total
End Sub
Option Explicit

' 修正:Dimで変数を宣言してから使う
Sub PastedCode_Fixed()
    Dim x As Long
    Dim y As Long
    Dim total As Long

    x = 10
    y = 20
    total = x + y
    MsgBox total     ' → 30
End Sub

9. 解決方法:変数を正しく宣言する

エラーが発生したときの対処は明確です。エラーで青くハイライトされた変数名を確認し、適切な場所にDim(またはPrivate・Public・Static)で宣言を追加するだけです。

9-1. 変数宣言の書き方の基本

' 変数宣言の基本構文
' Dim 変数名 As データ型

Dim i         As Long      ' 整数(行番号、カウンタ)
Dim name      As String    ' 文字列
Dim price     As Double    ' 小数を含む数値
Dim flag      As Boolean   ' True / False
Dim ws        As Worksheet ' ワークシートオブジェクト
Dim rng       As Range     ' セル範囲オブジェクト
Dim dt        As Date      ' 日付
Dim v         As Variant   ' 型不明の場合(多用は非推奨)

9-2. 型を省略した宣言(最低限の対応)

「型の選び方がよくわからない」という場合は、型指定なしで Dim 変数名 とだけ宣言しても構いません。型を省略した場合はVariant型として扱われます。まずはエラーを解消してから、後で型を指定していく進め方も有効です。

Option Explicit

Sub Sample_TypeOmit()
    Dim result   ' 型省略 → Variant型として扱われる(とりあえずエラー解消)
    result = 100
    MsgBox result
End Sub

9-3. 複数の変数を1行でまとめて宣言する際の注意

複数の変数を1行にまとめて書くときは、それぞれに As データ型 を記述する必要があります。

' NG例:この書き方だと i のみLong型、j と k はVariant型になる
Dim i, j, k As Long  ' ← 意図した型宣言にならない!

' OK例:すべてにAs Longを付ける
Dim i As Long, j As Long, k As Long

' または1行ずつ書く(最も読みやすい)
Dim i As Long
Dim j As Long
Dim k As Long

10. Option Explicitを自動挿入する設定方法(VBE設定)

毎回手動でOption Explicitを入力するのは手間です。VBEの設定を変更することで、新規モジュールを作成するたびに自動的にOption Explicitが挿入されるようになります。

VBEのデフォルト設定ではこのオプションはオフになっていますが、Excelをインストールしたら真っ先にこの設定をオンにすることが強く推奨されています(複数の専門家も同様に推奨しています)。

設定手順

  • VBE(Visual Basic Editor)を開く(Alt + F11)
  • メニューバーの「ツール」→「オプション」をクリック
  • 「オプション」ダイアログが開いたら「編集」タブを選択
  • 変数の宣言を強制する」チェックボックスをオンにする
  • 「OK」をクリックして設定を保存

設定後に新しいモジュールを挿入(「挿入」→「標準モジュール」)すると、モジュールの先頭に自動的に Option Explicit が追加されます。

注意:この設定は「それ以降に新規作成されるモジュール」に対して有効です。設定変更前に作成済みのモジュールには自動挿入されません。既存のモジュールには手動でOption Explicitを追加してください。

' 設定後、新規モジュールを挿入すると自動でこのように先頭に追加される
Option Explicit

' ここからプロシージャを書き始める
Sub NewMacro()
    ' ...
End Sub

11. 変数のスコープ(有効範囲)完全ガイド

Microsoftの公式ドキュメント(スコープと可視性について)では、スコープの種類として「プロシージャレベル」「プライベートなモジュールレベル」「パブリックなモジュールレベル」の3つを定義しています。「変数が定義されていません」エラーがスコープ起因の場合は、この3種類を理解することが解決の近道です。

11-1. プロシージャレベル(ローカル変数)

Option Explicit

Sub SubA()
    Dim localVar As Long   ' SubAの中でのみ有効
    localVar = 100
End Sub

Sub SubB()
    ' localVar はここでは使えない(SubAのスコープ外)
    ' Option Explicitがあればコンパイルエラーで教えてくれる
    ' Debug.Print localVar  ' → コンパイルエラー
End Sub

11-2. プライベートなモジュールレベル変数

Option Explicit

' モジュール先頭(宣言セクション)に記述
' DimはモジュールレベルではPrivate相当
Private moduleVar As Long
' Dim moduleVar As Long  ← Dimでも同じ意味

Sub SubA()
    moduleVar = 50   ' 同一モジュール内ならOK
End Sub

Sub SubB()
    Debug.Print moduleVar  ' 同一モジュール内ならOK → 50が出力
End Sub

11-3. パブリックなモジュールレベル変数(グローバル変数)

'=== Module1 ===
Option Explicit

' Publicはプロジェクト内すべてのモジュールから参照可
Public globalVar As Long

Sub SetGlobal()
    globalVar = 999
End Sub
'=== Module2 ===
Option Explicit

Sub UseGlobal()
    Debug.Print globalVar  ' Module1のPublic変数を参照できる → 999
End Sub

ただし、公式ドキュメントでも「スコープはできるかぎり狭く設定すべき」という考え方が基本です。必要以上に広いスコープ(特にPublic)を使うと、変数の管理が複雑になり、予期しない値の書き換えが起きやすくなります。

12. 「Option Explicitを削除すれば解決」は絶対NG

ネット上には「Option Explicitを削除すればエラーが消える」という情報が散見されますが、これは絶対に行ってはいけない対処法です。

Option Explicitを削除すると確かにコンパイルエラーは消えます。しかし、根本原因(変数の未宣言やスペルミス)はそのまま残り続けます。スペルミスによって新しいVariant型変数が0や空文字で生成されるため、マクロは「エラーなく」動いているように見えるのに、処理結果が正しくないというはるかに発見が難しい状態になります。

' NG対処:Option Explicitを削除してエラーを"消す"
' Option Explicit ← 削除してしまった

Sub WrongFix()
    Dim totalAmount As Long
    totalAmount = 50000

    ' スペルミス:totalAmountをtotalAmmountと書き間違えた
    ' Option Explicitがないとエラーにならず totalAmmount = 0 として処理される
    If totalAmmount > 30000 Then   ' ← 常にFalse(0 > 30000 → False)
        MsgBox "大口注文です"       ' ← このメッセージは絶対に表示されない
    End If
End Sub

上記のコードはエラーなく動きますが、「大口注文です」のメッセージが絶対に表示されないという致命的なバグを抱えています。Option Explicitがあれば、totalAmmount の段階でコンパイルエラーとなり、即座に気づけます。

「一部のサイトで変数の宣言を強制しないようにすれば良い → Option Explicitを削除しようとあります。これは絶対NGです。その場しのぎになって、後で後悔します。」という警告は、複数の実務VBA開発者からも一致して発せられています。

13. コンパイルエラーと実行時エラーの違い

「コンパイルエラー」と「実行時エラー」は混同されやすいので、ここで整理しておきます。

種類発生タイミング代表例デバッグボタン
コンパイルエラー実行前(コード解析段階)変数が定義されていません、構文エラーなし(エラー行が青くハイライト)
実行時エラー実行中(処理が進んだ後)エラー1004、エラー11、エラー6あり(ダイアログから該当行へジャンプ)

「変数が定義されていません」はコンパイルエラーのため、実行が始まる前に検出されます。エラーダイアログに「デバッグ」ボタンはなく、代わりにVBE上で問題のある変数名が青くハイライトされて表示されます。「OK」ボタンを押すとダイアログが閉じ、ハイライトされた変数名を確認できます。

14. 解決方法チェックリスト

「コンパイルエラー: 変数が定義されていません。」が発生したときに、上から順番に確認してください。

  • エラーダイアログのOKを押し、青くハイライトされた変数名を確認する
  • ハイライトされた変数が、コード内のどこかで Dim(または Public / Private / Static)で宣言されているか確認する
  • 宣言はあるのにエラーが出る場合は、宣言時の変数名と使用時の変数名が1文字も違わず一致しているか確認する(大文字・小文字の違いは問われないが、文字の増減はエラーになる)
  • Function内で戻り値を返す変数名が、Function名と完全に一致しているか確認する
  • グローバル変数(Public / Private)がプロシージャの中ではなく、モジュール先頭の宣言セクションに書かれているか確認する
  • 別のモジュールからPrivate変数やDim変数を参照しようとしていないか確認し、必要ならPublicに変更するか変数をそのモジュール内に移す
  • 他のファイルやネットからコピーしたコードに変数宣言がない場合は、使われているすべての変数にDim宣言を追加する
  • VBEのオプション「変数の宣言を強制する」がオンになっているか確認し、なっていなければオンにする
  • 絶対にOption Explicitを削除して解決しようとしない

15. よくある質問(FAQ)

Q1. 昨日まで動いていたマクロが今日突然「変数が定義されていません」になりました。なぜですか?

最もよくある原因は、コードを編集中に誤って変数宣言の行を削除してしまったか、スペルミスを含む変更を加えてしまったケースです。また、モジュールを別のブックからコピーした際にOption Explicitが追加され、既存の未宣言変数と衝突するケースもあります。Ctrl+Zで直前の操作を取り消して変化点を確認するか、青くハイライトされた変数名の宣言を追加してください。

Q2. Option Explicitはすべてのモジュールに書く必要がありますか?

はい。Option Explicitはモジュールごとに個別に記述する必要があります。標準モジュールAに書いても、標準モジュールBには効力が及びません。クラスモジュール、フォームモジュールも同様です。VBEのオプションで「変数の宣言を強制する」をオンにしておけば、新規作成するモジュールに自動挿入されます。

Q3. 「変数が定義されていません」と「ユーザー定義型は定義されていません」は別物ですか?

はい、別のエラーです。「変数が定義されていません」は通常の変数の未宣言・スペルミスが原因です。「ユーザー定義型は定義されていません」は、Dim reg As RegExp のようにオブジェクト型で宣言した際に、そのオブジェクトが定義されているライブラリへの参照設定がない場合に発生します。こちらはVBEの「ツール」→「参照設定」で必要なライブラリをチェックすることで解決します。

Q4. Variant型の変数を多用すれば「変数が定義されていません」は出なくなりますか?

Dim宣言さえしてあれば、型をVariantにしてもLongにしても「変数が定義されていません」は発生しません。ただし、Variantは型を明示していないため、意図しない型変換や処理速度の低下が起きやすくなります。変数の用途に応じて適切な型を指定することが推奨されています。

Q5. Option Explicitがないファイルをもらったときはどうすればよいですか?

まず全モジュールにOption Explicitを手動で追加し、その後にVBEのメニューから「デバッグ」→「VBAProjectのコンパイル」を実行してください。コンパイルエラーとして未宣言の変数がすべて洗い出されるので、Dimで宣言を追加していきます。一度この作業を行うことで、コード全体の品質が大幅に向上します。

まとめ

「コンパイルエラー: 変数が定義されていません。」は、変数の未宣言またはスペルミスが原因で、Option Explicitによって実行前に検出されるエラーです。Microsoftの公式ドキュメントでも明確に定義されているとおり、このエラーはOption Explicitが正しく機能している証拠であり、むしろ歓迎すべきものです。

対処法は明確で、青くハイライトされた変数名を確認してDimで宣言を追加するか、スペルミスを修正するだけです。「Option Explicitを削除する」というその場しのぎの対処は、より発見が難しいバグを生み出すため絶対に行ってはいけません。

VBEの「変数の宣言を強制する」オプションをオンにしてOption Explicitをすべてのモジュールに自動挿入するよう設定することは、Excelをインストールした直後に行うべきもっとも重要な設定のひとつです。これだけで、スペルミスによるバグ・意図しないゼロ初期化・型エラーなど、VBA開発における多くの落とし穴を事前に塞ぐことができます。