ACCESS 複数条件の検索フォーム作成方法(VBAコード公開)

複数条件の検索フォーム作成方法

ACCESSで検索フォームを作成する際、複数の条件を組み合わせて検索したいというケースが多いと思います。

・日付を期間指定しつつ、顧客名をあいまい検索で組み合わせる

・顧客名と担当者名を組み合わせる

などなど。

今回は、複数の条件を組み合わせて検索ができる、検索フォームの作成方法をご紹介します。


こんにちは。
はこにわガジェット (@hakoniwagadget) です。

ACCESSを使った売上管理、顧客管理などのデータベース開発を行っています。
ACCESSは使いこなすために少しスキルが必要なものの、うまく活用すればExcelよりも業務の効率化が図れます。
この記事ではACCESSで実際に作成したフォームやレポートを、その作成方法と共にご紹介していきます。

ACCESSで作成した検索フォーム(完成形)

まず、作成した検索フォームの機能をご紹介します。
画面は下記の通りです。

こちらは、売上データを検索するためのフォームです。

フォームの上段に設置されているのが検索条件で、

・売上日(期間指定)

・顧客名(あいまい検索)

・商品名(あいまい検索)

・未請求のみ(チェック)

・削除済みデータを含む(チェック)

の5つの検索条件を組み合わせて検索できるようになっています。
検索条件を入れて、「検索」ボタンを押すことで下段のレコード表示が変更されます。

例えば、顧客名を「株式会社ココナラ」、商品名を「レポート」に設定して検索すると以下の結果になります。

複数の条件に合ったレコードだけが抽出されていますね。

それでは、作り方を順にみていきましょう。

テーブル・クエリの準備

最初に、検索対象となるテーブル・クエリを準備しましょう。

今回は、LIST_売上明細というクエリを検索対象として準備しました。

ここで準備するのはテーブルでもクエリでもどちらでも構いません。

ただし、検索条件とするフィールドを必ず含めるようにしてください。
今回の例でいうと、売上日(クエリ上は処理日)、顧客名、商品名、請求済フラグ、削除フラグ、はクエリのフィールドに最低限含めています。

フォームの作成

次に、フォームを作っていきましょう。
ACCESSメニューの「作成」から「フォームウィザード」で作っていきます。

フォームウィザード

ウィザードを起動すると、フォームのもととなるテーブル・クエリと、フィールドを聞かれます。

今回は、クエリ「LIST_売上明細」を元に作成するので、プルダウンでこちらを選択した後に、選択可能なフィールド(左)から、選択したフィールド(右)へ必要なフィールドを映していきます。

右側に移したフィールドが、フォーム上で表示できるようになります。
今回はクエリのすべてのフィールドを右側に移動させます。

次に、フォームのレイアウトの選択です。

ここでは表形式を選択してください。
表形式は、複数のレコードを一覧表示できるレイアウトで、検索フォームに適しています。

最後に名前を付けてフォームを作成しましょう。

すると、とりあえずこんな感じのフォームが出来上がります。

ここから、フォームのデザインビューでレイアウトを修正していきます。

最初は詳細セクションです。

表形式のフォームでは詳細セクション(画面中央)がレコード数分、繰り返し表示されます。

まず、ここを必要なフィールドのみに修正し、横幅や高さを揃えていきましょう。

フォームに配置されているテキストボックスなどをコントロールと呼びます。高さはすべてのコントロールで揃えておくと見やすくなります。
また、すべてのコントロールを詳細セクションの最上段(高さ0)に配置し、詳細セクションの高さをコントールと合わせておくとさらに見やすいです。

下記のようなイメージです。

次に、フォームヘッダーを修正します。

フォームヘッダーには検索条件と、先ほど作成した詳細セクションの見出しにあたるラベルを配置します。

まずは検索条件です。
こちらは、ACCESSのメニューからテキストボックスを選択して配置していきます。

テキストボックス

この際、特にテーブルやクエリのフィールドとは紐づけない、非連結のテキストボックスにて作成してください。
非連結のテキストボックスは、フォーム上で操作はできますがそのままではデータベースのデータには影響を及ぼさないものです。

ここでは、売上日検索FROM、売上日検索TO、顧客名検索、商品名検索、未請求検索、削除検索というコントロールを作成しました。

なお、未請求検索、削除検索はチェックボックスになっていますので、同様にこちらのボタンから作成できます。

チェックボックス

これらの検索条件用コントロールを配置する際に注意したいのがコントロール名です。
これらのコントロールの名称はのちにVBAで使用しますので、テキスト1のようなデフォルト値ではなく、わかりやすいコントロール名に変更しておきましょう。

プロパティシートの「名前」欄で変更が可能です。

また、検索用のボタンも作成します。
フォームデザインメニューから、ボタンを選択します。

ボタン

こちらで、検索ボタンを作成します。
検索条件のテキストボックス同様、こちらもVBAで使用しますのでボタン名はわかりやすいものに変更しておきましょう。
私は命名規則を統一しており「〇〇〇〇_ボタン」としています。

なお、こうしたコントロール名には半角カナや記号は使わず、全角カナか半角英数、記号を使うならアンダーバー(_)のみにしましょう。

また、詳細セクションの見出しにあたるラベルは、フォームヘッダーの一番下に配置します。

フォームヘッダーの一番下にすることで、フォームビューで表示した際に表としてきれいに見えます。

それと、フォームヘッダーのラベルと、詳細セクションの各コントロールの横位置をぴったり合わせておくことにも注意しましょう。

横の位置がラベルとずれていると、表の縦線がずれているように見えて視認性が悪くなります。

あとはレイアウトなどを微調整してフォームのデザインを完成させます。

VBAのプログラミング

それでは、フォームも出来上がったのでここから検索機能のVBAプログラミングを行います。

フォームのデザインビューで検索ボタンを選択し、プロパティシートからクリック時のイベントプロシージャを作成します。

プロパティシートのクリック時の行の一番右にある「…」マークを押して、コードビルダーを選択してください。

コードビルダー

Visual Basic Editor(VBE)が起動しますので、そこで以下のコードを設定します。


Private Sub 検索_ボタン_Click()

'検索用変数の定義
Dim filter_txt As String

    filter_txt = ""

'FROM、TOの前後不備チェック
If Me!売上日検索FROM <> "" And Me!売上日検索TO <> "" Then

    If Me!売上日検索FROM > Me!売上日検索TO Then

        MsgBox "期間指定が不適切です。再度入力してください。", vbCritical + vbOKOnly, "期間指定不備"
        Exit Sub

    End If

End If

'売上期間
If Me!売上日検索FROM <> "" Then
    
    If Me!売上日検索TO <> "" Then
        
        filter_txt = "処理日 >= #" & Me!売上日検索FROM & "# and 処理日 <= #" & Me!売上日検索TO & "#"
    
    Else
        
        filter_txt = "処理日 >= #" & Me!売上日検索FROM & "#"
        
    End If
        
ElseIf Me!売上日検索TO <> "" Then

    filter_txt = "処理日 <= #" & Me!売上日検索TO & "#"
        
End If


'顧客名
If Me!顧客名検索 <> "" Then
       
    If filter_txt = "" Then
       
        filter_txt = "顧客名 like '*" & Me!顧客名検索 & "*'"
        
    Else

        filter_txt = filter_txt & " and 顧客名 like '*" & Me!顧客名検索 & "*'"
            
    End If
        
End If

'商品名
    If Me!商品名検索 <> "" Then
       
        If filter_txt = "" Then
       
            filter_txt = "商品名 like '*" & Me!商品名検索 & "*'"
        
    Else

        filter_txt = filter_txt & " and 商品名 like '*" & Me!商品名検索 & "*'"
            
    End If
        
End If

'未請求
If Me!未請求検索 = True Then
       
    If filter_txt = "" Then
       
        filter_txt = "請求済 = false"
       
    Else
         
        filter_txt = filter_txt & " and 請求済 = false"
    
    End If
        
End If
    
'削除
If Me!削除検索 = False Then
       
    If filter_txt = "" Then
       
        filter_txt = "削除 = false"
       
    Else
         
        filter_txt = filter_txt & " and 削除 = false"
    
    End If
        
End If
    
If filter_txt = "" Then

    Me.FilterOn = False

Else

    Debug.Print filter_txt
    Me.Filter = filter_txt
    Me.FilterOn = True
    Me.OrderBy = "処理日 DESC"
    Me.OrderByOn = True

End If

End Sub
 

以下、それぞれの内容を解説します。

全体の構成

この検索用コードは「filter_txt」という変数に、フォームで指定された内容をもとにした検索条件文を代入し、最終的に


    Me.Filter = filter_txt
    Me.FilterOn = True
 

でフォームにフィルターを適用することで検索条件に合致したレコードのみを表示する、という構成になっています。

そのため、コードのほとんどはfilter_txtの編集を行っています。

以下はそれぞれの検索条件ごとにどのようにフォームで入力された内容を、VBAでの検索条件文に反映しているか見ていきましょう。

売上日検索(日付期間指定検索)

最初は日付の期間指定による検索です。
フォームの売上日検索FROM、売上日検索TOで指定した日付の間にあるレコードのみを抽出するように条件文を設定します。

この際注意しなければいけないのは、フォームの入力状態として以下の4つのパターンが想定されることです。

1.売上日検索FROMだけが入力されている

2.売上日検索TOだけが入力されている

3.売上日検索FROM、売上日検索TOの両方が入力されている

4.売上日検索FROM、売上日検索TOのどちらも入力されていない

このすべてのパターンでエラーなく動作するような設定が必要なことです。

また、3.のパターンでは売上日検索FROMの日付の方が、売上日検索TOの日付よりも大きい場合は論理的に矛盾するため検索結果が表示できません。
そのため、この場合はアラートを画面に表示する必要があります。

これらを踏まえて、最初に


 If Me!売上日検索FROM <> "" And Me!売上日検索TO <> "" Then
 

で、3.売上日検索FROM、売上日検索TOの両方が入力されているのパターンのみ抽出しています。

Me!売上日検索FROMやMe!売上日検索TOというのは、現在のフォーム(この場合は売上検索フォーム)の売上日検索FROMや売上日検索TOコントロールを指しています。

つまり、フォームの売上日検索FROMも売上日検索TOも空白(””)ではない(<>)という条件になっているのです。

この条件に合致した場合、つまり売上日検索FROMと売上日検索TOの両方が入力されている場合、さらに売上日検索FROMの日付の方が、売上日検索TOの日付よりも大きい場合はMsgBox関数でアラートメッセージを出します。


    If Me!売上日検索FROM > Me!売上日検索TO Then

        MsgBox "期間指定が不適切です。再度入力してください。", vbCritical + vbOKOnly, "期間指定不備"
        Exit Sub

    End If
 

これでエラーチェックができましたので、次に実際の抽出条件文の作成処理を行います。


'売上期間
If Me!売上日検索FROM <> "" Then
    
    If Me!売上日検索TO <> "" Then
        
        filter_txt = "処理日 >= #" & Me!売上日検索FROM & "# and 処理日 <= #" & Me!売上日検索TO & "#"
    
    Else
        
        filter_txt = "処理日 >= #" & Me!売上日検索FROM & "#"
        
    End If
        
ElseIf Me!売上日検索TO <> "" Then

    filter_txt = "処理日 <= #" & Me!売上日検索TO & "#"
        
End If
 

If文で分岐させているのは、先ほどご説明した1.~4.のパターンを判別するためです。

最初のIf文、


If Me!売上日検索FROM <> "" Then
 

では売上日検索FROMが入力されているか否かを判定します。

次のIF文、


If Me!売上日検索TO <> "" Then
 

では売上日検索TOが入力されているか否かを判定します。

この2つのIf文を組み合わせることで、前述の4つのパターンを判定できるのです。

それぞれのパターンに対応した命令文は以下になっています。

1.売上日検索FROMだけが入力されている


 filter_txt = "処理日 >= #" & Me!売上日検索FROM & "#"
 

2.売上日検索TOだけが入力されている


 filter_txt = "処理日 <= #" & Me!売上日検索TO & "#"
 

3.売上日検索FROM、売上日検索TOの両方が入力されている


 filter_txt = "処理日 >= #" & Me!売上日検索FROM & "# and 処理日 <= #" & Me!売上日検索TO & "#"
 

4.売上日検索FROM、売上日検索TOのどちらも入力されていない

処理無し

ここで期間指定の抽出条件を記載する際の注意点をご説明します。
日付型のデータを扱う際には、値の前後に#が必要です。

上記の条件式も


 "処理日 >= " & Me!売上日検索FROM
 

ではなく、


 "処理日 >= #" & Me!売上日検索FROM & "#"
 

としています。
これは、Me!売上日検索FROMの値を日付型として扱うためです。

この#は忘れやすいので注意ください。

顧客名検索(テキストあいまい検索)

次に、顧客名での検索方法です。
こちらはフォームの「顧客名検索」に入力された値を元に、あいまい検索(部分一致)でレコードを抽出します。

コードで言うと下記の部分です。


'顧客名
If Me!顧客名検索 <> "" Then
       
    If filter_txt = "" Then
       
        filter_txt = "顧客名 like '*" & Me!顧客名検索 & "*'"
        
    Else

        filter_txt = filter_txt & " and 顧客名 like '*" & Me!顧客名検索 & "*'"
            
    End If
        
End If
 

まず最初のIf文である


 If Me!顧客名検索 <> "" Then
 

は、先ほどの売上日検索と同様に、フォームの顧客名検索に値が入力されているか否かのチェックです。
入力されていない場合は処理をスキップします。

実際に使用する条件式は以下です。


 filter_txt = "顧客名 like '*" & Me!顧客名検索 & "*'"
 

Me!顧客名検索の前後に*(アスタリスク)を付け、=ではなくLike演算子を使用することであいまい検索ができるようになっています。
例えば、フォームの顧客名検索に「たなか」とは言っていた場合は実際に使用される条件式は、「Me!顧客名検索」の部分が「たなか」に置き換えられますので


 顧客名 like "*たなか*"
 

となります。


 "顧客名 like '*" & Me!顧客名検索 & "*'" 
 

の最初と最後にある「”」は、条件式自体をテキストデータとして認識させるためのものですので、実際に利用される条件式からは除外されます。

複数の検索条件を組み合わせる方法

さて、ここにもう一つ条件分岐が入っています。


    If filter_txt = "" Then
 

こちらは、売上日検索のときにはなかった条件分岐です。
filter_txtに値が入っているか否かを判定する条件分岐ですが、これがなぜ必要になるかご説明します。

例えば、売上日と顧客名の両方の条件で検索を行いたいとします。

ここでは2022年1月1日から2022年2月28日の期間で、顧客名に「たなか」を含むレコードを検索したい、としましょう。
この際、フォームでは売上日検索と顧客名検索の両方に条件を入力し、その2つの条件をAnd条件(AかつB)で結果のレコードを表示したいわけです。

VBA上の動作では、まず最初の売上日検索の処理で、filter_txtに


 処理日 >= #2022/1/1# and 処理日 <= #2022/2/28#
 

が入ります。

一方、顧客名検索の処理では、


 顧客名 like "*たなか*"
 

が入ります。

この2つの条件を組わせる必要があるので、2つ目以降の条件式を作成する処理では、単純にfilter_txtに条件式を代入するだけではなく、


 filter_txt = filter_txt & 2つ目の条件式
 

として、すでにfilter_txtに入力されている式に追加の式を足していく必要があります。

しかし、ここで単純に&でつないでしまうと、filter_txtに代入される値は以下になってしまいます。


 処理日 >= #2022/1/1# and 処理日 <= #2022/2/28#顧客名 like "*たなか*"
 

これでは、2つの条件として読み込めないばかりか、filter_txt自体を条件式としてみなすことができなくなってしまいます。

そこで、2つの条件が正常に使えるように、条件式の間に単純な&ではなく


 & " and 
 

を入れる必要があるのです。

こうすることで、filter_txtに格納される値は


 処理日 >= #2022/1/1# and 処理日 <= # and 2022/2/28#顧客名 like "*たなか*"
 

となり、2つの条件式のAnd条件として利用できるようになります。

未請求検索(Yes / No検索)

さて、次の検索条件の設定に移りましょう。
商品名検索は顧客名検索と仕組みは同じなので割愛し、次は未請求検索です。

こちらは、フォームのチェックボックスを利用した検索条件設定です。

対象のコードはこちら。

'未請求
If Me!未請求検索 = True Then
       
    If filter_txt = "" Then
       
        filter_txt = "請求済 = false"
       
    Else
         
        filter_txt = filter_txt & " and 請求済 = false"
    
    End If
        
End If
 

最初の


 If Me!未請求検索 = True Then
 

ですが、未請求検索はフォーム上はチェックボックスになっていますので、TrueかFalseで判定します。

こちらのチェックがされている場合、つまりTrueの場合は、filter_txtには


 filter_txt = "請求済 = false"
 

を入れるという処理です。

filter_txtのNullチェックを行っているのは先ほどと同じ理由で、すでに条件式が入っているか否かを判別するためです。

検索条件が設定されていなかった場合

最後に、検索条件がフォーム上で全く設定されていなかった場合の処理です。

ここまで、filter_txtにフォームでの入力値を元に条件式を代入してきました。
しかし、フォームで検索条件が設定されていなかった場合は、検索処理を行う必要がないですよね。

そこで、以下のコードを入れています。

   
 If filter_txt = "" Then

    Me.FilterOn = False

 Else
 

これは、fiilter_txtへの代入処理がすべて終わった後に、それでもfilter_txtが空白だったら、フィルターを行わない、という命令文です。
最後にElseで終わっていますが、Else側、つまりfilter_txtに値が入っていた場合は正常系としてフィルター処理を実行します。

検索実行

ここまでで、filiter_txtに検索条件式が代入された状態が作れましたので、ようやく検索処理の実行です。


    Me.Filter = filter_txt
    Me.FilterOn = True
    Me.OrderBy = "処理日 DESC"
    Me.OrderByOn = True
 

Me.Filterにfilter_txtを代入することでフォームのフィルター条件を設定します。
そして、Me.FilterOn をTrueにしてフォームのフィルターを実行します。

これでここまで設定してきた抽出条件に合致したレコードのみが表示されます。

また、Me.OrderByが設定されていますが、こちらは並び替えです。
この例では処理日で降順(新しい日付が上)に来るように並び替えしています。

以上、複数条件の検索フォーム作成方法をご紹介しました。


ACCESSを使いこなせば、業務の効率化や自動化が実現できます。
しかし、自分でACCESSを学ぶには時間がない、難しそうで不安、という方も多いでしょう。

そんな時は、ACCESS開発歴20年以上、過去に100以上のACCESSデータベースを開発してきた私(@hakoniwagadget)にお任せください。

ACCESSの新規開発、既存のACCESSの修正、ACCESSの操作レッスンなど様々なサービスをご提供しています。
ご興味のある方は下記のサービス一覧をご覧ください。

サービス一覧

最後までお読みいただき、ありがとうございました。