Excel VBAのエラー438の対処法をお探しですね。
広告
Excel VBA「エラー438」が出たときの原因と対処法を分かりやすく解説
Excel VBAでマクロを実行したときに「実行時エラー438:オブジェクトは、このプロパティまたはメソッドをサポートしていません」と表示されると、どこを直せばいいのか分かりづらくて困りますよね。
このエラーは、単純な入力ミスだけでなく、オブジェクトの種類の違い、Excelのバージョン差、ActiveX設定の問題、自作関数での書き方ミスなど、いろいろな原因で起こります。
この記事では、Excel VBAのエラー438がなぜ起きるのかを、初心者の方にも分かりやすく原因別に整理して説明していきます。
Excel VBA「エラー438」って何?
Excel VBAのエラー438は、簡単に言うと**「そのオブジェクトに対して、指定したプロパティやメソッドは使えませんよ」**という意味です。
VBAでは、Range(セル範囲)、Worksheet(シート)、Workbook(ブック)、Applicationなど、操作する対象を「オブジェクト」として扱います。
そして、それぞれのオブジェクトには、使える操作(「メソッド」)と、状態や値を表す項目(「プロパティ」)が決まっています。
たとえば、セル範囲を表すRangeオブジェクトには「Copy」(コピー)メソッドがありますが、シートを保護する「Protect」メソッドはWorksheetオブジェクト専用です。
このように、見た目には似たような書き方でも、対象のオブジェクトが違えば使える命令も変わってくるんです。
エラー438が分かりにくい理由は、**コードの文法そのものは間違っていなくても発生する**という点にあります。
たとえば「ActiveSheet.Range(“A1”).Protect」のように書くと、VBE(Visual Basic Editor)上では「Protect」の先頭文字が自動的に大文字に変換されることがあります。
そのため「スペルは認識されているから正しいはず」と思いがちですが、実際にはRangeオブジェクトにProtectメソッドは存在しないため、実行するとエラー438になってしまいます。
つまり、このエラーを解決するには、スペルを見るだけでは不十分で、**「どのオブジェクトに対して、どのプロパティ・メソッドを呼び出しているか」**をしっかり確認する必要があります。
また、Microsoftの公式説明でも、すべてのオブジェクトがすべてのプロパティやメソッドをサポートしているわけではないとされています。
これはVBAの基本的な考え方であり、エラー438の中心となる原因です。
コードを書くときは「Cells」「Range」「Worksheet」「Workbook」などを同じように扱ってしまいがちですが、それぞれ役割が異なります。
エラーが出た行を見つけたら、まず**左側にあるオブジェクトが何を指しているのか、そのオブジェクトに右側の命令が本当に存在するのか**を確認することが大切です。
タイプミス・存在しないメソッド・プロパティの指定が原因
エラー438でよくある原因は、メソッド名やプロパティ名の**タイプミス**です。
たとえば、セルをコピーしたいのに「Cells(1, 1).Cppy」と書いてしまうと、VBAは「Cppy」というメソッドを探します。
でも、RangeオブジェクトにCppyというメソッドは存在しないため、「このプロパティまたはメソッドをサポートしていません」と判断されてしまいます。
VBAエディターには入力補完機能がありますが、すべてのミスを事前に防いでくれるわけではありません。
特に、英単語に似た名前や、過去に自分で作ったプロシージャ名と混同している場合は、気づきにくいミスになります。
存在しないメソッドやプロパティを指定した場合も、同じようにエラー438が発生します。
たとえば「ActiveSheet.Range(“A1”).CopyFormat」のように書いても、RangeオブジェクトにCopyFormatという標準メソッドはありません。
また、「Rangeに対してProtectを実行する」「Workbookに対してセルのValueを直接指定する」といったように、**別の種類のオブジェクト専用の機能を間違って使った場合**にも発生します。
このパターンでは、命令名自体はExcel VBAのどこかに存在しているため、初心者ほど原因を見つけにくくなります。
大切なのは、命令名が存在するかどうかだけでなく、**「その命令を今のオブジェクトに対して使えるか」**を確認することです。
たとえば、次のようなコードは、どちらもエラー438の原因になります。
“`vb
Sub Sample438()
Cells(1, 1).Cppy
ActiveSheet.Range(“A1”).Protect
End Sub
“`
1行目は「Copy」のタイプミス、2行目はRangeオブジェクトにWorksheet用のProtectメソッドを使っていることが原因です。
修正する場合は、前者なら「Cells(1, 1).Copy」と書き、後者なら「ActiveSheet.Protect」のように、保護したい対象であるWorksheetオブジェクトに対して実行します。
このように、エラー438では**「スペル」「対象オブジェクト」「使用できるメソッド・プロパティ」の3点をセットで確認**すると、原因を見つけやすくなります。
VBEのオブジェクトブラウザーや入力候補を使うと、対象オブジェクトが持つメンバーを確認できるため、思い込みによる指定ミスを減らせます。
オブジェクトの扱い方やSet忘れが原因になることも
エラー438は、プロパティやメソッドを**書き忘れた場合**にも発生することがあります。
VBAでは、Rangeオブジェクトのように既定のプロパティが働いて、値を省略しても動くケースがあります。
たとえば「Debug.Print Range(“A1”)」と書くと、実際にはRange(“A1”).Valueのように扱われることがあります。
しかし、WorkbookやWorksheetなど、すべてのオブジェクトで同じように省略できるわけではありません。
たとえば、ブック名を表示したいのに「Debug.Print wb」と書くと、Workbookオブジェクトそのものを文字列として出力しようとしてしまい、エラー438の原因になります。
この場合は、**何を取得したいのかを明示する**必要があります。
ブック名なら「wb.Name」、シート名なら「ws.Name」、セルの値なら「Range(“A1”).Value」のように、プロパティまで書くのが基本です。
初心者のうちは、オブジェクト変数をそのままDebug.PrintやMsgBoxに渡してしまうことがありますが、VBAは「オブジェクトそのものを表示したい」のか「名前や値を表示したい」のかを自動で都合よく判断してくれるとは限りません。
そのため、オブジェクトを扱うコードでは、**最後にどのプロパティを参照するのかを明確にする**ことが、エラー438の予防につながります。
自作関数でオブジェクトを返すときの**Set忘れ**も、見落とされやすい原因です。
VBAでは、WorksheetやWorkbook、Rangeなどのオブジェクトを変数や関数の戻り値に代入する場合、通常の値とは異なり「Set」を使います。
たとえば、シート名からWorksheetオブジェクトを返す関数を作る場合、戻り値の型をWorksheetにし、関数内でも「Set 関数名 = 対象オブジェクト」と書く必要があります。
型を明示しなかったり、Setを書き忘れたりすると、オブジェクトではなく値として扱おうとして、エラー438や別の実行時エラーにつながることがあります。
“`vb
Function GetSheetObj(ByVal wsName As String) As Worksheet
Set GetSheetObj = ThisWorkbook.Worksheets(wsName)
End Function
Sub UseSheet()
Dim ws As Worksheet
Set ws = GetSheetObj(“Sheet1”)
Debug.Print ws.Name
End Sub
“`
この例では、戻り値の型を「As Worksheet」と明示し、関数内でも呼び出し側でもSetを使っています。
オブジェクトを扱うときは、**値の代入とはルールが異なる**と覚えておくと、エラー438だけでなく「オブジェクト変数またはWithブロック変数が設定されていません」というエラー91の予防にも役立ちます。
特に、関数を自作して処理を分割しているコードでは、エラーが発生した行だけを見るのではなく、**呼び出し元と関数側の両方を確認する**ことが大切です。
Excelのバージョン差・ActiveX設定・参照設定も要チェック
コード自体に問題がないように見えても、**Excelのバージョン差**によってエラー438が発生することがあります。
たとえば、Microsoft 365やExcel 2024以降で追加された新しいワークシート関数を、Excel 2021以前の環境でVBAから呼び出すと、その関数が存在しないためエラーになる場合があります。
「自分のパソコンでは動いたのに、別の人の環境では動かない」というケースでは、このバージョン差を疑う必要があります。
特に、WorksheetFunction経由で新しい関数を呼び出している場合は、対象ユーザーのExcelでその関数が利用できるかを事前に確認しておくべきです。
たとえば、TextSplit関数のように比較的新しいExcelで使える関数は、古いExcelでは利用できないことがあります。
この場合、コードのスペルが正しくても、実行環境側にそのプロパティやメソッドが存在しないため、エラー438につながります。
業務用マクロを配布する場合は、開発環境だけでなく、**利用者のOfficeバージョン、32bit/64bitの違い、更新状況**も確認しておくと安全です。
どうしても新しい関数を使いたい場合は、代替処理を用意したり、On Errorで想定されるエラーを捕捉したりして、古い環境でも処理が止まらない設計にすることが重要です。
また、**ActiveXコントロール**を使っているブックやアドインでは、セキュリティ設定の変更が原因になることもあります。
Windows UpdateやOfficeの更新後に、ExcelのトラストセンターでActiveXの扱いが変更され、これまで動いていたマクロやソフトがエラー438を出すケースがあります。
特に、フォーム上のボタン、コンボボックス、チェックボックスなどのActiveXコントロールを操作している場合は、コードだけでなくExcel側の設定も確認してください。
Excelの「ファイル」から「オプション」→「トラストセンター」→「トラストセンターの設定」→「ActiveXの設定」へ進み、ActiveXが完全に無効化されていないかを確認することが有効です。
ただし、セキュリティを下げればよいという意味ではないため、組織のポリシーや信頼できるファイルかどうかを確認したうえで設定する必要があります。
さらに、クラスモジュールや外部ライブラリを使っている場合は、**参照設定やバインディング方式**も原因になります。
Object型やVariant型で宣言して実行時にメンバーを探す方法を「遅延バインディング」と呼びますが、Friendプロシージャのようにコンパイル時に名前が分かっている必要があるものは、遅延バインディングでは呼び出せません。
このケースは一般的なExcel作業では多くありませんが、アドイン、クラス設計、外部プロジェクト連携をしている場合には確認すべき要素です。
参照設定が外れている、ライブラリのバージョンが違う、同名のメソッドが別のオブジェクトを指しているといった状況でも、想定外のオブジェクトに対して命令を実行し、結果としてエラー438が起きることがあります。
エラー438を早く解決するコツ
エラー438の原因を早く見つけるには、**発生行で止めて、左側のオブジェクトが何型なのかを確認する**のが基本です。
VBEのローカルウィンドウ、ウォッチウィンドウ、イミディエイトウィンドウを使えば、変数が実際に何を参照しているかを確認できます。
また、**Option Explicit**をモジュール先頭に書いて変数宣言を必須にすると、タイプミスによる別変数の作成を防ぎやすくなります。
最後に、開発環境と実行環境が異なるマクロでは、Excelのバージョン、ActiveX設定、参照設定、使用関数の互換性をテストしてから配布することが重要です。
エラー438は「VBAが壊れた」というより、**「対象と命令の組み合わせが合っていない」**ことを知らせるエラーです。
その視点でコードと環境を順番に確認すれば、原因を効率よく特定できますよ。
広告
