VBAで自動化 VBA一覧 抽出・検索処理 条件一致・行列処理

【VBA】条件に一致する行を別シートへコピーする方法|指定した値で行を判定

Excel VBAで一覧データを処理していると、「条件に一致したデータだけ別のシートへコピーしたい」という場面があります。

たとえば、売上一覧からステータスが「未処理」のデータだけを作業用シートへコピーしたり、担当部署が「営業部」の行だけを別シートへ分けたりするケースです。データが数件なら手作業でも対応できますが、毎回数百行の一覧から対象を探してコピーするのは効率的ではありません。

VBAを利用すれば、指定した列の値を順番に確認し、条件に一致した行だけを別シートへ自動的にコピーできます。

ただし、実務では「どの列で判定するのか」「完全一致なのか部分一致なのか」「行全体をコピーするのか必要な範囲だけをコピーするのか」を最初に整理しておくことが重要です。

条件判定とコピー処理を明確に分けておけば、後から対象となる値や列が変更されても修正しやすいコードになります。

この記事では、指定した値と一致する行を判定し、該当する行を別シートへコピーする基本的な方法と、実務で扱いやすいコードの組み立て方を解説します。

✅ VBAで条件に一致する行を別シートへコピーする仕組み

条件に一致する行をコピーするとき、最初から複雑な条件式を作る必要はありません。まず重要なのは、「どの列を確認して」「どの値なら」「どの行をコピーするのか」という3点を分けて考えることです。実務では、条件となる文字が別の列にも存在していたため、意図しないデータを転記してしまうケースがあります。

また、「営業」と「営業部」のように完全一致と部分一致を混同すると、コピーされるデータも変わります。さらに、行全体をコピーすると書式なども含まれるため、必要なデータ範囲だけを扱いたい場合には別の設計が必要です。まずは条件判定とコピーの役割を整理してからコードを作成しましょう。

・判定する列とコピーする行を分けて考える

たとえば、「データ」シートに次の一覧があるとします。

A列:管理番号B列:商品名C列:状態
A001商品A完了
A002商品B未処理
A003商品C完了
A004商品D未処理

この一覧から、C列が「未処理」になっている行だけを「作業用」シートへコピーするとします。

処理の流れは次のようになります。

  1. コピー元となる「データ」シートを指定する
  2. コピー先となる「作業用」シートを指定する
  3. データの最終行を取得する
  4. C列の値を順番に確認する
  5. 「未処理」と一致するか判定する
  6. 一致した行を「作業用」シートへコピーする

ここで大切なのは、条件を確認する場所と、実際にコピーする対象は別に考えられることです。

今回であれば、条件判定に使用するのはC列ですが、条件に一致した場合にはA~C列を含む行のデータをコピーできます。

「C列を判定したからC列だけコピーする」という意味ではありません。

・完全一致で判定すれば対象データを限定できる

C列が「未処理」の場合だけコピーしたいのであれば、次のような条件式を使用できます。

If sourceSheet.Cells(rowIndex, "C").Value = targetValue Then

targetValueに、

targetValue = "未処理"

を設定しておけば、「未処理」と完全に一致したセルだけが対象になります。

たとえば、

C列の値コピー対象
未処理対象
未処理予定対象外
一部未処理対象外
完了対象外

となります。

「未処理」という文字が含まれていればすべて対象にする処理とは異なります。

実務では部分一致にすると想定以上のデータが対象になることもあるため、ステータスや区分など決められた値を条件にする場合は完全一致の方が対象を明確にしやすいというメリットがあります。

「未処理」と完全に一致する行ではなく、「未処理予定」「一部未処理」のように特定の文字を含む行を部分一致で判定したい場合は、検索方法を変える必要があります。部分一致で対象データを取得する方法については「【VBA】特定の文字を含む行を抽出する方法|部分一致したデータを取得」で詳しく解説しています。


✅ VBAで指定した値と一致する行を別シートへコピーする基本コード

条件に一致した行を別シートへコピーするコードでは、条件式そのものよりもコピー元・コピー先を明確にすることが重要です。ActiveSheetに依存したコードでも動作することはありますが、利用者が別のシートを開いた状態で実行すると意図しないシートを処理する可能性があります。

また、条件となる値をコードの各所へ直接記述すると、仕様変更時に修正箇所が増えてしまいます。小規模なマクロでは問題にならなくても、定期的に使用する処理ではこうした違いが保守性に影響します。そこで、対象シートと条件を最初に明示し、判定処理とコピー処理を読み取りやすく分けます。コードが何を基準に動いているのかを後から確認できる形にしておきましょう。

・条件に一致した行を別シートへ順番にコピーする

次の例では、「データ」シートのC列を確認し、「未処理」と一致する行を「作業用」シートへコピーします。

Sub CopyRowsByValue()

    Dim sourceSheet As Worksheet
    Dim destinationSheet As Worksheet
    Dim lastRow As Long
    Dim rowIndex As Long
    Dim destinationRow As Long
    Dim targetValue As String

    'コピー元・コピー先のシートを設定
    Set sourceSheet = ThisWorkbook.Worksheets("データ")
    Set destinationSheet = ThisWorkbook.Worksheets("作業用")

    '判定する値を設定
    targetValue = "未処理"

    'A列を基準にコピー元の最終行を取得
    lastRow = sourceSheet.Cells(sourceSheet.Rows.Count, "A").End(xlUp).Row

    'コピー先は2行目から使用
    destinationRow = 2

    '2行目から最終行まで条件を確認
    For rowIndex = 2 To lastRow

        If sourceSheet.Cells(rowIndex, "C").Value = targetValue Then

            '条件に一致した行をコピー
            sourceSheet.Rows(rowIndex).Copy _
                Destination:=destinationSheet.Rows(destinationRow)

            destinationRow = destinationRow + 1

        End If

    Next rowIndex

End Sub

このコードでは、コピー元のデータを上から順番に確認しています。

前回の「条件に一致する行を削除する処理」と違い、今回は元シートの行を削除しません。

そのため、

For rowIndex = 2 To lastRow

のように上から下へ処理しても、コピー元の行番号は変化しません。

ここは、行削除と行コピーで大きく異なるポイントです。

・コピー先の行番号を別の変数で管理する

今回のコードでは、

Dim destinationRow As Long

という変数を用意しています。

そして最初に、

destinationRow = 2

と設定しています。

これは、コピー元のrowIndexとコピー先の行番号を分けるためです。

たとえばコピー元では、

3行目:未処理
7行目:未処理
10行目:未処理

だったとしても、コピー先では、

2行目:コピー元3行目
3行目:コピー元7行目
4行目:コピー元10行目

のように詰めて配置できます。

条件に一致したときだけ、

destinationRow = destinationRow + 1

を実行しているためです。

もしコピー元と同じ行番号へそのまま転記すると、コピー先にも不要な空白行が大量に発生する可能性があります。

「どの行を調べているか」と「次にどこへ書き込むか」を別々に管理することで、処理の役割が明確になります。


✅ VBAで行全体をコピーするときに理解しておきたい範囲

Rows(rowIndex).Copyは分かりやすい方法ですが、「一覧表のデータだけを転記したい」という目的に対して常に最適とは限りません。RowsはA列からC列までのデータだけを意味するのではなく、Excelの行全体を表します。そのため、対象列が数列しかない一覧でも、コード上では行全体をコピーする指定になります。

また、コピー処理では値だけでなく書式なども引き継がれることがあるため、転記後のシートをどのように利用するかも考える必要があります。実務では「行をコピーしたい」という依頼でも、実際に必要なのはA列からF列までのデータだけということも珍しくありません。処理対象を必要以上に広げないためにも、Rowsと範囲指定の違いを理解しておきましょう。

・Rowsを使う方法は行全体をそのまま複製したい場合に向いている

今回の基本コードでは、

sourceSheet.Rows(rowIndex).Copy _
    Destination:=destinationSheet.Rows(destinationRow)

としています。

この方法は、条件に一致した行をそのまま別シートへコピーしたい場合には非常に分かりやすい書き方です。

たとえば元シートとコピー先で同じレイアウトを使用していて、

A列:管理番号
B列:商品名
C列:状態
D列:担当者
E列:更新日

といった一覧を行単位で移したい場合に利用できます。

一方で、A~E列しか使用していないのであれば、必要な範囲だけを明示する方法もあります。

sourceSheet.Range( _
    sourceSheet.Cells(rowIndex, "A"), _
    sourceSheet.Cells(rowIndex, "E") _
).Copy Destination:=destinationSheet.Cells(destinationRow, "A")

こちらは「A列からE列までをコピーする」という処理内容がコードから明確に分かります。

コードは少し長くなりますが、後から「F列も必要になった」といった仕様変更が発生した場合も、対象範囲を確認しやすくなります。

・行全体をコピーするか必要な列だけコピーするかを先に決める

どちらの書き方が正解というわけではありません。

元シートとコピー先の構成が完全に同じで、行全体をそのまま複製することに意味があるならRowsは分かりやすい方法です。

反対に、一覧表として使用している範囲が決まっているなら、必要な列だけを指定した方が処理の意図を明確にできます。

実務ではコードを書く前に、

  1. 条件判定に使用する列
  2. コピー対象となる列
  3. コピー先の開始位置
  4. 値だけ必要なのか、元の状態を含めてコピーしたいのか

を整理しておくと、後から処理を変更しやすくなります。

特に「条件に一致する行をコピーする」という要件だけでは、行全体を複製するのか、一覧表として必要な範囲だけを転記するのかが決まっていません。

この違いを最初に確認しておくことが、実務で使いやすいVBA処理を作るポイントです。

✅ VBAで条件に一致する行の値だけを別シートへ転記する

Copyメソッドは元データの状態を引き継ぎたい場合に便利ですが、実務では書式まで必要とは限りません。集計や後続処理のために別シートへデータを渡すだけなら、値だけを転記した方が扱いやすいケースがあります。

また、コピー元に数式が設定されている場合、その数式までコピーすると参照先が変化し、コピー先で想定外の結果になることがあります。元シートとコピー先で書式や数式の役割が異なる場合は、単純にCopyを使用する前に何を引き継ぐ必要があるのか確認することが重要です。見た目をそのまま複製するのか、データだけを受け渡すのかによって適切な方法は変わります。ここでは、条件に一致した行から必要な値だけを転記する方法を確認します。

・Valueを使って必要な範囲の値だけを転記する

たとえばA~E列の値だけを転記するのであれば、次のように記述できます。

If sourceSheet.Cells(rowIndex, "C").Value = targetValue Then

    destinationSheet.Range( _
        destinationSheet.Cells(destinationRow, "A"), _
        destinationSheet.Cells(destinationRow, "E") _
    ).Value = sourceSheet.Range( _
        sourceSheet.Cells(rowIndex, "A"), _
        sourceSheet.Cells(rowIndex, "E") _
    ).Value

    destinationRow = destinationRow + 1

End If

この方法では、コピー元のA~E列に入っている値を、コピー先の同じ範囲へ直接代入しています。

Copyメソッドを使用していないため、セルの書式をそのまま複製する処理とは役割が異なります。

たとえば元データのD列に数式があり、その計算結果だけを作業用データとして残したい場合にも利用できます。

実務では、

  • 元のレイアウトや書式も必要 → Copy
  • データの値を後続処理で使用したい → Value
  • コピーする列を限定したい → Rangeで対象範囲を明示

というように、目的から方法を決めると分かりやすくなります。

「コピー」という言葉だけで実装方法を決めず、コピー先でそのデータを何に使うのかまで考えることが重要です。


✅ VBAで別シートへコピーする前に既存データを確認する

条件判定が正しくても、コピー先の状態を考慮していなければ想定外の結果になることがあります。今回の基本コードではコピー先を2行目から使用するため、すでに2行目以降にデータが存在すれば上書きされる可能性があります。テスト用の空シートでは問題なく動作しても、本番では前回処理したデータが残っていることもあります。

また、毎回結果を作り直す処理と、過去データへ追加していく処理では、コピー先の行番号を決める方法そのものが異なります。この違いを曖昧にしたままコードを流用すると、データの重複や上書きにつながります。コピー元の条件だけでなく、コピー先をどのような状態にしたいのかも事前に決めておきましょう。

・毎回結果を作り直すならコピー先の扱いを決めておく

今回のコードでは、

destinationRow = 2

としているため、条件に一致した最初のデータはコピー先の2行目に配置されます。

これは、毎回同じ場所から結果を作成する場合には分かりやすい方法です。

ただし、前回の実行結果が残っている状態でそのまま実行すると、古いデータと新しいデータが混在する可能性があります。

たとえば前回は10件が条件に一致し、今回は5件しか一致しなかった場合、2~6行目は新しいデータに置き換わっても、その下に前回の結果が残ることがあります。

そのため、毎回結果を作り直す運用なら、

  1. コピー先に既存データがあるか確認する
  2. 必要に応じて前回の結果をクリアする
  3. 見出しは残す
  4. 2行目から新しい結果を配置する

という流れを考えておく必要があります。

ただし、コピー先シートに別の情報も存在する場合、安易にシート全体をクリアしてはいけません。

「前回結果として消してよい範囲」を明確にしてから処理することが重要です。

・既存データへ追加したい場合は開始行の考え方が変わる

今回の記事では、

destinationRow = 2

として固定位置からコピーしています。

一方で、

「コピー先にすでに10件あるので、その下へ今回のデータを追加したい」

という場合には、固定された2行目からコピーすることはできません。

コピー先の最終行を確認し、その次の行から書き込む必要があります。

これは単なる条件付きコピーではなく、「既存データを保持しながら最終行へ追記する処理」になります。

業務上も、

  • 毎回最新結果へ入れ替える
  • 前回結果を残しながら履歴として追加する

では目的が異なります。

同じ「別シートへコピー」という処理でも、コピー先の運用方法によってコード設計を分けることが大切です。

コピー先を毎回作り直すのではなく、すでに存在するデータを残したまま、その最終行の下へ条件に一致した行を追加したい場合は、コピー先の最終行を取得する必要があります。追記方式の具体的な処理については「【VBA】条件に一致する行をコピーして別シートの最終行へ追加する方法」で詳しく解説しています。


 

✅ VBAで条件に一致する行がない場合も想定しておく

テスト時には条件に一致するデータを用意することが多いため、「対象が1件もない場合」が見落とされがちです。しかし実務では、未処理データが0件の日や、指定した区分が一覧に存在しないケースも普通にあります。条件に一致しないこと自体はエラーではありませんが、利用者から見ると「マクロが動かなかったのか」「対象がなかったのか」が分からないことがあります。

また、前回結果を残したまま運用していると、新しい対象が0件なのに古い結果を今回のデータだと誤認する危険もあります。自動化では正常にコピーできる場合だけでなく、何もコピーしない場合の状態まで考えておくことが重要です。処理件数を管理すると、実行結果を判断しやすくなります。

・コピーした件数を変数で管理する

コピー件数を確認したい場合は、カウント用の変数を追加できます。

Dim copiedCount As Long

条件に一致してコピーしたときに、

copiedCount = copiedCount + 1

とします。

処理後には、たとえば次のように判定できます。

If copiedCount = 0 Then
    MsgBox "条件に一致するデータはありませんでした。"
Else
    MsgBox copiedCount & "件のデータをコピーしました。"
End If

これによって利用者は、

「処理が失敗したから何も起こらなかった」

のではなく、

「正常に処理した結果、対象が0件だった」

と判断できます。

特に他の人が使用する業務マクロでは、処理結果が画面から分かるようにしておくと問い合わせや誤操作を減らしやすくなります。

ただし、複数のマクロを連続実行する仕組みでは、毎回メッセージボックスを表示すると処理を止めてしまいます。

その場合は、件数をセルへ記録したり、後続処理でcopiedCountを利用したりする設計も考えられます。


✅ VBAでコピー先シートが存在するか確認してから処理する

コピー元とコピー先を明示していても、指定したシートが必ず存在するとは限りません。業務ファイルでは利用者がシート名を変更したり、不要だと思って削除したりすることがあります。

また、月ごとに新しいブックを作成する運用では、コピー先シートの作成漏れが発生することもあります。Worksheets("作業用")のように名前を直接指定している場合、対象シートが存在しなければ処理を継続できません。そのため、繰り返し利用するマクロでは「シートがあること」を前提にしてよいのかを検討する必要があります。エラーを無理に無視するのではなく、処理を開始するための前提条件を明確にすることが大切です。

・シートを自動作成するか処理を止めるかは用途で判断する

今回の基本コードには、

Set destinationSheet = ThisWorkbook.Worksheets("作業用")

という指定があります。

「作業用」シートが存在しなければ、そのままコピー処理へ進むことはできません。

ここで考えられる設計は、大きく2つです。

  1. コピー先シートがなければ新しく作成する
  2. コピー先シートがなければ処理を中止する

一見すると自動作成した方が便利に思えますが、必ずしもそうとは限りません。

既存の「作業用」シートにあらかじめ見出し、書式、数式などが設定されている場合、空のシートを自動作成してコピーを続行すると、処理自体は完了しても期待した結果にならない可能性があります。

そのため、コピー先が単なるデータ置き場なら自動作成、決められたレイアウトを持つシートなら存在しない時点で処理を止めるといった判断が必要です。

エラーを発生させないことだけを目的にせず、正常な処理を続行できる状態なのかを基準に判断しましょう。

コピー先を毎回用意する運用で、指定したシートが存在しない場合だけ自動作成したい場合は、シートの存在確認を組み合わせる方法があります。「【VBA】シートがなければ作成する方法|存在確認して安全に追加する実務コード」で、存在確認から追加までの処理を詳しく解説しています。


✅ VBAで条件一致のコピー・抽出・追記を使い分ける

条件に一致するデータを別シートへ移す処理には、似たような方法が複数あります。そのため、「コピー」「抽出」「最終行への追加」を同じものとして扱うと、記事だけでなく実際のコードでも目的が曖昧になりやすくなります。たとえば、毎回作業用シートを作り直す処理と、履歴シートへデータを蓄積する処理では必要な設計が違います。

また、1つの値との完全一致ではなく、複数条件や部分一致で対象を絞り込むなら条件判定そのものが主役になります。実務では「別シートに持っていきたい」という要望だけでコードを書き始めず、そのデータをコピー先でどう使うのかを確認することが重要です。それぞれの役割を分けると、必要以上に複雑なマクロを作らずに済みます。

・単一条件で行を複製するなら今回の方法が分かりやすい

今回の記事で扱っているのは、

指定した列を確認
↓
特定の値と完全一致するか判定
↓
一致した行を別シートへコピー

という基本的な処理です。

たとえば、

  • 「未処理」の行を作業用シートへコピー
  • 「営業部」の行を確認用シートへコピー
  • 「要確認」の行だけ別シートへ複製

といった用途に向いています。

一方で、「営業部かつ未処理」のように複数の条件を組み合わせて対象を絞る場合は、条件判定の設計がより重要になります。

また、特定の文字を含むデータを探す場合は、完全一致ではなく部分一致の処理が必要です。

今回の記事ではこれらまで広げず、1つの指定値を基準として該当行をコピーする基本処理を中心に考えます。

今回は1つの値との一致を条件にしていますが、「営業部かつ未処理」「営業部または総務部」のように複数条件を組み合わせて対象行を判定したい場合は、AND・OR条件を使った判定が必要です。「【VBA】複数条件に一致する行を抽出する方法|AND・OR条件でデータを判定」では、複数条件による行の絞り込み方を解説しています。

・履歴として蓄積するなら最終行への追加が必要になる

コピー先を毎回作り直すのではなく、

前回データ
前回データ
前回データ
今回データ ← ここから追加
今回データ

のように蓄積したい場合は、コピー先の最終行を取得して、その次からデータを追加します。

この処理は、履歴管理や日次データの蓄積などでよく使用します。

ただし、追記方式では同じデータをマクロの再実行によって二重登録してしまう可能性もあります。

そのため、「最終行を取得できれば終わり」ではなく、

  • 同じデータを再登録してよいのか
  • 重複判定が必要か
  • 見出し行はどこにあるか
  • コピー先の最終行をどの列で取得するか

まで考える必要があります。

単純な別シートへのコピーとは運用上の注意点が異なるため、目的に応じて処理を分けることが重要です。

条件に一致する行に対しては、コピーだけでなく、検索・抽出・削除など目的に応じてさまざまな処理を選択できます。特定の文字を含む行に対するVBA処理をまとめて確認したい場合は、「【VBA】特定の文字を含む行の処理:検索・削除・別シートにコピー」も参考にしてください。


✅ VBAで別シートへのコピーを実務で安定して使うポイント

条件付きコピーは比較的シンプルなVBA処理ですが、業務で繰り返し利用すると入力データやシート構成が少しずつ変化することがあります。最初はC列だけを判定していた処理に別の条件が追加されたり、コピー対象がA~E列からA~G列へ増えたりすることもあります。このような変更を想定すると、条件やシート名をコードの各所へ直接書くより、役割ごとに整理した方が修正しやすくなります。

また、コピー処理が正常でも、コピー先に古いデータが残っていれば業務上は正しい結果とはいえません。マクロ単体の動作だけでなく、実行前後のデータ状態まで確認することが重要です。最後に、安定して運用するためのポイントを整理します。

・条件・シート・コピー範囲を明確にしておく

今回のコードでは、

Set sourceSheet = ThisWorkbook.Worksheets("データ")
Set destinationSheet = ThisWorkbook.Worksheets("作業用")
targetValue = "未処理"

のように、処理に必要な設定を分かりやすくしています。

実務では、後からコードを見たときに、

「どこから、何を条件にして、どこへコピーするのか」

が把握できることが大切です。

特に条件判定、コピー処理、コピー先管理を1つの長い処理として複雑に書くと、仕様変更時に影響範囲を判断しにくくなります。

最初は多少コードが長くなっても、

  • コピー元
  • コピー先
  • 判定値
  • 判定列
  • コピー範囲

という役割を意識しておくと、後から変更しやすくなります。

また、本番ファイルへ導入する前には、条件に一致するデータだけでなく、

  1. 条件に一致する行が複数ある
  2. 条件に一致する行が連続している
  3. 条件に一致する行が1件しかない
  4. 条件に一致する行が1件もない

といったケースでも確認しておくと安心です。


 

✅ まとめ:VBAで条件に一致する行を別シートへ正しくコピーしよう

VBAを使用すれば、指定した列の値を判定し、条件に一致する行だけを別シートへコピーできます。

ただし、実務では単にIfとCopyを組み合わせるだけでなく、コピーする範囲やコピー先の状態まで考えることが重要です。

  • 条件判定に使用する列とコピー対象を分けて考える
  • ステータスなど決められた値なら完全一致で対象を明確にできる
  • コピー元とコピー先のシートは明示する
  • コピー元とコピー先の行番号は別々に管理する
  • 行全体が必要ならRows、必要な範囲だけならRangeを使う
  • データだけ必要ならValueによる転記も選択肢になる
  • コピー先に前回データが残っていないか確認する
  • 条件に一致するデータが0件の場合も想定する
  • コピー先シートが存在しない場合の動作を決めておく
  • 既存データへ蓄積する場合は単純なコピーとは分けて設計する

特に重要なのは、「条件に一致した行をコピーする」という処理と、「コピー先でそのデータをどう利用するか」をセットで考えることです。

確認用の一時データなら毎回結果を作り直す方法が扱いやすく、履歴として残すなら既存データへの追記が必要になります。また、元シートと同じ見た目を維持したい場合と、値だけを後続処理へ渡したい場合でも適切なコピー方法は変わります。

まずは「判定する列」「条件となる値」「コピーする範囲」「コピー先の使い方」の4点を整理してからコードを組み立ててみてください。

目的を明確にしておけば、データ量や業務内容が変わった場合にも修正しやすく、長く利用できるVBA処理につながります。

    -VBAで自動化, VBA一覧, 抽出・検索処理, 条件一致・行列処理