Article

【Excel VBA】条件に合う行だけ別シートにコピーするマクロ

この記事で分かること

Excel VBA で条件に合う行だけを別シートにコピーするマクロの作り方を解説します。コピペで使える完成コードと、文字列一致・数値比較・AND・OR などの条件カスタマイズ例、動かないときの確認ポイントも紹介します。

表のデータから条件に合う行だけ手作業でコピーしていませんか。VBA マクロを使えば、指定した条件に一致する行を自動で別シートに抽出できます。

この記事では、コピーしてすぐ使える完成コードと、VBE(Visual Basic Editor)での実行手順を解説します。条件を数値比較・部分一致・複数条件(AND / OR)に変えるカスタマイズ例と、動かないときの確認ポイントも紹介します。

練習用のサンプルファイルもダウンロードできます。

zip を展開すると、マクロ入りブック(filter-copy-sample.xlsm)が入っています。「元データ」シートにサンプルデータ、「抽出結果」シートは空の状態です。そのままマクロを実行して動作を確認できます。

条件に合う行を別シートにコピーするマクロ(完成コード)

以下のコードをコピーして、次のセクションの手順で実行すると、「元データ」シートの中から C 列(部署)が「営業部」の行だけを「抽出結果」シートにコピーします。

Sub CopyRowsByCondition()
    Dim wsSource As Worksheet
    Dim wsDest As Worksheet
    Dim lastRow As Long
    Dim destRow As Long
    Dim i As Long

    Set wsSource = ThisWorkbook.Sheets("元データ")
    Set wsDest = ThisWorkbook.Sheets("抽出結果")

    '--- 抽出先をクリアしてヘッダーをコピー ---
    wsDest.Cells.Clear
    wsSource.Rows(1).Copy Destination:=wsDest.Rows(1)

    '--- 元データの最終行を取得 ---
    lastRow = wsSource.Cells(wsSource.Rows.Count, 1).End(xlUp).Row
    destRow = 2

    '--- 1行ずつ条件を判定してコピー ---
    For i = 2 To lastRow
        If wsSource.Cells(i, 3).Value = "営業部" Then
            wsSource.Rows(i).Copy Destination:=wsDest.Rows(destRow)
            destRow = destRow + 1
        End If
    Next i

    MsgBox destRow - 2 & " 行コピーしました"
End Sub

コードの中で書き換えが必要な箇所は 3 か所です。

  • "元データ" ― コピー元のシート名
  • "抽出結果" ― コピー先のシート名
  • wsSource.Cells(i, 3).Value = "営業部" ― 抽出条件(列番号と比較する値)

条件の変え方は「条件の変え方(カスタマイズ例)」セクションで詳しく説明します。まずは使い方から見ていきましょう。

マクロの使い方(シート構成と実行手順)

シート構成を確認する

マクロを実行する前に、ブック内に次の 2 つのシートを用意します。

  • 元データ ― 1 行目がヘッダー、2 行目以降がデータ。A 列(最終行の判定基準)はすべての行にデータを入れてください
  • 抽出結果 ― 空のシート。マクロがヘッダーとデータを自動で書き込みます

この記事では、次のようなサンプルデータを使います。C 列の「部署」が「営業部」の行を抽出するのがゴールです。

A(No)B(名前)C(部署)D(売上)E(評価)
1No名前部署売上評価
21田中太郎営業部850000A
32鈴木花子総務部420000B
43佐藤次郎営業部1200000A
54山田美咲開発部680000C
65高橋一郎営業部530000B
76伊藤恵子総務部310000C
87渡辺健太開発部920000A
98小林由美営業部760000B
109中村拓也総務部480000B
1110松本さくら開発部1050000A
元データシートに10行のサンプルデータを入力した状態
元データシート ― 1 行目がヘッダー、2〜11 行目がデータ。C 列の「部署」を条件にして抽出する

VBE を起動してコードを貼り付ける

  1. Alt+F11 を押して VBE(Visual Basic Editor)を開く
  2. メニューバーの「挿入」→「標準モジュール」をクリック
  3. 右側に開いたコードウィンドウに、完成コードを貼り付ける
  4. "元データ""抽出結果"、条件の部分を自分のブックに合わせて書き換える
Visual Basic Editor に条件コピーマクロを貼り付けた画面
Alt+F11 で VBE を開き、「挿入」→「標準モジュール」でコードを貼り付けた状態

マクロを実行する

  1. コードウィンドウ内にカーソルを置いた状態で F5 を押す
  2. 処理が終わると「○行コピーしました」とメッセージが表示される
  3. Alt+F11 でシートに戻ると、「抽出結果」シートに条件に合う行だけがコピーされている

サンプルデータで実行すると、営業部の 4 名(田中・佐藤・高橋・小林)の行がヘッダー付きでコピーされます。

マクロ実行後に営業部の4行だけがコピーされた抽出結果シート
マクロ実行後の「抽出結果」シート ― 営業部の 4 行だけがヘッダー付きでコピーされた

保存形式の注意: マクロ入りブックは .xlsm 形式で保存します。通常の .xlsx で保存するとマクロが消えるため、保存時に「マクロ有効ブック (*.xlsm)」を選んでください。

コードの解説

完成コードを貼り付けて動かすだけなら前のセクションまでで十分ですが、条件を変えるときにはしくみの理解が役立ちます。ここではポイントを 3 つに絞って説明します。

最終行の取得 ― End(xlUp)

lastRow = wsSource.Cells(wsSource.Rows.Count, 1).End(xlUp).Row

この 1 行は「A 列の一番下(100 万行目付近)から上に向かって、最初にデータがあるセルの行番号を取得する」という意味です。手作業で Ctrl+ を押す操作と同じです。

注意: この方法は A 列を基準に最終行を判定します。A 列の途中に空行があっても、その下にデータがあればループ範囲には含まれます。ただし、A 列の末尾側が空白だと、他の列にデータが残っていてもその行を見落とします。A 列はすべての行にデータが入っている状態にしてください。

For ループで 1 行ずつ判定する

For i = 2 To lastRow
    If wsSource.Cells(i, 3).Value = "営業部" Then
        '... コピー処理 ...
    End If
Next i

For i = 2 でヘッダー行(1 行目)をスキップし、2 行目からデータの最終行まで 1 行ずつ処理します。

Cells(i, 3) は「i 行目の 3 列目」つまり C 列を指します。列番号は A = 1、B = 2、C = 3 のように数えます。自分のデータで条件にしたい列が何列目かを確認してください。

ABCDEFGH
番号12345678

Rows(i).Copy で行全体をコピーする

wsSource.Rows(i).Copy Destination:=wsDest.Rows(destRow)

Rows(i).Copy は i 行目の全列をコピーします。Destination:= を指定すると、クリップボードを経由せず直接コピー先に書き込まれます。

destRow は抽出先シートの書き込み位置を管理する変数です。コピーするたびに destRow = destRow + 1 で 1 つ下にずらすことで、抽出結果が詰めて並びます。

補足: 完成コードの wsDest.Cells.Clear はセルの値と書式をクリアします。書式を残して値だけ消したい場合は、wsDest.Cells.ClearContents に置き換えてください。

条件の変え方(カスタマイズ例)

完成コードの If の行を書き換えるだけで、さまざまな条件に対応できます。ここでは実務でよく使う 4 パターンを紹介します。

数値の大小で抽出する

D 列(売上)が 80 万以上の行を抽出する場合は、次のように書き換えます。

If wsSource.Cells(i, 4).Value >= 800000 Then

使える比較演算子は次のとおりです。

演算子意味
=等しい= 500000
<>等しくない<> 0
>より大きい> 1000000
>=以上>= 800000
<より小さい< 300000
<=以下<= 500000

文字列の部分一致で抽出する(Like)

B 列(名前)に「田」を含む行を抽出する場合は、= の代わりに Like を使います。

If wsSource.Cells(i, 2).Value Like "*田*" Then

* は「任意の 0 文字以上」を表すワイルドカードです。"*田*" は「田の前後に何があってもよい」=「田を含む」という意味になります。

パターン意味マッチ例
"*田*"「田」を含む田中太郎、山田美咲
"田*"「田」で始まる田中太郎
"*部"「部」で終わる営業部、開発部
"??太郎"2 文字 +「太郎」田中太郎

? は「任意の 1 文字」を表します。文字数が決まっている場合に使います。

2 つの条件を両方満たす行(AND)

C 列が「営業部」かつ D 列が 70 万以上の行だけを抽出する場合は、And でつなぎます。

If wsSource.Cells(i, 3).Value = "営業部" And wsSource.Cells(i, 4).Value >= 700000 Then

サンプルデータでは、営業部で売上 70 万以上の田中(85 万)・佐藤(120 万)・小林(76 万)の 3 名が抽出されます。

いずれかの条件を満たす行(OR)

C 列が「営業部」または E 列が「A」の行を抽出する場合は、Or でつなぎます。

If wsSource.Cells(i, 3).Value = "営業部" Or wsSource.Cells(i, 5).Value = "A" Then

サンプルデータでは、営業部の 4 名に加え、評価 A の渡辺・松本も対象となり、合計 6 名が抽出されます(田中・佐藤は両方に該当しますが、コピーは 1 回だけです)。

うまく動かないときの確認ポイント

マクロを実行してエラーが出たり結果が期待どおりにならないときは、次の表を確認してください。

症状よくある原因対処
1 件もコピーされない列番号の指定が違う条件にしたい列がA列から何列目かを数え直す(A = 1、B = 2、C = 3…)
1 件もコピーされない条件値の全角・半角が違うセルの値とコード内の文字列が完全に一致しているか確認する。前後の空白にも注意
末尾の行が抜けるA 列にデータがない行があるA 列はすべての行に値を入れる。不要な空行があれば削除する
「型が一致しません」エラー数値列に文字(”abc” など)やエラー値が混ざっているセルのデータを数値に直すのが最善。コードで対処するなら IsNumeric() で判定してスキップする(後述)
「インデックスが有効範囲にありません」シート名が違うコード内の "元データ" "抽出結果" とシートタブの名前が完全に一致しているか確認する
ヘッダーが 2 行になるFor ループの開始が 1 になっているFor i = 2 To lastRow2 を確認する(1 にするとヘッダーも条件判定される)

「型が一致しません」を防ぐ ― IsNumeric 関数

数値で比較したい列に “abc” のような文字やエラー値が混ざっていると、比較の時点で「型が一致しません」(エラー 13)が発生します。なお、セルに “850000” のように数字だけの文字列が入っている場合は、VBA が暗黙的に数値へ変換するためエラーにはなりません。

文字が混入する可能性がある場合は、IsNumeric() で数値かどうかを先に判定するのが確実です。

If IsNumeric(wsSource.Cells(i, 4).Value) Then
    If wsSource.Cells(i, 4).Value >= 800000 Then
        wsSource.Rows(i).Copy Destination:=wsDest.Rows(destRow)
        destRow = destRow + 1
    End If
End If

IsNumeric() は値が数値として扱えるかを返します。文字やエラー値の行はスキップされるため、マクロが途中で止まりません。

ただし最善策は、元データ側で数値列に文字が混入しないようにデータを整えることです。

まとめ

  • For ループで 1 行ずつ条件を判定し、Rows(i).Copy で別シートにコピーするのが基本の形
  • If の条件を書き換えるだけで、文字列一致・数値比較・部分一致(Like)・AND / OR に対応できる
  • 列番号の数え方(A = 1)と、シート名の一致が最初の確認ポイント
  • A 列はすべての行にデータを入れること。End(xlUp) は A 列を基準に最終行を取得するため、A 列の末尾が空白だと行を見落とす

Next Read

このあと読む記事

今の内容に近い記事から、次の1本と補助記事を続けて見つけられるようにしています。

Keep Exploring

このテーマをさらに探す

同じテーマの入口記事と更新記事を、一覧の形でまとめています。

コメント