一行のコードで終わらせる ① 空白セルを行ごと削除

或る列に於いて、空白セルを行ごと削除したい。
例えば、↓このような場合だ。

f:id:Infoment:20190101041636p:plain

様々な方がweb上で紹介されているとおり、上から順に消した場合、指示行と処理行の段違いが発生して大惨事になる。従い、下から削除するのが一般的なようだ。

Sub RowDelete()
    Dim i As Long
        For i = 10 To 1 Step -1
            If Cells(i, 1).Value = "" Then
                Cells(i, 1).EntireRow.Delete
            End If
        Next
End Sub


どうしても上から順に確認したい!という場合は、こんな方法もある。

Sub RowDelete()
    ' 空白セルをセットするための変数。
    Dim myRng As Range
    Dim i As Long
        For i = 1 To 10
            If Cells(i, 1).Value = "" Then
                ' 空白セルをmyRngに統合していく。
                If myRng Is Nothing Then
                    Set myRng = Cells(i, 1)
                Else
                    Set myRng = Union(myRng, Cells(i, 1))
                End If
            End If
        Next
        ' myRngを行ごと一括削除。
        myRng.EntireRow.Delete
End Sub


ところで初学者からしばらくの間、冒頭の方法しか知らなかった私は或る日、以下のコードを目にした。

Sub RowDelete()
    Range("A1:A10").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End Sub

グルグルとループさせることなく、一行で、一撃で処理を完了させている。これは衝撃だった。

今回用いたのは、「SpecialCellsメソッド」。指定された条件を満たす全てのセルを返してくれる、便利なメソッドだ。
Range.SpecialCells メソッド (Excel) | Microsoft Docs

今回は「xlCellTypeBlanks」つまり空白(Blanks)行を指定することで、最初の指定範囲から空白セルだけを返してくれる。

Range("A1:A10").SpecialCells(xlCellTypeBlanks)

空白セルを含む行全体(つまり「.EntireRow」)を削除(.Delete)して完了。
とてもシンプルで分かり易いと思った。

参考までに、今回のコードはマクロの記録で作ることもできる。
① 処理範囲を選択した状態で、条件を選択してジャンプ

f:id:Infoment:20190101044203p:plain


② 選択オプションで、「空白セル」を選択して「OK」

f:id:Infoment:20190101044421p:plain


③ 空白セルのみが選択された状態になる。

f:id:Infoment:20190101044457p:plain

出来上がったマクロがこちら。

Sub Macro1()
    Range("A1:A10").Select
    Selection.SpecialCells(xlCellTypeBlanks).Select
End Sub

SpecialCellsメソッドを覚えきれない場合は、マクロの記録で確認しても良いかも。
他にも

  • 可視セル
  • 最後のセル
  • 定数

など、色々と便利に抽出できる。使えるようなると、色々と便利だ。


ここまでは、良くある話。
実は最近別件で、「一行で済ます」処理があって衝撃を受けた。

明日に続きます。

参考まで。


~ 追記 ~
空白セルが一つもない場合、この方式だとエラーが出ます。
実際に使用する場合は、エラー回避処理が必要です。

Sub RowDelete()
    Dim myRng As Range
    Set myRng = Range("A1:A10").SpecialCells(xlCellTypeBlanks)
        If Not myRng Is Nothing Then
            myRng.EntireRow.Delete
        End If
End Sub