「実行時エラー ‘1004’: RangeクラスのSelectメソッドが失敗しました。」
VBAで最も遭遇する機会が多いエラーメッセージの1つです。
私も初心者の頃、このエラーに何時間も悩まされ、「なぜ同じコードなのに別シートではエラーが出るの?」と混乱しました。
実はこのエラー、原因が5つの典型的なパターンに分類できることがわかりました。
この記事では、「Rangeメソッドが失敗しました」エラーの5つの頻出パターンと、それぞれの具体的な解決コードを実例付きで徹底解説します。
✅ この記事で解決できるエラー
- 実行時エラー ‘1004’: RangeクラスのSelectメソッドが失敗しました。
- 実行時エラー ‘1004’: ‘Range’メソッドは失敗しました: ‘_Worksheet’オブジェクト
- 実行時エラー ‘1004’: ‘Range’メソッドは失敗しました: ‘_Global’オブジェクト
- 実行時エラー ‘1004’: アプリケーション定義またはオブジェクト定義のエラーです。
エラー1004「Rangeメソッド失敗」の基礎知識
エラーメッセージのバリエーション
同じエラー1004でも、表示されるメッセージは3種類あります。
| メッセージ | 意味 |
|---|---|
| RangeクラスのSelectメソッドが失敗しました | Selectメソッド実行時のエラー |
| ‘Range’メソッドは失敗しました: ‘_Worksheet’オブジェクト | Worksheets().Range()の実行エラー |
| ‘Range’メソッドは失敗しました: ‘_Global’オブジェクト | グローバルなRange()の実行エラー |
いずれも原因は同じで、Rangeオブジェクトの取得・操作に失敗しています。
なぜRangeメソッドは失敗するのか?
Rangeメソッドが失敗する根本原因は、以下の3つです。
- 親シートの指定が不一致(最頻出)
- 無効な範囲指定(変数が空、範囲外など)
- Selectできない状態でSelectした(別シートがアクティブなど)
それでは、5つの頻出パターンを見ていきましょう。
【頻出パターン①】別シートのRangeをSelectして失敗
エラーが出るコード例
Sub 別シートのSelect()
' Sheet1がアクティブな状態で実行
Worksheets("Sheet2").Range("A1").Select ' ← エラー1004
End Sub
エラー理由:
VBAでは、アクティブでないシートのセルは直接Selectできません。
✅ 解決方法①:先にシートをActivateする
Sub 正しい別シートのSelect()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet2")
' シートをアクティブにしてからSelect
ws.Activate
ws.Range("A1").Select
End Sub
✅ 解決方法②:Selectを使わない(推奨)
Sub Selectを使わない方法()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet2")
' Selectせずに直接操作
ws.Range("A1").Value = "更新"
ws.Range("A1").Interior.Color = RGB(255, 255, 0)
End Sub
💡 ポイント:
Selectは実行速度が遅く、エラーも多いため、できるだけ使わないのがベストプラクティスです。
✅ 解決方法③:Application.GoToを使う(複雑な場合)
Sub ApplicationGoToを使う()
Application.GoTo Reference:=Worksheets("Sheet2").Range("A1")
' これでSheet2のA1セルにジャンプして選択される
End Sub
【頻出パターン②】Range+Cellsで親シート不一致
エラーが出るコード例
Sub Range_Cellsの親シート不一致()
Dim lastRow As Long
lastRow = Worksheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
' ← エラー1004(RangeとCellsの親シートが違う)
Worksheets("Sheet2").Range(Cells(1, 1), Cells(lastRow, 1)).Select
End Sub
エラー理由:Range(Cells(1,1), Cells(lastRow,1))の中のCellsは、アクティブシートを参照します。
一方、外側のWorksheets("Sheet2").Range()はSheet2を指定しているため、親シートが不一致になります。
✅ 解決方法①:Withステートメントで統一
Sub Withで親シート統一()
Dim lastRow As Long
With Worksheets("Sheet2")
lastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
.Range(.Cells(1, 1), .Cells(lastRow, 1)).Select
End With
End Sub
✅ 解決方法②:変数で統一(推奨)
Sub 変数で親シート統一()
Dim ws As Worksheet
Dim lastRow As Long
Set ws = ThisWorkbook.Worksheets("Sheet2")
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
' wsで統一されているのでエラーなし
ws.Range(ws.Cells(1, 1), ws.Cells(lastRow, 1)).Select
End Sub
💡 ポイント:
Range()内でCellsを使う場合は、必ず親シートを明示するのが鉄則です。
✅ 解決方法③:Selectを使わず直接操作
Sub Selectを使わない最適解()
Dim ws As Worksheet
Dim lastRow As Long
Set ws = ThisWorkbook.Worksheets("Sheet2")
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
' Selectせずに背景色を変更
ws.Range(ws.Cells(1, 1), ws.Cells(lastRow, 1)).Interior.Color = RGB(255, 255, 0)
End Sub
【頻出パターン③】動的範囲指定で変数が空・範囲外
エラーが出るコード例
Sub 変数が空のRange指定()
Dim startCell As String
Dim endCell As String
' startCellに値を代入し忘れ(空のまま)
endCell = "A10"
' ← エラー1004(startCellが空)
Range(startCell & ":" & endCell).Select
End Sub
エラー理由:startCellが空のため、Range(":A10")という無効な指定になります。
✅ 解決方法①:変数が空でないかチェック
Sub 変数の空チェック付き()
Dim startCell As String
Dim endCell As String
startCell = "A1"
endCell = "A10"
' 空チェック
If startCell = "" Or endCell = "" Then
MsgBox "範囲が正しく指定されていません", vbExclamation
Exit Sub
End If
Range(startCell & ":" & endCell).Select
End Sub
✅ 解決方法②:Cells()で動的範囲指定(推奨)
Sub Cellsで動的範囲指定()
Dim ws As Worksheet
Dim startRow As Long
Dim endRow As Long
Set ws = ThisWorkbook.Worksheets("Sheet1")
startRow = 1
endRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
' Cellsで安全に範囲指定
ws.Range(ws.Cells(startRow, 1), ws.Cells(endRow, 1)).Interior.Color = RGB(255, 255, 0)
End Sub
✅ 解決方法③:エラーハンドリングで対応
Sub エラーハンドリング付き()
On Error GoTo ErrorHandler
Dim startCell As String
Dim endCell As String
startCell = InputBox("開始セルを入力(例:A1)")
endCell = InputBox("終了セルを入力(例:A10)")
Range(startCell & ":" & endCell).Select
MsgBox "範囲を選択しました", vbInformation
Exit Sub
ErrorHandler:
MsgBox "無効な範囲指定です。" & vbCrLf & _
"正しいセル範囲を入力してください。", vbCritical
End Sub
💡 ポイント:
ユーザー入力やファイル読み込みで範囲を指定する場合は、必ずエラーハンドリングを入れるのが安全です。
【頻出パターン④】結合セルに対するRange操作
エラーが出るコード例
Sub 結合セルへのRange操作()
' A1:C1が結合されている場合
Range("A1:C1").ClearContents ' ← エラーが出る場合がある
' または
Range("A1").Offset(1, 0).Select ' ← 結合セル内では予期しない動作
End Sub
エラー理由:
結合セルに対して一部のRange操作を実行すると、「この操作は結合したセルには行えません」というエラーが出ます。
✅ 解決方法①:MergeAreaプロパティを使う
Sub 結合セルを安全にクリア()
Dim rng As Range
Set rng = Range("A1")
' 結合セル全体をクリア
rng.MergeArea.ClearContents
End Sub
✅ 解決方法②:結合セルを判定してから操作
Sub 結合セル判定付き()
Dim rng As Range
Set rng = Range("A1")
' 結合セルかどうか判定
If rng.MergeCells Then
MsgBox "A1は結合セルです。範囲: " & rng.MergeArea.Address
' 結合セル全体に対して操作
rng.MergeArea.Interior.Color = RGB(255, 255, 0)
Else
rng.Interior.Color = RGB(255, 255, 0)
End If
End Sub
✅ 解決方法③:結合セルを解除してから操作
Sub 結合セルを解除してから操作()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1")
On Error Resume Next
' UsedRange内の結合セルをすべて解除
ws.UsedRange.UnMerge
On Error GoTo 0
' 通常のRange操作
ws.Range("A1:C1").Value = "更新"
ws.Range("A1:C1").Interior.Color = RGB(255, 255, 0)
End Sub
💡 ポイント:
結合セルは処理が複雑になるため、可能な限り使わないのがベストプラクティスです。
【頻出パターン⑤】R1C1形式とA1形式の混在
エラーが出るコード例
Sub R1C1形式でRangeを使う()
' ExcelがR1C1参照形式に設定されている場合
Range("A1").Select ' ← エラー1004(R1C1形式ではRangeが使えない)
End Sub
エラー理由:
ExcelがR1C1参照形式に設定されている場合、Range("A1")のようなA1形式の指定はエラーになります。
✅ 解決方法①:A1形式に戻す
Sub A1形式に戻す()
' R1C1形式からA1形式に変更
Application.ReferenceStyle = xlA1
' これでRangeが使える
Range("A1").Value = "テスト"
End Sub
✅ 解決方法②:Cellsを使う(推奨)
Sub Cellsを使う方法()
' CellsはR1C1形式でも動作する
Cells(1, 1).Value = "テスト" ' ← R1C1形式でもOK
Cells(1, 1).Interior.Color = RGB(255, 255, 0)
End Sub
✅ 解決方法③:参照形式を一時的に切り替える
Sub 参照形式を一時切り替え()
Dim originalStyle As Long
' 現在の参照形式を保存
originalStyle = Application.ReferenceStyle
' A1形式に切り替え
Application.ReferenceStyle = xlA1
' Range操作
Range("A1:A10").Interior.Color = RGB(255, 255, 0)
' 元の参照形式に戻す
Application.ReferenceStyle = originalStyle
End Sub
💡 ポイント:
Cellsを使えばR1C1形式でもA1形式でも動作するため、汎用性が高いコードになります。
Rangeエラーを根本的に防ぐ3つの鉄則
鉄則①:Selectを使わない
Selectを使わないメリット:
- ✅ 実行速度が速い(10倍以上高速化することも)
- ✅ エラー1004が激減する
- ✅ コードがシンプルになる
Selectを使わないコード例:
' ❌ Selectを使うコード(遅い・エラーが出やすい)
Worksheets("Sheet1").Activate
Range("A1").Select
Selection.Value = "テスト"
Selection.Interior.Color = RGB(255, 255, 0)
' ✅ Selectを使わないコード(速い・エラーなし)
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1")
ws.Range("A1").Value = "テスト"
ws.Range("A1").Interior.Color = RGB(255, 255, 0)
鉄則②:Withステートメントで親シートを統一
Withを使うメリット:
- ✅ 親シート不一致のエラーを防げる
- ✅ コードが読みやすくなる
- ✅ タイプミスを減らせる
Withの正しい使い方:
Sub Withで親シート統一()
With ThisWorkbook.Worksheets("Sheet1")
.Range("A1").Value = "テスト"
.Range(.Cells(1, 1), .Cells(10, 1)).Interior.Color = RGB(255, 255, 0)
' ↑ すべて「.」を付けて親シートを明示
End With
End Sub
鉄則③:変数でワークシートオブジェクトを管理
変数管理のメリット:
- ✅ シート名のタイプミスを防げる
- ✅ コード変更時の修正が1箇所で済む
- ✅ 親シートが明確になる
変数管理の正しい方法:
Sub 変数でワークシート管理()
' ワークシートを変数で管理
Dim wsData As Worksheet
Dim wsReport As Worksheet
Set wsData = ThisWorkbook.Worksheets("データ")
Set wsReport = ThisWorkbook.Worksheets("レポート")
' 変数を使うことで親シートが明確
wsData.Range("A1").Value = "元データ"
wsReport.Range("A1").Value = "集計結果"
' データをコピー
wsData.Range("A1:A10").Copy wsReport.Range("A1")
End Sub
実務で使える!Range操作の安全テンプレート
テンプレート①:別シートへの安全なデータ転記
Sub 安全な別シートデータ転記()
On Error GoTo ErrorHandler
Dim wsSource As Worksheet
Dim wsTarget As Worksheet
Dim lastRow As Long
' シートを変数で管理
Set wsSource = ThisWorkbook.Worksheets("元データ")
Set wsTarget = ThisWorkbook.Worksheets("転記先")
' 最終行を取得
lastRow = wsSource.Cells(wsSource.Rows.Count, 1).End(xlUp).Row
' Selectを使わずにコピー
wsSource.Range(wsSource.Cells(1, 1), wsSource.Cells(lastRow, 3)).Copy _
wsTarget.Range("A1")
MsgBox "データ転記が完了しました", vbInformation
Exit Sub
ErrorHandler:
MsgBox "エラーが発生しました" & vbCrLf & _
"エラー番号: " & Err.Number & vbCrLf & _
"エラー内容: " & Err.Description, vbCritical
End Sub
テンプレート②:Range+Cells動的範囲指定の完全版
Sub Range_Cells動的範囲指定完全版()
On Error GoTo ErrorHandler
Dim ws As Worksheet
Dim lastRow As Long
Dim lastCol As Long
Dim dataRange As Range
Set ws = ThisWorkbook.Worksheets("データ")
' 最終行・最終列を取得
With ws
lastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
lastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
End With
' データ範囲が空でないかチェック
If lastRow < 1 Or lastCol < 1 Then
MsgBox "データが存在しません", vbExclamation
Exit Sub
End If
' 範囲を取得(Selectは使わない)
Set dataRange = ws.Range(ws.Cells(1, 1), ws.Cells(lastRow, lastCol))
' 範囲に対して操作
dataRange.Interior.Color = RGB(255, 255, 200)
dataRange.Borders.LineStyle = xlContinuous
MsgBox "処理が完了しました。範囲: " & dataRange.Address, vbInformation
Exit Sub
ErrorHandler:
MsgBox "エラーが発生しました" & vbCrLf & _
"エラー番号: " & Err.Number & vbCrLf & _
"エラー内容: " & Err.Description, vbCritical
End Sub
テンプレート③:結合セル対応のRange操作
Sub 結合セル対応Range操作()
On Error GoTo ErrorHandler
Dim ws As Worksheet
Dim rng As Range
Dim cell As Range
Set ws = ThisWorkbook.Worksheets("Sheet1")
Set rng = ws.Range("A1:C10")
' 範囲内のセルをループ
For Each cell In rng
' 結合セルの場合はMergeAreaを使う
If cell.MergeCells Then
cell.MergeArea.Interior.Color = RGB(255, 200, 200)
Else
cell.Interior.Color = RGB(200, 255, 200)
End If
Next cell
MsgBox "処理が完了しました", vbInformation
Exit Sub
ErrorHandler:
MsgBox "エラーが発生しました" & vbCrLf & _
"エラー番号: " & Err.Number & vbCrLf & _
"エラー内容: " & Err.Description, vbCritical
End Sub
よくある質問(FAQ)
Q1. Selectを使わないと、どれくらい速くなりますか?
A. 処理内容によりますが、10倍〜100倍以上高速化することもあります。特に大量のセルを操作する場合は劇的に速くなります。Selectは画面描画も伴うため、非常に遅い処理です。
Q2. Withステートメントを使うと、必ず「.」を付けないとダメですか?
A. はい、Withブロック内では必ず「.」を付ける必要があります。「.」を付け忘れると、アクティブシートを参照してしまい、エラーの原因になります。
Q3. Range()とCells()、どちらを使うべきですか?
A. 基本的には以下のように使い分けます:
・固定範囲:Range(“A1:C10”)
・動的範囲:Cells(行, 列)
・Range+Cells:Range(Cells(1,1), Cells(10,3))
動的に範囲を指定する場合はCellsが便利です。
Q4. Application.GoToとActivate+Selectの違いは?
A. Application.GoToはシートをまたいだジャンプが1行でできる点が便利です。Activate+Selectは2行必要ですが、動作は同じです。どちらも画面描画を伴うため、Selectを使わない方法を推奨します。
Q5. R1C1形式のExcelで作業する場合の注意点は?
A. R1C1形式ではRange("A1")のような指定はエラーになります。Cells(1, 1)を使うか、Application.ReferenceStyle = xlA1で一時的にA1形式に切り替えてください。
✅ まとめ
実行時エラー1004「RangeクラスのSelectメソッドが失敗しました」は、5つの頻出パターンに分類できます。
| パターン | 原因 | 対策 |
|---|---|---|
| ①別シートのSelect | アクティブでないシートのSelectは不可 | Activateするか、Selectを使わない |
| ②Range+Cells親シート不一致 | RangeとCellsの親シートが違う | Withステートメントか変数で統一 |
| ③動的範囲指定で変数が空 | 変数が空・範囲外 | 空チェック、Cellsで指定 |
| ④結合セルへのRange操作 | 結合セルに対する一部の操作が不可 | MergeAreaを使う、結合を解除 |
| ⑤R1C1形式とA1形式の混在 | R1C1形式でRange(“A1”)は不可 | Cellsを使う、A1形式に戻す |
エラーを根本的に防ぐ3つの鉄則:
- Selectを使わない(最重要)
- Withステートメントで親シートを統一
- 変数でワークシートオブジェクトを管理
この記事の安全テンプレートをコピーして、自分のコードに組み込んでください。
Rangeエラーが出たときは、まず「どのパターンに該当するか?」を確認し、対応する解決方法を試してみましょう。

コメント