Excel VBAの「実行時エラー 9: インデックスが範囲にありません」の修正方法

初級📊 Microsoft Excel2026-04-11| Microsoft Excel (Office 365, 2021, 2019, 2016) - Windows または macOS

Error Message

Run-time error '9': Subscript out of range
#excel#vba#トラブルシューティング#コーディングのヒント

クイック解決策

**実行時エラー '9'**は、VBAが「言いたいことは分かりますが、コレクション内に見つかりません」と伝えていると考えてください。通常、存在しないワークシート、ワークブック、または配列要素にアクセスしようとしたときに発生します。

  • シート名の確認: Sheets("Data") がタブ名と完全に一致しているか確認してください。"Data " のように末尾にスペースが1つあるだけでも、このエラーが発生します。
  • ワークブックの状態を確認: ファイルが開いていることを確認してください。ファイルがハードドライブに保存されたまま開かれていない場合、VBAは Workbooks("Report.xlsx") を参照できません。
  • 配列の境界を検証: 5つの項目しかないリストに対してループを1から10まで回すと、6番目の項目でコードがクラッシュします。

このエラーが発生する理由

VBAは非常に厳密です。意図を推測することはせず、完全に一致するものを探します。このクラッシュの原因の約95%を占める3つのシナリオを紹介します。

1. 見えないスペースの罠

入力ミスが最も一般的な原因です。コードで Sheets("Invoices") を参照していても、ユーザーが誤ってタブ名を "Invoices "(末尾にスペースあり)に変更してしまった場合、マクロは失敗します。これは、SAPやOracleなどの外部ソフトウェアからデータをコピーした際の隠し文字でも発生します。

2. 閉じているワークブックの参照

VBAの Workbooks() コレクションには、現在アクティブな Excel インスタンスで開かれているファイルのみが含まれます。ファイルが閉じている状態で Workbooks("Q4_Results.csv") からデータを取得しようとすると、エラー 9 が表示されます。名前で参照する前に、まず Workbooks.Open を使用してファイルを開く必要があります。

3. 配列インデックスのミス

デフォルトでは、VBAの配列はインデックス 0 から始まります。Dim MyList(5) と宣言すると、実際には6つのスロット(0から5)が作成されます。しかし、多くの開発者は1から始まると想定してしまいます。MyList(10) にアクセスしようとすると、その変数に割り当てられたメモリ範囲外に踏み出すことになります。

修正方法

方法 1: シートのオブジェクト名(CodeName)を使用する(推奨)

ユーザーが変更可能なタブ名に頼るのはやめましょう。VBA プロジェクトエクスプローラーには Sheet1 (Sales) のように表示されます。この Sheet1 が**オブジェクト名(CodeName)**です。これをコード内で直接使用してください。誰かがタブ名を「Sales」から「Old Sales」に変更しても、コードが壊れることはありません。

' 脆弱: タブ名が変更されると壊れる
Sheets("Sales").Range("A1").Value = 100

' 堅牢: タブ名に関係なく動作する
Sheet1.Range("A1").Value = 100

方法 2: 安全なワークブック参照

ファイルが開いていると決めつけないでください。簡単なオブジェクトチェックを使用して、マクロのクラッシュを防ぎます。コードが保存されているのと同じファイル内で作業する場合は、ファイル名の代わりに ThisWorkbook を使用してください。

Dim wb As Workbook
On Error Resume Next
Set wb = Workbooks("Data_Source.xlsx")
On Error GoTo 0

If wb Is Nothing Then
    MsgBox "エラー: Data_Source.xlsx が開かれていません。", vbCritical
    Exit Sub
End If

方法 3: 動的な配列境界

For i = 1 To 10 のような数値をハードコーディングするのは避けましょう。代わりに LBound 関数と UBound 関数を使用します。これらは配列の開始と終了を自動的に検出するため、コードに柔軟性が生まれます。

Dim prices As Variant
prices = Range("A1:A50").Value ' 2次元配列を作成

Dim i As Long
' このループは範囲のサイズに安全に適応します
For i = LBound(prices, 1) To UBound(prices, 1)
    Debug.Print prices(i, 1)
Next i

修正の確認方法

エラーが発生したら、[デバッグ] ボタンをクリックしてください。黄色いハイライト行は、VBAが見つけられなかったオブジェクトを正確に指し示しています。イミディエイト ウィンドウ (Ctrl+G) を使用してオブジェクトをテストします。?Sheets("YourName").Name と入力して Enter キーを押します。そこでエラーが返される場合は、入力ミスがあるか、シートが存在しません。

プロのヒント

イミディエイト ウィンドウで次の1行を実行して、シート名に隠れたスペースがないか確認してください。For Each sh In Sheets: Debug.Print "'" & sh.Name & "'": Next。シングルクォーテーションで囲むことで、先頭や末尾のスペースが明確になります。

Related Error Notes