【VBA】空白行・空白セルを一括で削除する方法(コピペOK)

VBA
スポンサーリンク
スポンサーリンク

この記事でできること

  • データの途中に散在する空白行を、VBAで一括削除してデータを詰める
  • 削除前に件数を確認してから安全に実行できる
  • 空白「セル」だけを削除して上に詰める方法もわかる

対象: 空白行の手動削除に時間をかけている人、VBAが初めての人

所要時間: コピペ → 動作確認まで約5分(目安)


完成イメージ(Before / After)

Before(空白行が散在)

A(名前) B(部署) C(金額)
1 名前 部署 金額
2 田中 営業 50,000
3
4 鈴木 経理 30,000
5
6
7 佐藤 総務 45,000
8 高橋 営業 60,000
9
10 伊藤 経理 35,000

After(空白行を削除してデータが詰まった状態)

A(名前) B(部署) C(金額)
1 名前 部署 金額
2 田中 営業 50,000
3 鈴木 経理 30,000
4 佐藤 総務 45,000
5 高橋 営業 60,000
6 伊藤 経理 35,000

500件の売上データで空白行を手作業で1つずつ削除していた時期がある。途中で行を間違えて消してしまい、Ctrl+Zで戻すはめに。しかも空白行は飛び飛びにあるから、スクロールしながら探すだけで地味にストレスだった。VBAで一括削除するようにしてからは5秒で終わる。この記事で、同じ苦労をしている人が空白行の手動削除から解放されればうれしい。

最終行の取得(Cells.End(xlUp).Row)に不安がある場合は、先に 最終行・最終列を正確に取得する方法 を読んでおくと安心。

空白行の削除は、VBAに任せれば一瞬で終わる。


事前準備

バックアップを取る

空白行の削除は元に戻せないことがある。 マクロ実行前に、Excelファイルのコピーを別フォルダに保存しておくこと。

Excelをマクロ有効ブック(.xlsm)で保存する

  1. Excelを開く(新規でも既存でもOK)
  2. 「ファイル」→「名前を付けて保存」
  3. ファイルの種類を 「Excel マクロ有効ブック (*.xlsm)」 に変更して保存

.xlsx のままだとマクロが保存されない。必ず .xlsm にすること。

VBE(コードを書く画面)を開く

Alt + F11 キーを押すとVBE(Visual Basic Editor)が開く。

標準モジュールを挿入する

  1. VBEのメニューで「挿入」→「標準モジュール」をクリック
  2. 右側にコードウィンドウが開く → ここにコードを貼り付ける

手順(コピペ → 動作確認まで約5分)

  1. 上の「事前準備」でVBEを開き、標準モジュールを挿入する
  2. 下の「コード(最小版)」をコピーして、コードウィンドウに貼り付ける
  3. Alt + F8 を押してマクロ一覧を表示
  4. 「空白行を削除する」を選択して「実行」をクリック
  5. 空白行が削除されてデータが詰まれば成功

コード(最小版)– SpecialCellsで空白行を一括削除

まずはこれだけで動く。A列の空白セルを検出し、その行を一括削除する。


Sub 空白行を削除する()
    Dim ws As Worksheet
    Dim lastRow As Long
    Dim rng As Range

    Set ws = ActiveSheet
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

    ' A列で空白セルを検索
    On Error Resume Next
    Set rng = ws.Range("A2:A" & lastRow).SpecialCells(xlCellTypeBlanks)
    On Error GoTo 0

    If rng Is Nothing Then
        MsgBox "空白行はありませんでした。", vbInformation
        Exit Sub
    End If

    ' 空白セルがある行を削除
    rng.EntireRow.Delete

    MsgBox "空白行を削除しました。"
End Sub

コードの動作:

  1. アクティブシートのA列で最終行を取得(最終行の取得方法は /032 を参照)
  2. A2からA列の最終行までの範囲で、空白セルを SpecialCells(xlCellTypeBlanks) で検索
  3. 空白セルが見つからない場合はメッセージを表示して終了
  4. 空白セルがある行を EntireRow.Delete で一括削除

SpecialCells のポイント:

  • xlCellTypeBlanks は空白セルだけを取得する定数
  • 空白セルが1つもない場合にエラーが出るため、On Error Resume Next で囲む必要がある
  • A列が空白なら行ごと削除する、というシンプルな仕組み

コード(実務版)– 削除前の確認+件数表示

業務で使うなら、いきなり削除せずに件数を確認してから実行したい。自分もこの確認ダイアログを付けてからは、間違って必要な行を消す事故がなくなった。


Sub 空白行を安全に削除する()
    Dim ws As Worksheet
    Dim lastRow As Long
    Dim rng As Range
    Dim cnt As Long

    Set ws = ActiveSheet
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

    If lastRow < 2 Then
        MsgBox "データがありません。", vbExclamation
        Exit Sub
    End If

    ' A列の空白セルをカウント
    On Error Resume Next
    Set rng = ws.Range("A2:A" & lastRow).SpecialCells(xlCellTypeBlanks)
    On Error GoTo 0

    If rng Is Nothing Then
        MsgBox "空白行はありませんでした。", vbInformation
        Exit Sub
    End If

    cnt = rng.Cells.Count

    ' 削除前の確認
    If MsgBox(cnt & " 件の空白行が見つかりました。" & vbCrLf & _
              "削除してよろしいですか?", vbYesNo + vbQuestion) = vbNo Then
        Exit Sub
    End If

    ' 画面更新を停止して高速化
    Application.ScreenUpdating = False

    On Error GoTo ErrHandler
    rng.EntireRow.Delete

CleanUp:
    Application.ScreenUpdating = True
    MsgBox cnt & " 件の空白行を削除しました。"
    Exit Sub

ErrHandler:
    Application.ScreenUpdating = True
    MsgBox "エラーが発生しました: " & Err.Description, vbExclamation
End Sub

実務版の追加ポイント:

  • データがない場合(最終行が1以下)は処理しない
  • 削除前に空白行の件数を表示し、Yes/Noで確認してから削除
  • Application.ScreenUpdating = False で画面の再描画を止めて高速化
  • エラーハンドラで ScreenUpdating = True を確実に復帰
  • 削除完了後に件数を報告

逆順ループで削除する方法

SpecialCellsは高速だが、「A列が空白でもB列にデータがある行は残したい」など柔軟な条件が必要な場合は逆順ループを使う。

なぜ逆順か: 行を上から順に削除すると、削除のたびに行番号がズレる。例えば3行目を消すと、元の4行目が新しい3行目になる。下から上にループすれば、削除済みの行より上の行番号は変わらないのでズレない。


Sub 空白行を逆順ループで削除する()
    Dim ws As Worksheet
    Dim lastRow As Long
    Dim i As Long
    Dim cnt As Long

    Set ws = ActiveSheet
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

    Application.ScreenUpdating = False

    ' 下から上にループ(行削除でズレない)
    For i = lastRow To 2 Step -1
        If ws.Cells(i, 1).Value = "" Then
            ws.Rows(i).Delete
            cnt = cnt + 1
        End If
    Next i

    Application.ScreenUpdating = True

    MsgBox cnt & " 件の空白行を削除しました。"
End Sub

SpecialCells版と逆順ループ版の使い分け:

SpecialCells版 逆順ループ版
速度 速い(一括処理) 遅い(1行ずつ処理)
条件の柔軟性 空白セルのみ 自由に条件を追加できる
数式の空文字 空白と見なさない Len() で判定可能
おすすめ場面 シンプルな空白行削除 複雑な条件で削除したい場合

自分は普段SpecialCells版を使っているが、「A列は空白だけどB列にメモがある行は残したい」という依頼があったときに逆順ループ版に切り替えた。条件が複雑な場合は逆順ループ版が安全。


空白「セル」だけを削除して上に詰める方法

1列だけのリスト(名前一覧、商品リストなど)で途中の空白セルを詰めたい場合に使える。行全体ではなく、空白セルだけを削除してデータを上にシフトする。


Sub 空白セルを削除して上に詰める()
    Dim ws As Worksheet
    Dim lastRow As Long
    Dim rng As Range

    Set ws = ActiveSheet
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

    On Error Resume Next
    Set rng = ws.Range("A2:A" & lastRow).SpecialCells(xlCellTypeBlanks)
    On Error GoTo 0

    If rng Is Nothing Then
        MsgBox "空白セルはありませんでした。", vbInformation
        Exit Sub
    End If

    ' 空白セルを削除して上方向にシフト
    rng.Delete Shift:=xlShiftUp

    MsgBox "空白セルを削除して上に詰めました。"
End Sub

行削除との違い:

  • EntireRow.Delete → 行全体を削除(B列以降のデータも消える)
  • Delete Shift:=xlShiftUp → 空白セルだけ削除し、下のデータが上にシフトする

注意: 複数列のデータがある場合、A列だけ上に詰まるため列ごとにデータがズレる可能性がある。1列だけのリストで使うのが安全。複数列のデータがある場合は行全体の削除(最小版・実務版)を使うこと。


よくある落とし穴5選

# 症状 原因 対策
1 A列は空白だがB列にデータがある行まで消えた A列だけで空白判定しているため、B列以降のデータがある行も削除される 判定列を正しく選ぶ。行全体が空白かを確認したい場合は WorksheetFunction.CountA(ws.Rows(i)) = 0 で判定する
2 数式で ="" を返しているセルが削除されない SpecialCells(xlCellTypeBlanks) は「値が空のセル」を検出する。数式が入っているセルは空白と見なされない 逆順ループ版で Len(ws.Cells(i, 1).Value) = 0 に変更する。数式の有無に関係なく、表示が空なら削除される
3 行を上から順に削除したらデータが飛んだ For i = 2 To lastRow で上から削除すると、行番号がズレて一部の行がスキップされる。自分も最初これでデータを壊しかけた 逆順ループ(Step -1)またはSpecialCells一括削除を使う
4 削除後にCtrl+Zで元に戻せなかった VBAで実行した操作はUndoバッファに記録されないことがある マクロ実行前にファイルをバックアップすること。 これが最も確実な対策
5 結合セルがあるとエラーが出る 結合セルを含む範囲で行削除を実行すると、結合の整合性が崩れてエラーになる 結合を先に解除してからマクロを実行する。VBEのイミディエイトウィンドウ(Ctrl+G)で ActiveSheet.Cells.UnMerge を実行すれば一括解除できる

FAQ

Q1: A列ではなくB列で空白判定したい場合は?

ws.Range("A2:A" & lastRow)"A2:A""B2:B" に変更する。判定列は業務のデータに合わせて選ぶこと。主キーになる列(名前、ID、日付など必ず値が入る列)を判定列にするのがおすすめ。

Q2: 行全体が空白かどうかで判定したい場合は?

逆順ループ版の条件を以下に変更する:


If WorksheetFunction.CountA(ws.Rows(i)) = 0 Then
    ws.Rows(i).Delete
    cnt = cnt + 1
End If

CountA は行の中で値が入っているセルの数を返す。0なら行全体が空白。データ範囲が広い場合は ws.Range("A" & i & ":Z" & i) のように列を限定すると処理が速くなる。

Q3: 削除ではなく非表示にしたい場合は?

ws.Rows(i).Deletews.Rows(i).Hidden = True に変更する。非表示なら後から「書式」→「非表示/再表示」で元に戻せる。削除が不安なときの代替手段として使える。

Q4: 特定のシートだけ処理したい場合は?

Set ws = ActiveSheetSet ws = Worksheets("Sheet1") に変更する。シート名を直接指定すれば、別のシートがアクティブでも対象シートだけ処理される。複数シートを一括処理したい場合は 複数シートに同じ処理を一括実行する方法 と組み合わせる。

Q5: 数式の空文字列(=””)も空白として扱いたい場合は?

SpecialCells版では対応できない。逆順ループ版で以下の条件に変更する:


If Len(ws.Cells(i, 1).Value) = 0 Then
    ws.Rows(i).Delete
    cnt = cnt + 1
End If

Len() はセルの値の文字数を返す。数式で "" を返しているセルも文字数は0なので、空白として検出できる。


まとめ

この記事で、空白行を一括で削除してデータを詰める方法がわかった。

  • 最小版: SpecialCells で空白行を一括削除(5行のコードで完了)
  • 実務版: 削除前に件数を確認+Yes/Noダイアログで安全に削除
  • 逆順ループ版: 柔軟な条件が必要な場合に使う
  • 空白セル版: 行全体ではなく空白セルだけ削除して上に詰める

重要なのは以下の3点:

  1. バックアップを取ってから実行する(VBAの削除はCtrl+Zで戻せないことがある)
  2. 判定列を正しく選ぶ(A列以外にデータがある行を消さないように)
  3. SpecialCellsと逆順ループを使い分ける(シンプルな削除ならSpecialCells、複雑な条件なら逆順ループ)

関連記事


次にやりたくなること

コメント

タイトルとURLをコピーしました