• ベストアンサー

エクセルVBAでの複数条件でオートフィルタをする方法

VBA初心者です。 例えば、シートに A  B 1 桃  100 2 柿  150 3 葡萄 400 というデータが書いてあって、ある時は「桃or柿」、またある時は「柿」だけ、「柿or葡萄」というようにVBAでオートフィルタをかけてデータを抽出したいと思っています。 その条件は、別にリストボックスが用意されていて、ユーザが選択した項目に該当するデータだけを取得したいのですが・・・ 不特定数の複数項目をオートフィルタの「or」条件で結ぶ事が出来ずに困っています。それともオートフィルタでは無理なのでしょうか? (知識が乏しくてすみません) どなたか良い解決策、または別策がありましたらご教授下さい。

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

  • ベストアンサー
  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.3

こんにちは。 リストボックスということですと、TSV の読み込みの部分は出来上がっているということでしょうか?質問を見た感じでは、AutoFilter よりも、AdvancedFilter のほうが印象的には相応しいように思いますが。 コントロールツールのListBoxを設定してください。 プロパティは、MultiSelect 1-fmMultiSelectMulti してください。 選択する内容は、ワークシートに書いたものを、ListFillRange に設定してください。 例: K1:K3 ListBox のクリックイベントや、Change イベントですと、そのまま反応してしまいますので、ダブルクリックイベントにしました。ただし、右クリックすると、選択は、すべてクリアされます。 ListBox のアイテム数(30個以内)なら、複数を選択できます。 A1から、リストが存在し、1行目がタイトル行があるという条件の元で成立します。そうでない場合は、また、ご指摘ください。 'シートモジュールを使います。 '-------------------------------------------------------------- Dim Form2 As String Private Sub ListBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean) 'リストボックスのダブルクリックで、フィルターが掛けられます。      '適当な場所に、Criteria を置いてください。   Dim myCriteria As Range   Set myCriteria = Range("L1:L2") '空いているところならどこでも可   Call MakeForm   If Form2 <> "" Then     myCriteria.Cells(2, 1).FormulaLocal = Form2     With Range("A1").CurrentRegion       .AdvancedFilter _       Action:=xlFilterInPlace, _       CriteriaRange:=myCriteria, _       Unique:=False     End With   End If   Set myCriteria = Nothing End Sub Private Sub MakeForm() '数式を作るサプルーチン Dim i As Integer Dim Ar As String Dim buf As String Dim Form1 As String  For i = 0 To ListBox1.ListCount - 1    If ListBox1.Selected(i) Then      buf = ListBox1.List(i)      Form1 = Form1 & "," & "A2=""" & buf & """"    End If    buf = ""  Next i  If Len(Form1) > 1 Then   Form1 = Mid(Form1, 2)   Form2 = "=OR(" & Form1 & ")"  End If End Sub Private Sub ListBox1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)   '右クリックしたら、選択をすべて消す   If Button = 2 Then     Dim i As Long     For i = 0 To ListBox1.ListCount - 1       ListBox1.Selected(i) = False     Next i   End If   'フィルターモードクリア   If ActiveSheet.FilterMode Then     ActiveSheet.ShowAllData   End If End Sub これは、今ひとつ気がかりなのは、TSV でインポートしたときに、空白値が混じりこむことです。その処理をきちんとされていることが条件です。それが不可能というか、部分的に一致する文字を検出する場合は、プログラムの一部を変更するか、空白値を削除するプログラムを書かなくてはなりません。

To_mo_hyan
質問者

お礼

こちらのコードが大変参考になりましたので、良回答とさせていただきました。 ありがとうございました!

To_mo_hyan
質問者

補足

Wendy02さん、ありがとうございます。 ちょっと上記のコードを取り入れて検証してみました。 ですが、私の知識不足では、理解するのにもう一息ですので、少し質問させてください。 動きを追ってみたら、AdvancedFilter(私は始めて知りました)は、凄いですね。 おっしゃる通り、TSVの取り込みはできています。 Sheet1にそのリストボックスがあり、Sheet2には取り込んだままのTSV(データと余計なコメントなどが入ったもの)があり、Sheet3には、取り込んだTSV内のデータの部分のみ(タイトル行は除去されていました。すみません。)で、データはA1から始まる、という構成になっています。 色々調べたのですが、     myCriteria.Cells(2, 1).FormulaLocal = Form2     With Range("A1").CurrentRegion       .AdvancedFilter _       Action:=xlFilterInPlace, _       CriteriaRange:=myCriteria, _       Unique:=False     End With の部分が何をしているのか調べ切れませんでした。申し訳ないのですが、少々解説していただけたら、と思います。

その他の回答 (3)

  • Wendy02
  • ベストアンサー率57% (3570/6232)
回答No.4

こんにちは。 #3の回答者です。 説明するのは、ちょっとややこしいと思います。 >myCriteria.Cells(2, 1).FormulaLocal = Form2 ポイントは、ここの部分のみです。 Form2 は、他のサブルーチンで作った、モジュールレベルの変数、Form2 を呼んでいるのです。そこには、数式が入ります。これを、通常のフィルターオプション形式で書いていったら、2個・3個ならともかく、それ以上は、面倒で溜まったものではありませんので、数式にしました。 この方法は、Microsoft のサポートにハウツーが出ていたと思います。ここのCriteria は特殊で、Criteria というのは、2行あって、その1行目が空欄でなくてはなりません。その2行目に、数式を入れるのです。True Or False の数式が入るのです。それで、フィルタリングするのです。 後は、一般のフィルタオプション(AdvancedFilter)の方法だけです。 一度、ためしに、記録マクロをとってみてもよいと思います。こういうものは、記録マクロも手書きでも、変わらないのです。少し、工夫を加えてやるだけでよいです。(私が、あまり考えていないのがバレますが(^^;) Range("A1").CurrentRegion こういうことはお分かりですよね。 一応、連続のセルが続いていたりすると、余計なところまで巻き込んでしまいますので、列数を決める必要があれば、Columns 辺りで、変えなくてはなりません。また、間が空いていたら、End プロパティでとってあげなくてはなりません。

To_mo_hyan
質問者

お礼

初めて利用するので、よくわかっていませんでしたが、補足と、お礼の二つは別物なのですね。 補足と重複していまいますが、本当にありがとうございました!

To_mo_hyan
質問者

補足

Wendy02さん、ご丁寧にありがとうございました。 解決できそうです。これから盛り込んでいくところです。 実は記録マクロを全然利用しないで手書きをしていたので、AdvancedFilterに気づけなかったのも一因だと、今回の質問を通して痛感いたしました。 それを利用して初めて データ→フィルタ→フィルタオプションの設定は、AdvancedFilterが用いられている、ということを知りました。 (この「フィルタオプションの設定」もあまり使用しないので、見落としていました) 色々勉強になりました!

  • hana-hana3
  • ベストアンサー率31% (4940/15541)
回答No.2

1.オートフィルタで設定可能な条件は2つなので、    「桃or柿」「柿」「柿or葡萄」という設定なら可能です。 Selection.AutoFilter Field:=1, Criteria1:= "=" & "柿", Operator:=xlOr, _ Criteria2:= "=" & "桃" 2.「その条件は、別にリストボックスが用意されていて」というのは、かなり難しくなります。 普通にオートフィルタを設定して、オプションで選択する方が簡単かもしれません。

To_mo_hyan
質問者

お礼

オートフィルタ機能が難しい、という判断を早めに出来たので、時間をロスせずに助かりました。 実際に複数「xlOr」を繋げてみたら、動きませんでした。 その検証もせずに、複数をオートフィルタで、と考えていた自分に未熟さを感じます。 ありがとうございました。

To_mo_hyan
質問者

補足

hana-hana3さん。 恥ずかしながら「オートフィルタに設定可能な条件は2つ」ということ知りませんでした。 1.逆引きVBAの本を片手に作業しているのですが、「xlOr」を繋げれば、いくつでも指定できるのかと思っていました。 2.例えば、「ANo.1」で補足したデータで説明すると、「果物名リストボックス」には、データの「果物名」に入っている全てのアイテム(重複無し)が表示されています。そこから、ユーザは複数選択を行い、その結果を返したいのです。 色々ありがとうございました。 今回やろうとしていることは、オートフィルタ機能では難しいのかもしれない、ということがわかれば、別の案を検討できます。

  • pbforce
  • ベストアンサー率22% (379/1719)
回答No.1

項目が2つでよければ、手動でオートフィルターがかけれます。 その動作をマクロの記録を使えば、方法は判明しますよ。

To_mo_hyan
質問者

お礼

マクロの記録を使用したことが無かったのですが、今回の質問を通して、とても勉強になりました。 貴重なお時間、ありがとうございました。

To_mo_hyan
質問者

補足

pbforceさん、早々とありがとうございます。 実際の項目は2つではなく、とりこんだTSVによって変化します。 もう少し説明を付加しますと   A    B 1 果物名 値段 (←先ほどこれがぬけていましたが、項目名です) 2 桃  100 3  柿   150 4 葡萄  400 とデータがあるとして、別のリストボックスで桃だけ選択されたなら Range("A1").AutoFilter 1, "桃" 桃と柿が選択されたなら Range("A1").AutoFilter 1, "桃", xlOr, "柿" 桃と柿と葡萄が選択されたなら Range("A1").AutoFilter 1, "桃", xlOr, "柿", xlOr, "葡萄" という風にVBAで書きたいのです。 今回ユーザは、リストボックスのみを操作し、該当するデータを抽出したいのです。説明が足りなくて申し訳ございませんでした。

関連するQ&A

  • エクセルVBA オートフィルタについて

    オートフィルタは2つまでしか条件が設定できません。 3つ以上設定する方法はないでしょうか?(OR条件です) オートフィルタの引数(Criteria)は2つしかありませんから、恐らく3つ以上の設定はできないと思っています。 そこで、オートフィルタを複数回設定し、使っていない列に特定の文字(例えば○など)を入れ、最後にこの○を条件にすることにより、実質的に3つ以上条件のフィルタリングを実現させたいと考えております。 そこでお聞きしたいのは、各条件でフィルタリングした時に、任意の列に○を入れる方法です。 例えば myRng.AutoFilter Field:=4, Criteria1:="=?UA*" でフィルタリングしたエリアの特定の列に○を入れるにはどのようなVBAになるのでしょうか? オートフィルタを使わず、ループで全行の条件を聞いて、○をつけることは可能ですが、行数が非常に多いので時間がかかってしまいます。 オートフィルタを使えばすばやく該当行が選択されますので、何とかこれを利用したいと思っています。何か良い方法は無いでしょうか? よろしくお願いします。

  • エクセルのオートフィルターの使い方

    エクセル2010で1000行程度の表からオートフィルターで必要な情報を抽出しているのですが、該当する条件を▼セルで探すのも面倒なので、所定のセルに条件を入力したらオートフィルターで抽出できる方法があれば教えてください。

  • エクセルのオートフィルタについて

    エクセルのオートフィルタについて以下の2つの作業が可能であれば教えて下さい。 (1)1桁目の数字が1、2、3、4の四つの場合の行を抽出することは可能でしょうか?オートフィルタオプションでは「or」条件で例えば1、2の二つの場合の行の抽出はできるのですが。 (2)6桁の数字があるとして5桁目が5の数字の行を抽出することは可能でしょうか?オートフィルタオプションでは「~で始まる」や「~で終わる」行の抽出はできるのですが。

  • オートフィルタオプションをVBAで指定したい

    表中に、このような列があるとします。 肩ロース100g 肩ロース500g ヒレ100g ヒレ250g ヒレ500g レバー100g レバー250g 他の列には注文日や個数、小計金額があるとします。 オートフィルタをかけて、フィルタオプションで「○○で始まる」を指定し、例えばレバーの行のみを手作業で抽出することはできます。 この動作を、フィルタオプションでの設定を経由せずに行えないものでしょうか? たとえば、別の列などに「肩ロース」「ヒレ」「レバー」が記載されていて、そのデータを元にオートフィルタの▼をクリックすると「肩ロース」「ヒレ」のように抽出条件データが表示される、というふうには出来ないものでしょうか? VBA等を使用しても構いません。 抽出項目は固定ですので、コード中に記述しても構いません。 動作が要望を満たせば、オートフィルタを使用しなくても構いません。 フォームウィンドウで抽出項目を指定し、その項目をCriteria等に設定してフィルタオプションでも構いません(この方法は自力で出来そうですが)。 良い方法があれば、お教え下さい。

  • 「~以上、~以下」のオートフィルタのVBAについて

    こんばんは、オートフィルタについて2つ質問させてください! 1つ目は、10列目に入っている値で、20170901以上かつ20170931以下の値をオートフィルタで抽出しようと以下のVBAを入力しましたが、該当するデータがあるにも関わらず抽出ができませんでした(T_T)何か間違っているのでしょうか…?! Range("A1:K" & Cells(1).CurrentRegion.Rows.Count).AutoFilter Field:=10, Criteria1:=">=20170901" _ , Operator:=xlAnd, Criteria2:="<=20170931" 2つ目は、同様のデータでInputBoxを利用し、入力した数字をそのままオートフィルタの条件に反映しようとする以下のVBAを入力してみました。しかし、やはり記述の方法が違うのか該当するデータがあるにも関わらず抽出は成功しませんでした・・・。 Dim 日付 As Date 日付 = InputBox("処理月を入力して下さい(例:201709)") Range("A1:K" & Cells(1).CurrentRegion.Rows.Count).AutoFilter Field:=10, Criteria1:=">= 日付 & 01" _ , Operator:=xlAnd, Criteria2:="<= 日付 & 31 " どなたかご助力いただけるととても助かります、どうぞよろしくお願いいたします!m(_ _)m

  • Excel VBAでオートフィルタ後の結果を置換する方法

    こんばんは、フィルタを使うべきか、(検索で2つの条件は設定できないし・・・)悩んでいます。 オートフィルタで、2つの項目に対して、条件を設定し表を絞り込んだのですが、その結果に対して、例えば こもも ピンク こもも ピンク こもも ピンク こもも ピンク などと抽出が出来たとします。この結果の「こもも」を「ピーチ小」に置き換えたいのですが、どのような手順でマクロを組めばよいのでしょうか。 VBAが少しずつ判りかけてきたのですが、難しい記述は良くわかりません。 できればたくさんコメントを頂くと助かります。 宜しくお願い致します。

  • エクセルのオートフィルタ

    エクセルで住所録を作り、そのうちの東京都のデータだけオートフィルタで抽出し、それを別のシートにコピーして表を作りたいのですが、抽出はできても表にすることができません。オートフィルタで抽出したデータだけを一覧表にすることはできないのでしょうか?

  • エクセルVBAで3つ以上の複数条件でオートフィルタをする方法

    表題のとおりなんですが、コマンドボタンを使って、VBAで3つ以上の条件でオートフィルタを実行したいのですが、なにかいい方法はありませんか?

  • エクセルで、オートフィルターに多数の条件をいれたい

    表題のように、エクセルで、日付、商品名、分類、数量、単価、金額・・・などの情報を、横並びにして、その一つ一つのデータが縦に1000行強あるようなシートの構成において、オートフィルタを使ってある条件にあったもののみを抽出したいのですが、条件が二つまでならオートフィルタのオプションで選べますが、ランダムな条件を4つ、あるいは6つという風にたくさん入れたい場合、どうすればいいでしょう?データとしてはピボットで解決できて集計もできますが、ピボットだと最初のデータと見た目が全然違ってしまうのであとに続く処理にはふさわしくないのです。 関数を使って、あるシートから多数の条件にかなったものを抽出するにはどうすればいいでしょうか?よろしくお願いします。

  • エクセルのオートフィルタについて

    質問させてください エクセルのオートフィルタ機能でデータを抽出したのですが、 他の表からも同様にオートフィルタ機能でデータを抽出しようとすると、 ツールバーのオートフィルタの所に既にチェックが入っていて、 そこをクリックしてしまうと、最初の表で抽出したデーターが元に戻ってしまいます。 オートフィルタは2つの表には適用できないのでしょうか? それとも、最初の表のオートフィルタを確定し、次の表に進むことは出来るのでしょうか? どなたか、ご指導よろしくお願い致します。

専門家に質問してみよう