Excel VBAでCopyFromRecordsetを実行したとき、「データが貼り付けられない」「実行時エラーになる」と困っていませんか? 対処の近道は、思いつきで修正することではなく、接続・Recordset・転記先を順番に切り分けることです。
ケンさん(SE)たった1行の転記処理なのに、どこを調べればいいの?



エラー番号と止まった行を確認してから、7つの項目を調べるにゃ。
CopyFromRecordsetで確認すべき7つのポイント
- 止まった行とエラー番号:接続、SQL、転記のどの段階か。
- Recordsetの生成:Nothingではないか。
- Recordsetの状態:ADOなら
Stateが開いている状態か。 - 現在位置:
EOFがTrueになっていないか。 - 貼り付け先:シート保護・結合セルなどがないか。
- 転記サイズ:行列数がExcelの範囲を超えないか。
- フィールド:OLEオブジェクトなど転記できない型が含まれないか。
まずはRecordsetの状態を確認
次のコードはrsを取得済みのADO Recordsetとして、転記直前を診断する抜粋です。接続・SQL実行・後片付けは省略しています。
Dim ws As Worksheet
Dim dest As Range
Set ws = ThisWorkbook.Worksheets("Sheet1")
Set dest = ws.Range("A2")
If rs Is Nothing Then
MsgBox "Recordsetが設定されていません"
Exit Sub
End If
If rs.State = 0 Then
MsgBox "Recordsetが閉じています"
Exit Sub
End If
If rs.EOF Then
MsgBox "現在位置に転記対象がありません"
Exit Sub
End If
dest.CopyFromRecordset rs
ADOとDAOではオブジェクトの状態確認方法が異なります。
また、EOF=Trueは「SQLの検索結果が必ず0件」という意味ではありません。別の処理でRecordsetを最後まで読み進めた場合もTrueになります。
EOF=Trueになった場合の注意点
CopyFromRecordsetはRecordsetの現在位置からデータをコピーします。
先頭に戻すMoveFirstは利用できるカーソルに制限があるため、単純に追加して直るとは限りません。
カーソル設定、直前の読み取り処理、SQLの結果を確認しましょう。
貼り付け先で確認すること
Recordsetの内容が正常でも、シートが保護されている場合や結合セルを含む範囲に書き込む場合は失敗することがあります。検証用の新しいシートを使い、転記範囲の保護や結合を外して切り分けてください。既存データがある場合は上書きにも注意が必要です。
OLE型フィールドがある場合
Microsoftの公式ドキュメントでは、RecordsetにOLEオブジェクトを含むフィールドがあるとCopyFromRecordsetが失敗する、と説明されています。画像などの特殊な列を一緒にSELECTしていないか確認し、必要な列だけをSQLで取り出してみましょう。
【実行前・実行後】EOFがTrueで転記できない例


架空の2件を含むADO Recordsetを末尾まで読み進め、EOF=Trueのまま転記を試すと、戻り値は0でA2は空欄でした。MoveFirstで先頭に戻して転記すると、A2:B3に2件が入りました。
「取得結果はあるはずなのに貼り付けられない」場合を、架空の2件のデータで確認します。1件も出力されない原因が、SQLではなく現在位置にあるケースです。
実行前:Recordsetには2件あるが、読み取り位置が末尾を越えている状態
| Recordsetの内容 | 商品名 | 数量 |
|---|---|---|
| 1件目 | 商品A | 10 |
| 2件目 | 商品B | 20 |
| 現在位置 | EOF=True(次に読むレコードがない) | — |
次の検証用コードは、外部データベースを使わず、メモリ上に架空のADO Recordsetを作ります。Excelの標準モジュールに貼り付けてください。Windows版ExcelでADOを利用できる環境を想定し、遅延バインディングを使っています。
Sub DemoEOFAndCopyFromRecordset()
Dim rs As Object, ws As Worksheet
Dim dest As Range
Set ws = ThisWorkbook.Worksheets.Add
Set rs = CreateObject("ADODB.Recordset")
rs.CursorLocation = 3 ' adUseClient
rs.Fields.Append "商品名", 202, 30 ' adVarWChar
rs.Fields.Append "数量", 3 ' adInteger
rs.Open
rs.AddNew Array("商品名", "数量"), Array("商品A", 10)
rs.AddNew Array("商品名", "数量"), Array("商品B", 20)
rs.MoveFirst
' 全件を読み進めてEOF=Trueを再現
Do Until rs.EOF
rs.MoveNext
Loop
Debug.Print "転記前 EOF=" & rs.EOF ' True
' 静的カーソルを使用した検証例:先頭へ戻す
rs.MoveFirst
ws.Range("A1").Value = "商品名"
ws.Range("B1").Value = "数量"
Set dest = ws.Range("A2")
dest.CopyFromRecordset rs
rs.Close
Set rs = Nothing
End Sub
実行後:新規ワークシートに2件が出力される
| Excelの行 | A列:商品名 | B列:数量 |
|---|---|---|
| 1 | 商品名 | 数量 |
| 2 | 商品A | 10 |
| 3 | 商品B | 20 |
ここでのMoveFirstは、先頭に戻れるRecordsetを意図的に作った検証例です。実際のシステムで前方専用カーソルを使っている場合は利用できないことがあるため、むやみに追加せず、カーソル設定やSQLの再実行を確認しましょう。
検証環境はWindows版Excel 16.0(ビルド20527)とADOです。2026年11月8日に、外部データベースを使わず架空データで検証しました。
CopyFromRecordsetをもっと詳しく学びたい方へ
基本操作からエラー対策、データの取り込みや書式設定まで体系的に学びたい方には、Kindle書籍『Excel VBA CopyFromRecordset 実践ガイド』もおすすめです。



ぜひ、読んでみてニャ🐈
まとめ
大切なのはエラー発生行→Recordsetの状態→現在位置→転記先の順に調べること。
一度に複数箇所を変更せず、検証結果を残すと原因を特定しやすくなります。
関連記事・もっと詳しく学ぶには
基本から確認したい方は、CopyFromRecordsetの使い方完全ガイドをご覧ください。
高速化の背景はCopyFromRecordsetはなぜ速い?で解説しています。
参考資料:Microsoft Learn:Range.CopyFromRecordset メソッド(確認日:2026年11月8日)。コード例は架空データ・一般的な環境を想定しています。本番実行前に検証してください。




