By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,661 Members | 1,319 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,661 IT Pros & Developers. It's quick & easy.

Search Form: multiple controls (Access 2003)

P: 9
Hi all,

I'm not very conversant with the vocabulary of Access, so please ask for clarification if necessary...

I am trying to build a search form that allows combinations of search terms. For example, let's say I have three controls on my form; year, keyword, location. Entering a valid value for all three gives expected results from the dataset. However, I'd like to interpret a blank field in the search form as ignoring that constraint. The user should be able to enter values into any combination of form fields, e.g., entering only a year returns all records associated with that year, irrespective of any values in the other two fields. Entering a value in one of the other two fields refines the search result.

I've seen forms like this one:
http://www.mvps.org/access/forms/frm0045.htm

This looks like a great utility, but I can't get it to work in my db... launching the form populates the list of objects control, but clicking any button or object name yields a 'Variable not defined' error. I don't know enough about VB/A to troubleshoot this.

Other solutions I've seen around look very close, but require more understanding of the scripts than I have currently. Here is the query I'm starting with:
Expand|Select|Wrap|Line Numbers
  1. SELECT tblCards01.serialNumber, tblCards01.barcode, tblCards01.cardTitle, tblCards01.cardKeywords, tblCards01.cardYear, tblCards01.locCity, tblCards01.locState, tblCards01.cardStory, tblCards01.luOrientation, tblCards01.luDimensions
  2. FROM tblCards01
  3. WHERE (((tblCards01.cardKeywords) Like "*" & Forms!frmQryKeyword!qryKeyword & "*") And ((tblCards01.luOrientation)=(Forms!frmQryKeyword!qryOrientation)) And ((tblCards01.cardYear)=(Forms!frmQryKeyword!qryYear)));
  4.  
Clearly this is a simple Logical AND setup, so I understand it requires a value to search on for each criterion. Not entering a value is interpreted literally - the query is looking for null values in the field.

So, I'm wondering 1) if there's something relatively simple I'm missing in setting up the query to interpret no value as meaning 'ignore this parameter', 2) is my approach all wrong, 3) does anyone know of a way to get the linked form to work, or of a competing utility that will provide similar functionality.

I do some scripting in other languages, but have precious little experience w/ VB. I'm willing to do some homework here, but I've got lots of other irons in the fire, and don't want to take a couple of courses to solve this issue. Having said that, I do appreciate any insights even if they include 'take a class' :)

Thanks!

-Scott
Feb 18 '07 #1
Share this Question
Share on Google+
9 Replies


P: 16
Dear Scott,

i used this code to create a search form on an application of mine, and it works great..... it will find the results to any number of criteria. All you need to do is customize the code to fit your application.


PLease fins below the article for the search from (i have copied the whole article for you so you can better understand the code before using it):
Expand|Select|Wrap|Line Numbers
  1. Experts, please don't answer this Q, this is being posted as a general tutorial question, but please feel free to add your comments and suggest any additions!
  2.  
  3. Q. We want to create a form for users to look up records in our table. Our table is called Customers and looks like this:
  4. CusID (Autonumber field)
  5. LastName (Text field)
  6. FirstName (Text field)
  7. Age (Number)
  8. Address (Text Field)
  9. Status (Text field, and it will only ever contain "Active", "Inactive" or "Prospect")
  10.  
  11. A. We have a form called SearchForm. It has 5 controls:
  12. * Two combo boxes called cboFindFirstName and cboFindLastName. These show all the unique first names from the customers table, and their RowSource properties are set to SQL like this: SELECT DISTINCT FirstName FROM Customers. We want the search form to find all records matching what We choose from these combo boxes.
  13.  
  14. * A text box called txtFindAge. We want to find everyone older than the number we put in here.
  15.  
  16. * An text box called txtFindAddress. We want to find addresses that contain any text we put in here. So if we put in "19 East", we want it to find "19 East Road" and "19 East Avenue"
  17.  
  18. * A multiselect list box called lstFindStatus which shows "Active", "Inactive" or "Prospect". We want to find records matching all the statuses we pick from this box. So if we choose both Active and Inactive, we want to find both active and inactive customers.
  19. If we leave any of these controls blank or we don't choose anything, we don't want it to search on that field.
  20.  
  21. One way of doing this is described here.
  22.  
  23. In order to achieve the above, we have to create a filtering string. We have a command button on the form, "Find records", called cmdFindRecords.
  24.  
  25. We need to put code in the OnClick event of this button. To do this, click on the command button in design view, and then click View->Properties on the menus. This brings up the Properties window. Click on the Event page, and click in the "On Click" row. A build button with "..." on it appears. Click on that button, and choose Code Builder.
  26.  
  27. A window with:
  28. Private Sub cmdFindRecords_Click()
  29.  
  30. End Sub
  31. appears. All our code goes in between those two lines.
  32.  
  33. First of all, we create a string variable to hold our filtering string, and set it to an empty string. We also need a variable to represent the items we've selected from the list box:
  34. ---
  35. Dim strFilter As String
  36. Dim varItem As Variant
  37.  
  38. strFilter=""
  39. ---
  40.  
  41. Now we check to see if the combo boxes are empty. If they aren't, we add them to the filter string:
  42. ---
  43. If Not IsNull(Me!cboFindFirstName) Then strFilter = strFilter & "[FirstName]=" Chr(34) & Me!cboFindFirstName & Chr(34) & " AND "
  44. If Not IsNull(Me!cboFindLastName) Then strFilter = strFilter & "[LastName]=" Chr(34) & Me!cboFindLastName & Chr(34) & " AND "
  45. ---
  46. Using Me!cboFindFirstName and Me!cboFindLastName gives us the values we've chosen in those combo boxes. We first check to see if they are empty by using the IsNull function (which gives us back True if they are). Because FirstName and LastName are text fields, we put quote characters around them in the string (this is what Chr(34) is). We could use apostrophes (') but we might have names like O'Sullivan, which would cause the filter string to be wrong so we use quotes instead.
  47.  
  48. Now we check if anything has been entered into the txtAge text box.
  49. ---
  50. If Not IsNull(Me!txtFindAge) Then strFilter = strFilter & "[Age]>" & Me!txtFindAge & " AND "
  51. ---
  52. Because Age is a number field, we don't need to put apostrophes or quote marks around the value.
  53.  
  54. The next thing to check is the address. We want to match lines containing what we've typed not exact matches, so we have to use the Like operator which lets us use wildcards:
  55. ---
  56. If Not IsNull(Me!txtFindAddress) Then strFilter = strFilter & "[Address] Like " Chr(34) & "*" & Me!txtFindAddress & "*" & Chr(34) & " AND "
  57. ---
  58.  
  59. The final thing to check is the multiselect list box. This is trickier because the user might have chosen more than one item. So we have to loop through the list box's items to see which ones have been selected:
  60. ---
  61. if Me!lstFindStatus.ItemsSelected.Count>0 Then
  62.    strFilter = strFilter & "("
  63.    For Each varItem In Me!lstFindStatus.ItemsSelected
  64.       strFilter = strFilter & "[Status]=" & Chr(34) & Me!txtFindStatus.ItemData(varItem) & Chr(34) & " OR "
  65.    Next
  66.    strFilter = Left$(strFilter, Len(strFilter)-4) & ") AND "
  67. End If
  68. ---
  69.  
  70. We begin the above code checking to see if anything has been selected, We then loop through each selected item and add it to the filtering string. We use OR here rather than AND because we want to find records that have a status of say, Active OR have a status of Inactive. After the loop finishes, we have a stray OR at the end, so we take that off and put a close bracket on the end.
  71.  
  72. Finally, we have to check to see if our filter string has anything in it at all (because someone might have clicked on Find Records but not typed anything in or chosen anything from the combos and listbox. If they've chosen or typed anything, our filter string will have a stray AND, so we have to take that off.
  73. ---
  74. If strFilter<>"" Then strFilter = Left$(strFilter,Len(strFilter)-5)
  75. ---
  76. So if the user has chosen "Smith" in the last name combo, "Joe" in the first name combo, typed "20" in the age box, "Main" in the address box and chosen "Active" and "Inactive" from the list box, our filter string looks like this:
  77. [FirstName]="Joe" AND [LastName]="Smith" AND [Age]>20 AND [Address] Like "*Main*" AND ([Status]="Active" OR [Status]="Inactive")
  78.  
  79. Now that we have our filtering string, what do we do with it ?
  80.  
  81. We can use it to open another form which shows all of the records from the Customers table. For example:
  82. ---
  83. DoCmd.OpenForm "frmCustomerDetails", , ,strFilter
  84. ---
  85. This opens frmCustomerDetails (which is based on the Customers table and would normally shows all customers) and applies the filter to only show records matching our criteria.
  86.  
  87. Or instead, we might have a subform inside our search form which shows all the customer details in a tabular format (a continuous or datasheet subform). This subform might be called frmSubCustomerDetails, and is held inside a subform control called subCustomers. We can use our filter string to set a  filter for the subform:
  88. ---
  89. If strFilter="" Then
  90.    Me!subCustomers.Form.FilterOn = False
  91. Else
  92.    Me!subCustomers.Form.Filter = strFilter
  93.    Me!subCustomers.Form.FilterOn = True
  94. End If
  95. ---
  96. This checks to see if our filter is empty. If it is, we just switch any existing filter on our subform off. Otherwise, we set the subform's filter to our string, and then switch the filter on.
  97.  
  98. Our completed code looks like this:
  99. ===================================
  100.  
  101. Private Sub cmdFindRecords_Click()
  102. Dim strFilter As String
  103. Dim varItem As Variant
  104.  
  105. strFilter=""
  106.  
  107. If Not IsNull(Me!cboFindFirstName) Then strFilter = strFilter & "[FirstName]=" Chr(34) & Me!cboFindFirstName & Chr(34) & " AND "
  108. If Not IsNull(Me!cboFindLastName) Then strFilter = strFilter & "[LastName]=" Chr(34) & Me!cboFindLastName & Chr(34) & " AND "
  109. If Not IsNull(Me!txtFindAge) Then strFilter = strFilter & "[Age]>" & Me!txtFindAge & " AND "
  110. If Not IsNull(Me!txtFindAddress) Then strFilter = strFilter & "[Address] Like " Chr(34) & "*" & Me!txtFindAddress & "*" & Chr(34) & " AND "
  111. if Me!lstFindStatus.ItemsSelected.Count>0 Then
  112.    strFilter = strFilter & "("
  113.    For Each varItem In Me!lstFindStatus.ItemsSelected
  114.       strFilter = strFilter & "[Status]=" & Chr(34) & Me!txtFindStatus.ItemData(varItem) & Chr(34) & " OR "
  115.    Next
  116.    strFilter = Left$(strFilter, Len(strFilter)-4) & ") AND "
  117. End If
  118.  
  119. If strFilter<>"" Then strFilter = Left$(strFilter,Len(strFilter)-5)
  120. DoCmd.OpenForm "frmCustomerDetails", , ,strFilter
  121. End Sub


Hope this helped,
Christina
Feb 18 '07 #2

MMcCarthy
Expert Mod 10K+
P: 14,534
Hi Scott

Check out this tutorial on Example Filtering on a Form

Mary
Feb 18 '07 #3

P: 9
Wow!

Thanks to both of you for great replies. I'm going to spend some time digesting these so I can find the right solution for me.

Christina - I've taken the liberty of beginning to convert that article to a PDF for easy reference. If you'd like it, let me know and I'll post it somewhere for you. It's only got basic formatting for the moment, but I can do some doctoring if you like.

Mary - I presume that thread you noted combines a query result with filtering? I'm not sure how to approach that method since I'm looking for a way to avoid a hierarchy in my query. Essentially, I need to leave out any search criteria that are not explicitly called for. Am I misunderstanding the nature of that thread?
Feb 18 '07 #4

MMcCarthy
Expert Mod 10K+
P: 14,534
Mary - I presume that thread you noted combines a query result with filtering? I'm not sure how to approach that method since I'm looking for a way to avoid a hierarchy in my query. Essentially, I need to leave out any search criteria that are not explicitly called for. Am I misunderstanding the nature of that thread?
This kind of filtering usually work on the recordsource of the opening form.

Presumably you want your results in a form or datasheet. All you do is set up the form or datasheet to return all records without criteria. Then use the tutorial to set filtering criteria and open your form based on this criteria.

Expand|Select|Wrap|Line Numbers
  1. DoCmd.OpenForm "FormName", , , "Criteria"
Mary
Feb 18 '07 #5

P: 9
Presumably you want your results in a form or datasheet. All you do is set up the form or datasheet to return all records without criteria. Then use the tutorial to set filtering criteria and open your form based on this criteria.
Gotcha.

Ok, I'm working through this approach, and have started with just a single search for a keyword. I have done this with a simple query, but am having trouble with this part of the script:

Expand|Select|Wrap|Line Numbers
  1. If Not IsNull(Me!txtFindTitle) Then strFilter = strFilter & "[cardTitle]=" Chr(34) & Me!txtFindTitle & Chr(34) & " AND "
  2.  
The error I get says "Compile Error. Expected: end of statement" and the Chr(34) is highlighted. Does this have something to do with the VB version, or did I just type something incorrectly?
Feb 18 '07 #6

MMcCarthy
Expert Mod 10K+
P: 14,534
Gotcha.

Ok, I'm working through this approach, and have started with just a single search for a keyword. I have done this with a simple query, but am having trouble with this part of the script:

Expand|Select|Wrap|Line Numbers
  1. If Not IsNull(Me!txtFindTitle) Then strFilter = strFilter & "[cardTitle]=" Chr(34) & Me!txtFindTitle & Chr(34) & " AND "
  2.  
The error I get says "Compile Error. Expected: end of statement" and the Chr(34) is highlighted. Does this have something to do with the VB version, or did I just type something incorrectly?
You didn't use the & before the first Chr(34). Just use the single quotes, it's easier:

Expand|Select|Wrap|Line Numbers
  1. If Not IsNull(Me!txtFindTitle) Then 
  2.   strFilter = strFilter & "[cardTitle]='" & Me!txtFindTitle & "' AND "
  3.  
Also don't forget to remove the last "AND" in the build.

Mary
Feb 18 '07 #7

P: 9
You didn't use the & before the first Chr(34).
Thanks again, Mary. I added &, but also declared a variable for Chr$(34) which seems to make everything happy.

For reference, here's what I ended up with:

Expand|Select|Wrap|Line Numbers
  1. Private Sub cmdFindRecords_Click()
  2.  
  3. Dim strFilter As String
  4. Dim strQt As String
  5.  
  6. strFilter = ""
  7. strQt = Chr$(34)
  8.  
  9. If Not IsNull(Me!txtFindTitle) Then strFilter = strFilter & "[cardTitle]=" & strQt & "*" & Me!txtFindTitle & "*" & strQt & " AND "
  10. If Not IsNull(Me!txtFindKeyword) Then strFilter = strFilter & "[cardKeywords]Like" & strQt & "*" & Me!txtFindKeyword & "*" & strQt & " AND "
  11. If Not IsNull(Me!cboOrientation) Then strFilter = strFilter & "[luOrientation]=" & strQt & Me!cboOrientation & strQt & " AND "
  12. If Not IsNull(Me!cboFindYear) Then strFilter = strFilter & "[cardYear]=" & Me!cboFindYear
  13.  
  14. 'End If
  15.  
  16. If strFilter <> "" Then strFilter = Left$(strFilter, Len(strFilter) - 5)
  17. DoCmd.OpenForm "frmSearchResults", , , strFilter
  18.  
  19. End Sub
  20.  
This search allows for keywords (from a memo field), title search, and selection based on distinct entries (image orientation and year of publication). The purpose of this db is to cull images for printing from a template, so I needed a variety of selection options, but also to restrict possible combinations that are incompatible (two orientations, for example, because each orientation uses a different template). Possible enhancements to this are allowing multiple years, and adding more keywords - right now, you can only enter a single search term in each of the title and keyword boxes.

Thanks very much for all the help!

My next step is to export the results to a tab-delimited text file, which I'll ask about in a new thread.

-A very appreciative n00b (Scott)
Feb 18 '07 #8

MMcCarthy
Expert Mod 10K+
P: 14,534
Thanks for posting the final solution.

When you get into dealing with multiple values you can use multi select listboxes and access them for the build in a for...loop as per this example.

Mary
Feb 18 '07 #9

NeoPa
Expert Mod 15k+
P: 31,271
A hijack post has been split across to Search Form. Interested parties can follow the progress there.
Aug 6 '10 #10

Post your reply

Sign in to post your reply or Sign up for a free account.