Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Create a flexible Search Tool in MS Access 2

Status
Not open for further replies.

RottPaws

Programmer
Mar 1, 2002
478
US
PURPOSE: Outline a method I have used to create a flexible search tool in MS Access. This is just one way to create a flexible search tool. It is not the only way, and may not even be the best, but it is effective.

OVERVIEW: This method uses 3 forms; one to gather search criteria, one to retrieve and display results in a summarized form, and another that displays all the detailed information of a record selected from the list.

Criteria is entered into the search form and then a command button is clicked. The On_Click procedure builds the WHERE clause for the retreive form based on the criteria entered and then opens the retrieve form and sets the recordsource to the selected records.

HOW IT WORKS:
My application tracks work orders for a number of locations. Each work order includes an order ID, an order manager who is repsonsible for the order, a customer name, a location, an order entry date, and an order completion date.

The search form allows a user to search for orders by any combination of these fields. When the search command button is clicked, the search form opens the retrieve form and sets the recordsource for that form by modifying the WHERE clause of the query that populates that form.

If no criteria is entered, a list of all orders is retrieved.

Tables involved:
Orders
OrderID Long (PK)
OrdMgrID Long (FK) Employees.EmpID
Cust Text
LocID Long (FK) Locations.LocID
OrdEntry Date
OrdComp Date
Cost Double
Other1 Text
Other2 Text
Other3 Text
Other4 Text
Other5 Text

Locations
LocID Long (PK)
LocName Text
SiteMgr Text

Employees
EmpID Long (PK)
Name Text


The Search form:
frmSearch is a form that has a number of controls (with appropriate labels) to collect criteria from user input:
Control Name Label
Text box txtOrderID Order Number
Combo box cboOrderMgr Order Manager
Text box txtCust Customer Name
Check box chkCustExact Exact Customer Name
Text box txtLocation Location
Frame fraLocSearchType Location Search Type
Text box txtOrdEntryFrom Order Entered From:
Text box txtOrdEntryTo Order Entered To:
Checkbox chkOpenOnly Open Orders Only
Checkbox chkClosedOnly Closed Orders Only
Command Button cmdSearch Retrieve Orders
Command Button cmdCancel Cancel
Command Button cmdClear Clear

Option buttons in the frame:
Name Option Value Caption
optExact 1 Exact
optBegins 2 Begins With
optContains 3 Contains
optEnds 4 Ends With

cboLocation gets a list of valid locations from the Locations table and is bound to the LocID field.

CODE FOR frmSearch

Private Sub chkClosedOnly_Click()
‘*****************************************************************
‘Purpose: An order cannot be both open and closed, so these
‘ check boxes are mutually exclusive.
‘*****************************************************************

‘If the closed only check box is checked, uncheck open only
If chkClosedOnly = True Then
ChkOpenOnly = False
End If

End Sub

Private Sub chkOpenOnly_Click()
‘*****************************************************************
‘Purpose: An order cannot be both open and closed, so these
‘ check boxes are mutually exclusive.
‘*****************************************************************

‘If the closed only check box is checked, uncheck closed only
If chkOpenOnly = True Then
ChkClosedOnly = False
End If

End Sub

Private Sub cmdCancel_Click()

DoCmd.Close

End If

Private Sub cmdCancel_Click()
‘*****************************************************************
‘Purpose: Clear all criteria from previous searches
‘*****************************************************************

txtOrderID = “”
cboOrderMgr = “”
txtCust = “”
txtLocation = “”
fraLocSearchType = 3 ‘Sets Default to “Contains”
txtOrdEntryFrom = “”
txtOrdEntryTo = “”
chkOpenOnly = True ‘Sets Default to Open Orders Only
chkClosedOnly = False


End If

Private cmdSearch_Click()
‘*****************************************************************
‘Purpose: Build the WHERE clause for the SQL statement that
‘ populates the search results form (frmRetrieve),
‘ open that form, and set the recordsource based on
‘ that WHERE clause
‘*****************************************************************
Dim sSQL As String 'SQL for recordsource for frmRetrieve
Dim sWHERE As String 'WHERE clause for SQL statement
Dim sAND As String 'And string starts as an empty string
‘until the first criteria. Thereafter
‘it contains “ AND “ to connect
‘additional criteria to the clause

‘If no criteria is entered, set WHERE string to nothing and
‘retrieve all records.
If IsNull(txtOrderID) And _
IsNull(cboOrderMgr) And _
IsNull(txtCust) And _
IsNull(txtLocation) And _
IsNull(txtOrdEntryFrom) And _
IsNull(txtOrdEntryTo) And _
chkOpenOnly = False And _
chkClosedOnly = False Then

sWHERE = “;”
GoTo GetIt
Else
sWHERE = “WHERE “
sAND = “”
End If

‘Go through all the fields and build WHERE clause
‘Order ID
If Not IsNull(txtOrderID) Then
sWHERE = sWHERE & “Orders.OrderID = “ & txtOrderID & “ “
‘Skip checking other fields
GoTo GetIt
End If

‘Order Manager
If Not IsNull(cboOrderMgr) Then
sWHERE = sWHERE & “Orders.OrdMgrID = “ & cboOrderMgr & “ “
sAND = “ AND “
End If

‘Customer
If Not IsNull(txtCust) Then
If chkCustExact = True Then
sWHERE = sWHERE & sAND & “Orders.Cust = ‘” & txtCust _
& “’ “
Else
sWHERE = sWHERE & sAND & “Orders.Cust Like ‘*” & _
txtCust & “*’ “
End If

sAND = “ AND “
End If

‘Location
If Not IsNull(txtLocID) then
Select Case fraLocSearchType
Case 1 ‘Exact match
sWHERE = sWHERE & sAND & “Locations.LocName = ‘” & _
txtLocation & “’ “
Case 2 ‘Begins With Entered Text
sWHERE = sWHERE & sAND & “Locations.LocName LIKE ‘*” & _
txtLocation & “’ “
Case 3 ‘Contains Entered Text
sWHERE = sWHERE & sAND & “Locations.LocName LIKE ‘*” & _
txtLocation & “*’ “
Case 4 ‘Ends With entered text
sWHERE = sWHERE & sAND & “Locations.LocName LIKE ‘” & _
txtLocation & “*’ “
End Select

sAND = “ AND “
End If


‘Order Entry Date – From Only
If Not IsNull(txtOrdEntryFrom) And IsNull(txtOrdEntryTo) Then
sWHERE = sWHERE & sAND & “Orders.OrdEntry >= #” & _
txtOrdEntryFrom & “# “
sAND = “ AND “
End If

‘Order Entry Date – To Only
If IsNull(txtOrdEntryFrom) And Not IsNull(txtOrdEntryTo) Then
sWHERE = sWHERE & sAND & “Orders.OrdEntry <= #” & _
txtOrdEntryTo & “# “
sAND = “ AND “
End If

‘Order Entry Date – Between From and To
If Not IsNull(txtOrdEntryFrom) And IsNull(txtOrdEntryTo) Then
sWHERE = sWHERE & sAND & “Orders.OrdEntry Between #” & _
txtOrdEntryFrom & “# AND #“ & txtOrdEntryTo & “# “
sAND = “ AND “
End If

‘Open or closed Orders Only
If chkOpenOnly = True Then
sWHERE = “Orders.OrdComp IS NULL “
ElseIf chkClosedOnly = True Then
sWHERE = “Orders.OrdComp IS NOT NULL “
End If

sWHERE = sWHERE & “;”

GetIt:
‘Print WHERE clause in debug window
Debug.Print sWHERE
SSQL = “SELECT Orders.OrderID, Employees.Name, Orders.Cust, “ & _
“Locations.LocName, Orders.OrdEntry, Orders.OrdComp, “ & _
“Orders.Cost, Locations.SiteMgr “ & _
“FROM (Locations INNER JOIN Orders ON “ & _
“Locations.LocID = Orders.LocID) INNER JOIN “ & _
“Employees ON Orders.OrdMgrID = Employees.EmpID “ & _
sWHERE

‘Open the retrieve form
DoCmd.OpenForm “frmRetrieve”, acNormal, , , acFormReadOnly, _
acHidden
Forms!frmRetrieve.RecordSource = sSQL
Forms!frmRetrieve.Visible = True
Forms!frmSearch.Visible = False

End If

Private Sub txtOrderID_AfterUpdate()
‘*****************************************************************
‘Purpose: If a search is done on an Order ID, no other criteria
‘ is necessary. If an Order ID is entered, all other
‘ fields are disabled. If the order ID is removed, other
‘ fields are enabled.
‘*****************************************************************

Dim bEnableIt As Boolean

‘If an Order ID is entered, disable all other fields
If IsNull(txtOrderID) Then
bEnableIt = True
Else
bEnableIt = False
End If

CboOrderMgr.Enabled = bEnableIt
txtCust.Enabled = bEnableIt
txtLocation.Enabled = bEnableIt
fraLocSearchType.Enabled = bEnableIt
txtOrdEntryFrom.Enabled = bEnableIt
txtOrdEntryTo.Enabled = bEnableIt
chkOpenOnly.Enabled = bEnableIt
chkClosedOnly.Enabled = bEnableIt

End Sub



The Retrieve form:
frmRetrieve is a form that has labels with field names in a row in the Form Header and and a single row of fields below those labels in the Detail secion. The form’s Default View property is set to Continuous Forms to get a tabular form that will show a list of records retrieved by the search. The fields on the retrieve form are OrderID, OrderMgr, Cust, LocID, OrdEntry, OrdComp, OrdCost, SiteMgr. This form also has a command button that closes the form and returns to the search form.

The double-click even of the controls on this form opens the third form displaying the details of the record that was double-clicked.

The third form is the form where records are actually entered/edited.


_________
Rott Paws
 
Rott - thanks for the code. Will check it out - looks good...
 
Hi Rob,

Your search sounds great! I am just a semi-professional user though. Could you send me a sample of this search tool? I am sure I can figure it out from there :)

My mail is sheilaalighieri1980@yahoo.it

Sheila
 
Hi Rob & Sheila,

Can you please send me a sample of this search tool? My mail is khofiza@yahoo.com
Lily
 
I don't have a working copy of it anymore. If you follow the instructions above, it should be pretty easy to build it.

If you have any problems with it, let me know and I'll try to help. _________
Rott Paws

...It's not a bug. It's an undocumented feature!!!
 
I've created something similiar to this, but made it more generic. That way I can call the same routine to build my Where clause from multiple databases. And it's pretty simple.

I have one routine that builds the where clause for date ranges. Another routine to build the where clause for multi-select list boxes. Another for text boxes, etc. (This could all be done in one routine, but I split it out so that I could have more control as to how I called them.)

I use the tag property of the controls to tell me what to do. I also use a naming convention for some of the controls. For example, for a date range, the first control's name might be HireDate_Begin and the 2nd control's name might be HireDate_End.

Finally, I created wizards to create these controls with the correct naming convention and formatting of the tag property (a convenience, not a neccessity)

Simply set the Tag property of each control on the form (only those controls that can contain criteria). The tag property would look something like this:

Tag ... Criteria:TableName.FieldName.DataType;

Where &quot;TableName&quot; is the name of the Table that will be used in your Where clause. And FieldName is the name of the field within the table, and DataType is the data type of the field (i.e. string, number). The DataType will help in determining how to format the string (see code).

Now your function simply loops thru all of the controls on the form and checks the tag property. If the tag property contains the word Criteria: then you know how to build the Where clause. Note that if the control has been disabled or made invisible, then I ignore it.

The example code below was put together real quickly. But should work for text boxes. You can add other controls as well.

Code:
    Dim i As Integer
    Dim k As Integer
    
    Dim strTableName As String
    Dim strFieldName As String
    Dim strDataType As String
    Dim strWhere As String

    Dim var As Variant
    
    strWhere = vbNullString
    
    For Each var In Me.Controls
        If (var.ControlType = acTextBox) Then
            If (Not IsNull(var)) And (var.Enabled) And (var.Visible) Then
                i = InStr(1, var.Tag, &quot;Criteria:&quot;)
                If (i > 0) Then
                    k = InStr(i + 9, var.Tag, &quot;.&quot;)
                    strTableName = Mid(var.Tag, i + 9, k - (i + 9))
                    i = InStr(k + 1, var.Tag, &quot;.&quot;)
                    strFieldName = Mid(var.Tag, k + 1, i - (k + 1))
                    k = InStr(i + 1, var.Tag, &quot;;&quot;)
                    If (k = 0) Then k = Len(var.Tag)
                    strDataType = Mid(var.Tag, i + 1, k - (i + 1))
                    If (strDataType = &quot;string&quot;) then
                        strWhere = strTableName & &quot;.&quot; & strFieldName & &quot; = '&quot; & var.Value & &quot;' And &quot;
                    ElseIf (strDataType = &quot;number&quot;) then
                        strWhere = strTableName & &quot;.&quot; & strFieldName & &quot; = &quot; & var.Value & &quot; And &quot;

                End If
            End If
        End If
    Next
    
    If (strWhere <> vbNullString) Then strWhere = Left(strWhere, Len(strWhere) - 4) 'get rid of last &quot;And &quot;

    msgbox strWhere
 
Hi Rott,
Altough I created frmRetrieve as you suggested in document.
it giving me error run time error 2494 the action or method requires a
form name argument on following line

DoCmd.OpenForm “frmRetrieve”, acNormal, , , acFormReadOnly, _
acHidden


How can we link frmSearch and frmRetrieve.
Do we have to set some property.
Hope you will help me
Thanks
Lily
 
RottPaws: This would make a good FAQ. You could just cut and paste your whole initial post. It's easy to write a FAQ (see the link at the top of the Reply form below), and it may be easier for users to find your idea that way. Why don't you consider it? Rick Sprague
To write a program from scratch, first create the universe. - Paraphrased from Albert Einstein
 
Lily,

It looks like when I pasted my code, the single and double quotes got replace with other characters that look similar, but are different.

In addition to that, it looks like I messed up something in my code and a many of what are supposed to be &quot;End Sub&quot; are &quot;End If&quot; in the code.

To answer your question about the error you are getting, I'd try deleting the quotes before and after 'frmRetrive' in the command and replace them with the correct quotation mark characters.

I'm almost finished rebuilding a simple database with this search engine. Hopefully, I'll be able to email a copy to you tomorrow.

Sheila, I will email it to you also. _________
Rott Paws

...It's not a bug. It's an undocumented feature!!!
 
Rick,

Thanks for the suggestion on making this an FAQ. That's kinda what I had in mind when I posted it. I made it a &quot;tip&quot; rather than a question in the forum. I was pretty new to the site then . . .

Once I get the code corrected, I'll make it into an FAQ.

One question......you said it would be easier for users to find that way......Why?

FanciePrairie,

I really like your idea! I'll check it out when I have time and try to work that in. Thanks! _________
Rott Paws

...It's not a bug. It's an undocumented feature!!!
 
Sheila/Lily,

I've emailed an example of my Access search tool to the email addresses you provided above.

Let me know if you have any problems figuring it out. _________
Rott Paws

...It's not a bug. It's an undocumented feature!!!
 
i wonder if you can help me.
i have a search function very similar to this example and open the next form the same way as you have done.
however, i would like to add code that returns a message box telling the user when there are no results from the search (not opening the new form). i dont want to run the query twice, to check if there are results and then open the basic_results form.

any way of doing this?
 
Hi Rott,
Thanks a lot .It is very good for me to jump into access
programming.
Lily
 
Hey that sounds great RottPaws! I'm looking for something just like this, could you please send me a copy of your sample database to markwaddington@blueyonder.co.uk ?

Many many thanks!

Mark Waddington.
 
Mark,

It's on it's way. _________
Rott Paws

...It's not a bug. It's an undocumented feature!!!
 
It's ok I figured it out by myself!

The only trouble i'm having is with the form where you gather search criteria.

It gives me false results when I make some of my search fields Null, and I have to clear the form again otherwise it won't find any records from other criteria I type in other fields (even if there are records that satisfy the search).

I just got round it by putting a couple of lines of code in the &quot;AfterUpdate&quot; event of my registration number field, where it closes the form and opens it again... you hardly notice it.

Cheers,

Mark Waddington.
 
That sounds great RottPaws! I'm looking for something just like this, could you please send me a copy of your sample database to meadowsstephen@hotmail.com ?

Many thanks

Stephen
 
Mark,

Another good thing to do (I forgot to do it in this example) is add another command button (I call mine cmdClear) that has code that resets everything to default values......

Stephen,

On the way......... _________
Rott Paws

...It's not a bug. It's an undocumented feature!!!
 
RottPaws, I hate to ask, but could you also send me a copy of your database to swisstexy@aol.com?

Thank you so much!
Natalie
 
..and finally, one to biochem3d@cs.com I have been quite interested in this topic from the beginning. Thanks!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top