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

Excel VBA でシートを追加する — ワークシートを作成し、正しく手元に捕まえる

|

Excel VBA でシートを追加する — ワークシートを作成し、正しく手元に捕まえる

TL;DRWorksheets.Add作成したばかりのシートを戻り値として返します。その戻り値を Set ws = Worksheets.Add(...) で受け取れば、どれが新しいシートかを二度と当てずっぽうで探さなくて 済みます。誰もがつまずくのは位置と名前の二つです。引数なしの Worksheets.Add はシートをアクティブ シートの に落とし(末尾ではありません)、名前は Add の呼び出しの中では渡せません — .Name を後から設定するのですが、そこで重複・空白・長すぎる名前は実行時エラー 1004 を投げます。

Sub AddMonthSheet()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Worksheets.Add(After:=Worksheets(Worksheets.Count))
    ws.Name = "Sep 2026"          ' 31 文字以内・一意・: \ / ? * [ ] を含まない
End Sub

Worksheets.Add は、ホーム ▸ 挿入 ▸ シートの挿入 と、タブ横の小さな + ボタンのコード版です。 レポート系のマクロが最初にやることの一つであり、毎回きまって同じ二か所で失敗します — シートが予想し ない場所に現れるか、リネームの行が吹き飛ぶかです。どちらの問題も、Add を「シートを探しに行かせるコ マンド」ではなく「完成したシートを 手渡してくれる ファクトリー」として捉えた瞬間に消えます。

この記事で学べること

  • 考え方の軸 — Add は新しいシートを返すので、それを受け取って ActiveSheet に頼るのをやめる
  • ほとんどのバグを防ぐ唯一のルール — 戻り値を Worksheet 型の変数に代入する
  • なぜ引数なしの Add はシートを左に落とすのか、そして BeforeAfter でどう直すのか
  • なぜ Add の中で名前を付けられないのか、そして .Name が 1004 を投げるルール
  • すでに存在するときだけ追加しない方法

考え方の軸:Add はシートを手渡す

Worksheets.Add は、投げっぱなしのコマンドではありません。シートを作成し、それへの参照を返す 関数で す。最も多い間違いは、その参照を捨ててしまうことです。

Worksheets.Add                    ' 新しいシートが作られ...そして見失われる
Worksheets(Worksheets.Count).Name = "Data"   ' どこへ行ったか当てずっぽう

二行目は当てずっぽうです。新しいシートが末尾にあると決めてかかっていますが、既定ではそうならないので、 間違ったタブをリネームします。その先のすべて — 見出しの書き込み、書式設定、数式の追加 — が、運任せに 選ばれたシートを狙うことになります。代わりに戻り値を受け取れば、当てずっぽうは永遠になくなります。

Dim ws As Worksheet
Set ws = Worksheets.Add
ws.Name = "Data"                  ' これは紛れもなく、いま作ったシートそのもの

いったん ws が本物のオブジェクトを保持すれば、位置は 正しさ の観点では問題でなくなります — シート をどこに置こうと、コードは正しいシートと会話し続けます。

最も大事なルール:戻り値を代入する

信頼できるシート追加ルーチンは、どれも同じ形で始まります — Set ws = Worksheets.Add(...)。これは、バ グのカテゴリを丸ごと取り除くルールです。もろい代替案は二つとも、ごく普通の条件で壊れるからです。

  • Add のあとの ActiveSheetたいてい 新しいシートを指します — が、イベントや Calculate、ある いは別の行が先にフォーカスを動かしていれば、そうはなりません。慣習であって、保証ではありません。
  • Sheets(Sheets.Count) は新しいシートが末尾にあると決めてかかりますが、それが真なのは、そこに追加し た場合だけです。

戻り値は、シートがどこに着地しようと、次に何が走ろうと、常に、即座に正しい唯一の参照です。「シートを 追加する」と「シートを手元に握る」を、分けられない一つのステップとして扱ってください。

位置決め:Before、After、そしてなぜ既定は左に落ちるのか

Worksheets.AddBefore:=After:= の引数を取ります — その前に挿入するシート、あるいは後ろに 挿入するシートです。渡すのは多くても一つ。どちらも 渡さないと、Excel は新しいシートを アクティブシ ートのすぐ前 に挿入します。これは初回にほぼ全員を驚かせます — 人は「末尾」を期待するのに、タブはブッ クの真ん中に現れるのです。

末尾に追加するには — 実際にほとんどのマクロが望む位置です — After で最後のシートに錨を下ろします。

Set ws = Worksheets.Add(After:=Worksheets(Worksheets.Count))   ' 常に末尾
Set ws = Worksheets.Add(Before:=Worksheets(1))                 ' 常に先頭

Worksheets(Worksheets.Count) は「最後のワークシート」を表す定番の書き方です。数えているのは ワークシ ート であって全シートではない点に注意してください — ブックがグラフシートも持っていれば、Sheets.CountWorksheets.Count は食い違います。迷ったら明示的に位置を指定しましょう。人が読むコードで、アクティ ブシートの左という既定に頼ってはいけません。

命名こそ Add がクラッシュする場所

AddName 引数はありません。シートを作成し、それから受け取ったオブジェクトに .Name を設定しま す。実行時エラー 1004 が棲んでいるのはこの二段目です。Excel はシート名に厳格なルールを課すからで — しか もそのルールは、新品のシートに名前を付けるときも、古いシートをリネームするときも 同じ です。

  • 31 文字まで
  • ブック内で 一意 でなければならない(大文字小文字は区別しない) — 重複が一番多いクラッシュ原因
  • 空白にできない
  • : \ / ? * [ ]含められない

どれか一つでも破ると .Name = ... は 1004 を投げます。最も多い引き金は、すでに一度 "Data" を作った マクロを再実行することです — 二回目の実行で衝突します。作成とリネームでルールが同一なので、名前を一か 所で守っておく価値があります。

Function SafeName(nm As String) As String
    nm = Left$(nm, 31)
    Dim bad As Variant, ch As Variant
    For Each ch In Array(":", "\", "/", "?", "*", "[", "]")
        nm = Replace(nm, ch, "-")
    Next ch
    SafeName = nm
End Function

これで長さと不正文字は片付きます。一意性は、先に確認することで扱います — それが次の節です。

すでに存在するときだけ追加しない

シートに組み込みの Exists はないので、再実行時の衝突を防ぐのはあなたの仕事です。追加する前に名前でコ レクションを確認し、すでにあればそのシートを再利用します。

Function GetOrAddSheet(nm As String) As Worksheet
    Dim ws As Worksheet
    For Each ws In ThisWorkbook.Worksheets
        If StrComp(ws.Name, nm, vbTextCompare) = 0 Then
            Set GetOrAddSheet = ws          ' 既存のものを再利用
            Exit Function
        End If
    Next ws
    Set GetOrAddSheet = ThisWorkbook.Worksheets.Add(After:=Worksheets(Worksheets.Count))
    GetOrAddSheet.Name = nm                 ' 自由に命名できる - 未使用だと分かっている
End Function

これは、初回は動くのにその後は永遠に 1004 を投げるマクロではなく、シート追加マクロを 冪等 に — 二度 実行しても安全に — するパターンです。判断はこうです。二回以上走るかもしれないルーチンで、Add.Name を盲目的に呼んではいけません。まず名前を調べ、再利用するか作成するかのどちらかにします。

ExcelMaster の活用

シートの追加は一行に見えて、三つの判断を隠しています — 戻り値を受け取る、位置を選ぶ、正当で一意な名前 を作る — そしてどれを間違えても、静かに(間違ったタブをリネーム)あるいは派手に(二回目の実行でエラー 1004)失敗します。

ExcelMaster には、望むことをそのま ま伝えられます — 「今月の名前を付けた月次シートを末尾に追加して、すでにあれば再利用して」 — すると、 Set ws = Worksheets.Add(After:=...) の受け取りを書き、正しい場所に追加し、31 文字ルールと不正文字ルー ルに照らして名前を整え、まずコレクションを確認して、二回目の実行がクラッシュせずシートを再利用するよう にします。ブックとコードはあなたの手元に残ります。

よくある質問

VBA でシートを追加して名前を付けるには?

戻り値を受け取り、それに .Name を設定します — Set ws = Worksheets.Add(After:=Worksheets(Worksheets.Count))、 それから ws.Name = "Data"Add 自体に Name 引数はありません。名前は 31 文字以内、ブック内で一意、 空白でなく、: \ / ? * [ ] を含まないこと。さもないと .Name が実行時エラー 1004 を投げます。

新しいシートが変な位置に現れるのはなぜ?

引数なしの Worksheets.Add が、末尾ではなく アクティブシートのすぐ前 にシートを挿入するからです。 Before:=After:= で制御します。末尾に追加するなら Worksheets.Add(After:=Worksheets(Worksheets.Count))、 先頭に置くなら Worksheets.Add(Before:=Worksheets(1)) を使います。

シートの追加や命名でエラー 1004 が出るのはなぜ?

ほぼ必ず名前ルール違反で、たいていは重複です。シート名は一意でなければならないので、すでに "Data" を 作ったマクロを再実行すると二回目で衝突します。名前はさらに、31 文字以内、空白でなく、: \ / ? * [ ] を 含まないこと。追加する前にコレクションで名前を確認し、まず文字列を整えましょう。

すでに存在するときは追加しないようにするには?

Exists メソッドはないので、Worksheets コレクションをループし、StrComp(ws.Name, nm, vbTextCompare) = 0 で名前を比較します。一致すればそのシートを再利用し、なければ Add を呼んで命名します。これを GetOrAddSheet 関数に包めば、マクロを繰り返し実行しても安全になります。

ブックのいちばん末尾にシートを追加するには?

最後のワークシートに錨を下ろします — Worksheets.Add(After:=Worksheets(Worksheets.Count))Worksheets(Worksheets.Count) が最後のワークシートなので、その 後ろ に挿入すれば末尾に追加されます。 Worksheets.Count の代わりに Sheets.Count を使うのは、グラフシートも意図的に数えたいときだけにしまし ょう。

検証環境

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

関連ガイド: VBA シートのコピー · VBA シートの削除 · VBA Worksheets · VBA Worksheet · VBA ThisWorkbook