この記事でできること
VBAでテンプレートシートをコピーし、月別(4月〜3月)・担当者別にシートを一括生成できるようになる。
- 対象:テンプレートシートを手作業でコピー&リネームしている人
- 所要時間:コピペ → 実行まで5分
—
どんな場面で使う?
- 月別シートの一括作成: 4月〜3月の12ヶ月分のシートをテンプレートから一気に作成する
- 担当者別シートの量産: 営業担当者や拠点ごとにシートを作成し、名前やタイトルまで自動書き換え
- 年度替わりの準備作業: 新年度のブックを作るとき、12ヶ月分×5担当者=60シートを手作業で作る代わりにVBAで一発生成
- プロジェクト別の管理シート作成: プロジェクト一覧からテンプレートをコピーして、プロジェクト名・開始日を自動設定
- イベントや研修の参加者別シート: 参加者リストからシートを量産し、名前や所属を自動転記
—
完成イメージ(Before / After)
Before(手作業)
| 操作 | 回数 |
|---|---|
| シートタブを右クリック →「移動またはコピー」 | 12回(月別の場合) |
| シート名を1つずつ変更 | 12回 |
| テンプレート内のタイトルセルを手修正 | 12回 |
合計36回の手作業。担当者が10人なら、さらに10倍。
After(VBA実行後)
- 実行ボタンを1回押すだけで、テンプレートシートから12枚(月別)や任意の枚数(担当者別)のシートが自動生成される
- シート名もセル値も自動で書き換え済み
—
導入
自分も毎月、テンプレートシートを右クリック → コピー → シート名変更 → タイトルセル修正、を12回繰り返していた。担当者が5人いるチームだと、12ヶ月分×5人=60シート。右クリック → コピー → 名前変更を60回繰り返すと、それだけで1時間以上かかる。しかもシート名を間違えて作り直したり、コピー元を間違えて書式が崩れたりで、精神的にもかなりキツい作業だった。
VBAで自動化してからは、リストシートに名前を並べてボタンを1回押すだけで、60枚のシートが数秒で揃うようになった。シート名もセル内のタイトルも自動で書き換わるので、コピー後の手修正がゼロ。
この記事で、同じように手作業のシートコピーに時間を取られている人がサクッと自動化できるようになればうれしい。
前提条件
– Excel 2016以降 / Microsoft 365
– Windows 10/11
– ファイルは
.xlsm(マクロ有効ブック)で保存
– コードは 標準モジュール に貼り付け
– 実行方法:Alt + F8 →マクロ選択 → 実行
VBE(コードを書く画面)の開き方や標準モジュールの挿入がわからない場合は、シートを別ブックにコピー・移動する方法の手順を参考にしてください。
—
手順
- Excelファイルを
.xlsmで保存する - ファイル → 名前を付けて保存 → ファイルの種類を「Excelマクロ有効ブック (*.xlsm)」に変更
- テンプレートシートを用意する
- シート名を「テンプレート」にする(コード内のシート名と合わせる)
- VBEを開く
- Alt + F11 キーを押す
- 標準モジュールを挿入する
- VBE画面の左側「VBAProject」を右クリック → 挿入 → 標準モジュール
- コードを貼り付ける
- 下記のコードをコピーして貼り付ける
- マクロを実行する
- Alt + F8 → マクロ名を選択 → 実行
実行前に必ずバックアップを取ってください。 シートのコピーは元に戻す(Ctrl+Z)が効きません。
—
基本コード(月別シートを単純コピー)
まずはこれで動く最小限のコード。テンプレートシートを12回コピーして、4月〜3月のシート名を付ける。
Sub テンプレートから月別シート作成()
Dim wsTemplate As Worksheet
Dim i As Long
Dim sheetName As String
Set wsTemplate = ThisWorkbook.Worksheets("テンプレート")
For i = 4 To 15
' 4月〜翌3月の月名を生成
If i <= 12 Then
sheetName = i & "月"
Else
sheetName = (i - 12) & "月"
End If
' 同名シートが既にあればスキップ
If Not SheetExists(sheetName) Then
wsTemplate.Copy After:=ThisWorkbook.Worksheets(ThisWorkbook.Worksheets.Count)
ActiveSheet.Name = sheetName
End If
Next i
MsgBox "月別シートの作成が完了しました。", vbInformation
End Sub
Function SheetExists(ByVal name As String) As Boolean
Dim ws As Worksheet
On Error Resume Next
Set ws = ThisWorkbook.Worksheets(name)
On Error GoTo 0
SheetExists = Not ws Is Nothing
End Function
ポイント
Copy After:=で末尾にコピーを追加SheetExists関数で重複を防止(2回実行してもエラーにならない)- シート名の存在チェックにはシート名の取得・一括変更・存在チェックする方法も参考になる
コード解説: For i = 4 To 15 のループで4月〜翌3月の12ヶ月分を処理している。i が12以下なら i & "月"(4月〜12月)、13以上なら (i - 12) & "月"(1月〜3月)としてシート名を生成する。wsTemplate.Copy After:=ThisWorkbook.Worksheets(ThisWorkbook.Worksheets.Count) はテンプレートシートをブックの末尾にコピーする命令で、コピー直後に ActiveSheet が新しいシートを指すので、そこで .Name プロパティにシート名を設定している。SheetExists 関数は On Error Resume Next を使って同名シートの取得を試み、エラーが出れば存在しない(False)と判定するシンプルなテクニック。
—
実務版コード(リストからシート名を読み取って量産+セル値書き換え)
自分はこの実務版を使うようになってから、月別だけでなく担当者別・拠点別のシート作成も全部これ1本で回している。テンプレートの中身(タイトルや日付)まで自動で書き換わるので、コピー後の手修正がゼロになった。
Sub テンプレートからシート量産()
'================================================
' 「リスト」シートのA列にシート名の一覧を用意しておく
' テンプレートシートをコピーし、シート名とセル値を自動設定
'================================================
Dim wsTemplate As Worksheet
Dim wsList As Worksheet
Dim wsNew As Worksheet
Dim lastRow As Long
Dim i As Long
Dim newName As String
Set wsTemplate = ThisWorkbook.Worksheets("テンプレート")
Set wsList = ThisWorkbook.Worksheets("リスト")
' リストシートのA列からシート名を取得
lastRow = wsList.Cells(wsList.Rows.Count, "A").End(xlUp).Row
If lastRow < 2 Then
MsgBox "リストシートのA列(A2以降)にシート名を入力してください。", vbExclamation
Exit Sub
End If
' 画面更新を停止して高速化
Application.ScreenUpdating = False
For i = 2 To lastRow
newName = Trim(wsList.Cells(i, "A").Value)
' 空白セルはスキップ
If newName = "" Then GoTo NextItem
' シート名に使えない文字をチェック
If InStr(newName, ":") > 0 Or InStr(newName, "\") > 0 Or _
InStr(newName, "/") > 0 Or InStr(newName, "?") > 0 Or _
InStr(newName, "*") > 0 Or InStr(newName, "[") > 0 Or _
InStr(newName, "]") > 0 Then
Debug.Print "スキップ(禁止文字): " & newName
GoTo NextItem
End If
' シート名が31文字を超える場合はスキップ
If Len(newName) > 31 Then
Debug.Print "スキップ(31文字超): " & newName
GoTo NextItem
End If
' 同名シートが既にあればスキップ
If SheetExists(newName) Then
Debug.Print "スキップ(既存): " & newName
GoTo NextItem
End If
' テンプレートをコピー
wsTemplate.Copy After:=ThisWorkbook.Worksheets(ThisWorkbook.Worksheets.Count)
Set wsNew = ActiveSheet
wsNew.Name = newName
' ---- ここが追加:テンプレート内のセル値を書き換え ----
' B列の値があればセルA1(タイトル)に設定
If wsList.Cells(i, "B").Value <> "" Then
wsNew.Range("A1").Value = wsList.Cells(i, "B").Value
Else
wsNew.Range("A1").Value = newName
End If
' C列の値があればセルA2(日付や補足)に設定
If wsList.Cells(i, "C").Value <> "" Then
wsNew.Range("A2").Value = wsList.Cells(i, "C").Value
End If
' ---- 追加ここまで ----
NextItem:
Next i
Application.ScreenUpdating = True
MsgBox "シートの量産が完了しました。", vbInformation
End Sub
Function SheetExists(ByVal name As String) As Boolean
Dim ws As Worksheet
On Error Resume Next
Set ws = ThisWorkbook.Worksheets(name)
On Error GoTo 0
SheetExists = Not ws Is Nothing
End Function
リストシートの構成例
| A列(シート名) | B列(タイトル) | C列(補足) | |
|---|---|---|---|
| 1行目 | シート名 | タイトル | 補足 |
| 2行目 | 4月 | 4月度 売上報告 | 2026年4月 |
| 3行目 | 5月 | 5月度 売上報告 | 2026年5月 |
| 4行目 | 田中 | 田中担当分 | 東京エリア |
この方法なら、リストシートの内容を変えるだけで月別でも担当者別でも拠点別でも対応できる。同僚に渡すときも「リストシートに名前を入れて実行してね」で済むので、VBAを知らない人でも使える。
—
落とし穴
自分も最初、シート名に「/」を含む名前(「2026/04」など)を入れてしまい、実行時エラー1004で止まった。原因がわかるまで30分くらい溶かした。
| # | 症状 | 原因 | 対策 |
|---|---|---|---|
| 1 | 実行時エラー 1004「そのシート名は正しくありません」 | シート名に使えない文字(: \ / ? * [ ])が含まれている |
実務版コードでは禁止文字チェックを追加済み。リストに入力する名前を事前に確認する |
| 2 | 実行時エラー 1004「同じ名前は使用できません」 | 同名のシートが既に存在する | SheetExists 関数で事前チェックしている。2回目以降の実行でも安全 |
| 3 | シート名が途中で切れる | シート名は最大31文字の制限がある | 31文字を超える名前は実務版コードでスキップされる。短い名前にする |
| 4 | テンプレートの書式が崩れる | テンプレートシートにフィルタやグループ化が設定されていると、コピー時に意図しない状態になることがある | コピー前にテンプレートのフィルタを解除しておく。複数シートに同じ処理を一括実行する方法でフィルタ解除を自動化できる |
| 5 | シートが大量にできて動作が重い | シート数が多すぎるとExcel自体の動作が遅くなる | 1ブックあたり50枚程度を目安にする。それ以上はシートを別ブックにコピー・移動する方法でブックを分割する |
| 6 | Ctrl+Z(元に戻す)が効かない | VBAで追加したシートは「元に戻す」の対象外 | 実行前にバックアップを取る習慣をつける |
VBA シートコピー 名前 重複エラーの対処
Sheet.Copy でシートをコピーした後に ActiveSheet.Name = "4月" のようにシート名を設定すると、同名のシートが既に存在する場合に実行時エラー1004が発生する。このエラーを防ぐには、名前を設定する前に SheetExists 関数で同名シートの有無をチェックする(実務版コードでは対応済み)。もう1つのパターンとして、2回目の実行時に前回作成したシートが残っている場合がある。この場合は、既存シートを削除してから再実行するか、スキップして次に進む設計にする。削除する場合は Application.DisplayAlerts = False でExcelの確認ダイアログを抑制する必要がある。
VBA テンプレート 量産 遅い場合の高速化
シートを50枚以上コピーすると処理が目に見えて遅くなることがある。まず Application.ScreenUpdating = False で画面更新を停止する(実務版コードでは対応済み)。これだけで体感速度が大幅に改善する。それでも遅い場合は、Application.Calculation = xlCalculationManual で自動計算を一時停止し、処理後に xlCalculationAutomatic に戻す。テンプレートに大量の数式や条件付き書式が入っていると、コピーのたびに再計算が走るため、これが効果的。詳しくは 処理時間を計測してボトルネックを見つける方法 でどこに時間がかかっているか特定できる。
コピーしたシートの並び順がおかしい場合
Copy After:=ThisWorkbook.Worksheets(ThisWorkbook.Worksheets.Count) は常にブック末尾にシートを追加するので、リストの順番どおりにシートが並ぶ。ただし、途中でエラーが発生してスキップした場合、順番が飛ぶことがある。また、既存のシートが間に挟まっていると意図した並び順にならない。並び順を厳密に制御したい場合は、全シート作成後に Worksheets("4月").Move After:=Worksheets("テンプレート") のように Move メソッドで並べ替えるとよい。
—
FAQ
Q1. テンプレートシートに数式が入っていても大丈夫?
大丈夫です。Sheet.Copy はセルの値・数式・書式・条件付き書式・入力規則をすべてコピーします。ただし、他のシートを参照する数式(例:=Sheet1!A1)は参照先がコピー元のままになる場合があるので、コピー後に確認してください。
Q2. 年度(4月始まり)の順番でシートを並べたいが、順番がずれる
基本コードでは Copy After:=ThisWorkbook.Worksheets(ThisWorkbook.Worksheets.Count) で末尾に追加しているため、4月→5月→…→3月の順番になります。リストシートのA列に並べた順番どおりにシートが作成されます。
Q3. 特定のシートだけ削除してやり直したい
手動でシートタブを右クリック → 削除でOKです。VBAで一括削除する場合は、Application.DisplayAlerts = False を使いますが、削除は元に戻せないので必ずバックアップを取ってから実行してください。
Q4. ボタンを設置してワンクリックで実行したい
Excelで請求書を自動作成する方法でもボタン実行の手順を紹介しています。シート上にボタンを配置し、このマクロを割り当てれば、VBEを開かなくてもワンクリックで実行できます。
Q5. シート名ではなく日付(2026-04など)で作りたい
リストシートのA列に「2026-04」「2026-05」…と入力すればOKです。ただし「/」はシート名に使えないため、「2026/04」ではなく「2026-04」のようにハイフンで区切ってください。
—
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "テンプレートシートに数式が入っていても大丈夫?",
"acceptedAnswer": {
"@type": "Answer",
"text": "大丈夫です。Sheet.Copyはセルの値・数式・書式・条件付き書式・入力規則をすべてコピーします。ただし、他のシートを参照する数式は参照先がコピー元のままになる場合があるので、コピー後に確認してください。"
}
},
{
"@type": "Question",
"name": "年度(4月始まり)の順番でシートを並べたいが、順番がずれる",
"acceptedAnswer": {
"@type": "Answer",
"text": "基本コードではCopy After:=でブック末尾に追加するため、4月→5月→…→3月の順番で作成されます。リストシートのA列に並べた順番どおりにシートが作成されます。"
}
},
{
"@type": "Question",
"name": "特定のシートだけ削除してやり直したい",
"acceptedAnswer": {
"@type": "Answer",
"text": "手動でシートタブを右クリック→削除でOKです。VBAで一括削除する場合はApplication.DisplayAlerts = Falseを使いますが、削除は元に戻せないので必ずバックアップを取ってから実行してください。"
}
},
{
"@type": "Question",
"name": "ボタンを設置してワンクリックで実行したい",
"acceptedAnswer": {
"@type": "Answer",
"text": "シート上にボタンを配置し、このマクロを割り当てれば、VBEを開かなくてもワンクリックで実行できます。請求書自動作成の記事でもボタン実行の手順を紹介しています。"
}
},
{
"@type": "Question",
"name": "シート名ではなく日付(2026-04など)で作りたい",
"acceptedAnswer": {
"@type": "Answer",
"text": "リストシートのA列に「2026-04」「2026-05」…と入力すればOKです。ただし「/」はシート名に使えないため、ハイフンで区切ってください。"
}
}
]
}
—
まとめ
この記事では、VBAでテンプレートシートをコピーして月別・担当者別にシートを量産する方法を紹介した。手作業で右クリック → コピー → 名前変更を何十回も繰り返していた作業が、リストを用意してマクロを1回実行するだけで完了する。シート名の重複チェックや禁止文字チェックも入っているので、誰が何回実行しても安全に動作する。
- 基本コード:テンプレートを12回コピーして月名を付けるシンプルな方法
- 実務版コード:リストシートからシート名を読み取り、セル値まで自動書き換え
リストシートの内容を変えるだけで、月別・担当者別・拠点別など自由に応用できる。VBAを知らない同僚にも「リストに名前を入れて実行ボタンを押すだけ」で渡せるのが、この方法の大きな利点。
—
次にやりたくなること
テンプレートからシートを量産できたら、次はこのあたりが気になるはず。
- 量産したシートに同じ処理を一括で適用したい → 複数シートに同じ処理を一括実行する方法で、全シートへの書式変更やデータ集計をまとめて実行できる
- シート名を後から一括で変更したい → シート名の取得・一括変更・存在チェックする方法で、シート名の管理が楽になる
- 量産したシートを別ブックに分割して配布したい → シートを別ブックにコピー・移動する方法で、担当者ごとにブックを分けて渡せる
- 量産したシートから見積書や帳票を自動生成したい → 見積書・納品書をテンプレートから自動作成する方法で、テンプレート転記と帳票出力を組み合わせた実務パターンを紹介している
- 量産が遅いと感じたら → 処理時間を計測してボトルネックを見つける方法で、どの処理に時間がかかっているか特定し、高速化のヒントを得られる


コメント