重複行を削除する


上図のようなリストがあったとします。同じ名前の人が重複していますね。このリストから重複したデータを削除するには次のようにします。

Sub Sample()
    Dim i As Long
    With Range("A2")
        Do While .Offset(i, 0) <> ""
            If .Offset(i, 0) = .Offset(i - 1, 0) Then .Offset(i, 0).EntireRow.Delete
            i = i + 1
        Loop
    End With
End Sub

セルA2を基点として"注目セル"を1つずつ下げていきます。このとき、アクティブセルを移動するのではなくOffsetメソッドを使います。"注目セル"が、"注目セルの1つ上"と同じだったら、"注目セル"を含む行(EntireRow)を削除(Delete)します。

行の削除をマクロ記録で調べるとき、普通は行番号を右クリックして行全体を選択してから[削除]を実行します。すると記録されるのは次のようなコードです。

Sub Macro1()
    Rows("5:5").Select
    Selection.Delete Shift:=xlUp
End Sub

これを参考にしてもいいのですが、任意のセルを含む行を表すEntireRowプロパティを使う方がスマートです。このプロパティが記録されるには、行全体を選択して削除してはいけません。行を削除する操作をもう1つ知っていれば、このプロパティと出会えます

Sub Macro2()
    Selection.EntireRow.Delete
End Sub

これは削除したい行にアクティブセルを移動して、[編集]メニューの[削除]をクリックしました。表示される[削除]ダイアログボックスで[行全体]を選択して[OK]ボタンをクリックした操作を記録したのです。この操作では行を選択していませんので、EntireRowプロパティが記録されます。このプロパティは非常に応用範囲が広いですから、ぜひ覚えておきましょう

さて、これで完成…と安心してはいけません。いろいろなテストをしてみると、同じデータが3行以上続くとウマくいきません。重複しているデータを2行までしか削除できないようです。これは、Offset(i,0)を削除すると、それまでOffset(i+1,0)だった行がOffset(i,0)になってしまい、i=i+1したとき、それまでOffset(i+1,0)だった行を飛ばしてしまうからです。困りました…

こんなときは、"注目セル"を下から上に移動します。

Sub Sample02()
    Dim i As Long
    With Range("A2")
        For i = .CurrentRegion.Rows.Count To 1 Step -1
            If .Offset(i, 0) = .Offset(i - 1, 0) Then .Offset(i, 0).EntireRow.Delete
        Next i
    End With
End Sub

Range("A2").CurrentRegionは、セルA2を含む連続したセル範囲を返します。今回のサンプルでしたらセル範囲A1:B10です。そのセル範囲の行数はRows.Countでわかります。ここでは10行です。すると、Sample02のFor Nextステートメントは次のように整理できます。

        For i = 10 To 1 Step -1
            ''行削除のコード
        Next i

For Nextステートメントでは繰り返し回数を「i = 初期値 To 終了値」と指定します。このとき、一般的には「初期値 <= 終了値」です。もし終了値より大きい初期値を指定すると、いきなり最初の1回で繰り返しが終了してしまいます。そこで、初期値から終了値に向けてカウンタを1つずつ減少させる指定がStep -1です。

Sample02では最後の行をCurrentRegion.Rows.Countで取得しましたが、Range("A2").End(xlDown).Rowなど他にもいろいろな手があります。