🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

Excel VBA でシートをコピーする — 新しいブックを生まずにワークシートを複製する

|

Excel VBA でシートをコピーする — 新しいブックを生まずにワークシートを複製する

TL;DRWorksheet.Copy は、Add で使うのと同じ Before:=After:= の位置指定を取りますが、誰もが引っかかる二つの違いがあります。第一に、何も返しませんSet ws = sheet.Copy は書けないので、できたてのコピーはすぐ次の行で ActiveSheet 経由で掴みます。 第二に、そしてこれが大物ですが、引数なしの ws.Copy はブック内でコピーせず、コピーを収めた真新し いブックを作ります。新しいファイルこそが望みでない限り、常に BeforeAfter を渡してください。

Sub DuplicateTemplate()
    Dim src As Worksheet, copy As Worksheet
    Set src = ThisWorkbook.Worksheets("Template")

    src.Copy After:=ThisWorkbook.Worksheets(Worksheets.Count)  ' 末尾に複製する
    Set copy = ActiveSheet                                     ' コピーがいまアクティブ
    copy.Name = "Template " & Format(Now, "hhmmss")            ' すぐにリネームする
End Sub

Worksheet.Copy は、タブを右クリック ▸ シートの移動またはコピー ▸ コピーを作成する のコード版です。 レポート系のマクロが毎月テンプレートから新しいシートを打ち出すのに使います。同時に、シート管理系の中で いちばん意外なメソッドでもあります。「当たり前」に見える呼び出し — 引数なしの Sheets("Template").Copy — が、名前から想像するのとはまったく別のことをするからです。

この記事で学べること

  • 考え方の軸 — CopyAdd の双子:同じ位置指定、戻り値なし
  • ほとんどのマクロを壊す驚き — 引数なしの Copy は新しいブックを生む
  • メソッドが何も返さないとき、コピーを参照する方法
  • コピーされたシートについてくるもの — 数式、書式、コード、そして定義された名前
  • Move が反対の意図で Copy を映し出す仕組み、そして別のブックへコピーする方法

考え方の軸:Copy は Add の双子、ただし戻り値なし

シートの追加とコピーは文法を共有します。どちらも シートがどこに着地するか を言うために Before:=After:= を受け取り、どちらも末尾ではなくある位置を既定にします。違いは、Add が新しいシートを手渡す 関数であるのに対し、Copy はまったく何も返さないメソッド だということです。Set ws = src.Copy は 書けません — コンパイルエラーになります。

そこで Excel が、できたての複製を掴む方法をちょうど一つだけ残しています — Copy が走った直後、コピーが アクティブシート になるのです。ほかの何かがフォーカスを奪う前に、次の行で掴んでください。

src.Copy After:=Worksheets(Worksheets.Count)
Dim copy As Worksheet
Set copy = ActiveSheet          ' これがコピー - いま掴む

ここは、ActiveSheet に頼るのがだらしなさではなく正しい、数少ない場面の一つです。Copy は本当に新しい シートをアクティブなまま残し、それ以上の取っ手がないからです。肝心なのは すぐに やることです — CopySet copy = ActiveSheet のあいだに挟まった CalculateDoEvents、あるいはイベントハンドラーがフ ォーカスを動かし、間違ったシートを掴ませることがあります。

ほとんどのマクロを壊す驚き:引数なしの Copy は新しいブックを生む

人を検索エンジンへ走らせる挙動がこれです。引数なしの Sheets("Template").Copy は、現在のブックの中でシ ートを複製する、と当然のように期待するでしょう。しません。BeforeAfter もない Copy は、シー ト一枚だけの新しいブックを作り、そこにコピーを置きます。ループで回せば、新しいタブの山ではなく、新し いウィンドウの山ができあがります。

src.Copy                        ' ローカルの複製ではない - まるごと新しいブックが現れる

ルールは単純です — ブック内で複製したいなら、常に行き先を渡す。とはいえ、引数なしの形はバグではあ りません — 一枚のシートを独立したファイルとして書き出す のに、VBA じゅうで最もきれいな定番の書き方で す。

src.Copy                                 ' このシートだけの新しいブック
ActiveWorkbook.SaveAs "C:\Reports\September.xlsx", FileFormat:=xlOpenXMLWorkbook
ActiveWorkbook.Close SaveChanges:=False

つまり同じメソッドが、たった一つの引数の有無で二つの意図に仕えます。どちらのつもりかを決め、After の 欠落が「このタブを複製する」を「ブックを四十個開く」に変えてしまわないようにしてください。

コピーされたシートについてくるもの

Copy は値だけでなく オブジェクト を複製します — そしてそれは、多くの人が思い描くより多くを含みま す。コピーされたシートは、数式、書式、グラフ、図形、条件付き書式、そのシートモジュールのコード、そ して シート単位で定義された名前 を持ってきます。ここから二つの帰結が生まれます。

  • ほかのシートを参照していた数式は、その参照を保ちます。だから同じブック内のコピーは、こっそり元シ ートの隣人を指し返すことがあります — 参照を張り替えたかったのか確認してください。
  • 複製された定義名 は定番の副作用です。スコープ付きの名前を持つシートをコピーすると、Excel はすでに 存在する名前について確認を求めるか、あるいは黙って二つ目の、別スコープの名前を作ります。

データ だけが欲しいなら、シートをコピーしてはいけません — 範囲をコピーします。 dst.Range("A1:Z100").Value = src.Range("A1:Z100").Value は、荷物を一切連れずに値を移します。シート全 体のコピーが正しい道具になるのは、テンプレート — レイアウト、数式、コード — をそっくりそのまま再現した いと意図的に望むときです。

コピーの命名、そして Move が Copy を映し出す仕組み

Excel は複製を Template (2)Template (3) のように自動命名するので、ほとんど必ずすぐにリネームしま す。戻り値がないので、Copy の直後の行でアクティブシート経由でリネームし、Add の記事と同じルールが当てはまります — 31 文字、一意、: \ / ? * [ ] は不可。

Worksheet.MoveCopy の鏡像です。まったく同じ Before:=After:= 引数を取りますが、シートを 複製するのではなく 移動 させ、行き先のない引数なしの Moveまた 新しいブックを開きます — シー トを現在のブックから丸ごと外へ出すのです。引数の形は同じ、意図は反対です。

src.Move After:=Worksheets(Worksheets.Count)   ' 末尾へ移動(複製ではない)
src.Copy To:=Workbooks("Report.xlsx").Worksheets(1)   ' 別の開いているブックの中へコピー

別のブックへコピーするには、その BeforeAfter 引数でそのブックのシートを指定します — 両方のファイ ルが開いている必要があります。メソッド全体を貫く判断はこうです。常に行き先を渡し、コピーは次の行で ActiveSheet 経由で掴み、コピーがコードと名前を連れてくることを忘れず、引数なしの形に手を伸ばすのは 「新しいブック」が本当の目的のときだけにする。

ExcelMaster の活用

シートのコピーは地雷を隠しています — 引数なしの形が、複製ではなく新しいブックを開くのです — そして二つ の静かな罠も。掴むべき戻り値がないこと、そしてコピーが自分のコードと定義名を引きずってくることです。

ExcelMaster には、意図をそのまま 伝えられます — 「Template シートを末尾に複製して、今日の日付で名前を付けて」あるいは「このシートを独立 したファイルとして書き出して」 — すると、それぞれに正しい形を書きます。ブック内の複製には、位置指定した CopyActiveSheet の受け取りとリネームを添えた形。書き出しには、引数なしの CopySaveAs を 足した形。さらに、コピーされるシートが衝突する数式や名前を抱えているときには警告します。ブックとコード はあなたの手元に残ります。

よくある質問

VBA でワークシートをコピーするには?

行き先を付けて Worksheet.Copy を使います — src.Copy After:=Worksheets(Worksheets.Count) はシートを 末尾に複製します。Copy は何も返さないので、新しいシートは次の行で ActiveSheet 経由で掴みます — Set copy = ActiveSheet — それからリネームします。常に Before:=After:= を渡してください。引数 なしの形は別のことをします。

Copy マクロが新しいブックを開いてしまうのはなぜ?

CopyBeforeAfter も付けずに呼んだからです。引数なしの Worksheet.Copy は、現在のブックの 中で複製しません — コピーを収めた、シート一枚だけの新しいブックを作ります。その場で複製するには行き先 (After:=Worksheets(Worksheets.Count))を渡し、引数なしの形は、シートを独立したファイルとして書き出す 用途に取っておきましょう。

コピーされたシートへの参照を得るには?

Copy に戻り値はないので、Set ws = src.Copy は書けません。代わりに、呼び出しの直後にコピーがアクティ ブシートになるので、すぐ次の行で Set copy = ActiveSheet として掴みます — CalculateDoEvents、 イベントハンドラーがフォーカスを動かして間違ったシートを掴ませる前に。

シートを別のブックにコピーするには?

両方のファイルを開いた状態で、位置指定の引数の中で相手のブックのシートを指定します — src.Copy After:=Workbooks("Report.xlsx").Worksheets(Worksheets.Count)。コピーは数式、書式、コードを連 れていきます。元のブックを参照していた数式には注意してください — 元ファイルを指し返すことがあります。

Copy と Move の違いは?

Worksheet.Copy はシートを複製し、Worksheet.Move はそれを移動させて、元の位置から取り除きます。どち らも同じ Before:=After:= 引数を取り、どちらも行き先なしで呼ぶと新しいブックを開きます。複製を打ち 出すには Copy、シートを並べ替えたり抜き出したりするには Move を使います。

検証環境

検証環境: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-09-14。

関連ガイド: VBA シートの追加 · VBA シートの削除 · VBA Worksheets · VBA ブックを開く · VBA ThisWorkbook