テーブル内の特定行だけ削除するには、どうしたらいいでしょう。ここでは、下図のようなテーブルから、[名前]が"田中"の行だけを削除するケースで考えてみます。
これ、普通のセル範囲だったら、たとえば次のように考えます。
Sub Sample1() Dim i As Long For i = 10 To 2 Step -1 If Cells(i, 2) = "田中" Then Cells(i, 2).EntireRow.Delete End If Next i End Sub
もちろん、これでも成功します。ですがこれは、普通のワークシート上での考え方です。テーブルはExcelが管理する特別なデータベース領域です。
データベース的に考えるのなら、上のようにセルを1つずつ見ていって、それが条件に一致するかどうか…という判定はしません。非効率的だからです。データベース的な発想なら「[名前]フィールドが"田中"であるすべてのレコード(行)」だけを取り出すという操作をするでしょう。いわゆるクエリーを使います。テーブルに対しても、同じアプローチをしましょう。Excelでクエリーといえば、何といってもオートフィルタです。テーブルの[名前]列つまり2列目を"田中"で絞り込みます。
Sub Sample2() Range("A1").ListObject.Range.AutoFilter 2, "田中" End Sub
オートフィルタで絞り込んだ結果のうち「タイトル行を除く実データだけ」を削除したいのですから、このテーブルのDataBodyRangeを操作してやります。ただ、そうなると、オートフィルタをかけるときが"Range"で実データを特定するときが"DataBodyRange"になってしまいます。オートフィルタで絞り込むときも"DataBodyRange"でいけますから、ここは可読性のために統一するといいでしょう。
Sub Sample3() Range("A1").ListObject.DataBodyRange.AutoFilter 2, "田中" Range("A1").ListObject.DataBodyRange.Select End Sub
削除します。
Sub Sample4() Range("A1").ListObject.DataBodyRange.AutoFilter 2, "田中" Range("A1").ListObject.DataBodyRange.EntireRow.Delete Range("A1").ListObject.DataBodyRange.AutoFilter 2 End Sub
「Range("A1").ListObject.DataBodyRange」を連呼していて可読性が悪いですから、ここはWithでくくりましょう。
Sub Sample5() With Range("A1").ListObject.DataBodyRange .AutoFilter 2, "田中" .EntireRow.Delete .AutoFilter 2 End With End Sub
削除するとき、ただ「.Delete」だけでも成功しますが、テーブルではセル単位での挿入や削除が許されていません。常に行(レコード)単位で操作します。したがって、ただ「.Delete」だけだと次の確認メッセージが表示されてマクロが停止します。
なので、ここは「.EntireRow.Delete」と、"行全体"を指定します。なお、最後の「.AutoFilter 2」はオートフィルタの絞り込みを解除しています。普通のワークシートでしたら「.AutoFilter」だけを実行して、オートフィルタ矢印ボタン(▼ボタン)まで消すところですが、テーブルにはもれなくオートフィルタがついてきます。テーブルでは通常オートフィルタ矢印ボタン(▼ボタン)が常に表示されていますので、オートフィルタ自体を解除するのではなく「2列の目の絞り込みだけを解除」します。そのときは、列位置を表す数値だけは指定します。