質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

解決済

3回答

2072閲覧

「Filterプロパティを利用した検索機能」エラーの原因は分かっているのですが、よい回避策が分からずにいます。

miniryu

総合スコア15

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2018/03/20 02:26

編集2018/03/22 03:05

前回の続きになります。進捗が遅くてお恥ずかしいですが、どうぞよろしくお願い致します。
Filterプロパティを利用した検索機能についてなのですが、エラーの原因は分かっているのですが、対処の仕方が分からずにいます。どうぞ知恵をおかしください。

検索機能について
ユーザーフォームにオブジェクト(テキストボックスを2つ、検索ボタンを1つ、リストボックスを1つ)を設置しています。

検索にかける文字列は、TextBox1に姓(ex.山田)もしくはセイ(ex.ヤマダ)、TextBox2に数字4文字(ex.0123)。

検索の参照先は、TextBox1がレコードセット(adoRs)の「姓」もしくは「セイ」のフィールドの値、TextBox2が「電話番号1」もしくは「電話番号2」のフィールドの値です。

検索条件は、TextBox1とTextBox2と共に部分一致です。またテキストボックスへの入力はTextBox1とTextBox2のどちらか一方のみ、もしくは2つとも入力しても検索可能な仕様にしたいと思っています。

最後に検索条件に一致したら、レコードセットを参照して必要な情報をリストボックスに表示します。

エラーがでる場所

vba

1adoRs.Filter = "姓 like '%" & Me.TextBox1.Value & "%'" & "OR セイ like '%" & Me.TextBox1.Value & "%'" & _ 2 "OR 電話番号1 like '%" & Me.TextBox2.Value & "%'" & "OR 電話番号2 like '%" & Me.TextBox2.Value & "%'"

エラーメッセージ
実行時エラー'301':
引数が間違った型、許容範囲外、または競合しています。

原因と思われるもの
Filterプロパティの検索文字列にはNullの値は使用できないという説明がありました。
用意している参照先のAccessデータベースにはNullもあります。
テキストボックスの値は空("")のときにエラーが出るので、これがNullと競合?しているのだと思われます。

考えてみた解決策
素人考えで解決策を考えてみました。テキストボックスの値が空だとエラーが出るので、空の場合はアンダーバーを入れる、というようにしてみました。しかし、うまいやり方ではないんじゃないかと思われて…。(下記のコードをadoRs.Filterより前にかませてみたら一応動きはしたのですが…)

vba

1 If Me.TextBox1.Value = "" Then 2 Me.TextBox1.Value = "_" 3 Else 4 Me.TextBox1.Value = Me.TextBox1.Value 5 End If 6 If Me.TextBox2.Value = "" Then 7 Me.TextBox2.Value = "_" 8 Else 9 Me.TextBox2.Value = Me.TextBox2.Value 10 End If 11

なにか良い回避策をご教授いただけませんでしょうか?どうぞよろしくお願い致します。
質問に不備がありましたら改善したいと思いますので、ご指摘いただけると幸いです。

全文は下記の通りです。

vba

1Option Explicit 2 3'---ACCESS接続用 4Private adoCn As Object 5Private adoRs As Object 6Private strSQL As String 7 8'---ユーザーを検索 9Private Sub SearchButton_Click() 10 Dim cnt As Long 11 12 Call ConnectDB 'データベースに接続 13 14 strSQL = "SELECT * FROM 顧客マスター" 15 adoRs.Open strSQL, adoCn 16 17 '抽出条件を設定してフィルターをかける 18 adoRs.Filter = "姓 like '%" & Me.TextBox1.Value & "%'" & "OR セイ like '%" & Me.TextBox1.Value & "%'" & _ 19 "OR 電話番号1 like '%" & Me.TextBox2.Value & "%'" & "OR 電話番号2 like '%" & Me.TextBox2.Value & "%'" 20 21 If adoRs.BOF = True And adoRs.EOF = True Then '条件に一致するデータがない場合、データベースを切断して終了 22 Call CutDB 23 MsgBox "条件に一致するデータがありません。" 24 Else 25 With Me.SearchList 26 .ColumnCount = 8 27 .ColumnWidths = "50;50;40;40;60;200;100;100;" 28 .Font.Size = 13 29 Do Until adoRs.EOF 'レコードが終了するまで繰り返す 30 .AddItem "" 'リストボックスに表示する 31 .List(cnt, 0) = NullChg(adoRs(3).Value) '姓 32 .List(cnt, 1) = NullChg(adoRs(4).Value) '名 33 .List(cnt, 2) = NullChg(adoRs(6).Value) 'セイ 34 .List(cnt, 3) = NullChg(adoRs(7).Value) 'メイ 35 .List(cnt, 4) = NullChg(adoRs(10).Value) '都道府県(住所1) 36 .List(cnt, 5) = NullChg(adoRs(11).Value) '住所2 37 .List(cnt, 6) = NullChg(adoRs(13).Value) '電話番号1 38 .List(cnt, 7) = NullChg(adoRs(14).Value) '電話番号2 39 adoRs.MoveNext 40 cnt = cnt + 1 41 Loop 42 End With 43 End If 44 45 Call CutDB '検索がすんだら、データベースを切断して終了 46 Exit Sub 47 48End Sub 49

追記

たびたび申し訳ありません。自分がやりたい事というのが自分でもよく把握していなかったみたいです…。今回、皆さま方よりご回答をいただいて、ようやくそれを明確にできてきました。

それで、いただいたご回答を参考にしながら、自分のやりたい抽出条件を書いてみました。
①それぞれのテキストボックスに別々の抽出条件(SearchFilter1とSearchFilter2)を設定する
②その上でテキストボックスへの記入がされているかどうかで条件分岐して
③最初に設定した抽出条件を使用して、最終的な抽出条件(adoRs.filter)を決定する。

vba

1Dim SearchFilter1 As String, SearchFilter2 As String 2 3'それぞれのテキストボックスに抽出条件を設定 4SearchFilter1 = ("姓 like '%" & Me.TextBox1.Value & "%'" & " OR セイ like '%" & Me.TextBox1.Value & "%'") 5SearchFilter2 = ("電話番号1 like '%" & Me.TextBox2.Value & "%'" & " OR 電話番号2 like '%" & Me.TextBox2.Value & "%'") 6 7'それぞれのテキストボックスへの入力の有無により条件分岐 8If Me.TextBox1.Value = "" And Me.TextBox2.Value = "" Then 'どちらも未入力の場合 9 Call CutDB 10 MsgBox "テキストボックスに条件を入力してください。" 11 Exit Sub 12ElseIf Me.TextBox1.Value <> "" And Me.TextBox2.Value <> "" Then 'どちらにも入力されている場合 13 adoRs.filter = SearchFilter1 & " AND " & SearchFilter2 14ElseIf Me.TextBox1.Value <> "" And Me.TextBox2.Value = "" Then 'TextBox1のみ入力されている場合 15 adoRs.filter = SearchFilter1 16ElseIf Me.TextBox1.Value = "" And Me.TextBox2.Value <> "" Then 'TextBox2のみ入力されている場合 17 adoRs.filter = SearchFilter2 18End If 19

ただ、これだと adoRs.filter = SearchFilter1 & " AND " & SearchFilter2 でエラーが出てしまいます。
ANDOR にすると動くのですが、意図する仕様は AND です。

エラーメッセージ
実行時エラー'301':
引数が間違った型、許容範囲外、または競合しています。

OR はよくて AND はだめな理由が分かりません。。

追記2

サンプルコードありがとうございます。示していただいたサンプルコードを試してみたのですが、やはり AND のところで、同様のエラーが発生してしまいます。同じように OR だと動きます。

いろいろ試すことで、vbaに少しずつ慣れてきているのは自分でも嬉しいのですが、それは置いといて、なぜ意図どおりに動いてくれないのか…

ORの場合は動くので、最初に思いついた原因の「Nullとうまく参照できていない」というのとは別に原因がありそうだと思い直しています。

追記2-2

公式の説明にANDで結合できないことが書かれてありました。結合の仕方を変える必要があるそうです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

or演算子の前にスペースがありませんけど。

追記

テキストボックスが空の場合には値0の文字列となり、長さ0の文字列とは異なります。
どちらでも""として比較できるようですけど、Nullと合わせてややこしそうなので、
それらを一旦変数に格納してから、処理を行うように変更してみました。
※条件組み立て部分も一部修正

VBA

1Dim SearchFilter1 As String, SearchFilter2 As String 2Dim ConditionsItem1 as string, ConditionsItem2 as string 3 4ConditionsItem1 = IIF(IsNull(Me.TextBox1.Value),"", Me.TextBox1.Value) 5ConditionsItem2 = IIF(IsNull(Me.TextBox2.Value),"", Me.TextBox2.Value) 6 7'それぞれのテキストボックスに抽出条件を設定 8SearchFilter1 = ("姓 like '%" & ConditionsItem1 & "%'" & " OR セイ like '%" & ConditionsItem1 & "%'") 9SearchFilter2 = ("電話番号1 like '%" & ConditionsItem2 & "%'" & " OR 電話番号2 like '%" & ConditionsItem2 & "%'") 10 11'それぞれのテキストボックスへの入力の有無により条件分岐 12If ConditionsItem1 = "" And ConditionsItem2 = "" Then 'どちらも未入力の場合 13 Call CutDB 14 MsgBox "テキストボックスに条件を入力してください。" 15 Exit Sub 16ElseIf ConditionsItem1 <> "" And ConditionsItem2 <> "" Then 'どちらにも入力されている場合 17 adoRs.filter = "(" & SearchFilter1 & ") AND (" & SearchFilter2 & ")" '←括弧で括る 18ElseIf ConditionsItem1 <> "" And ConditionsItem2 = "" Then 'TextBox1のみ入力されている場合 19 adoRs.filter = SearchFilter1 20ElseIf ConditionsItem1 = "" And ConditionsItem2 <> "" Then 'TextBox2のみ入力されている場合 21 adoRs.filter = SearchFilter2 22End If

投稿2018/03/20 04:21

編集2018/03/20 09:47
sazi

総合スコア25173

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

miniryu

2018/03/20 09:01

ご指摘ありがとうございます。修正させていただきます。
guest

0

ベストアンサー

おそらくテキストボックスが空のときは、フィルタの条件が%%になってしまうのが原因ではないでしょうか。
値があるときとないときで条件を動的に変更してみては。

VBA

1Dim filter As String 2filter = "" 3If Me.TextBox1.Value <> "" Then 4 filter = "姓 like '%" & Me.TextBox1.Value & "%'" & "OR セイ like '%" & Me.TextBox1.Value & "%'" 5End If 6If Me.TextBox2.Value <> "" Then 7 If filter <> "" Then 8 filter = filter & " OR " 9 End If 10 filter = filter & "電話番号1 like '%" & Me.TextBox2.Value & "%'" & "OR 電話番号2 like '%" & Me.TextBox2.Value & "%'" 11End If 12adoRs.Filter = filter

ちなみに空のときに_で置き換えてしまうと、%_%という条件になってしまい、アンダースコアを含むものが抽出されてしまいますので、間違った処理です。

--
少しだけかっこよく書き直してみました。
但し、条件がOR固定なのでAND条件があったりすると改造が必要です。
単純にOR条件を追加していく分には楽ではないかと思います。

VBA

1Private Sub SearchButton_Click() 2 ~省略~ 3 4 Dim filters() As String 5 ' テキストボックス1が入力されているとき 6 If Me.TextBox1.Value <> "" Then 7 Call AddFilter(filters, "姓 like '%" & Me.TextBox1.Value & "%'") 8 Call AddFilter(filters, "セイ like '%" & Me.TextBox1.Value & "%'") 9 End If 10 ' テキストボックス2が入力されているとき 11 If Me.TextBox2.Value <> "" Then 12 Call AddFilter(filters, "電話番号1 like '%" & Me.TextBox2.Value & "%'") 13 Call AddFilter(filters, "電話番号2 like '%" & Me.TextBox2.Value & "%'") 14 End If 15 '抽出条件を設定してフィルターをかける 16 adoRs.Filter = Join(filters, " OR ") 17 18 ~省略~ 19End Sub 20 21Sub AddFilter(ByRef filters() As String, joken As String) 22 If Not Not filters Then 23 ReDim Preserve filters(UBound(filters) + 1) 24 Else 25 ReDim filters(0) 26 End If 27 filters(UBound(filters)) = joken 28End Function

--
ORとANDの混在バージョン。

VBA

1Private Sub SearchButton_Click() 2 ~省略~ 3 4 Dim filters() As String 5 ' テキストボックス1が入力されているとき 6 With Me.TextBox1 7 If .Value <> "" Then 8 Call AddFilter(filters, "(姓 like '%" & .Value & "%' OR セイ like '%" & .Value & "%')") 9 End If 10 End With 11 ' テキストボックス2が入力されているとき 12 With Me.TextBox2 13 If .Value <> "" Then 14 Call AddFilter(filters, "(電話番号1 like '%" & .Value & "%' OR 電話番号2 like '%" & .Value & "%')") 15 End If 16 End With 17 '抽出条件を設定してフィルターをかける 18 adoRs.Filter = Join(filters, " AND ") 19 20 ~省略~ 21End Sub

投稿2018/03/20 02:33

編集2018/03/20 09:15
ttyp03

総合スコア16998

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

miniryu

2018/03/20 09:05

まだ使ったことがない関数があったりして、こういう書き方もあるのかと、とても勉強になります。 自分の頭が弱いせいか、ここに来てようやく自分のやりたいことが、AND条件を使用するものであることが分かってきました。行きつ戻りつして、お手数をおかけしてしまいすみません。
ttyp03

2018/03/20 09:15

一応ANDにも対応したのを書いて見ました(動作未確認) 参考にしてみてください。
guest

0

処理を詳細に分けるべきですね。

Dim Filter1 As String
if Me.TextBox1.Value <> "" Then
Filter1 = "姓 like '%" & Me.TextBox1.Value & "%'"
End if

という風に分け、Or が必要なら後から変数に追加し、
adoRs.Filter = Filter1 & Filter2 & Filter3 & Filter4
等としてみては?

投稿2018/03/20 02:37

ExcelVBAer

総合スコア1175

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問