Excel VBA 逆引き集 | 重複高速テンプレ

Excel VBA
スポンサーリンク

重複高速テンプレ

大量データで「重複チェック・削除・一覧化」をするとき、普通にセルを1つずつ見ていると遅くなります。そこで 配列+Dictionary を使うと一気に高速化できます。初心者でも理解しやすいように、コード例をかみ砕いて説明します。


高速化の基本テクニック

  • 画面更新停止: Application.ScreenUpdating = False
  • イベント停止: Application.EnableEvents = False
  • 計算停止: Application.Calculation = xlCalculationManual
    → 終了時に必ず元に戻す。
  • 配列に読み込む: Range.Valueを配列に入れて一括処理。セルを1つずつ読むより数十倍速い。
  • Dictionaryで突合: キー存在判定が一瞬でできる。重複判定に最適。

テンプレ1:重複を色でマーク(高速版)

A列の重複セルを黄色で塗ります。

Sub FastMarkDuplicates()
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    Application.Calculation = xlCalculationManual

    Dim ws As Worksheet: Set ws = Worksheets("Data")
    Dim lastRow As Long: lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
    Dim v As Variant: v = ws.Range("A2:A" & lastRow).Value

    Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
    Dim i As Long

    ' 一旦色をクリア
    ws.Range("A2:A" & lastRow).Interior.ColorIndex = xlNone

    For i = 1 To UBound(v, 1)
        Dim key As String: key = UCase$(Trim$(CStr(v(i, 1))))
        If Len(key) = 0 Then GoTo cont
        If dict.Exists(key) Then
            ws.Cells(i + 1, "A").Interior.Color = vbYellow
            ws.Cells(dict(key), "A").Interior.Color = vbYellow
        Else
            dict(key) = i + 1 ' 行番号を保持
        End If
cont:
    Next

    Application.Calculation = xlCalculationAutomatic
    Application.EnableEvents = True
    Application.ScreenUpdating = True

    MsgBox "重複セルを高速にマークしました"
End Sub
VB
  • ポイント: 配列で一気に読み込むので速い。行番号はDictionaryに保持。

テンプレ2:重複一覧を別シートに出力(高速版)

A列の重複値と行番号を「重複一覧」シートに出力します。

Sub FastListDuplicates()
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    Application.Calculation = xlCalculationManual

    Dim ws As Worksheet: Set ws = Worksheets("Data")
    Dim lastRow As Long: lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
    Dim v As Variant: v = ws.Range("A2:A" & lastRow).Value

    Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
    Dim pos As Object: Set pos = CreateObject("Scripting.Dictionary")

    Dim i As Long, key As String
    For i = 1 To UBound(v, 1)
        key = UCase$(Trim$(CStr(v(i, 1))))
        If Len(key) = 0 Then GoTo cont
        If dict.Exists(key) Then
            pos(key) = pos(key) & "," & (i + 1)
        Else
            dict(key) = True
            pos(key) = CStr(i + 1)
        End If
cont:
    Next

    Dim out As Worksheet
    On Error Resume Next
    Set out = Worksheets("重複一覧")
    On Error GoTo 0
    If out Is Nothing Then
        Set out = Worksheets.Add
        out.Name = "重複一覧"
    End If
    out.Cells.Clear
    out.Range("A1:C1").Value = Array("値", "出現回数", "行番号一覧")

    Dim r As Long: r = 2
    Dim k As Variant
    For Each k In pos.Keys
        Dim arr() As String: arr = Split(pos(k), ",")
        If UBound(arr) >= 1 Then
            out.Cells(r, 1).Value = k
            out.Cells(r, 2).Value = UBound(arr) + 1
            out.Cells(r, 3).Value = pos(k)
            r = r + 1
        End If
    Next

    out.Columns.AutoFit
    Application.Calculation = xlCalculationAutomatic
    Application.EnableEvents = True
    Application.ScreenUpdating = True

    MsgBox "重複一覧を高速に作成しました"
End Sub
VB
  • ポイント: 行番号一覧を残すので、後で確認が楽。

テンプレ3:重複行を削除(2回目以降を削除)

A列の重複行を削除します。必ず「下から」削除。

Sub FastRemoveDuplicates()
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    Application.Calculation = xlCalculationManual

    Dim ws As Worksheet: Set ws = Worksheets("Data")
    Dim lastRow As Long: lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
    Dim v As Variant: v = ws.Range("A2:A" & lastRow).Value

    Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
    Dim delRows As Collection: Set delRows = New Collection

    Dim i As Long, key As String
    For i = 1 To UBound(v, 1)
        key = UCase$(Trim$(CStr(v(i, 1))))
        If Len(key) = 0 Then GoTo cont
        If dict.Exists(key) Then
            delRows.Add i + 1
        Else
            dict(key) = True
        End If
cont:
    Next

    Dim r As Long
    For r = delRows.Count To 1 Step -1
        ws.Rows(delRows(r)).Delete
    Next

    Application.Calculation = xlCalculationAutomatic
    Application.EnableEvents = True
    Application.ScreenUpdating = True

    MsgBox "重複行を高速に削除しました: " & delRows.Count & "行"
End Sub
VB
  • ポイント: 削除は必ず「下から」。上から削除すると行番号がズレます。

例題で練習

'例1:A列の重複セルを高速に色付け
Sub Example_Mark()
    FastMarkDuplicates
End Sub

'例2:A列の重複一覧を高速に作成
Sub Example_List()
    FastListDuplicates
End Sub

'例3:A列の重複行を高速に削除(2回目以降)
Sub Example_Remove()
    FastRemoveDuplicates
End Sub
VB

初心者向けポイント

  • 配列+Dictionary: セルを1つずつ読むより圧倒的に速い。
  • 正規化: TrimUCaseで表記揺れを吸収。
  • 削除は下から: 行ズレ防止の鉄則。
  • まずは一覧化: いきなり削除せず、候補を出して確認→承認→削除が安心。
タイトルとURLをコピーしました