【VBA】シートを別ブックにコピー・移動する方法(コピペOK)

VBA
  1. この記事でできること
  2. どんな場面で使う?
  3. 完成イメージ(Before / After)
  4. コピーと移動の違い
  5. 実行前の準備
    1. バックアップを取る(必須)
    2. コピー先ブックを開いておく(別ブックにコピーする場合)
    3. Excelをマクロ有効ブック(.xlsm)で保存する
  6. 手順(コピペ → 実行まで約5分)
    1. VBE(コードを書く画面)を開く
    2. 標準モジュールを挿入する
    3. コードを貼り付けて実行する
  7. コード(最小版)– 1シートを別ブックにコピーする
  8. コード(応用版)– 複数シートの一括コピー/新規ブックへのコピー
    1. 応用1: 複数シートを別ブックに一括コピー
    2. 応用2: シートを新規ブックにコピーして保存
  9. コード(実務版)– 月別シートを別ブックに分割保存
  10. よくある落とし穴5選
    1. 1. Copy のつもりで Move を使い、元シートが消えた
    2. 2. コピー先ブックが開いていなくてエラー
    3. 3. 数式が外部参照に変わってしまう
    4. 4. ブック内最後の1シートを Move するとエラー
    5. 5. シート名にファイル名に使えない文字が含まれている
    6. VBAでシートコピー時に名前の重複エラーが出るときの対処法
    7. VBAのSheets.Copyが別ブックに失敗するときの対処法
  11. FAQ
    1. Q1: コピー先ブックが閉じている場合、自動で開いてコピーしたい
    2. Q2: コピーしたシートの名前を変えたい
    3. Q3: シートではなくファイルをコピー・移動したい
    4. Q4: 複数ブックのデータを1つに統合したい(逆の操作)
    5. Q5: コピー後に元ブックのシートを削除したい
  12. まとめ
    1. 関連記事
  13. 次にやりたくなること
  14. もっとカスタマイズしたい場合

この記事でできること

  • VBAでシートを別のブック(Excelファイル)にコピーできる
  • シートを別ブックに移動できる(元ブックからは消える)
  • 複数シートを一括で別ブックにコピーできる
  • 月別シートを個別ファイルに分割保存できる

対象: Excel 2016以降 / Microsoft 365、Windows 10/11

どんな場面で使う?

  • 拠点別・部門別の売上シートを本社用ブックにまとめて提出するとき
  • 月別シート(1月〜12月)を個別のExcelファイルに分割して配布するとき
  • 特定のシートだけを抜き出して、社外に渡す用のブックを作りたいとき
  • テンプレートシートを新規ブックにコピーして、新しい案件用ファイルを自動作成したいとき
  • 条件に合う行を別シートにコピーした後、そのシートごと別ブックに切り出したいとき

シートのコピー・移動は手動でもできるが、枚数が多いと時間がかかるしミスしやすい。VBAなら配列にシート名を列挙するだけで一括処理できる。

完成イメージ(Before / After)

Before(手動で繰り返し):

  1. シートタブを右クリック →「移動またはコピー」
  2. コピー先ブックを選択
  3. 「コピーを作成する」にチェック
  4. 「OK」をクリック
  5. …これを5シート分繰り返し
  6. コピー先を間違えて、別ファイルにシートが増殖

After(VBAで自動化):

  1. マクロを実行
  2. 指定シートが別ブックにコピー(または移動)される
  3. 完了メッセージが表示される

拠点別の売上シートを本社用ブックに手作業でコピーしていた。シートタブを右クリック→「移動またはコピー」→コピー先ブックを選択→「コピーを作成する」にチェック…を5拠点分。毎月やるのに15分かかっていたし、コピー先ブックを間違えて違うファイルにシートが増殖したこともある。VBAのSheets.Copyを使うようにしてからは、5シート分のコピーが数秒で終わるようになった。この記事で、手作業のコピー地獄から抜け出してほしい。

シートのコピー・移動を手動で繰り返すのは、ミスの温床。VBAに任せよう。

なお、「シート」ではなく「ファイル」をコピー・移動したい場合は ファイルを別フォルダにコピー・移動する方法 を参照。また、逆に複数ブックのデータを1つに統合したい場合は 複数Excelファイルを1つに統合 を参照。

コピーと移動の違い

処理を始める前に、コピーと移動の違いを確認する。

コピー(Sheets.Copy) 移動(Sheets.Move)
元シート 残る なくなる
危険度 低い(元が残る) 高い(元からなくなる)
ブック内最後の1シートに対して 実行可能 エラー(ブックには最低1シート必要)
同名シートがコピー先にある場合 自動リネーム(例: Sheet1 (2)) 自動リネーム

移動はシートが元ブックからなくなる破壊的操作です。 移動を使う場合は、必ず事前にバックアップを取ってください。

実行前の準備

バックアップを取る(必須)

移動(Sheets.Move)は元ブックからシートがなくなる操作です。 必ず元ブックをコピーしてバックアップを取ってください。コピーだけの場合も、念のためバックアップを推奨する。

コピー先ブックを開いておく(別ブックにコピーする場合)

Sheets.Copy After:=Workbooks("コピー先.xlsx")... のように書くとき、コピー先ブックが開いていないとエラーになる。事前にExcelで開いておくか、コード内で Workbooks.Open で開く。

Excelをマクロ有効ブック(.xlsm)で保存する

  1. 「ファイル」→「名前を付けて保存」
  2. ファイルの種類を「Excelマクロ有効ブック (*.xlsm)」に変更
  3. 保存

手順(コピペ → 実行まで約5分)

VBE(コードを書く画面)を開く

  1. Excelで Alt + F11 を押す
  2. VBE(Visual Basic Editor)が開く

標準モジュールを挿入する

  1. VBEのメニュー →「挿入」→「標準モジュール」
  2. 白い画面(コードウィンドウ)が表示される

コードを貼り付けて実行する

  1. コードウィンドウに、下のコードをそのままコピペする
  2. Alt + F8 → マクロ名を選んで「実行」

コード(最小版)– 1シートを別ブックにコピーする

まずはこれだけで動く。Sheets.Copy で1枚のシートを別ブックの末尾にコピーする。


'============================================================
' ■ 1シートを別ブックにコピー(最小版)
'   → コピー先ブックは事前に開いておく
'   ※ ThisWorkbook = このマクロが入っているブック
'     (ActiveWorkbook とは異なる。通常は ThisWorkbook を使う)
'============================================================
Sub CopySheetToAnotherBook()

    Dim srcBook As Workbook
    Dim dstBook As Workbook

    ' ★ マクロが入っているブック(コピー元)
    Set srcBook = ThisWorkbook

    ' ★ コピー先ブック名を書き換える(事前に開いておく)
    Set dstBook = Workbooks("コピー先.xlsx")

    ' ★ コピーするシート名を書き換える
    srcBook.Worksheets("売上データ").Copy _
        After:=dstBook.Sheets(dstBook.Sheets.Count)

    MsgBox "シートのコピーが完了しました。", vbInformation

End Sub

ポイント:

  • After:=dstBook.Sheets(dstBook.Sheets.Count) でコピー先ブックの末尾にコピーされる。なぜ dstBook.Sheets.Count を使うかというと、コピー先の最後のシートの「後ろ」を指定することで、常に末尾に追加できるからだ
  • AfterBefore に変えると、指定シートのにコピーされる
  • コピーではなく移動したい場合は、.Copy.Move に変える。ただし元ブックからシートがなくなるので注意
  • コピー先ブックは事前にExcelで開いておくこと。開いていないと「インデックスが有効範囲にありません」エラーが出る。自動で開きたい場合はファイルの開閉を参照
  • コピー先に同名シートがある場合、自動的に「売上データ (2)」のようにリネームされる。リネームを避けたい場合は、事前にシート名の存在チェックを行うとよい

コード(応用版)– 複数シートの一括コピー/新規ブックへのコピー

応用1: 複数シートを別ブックに一括コピー

配列で指定した複数シートをまとめて別ブックにコピーする。


'============================================================
' ■ 複数シートを別ブックに一括コピー
'   → 配列でシート名を指定。ループでコピー
'============================================================
Sub CopyMultipleSheets()

    Dim srcBook As Workbook
    Dim dstBook As Workbook
    Dim sheetNames As Variant
    Dim i As Long
    Dim count As Long

    Set srcBook = ThisWorkbook

    ' ★ コピー先ブック名を書き換える(事前に開いておく)
    Set dstBook = Workbooks("コピー先.xlsx")

    ' ★ コピーするシート名を書き換える
    sheetNames = Array("東京", "大阪", "名古屋", "福岡", "札幌")

    count = 0

    For i = LBound(sheetNames) To UBound(sheetNames)

        ' シートが存在するかチェック
        If SheetExists(srcBook, CStr(sheetNames(i))) Then
            srcBook.Worksheets(CStr(sheetNames(i))).Copy _
                After:=dstBook.Sheets(dstBook.Sheets.Count)
            count = count + 1
        Else
            MsgBox "シートが見つかりません:" & sheetNames(i), vbExclamation
        End If

    Next i

    MsgBox count & " シートのコピーが完了しました。", vbInformation

End Sub

'============================================================
' ■ 補助関数: シートが存在するかチェック
'============================================================
Private Function SheetExists(wb As Workbook, sheetName As String) As Boolean
    Dim ws As Worksheet
    On Error Resume Next
    Set ws = wb.Worksheets(sheetName)
    On Error GoTo 0
    SheetExists = Not ws Is Nothing
End Function

応用2: シートを新規ブックにコピーして保存

Sheets.Copy を引数なしで呼ぶと、新規ブックが自動で作られ、そこにシートがコピーされる。


'============================================================
' ■ シートを新規ブックにコピーして保存
'   → 引数なしの Copy で新規ブックが作られる
'   → 保存先パスを指定して保存
'============================================================
Sub CopySheetToNewBook()

    Dim savePath As String

    ' ★ 保存先のフルパスを書き換える
    savePath = "C:\Users\(ユーザー名)\Desktop\売上データ_コピー.xlsx"

    ' シートを新規ブックにコピー(引数なし = 新規ブック作成)
    ThisWorkbook.Worksheets("売上データ").Copy

    ' 新規ブックがアクティブになっているので保存
    ActiveWorkbook.SaveAs savePath, FileFormat:=xlOpenXMLWorkbook
    ActiveWorkbook.Close SaveChanges:=False

    MsgBox "新規ブックに保存しました:" & vbCrLf & savePath, vbInformation

End Sub

ポイント:

  • Sheets.Copy(引数なし)で新規ブックが自動作成される。手動で Workbooks.Add する必要はない
  • コピー直後は新規ブックが ActiveWorkbook になる
  • FileFormat:=xlOpenXMLWorkbook.xlsx 形式で保存。マクロ付きで保存したい場合は xlOpenXMLWorkbookMacroEnabled(.xlsm)に変える
  • 同名ファイルが既に存在すると上書き確認ダイアログが表示される

コード(実務版)– 月別シートを別ブックに分割保存

1つのブックに「1月」「2月」…「12月」のシートがある場合に、各シートを個別のExcelファイルとして保存する。月次報告書の配布や、拠点別データの振り分けに便利。


'============================================================
' ■ 月別シートを別ブックに分割保存(実務版)
'   → 指定シートを1枚ずつ新規ブックにコピーして保存
'   → スキップ対象(目次・集計)は除外
'   → 保存先フォルダがなければ自動作成
'============================================================
Sub SplitSheetsByMonth()

    Dim srcBook As Workbook
    Dim ws As Worksheet
    Dim saveFolderPath As String
    Dim saveFilePath As String
    Dim count As Long
    Dim skipCount As Long
    Dim fso As Object

    ' ★ 保存先フォルダを書き換える(末尾の \ を忘れずに)
    saveFolderPath = "C:\Users\(ユーザー名)\Desktop\月別分割\"

    ' ★ スキップするシート名(目次や集計シートなど)
    Dim skipSheets As Variant
    skipSheets = Array("目次", "集計")

    Set srcBook = ThisWorkbook
    Set fso = CreateObject("Scripting.FileSystemObject")

    ' 保存先フォルダがなければ作成
    If Not fso.FolderExists(saveFolderPath) Then
        fso.CreateFolder saveFolderPath
    End If

    ' 確認ダイアログ
    Dim msg As String
    msg = "各シートを個別のExcelファイルに分割保存します。" & vbCrLf & _
          "保存先:" & saveFolderPath & vbCrLf & vbCrLf & _
          "実行しますか?"

    If MsgBox(msg, vbYesNo + vbQuestion) = vbNo Then
        Set fso = Nothing
        Exit Sub
    End If

    count = 0
    skipCount = 0

    For Each ws In srcBook.Worksheets

        ' 非表示シートをスキップ
        If ws.Visible <> xlSheetVisible Then
            skipCount = skipCount + 1
            GoTo NextSheet
        End If

        ' スキップ対象のシートをスキップ
        '    ※ GoTo NextSheet は VBA でスキップ処理を書く定番パターン。
        '      ネストが深くならず可読性が高い
        If IsInArray(ws.Name, skipSheets) Then
            skipCount = skipCount + 1
            GoTo NextSheet
        End If

        ' 保存ファイル名を作成(シート名 + .xlsx)
        saveFilePath = saveFolderPath & ws.Name & ".xlsx"

        ' シートを新規ブックにコピー
        ws.Copy

        ' 新規ブックを保存して閉じる
        On Error Resume Next
        ActiveWorkbook.SaveAs saveFilePath, FileFormat:=xlOpenXMLWorkbook
        If Err.Number <> 0 Then
            MsgBox "保存に失敗しました:" & ws.Name & vbCrLf & _
                   Err.Description, vbExclamation
            ActiveWorkbook.Close SaveChanges:=False
            Err.Clear
            On Error GoTo 0
            GoTo NextSheet
        End If
        On Error GoTo 0

        ActiveWorkbook.Close SaveChanges:=False
        count = count + 1

NextSheet:
    Next ws

    Set fso = Nothing

    MsgBox "完了しました。" & vbCrLf & _
           "保存:" & count & " シート" & vbCrLf & _
           "スキップ:" & skipCount & " シート" & vbCrLf & _
           "保存先:" & saveFolderPath, vbInformation

End Sub

'============================================================
' ■ 補助関数: 値が配列に含まれるかチェック
'============================================================
Private Function IsInArray(val As String, arr As Variant) As Boolean
    Dim i As Long
    For i = LBound(arr) To UBound(arr)
        If arr(i) = val Then
            IsInArray = True
            Exit Function
        End If
    Next i
    IsInArray = False
End Function

使い方:

  1. コード内の saveFolderPath を自分の保存先フォルダに書き換える
  2. skipSheets にスキップしたいシート名を追加・削除する
  3. Alt + F8 →「SplitSheetsByMonth」を選択して実行
  4. 確認ダイアログで「はい」を押す
  5. 各シートが個別の .xlsx ファイルとして保存される

保存先フォルダの自動作成: 保存先フォルダが存在しない場合、FileSystemObjectCreateFolder で自動作成する。MkDir ではなく FileSystemObject を使っている理由は、パスの存在確認(FolderExists)とフォルダ作成を同じオブジェクトで統一的に扱えるからだ。ファイルの存在確認も参考にしてほしい。

スキップ対象の管理: skipSheets = Array("目次", "集計") でスキップするシート名を管理。追加・削除は Array(...) 内を変更するだけ。補助関数 IsInArray で配列内に値が含まれるかチェックしている。Dictionaryを使えばより高速に判定できるが、シート数が数十枚程度なら配列ループで十分だ。

GoTo NextSheet の設計: VBAには Continue For がないため、ループ内でスキップするには GoTo ラベルを使うのが定番パターンだ。ネストを深くせずに読みやすいコードが書ける。

ファイル名の規則: シート名がそのままファイル名になる。シート名に \ / : * ? " < > | が含まれると保存に失敗するので注意。

複数シートに同じ処理を一括実行する方法(ヘッダー挿入や書式設定など)は 複数シートを一括処理する方法 を参照。

よくある落とし穴5選

1. Copy のつもりで Move を使い、元シートが消えた

自分もこれをやらかした。Sheets.Move を使ったら元ブックからシートが消えた。Move は「移動」だから当然なのだが、Copy のつもりで書いていた。メソッド名の1文字違いで元データを失いかけた。バックアップがあったから助かったが、冷や汗ものだった。

対策: CopyMove は意味が全く違う。まずは Copy で試し、移動が必要な場合のみ Move を使う。Move を使うときは必ずバックアップを取る。

2. コピー先ブックが開いていなくてエラー

原因: Workbooks("コピー先.xlsx") は開いているブックのみ参照できる。閉じているブックを指定すると「インデックスが有効範囲にありません」エラーになる。

対策: コピー先ブックを事前にExcelで開いておく。またはコード内で Workbooks.Open を使って開く。

3. 数式が外部参照に変わってしまう

原因: コピー元シートに他のシートを参照する数式(例: =Sheet2!A1)があると、コピー後に外部参照(=[元ブック.xlsm]Sheet2!A1)に変わる。

対策: 数式ではなく値だけコピーしたい場合は、Sheets.Copy ではなく、新規シートを作って PasteSpecial xlPasteValues で値のみ貼り付ける。

4. ブック内最後の1シートを Move するとエラー

原因: Excelのブックには最低1枚のシートが必要。最後の1シートを Move しようとすると「オブジェクトが必要です」エラーになる。

対策: Move を実行する前にシート数をチェックする。If srcBook.Worksheets.Count <= 1 Then で事前に判定。

5. シート名にファイル名に使えない文字が含まれている

原因: シート名をファイル名に使って保存する場合(実務版)、シート名に \ / : * ? " < > | が含まれていると保存に失敗する。

対策: シート名からこれらの文字を除去するか、事前にシート名を変更しておく。

VBAでシートコピー時に名前の重複エラーが出るときの対処法

「Sheets.Copyを実行すると『この名前は既に使われています』エラーが出る」という場合、原因はコピー先ブックに同名のシートが既に存在していることだ。通常Excelはコピー時に自動リネーム(例:「売上データ (2)」)するが、名前付き範囲やテーブルの名前が重複しているとエラーになることがある。対処法はコピー前にコピー先ブックのシート一覧をチェックし、同名シートがあればリネームまたは削除すること。補助関数 SheetExists を使えば存在チェックが簡単にできる。自分も同名シートの存在に気づかず、2回目の実行でエラーが出て焦ったことがある。

VBAのSheets.Copyが別ブックに失敗するときの対処法

「Sheets.Copyで別ブックにコピーしようとしたら『インデックスが有効範囲にありません』エラーが出る」という場合、原因はコピー先ブックがExcelで開かれていないことだ。Workbooks("コピー先.xlsx") は現在開いているブックのみ参照できる仕様で、閉じているブックを指定するとエラーになる。対処法はコピー先ブックを事前にExcelで開いておくか、コード内で Set dstBook = Workbooks.Open("パス") を使って自動で開くこと。もう1つありがちなのはブック名のスペルミスで、拡張子(.xlsx / .xlsm)まで含めて正確に指定する必要がある。

---

FAQ

Q1: コピー先ブックが閉じている場合、自動で開いてコピーしたい

Workbooks.Open でコピー先ブックを開いてからコピーする:


Dim dstBook As Workbook
Set dstBook = Workbooks.Open("C:\Users\(ユーザー名)\Desktop\コピー先.xlsx")

ThisWorkbook.Worksheets("売上データ").Copy _
    After:=dstBook.Sheets(dstBook.Sheets.Count)

dstBook.Save
dstBook.Close

Q2: コピーしたシートの名前を変えたい

コピー直後は、コピーされたシートがアクティブになる。そのタイミングで名前を変更する:


ThisWorkbook.Worksheets("売上データ").Copy _
    After:=dstBook.Sheets(dstBook.Sheets.Count)

' コピー直後のアクティブシートが、コピーされたシート
ActiveSheet.Name = "売上データ_202603"

Q3: シートではなくファイルをコピー・移動したい

シート単位ではなくファイル単位でコピー・移動する方法は ファイルを別フォルダにコピー・移動する方法 を参照。

Q4: 複数ブックのデータを1つに統合したい(逆の操作)

分割ではなく統合したい場合は 複数Excelファイルを1つに統合 を参照。

Q5: コピー後に元ブックのシートを削除したい

Copy した後に元シートを削除すれば、実質 Move と同じ動作になる。削除前に確認ダイアログを入れると安全:


' コピー
ThisWorkbook.Worksheets("売上データ").Copy _
    After:=dstBook.Sheets(dstBook.Sheets.Count)

' 確認してから元シートを削除
If MsgBox("元シートを削除しますか?", vbYesNo + vbExclamation) = vbYes Then
    Application.DisplayAlerts = False  ' 削除確認を抑制
    ThisWorkbook.Worksheets("売上データ").Delete
    Application.DisplayAlerts = True
End If

---

まとめ

  • Sheets.Copy After:= で別ブックの末尾にシートをコピーできる
  • Sheets.Copy(引数なし)で新規ブックにコピーできる
  • Sheets.Move は元ブックからシートがなくなる。必ずバックアップを取ってから使う
  • コピー先ブックは事前に開いておく必要がある
  • 月別シートの分割保存は、ループ + 引数なし Copy + SaveAs で実現できる

シートのコピー・移動は、月次報告や拠点別データの配布など、実務で頻繁に使う操作だ。まずは最小版で1シートのコピーを試し、動きを確認してから応用版・実務版に進むのがおすすめだ。自分は最初、月別シートの分割保存に30分かかっていたが、実務版マクロを導入してからは数秒で12ファイルが自動生成されるようになった。配布先ごとにファイルを分けたい業務では特に効果が大きいので、ぜひ試してみてほしい。分割保存で作ったファイルをブックの保存の仕組みで自動バックアップしたり、CSV書き出しで他システム用に変換したりと、組み合わせの幅が広い。

関連記事

---

次にやりたくなること

---

もっとカスタマイズしたい場合

「特定条件のシートだけ別ブックに振り分けたい」「コピー後にシート名を日付付きに変えたい」「コピーと同時にPDF出力もしたい」など、業務に合わせたカスタマイズが必要な場合は、ココナラで相談できる。

相談時に伝えると話が早い情報:

  • Excel のバージョン / OS
  • シートの枚数と構成(月別/拠点別など)
  • コピー先のブック名またはフォルダ構成
  • コピー後に行いたい処理(リネーム、書式変更など)

コメント

タイトルとURLをコピーしました