Filtering report by date range and multiple list boxes (1 Viewer)

jlb4350

Registered User.
Local time
Yesterday, 19:25
Joined
Nov 19, 2013
Messages
22
This one has me stumped. I have a form that contains two text fields to enter a date range, and three multiple-select list boxes. When a "generate report" button is clicked, I would like the code to display a report that is filtered by the date range entered, and all the data selected from the three list boxes.

I have the report completed and it works perfectly when the date ranges are entered, however, when I select something from one of the list boxes, I get an error (see attached - the dates in the attachment are because I entered those dates in the range).

Here is my code and I'm sure I have something wrong in the section that has the comment: There is something wrong between these two lines:

Code:
Private Sub cmdPreview_Click()
'On Error GoTo Err_Handler      'Remove the single quote from start of this line once you have it working.
    'Purpose:       Filter a report to a date range.
    'Note:          Filter uses "less than the next day" in case the field has a time component.
    
    Dim strReport As String
    Dim strDateField As String
    Dim strWhere As String
    Dim lngView As Long
    Dim ctl As Control
    Dim VarItem As Variant
    Const strcJetDate = "\#mm\/dd\/yyyy\#"  'Do NOT change this format.
    
    strReport = "rptRecentChanges"
    strDateField = "[EffectiveDate]"
    lngView = acViewReport     'Use acViewNormal to print instead of preview.
    
    'Build the filter string.
    If IsDate(Me.txtStartDate) Then
        strWhere = "(" & strDateField & " >= " & Format(Me.txtStartDate, strcJetDate) & ")"
    End If
    If IsDate(Me.txtEndDate) Then
        If strWhere <> vbNullString Then
            strWhere = strWhere & " AND "
        End If
        strWhere = strWhere & "(" & strDateField & " < " & Format(Me.txtEndDate + 1, strcJetDate) & ")"
    End If
    
    'Close the report if already open: otherwise it won't filter properly.
    If CurrentProject.AllReports(strReport).IsLoaded Then
        DoCmd.Close acReport, strReport
    End If
 
'THERE IS SOMETHING WRONG BETWEEN THESE TWO LINES
  Set ctl = Me.lstDrugProduct
  For Each VarItem In ctl.ItemsSelected
    strWhere = strWhere & ctl.ItemData(VarItem) & ","
  Next VarItem
  
  Set ctl = Me.lstDescription
  For Each VarItem In ctl.ItemsSelected
    strWhere = strWhere & ctl.ItemData(VarItem) & ","
  Next VarItem
  
  Set ctl = Me.lstRecordType
  For Each VarItem In ctl.ItemsSelected
    strWhere = strWhere & ctl.ItemData(VarItem) & ","
  Next VarItem
'THERE IS SOMETHING WRONG BETWEEN THESE TWO LINES

    'Open the report.
    'Debug.Print strWhere        'Remove the single quote from the start of this line for debugging purposes.
    DoCmd.OpenReport strReport, lngView, , strWhere

Exit_Handler:
    Exit Sub

Err_Handler:
    If Err.Number <> 2501 Then
        MsgBox "Error " & Err.Number & ": " & Err.Description, vbExclamation, "Cannot open report"
    End If
    Resume Exit_Handler
End Sub

If I remove the section between the indicated comments, then the code and report runs fine, but only uses the date filters.

Also, I'm afraid I cannot update the database due to sensitive information; however, if needed, I can create a sample. I'm hoping someone will see the problem in the code and have a solution though.

Thank you for your time. Any help is greatly appreciated!
 

Attachments

  • error1.JPG
    error1.JPG
    20.3 KB · Views: 96

theDBguy

I’m here to help
Staff member
Local time
Yesterday, 19:25
Joined
Oct 29, 2018
Messages
21,479
Hi. I think your criteria is mal constructed. When you first assign the date criteria to strWhere, it is correct. But in all succeeding assignments to the same variable, you are missing the AND operator. If you want to get rid of the commas, you'll have to use the OR operator. If you want to keep the commas, you can use the In() clause.
Code:
(DateField >= StarDate AND DateField <= EndDate) AND (FieldName = FirstValue OR FieldName = SecondValue...
or
Code:
(DateField...) AND (FieldName In(First,Second,etc)) AND (OtherField In(...))
Hope it makes sense...
 

Gasman

Enthusiastic Amateur
Local time
Today, 03:25
Joined
Sep 21, 2011
Messages
14,329
I would have thought you would need to build a string along the lines of

AND YourField IN (list items here, separated by commas) for each of the list items? and add those to your initial strWhere with the dates?

If you debug.print your strWhere what do you get ?

HTH
 

jlb4350

Registered User.
Local time
Yesterday, 19:25
Joined
Nov 19, 2013
Messages
22
I would have thought you would need to build a string along the lines of

AND YourField IN (list items here, separated by commas) for each of the list items? and add those to your initial strWhere with the dates?

If you debug.print your strWhere what do you get ?

HTH

Thanks Gasman. Let's assume I choose a date range or 2/1/17 - 4/5/19, and then select "Blank Film" in one listbox, and "Specifications" in the other list box. The debug shows this:

Code:
([EffectiveDate] >= #02/01/2017#) AND ([EffectiveDate] < #04/05/2019#)Blank Film,Specifications,
 

jlb4350

Registered User.
Local time
Yesterday, 19:25
Joined
Nov 19, 2013
Messages
22
Hi. I think your criteria is mal constructed. When you first assign the date criteria to strWhere, it is correct. But in all succeeding assignments to the same variable, you are missing the AND operator. If you want to get rid of the commas, you'll have to use the OR operator. If you want to keep the commas, you can use the In() clause.
Code:
(DateField >= StarDate AND DateField <= EndDate) AND (FieldName = FirstValue OR FieldName = SecondValue...
or
Code:
(DateField...) AND (FieldName In(First,Second,etc)) AND (OtherField In(...))
Hope it makes sense...

The strange thing is that the date filtering works fine. This report was originally a date filter only report, but I needed to add more data to further filter. The code between the commented lines is what I added. If I were to comment those lines out, the report would run fine. I think I'm just not sure how to add in that additional code into the original code to make the list boxes work.

I think a more likely cause is that I don't know what I'm doing lol. I find most of my code online and play with it until it works, but I couldn't make this one work.

I can post a sample if needed.
 

theDBguy

I’m here to help
Staff member
Local time
Yesterday, 19:25
Joined
Oct 29, 2018
Messages
21,479
Hi. As I said above, the date criteria works because you have properly used the AND logical operator with it. However, in the other criteria you're trying to add, you haven't specified whether to use AND or OR (depending on your requirements).
 

June7

AWF VIP
Local time
Yesterday, 18:25
Joined
Mar 9, 2014
Messages
5,479
If you want to allow multi-select listbox, whether selecting 1 or multiple items, use IN() so the result is like:
Code:
([EffectiveDate] >= #02/01/2017#) AND ([EffectiveDate] < #04/05/2019#) AND [DrugProduct] IN('a','b','c') AND [Description] IN('d','e','f') AND [RecordType] IN('g','h','i')
The apostrophe delimiters are needed for text fields. If you use numeric key fields for the criteria, don't use apostrophes.

Review http://allenbrowne.com/ser-50.html
 
Last edited:

Gasman

Enthusiastic Amateur
Local time
Today, 03:25
Joined
Sep 21, 2011
Messages
14,329
As June7 has shown.

Build the string up in parts. Debug.print it before trying to use.
 

Gasman

Enthusiastic Amateur
Local time
Today, 03:25
Joined
Sep 21, 2011
Messages
14,329
Thanks Gasman. Let's assume I choose a date range or 2/1/17 - 4/5/19, and then select "Blank Film" in one listbox, and "Specifications" in the other list box. The debug shows this:

Code:
([EffectiveDate] >= #02/01/2017#) AND ([EffectiveDate] < #04/05/2019#)Blank Film,Specifications,

Exactly, which is nowhere near correct syntax. June7 has shown you the correct syntax.
 

jlb4350

Registered User.
Local time
Yesterday, 19:25
Joined
Nov 19, 2013
Messages
22
Thank you all. I understand now why I need to IN clause and what the results should look like. What I don't yet understand though is where I put this into my code. Could you add an example to my original code above? I should be able to work it out from there.

Sorry, I'm still a novice :(
 

June7

AWF VIP
Local time
Yesterday, 18:25
Joined
Mar 9, 2014
Messages
5,479
Already provided example.

Expand on the code you already have. Fix the code for each listbox to use Allen Browne code to conditionally build each IN() criteria and concatenate.
 

jlb4350

Registered User.
Local time
Yesterday, 19:25
Joined
Nov 19, 2013
Messages
22
Expand on the code you already have. Fix the code for each listbox to use Allen Browne code to conditionally build each IN() criteria and concatenate.

Ok, i'll give it a shot and post the code when it's done. Let's see what happens...
 

jlb4350

Registered User.
Local time
Yesterday, 19:25
Joined
Nov 19, 2013
Messages
22
I changed the code to this, but obviously not correct because I get a type mismatch when i run it.

Code:
 Set ctl = Me.lstDrugProduct
  For Each VarItem In ctl.ItemsSelected
    strWhere = "[DrugProduct] IN (" & Left$(strWhere, lngLen) & ")"
  Next VarItem
  
  Set ctl = Me.lstDescription
  For Each VarItem In ctl.ItemsSelected
    strWhere = "[Description] IN (" & Left$(strWhere, lngLen) & ")"
  Next VarItem
  
  Set ctl = Me.lstRecordType
  For Each VarItem In ctl.ItemsSelected
    strWhere = "[RecordType] IN (" & Left$(strWhere, lngLen) & ")"
  Next VarItem
 

June7

AWF VIP
Local time
Yesterday, 18:25
Joined
Mar 9, 2014
Messages
5,479
Well, you are not using the complete code provided by Allen Browne.

And you are not including the " AND " operator.

Have you reviewed both tutorial articles in detail? The information is all there.
 

Gasman

Enthusiastic Amateur
Local time
Today, 03:25
Joined
Sep 21, 2011
Messages
14,329
Debug.Print the strWhere and you will see where you are going wrong.

I changed the code to this, but obviously not correct because I get a type mismatch when i run it.

Code:
 Set ctl = Me.lstDrugProduct
  For Each VarItem In ctl.ItemsSelected
    strWhere = "[DrugProduct] IN (" & Left$(strWhere, lngLen) & ")"
  Next VarItem
  
  Set ctl = Me.lstDescription
  For Each VarItem In ctl.ItemsSelected
    strWhere = "[Description] IN (" & Left$(strWhere, lngLen) & ")"
  Next VarItem
  
  Set ctl = Me.lstRecordType
  For Each VarItem In ctl.ItemsSelected
    strWhere = "[RecordType] IN (" & Left$(strWhere, lngLen) & ")"
  Next VarItem
 

jlb4350

Registered User.
Local time
Yesterday, 19:25
Joined
Nov 19, 2013
Messages
22
Guys, I really appreciate the guidance, but I just can't figure it out. The code from AllenBrowne looks good, and I could make that work if it were on its own, but I just don't understand how to integrate that into my current code that already has the date filter. I'm still learning and I know what the AND operator does, but I don't know where to add it to make the two sets of code work together.

I'm attaching a sample that I reworked using the original database. If anyone has time and can check the code on frmLatestChanges and provide an example of how I can include the list boxes, I would be most thankful. That will also help me learn.

Thanks again and I apologize for my ignorance. I simply don't yet understand it enough.
 

Attachments

  • Multiple-Select List Box Filters with Date Filters.zip
    829.9 KB · Views: 122

Gasman

Enthusiastic Amateur
Local time
Today, 03:25
Joined
Sep 21, 2011
Messages
14,329
TBH I think you will learn more if you do some of the work yourself.

I have added code as shown below and it appears to work.
I have been a little untidy by not removing the last , for the IN statement, but it still works fine, so left it as is.

You need to repeat the functionality I coded for lstDrugProduct for the other listboxes. You also need to DIM strIN
HTH

Code:
    If IsDate(Me.txtEndDate) Then
        If strWhere <> vbNullString Then
            strWhere = strWhere & " AND "
        End If
        strWhere = strWhere & "(" & strDateField & " < " & Format(Me.txtEndDate + 1, strcJetDate) & ")"
    End If
    
    ' Now check the listboxes
    strIN = ""
    Set ctl = Me.lstDrugProduct
    For Each varItem In ctl.ItemsSelected
        strIN = strIN & "'" & ctl.ItemData(varItem) & "'" & ","
    Next varItem
    Debug.Print strIN
    'Now check if we used strIN
    If Len(strIN) > 0 Then ' yes we used it
        strWhere = strWhere & " AND DrugProduct IN (" & strIN & ")"
    End If
    Debug.Print strWhere
 

jlb4350

Registered User.
Local time
Yesterday, 19:25
Joined
Nov 19, 2013
Messages
22
TBH I think you will learn more if you do some of the work yourself.

I have added code as shown below and it appears to work.
I have been a little untidy by not removing the last , for the IN statement, but it still works fine, so left it as is.

You need to repeat the functionality I coded for lstDrugProduct for the other listboxes. You also need to DIM strIN
HTH

Code:
    If IsDate(Me.txtEndDate) Then
        If strWhere <> vbNullString Then
            strWhere = strWhere & " AND "
        End If
        strWhere = strWhere & "(" & strDateField & " < " & Format(Me.txtEndDate + 1, strcJetDate) & ")"
    End If
    
    ' Now check the listboxes
    strIN = ""
    Set ctl = Me.lstDrugProduct
    For Each varItem In ctl.ItemsSelected
        strIN = strIN & "'" & ctl.ItemData(varItem) & "'" & ","
    Next varItem
    Debug.Print strIN
    'Now check if we used strIN
    If Len(strIN) > 0 Then ' yes we used it
        strWhere = strWhere & " AND DrugProduct IN (" & strIN & ")"
    End If
    Debug.Print strWhere

Thank you for this. Just to be clear though, I hope you don't think I'm being lazy. I tried for hours trying to get this to work with examples from all over the web even before I created this post. I didn't ask for it to be done for me, just an example, so that I can understand how the operators fit.

Anyway, I'll give this a go. I do appreciate your help though. I'll let you know how it turns out.
 

Gasman

Enthusiastic Amateur
Local time
Today, 03:25
Joined
Sep 21, 2011
Messages
14,329
If you pretty much copy the code I created and amend for the different names (listbox, field etc) then it should just work. The correct logic is there I believe.

I have done as you asked/were looking for. You have an example that works.

I'm not an expert here, it takes me a while to even create a short piece of code like that. Often I have to Google for the correct syntax, which is why I went back to your method for identifying selected items.
 

Users who are viewing this thread

Top Bottom