CopyFromRecordsetでExcelにデータを貼り付けると、列見出しが出なかったり、想定以上の件数が出力されたりすることがあります。これは使い方を整理すると解決できます。
ケンさん(SE)データは貼れたのに、1行目に項目名がないんだ。



ヘッダーは別に書くにゃ。最大行数と列数も指定できるよ。
CopyFromRecordsetはデータ本体だけをコピーする
CopyFromRecordsetはRecordsetのフィールド名を見出しとして自動転記しません。Fields(i).Nameを使い、ヘッダーを先に出力します。
見出し行を付けるVBAサンプル
以下は取得済みのRecordsetrsを使う抜粋です。事前に接続・SQL実行が完了しているものとします。
Dim ws As Worksheet
Dim dest As Range
Dim i As Long
Dim copied As Long
Set ws = ThisWorkbook.Worksheets("Sheet1")
For i = 0 To rs.Fields.Count - 1
ws.Cells(1, i + 1).Value = rs.Fields(i).Name
Next i
Set dest = ws.Range("A2")
copied = dest.CopyFromRecordset(rs)
MsgBox copied & "件を出力しました"
ここでは、1行目に列名、2行目以降にデータを配置しています。戻り値のcopiedはコピーされたレコード数です。
MaxRows・MaxColumnsで最大件数と最大列数を指定
CopyFromRecordsetには省略可能な2つの引数があります。MaxRowsは最大レコード数、MaxColumnsは最大フィールド数です。
Set dest = Worksheets("Sheet1").Range("A2")
copied = dest.CopyFromRecordset(rs, 100, 3)
この例では最大100行×3列をコピーします。ただし、Recordsetに100件未満しか残っていなければ、残りの件数までしか転記されません。
列の並び替えはSQLで指定する
MaxColumns=3は好きな列を3つ選ぶ機能ではありません。Recordsetの先頭から3列を対象とします。必要なフィールドと並び順はSELECT句で決めましょう。
SELECT product_code, product_name, quantity
FROM sample_items
ORDER BY product_code
上のSQLは架空のテーブルに対する例です。SELECT *を避けて必要な列を明示すると、出力列の仕様が安定しやすくなります。行の順序も必要ならORDER BYを指定します。
行数制限とSQLでの絞り込みの違い
MaxRowsはExcelへコピーする最大レコード数を指定するもので、SQLの検索件数を減らすものではありません。データベースへの負荷や取得時間も抑えたい場合は、SQLのWHERE句などで取得対象そのものを絞り込みます。
出力前にチェックする項目
- ヘッダーの項目数とRecordsetのフィールド数が合っているか
- Excelの最終行・最終列からはみ出さないか
- 前回の出力結果を消す必要があるか
- 同じRecordsetを再利用する際、現在位置は適切か
【実行前・実行後】5件のデータから先頭3件・2列だけ表示する


転記前のRecordsetは5件・3フィールドでした。CopyFromRecordset(rs, 3, 2)の戻り値は3で、見出しを含めてA1:B4に出力されました。5行目とC列は空欄でした。
元データ5件を、見出し付きのExcel表に最大3行×2列で出力する例です。データの件数と引数の対応を見比べてみましょう。
実行前:Recordsetにある5件・3フィールド(架空データ)
| 商品コード | 商品名 | 数量 |
|---|---|---|
| P001 | 商品A | 10 |
| P002 | 商品B | 20 |
| P003 | 商品C | 15 |
| P004 | 商品D | 30 |
| P005 | 商品E | 12 |
VBAコード:先頭2フィールドのヘッダーを追加して3件だけ転記。次は外部DB接続を必要としないADOの検証用サンプルです。
Sub DemoHeaderAndLimit()
Dim rs As Object, ws As Worksheet
Dim dest As Range
Dim i As Long, n As Long
Dim names As Variant, qty As Variant
names = Array("商品A", "商品B", "商品C", "商品D", "商品E")
qty = Array(10, 20, 15, 30, 12)
Set rs = CreateObject("ADODB.Recordset")
rs.CursorLocation = 3 ' adUseClient
rs.Fields.Append "商品コード", 202, 8
rs.Fields.Append "商品名", 202, 30
rs.Fields.Append "数量", 3
rs.Open
For i = 0 To 4
rs.AddNew Array("商品コード", "商品名", "数量"), _
Array("P00" & (i + 1), names(i), qty(i))
Next i
rs.MoveFirst
Set ws = ThisWorkbook.Worksheets.Add
ws.Range("A1").Value = rs.Fields(0).Name
ws.Range("B1").Value = rs.Fields(1).Name
Set dest = ws.Range("A2")
n = dest.CopyFromRecordset(rs, 3, 2)
Debug.Print n & "件を転記しました"
rs.Close
Set rs = Nothing
End Sub
実行後:Excelにヘッダー+3行・2列を出力
| Excelの行 | A列:商品コード | B列:商品名 |
|---|---|---|
| 1 | 商品コード | 商品名 |
| 2 | P001 | 商品A |
| 3 | P002 | 商品B |
| 4 | P003 | 商品C |
このようにCopyFromRecordset(rs, 3, 2)では最大3レコード・先頭2フィールドをコピーします。3行のデータにヘッダー1行が加わり、Excel上は合計4行になります。戻り値はVBAエディターのイミディエイトウィンドウ(Ctrl+G)で確認できます。
注意:ここでの3件は現在のレコード位置からの件数です。SQLで取得する件数を3件に減らす指定ではありません。また、先頭2列以外を選びたい場合はSELECT句の列順を変更してください。
検証環境はWindows版Excel 16.0(ビルド20527)とADOです。2026年11月8日に、外部データベースを使わず架空データで検証しました。
CopyFromRecordsetをもっと詳しく学びたい方へ
基本操作からエラー対策、データの取り込みや書式設定まで体系的に学びたい方には、Kindle書籍『Excel VBA CopyFromRecordset 実践ガイド』もおすすめです。



ぜひ、読んでみてニャ🐈
まとめ
ヘッダーはFields.Name、件数と列数は引数、列選択はSQLと役割を分けると、意図した表を作りやすくなります。
関連記事・もっと詳しく学ぶには
基本から確認したい方は、CopyFromRecordsetの使い方完全ガイドをご覧ください。
高速化の背景はCopyFromRecordsetはなぜ速い?で解説しています。
参考資料:Microsoft Learn:Range.CopyFromRecordset メソッド(確認日:2026年11月8日)。コード例は架空データ・一般的な環境を想定しています。本番実行前に検証してください。




