Excel VBAで条件にマッチする行を抽出する方法

このQ&Aのポイント
  • Excelで特定の条件にマッチする行を抽出するVBAプログラムの例を紹介します。
  • D3またはE3に入力された条件に合致する行だけが抽出され、リアルタイムで結果が変更されます。
  • 本記事では、フィルタオプションを使用して抽出結果を表示する方法と、VBAを使用して抽出結果を別のシートにコピーする方法を解説します。
回答を見る
  • ベストアンサー

条件にマッチする行を抽出するVBAを教えてください

アイデア、またはVBAプログラムの例を教えていただきたく、質問させていただきます excelで、添付画像のようなリスト管理表を作っています。 リストは600行近くになります。 やりたいことは、D3またはE3に商品名または保管庫を入力すると、リスト内から、合致する行だけが抽出される、というもの。 D3とE3は、どちらか片方にのみ条件が入る。D3とE3の内容を変更するとリアルタイムで抽出結果も変更されるようにしたい。 触る人が初心者なので、難しい作業を一切せずに、D3またはE3を打ちかえるだけで必要な項目だけのリストとなり、印刷するだけでいいようにしたいわけです。 本来ならオートフィルタですればいい話ですが、どうしてもD3という離れたセルの入力内容で抽出したいのです。 VBAでなく、D3のセル内容を使ってD8~のオートフィルタが行えるなら、それが一番理想です。 が、自分でやってみた限りはできませんでした。 フィルタオプションならどうかとやってみたところ、一回目は抽出できました。しかし、D3またはE3の条件を変更しても、リアルタイムで抽出結果が切り変わらない。 フィルタオプションの抽出結果を別のセルに出せばいいのですが、そうすると無駄な情報が残り、ただ印刷しただけでOK・・というわけにいきません。(印刷範囲を区切るとかでなく、シートの見栄えが必要な情報だけにならないと…扱う初心者が混乱します) 自分なりには、VBAにより、 D3・E3のセル内容が書き換わったらフィルタオプションの抽出結果をいったん同シートの別セルに出し、抽出結果部分だけを別のシートにカット&ペースト成形。そのシートを印刷させればよい。 という考えになりましたが、やってみたら、なぜか別のブックに同じものが形成され、抽出した結果だけ単独のデータにできません。 そもそももっと良いアイデアがあればそれをおしえていただきたい。 あるいは、VBAで目的達成できるように問題点をご指摘ください。 一応、プログラムを書いておきます ■添付画像のデータが入っているシート(『一覧』という名前のシート)内コード Private Sub Worksheet_Change(ByVal Target As Range) ' If Target.Column = 4 Then If Target.Row >= 3 And Target.Row <= 3 Then Call Filter Call copy End If End If End Sub ■サブルーチンFilter() 標準モジュールに記載 Sub Filter() ' Filter Macro 'フィルタオプションを使って同シート内「D1100」以降に抽出結果を出します ActiveWorkbook.Worksheets("一覧").Select '一覧表はD7~F1000。検索条件はD2~F3までの範囲に名前を付けたもの Range("一覧表").AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=Range( _ "検索条件"), CopyToRange:=Range("D1100"), Unique:=False Range("A1").Select End Sub ■サブルーチンcopy() 標準モジュールに記載 Sub copy() ' ' copy Macro ' '抽出された内容(45行目~100行目まで)を別のシートにコピーします ActiveWorkbook.Worksheets("一覧").Select Rows("45:100").Select Selection.Cut ActiveWorkbook.Worksheets("抽出結果").Select Rows("4:4").Select Selection.Insert Shift:=xlDown Range("A1").Select End Sub

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

追記: では、当方で検証したサンプルコードを載せますので、ご参考に。結果提示用に「抽出結果」と名付けたまっさらなシートを予め用意しておいてください。 と、その前に注意点。 ご質問内容では、シートモジュールや標準モジュール等、複数のモジュールにコードが分散していますが、今回の処理内容では、モジュールを分ける意味がありません。シートモジュールのワークシートチェンジイベント1本で十分です。従って、ご案内するコードは、一覧表のあるシートのシート見出しを右クリック→コードの表示から呼び出した画面に書き込み、入力が終わったら、ファイルタブ→終了してexcelに戻る、としてください。 それと、クライテリアを使うと、倉庫1の検索で倉庫10以降もピックアップされてしまうので、1は全角で10以降は半角にするなど、元ネタに区別をしてください。 また、利用者のなかにビギナーがいるのであれば、セルのロックと保護を使い、一覧シートのD3:E3しか操作出来ないようにする、入力規則を使って、商品1,商品2といったリストから選ばせる、等の工夫も考えられます。それらをどう併用するかによって適切なコードも変わってきますので、細部はご自身で調整してください。 Private Sub Worksheet_Change(ByVal Target As Range) If Application.Intersect(Target, [D3:E3]) Is Nothing Then Exit Sub Worksheets(”抽出結果”).[A1:C1000].ClearContents Range(”一覧表”).AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=Range _ (”検索条件”), Copytorange:=Worksheets(”抽出結果”).Range(”A1”) End Sub

tanako-gi-
質問者

お礼

サンプルコードを書いてくださったのも勿論ありがたかったのですが、注意点や特徴をよく説明してくださって、大変分かりやすかったです。 処理自体は、まだまだ多くの工程を経て完成に向かいますが、質問項目に関しては目標を達成でき、理解が深まったと感じます。 総じてyaritsusozaiさんおひとかたのみの回答でしたが、よいかたと巡りあえて幸運でした。 このプログラムと解説、大事に活用させていただきます。 ありがとうございました(*^^*)

その他の回答 (1)

回答No.1

抽出結果を1100行以降に書き出したのに、その後45~100行を選んでコピーしているのが意味不明ですが… AdvancedFilterのCopytorangeを、 :=Worksheets(”抽出結果”).Range(”A1”) にすれば、どこかに抽出したデータをさらに別シートにコピーするといったような”二度手間”は省けます。 もう一点、新たな抽出の際、前回抽出したものが残っているとごっちゃになる恐れがあるので、 AdvancedFilterを使う前に、 Worksheets(”抽出結果”).[A1:C1000].ClearContents などで、宛先をクリアにしておくと良いと思います。

tanako-gi-
質問者

補足

>抽出結果を1100行以降に書き出したのに、 >その後45~100行にコピーしているのが意味不明 すみません、データを少なくして実行チェックを行っていたので、それが残ってました… この部分は正しく100行以降にコピーするように直して実行しています。 >AdvancedFilterのCopytorangeを、 >:=Worksheets(”抽出結果”).Range(”A1”)にすれば、 それが…マクロを記録する際にも別シートは選べませんでしたし、 VBAコード側でこれを書き込んでみましたが、抽出結果が現れませんでした… >Worksheets(”抽出結果”).[A1:C1000].ClearContents >などで、宛先をクリアに これは確かにしておくべき、と思いました。ありがとうございます。

関連するQ&A

  • シートを増やすVBA

    フィルタで隠れている場合もある列の値を シート名として増やしていくVBAで以下のようなものをつくりました (値は重複している場合もある) 雛型シートがありそれをシート名だけ増やしていくというものです Sub シートを増やす() Dim target As Range Dim h As Range On Error Resume Next Set target = Worksheets("一覧シート").Range("E10:E" & Worksheets("一覧シート").Range("E65536").End(xlUp).Row).SpecialCells(xlCellTypeVisible) If target Is Nothing Then Exit Sub 'シートを増やしていく For Each h In target On Error GoTo errhandle Worksheets(h.Value).Select On Error GoTo 0 Next Sheets("一覧シート").Select Exit Sub errhandle: Worksheets("雛型").Copy after:=Worksheets(Worksheets.Count) ActiveSheet.Name = h.Value Resume End Sub そうすると、実行エラー1004 ”シートの名前をほかのシート、Visual Basicで参照されるオブジェクトライブラリまたはワークシートと同じ名前に変更することはできません。” というエラーがたまにおきます(シート名が数字の場合におきるようです) 解決方法及び理由をご教授ください

  • excelで複数条件で抽出する

    excel VBAで質問です。(初心者レベルです) A列からZ列までデータがあり、オートフィルタでE列で条件に当てはまるものと、E列では条件外だが、Y列では条件に当てはまるものを別シートに抽出したいと思っています。 Sub Macro1()   With Worksheets("Sheet1")     .Range("A1").AutoFilter _       Field:=5, Criteria1:="*条件*"     .Range("A1").CurrentRegion.SpecialCells(xlCellTypeVisible).Copy _       Worksheets("Sheet2").Range("A1")   End With End Sub Fieldを変えて、E列、Y列それぞれはできるのですが、データが重複してしまいます。 重複分を削除するため、セル入力で連番を降って、重複するものを削除しようとしましたがうまくいかず。 なにかいい方法はないでしょうか。

  • エクセルVBAでコピーすると行の高さが低くなる

    いつもお世話になってます。 エクセル2003のVBAで、セルの範囲を指定してコピーすると行の高さが低くなってしまいます。その他の書式は、変化せずうまくコピーできています。以下がプログラムです。 Sub copy_hyou() Worksheets("sheet1").Activate Range("A1:K24").Copy 'セルA1からK24をコピーします。 Range("A25").Select 'A25からペイストします。 ActiveSheet.Paste End Sub どう直せば、行の高さもコピーできるでしょうか? お休み中すみませんがよろしくお願いいたします。

  • VBA 最終行を選んだシートにコピーする。

    VBAど初心者です。どうしても最終行のデータを選んだシートにコピーできません。 LastRow.Selectのところで、止まってしまいます。どのように行を設定していいのかさっぱりわかりません。どなたか、ご指導のほどよろしくお願いします。 Sub copy_last_line() Dim LastRow As Long Sheets("Sheet1").Select LastRow = Cells(Rows.Count, 1).End(xlUp).Row LastRow.Select Selection.Copy Sheets("Sheet2").Select Range("A1").Select ActiveSheet.Paste Sheets("Sheet1").Select Range("A1").Select End Sub

  • 抽出してコピペ 検索すべき文字が存在しない場合は?

    エクセルのマクロを使って、売上帳を作成しています。 下のようなコードで、F2に顧客番号を入れると、売上帳シート内から選んだ顧客のみの売上明細が個別売上帳シートに移るように作っています。 そこで問題なのですが、売上帳シート内に存在しない顧客番号(取引がなかった顧客)を抽出しようとすると、全明細がそっくり抽出されてしまいます。 私としては、その場合は抽出すべきものがないとして、個別売上帳シートは空欄にしてしまいたいのですが、どうすればよいでしょう? 教えてください。 Sub 顧客抽出コピペ() Sheets("売上帳").Select Range("B6").AutoFilter Field:=2, Criteria1:=Range("F2").Value '2つ目のフィルターに検索文字 Range("B5:B2005").Select Selection.Copy Sheets("個別売上帳").Select Range("B5").Select Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False Sheets("売上帳").Select Range("E5:J2005").Select Selection.Copy Sheets("個別売上帳").Select Range("C5").Select Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False End Sub

  • ExcelのVBAで教えてください。

    Private Sub Worksheet_Changeについて教えて下さい。 まず初歩的なご質問ですが、Private Sub Worksheet_Changeを1つのシートモジュールに1個以上組むことは可能なのでしょうか? 例えばネットで以下のようにsheet1に Private Sub Worksheet_Change Private Sub Worksheet_Change_1 _1を付けてるのを見たことがあったので試してみましたが動作しませんでした。 今回行いたいのは1つが、指定したセルが変更されると次の指定セルに移動する。 以下がマクロです。 Private Sub Worksheet_Change(ByVal Target As Excel.Range) Select Case Target.Address(0, 0) Case "E14" [E15].Select Case "E15" [E26].Select Case "E26" [E22].Select Case "E22" [E25].Select Case "E25" [E29].Select Case "E29" [E20].Select Case "E20" [E21].Select Case "E21" [E16].Select Case "E16" [E17].Select Case "E17" [E27].Select Case "E27" [E23].Select Case "E23" [E24].Select Case "E24" [E28].Select Case "E28" [E18].Select Case "E18" [E19].Select End Select End Sub もう一つが、あるセルに数値をいれると他のブックのシートからそのシートの指定した行のセルの 数値を読み込んできて、元のブックのシートに数値を書き込むといったもです。 以下がマクロです。 Private Sub Worksheet_Change_1(ByVal Target As Excel.Range) Dim w As Workbook Dim c As Range On Error Resume Next Set xCur = Selection If Application.Intersect(Target, Range("F3")) Is Nothing Then Exit Sub If Range("F3") = "" Then Exit Sub Application.ScreenUpdating = False '転記元のブックを開いて逆順で検索する Set w = Workbooks.Open("V:\新3係(FIA・iPot)\(2)新4係(iPot)\ipot進捗\履歴管理\(9)KBB39360 X8 imm1.35 G1履歴、本体履歴 .xls") Set c = w.Worksheets("対物").Range("B:B").Find(what:=Range("F3").Value, LookIn:=xlValues, lookat:=xlPart, searchdirection:=xlPrevious) '見つけた(一番下の)セルを基準に転記する If Not c Is Nothing Then Range("F4").Value = c.Offset(0, 1).Value End If w.Close False Application.ScreenUpdating = True End Sub ともに1つずつなら問題なく動作するのですが、2個のマクロを組むと片方しか動作しません。 多分ものすごく初歩的な事だとは思いますが、御指導の程宜しくお願いします。

  • EXCEL VBA オートフィルで別シートへコピー

    EXCEL VBA オートフィルで別シートへコピー しようとしたら、うまくいきません 別々に書くとうまくいくのですが コードを一緒にするとうまくいきません? コード *********************************************** Sub 抽出別シート() Worksheets("時間合計VB").Select ' 時間合計VBのシートを選択 Range("A1").AutoFilter field:=8, Criteria1:="<=1" '1時間以下の8列目のをフィルター end sub sub カレントで別シートへコピー() Range("A1").CurrentRegion.Copy Sheets("1hdown").Range("A1")   'それをカレントして別シートのA1へコピー Range("A1").AutoFilter End Sub *********************************************** このように書くとうまくいくのですが これを一緒に書くと別シートへコピーがうまくいきません。 全てコピーされてしまいます +++++++++++++++++++++++++++++++++++++++++++++++ 一緒にしたコードです +++++++++++++++++++++++++++++++++++++++++++++++ *********************************************** Sub 抽出別シート() '1h以下をを抽出別シートへコピー Worksheets("時間合計VB").Select ' 時間合計VBのシートを選択 Range("A1").AutoFilter field:=8, Criteria1:="<=1"    '1時間以下の8列目のをフィルター Range("A1").CurrentRegion.Copy Sheets("1hdown").Range("A1")    'それをカレントして別シートのA1へコピー Range("A1").AutoFilter End Sub *********************************************** 意味が分かりませんどなたかおしえていただけませんでしょうか? よろしくお願いいたします

  • VBAでオートフィルタ抽出後コピペ

    VBA初心者で勉強中の者です。 『工事台帳シート』からオートフィルタで抽出したものを、『工事別表示シート』にコピペするコードをつくりました。 以下のものです。 Sub 工事抽出コピペ() Dim Obj As Object With Sheets("工事台帳") Set Obj = .Range("E5:E65536").Find(.Range("E2"), LookAt:=xlWhole) If Obj Is Nothing Then MsgBox "見つかりませんでした。" Sheets("工事別表示").Range("B11:F65536").ClearContents Exit Sub Else .Range("B6").AutoFilter Field:=4, Criteria1:=.Range("E2").Value .Range("F5:J65536").Copy End If End With Sheets("工事別表示").Range("B11").PasteSpecial Paste:=xlPasteValues Application.CutCopyMode = False End Sub これを起動させると、 Sheets("工事別表示").Range("B11").PasteSpecial Paste:=xlPasteValues の部分が黄色くなり、 実行時エラー'1004'「コピー領域と貼付領域の形が違うため、情報を貼り付けることができません」 という表示が出てきます。 これはどういう意味なのでしょうか? ちなみにコピー領域セルも貼付領域セルも結合はなく、行・列の幅も同じです。 このコードもいろいろな本やサイトで教えてもらったのを参考に作っているので、私自身深く理解せずに書いているところもあります。 どなたか教えてくださる方、よろしくおねがいします。

  • エクセルVBAの条件指定が上手くいきません

    「7を超えたら、For Eachステートメントを抜けなさい」という条件を入れたいのですが、 7を超えても処理が継続し困っています。 勉強不足で申し訳ないですが、ご教授願います。 【やりたいこと】 まず、セルB1~D3までのセルの値(9つ)が、7を超えない条件で1を加算していきます。 加算したときの値はE~Gの列に貼り付けていきます。 7を超えた時点でFor Eachステートメントを抜けます。 また、B1~D3までのセルには計算式が入っており、A1に数字を入れると、 それぞれ異なる増え方をします。(計算式自体は$A$1+1.1、$A$1+2.1などシンプルなもの) Sub test() Dim i As Range Dim n As Long Dim x As Long n = 1 x = 1 For Each i In Range("B1:D3") Range("A1").Value = x If i < 7 Then Range("B1:D3").Copy Cells(n, 5).Select Selection.PasteSpecial Paste:=xlPasteValues n = n + 3 x = x + 1 ElseIf i > 7 Then Exit For End If Next End Sub お手数ですが、宜しくお願いいたします。

  • 複数のシートにまたがり、フィルタオプションの設定から値を抽出するマクロ

    複数のシートにまたがり、フィルタオプションの設定から値を抽出するマクロを組んでおります。 表示したくないシート(data,output)を非表示にしたら、エラーが出てしまいました。 非表示シートの状態で処理することはできませんでしょうか。 Sub Macro7() Application.ScreenUpdating = False Sheets("data").Select Columns("A:J").AdvancedFilter Action:=xlFilterInPlace, CriteriaRange:= _ Sheets("マップ").Range("E2:N3"), Unique:=False Columns("A:J").Select Selection.Copy Sheets("output").Select Range("A1").Select ActiveSheet.Paste Application.CutCopyMode = False Selection.Copy Sheets("マップ").Select Range("E5").Select ActiveSheet.Paste Range("H4").Select Sheets("data").Select Application.CutCopyMode = False ActiveSheet.ShowAllData Sheets("マップ").Select End Sub