シートコピー時に延々と表示されるエラー

Excelでシートをコピーした際に
「名前の定義が重複しています」
というエラーが何度も何度も表示され、Enterキーを押し続けて進めた経験はありませんか?

これは、ブック内に大量の不要な名前の定義(Name)」が残っている場合に発生します。さらに厄介なのは、ExcelのUI(Ctrl+F3の名前の管理)では見えない「非表示の名前の定義」が存在することです。

この記事の要点

この記事では以下について解説しています。

・エラーが発生する原因
・非表示の名前が消せない理由
・削除してはいけない名前(印刷範囲・フィルタなど)
・参照エラー(#REF!)の名前だけ安全に削除するVBAコード
・最低限を残して全削除するVBAコード

Excel実務者(経理・財務・監査・コンサル)はぜひお読みください。

延々と表示される名前の定義の重複

Excelでシートコピーした際に以下のようなエラーが表示されたことはありませんか?

コピーにより名前の定義が重複する場合に表示されるエラーですが、名前の数が膨大だと、このエラーをエンターキーを押しっぱなしにして延々とスキップし続ける必要があります。

このエラーは、Ctrl+F3で表示される名前の管理から不要な名前を削除することで回避できます。ただし、すべて削除したのに同じエラーが表示されることがあります。原因は非表示の名前の定義が存在しているケースです。ピボットテーブルや外部データ接続などの機能は非表示の名前を生成することがあり得るようです。「非表示」設定は、元々VBAからしか設定・変更できない特殊なプロパティであるため、標準の[名前の管理]ダイアログボックスでは操作できません。

削除してはいけない名前の定義

不要な名前の定義の典型例は#REF!エラーが表示されている名前です。名前の定義の参照先としていたセルやシートを削除すると、#REF! エラーが発生します。

一方で、削除してはいけない名前もあります。印刷範囲、ピボットテーブルの機能などは名前の定義が紐づいており、削除してしまうと想定と異なる挙動となってしまうことがありえます。

参照先エラーの名前をすべて削除するVBAコード(非表示の名前も含む)

インターネット上には、「非表示の名前をすべて表示する」タイプのVBAコードも多く公開されています。
これらは「見えない名前を可視化する」点では有用ですが、「どの名前を削除してよいか」「どれを残すべきか」までは判別してくれません。

以下は非表示となっているものも含めて、参照先がエラー(#REF!)となっている名前の定義をすべて削除するVBAコードです。なお、実行前に必ずバックアップをとってからお試しください。VBAを実行すると『元に戻す』ボタン(Ctrl+Z)で戻れない点もお気をつけください。

ExcelでAlt + F11でVBAの画面を呼び出し、「挿入」から「標準モジュール」の画面へ貼り付けてF5で実行することで動作します。

ショートカットの場合は以下の手順になります。
Alt +F11でVBAの画面呼び出し Alt + I → M→ コードをコピペ →F5

以下コード
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

Sub DeleteRefErrorNamesSafely()
    Dim nm As Name
    Dim i As Long
    Dim delCount As Long
    Dim isSystemName As Boolean
    Dim isRefError As Boolean
    
    ' 実行前の確認
    If MsgBox("参照先がエラー(#REF!)になっている名前定義のみを削除します。" & vbCrLf & _
              "※印刷設定やフィルタ設定、正常な名前は保持されます。" & vbCrLf & vbCrLf & _
              "実行してよろしいですか?", vbYesNo + vbExclamation) = vbNo Then
        Exit Sub
    End If

    ' 全コレクションを後ろから順にチェック
    For i = ActiveWorkbook.Names.Count To 1 Step -1
        Set nm = ActiveWorkbook.Names(i)
        
        ' 1. システム上重要な名前かどうかの判定
        isSystemName = False
        If InStr(1, nm.Name, "Print_Area", vbTextCompare) > 0 Then isSystemName = True
        If InStr(1, nm.Name, "Print_Titles", vbTextCompare) > 0 Then isSystemName = True
        If InStr(1, nm.Name, "_FilterDatabase", vbTextCompare) > 0 Then isSystemName = True
        
        ' 2. 参照エラー(#REF!)を含んでいるかの判定
        ' RefersTo(参照範囲)の文字列の中に "#REF!" があるか探す
        isRefError = (InStr(1, nm.RefersTo, "#REF!", vbTextCompare) > 0)
        
        ' 【削除条件】
        ' 「システム名ではなく」かつ「参照エラーである」場合のみ削除
        If (Not isSystemName) And isRefError Then
            On Error Resume Next
                nm.Visible = True ' 念のため表示状態にする
                nm.Delete
                If Err.Number = 0 Then delCount = delCount + 1
            On Error GoTo 0
        End If
        
    Next i

    MsgBox "処理が完了しました。" & vbCrLf & _
           "削除されたエラー定義数: " & delCount & " 個", vbInformation
End Sub

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

フィルタ設定・印刷設定以外の「名前の定義」をすべて削除するVBAコード

なお、経験談ではありますが、参照エラー(#REF!)になっていないものでも、名前の定義が本来の意図通りに機能しているケースはかなり稀なように思います。参照エラー(#REF!)でなくとも、印刷範囲など必ず必要なものを除いてすべて削除してしまうコードは以下になります(当然ながらご自身で設定した便利な名前(セル範囲への参照など)も消えてしまうため、実行する際は名前を削除しても問題ないか確認のうえご使用ください。バックアップも忘れずに)。

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

Sub DeleteNonSystemNames()
    Dim nm As Name
    Dim i As Long
    Dim delCount As Long
    Dim isSystemName As Boolean
    
    ' 実行前の確認
    If MsgBox("参照エラー(#REF!)に関係なく、" & vbCrLf & _
              "フィルタ設定・印刷設定以外の「名前の定義」をすべて削除します。" & vbCrLf & vbCrLf & _
              "よろしいですか?", vbYesNo + vbExclamation) = vbNo Then
        Exit Sub
    End If

    ' 後ろから前へループ
    For i = ActiveWorkbook.Names.Count To 1 Step -1
        Set nm = ActiveWorkbook.Names(i)
        
        ' システム名判定(残す)
        isSystemName = False
        If InStr(1, nm.Name, "Print_Area", vbTextCompare) > 0 Then isSystemName = True
        If InStr(1, nm.Name, "Print_Titles", vbTextCompare) > 0 Then isSystemName = True
        If InStr(1, nm.Name, "_FilterDatabase", vbTextCompare) > 0 Then isSystemName = True
        
        ' システム名以外はすべて削除
        If Not isSystemName Then
            On Error Resume Next
                nm.Visible = True   ' 念のため表示状態にする
                nm.Delete
                If Err.Number = 0 Then delCount = delCount + 1
            On Error GoTo 0
        End If
        
    Next i

    MsgBox "処理が完了しました。" & vbCrLf & _
           "削除された名前定義数: " & delCount & " 個", vbInformation
End Sub
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

おわりに

Excelでシートをコピーする際に延々と表示される「名前の定義が重複しています」というエラーは、非表示の名前の定義が原因で発生することがあります。通常の名前の管理画面(Ctrl+F3)では確認できない非表示の名前が残っているため、UIからの削除では完全に解決できないケースが多く見られます。

本記事では、この問題を根本から解決するための2つのVBAコードをご紹介しました。

1つ目は、参照エラー(#REF!)となっている名前の定義だけを安全に削除するコードです。印刷範囲やフィルタ設定など、Excel の動作に必要な名前は保護しながら、壊れた名前だけを削除できます。

2つ目は、システムに必要な最低限の名前以外をすべて削除するコードです。より徹底的に名前の定義を整理したい場合に有効ですが、独自に設定した名前も削除されるため、実行前の確認が必要です。

いずれのコードも、実行前に必ずブックのバックアップを取ること、そしてVBAの実行後は元に戻す(Ctrl+Z)ができない点にご注意ください。

これらのVBAコードを活用することで、シートコピー時のエラー表示に悩まされることなく、スムーズなExcel作業が可能になります。経理・財務・監査・コンサルティングなど、日常的にExcelを扱う実務者の方々の作業効率化にお役立てください。