VBAを実行しようとしたとき、「コンパイルエラー: 修飾子が不正です。」というダイアログが表示されて止まってしまう——他のエラーと比べてもエラーメッセージの意味が伝わりにくく、「修飾子って何?」「どこが問題なのかさっぱりわからない」と戸惑う方が多いエラーです。

特に厄介なのが、コードを書いた直後には正常にコンパイルできていたのに、後から変数名を変更したり別のモジュールを追加したりしたタイミングで突然エラーが出るケースです。一見してどこが原因なのかわかりにくいため、解決に時間がかかります。

本記事では、Microsoft公式ドキュメント(Office VBA リファレンス)および信頼性の高い実務ベースの情報をもとに、「修飾子が不正です」の意味・発生する全パターン・正しいオブジェクト参照の書き方を体系的に解説します。

目次

  1. 「修飾子」とは何か——エラーの意味を正確に理解する
  2. コンパイルエラー「修飾子が不正です」の全体像
  3. 原因1:オブジェクト型でない変数にドット演算子でアクセスした
  4. 原因2:String型変数に .Value や .Length などを使った
  5. 原因3:他言語のメソッドをVBAで使った(StartsWith・Splitなど)
  6. 原因4:変数名とモジュール名(またはクラス名)が重複している
  7. 原因5:変数名とVBA組み込み関数名が重複している
  8. 原因6:変数名のスペルミスでスコープ外の識別子を参照している
  9. 原因7:Withブロック内でオブジェクトが誤って参照されている
  10. 原因8:Private変数をスコープ外から修飾子として使っている
  11. 正しいオブジェクト参照の書き方——Set文とAs宣言
  12. ドット演算子(.)が使えるオブジェクトと使えない型の一覧
  13. エラー箇所の特定方法
  14. 解決方法チェックリスト
  15. よくある質問(FAQ)

1. 「修飾子」とは何か——エラーの意味を正確に理解する

このエラーを理解する第一歩は、「修飾子」という言葉の意味を知ることです。VBAにおける「修飾子(クォリファイア)」とは、ドット演算子(.)の左側に置いて、右側のプロパティ・メソッドが「何に対するものか」を示すオブジェクトのことです。

例えば sh.Range("A1") という記述では、shRange プロパティを修飾する修飾子です。

Microsoftの公式ドキュメントでは、このエラーの定義を「修飾子はあいまいさを回避するために使用されます。修飾子によって、現在のスコープ内にあるユーザー定義型のプロジェクト、モジュール、オブジェクト、または変数は識別されません。」と説明しています。

平易に言い換えると、「ドットの左側に書いたものが、プロパティやメソッドを持つオブジェクトとして認識できない」ときにこのエラーが発生します。

「修飾子」と「アクセス修飾子」の違い:同じ「修飾子」という言葉でも、PublicPrivateなどの宣言に使う「アクセス修飾子」とは別物です。このエラーでいう修飾子は、オブジェクト参照の文脈における「ドットの左側のオブジェクト識別子」を指します。

2. コンパイルエラー「修飾子が不正です」の全体像

このエラーは、大きく分けると3つの状況で発生します。

  • 型の不一致:ドット演算子の左側に、オブジェクト型でない変数(String・Long・Integerなど)が来ている
  • 名前の重複・衝突:変数名がモジュール名・クラス名・組み込み関数名と同じ(または大文字小文字のみ異なる)ため、VBAが識別を誤る
  • スコープの問題:修飾子として使おうとした識別子が現在のスコープから見えない場所にある

このエラーはコンパイルエラーのため、マクロを実行する前の解析段階で検出されます。エラーダイアログの「OK」を押すと、問題のある箇所が青くハイライトされた状態でVBEが表示されます。

3. 原因1:オブジェクト型でない変数にドット演算子でアクセスした

このエラーの最も基本的なパターンです。変数をString型やLong型などの値型として宣言しているにもかかわらず、その変数に対してドット演算子(.)でプロパティやメソッドにアクセスしようとした場合に発生します。

Rangeの修飾子であるワークシートオブジェクトが、Stringなどのオブジェクトでない型だった場合、VBAは「そのオブジェクトは不正(Invalid)だ」と判断してエラーを出します。

Option Explicit

' NG例:sh を String型で宣言してドット演算子でアクセスしている
Sub Sample_NG1()
    Dim sh As String
    sh = "Sheet1"          ' シート名の文字列を代入
    sh.Range("A1") = 100   ' コンパイルエラー:sh はStringなのでドット演算子は使えない
End Sub
Option Explicit

' OK例1:Worksheet型で宣言し、Setで代入してからドット演算子を使う
Sub Sample_OK1a()
    Dim sh As Worksheet
    Set sh = Worksheets("Sheet1")  ' Setでオブジェクトを代入
    sh.Range("A1") = 100           ' Worksheet型なのでドット演算子が使える
    Set sh = Nothing               ' 使い終わったら解放
End Sub

' OK例2:シート名を変数から参照するだけなら文字列型でOK(ただしドット演算子は使わない)
Sub Sample_OK1b()
    Dim shName As String
    shName = "Sheet1"
    Worksheets(shName).Range("A1") = 100  ' Worksheetsにシート名文字列を渡して参照
End Sub

このパターンで特に多い具体例をまとめます。

誤った宣言型やろうとした操作正しい宣言型
Dim sh As Stringsh.Range("A1")Dim sh As Worksheet
Dim wb As Stringwb.Worksheets(1)Dim wb As Workbook
Dim rng As Stringrng.Value = 100Dim rng As Range
Dim xFile As StringxFile.Worksheets("sheet1")Dim xFile As Workbook

4. 原因2:String型変数に .Value や .Length などのプロパティを使った

VBAのString型(文字列型)は、他のプログラミング言語のStringオブジェクトとは異なり、プロパティやメソッドを持っていません。したがって、String型の変数に対してドット演算子(.)でプロパティにアクセスしようとするとこのエラーが発生します。

Option Explicit

' NG例:String型変数に .Value を使っている
Function GetFileName(ByVal filePath As String) As String
    Dim pos As Long
    pos = InStr(filePath.Value, "\")   ' コンパイルエラー:String型に.Valueは存在しない
    GetFileName = Mid(filePath, pos + 1)
End Function
Option Explicit

' OK例:String型変数はそのまま関数に渡すだけでよい(ドット演算子不要)
Function GetFileName(ByVal filePath As String) As String
    Dim pos As Long
    pos = InStr(filePath, "\")    ' String変数はそのまま使う
    GetFileName = Mid(filePath, pos + 1)
End Function

セルから取得した値をString型変数に代入した後、その変数に .Value を付けてしまう間違いは非常によく見られます。.ValueRange オブジェクトのプロパティです。文字列変数にはすでに値が代入されているため、.Value は不要です。

Option Explicit

' よくある間違いのパターン
Sub CommonMistake()
    Dim cellText As String
    cellText = Range("A1").Value   ' セルの値をStringに代入 → これは正しい

    ' NG:すでにStringに代入済みなのに .Value を付けてしまう
    If cellText.Value = "完了" Then   ' コンパイルエラー
        MsgBox "完了しています"
    End If
End Sub

Sub CommonMistake_Fixed()
    Dim cellText As String
    cellText = Range("A1").Value

    ' OK:String変数はそのまま使う(.Valueは不要)
    If cellText = "完了" Then
        MsgBox "完了しています"
    End If
End Sub

5. 原因3:他言語のメソッドをVBAで使った(StartsWith・Splitなど)

C#・Java・VB.NETなど他のプログラミング言語の経験がある方が、その言語のメソッド記法をVBAに持ち込んでしまうパターンです。VBAのString型は .StartsWith().Contains() .Length のようなメソッドやプロパティを持っていません。これらをString型変数に対して使うと「修飾子が不正です」エラーになります。

Option Explicit

' NG例:C#やVB.NETのメソッドをVBA String型に使おうとしている
Sub Sample_NG3()
    Dim hoge As String
    hoge = Range("K2").Value

    If hoge.StartsWith("hogehoge") Then   ' コンパイルエラー:VBAに.StartsWithはない
        MsgBox "一致しました"
    End If
End Sub
Option Explicit

' OK例:VBAの組み込み文字列関数で代替する
Sub Sample_OK3()
    Dim hoge As String
    hoge = Range("K2").Value

    ' StartsWith → Left関数 または InStr関数で代替
    If Left(hoge, Len("hogehoge")) = "hogehoge" Then
        MsgBox "先頭が一致しました"
    End If

    ' Contains → InStr関数で代替
    If InStr(hoge, "hogehoge") > 0 Then
        MsgBox "文字列が含まれています"
    End If
End Sub

他言語メソッドとVBAの対応表

他言語のメソッドVBAでの代替方法説明
s.StartsWith("abc")Left(s, 3) = "abc"
InStr(s, "abc") = 1
先頭文字列の一致判定
s.EndsWith("xyz")Right(s, 3) = "xyz"末尾文字列の一致判定
s.Contains("abc")InStr(s, "abc") > 0文字列の含有判定
s.LengthLen(s)文字列の長さ取得
s.ToUpper()UCase(s)大文字変換
s.ToLower()LCase(s)小文字変換
s.Trim()Trim(s)前後のスペース除去(VBAにも同名関数あり)
s.Replace("a","b")Replace(s, "a", "b")文字列置換(VBAにも同名関数あり)
s.Split(",")Split(s, ",")文字列分割(VBAにも同名関数あり)

6. 原因4:変数名とモジュール名(またはクラス名)が重複している

これは非常に気づきにくいパターンです。VBAは大文字・小文字を区別しません。そのため、変数名とモジュール名(または標準モジュール名・クラス名)が同じ名前(大文字小文字だけが異なる場合も含む)になると、VBAがどちらを参照しているか識別できなくなり、このエラーが発生します。

VBEditor上では、変数名とモジュール名が衝突すると自動補正機能によって大文字・小文字がどちらかに統一されてしまい、結果として参照の意図が失われます。

'=== 標準モジュール名:「Test」===
' このモジュールにGetMessage関数が定義されている

Option Explicit

Public Function GetMessage() As String
    GetMessage = "テストメッセージです"
End Function
'=== Module1 ===
Option Explicit

' NG例:変数名「test」とモジュール名「Test」が大文字小文字のみ異なる
Sub Main_NG()
    Dim test As String          ' 変数名が「test」
    test = Test.GetMessage()   ' VBAは test と Test を区別できない → エラー
    '      ↑ここが青くハイライトされる
    MsgBox test
End Sub
'=== Module1(解決策1:変数名を変更する) ===
Option Explicit

Sub Main_OK1()
    Dim testMsg As String        ' 変数名をモジュール名と異なる名前に変更
    testMsg = Test.GetMessage()  ' 「testMsg」と「Test」は別物と認識される
    MsgBox testMsg
End Sub
'=== Module1(解決策2:モジュール名の修飾子を省略する) ===
Option Explicit

Sub Main_OK2()
    Dim test As String
    test = GetMessage()   ' モジュール名「Test.」を省いて直接呼び出す
    MsgBox test
End Sub

同様に、変数名とクラス名が衝突した場合も同じ理由でこのエラーが発生します。クラスモジュールを作成した際も、そのクラス名と同じ変数名を使わないよう注意が必要です。

7. 原因5:変数名とVBA組み込み関数名が重複している

VBAには Log(対数)・Time(現在時刻)・Date(現在日付)・ErrorNow など、短い名前の組み込み関数が多数存在します。これらと同じ名前で変数を宣言すると、変数とVBA組み込み関数名が衝突し、「修飾子が不正です」エラーが発生することがあります。

Option Explicit

' NG例:変数名「Log」がVBA組み込み関数Log()と衝突する
Function Cleansing(ByVal Log As String) As String
    Dim Str As Long
    Str = InStr(Log.Value, "/")   ' Log はString型変数なのに .Value を使っている
    '         ↑コンパイルエラー:Log という識別子が不正な修飾子として認識される
    Cleansing = Mid(Log, Str + 1)
End Function
Option Explicit

' OK例:組み込み関数と衝突しない変数名に変更 + .Value を削除
Function Cleansing(ByVal logStr As String) As String  ' LogをlogStrに変更
    Dim pos As Long
    pos = InStr(logStr, "/")   ' .Valueを削除し、直接文字列変数を渡す
    If logStr = "" Then
        Cleansing = ""
        Exit Function
    End If
    logStr = Mid(logStr, pos + 1)
    logStr = Replace(logStr, ")", "")
    Cleansing = logStr
End Function

使用を避けるべき変数名(VBA組み込み関数・定数と重複するもの)

  • Log(対数関数 Log())
  • Time(現在時刻 Time())
  • Date(現在日付 Date())
  • Now(現在日時 Now())
  • Error(エラー番号 Error())
  • Str(数値→文字列変換 Str())
  • Val(文字列→数値変換 Val())
  • Len(文字列長 Len())
  • Left(左側文字列 Left())
  • Right(右側文字列 Right())
  • Mid(中間文字列 Mid())
  • Array(配列生成 Array())
  • TrueFalse(組み込み定数)
  • NothingEmptyNull(特殊値)

8. 原因6:変数名のスペルミスでスコープ外の識別子を参照している

変数名のスペルミスや変数名の重複なども原因になることがあります。スペルミスによって、宣言した変数とは別の識別子(スコープ外の変数・モジュール名・クラス名など)が参照されてしまい、それがドット演算子の修飾子として機能しないためにエラーになるケースです。

Option Explicit

' NG例:スペルミスで宣言した変数とは別の識別子が参照されている
Sub Sample_NG6()
    Dim wsTarget As Worksheet
    Set wsTarget = Worksheets("売上")

    ' 「wsTarget」を「wsTaret」(gが抜けている)とミスタイプ
    ' Option Explicitがあるため「wsTaret」は未定義変数でコンパイルエラーとなる
    wsTaret.Range("A1").Value = 100   ' コンパイルエラー:wsTaret が未定義
End Sub

Option Explicitが宣言されているときは「変数が定義されていません」エラーになることが多いですが、スペルミスの結果として別の識別子(特にモジュール名やスコープ外の変数名)と一致してしまった場合に「修飾子が不正です」エラーが発生します。

9. 原因7:Withブロック内でオブジェクトが誤って参照されている

Withブロックを使った処理の中で、誤ってWithの対象オブジェクトとは別のオブジェクト変数にドット演算子でアクセスしてしまった場合も、このエラーが発生することがあります。特に変数名が .Name のように、Withの省略形と混同されやすい記述になっているとき注意が必要です。

Option Explicit

' NG例:With内でLong型の変数「番号」に .Value や .Name を使っている
Sub Sample_NG7()
    Dim 番号 As Long
    For 番号 = 1 To 50
        If Cells(番号 + 1, 8) = Cells(6, 3) Then
            Worksheets("原本").Copy After:=Worksheets(Worksheets.Count)
            With ActiveSheet
                .Name = 番号.Value   ' コンパイルエラー:Long型の「番号」に.Valueは使えない
                .Range("B1") = 番号.Value  ' 同様にエラー
            End With
        End If
    Next 番号
End Sub
Option Explicit

' OK例:Long型の変数はそのまま使うか、CStrで文字列変換する
Sub Sample_OK7()
    Dim 番号 As Long
    For 番号 = 1 To 50
        If Cells(番号 + 1, 8) = Cells(6, 3) Then
            Worksheets("原本").Copy After:=Worksheets(Worksheets.Count)
            With ActiveSheet
                .Name = CStr(番号)   ' Long型を文字列に変換してから代入
                .Range("B1") = 番号  ' Long型の値はそのまま代入できる(.Valueは不要)
            End With
        End If
    Next 番号
End Sub

10. 原因8:Private変数をスコープ外から修飾子として使っている

Microsoft公式ドキュメントでも明記されているとおり、「Private モジュール内のユーザー定義型の変数は、そのモジュール内でのみ表示されます。」という制約があります。Privateで宣言した変数(またはユーザー定義型)を別のモジュールから修飾子として参照しようとするとこのエラーが発生します。

'=== Module1 ===
Option Explicit

' ユーザー定義型(Private)
Private Type ProductInfo
    Name As String
    Price As Long
End Type

' Private変数
Private myProduct As ProductInfo
'=== Module2 ===
Option Explicit

' NG例:Module1のPrivateユーザー定義型変数を外部から参照しようとしている
Sub Sample_NG8()
    ' Module1のmyProductはPrivateなのでModule2からは見えない
    Debug.Print Module1.myProduct.Name   ' コンパイルエラー:修飾子が不正
End Sub
' 解決策:Public関数経由でアクセスを提供する
'=== Module1(修正版) ===
Option Explicit

Private Type ProductInfo
    Name As String
    Price As Long
End Type

Private myProduct As ProductInfo

' Publicな関数経由でアクセスを提供する
Public Function GetProductName() As String
    GetProductName = myProduct.Name
End Function

11. 正しいオブジェクト参照の書き方——Set文とAs宣言

「修飾子が不正です」エラーの根本的な予防策は、オブジェクトを扱う変数に正しいオブジェクト型を宣言し、Setステートメントで代入することです。

11-1. Setステートメントの正しい使い方

オブジェクト変数への代入は通常の代入演算子(=)ではなく、Setステートメントを使います。Setを使わずに代入すると「オブジェクトが必要です」などの別のエラーが発生します。

Option Explicit

Sub CorrectObjectRef()
    ' Worksheet型の変数宣言とSet代入
    Dim ws As Worksheet
    Set ws = Worksheets("Sheet1")     ' ← Set を使う
    ws.Range("A1").Value = "テスト"   ' ← ドット演算子が正しく使える

    ' Workbook型の変数宣言とSet代入
    Dim wb As Workbook
    Set wb = Workbooks.Open("C:\data\sales.xlsx")
    Debug.Print wb.Worksheets.Count

    ' Range型の変数宣言とSet代入
    Dim rng As Range
    Set rng = ws.Range("A1:D10")
    rng.Interior.Color = RGB(255, 255, 0)

    ' 使い終わったらNothingで解放(メモリ管理のベストプラクティス)
    Set rng = Nothing
    Set ws = Nothing
End Sub

11-2. 固有型とObject型の使い分け

オブジェクト変数の宣言には「固有型(Worksheet・Workbook・Rangeなど)」と「汎用型(Object)」の2種類があります。固有型を使うほうがVBEの入力補完が効き、コンパイル時に型エラーを検出できるため推奨されています。

Option Explicit

Sub TypeDeclarationComparison()
    ' 推奨:固有型で宣言(入力補完が効く・コンパイル時に型エラーを検出)
    Dim ws1 As Worksheet
    Set ws1 = Worksheets("Sheet1")
    ws1.Range("A1").Value = 100   ' Worksheetのプロパティ・メソッドが補完される

    ' 許容:Object型で宣言(汎用的だが補完が効かない)
    Dim ws2 As Object
    Set ws2 = Worksheets("Sheet1")
    ws2.Range("A1").Value = 100   ' 動くが入力補完なし

    ' NG:String型で宣言してオブジェクト操作しようとする(最も多い間違い)
    ' Dim ws3 As String
    ' Set ws3 = Worksheets("Sheet1")  ' コンパイルエラー:型が一致しません
    ' ws3.Range("A1").Value = 100     ' コンパイルエラー:修飾子が不正です
End Sub

12. ドット演算子(.)が使えるオブジェクトと使えない型の一覧

「修飾子が不正です」エラーを防ぐために、ドット演算子が使えるものと使えないものを正確に把握しておきましょう。

型・識別子の種類ドット演算子の使用代表例
Worksheetオブジェクト使用可ws.Range("A1")
Workbookオブジェクト使用可wb.Worksheets(1)
Rangeオブジェクト使用可rng.Value
Objectオブジェクト使用可(実行時チェック)obj.Name
標準モジュール名使用可(変数との重複に注意)Module1.GetMessage()
ユーザー定義クラス使用可myObj.ProcessData
String型(文字列)使用不可s.Length → エラー
Long・Integer型(整数)使用不可n.Value → エラー
Double・Single型(小数)使用不可d.Value → エラー
Boolean型使用不可flag.Value → エラー
Date型使用不可dt.Year → エラー

13. エラー箇所の特定方法

13-1. OKボタンを押してハイライトを確認する

エラーダイアログの「OK」を押すと、VBE上で問題のある識別子が青くハイライトされます。ハイライトされているのはドット演算子の左側の「修飾子」です。その識別子がどのような型で宣言されているかを確認するのが最初のステップです。

13-2. ハイライトされた変数の型をイミディエイトウィンドウで確認する

' ブレークポイントで停止中にイミディエイトウィンドウで確認
? TypeName(sh)          ' sh の型名を表示("String"/"Worksheet"/"Object"など)
? TypeName(xFile)       ' xFile の型名を確認
? VarType(myVar)        ' 変数の型を数値で確認(8=Object, 2=Integer, 8198=String...)

13-3. 変数の宣言箇所をCtrl+Shift+F2で確認する

ハイライトされた変数名にカーソルを置いて Shift+F2 を押すと、その変数の宣言箇所にジャンプできます。宣言されている型(As ○○の部分)を確認して、オブジェクト型になっているかどうかを確認してください。

13-4. プロジェクト全体をコンパイルして一括確認する

VBEのメニュー「デバッグ」→「VBAProjectのコンパイル」を実行すると、プロジェクト全体のコンパイルエラーを実行前にまとめて確認できます。1つ修正したら再度コンパイルして次のエラーに進む、というサイクルで解消していきます。

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

「コンパイルエラー: 修飾子が不正です。」が発生したとき、上から順番に確認してください。

  • エラーダイアログの「OK」を押し、青くハイライトされた識別子(修飾子)を確認する
  • ハイライトされた識別子の宣言(Dimの行)にカーソルを置いてShift+F2でジャンプし、型(As ○○)を確認する
  • String・Long・Integer・Double・Date・Booleanなど値型で宣言されているなら、正しいオブジェクト型(Worksheet・Workbook・Rangeなど)に変更する
  • オブジェクト型に変更した場合は、代入文が = でなく Set ~ = になっているか確認する
  • String型変数に .Value .Length などのプロパティを付けていないか確認し、付けているなら削除する
  • 他言語(C#・Java・VB.NET)のメソッド(.StartsWith().Contains()など)を使っていないか確認し、VBAの組み込み関数(Left・InStr・Lenなど)に置き換える
  • 変数名がモジュール名・クラス名と重複していないか確認する(大文字小文字の違いのみの場合も重複とみなされる)
  • 変数名がVBA組み込み関数名(Log・Time・Date・Strなど)と重複していないか確認する
  • Withブロック内でLong・Integer型変数などの値型に .Value.Name を付けていないか確認する
  • 別モジュールからPrivate変数・ユーザー定義型を修飾子として参照しようとしていないか確認する
  • VBEメニューの「デバッグ」→「VBAProjectのコンパイル」で全体コンパイルを実行し、残りのエラーを一括確認する

15. よくある質問(FAQ)

Q1. 昨日まで動いていたコードが今日突然「修飾子が不正です」になりました。変数は変えていません。

最も多い原因は、新しいモジュールやクラスを追加したときにその名前が既存の変数名と重複したケースです。VBAは大文字小文字を区別しないため、例えば変数名「test」とモジュール名「Test」が衝突します。追加したモジュール・クラスの名前を確認し、既存の変数名と重複していないかをCtrl+Fで検索してください。

Q2. Workbookを変数に入れようとしているのですが「修飾子が不正です」が出ます。

変数の宣言が Dim xFile As String のようにString型になっていないか確認してください。Workbookオブジェクトを扱う変数は Dim xFile As Workbook と宣言し、Set xFile = Workbooks.Open("ファイルパス") のようにSetで代入します。String型の変数にWorkbookオブジェクトは代入できず、ドット演算子も使えません。

Q3. C#の経験があり、文字列の .Length.StartsWith() をVBAでも使いたいのですが。

VBAのString型はC#のstringクラスとは異なり、プロパティやメソッドを持つオブジェクトではありません。LengthはLen()関数、StartsWithはLeft()またはInStr()関数、ContainsはInStr()関数、ToUpper/ToLowerはUCase()/LCase()関数でそれぞれ代替できます。本記事の「他言語メソッドとVBAの対応表」を参照してください。

Q4. 「修飾子が不正です」と「オブジェクトが必要です」は何が違いますか?

両者はよく似ていますが、発生タイミングが異なります。「修飾子が不正です」はコンパイルエラー(実行前の検出)、「オブジェクトが必要です」は実行時エラー(実行中に値型の変数でドット演算子を使おうとしたときの検出)です。String型変数に対してドット演算子を使っても、Variant型や型宣言なしの変数では実行時まで検出されないため「オブジェクトが必要です(実行時エラー424)」になる場合があります。

Q5. 変数名とモジュール名の重複を防ぐ方法はありますか?

いくつかの命名規則が有効です。変数名にはキャメルケース(例:testMessage)、モジュール名にはパスカルケース(例:TestModule)を使い明確に区別する方法や、変数名にプレフィックス(str_ws_l_など)を付ける方法があります。また、モジュール名には意味のある長めの名前をつける(TestではなくTestHelperMessageUtilなど)ことで変数名との衝突を防ぎやすくなります。

まとめ

「コンパイルエラー: 修飾子が不正です。」は、ドット演算子(.)の左側に置いた識別子(修飾子)がVBAのオブジェクトとして認識されないときに発生するエラーです。Microsoftの公式ドキュメントは「修飾子のスペルをチェックし、対象の識別子が現在のスコープ内に存在することを確認してください。」と解決策を示しています。

実務で特に多い原因は3つです。変数をString型で宣言しているのにオブジェクトとして使おうとしたこと、C#やVB.NETの経験から .StartsWith().Length のようなメソッドをVBAのString型変数に使おうとしたこと、そして変数名とモジュール名(またはクラス名・組み込み関数名)が重複してVBAが識別を誤ったことです。

解決の基本は、エラーでハイライトされた修飾子の型(Dimの宣言)を確認し、適切なオブジェクト型に修正してSetで代入することです。本記事のチェックリストと対応表を活用することで、このエラーに遭遇してもすばやく原因を特定し、修正できるようになるはずです。