シートコピー時の重複名回避
コピー後の命名で「同名エラー」を防ぐための安全テンプレートをまとめました。禁止文字・31文字上限・連番付与・警告非表示まで、初心者向けにコピペで使える形で解説します。
基本:コピーして安全に命名(重複なら連番)
Sub CopyTemplate_SafeRename()
Dim src As Worksheet, dst As Worksheet, baseName As String, safeName As String
Set src = ThisWorkbook.Worksheets("Template") 'コピー元
baseName = "レポート" '希望の名前
'末尾にコピー
src.Copy After:=ThisWorkbook.Worksheets(ThisWorkbook.Worksheets.Count)
Set dst = ActiveSheet 'コピー直後は新シートがアクティブ
'安全名へ整形+重複回避
safeName = UniqueSheetName(baseName, ThisWorkbook)
'命名(警告を抑止して確実に実行)
Dim wasAlerts As Boolean: wasAlerts = Application.DisplayAlerts
Application.DisplayAlerts = False
dst.Name = safeName
Application.DisplayAlerts = wasAlerts
MsgBox "コピー完了: " & dst.Name
End Sub
VB- ポイント:
- ActiveSheet: Copy直後の新シートはアクティブ。そこで命名するのが最短。
- DisplayAlerts: 命名時のダイアログを抑止。処理後は元に戻す。
- UniqueSheetName: 禁止文字・長さ・重複に強い安全命名関数を使う。
安全命名テンプレート:禁止文字・31文字上限・連番付与
Function SanitizeSheetName(rawName As String) As String
Dim s As String: s = Trim$(rawName)
s = Replace(s, ":", "_")
s = Replace(s, "/", "_")
s = Replace(s, "\", "_")
s = Replace(s, "?", "_")
s = Replace(s, "*", "_")
s = Replace(s, "[", "_")
s = Replace(s, "]", "_")
If Len(s) = 0 Then s = "Sheet"
If Len(s) > 31 Then s = Left$(s, 31)
SanitizeSheetName = s
End Function
Function SheetExists(name As String, wb As Workbook) As Boolean
Dim t As Worksheet
On Error Resume Next
Set t = wb.Worksheets(name)
SheetExists = Not t Is Nothing
On Error GoTo 0
End Function
Function UniqueSheetName(baseName As String, wb As Workbook) As String
Dim name As String: name = SanitizeSheetName(baseName)
Dim i As Long: i = 1
Do While SheetExists(name, wb)
i = i + 1
name = SanitizeSheetName(baseName & " (" & CStr(i) & ")") '「(2)」形式
Loop
UniqueSheetName = name
End Function
VB- ポイント:
- 禁止文字対応:
: / \ ? * [ ]は使えないため_に置換。 - 31文字制限: 超過は切り詰め。空文字は「Sheet」に。
- 連番形式: Excelの慣例「(2)」スタイルで読みやすく。
- 禁止文字対応:
他ブックへコピーする場合(既存ブック末尾へ)
Sub CopyToOtherWorkbook_Safe()
Dim src As Worksheet, dstWb As Workbook, newName As String
Set src = ThisWorkbook.Worksheets("Template")
Set dstWb = Workbooks("月次集計.xlsm") '既に開いているブック
'相手ブックの末尾にコピー
src.Copy After:=dstWb.Worksheets(dstWb.Worksheets.Count)
'新しくできたシートは「相手ブック側で」アクティブになる
newName = UniqueSheetName("月次レポート", dstWb)
Dim wasAlerts As Boolean: wasAlerts = Application.DisplayAlerts
Application.DisplayAlerts = False
dstWb.ActiveSheet.Name = newName
Application.DisplayAlerts = wasAlerts
MsgBox "他ブックへコピー完了: " & newName
End Sub
VB- ポイント:
- 対象の明確化: コピー先のブックでActiveSheetが新シートになる。命名はそのブック側で行う。
- UniqueSheetName: 連番付与は「コピー先のブック」を基準に判定。
連続コピーの重複回避(まとめて量産)
Sub BulkCopyTemplate_Safe()
Dim i As Long, nm As String
For i = 1 To 5
nm = "週報_" & Format(i, "00")
Call CopyTemplateWithName(nm)
Next
MsgBox "週報を5枚作成しました。"
End Sub
Sub CopyTemplateWithName(desiredName As String)
Dim src As Worksheet, dst As Worksheet, safe As String
Set src = ThisWorkbook.Worksheets("Template")
src.Copy After:=ThisWorkbook.Worksheets(ThisWorkbook.Worksheets.Count)
Set dst = ActiveSheet
safe = UniqueSheetName(desiredName, ThisWorkbook)
Dim wasAlerts As Boolean: wasAlerts = Application.DisplayAlerts
Application.DisplayAlerts = False
dst.Name = safe
Application.DisplayAlerts = wasAlerts
End Sub
VB- ポイント:
- 使い回し: 1枚コピー+命名をサブルーチン化して量産。
- 重複対策: 同名があっても「週報_01 (2)」のように自動で逃がす。
On Error を使った最短回避(簡易版)
Sub CopyWithSimpleFallback()
Worksheets("Template").Copy After:=Worksheets(Worksheets.Count)
On Error Resume Next
ActiveSheet.Name = "レポート"
If ActiveSheet.Name <> "レポート" Then
ActiveSheet.Name = "レポート (2)"
End If
On Error GoTo 0
End Sub
VB- ポイント:
- 手軽: まず希望名で命名、失敗したら「(2)」で再試行するだけの簡易策。
- 限界: 既に「(2)」まである場合などは足りないため、実務はUnique関数がおすすめ。
例題で練習
例題1:テンプレートを「年月レポート」でコピーし、重複なら連番
Sub Example_MonthlyReport()
Dim nm As String
nm = Format(Date, "yyyy-mm") & "_レポート"
CopyTemplateWithName nm
End Sub
VB- ポイント:
- 安定命名: 年月を含める規則+重複回避で運用が楽。
例題2:一覧(Control!A2:A)に書いた名前で順次コピー・命名
Sub Example_CopyFromList()
Dim ctrl As Worksheet, last As Long, r As Long, nm As String
Set ctrl = ThisWorkbook.Worksheets("Control")
last = ctrl.Cells(ctrl.Rows.Count, "A").End(xlUp).Row
For r = 2 To last
nm = CStr(ctrl.Cells(r, "A").Value)
CopyTemplateWithName nm
Next
End Sub
VB- ポイント:
- 運用連動: 管理用シートからの一括作成に相性が良い。
例題3:他ブックへ「売上」「在庫」「顧客」を安全コピー
Sub Example_CopyToOtherBook()
Dim dstWb As Workbook, arr As Variant, i As Long, nm As String
Set dstWb = Workbooks("集計.xlsm")
arr = Array("売上", "在庫", "顧客")
For i = LBound(arr) To UBound(arr)
Worksheets("Template").Copy After:=dstWb.Worksheets(dstWb.Worksheets.Count)
nm = UniqueSheetName(CStr(arr(i)), dstWb)
Dim wasAlerts As Boolean: wasAlerts = Application.DisplayAlerts
Application.DisplayAlerts = False
dstWb.ActiveSheet.Name = nm
Application.DisplayAlerts = wasAlerts
Next
MsgBox "他ブックへ安全コピーしました。"
End Sub
VB- ポイント:
- 先方基準: 重複判定は「コピー先ブック」単位で行う。
実務の落とし穴と対策
- 同名エラー:
- 対策: 命名前に必ずUnique生成。簡易なら「希望名→(2)」再試行でも最低限回避。
- 禁止文字・長さ上限:
- 対策: Sanitizeで置換+31文字切り詰め。入力由来の名前は必ず整形。
- DisplayAlertsの戻し忘れ:
- 対策: 現設定を退避して必ず復帰。例外時でも戻す構造が安全。
- コピー先のブック混同:
- 対策: 他ブックへコピー時は「どのブックのActiveSheetか」を意識して命名。
- VeryHidden/Hiddenのコピー:
- 注意: 非表示でもコピーは可能。表示操作が絡むなら可視化が必要な場面あり。
