和風スパゲティのレシピ

日本語でコーディングするExcelVBA

指定行より下を最終行まですべて削除する

指定行より下の行をすべて削除するコードを解説します。

特に見出し(ヘッダー)行より下をすべて削除して、
テーブル形式のデータを初期化するときなどに使用します。


なお、「最終行まで」というと以下の二つの意味があります。

  1. シートの最終行(現在は1048576行)
  2. データの最終行(ListObjectやUsedRangeの最終行)

 
1のシート全体削除は処理が重そうに感じますが全くそんなことはなく、
どちらもほぼ一瞬で処理が終わります。
※ フィルターがかかっている場合を除く

よって通常は1のシート全体削除を使っておけば問題ありませんが、
データ部分だけを消したいなど、必要に応じて2を使用してください。

指定行からシートの最終行までをすべて削除

基本コード

Dim 対象シート As Worksheet
Set 対象シート = Worksheets("○○")

Dim 指定行 As Long
指定行 = 4

対象シート.Range(対象シート.Rows(指定行) _
                       , 対象シート.Rows(対象シート.Rows.Count)).Delete

解説

複数行を一括で削除する場合は、
Range(Rows, Rows)で取得した対象行にDeleteメソッドを実行します。

複数の行をひとつのRangeオブジェクトに取得するには、
このRange(Rows, Rows)が基本形ですので覚えておきましょう。


きっちり書くとこの形ですが、Rows("○:△")でも同じ処理はできますので、
状況に応じて以下のコードで実装してもOKです。

対象シート.Range(指定行 & ":" & 対象シート.Rows.Count).Delete

 
また他の短縮表現として「Withステートメント」を使用する方法があり、
以下のように相当なコード削減効果がありますのでおすすめです。

With 対象シート
    .Range(.Rows(指定行), .Rows(.Rows.Count)).Delete
End With

(注)このコードはフィルターがかかっていると全行削除になりません

Deleteメソッドはフィルター抽出中は挙動が変わり、
手作業の時と同様「抽出中のデータだけを削除」という動きになります。

これはこれで便利なことも多いですが、
本当にすべての行を削除したい場合はフィルターをクリアしてから実行してください。

フィルタークリアコードはエラー対策が意外と面倒なので気を付けましょう。

If 対象シート.AutoFilterMode = True Then ' フィルタが設置されていて
    If 対象シート.AutoFilter.FilterMode = True Then ' いずれかの抽出あれば
        対象シート.ShowAllData ' クリアを実行(↑の判定を忘れるとエラーになる)
    End If
End If

汎用関数化

この処理をよく行う場合は、汎用関数化しておくのがおすすめです。

' 指定行以下を削除する汎用関数
Sub 指定行より下をすべて削除する(対象シート As Worksheet, 指定行 As Long)
    With 対象シート
        
        If 対象シート.AutoFilterMode = True Then ' フィルタが設置されていて
            If 対象シート.AutoFilter.FilterMode = True Then ' いずれかの抽出あれば
                対象シート.ShowAllData ' クリアを実行(↑の判定を忘れるとエラーになる)
            End If
        End If
        
        .Range(.Rows(指定行), .Rows(.Rows.Count)).Delete
        
    End With
End Sub

' 使用例
Sub オートフィルターのデータ部分以下をすべて削除する()

    Dim 対象シート As Worksheet
    Set 対象シート = Worksheets("○○")

    Call 指定行より下をすべて削除する(対象シート _
        , 対象シート.AutoFilter.Range.Row + 1)

End Sub

使用例のメインコードを見るとわかる通り、
汎用関数を使うことで今回の処理が1行のコードで実行できるようになります。

読みやすさ・書きやすさもさることながら、
フィルターのクリアを忘れることがなくなるのも強みですね。


このように、「簡単だけど書くのが面倒なコード」は、
関数化が簡単な割に、汎用関数にするメリットが大きい
です。

汎用関数集を作っている方は、ぜひそのメンバーに加えてあげてください。

汎用関数集の作り方・使い方についてはこちらをどうぞ。
www.limecode.jp

指定行からデータの最終行までをすべて削除

基本コード

Dim 対象シート As Worksheet
Set 対象シート = Worksheets("○○")

Dim 対象データ範囲 As Range

' 例:オートフィルター範囲から見出し行を除外した範囲
Set 対象データ範囲 = 対象シート.AutoFilter.Range
Set 対象データ範囲 = 対象データ範囲.Offset(1).Resize(対象データ範囲.Rows.Count - 1)

対象データ範囲.EntireRow.Delete

解説

特定のデータを行ごとすべて削除したい場合は、
セル範囲を含む行全体を取得するEntireRowプロパティを使用します。


シートの最終行までを取得する際に使ったRange(Rows, Rows)の記述は、
最終行の行番号を取得する必要があります。

これが分かっているときはもちろんこの記述でもいいのですが、
わざわざ最終行を取得するとなると以下の面倒なコードが必要になります。

対象データ範囲.Rows.Count + 対象データ範囲.Row - 1

これを計算するくらいならEntireRowを使った方が早い場面が多いと思います。

状況に応じて使い分けてください。

汎用関数化

今回のコードはEntireRow.Delete一発なので、
これ自体を汎用関数にする必要はないかと思います。

しかしその前段で行う

  • 指定エリアの最終行を取得する(Rows.Count + Row - 1)
  • 指定エリアから見出しを除外する(Offset(1).Resize(データ行数-1))

これらの処理は汎用化しておくと便利です。

先ほどの関数と同様、これらも汎用関数集に加えてあげてください。

Function Getセル範囲の最終行(セル範囲 As Range) As Long
    Getセル範囲の最終行 = セル範囲.Rows.Count + セル範囲.Row - 1
End Function
Function セル範囲の上部をn行除外(元のセル範囲 As Range, n As Long) As Range
    Set セル範囲の上部をn行除外 = 元のセル範囲.Offset(n).Resize(元のセル範囲.Rows.Count - n)
End Function