Microsoft Access 掲示板

フィルターの式が正しく書けない

14 コメント
views
4 フォロー

お世話になっております。
受注履歴のレコード一覧を、検索条件を非連結のテキストボックスに入力して絞り込むフォームを作成しておるのですが、Filterの式がうまく書けず苦戦しております。

txb_納期検索1には抽出したい期間の始まりを、txb_納期検索2には抽出したい期間の終わりを入力します。

①txb_納期検索1だけが入力されている場合は入力した期間以降のレコードを、②txb_納期検索2のみが入力されている場合は入力した期間以前のレコードを、③両方入力されている場合はその期間の範囲内のレコードを、④両方未入力の場合は他の検索ワードのみでの抽出(ここに関しては問題なく抽出できていたため、下記のコードではExit Sub)出来るようにしたいです。

Private Sub btn_検索_Click()

    Dim StartDueDate As String
    Dim EndDueDate As String
    
    StartDueDate = Trim(Nz([txb_納期検索1], ""))
    EndDueDate = Trim(Nz([txb_納期検索2], ""))
    
    Me.Refresh
    
    If StartDueDate <> "" And EndDueDate <> "" Then
    
        Me.Filter = "([納期] between StartDueDate and EndDueDate)"
        
    ElseIf StartDueDate <> "" And EndDueDate = "" Then
    
        Me.Filter = "([納期] >= StartDueDate)"
        
    ElseIf StartDueDate = "" And EndDueDate <> "" Then
    
        Me.Filter = "([納期] <= EndDueDate)"
        
    Else
    
        Exit Sub
        
    End If
        
    Me.FilterOn = True
    btn_解除.SetFocus
        
End Sub

エラーは出ないのですが、1件もレコードが抽出されなかったり、パラメータの入力を求められたりしてしまいます。

驚天動地!前任者失踪丸
作成: 2024/03/11 (月) 10:33:45
通報 ...
1

まずフィールド[納期]のデータ型を明記されることをお奨めします。

2
驚天動地!前任者失踪丸 2024/03/11 (月) 10:47:01 23e8e@44ebd >> 1

納期のデータ型は短いテキスト型です。

5
驚天動地!前任者失踪丸 2024/03/11 (月) 11:04:42 23e8e@44ebd >> 2

客先から受け取るCSVデータをインポートすると短いテキスト型になっており、値も"240311”の6桁です。

6
驚天動地!前任者失踪丸 2024/03/11 (月) 11:18:33 23e8e@44ebd >> 2

リアクションでは何を伝えたいのか分かりませんので文章にしていただきますようよろしくお願い致します。

9

反応がないようなので、管理者権限で削除しておきました。

10
驚天動地!前任者失踪丸 2024/03/11 (月) 15:42:53 23e8e@44ebd >> 2

Hatenaさん、お手数をおかけしてしまい申し訳ありません。
ありがとうございます。

3

では、とりあえず以下のように修正してみて下さい。

Private Sub btn_検索_Click()

    Dim StartDueDate As String
    Dim EndDueDate As String

    StartDueDate = Trim(Nz([txb_納期検索1], ""))
    StartDueDate = Replace(StartDueDate, "'", "''", 1, -1, vbBinaryCompare)
    
    EndDueDate = Trim(Nz([txb_納期検索2], ""))
    EndDueDate = Replace(EndDueDate, "'", "''", 1, -1, vbBinaryCompare)

    Me.Refresh

    If StartDueDate <> "" And EndDueDate <> "" Then
        Me.Filter = "([納期] between '" & StartDueDate & "' and '" & EndDueDate & "')"
    ElseIf StartDueDate <> "" And EndDueDate = "" Then
        Me.Filter = "([納期] >= '" & StartDueDate & "')"
        
    ElseIf StartDueDate = "" And EndDueDate <> "" Then
        Me.Filter = "([納期] <= '" & EndDueDate & "')"
    Else
        Exit Sub
    End If
        
    Me.FilterOn = True
    btn_解除.SetFocus
        
End Sub
7
驚天動地!前任者失踪丸 2024/03/11 (月) 11:21:41 23e8e@44ebd >> 3

skさん、回答ありがとうございます。
思う通りに動作するようになりました。

StartDueDate = Replace(StartDueDate, "'", "''", 1, -1, vbBinaryCompare)
EndDueDate = Replace(EndDueDate, "'", "''", 1, -1, vbBinaryCompare)

これはどのような操作なのでしょうか?

8

それぞれの非連結テキストボックスの値の中に含まれている
シングルクォーテーション( ' )を Replace 関数によって
'' に置換し、更に囲み記号としての ' で囲って 1 つの
文字列リテラルとして解釈されるようにしています。

前述の例ではフィルター条件式における文字列リテラルの囲み記号として
シングルクォーテーションを用いていますが、その場合において
「文字列としてのシングルクォーテーション」を文字列リテラルに含めるには
'' のように 2 つ続けて記述しなければなりません。

Dim strFilter As String

strFilter = "[テキスト型のフィールド名] = 'I''m your father.'"

Me.Filter = strFilter
Me.FilterOn = True

それぞれの非連結テキストボックスにシングルクォーテーションを含む文字列が
入力された場合、上記のようにエスケープ処理をしておかないと
「文字列としての ' 」ではなく「文字列リテラルの囲み記号の ' 」として
解釈されてしまい、構文エラーが発生する可能性が高くなります。

11
驚天動地!前任者失踪丸 2024/03/11 (月) 15:44:15 23e8e@44ebd >> 3

なるほど、想定していない(この場合だと6桁以外の数字)入力内容だった場合にエラーを回避するための処理ということですね。勉強になります。

12

客先から受け取るCSVデータをインポートすると短いテキスト型になっており、値も"240311”の6桁です。

ということなら、下記のような感じで入力チェックするといいかと思います。
そうしないと、正しくない値が入力されたときに、抽出結果も正しいものになりません。

    StartDueDate = Trim(Nz([txb_納期検索1], ""))
    If StartDueDate Like "######" Then
        If Not IsDate(Format("20" & StartDueDate, "0000/00/00")) Then
            MsgBox "日付としてありえない値です。yymmddの書式で日付を入力してください。"
            txb_納期検索1.SetFocus
            Exit Sub
        End If
    Else
        MsgBox "数字6桁で入力してください。"
        txb_納期検索1.SetFocus
        Exit Sub
    End If

   'EndDueDate も同様にチェック

あるいは、テキストボックスの定型入力プロパティに
000000;;_
と設定しておくと数字6桁の入力が強制されますので、日付チェックのみで済みます。

    StartDueDate = Trim(Nz([txb_納期検索1], ""))
    If Not IsDate(Format("20" & StartDueDate, "0000/00/00")) Then
        MsgBox "日付としてありえない値です。yymmddの書式で日付を入力してください。"
        txb_納期検索1.SetFocus
        Exit Sub
    End If
13
驚天動地!前任者失踪丸 2024/03/12 (火) 08:33:07 23e8e@44ebd >> 12

回答ありがとうございます!
意図しない入力を防ぐ仕組みも必要ということですね。

14

ちなみに、自分がするなら、

テキストボックスの定型入力プロパティに
000000;;_
と設定しておいて下記のコードにします。

Private Sub btn_検索_Click()
    Dim StartDueDate As String
    Dim EndDueDate As String
    StartDueDate = Trim(Nz(Me.txb_納期検索1.Value, ""))
    EndDueDate = Trim(Nz(Me.txb_納期検索2.Value, ""))
    
    If StartDueDate & EndDueDate = "" Then
        MsgBox "納期期限の開始日または終了日を入力してください。"
        Me.txb_納期検索1.SetFocus
        Exit Sub
    End If
    
    If Not IsDate(Format("20" & StartDueDate, "0000/00/00")) Then
        MsgBox "日付としてありえない値です。yymmddの書式で日付を入力してください。"
        Me.txb_納期検索1.SetFocus
        Exit Sub
    End If
    If Not IsDate(Format("20" & EndDueDate, "0000/00/00")) Then
        MsgBox "日付としてありえない値です。yymmddの書式で日付を入力してください。"
        Me.txb_納期検索1.SetFocus
        Exit Sub
    End If
    
    Me.Refresh
    
    Dim strFilter As String
    If StartDueDate <> "" Then
        strFilter = " And [納期] >='" & StartDueDate & "'"
    End If
    
    If EndDueDate <> "" Then
        strFilter = strFilter & " And [納期] <='" & EndDueDate & "'"
    End If
            
    Me.Filter = Mid(strFilter, 6)
    Me.FilterOn = (strFilter <> "")
    
    Me.btn_解除.SetFocus
End Sub