Excelマクロを実行したとき「実行時エラー ‘438’: オブジェクトはこのプロパティまたはメソッドをサポートしていません」というエラーが発生して処理が止まってしまう――このエラーは、存在しないプロパティ名・メソッド名をオブジェクトに対して呼び出したときに発生するVBAの代表的なエラーです。スペルミスや大文字・小文字の違い程度の原因から、ExcelバージョンによるAPIの差異、オブジェクトの型の取り違えまで、原因は幅広くあります。本記事では、エラー438が発生するすべての主要パターンをコード付きで体系的に解説し、その場で使える修正方法と予防策を詳しくお伝えします。


目次


実行時エラー’438’とは何か

エラー438「オブジェクトはこのプロパティまたはメソッドをサポートしていません(Object doesn’t support this property or method)」は、VBAがオブジェクトに対してプロパティの読み書きやメソッドの呼び出しを試みたとき、そのオブジェクトが指定された名前のプロパティ・メソッドを持っていない場合に発生します。

エラー91(Nothingのオブジェクトへのアクセス)とよく混同されますが、エラー438はオブジェクトは存在しているが、呼び出した名前が間違っているという点で明確に異なります。主な発生パターンは次のとおりです。

  • プロパティ名・メソッド名のスペルミスや大文字・小文字の誤り
  • 取得したオブジェクトの型が意図したものと異なる(RangeのつもりがWorksheetになっているなど)
  • 古いコードをそのまま使っているが、Excelのバージョンアップで廃止・変更されたプロパティ
  • ADODBやDAOなどの外部ライブラリで、オブジェクトの種類に応じたメソッドを誤って呼び出している
  • InternetExplorerオブジェクトなどすでに廃止されたオブジェクトを使おうとしている
  • 自作クラスモジュールに定義していないプロパティ・メソッドを外部から呼び出している

エラー438はコンパイル時ではなく実行時に発生するのが特徴です。これは変数を Object 型や Variant 型で宣言している場合、VBAがコンパイル時に型チェックを行わないためです。具体的な型(WorksheetRangeなど)で宣言するほうが、入力補完も効いてエラーを未然に防ぎやすくなります。


原因1:プロパティ名・メソッド名のスペルミス

エラー438の原因として最も多いのが、プロパティ名・メソッド名のスペルミスです。VBAのプロパティ名やメソッド名は英語であるため、日本語母語のユーザーにとって見落としやすく、特に似た名前が複数存在する場合に混乱しやすいです。

エラーが起きるコード例

' よくあるスペルミスの例

' NG:Valueの複数形(Values)はRangeオブジェクトには存在しない
ActiveSheet.Range("A1").Values = "テスト"    ' → エラー438
' OK
ActiveSheet.Range("A1").Value = "テスト"

' NG:Colorの末尾にsを付けてしまう
ActiveSheet.Range("A1").Interior.Colors = RGB(255, 0, 0)   ' → エラー438
' OK
ActiveSheet.Range("A1").Interior.Color = RGB(255, 0, 0)

' NG:AutoFitを誤字
ActiveSheet.Columns("A").AutoFits    ' → エラー438
' OK
ActiveSheet.Columns("A").AutoFit

' NG:EntireRowをEntireRowsと誤記
ActiveSheet.Range("A1").EntireRows.Delete   ' → エラー438
' OK
ActiveSheet.Range("A1").EntireRow.Delete

' NG:UsedRangeをUseRangeと誤記
Dim lastRow As Long
lastRow = ActiveSheet.UseRange.Rows.Count   ' → エラー438
' OK
lastRow = ActiveSheet.UsedRange.Rows.Count

スペルミスを防ぐための3つの対策

  • 変数を具体的な型で宣言するDim ws As Object ではなく Dim ws As Worksheet と宣言するとVBAエディタの入力補完(IntelliSense)が機能し、存在するプロパティ・メソッドだけが一覧表示されます
  • オブジェクトブラウザで確認する:VBAエディタでF2キーを押してオブジェクトブラウザを開き、クラス名とメンバー名を正確に確認します
  • 入力補完を積極的に使う:オブジェクト変数の後にピリオドを入力したとき自動表示されるメンバー一覧から選択することでスペルミスをゼロにできます
' 入力補完が機能する宣言の書き方(推奨)
Dim ws  As Worksheet      ' WorksheetのプロパティがIntelliSenseで表示される
Dim rng As Range          ' RangeのプロパティがIntelliSenseで表示される
Dim wb  As Workbook       ' WorkbookのプロパティがIntelliSenseで表示される

' 入力補完が機能しない宣言(非推奨)
Dim ws  As Object         ' ← Object型ではIntelliSenseが効かない
Dim rng As Variant        ' ← Variant型でもIntelliSenseが効かない

原因2:オブジェクトの型の取り違え

取得したオブジェクトが意図した型と異なる場合、そのオブジェクトが持っていないプロパティ・メソッドを呼び出そうとしてエラー438が発生します。特に ActiveCellSelectionActiveSheet などの「現在の状態に依存するオブジェクト」を使うときに起きやすいです。

エラーが起きるコード例

' Selectionはその時点での選択内容によって型が変わる
' セルを選択しているときはRange型だが、グラフを選択しているとChart型になる
Selection.Value = "テスト"   ' グラフが選択されていると → エラー438

' ActiveSheetはWorksheetとは限らない
' グラフシート(Chart)がアクティブのとき
ActiveSheet.Cells(1, 1).Value = "テスト"   ' → エラー438(ChartにはCellsがない)

' RangeのつもりでWorksheetのメソッドを呼ぼうとしている
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets(1)
ws.Value = "テスト"   ' → エラー438(WorksheetにはValueがない)

修正後のコード(TypeNameで型確認・具体的な参照に変更)

' ========================================
' オブジェクトの型を確認してから処理する
' ========================================
Sub SafeSelectionAccess()

    ' Selectionの型を確認してから処理
    If TypeName(Selection) = "Range" Then
        Selection.Value    = "テスト"
        Selection.Font.Bold = True
    ElseIf TypeName(Selection) = "ChartArea" Or _
           TypeName(Selection) = "Chart" Then
        MsgBox "グラフが選択されています。セルを選択してから実行してください。", vbExclamation
    Else
        MsgBox "想定外の選択状態です。型:" & TypeName(Selection), vbExclamation
    End If

End Sub

' ActiveSheetの型確認
Sub SafeActiveSheetAccess()

    ' WorksheetとChartシートを区別する
    If TypeName(ActiveSheet) = "Worksheet" Then
        Dim ws As Worksheet
        Set ws = ActiveSheet
        ws.Cells(1, 1).Value = "処理済"
    Else
        MsgBox "アクティブシートがワークシートではありません。" & vbCrLf & _
               "型:" & TypeName(ActiveSheet), vbExclamation
    End If

End Sub
' ========================================
' Selectionを使わずに明示的にオブジェクトを指定する(推奨)
' ========================================
Sub ExplicitObjectAccess()

    ' Selectionに依存せず、シートとセルを直接指定する
    Dim ws  As Worksheet
    Dim rng As Range

    Set ws  = ThisWorkbook.Sheets("データ入力")
    Set rng = ws.Range("B2:B50")

    rng.Value      = "処理済"
    rng.Font.Bold  = True
    rng.Interior.Color = RGB(200, 255, 200)

    Set rng = Nothing
    Set ws  = Nothing

End Sub

TypeNameで確認できる主なオブジェクト型

  • "Worksheet":通常のワークシート
  • "Chart":グラフシート(ChartシートはCellsやRangeを持たない)
  • "Range":セル範囲
  • "ChartArea":埋め込みグラフのチャートエリア
  • "Nothing":未設定のオブジェクト変数(→ エラー91の原因)
  • "OLEObject":ActiveXコントロールや埋め込みオブジェクト

原因3:Excelバージョン間の機能差異

古いExcelで作成されたマクロをExcel 2016/2019/2021/Microsoft 365で実行したとき、または逆に新しいAPIを旧バージョンで使おうとしたときにエラー438が発生することがあります。バージョン間でプロパティ名が変更・廃止されたケースが代表例です。

よく問題になるバージョン差異の例

' ----------------------------------------
' 例1:スパークラインは Excel 2010以降のみ
' ----------------------------------------
' Excel 2007以前で実行するとエラー438
ActiveSheet.SparklineGroups.Add Type:=xlSparkLine, _
    SourceData:="B2:M2"
' 対処:バージョン確認を追加する
If Val(Application.Version) >= 14 Then   ' 14 = Excel 2010
    ActiveSheet.SparklineGroups.Add Type:=xlSparkLine, SourceData:="B2:M2"
Else
    MsgBox "スパークラインはExcel 2010以降で使用できます。", vbExclamation
End If

' ----------------------------------------
' 例2:WorksheetFunction.Forecast_ETSは Excel 2016以降
' ----------------------------------------
If Val(Application.Version) >= 16 Then   ' 16 = Excel 2016
    Dim result As Double
    ' Forecast_ETSを使った処理
Else
    MsgBox "この関数はExcel 2016以降で使用できます。", vbExclamation
End If

' ----------------------------------------
' 例3:xlCSVUTF8はExcel 2016以降
' ----------------------------------------
Dim saveFormat As Long
If Val(Application.Version) >= 16 Then
    saveFormat = 62   ' xlCSVUTF8
Else
    saveFormat = 6    ' xlCSV(Shift-JIS)
End If
ActiveWorkbook.SaveAs ThisWorkbook.Path & "\output.csv", saveFormat

Excelのバージョン番号早見表

  • Application.Version"11.0":Excel 2003
  • Application.Version"12.0":Excel 2007
  • Application.Version"14.0":Excel 2010
  • Application.Version"15.0":Excel 2013
  • Application.Version"16.0":Excel 2016 / 2019 / 2021 / Microsoft 365(すべて16.0)
' バージョンを数値で安全に比較するユーティリティ
Function ExcelVersionNumber() As Double
    ExcelVersionNumber = CDbl(Application.Version)
End Function

' 使用例
Sub VersionCheckExample()
    Dim ver As Double
    ver = ExcelVersionNumber()

    Debug.Print "Excelバージョン番号: " & ver

    If ver >= 16 Then
        Debug.Print "Excel 2016以降の機能が使用可能です"
    ElseIf ver >= 14 Then
        Debug.Print "Excel 2010〜2013の機能が使用可能です"
    Else
        Debug.Print "旧バージョンのExcelです"
    End If
End Sub

原因4:ADODBやDAOなどの外部オブジェクトのメソッドミス

データベース操作でよく使われるADODB(ActiveX Data Objects)やDAO(Data Access Objects)では、オブジェクトの種類によって使えるメソッドが厳密に決まっています。ConnectionオブジェクトにRecordsetのメソッドを使うなど、オブジェクトの取り違えが起きるとエラー438が発生します。

エラーが起きるコード例

' ConnectionオブジェクトにRecordset系のメソッドを使おうとするとエラー438
Dim conn As Object
Set conn = CreateObject("ADODB.Connection")
conn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
                        "Data Source=C:\data\sample.accdb;"
conn.Open

' ConnectionにはMoveNextはない(RecordsetのメソッドをConnectionに呼ぼうとしている)
conn.MoveNext   ' → 実行時エラー '438'
' Recordsetを閉じた後にアクセスしようとしてもエラー438になるケースがある
Dim rs As Object
Set rs = CreateObject("ADODB.Recordset")
' ... rs.Open後の処理 ...
rs.Close

rs.MoveFirst   ' → 閉じたRecordsetへのアクセス → エラー438またはエラー3704

修正後のコード(ADODBの正しい実装パターン)

' ========================================
' ADODBの正しい実装パターン
' ========================================
Sub ReadFromAccessDB()

    Dim conn As Object
    Dim rs   As Object
    Dim ws   As Worksheet
    Dim row  As Long

    Set conn = CreateObject("ADODB.Connection")
    Set rs   = CreateObject("ADODB.Recordset")
    Set ws   = ThisWorkbook.Sheets(1)

    On Error GoTo ErrorHandler

    ' Connection を開く
    conn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
                            "Data Source=C:\data\sample.accdb;"
    conn.Open

    ' Recordset を開く(ConnectionとRecordsetは別オブジェクト)
    rs.Open "SELECT * FROM 売上テーブル", conn, 3, 1
    ' 引数: SQL, Connection, CursorType(3=Static), LockType(1=ReadOnly)

    ws.Cells.Clear
    row = 1

    ' フィールド名をヘッダーとして出力
    Dim i As Integer
    For i = 0 To rs.Fields.Count - 1
        ws.Cells(1, i + 1).Value = rs.Fields(i).Name
    Next i
    row = 2

    ' レコードを1件ずつ読み込む
    Do While Not rs.EOF
        For i = 0 To rs.Fields.Count - 1
            ws.Cells(row, i + 1).Value = rs.Fields(i).Value
        Next i
        rs.MoveNext   ' ← MoveNextはRecordsetのメソッド(Connectionではない)
        row = row + 1
    Loop

    MsgBox (row - 2) & " 件のデータを取得しました。", vbInformation
    GoTo CleanUp

ErrorHandler:
    MsgBox "エラーが発生しました。" & vbCrLf & _
           "番号: " & Err.Number & vbCrLf & _
           "内容: " & Err.Description, vbCritical

CleanUp:
    ' 状態を確認してから閉じる
    If Not rs   Is Nothing Then If rs.State   = 1 Then rs.Close
    If Not conn Is Nothing Then If conn.State = 1 Then conn.Close
    Set rs   = Nothing
    Set conn = Nothing
    Set ws   = Nothing

End Sub

ADODBオブジェクトとメソッドの対応早見表

  • ADODB.Connection が持つ主なメソッド:OpenCloseExecuteBeginTransCommitTransRollbackTrans
  • ADODB.Recordset が持つ主なメソッド:OpenCloseMoveFirstMoveLastMoveNextMovePreviousAddNewUpdateDeleteFindFilter
  • ADODB.Command が持つ主なメソッド:ExecuteCreateParameter

原因5:グラフ・図形オブジェクトへのアクセスミス

Excelのグラフ操作では、Chart / ChartObject / ChartArea / PlotArea / Series など似た名前のオブジェクトが階層的に存在します。これらを混同してプロパティ・メソッドを呼び出すとエラー438が発生します。

よくある混同パターン

' ChartObjectとChartの混同
' NG:ChartObjectにはChartTitleプロパティは存在しない
Dim co As ChartObject
Set co = ActiveSheet.ChartObjects(1)
co.ChartTitle.Text = "売上推移"   ' → エラー438

' OK:ChartObjectの.Chartプロパティを経由してChartにアクセスする
co.Chart.HasTitle = True
co.Chart.ChartTitle.Text = "売上推移"
' NG:SeriesCollectionのメソッドをChartに呼ぼうとしている
Dim cht As Chart
Set cht = ActiveSheet.ChartObjects(1).Chart
cht.MarkerStyle = xlMarkerStyleCircle   ' → エラー438(ChartにはMarkerStyleがない)

' OK:Seriesオブジェクトを経由してアクセスする
Dim ser As Series
Set ser = cht.SeriesCollection(1)
ser.MarkerStyle = xlMarkerStyleCircle

グラフ操作の正しいオブジェクト階層

' ========================================
' グラフ操作の正しいオブジェクト階層
' ========================================
Sub SafeChartAccess()

    Dim ws  As Worksheet
    Dim co  As ChartObject    ' シートに埋め込まれたグラフコンテナ
    Dim cht As Chart           ' グラフ本体
    Dim ser As Series          ' データ系列

    Set ws = ThisWorkbook.Sheets(1)

    ' ChartObjectsコレクションからChartObjectを取得
    If ws.ChartObjects.Count = 0 Then
        MsgBox "グラフが存在しません。", vbExclamation
        Exit Sub
    End If

    Set co  = ws.ChartObjects(1)   ' 1番目のグラフコンテナ
    Set cht = co.Chart              ' グラフ本体(ChartオブジェクトはChartObjectの中にある)

    ' グラフタイトルの設定
    cht.HasTitle       = True
    cht.ChartTitle.Text = "月別売上推移"

    ' 軸ラベルの設定
    With cht.Axes(xlCategory)
        .HasTitle      = True
        .AxisTitle.Text = "月"
    End With

    With cht.Axes(xlValue)
        .HasTitle      = True
        .AxisTitle.Text = "売上(万円)"
    End With

    ' 1番目のデータ系列の設定
    Set ser = cht.SeriesCollection(1)
    ser.Name        = "2024年売上"
    ser.MarkerStyle = xlMarkerStyleCircle
    ser.Format.Line.ForeColor.RGB = RGB(0, 112, 192)

    Set ser = Nothing
    Set cht = Nothing
    Set co  = Nothing
    Set ws  = Nothing

    MsgBox "グラフの設定が完了しました。", vbInformation

End Sub

原因6:廃止・変更されたオブジェクト(InternetExplorerなど)

以前は広く使われていたが現在は廃止・動作不能になったオブジェクトを使おうとするとエラー438が発生します。代表例がInternet Explorer(IE)オブジェクトを使ったWebスクレイピングのコードです。IEはWindows 11・Microsoft 365環境では起動すらできなくなっているため、CreateObject("InternetExplorer.Application") が成功したとしても、以降の操作でエラー438が多発します。

廃止されたIEオブジェクトのコードと代替手段

' NG:IEオブジェクトを使った旧来のスクレイピング(現在は動作しない環境が多い)
Dim ie As Object
Set ie = CreateObject("InternetExplorer.Application")
ie.Visible = True
ie.Navigate "https://example.com"

Do While ie.Busy Or ie.ReadyState <> 4
    DoEvents
Loop

' IEが廃止されている場合、以降の操作でエラー438が発生する
Dim doc As Object
Set doc = ie.Document
doc.getElementById("keyword").Value = "検索語"   ' → エラー438の場合あり
' OK:XMLHTTPRequestを使ったHTTPリクエスト(IEが不要)
Sub FetchWebDataWithXHR()

    Dim http    As Object
    Dim url     As String
    Dim resText As String

    url = "https://api.example.com/data"

    Set http = CreateObject("MSXML2.XMLHTTP")

    http.Open "GET", url, False
    http.setRequestHeader "Content-Type", "application/json"
    http.Send

    If http.Status = 200 Then
        resText = http.responseText
        Debug.Print resText
        ' 取得したJSONやHTMLを解析して処理する
    Else
        MsgBox "HTTPリクエストが失敗しました。ステータス: " & http.Status, vbExclamation
    End If

    Set http = Nothing

End Sub
' OK:PowerShellを呼び出してWebスクレイピングを行う代替方法
Sub FetchWithPowerShell()

    Dim cmd     As String
    Dim url     As String
    Dim outFile As String

    url     = "https://example.com"
    outFile = ThisWorkbook.Path & "\response.txt"

    ' PowerShellのInvoke-WebRequestコマンドを使ってHTMLを取得
    cmd = "powershell -Command ""Invoke-WebRequest -Uri '" & url & _
          "' -UseBasicParsing | Select-Object -ExpandProperty Content | " & _
          "Out-File -FilePath '" & outFile & "' -Encoding UTF8"""

    Shell cmd, vbHide
    Application.Wait Now + TimeValue("00:00:05")   ' 完了を待つ

    ' 取得したテキストを読み込んで処理
    If Dir(outFile) <> "" Then
        Dim fileNo  As Integer
        Dim content As String
        fileNo = FreeFile()
        Open outFile For Input As #fileNo
        Dim line As String
        Do While Not EOF(fileNo)
            Line Input #fileNo, line
            content = content & line & vbCrLf
        Loop
        Close #fileNo
        Debug.Print Left(content, 500)   ' 先頭500文字を確認
    End If

End Sub

原因7:自作クラスに存在しないメンバーへのアクセス

クラスモジュールを使って自作クラスを作成している場合、クラスに定義していないプロパティ・メソッドを外部から呼び出すとエラー438が発生します。また、Property Get は定義しているが Property Let を定義し忘れた場合に書き込もうとしてもエラー438になります。

エラーが起きるコード例

' クラスモジュール(clsPerson)の定義
' ---- clsPerson の内容 ----
Private m_Name As String
Private m_Age  As Long

Public Property Get Name() As String
    Name = m_Name
End Property

Public Property Let Name(val As String)
    m_Name = val
End Property

Public Property Get Age() As Long
    Age = m_Age
End Property
' Property Let Age は定義していない(読み取り専用のつもり)
' ---- ここまで ----

' 呼び出し側
Dim p As clsPerson
Set p = New clsPerson

p.Name = "山田太郎"    ' OK(Property Letあり)
p.Age  = 30            ' → エラー438(Property LetがないのでAgeへの書き込みは不可)
Debug.Print p.Email    ' → エラー438(Emailプロパティは定義していない)

修正後のコード

' ========================================
' クラスモジュール(clsPerson)の正しい実装
' ========================================

' ---- clsPerson の内容 ----
Option Explicit

Private m_Name  As String
Private m_Age   As Long
Private m_Email As String

' Name:読み書き可能
Public Property Get Name() As String
    Name = m_Name
End Property
Public Property Let Name(val As String)
    m_Name = val
End Property

' Age:読み取り専用(外部から書き込み不可)
Public Property Get Age() As Long
    Age = m_Age
End Property
' ※ Property Let Ageを定義しないことで意図的に読み取り専用にしている
'    外部からAge = 30 のように書くとエラー438になる(意図どおり)

' Email:読み書き可能
Public Property Get Email() As String
    Email = m_Email
End Property
Public Property Let Email(val As String)
    m_Email = val
End Property

' 初期化メソッド(コンストラクタ代わり)
Public Sub Initialize(name As String, age As Long, _
                      Optional email As String = "")
    m_Name  = name
    m_Age   = age
    m_Email = email
End Sub

' 文字列表現を返すメソッド
Public Function ToString() As String
    ToString = m_Name & "(" & m_Age & "歳)" & _
               IIf(Len(m_Email) > 0, " <" & m_Email & ">", "")
End Function
' ---- ここまで ----

' 呼び出し側
Sub UseClsPerson()

    Dim p As clsPerson
    Set p = New clsPerson

    p.Initialize "山田太郎", 30, "[email protected]"

    Debug.Print p.Name     ' → "山田太郎"
    Debug.Print p.Age      ' → 30(読み取りはOK)
    Debug.Print p.Email    ' → "[email protected]"
    Debug.Print p.ToString ' → "山田太郎(30歳) <[email protected]>"

    ' p.Age = 31  ← コメントアウト:読み取り専用なのでエラー438になる(意図どおり)

    Set p = Nothing

End Sub

オブジェクトブラウザを使った正しいプロパティ・メソッドの調べ方

エラー438を根本から防ぐには、オブジェクトブラウザを活用してオブジェクトが持つプロパティ・メソッドを正確に確認する習慣が重要です。

オブジェクトブラウザの開き方と使い方

  • VBAエディタで F2キー を押す(またはメニューの「表示」→「オブジェクトブラウザ」)
  • 左上のドロップダウンから調べたいライブラリ(例:ExcelADODB)を選択する
  • 左のクラス一覧から調べたいクラス(例:RangeWorksheet)を選択する
  • 右のメンバー一覧に、そのクラスが持つすべてのプロパティ・メソッド・イベントが表示される
  • メンバーを選択すると画面下部に説明・引数・戻り値の型が表示される
' オブジェクトブラウザでの確認例:
' 1. F2キーでオブジェクトブラウザを開く
' 2. ライブラリ選択:「Excel」
' 3. クラス選択:「Range」
' 4. メンバー一覧で「Value」を探すと:
'    Property Value As Variant
'    という定義が確認できる

' 5. 「Values」を検索すると見つからない
'    → 「Value」が正しく「Values」はエラーになることが事前に確認できる

オブジェクトの型をコード内で動的に確認する方法

' ========================================
' オブジェクトの型とメンバーをコード内で確認するデバッグ用プロシージャ
' ========================================
Sub InspectObject(obj As Object)

    If obj Is Nothing Then
        Debug.Print "オブジェクトはNothingです"
        Exit Sub
    End If

    Debug.Print "=============================="
    Debug.Print "TypeName  : " & TypeName(obj)
    Debug.Print "VarType   : " & VarType(obj)

    ' プロパティへのアクセスチェック例
    On Error Resume Next

    Dim testVal As Variant

    ' よく使うプロパティが存在するかを動的に確認
    testVal = CallByName(obj, "Value",   VbGet)
    If Err.Number = 0 Then Debug.Print "Value     : サポートあり"
    Err.Clear

    testVal = CallByName(obj, "Name",    VbGet)
    If Err.Number = 0 Then Debug.Print "Name      : サポートあり"
    Err.Clear

    testVal = CallByName(obj, "Address", VbGet)
    If Err.Number = 0 Then Debug.Print "Address   : サポートあり"
    Err.Clear

    On Error GoTo 0
    Debug.Print "=============================="

End Sub

' 使用例
Sub CheckObjectType()
    InspectObject ActiveSheet.Range("A1")   ' Range型のメンバーを確認
    InspectObject ActiveSheet               ' Worksheet型のメンバーを確認
    InspectObject ActiveSheet.ChartObjects(1)   ' ChartObject型のメンバーを確認
End Sub

デバッグ手順:エラー438の原因を素早く特定する

ステップ1:エラー行でどのオブジェクトの何を呼んでいるかを確認する

エラーダイアログで「デバッグ」ボタンを押してエラー行を特定します。その行で「どのオブジェクト変数に対して」「どのプロパティ・メソッドを」呼んでいるかを確認してください。

ステップ2:イミディエイトウィンドウでTypeNameを確認する

' Ctrl+G でイミディエイトウィンドウを開き、以下を入力してEnter
' ?TypeName(変数名)

' 例:ws変数の型を確認
?TypeName(ws)
' → "Worksheet" なら正しい
' → "Chart"     ならChartシートが取得されている(CellsなどはChartにはない)
' → "Nothing"   ならエラー91が発生するはず

' Selectionの型を確認
?TypeName(Selection)
' → "Range" ならセルが選択されている
' → "ChartArea" などならグラフ系オブジェクトが選択されている

ステップ3:プロパティ名のスペルをオブジェクトブラウザで確認する

エラー行のプロパティ名・メソッド名をF2キーのオブジェクトブラウザで検索してください。見つからない場合はスペルミスか、そのオブジェクト型には存在しないメンバーです。

ステップ4:On Error Resume Nextで438かどうかを絞り込む

' エラー438が特定の行で起きているかを確認するデバッグコード
On Error Resume Next

Dim testResult As Variant
testResult = ActiveSheet.Range("A1").Values   ' 疑わしいコード

If Err.Number = 438 Then
    Debug.Print "エラー438確認:このプロパティはサポートされていません"
    Debug.Print "正しいプロパティ名: Value(Valuesではない)"
    Err.Clear
End If

On Error GoTo 0

エラーハンドリングテンプレート

' ========================================
' エラー438対応エラーハンドリングテンプレート
' ========================================
Sub MainWithError438Handling()

    Dim ws  As Worksheet
    Dim rng As Range

    Application.ScreenUpdating = False
    Application.Calculation    = xlCalculationManual
    Application.EnableEvents   = False

    On Error GoTo ErrorHandler

    ' オブジェクトを具体的な型で宣言・取得することでエラー438を予防する
    Set ws  = ThisWorkbook.Sheets("データ")
    Set rng = ws.Range("A1:A100")

    ' ===== メイン処理 =====
    rng.Value      = "処理済"
    rng.Font.Bold  = True
    ' =====================

    MsgBox "処理完了", vbInformation
    GoTo CleanUp

ErrorHandler:
    Dim msg As String

    Select Case Err.Number
        Case 438
            msg = "プロパティまたはメソッドがサポートされていません(エラー438)。" & vbCrLf & vbCrLf & _
                  "確認してください:" & vbCrLf & _
                  "・プロパティ名・メソッド名のスペルが正しいか(F2でオブジェクトブラウザ確認)" & vbCrLf & _
                  "・取得したオブジェクトの型が意図したものか(TypeNameで確認)" & vbCrLf & _
                  "・Excelバージョンがその機能に対応しているか(Application.Versionで確認)" & vbCrLf & _
                  "・廃止されたオブジェクト(IEなど)を使っていないか"
        Case 91
            msg = "オブジェクト変数が設定されていません(エラー91)。" & vbCrLf & _
                  "Setキーワードでオブジェクトを代入してください。"
        Case 9
            msg = "添字が有効範囲にありません(エラー9)。" & vbCrLf & _
                  "シート名・配列の添字を確認してください。"
        Case 1004
            msg = "Excelオブジェクトへの操作が失敗しました(エラー1004)。"
        Case Else
            msg = "予期しないエラーが発生しました。"
    End Select

    MsgBox msg & vbCrLf & vbCrLf & _
           "エラー番号:" & Err.Number & vbCrLf & _
           "内容:" & Err.Description & vbCrLf & _
           "発生元:" & Err.Source, _
           vbCritical, "実行時エラー " & Err.Number

CleanUp:
    Application.ScreenUpdating = True
    Application.Calculation    = xlCalculationAutomatic
    Application.EnableEvents   = True

    Set rng = Nothing
    Set ws  = Nothing

End Sub

エラー438 原因チェックリスト

エラー438が発生したとき、以下のリストを上から順番に確認してください。

  • エラー行のプロパティ名・メソッド名をF2キーのオブジェクトブラウザで検索して正確に存在することを確認したか
  • 単数形・複数形の違いや末尾の s の有無(Value vs Values、Color vs Colors、Row vs Rowsなど)を確認したか
  • TypeName(変数名) でオブジェクトの型が意図したものになっているかイミディエイトウィンドウで確認したか
  • 変数を Object 型や Variant 型ではなく具体的な型(Worksheet、Range など)で宣言してIntelliSenseを有効にしているか
  • Selection を使っている場合、その時点でセル(Range)が選択されているか、グラフや図形が選択されていないか確認したか
  • ActiveSheet を使っている場合、通常のワークシートがアクティブか、グラフシート(Chart)ではないかを確認したか
  • ChartObjectとChart を混同していないか(ChartTitleなどはChart経由でアクセスする)
  • 使用している機能が現在のExcelバージョンでサポートされているか(Application.Version で確認)
  • IE(InternetExplorer)オブジェクトを使ったコードをそのまま使っていないか(Windows 11・Microsoft 365環境では動作しない)
  • ADODBを使っている場合、ConnectionとRecordsetのメソッドを混同していないか
  • 自作クラスに対して定義していないプロパティ・メソッドを呼び出していないか
  • 読み取り専用プロパティ(Property Let が未定義)に書き込もうとしていない

まとめ

実行時エラー’438’「オブジェクトはこのプロパティまたはメソッドをサポートしていません」は、呼び出したプロパティ名・メソッド名がそのオブジェクトに存在しないときに発生します。エラー91(Nothingへのアクセス)と並んでVBAで最も遭遇しやすいオブジェクト関連エラーです。本記事の要点をまとめると次のとおりです。

  • スペルミス対策:変数を Object ではなく WorksheetRange などの具体的な型で宣言してIntelliSenseを活用する。F2キーのオブジェクトブラウザで正確な名前を確認する
  • オブジェクト型の確認TypeName() でオブジェクトの実際の型を確認し、SelectionActiveSheet などの状態依存オブジェクトは使用前に型チェックを入れる
  • バージョン対応Application.Version でExcelのバージョンを確認し、新機能を使うときはバージョン分岐を入れる
  • グラフ操作:ChartObjectとChartを混同しない。ChartTitle・SeriesなどはChart経由でアクセスする
  • 廃止オブジェクト:IEオブジェクトなど廃止されたオブジェクトはXMLHTTPRequestやPowerShellへの移行を検討する
  • ADODBの使い方:ConnectionとRecordsetのメソッドを正確に区別する。MoveNextなどはRecordsetのメソッド
  • 自作クラス:Property LetとProperty Getの両方を定義しないと書き込み時にエラー438になる

エラー438は、コードを書く時点での型指定と入力補完の活用によって大幅に予防できます。As ObjectAs Variant で宣言する習慣から、具体的な型名で宣言する習慣に切り替えるだけで、エラー438の発生件数を劇的に減らすことができます。