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

Excel VBA のシート名変更 — リネームで自動更新されるもの、黙って壊れるもの

|

Excel VBA のシート名変更 — リネームで自動更新されるもの、黙って壊れるもの

TL;DR — ws.Name = "Sales 2026" でシート名が変わります。コードは一行で終わりますが、その影響は一行では終わりません。リネームは リファクタリング です。Excel は自分で 解析できる 参照 — セルの数式、名前定義、グラフの系列、入力規則のリスト — をすべて書き換えますが、ただの 文字列 である参照は、もう存在しない名前を指したまま放置します。INDIRECT の文字列、ハイパーリンクのリンク先、そして Worksheets("Sales") と書いたあなた自身のマクロです。リネームする前に、ブックがどちらの参照に頼っているかを把握しましょう。名前はセルから直接ではなく必ずサニタイズ関数を通して作り、自分のコードは CodeName に紐づけます。CodeName はどんなリネームにも影響されません。

Sub RenameMonthSheet()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Worksheets("Template")
    ws.Name = "Report " & Format(Date, "yyyy-mm")   ' 日付をそのまま使わない: 9/30/2026 には / が入る
End Sub

これは、シートの「身元」を扱う三部作の第一回です。シート見出しの名前は、ユーザーが持ち主のラベルです。リネーム はそのラベルを変え、非表示 はシートに手が届く状態のまま見出しを画面から消し、シートの存在確認 はラベルを信用する前にその名前が使われているかを確かめます。ユーザーの操作に耐えなければならないコードは、ユーザーが変えられないものに紐づけます。どうしても名前を使うコードは、まずその名前を確認します。

この記事で学べること

  • 考え方の軸:リネームは二種類の参照を持つリファクタリング
  • Excel が代わりに更新してくれるもの、黙って壊れたまま残すもの
  • エラー 1004 の裏にある命名ルールと、それを守るサニタイズ関数
  • 日付のセルからシート名を付けると、ある国では動き、別の国ではエラーになる理由
  • 一括リネームと、二つの名前を衝突させずに入れ替える方法
  • シート名を読み取る方法(VBA と数式の両方)

考え方の軸:リネームはリファクタリング

シートへの参照は、すべて二種類のどちらかです。解析される 参照とは、Excel がポインターとして理解しているものです — セルの =Sales!B4、Sales!$A$1:$A$50 を参照する名前定義、グラフの系列、データの入力規則のリスト。Excel はこれらをシートへのポインターとして保持しているので、名前が変わると文字列を代わりに書き換えてくれます。=Sales!B4 は ='Sales 2026'!B4 になり、スペースがあるので引用符も付け足されます。

文字列の 参照とは、たまたまシート名を綴っているだけの文字列です。Excel はそれがどこかを指しているとは知らないので、リネームしてもそのまま残り — 何も指さなくなります。

参照 種類 リネーム後
セル内の =Sales!B4 解析される 自動で更新
名前定義、グラフの系列、入力規則のリスト、条件付き書式 解析される 自動で更新
開いている 他のブックの数式 解析される 自動で更新
=INDIRECT("Sales!B4") 文字列 #REF!
=HYPERLINK("#Sales!A1", "Go") と挿入したハイパーリンク 文字列 リンク先が行方不明に
VBA の Worksheets("Sales") 文字列 実行時エラー 9
リネームの間 閉じていた ブックからのリンク 保存されたパス 次の更新で切れる

この表が、この記事全体の縮図です。リネームそのものが黙って失敗することはありません。黙って壊れるのは、その 文字列の参照 のほうです。

シート名を変更し、読み取る

仕組みは読み書きできるプロパティ一つだけです。

Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sales")

Debug.Print ws.Name              ' 読み取り: "Sales"
ws.Name = "Sales 2026"           ' 書き込み: シート見出しがすぐに変わる
Debug.Print ActiveSheet.Name     ' アクティブなシートの名前

上のように、リネームする前にシートを変数に入れておきましょう。名前が変わると Worksheets("Sales") ではもう見つかりませんが、変数は同じシートオブジェクトを指したままなので、マクロの残りは動き続けます。長く使うコードでシートの CodeName(VBA エディターのプロパティウィンドウで設定する Sheet3 など)を使うべきなのも同じ理由です。CodeName は VBA の中で解析される参照であり、どんなシート見出しのリネームでも壊れない理由は Worksheets のガイド で説明しています。CodeName はコードの実行中は読み取り専用なので、シート見出しの名前のようにマクロから CodeName を変更することはできません。

シート名をセルに表示するなら、コードではなく数式を使います。

' セルに入力 (Excel 365):  =TEXTAFTER(CELL("filename", A1), "]")
' 数式が入っているシートの名前を返す。ブックを保存するまでは空になる。

エラー 1004 の裏にある命名ルール

Excel はルールに反する名前を拒否し、どの拒否も同じ実行時エラー 1004 になります。

  • 31 文字以内で、空ではないこと。
  • : \ / ? * [ ] のいずれも含まないこと。
  • 先頭や末尾がアポストロフィでないこと。
  • ブック内の他のシートと同じ名前でないこと。大文字と小文字は区別されません(sales は Sales と衝突します)。
  • 英語版 Excel が変更履歴用のシートに予約している History でないこと。

新しいシートに最初の名前を付ける場面でのルールは シートの追加のガイド で扱っています。リネームについての実践的な答えは、きれいにしていない名前を決して代入しないことです。重複以外のすべてのルールは、小さなサニタイズ関数で処理できます。

Function SafeSheetName(ByVal s As String) As String
    Dim ch As Variant
    For Each ch In Array(":", "\", "/", "?", "*", "[", "]")
        s = Replace(s, ch, "-")
    Next ch
    s = Left$(Trim$(s), 31)
    Do While Left$(s, 1) = "'"
        s = Mid$(s, 2)
    Loop
    Do While Right$(s, 1) = "'"
        s = Left$(s, Len(s) - 1)
    Loop
    If Len(s) = 0 Then s = "Sheet"
    SafeSheetName = s
End Function

アポストロフィを取り除くのは、31 文字に切り詰めた後です。先ではありません。31 文字で切ると、新しい末尾にアポストロフィが現れることがあるからです。

落とし穴:セルの値からシート名を付ける

実際のブックで一番よくあるリネームは「各シートに A1 の値の名前を付ける」です。一見、無害に見えます。

ws.Name = ws.Range("A1").Value     ' A1 には日付が入っている

A1 に日付が入っていると、.Value は Date を返し、VBA はそれを パソコンの地域設定の短い日付形式 で文字列に変換します。ドイツのパソコンなら 30.09.2026 — シート名としてまったく問題ありません。米国のパソコンなら 9/30/2026 で、スラッシュがエラー 1004 を起こします。同じマクロがミュンヘンではすべてのテストに合格し、シカゴではエラーで止まるのです。日本のパソコンでは 2026/09/30 となり、やはりスラッシュを含むのでエラーになります — 日本の読者が最初に踏むのはこちらでしょう。数値にも同じ問題の目立たない版があります。小数点の記号も地域によって変わるのです。

解決策は、文字列を自分で決めてから、サニタイズすることです。

Dim v As Variant
v = ws.Range("A1").Value
If IsDate(v) Then
    ws.Name = SafeSheetName(Format(v, "yyyy-mm-dd"))
Else
    ws.Name = SafeSheetName(CStr(v))
End If

明示的なパターンを指定した Format は、どのパソコンでも同じ文字列を作ります。データから作る名前すべてに通じるルールです。書式を決めるのはあなたであって、地域設定ではありません。

一括リネームと、二つの名前の入れ替え

一括リネームは衝突で失敗します。たいていは途中で失敗し、ブックは半分だけリネームされた状態で残ります。二つの習慣でそれを防げます。一つ目は、代入する前にすべての名前を一意にしておくことです。シートの存在確認 を使います。

Function UniqueSheetName(wb As Workbook, ByVal base As String) As String
    Dim nm As String, n As Long
    nm = base
    Do While SheetExists(nm, wb)
        n = n + 1
        nm = Left$(base, 31 - Len(" (" & n & ")")) & " (" & n & ")"
    Loop
    UniqueSheetName = nm
End Function

二つ目は、二つのシートの名前を入れ替えるときに、一時的な名前を経由することです。B がまだ存在する状態で A を B にリネームすると重複となり 1004 が起きますが、三段階の入れ替えなら決して衝突しません。

Sub SwapSheetNames(ws1 As Worksheet, ws2 As Worksheet)
    Dim n1 As String, n2 As String
    n1 = ws1.Name: n2 = ws2.Name
    ws1.Name = "~swap~"
    ws2.Name = n1
    ws1.Name = n2
End Sub

大文字と小文字だけを変えるリネーム — sales を Sales に — は衝突ではありません。同じシートなので、Excel は受け入れます。

判断の分かれ目:リネームの前に文字列の参照を検索する

手作業のリネームも、コードでのリネームと効果は同じです。ですから判断の軸は VBA ではありません。ブックがどちらの種類の参照に頼っているか です。シートを指すものがすべて解析される参照なら、自由にリネームしてかまいません。リファクタリングは Excel がやってくれます。名前を文字列として綴っているものが一つでもあるなら — INDIRECT、ハイパーリンク、マクロ、シートを名前で読む Power Query のステップ — まず旧名を検索し(Ctrl+F で「検索場所: ブック」「検索対象: 数式」、VBA エディターでは Ctrl+Shift+F)、同じ変更の中で直します。私のルール:ユーザーが目にするシートはリネームしてよい。ただし、コードをその名前に依存させてはいけない。 マクロは CodeName か、一度だけ Set した変数に紐づけておけば、リネームは本来あるべき姿 — ラベルの変更 — のままです。

ExcelMaster の活用

リネームの問題は、リネームから遠く離れた場所で表に出ます。翌月になって #REF! に変わる INDIRECT、同僚がシート見出しを整理した途端にエラー 9 で止まるマクロ、米国式の日付に設定されたノートパソコンでだけ失敗する月次シート。

ExcelMaster には、仕事の内容をそのまま伝えられます — 「各シートを A1 の地域名でリネームして、旧名を指したままのものも全部直して」 — すると、サニタイズ済みで重複しない名前でリネームを書き、さらにリネームで取り残される文字列の参照を見つけて、同じ流れの中で更新してくれます。

よくある質問

VBA でシート名を変更するには?

Name プロパティを設定します。Worksheets("Sheet1").Name = "Sales"、アクティブシートなら ActiveSheet.Name = "Sales" です。マクロがその後もシートを使い続けるなら、先に変数に入れておきましょう。名前が変わると Worksheets("Sheet1") ではもう見つからないからです。

シート名を変更するとエラー 1004 が出るのはなぜですか?

名前がルールに反しています。31 文字を超えている、空である、: \ / ? * [ ] のいずれかを含む、先頭か末尾がアポストロフィである、History である、あるいは大文字小文字に関係なくブック内の他のシートと一致している、のいずれかです。サニタイズ関数で名前をきれいにし、代入する前にその名前がまだ使われていないことを確認しましょう。

シート名を変更すると数式は更新されますか?

=Sales!B4 のようにシートを直接参照する数式は自動で更新されます。名前定義、グラフ、入力規則のリストも同様です。文字列として書かれた参照は更新されません。INDIRECT("Sales!B4")、ハイパーリンクのリンク先、Worksheets("Sales") のような VBA の文字列は旧名のまま残り、壊れます。

セルの値でシート名を変更するには?

セルを読み、値を自分で文字列に変換してから、サニタイズします。日付には Format(value, "yyyy-mm-dd")、それ以外には CStr を使い、その結果を不正な文字を取り除く関数に通します。日付のセルを直接代入すると、名前がパソコンの地域の日付形式に左右されてしまいます。

VBA でアクティブシートの名前を取得するには?

ActiveSheet.Name を読みます。特定のシートなら、ワークシート変数の ws.Name を読みます。シート自身の名前をセルに表示するには、Excel 365 で =TEXTAFTER(CELL("filename", A1), "]") を使います。ブックを一度保存すれば動きます。

検証環境

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

関連ガイド: VBA シートの非表示 · VBA シートの存在確認 · VBA Worksheets · VBA シートの追加 · VBA シートのコピー · VBA Format · VBA Replace · VBA 名前付き範囲