上図のようなリストがあったとします。同じ名前の人が重複していますね。このリストから重複したデータを削除するには次のようにします。
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など他にもいろいろな手があります。