[[20160224181436]] 『VBA オートフィルタの文字列(数値)検索についax(そら) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『VBA オートフィルタの文字列(数値)検索について』(そら)

お忙しいとは思いますがご教示お願いいたします。

○状況
sheetに文字列書式でデータを入力(数値の文字列エラー出ていない状態)

(例)A列

      15
     115
     115/りんご
     apple

userformにINPUT用のコンボボックス、およびコマンドボタンあり

○手順
userformのコンボボックスよりINPUTデータを取得(FindKey/string)
userformのコマンドボタンよりvba実行

【コード】
Dim FindKey as String
FindKey = ComboBox1.Text
WorkSheets("sheet1").Range("A1").AutoFilter _

        Field:=1, _
        Criteria1:="*" & FindKey & "*"

コンボボックスで15(Findkey=15)を入力した際、
115/りんごはフィルタでヒットされるも、15や115はヒットされません。
ただ、一度15や115をダブルクリックし、エラー検知(数値が文字列として〜)させると、
ヒットするようになります。(その後、エラーを無視にしてもヒット)
また、ワイルドカードを使用しない場合(*を外す)もヒットします。

色々試しましたが、何か基礎的な考えが抜けてる気がします。。。
ご教示して頂いても宜しいでしょうか?

< 使用 Excel:Excel2010、使用 OS:Windows7 >


 こう云うことで悩んだ事がなかったので、今回、実際に試行してみました。

 <現象からすると・・ですけど・・>

 >コンボボックスで15(Findkey=15)を入力した際、 
 >115/りんごはフィルタでヒットされるも、15や115はヒットされません。

 「ワイルドカード(*)を付加したために、検索対象が文字列だけになってしまった」
 と云うことになります。

 >一度15や115をダブルクリックし、エラー検知(数値が文字列として〜)させると、 
 >ヒットするようになります。(その後、エラーを無視にしてもヒット) 

 これは、セルの書式を文字列にしてある為、ダブルクリックによって、数値が文字列に変化した為です。

 >ワイルドカードを使用しない場合(*を外す)もヒットします。 

 この場合は、数値も文字列も対象になるようです。

 <対策としては>
 (1) 15や115が、数値型にしておく必要がなければ、数字(文字型)に変更してからフィルターに掛ける。

 (2) 15や115が、数値型のままにしておく必要があるなら、
     別の列に文字型に変えたデータを作り、そっちの列でオートフィルターに掛ける。
   ※文字型に変更する数式は簡単です。
    E列でやる場合:E1セルに =A1&"" と入力して下にコピーする。

(半平太) 2016/02/24(水) 20:44


半平太様、お忙しい中、早々なご回答ありがとうございます。

説明不足な点がございましたが、現在の状況/必要条件、私がした事も追記させて頂き、
コード内やデータだけでの対策があれば幸いです。

現在の状況/必要条件のおさらいとしては以下の通りです。

○15や115など含め、全てシート書式は「文字列」になっている
(セル編集を行うと数値の文字列エラーが出る⇒その状態であればVBAでヒット⇒現在はセル編集をしていない状態でエラーは出ていない)
○普通に手作業でオートフィルタをすれば「15」でも「*15*」でも全てヒットする
○"*" & FindKey & "*" ⇒ "*" & CStr(FindKey) & "*"に変更しても結果は変わらず
 CStr有り無し関わらず、検索前のFindKeyは文字列型(8)です(Vartype関数)
○他の列に追加する対策は除外させて下さい
○データ自体は変更できません(15,115,115/りんご,apple・・・などが複合⇒文字列設定にて)

普通に手作業で行うオートフィルタにあって、
VBAにするオートフィルタには何かオプションが足りないのか、
もしくはシートやデータ自体に問題があるのかが分かりません。

何度も質問してしまい申し訳ございませんが、ご教示宜しくお願いいたします。
(そら) 2016/02/25(木) 10:48


 >○普通に手作業でオートフィルタをすれば「15」でも「*15*」でも全てヒットする 

 この部分は、前回の試行では特に意識していなかったです。

 その作業を「マクロの記録」でコードを録ってみると「*15*」を指定しているのではなく、 
  Criteria1:=Array("115", "115/りんご", "15")

 となっていますから、複数の選択項目を配列に入れて「直接指定」していますよね。

 それが、手作業で行うことの意味(実体もしくは裏処理)と云えるんじゃないでしょうか?
 それと同じことをするならば、

 Sub FiterByArray()
     Dim FindKey As String
     Dim dtAry

     FindKey = ComboBox1.Text

     dtAry = Filter(Application.Transpose(ActiveSheet.Range("$A$1:$A$6").Value), FindKey, True)

     If UBound(dtAry) >= 0 Then
         Worksheets("sheet1").Range("A1").AutoFilter _
         Field:=1, Criteria1:=dtAry, Operator:=xlFilterValues
     Else
         MsgBox "該当なし"
     End If
 End Sub

 ’サンプルでは問題なかったですが、選択項目数がすごく多い場合どうなるか、こちらでは確かめておりません。

(半平太) 2016/02/25(木) 12:09


  ↑
 <追記>
 配列内(dtAry)の重複項目は排除すべきでした。m(__)m
 まずは、そちらで考えてみてください。

(半平太) 2016/02/25(木) 12:17


 >○普通に手作業でオートフィルタをすれば「15」でも「*15*」でも全てヒットする 

   この部分は、前回の試行では特に意識していなかったです。

   その作業を「マクロの記録」でコードを録ってみると「*15*」を指定しているのではなく、 
    Criteria1:=Array("115", "115/りんご", "15")

   となっていますから、複数の選択項目を配列に入れて「直接指定」していますよね。
   それが、手作業で行うことの意味(実体もしくは裏処理)と云えるんじゃないでしょうか?

  それと同じことをするならば、

 Sub FiterByArray()
     Dim FindKey As String
     Dim dtAry, exItem, dicT As Object
     Dim Ws As Worksheet

     FindKey = ComboBox1.Text

     Set Ws = Worksheets("sheet1")
     Set dicT = CreateObject("Scripting.Dictionary")

     For Each exItem In Ws.Range("A1", Ws.Cells(Ws.Rows.Count, "A").End(xlUp)).Value
         dicT(exItem) = Empty
     Next

     dtAry = Filter(dicT.keys, FindKey, True)

     If UBound(dtAry) >= 0 Then
         Ws.Range("A1").AutoFilter _
         Field:=1, Criteria1:=dtAry, Operator:=xlFilterValues
     Else
         MsgBox "該当なし"
     End If
 End Sub

 ’サンプルでは問題なかったですが、選択項目数がすごく多くなるとどうなるか、こちらでは確かめておりません。

 '<追記>
 ’配列内(dtAry)の重複項目を無くしたバージョンに変更しました。

(半平太) 2016/02/25(木) 17:00


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.