Solved Like in a VBA where clause (1 Viewer)

mikenyby

Member
Local time
Today, 13:07
Joined
Mar 30, 2022
Messages
87
Hello! I'm creating an advanced search page for my organization's database, and if possible, I'd like to return results using if/then statements and where clauses in vba. But I can't make Like work properly in a vba where clause. Here's an excerpt of the code I'm working on:

Code:
Private Sub cmdItemSearch_Click()
    If Me.cboItemField1 = "NAME" And Me.cboBool1 = "1" Then
        DoCmd.OpenForm "frmAdvancedSearchSelectItem", acNormal, , "ItemName = Like '*" & [Forms]![frmAdvancedSearch]![txtItemNameSearch1] & "*'", acFormPropertySettings, acWindowNormal
         Me.txtItemNameSearch1 = ""
            ElseIf Me.cboItemField1 = "YEAR" And Me.cboBool1 = "1" Then
                DoCmd.OpenForm "frmAdvancedSearchSelectItem", acNormal, , "ItemYearofProvenance = Like '*" & [Forms]![frmAdvancedSearch]![txtItemYearSearch1] & "*'", acFormPropertySettings, acWindowNormal
    End If
End Sub

How it is now, I get this message when I click cmdItemSearch.
1701893474233.png


What am I doing wrong?
 

pbaldy

Wino Moderator
Staff member
Local time
Today, 10:07
Joined
Aug 30, 2003
Messages
36,126
Happy to help!
 

Pat Hartman

Super Moderator
Staff member
Local time
Today, 13:07
Joined
Feb 19, 2002
Messages
43,275
@mikenyby This has nothing to do with anything. Glad the answer was easy. Please ignore me if you like. Personally, I hate ElseIf. No one ever indents them in a meaningful fashion. At the moment, you have two very similar options but I'm sure you want to go further with this and the code will become unreadable. I've attached the code behind one of my complex search forms. Notice as you look at the code, it takes one field as a time and incorporates it into a where clause. Later, the where clause is combined with the select and order by and used as the RecordSource query for a form that lists clients that were selected by the criteria. Then the user double clicks on a specific client record and opens the edit form for that client. The only code I included is that which is used to format the SQL strings. One important concept - NEVER use Like UNLESS the field is a text string such as a name or address where you might have only a partial string. If you pick from a combo,you ALWAYS have a full string or an ID so you use = in that case. Using Like is necessary for some fields. However, it will almost always force a full table scan and will not take advantage of indexes to speed up the selection process. That means as you table grows in size, Like eventually becomes very slow.
I also included a picture of the form so you can see the options. In all cases, fields are joined with AND. Creating a search that mixes AND with OR is infinitely more complex since you need to use parentheses to control how the compound expression is evaluated.

A or B and C --- is not the same as (A or B) and C --- so this expression will return different results depending on if and where parentheses are used.

For my own samity, the form includes a Box that shows the actual query the code created. This made testing very much easier and if you do something like this and you don't want the users to be bothered by it, hide it for all users except your specific Environ("UserName") value.

Another thing in the code is the use of a global variable named QUOTE. This is a constant that includes a double quote. I use the variable whenever I want to embed a double quote into the string. This makes the code simple to read and understand since otherwise you would be using """ or """" depending on context and no one can keep that straight in a complex concatenation such as this one.

1701904538594.png

Code:
Public Sub BuildSQL()
Dim strSQL As String
Dim strSelect As String
Dim strSelectForExport As String
Dim strWHERE As String
Dim strCondition As String
Dim strOrderBy As String

    strSelect = "Select * from qClientList "
    strSelectForExport = "Select * from qClientListExport "
    strOrderBy = " ORDER BY FullName"
    strWHERE = ""
 
    If Me.txtFirstName & "" = "" Then
    Else
        strWHERE = "FirstName Like " & QUOTE & Me.txtFirstName & "*" & QUOTE
    End If
    If Me.txtLastName & "" = "" Then
    Else 
        strWHERE = strWHERE & " AND " & "LastName Like " & QUOTE & Me.txtLastName & "*" & QUOTE
    End If
    If Me.txtcity & "" = "" Then
    Else 
        strWHERE = strWHERE & " AND " & "City Like " & QUOTE & Me.txtcity & "*" & QUOTE
    End If
    If Me.txtaddress & "" = "" Then
    Else
        strWHERE = strWHERE & " AND " & "Address Like " & QUOTE & Me.txtaddress & "*" & QUOTE
    End If
    If Me.chkBUP = True Then
        strWHERE = strWHERE & " AND " & "BUP = True"
    End If
    If Me.cboCareMgrID & "" = "" Then
    Else
        strWHERE = strWHERE & " AND " & "CareMgrID = " & Me.cboCareMgrID
    End If
    If Me.cboGenderID & "" = "" Then
    Else 
        strWHERE = strWHERE & " AND " & "GenderID = " & Me.cboGenderID
    End If
    If Me.txtZip & "" = "" Then
    Else
        strWHERE = strWHERE & " AND " & "Zip = '" & Me.txtZip & "'"
    End If

    If Me.cboRaceID & "" = "" Then
    Else
        strWHERE = strWHERE & " AND " & "RaceID = " & Me.cboRaceID
    End If
    If Me.cboDiagnosis & "" = "" Then
    Else
        strWHERE = strWHERE & " AND " & "Diagnosis = " & QUOTE & Me.cboDiagnosis & QUOTE
    End If
    If Me.txtpid & "" <> "" Then
        strWHERE = strWHERE & " AND " & "PID = " & QUOTE  & Me.txtpid & QUOTE 
    End If
    If Me.txtClientID & "" <> "" Then
        strWHERE = strWHERE & " AND " & "ClientID = " & Me.txtClientID
    End If
    If Me.txtems & "" <> "" Then
        strWHERE = strWHERE & " AND " & "EMS = " & QUOTE & Me.txtems & QUOTE
    End If
     
    If Me.txtPhone & "" <> "" Then
        strWHERE = strWHERE & " AND " & "(Phone = " & QUOTE & Me.txtPhone & QUOTE & " OR CellPhone = " & QUOTE & Me.txtPhone & QUOTE & ")"
    End If
 
    If Me.cboCounty & "" <> "" Then
        strWHERE = strWHERE & " AND " & "County = " & QUOTE & Me.cboCounty & QUOTE
    End If
     
    If Me.cboLevelID & "" <> "" Then
        strWHERE = strWHERE & " AND " & "LevelID = " & Me.cboLevelID
    End If
 
    If Me.cboTier & "" <> "" Then
        strWHERE = strWHERE & " AND " & "PCATier = " & Me.cboTier
    End If
 
    'Plans
    If Me.cboProgramID & "" = "" Then
    Else
        strWHERE = strWHERE & " AND " & "ProgramID = " & Me.cboProgramID
    End If
 
    'Funding
    If Me.chkT19 = True Then
        strWHERE = strWHERE & " AND " & "T19 = True"
    End If

    If Me.chkSelf = True Then
        strWHERE = strWHERE & " AND " & "Self = True"
    End If
    If Me.chkMFP = True Then
        strWHERE = strWHERE & " AND " & "MFP = True"
    End If
 
    If Me.chkNOTT19 = True Then
        strWHERE = strWHERE & " AND " & "Not(T19 = True)"
    End If
    If Me.chkNOTSelf = True Then
        strCondition = "Not (Self = True)"
        strWHERE = strWHERE & " AND " & strCondition
    End If
    If Me.chkNOTMFP = True Then
        strWHERE = strWHERE & " AND " & "Not(MFP = True)"
    End If

  
    Select Case Me.fraStatus
        Case 1
            strCondition = "StatusID = 1318"          'Open
        Case 2
            strCondition = "StatusID = 1319"          'Closed
        Case 4
            strCondition = "StatusID = 1427"          'Pending
        Case Else
            strCondition = ""
    End Select
    If strWHERE = "" Then
        If strCondition = "" Then
        Else
            strWHERE = strCondition
        End If
    Else
        If strCondition = "" Then
        Else
            strWHERE = strWHERE & " AND " & strCondition
        End If
    End If
 
    If Left(strWHERE, 5) = " AND " Then
        strWHERE = Mid(strWHERE,6)
    End If

'query for form/report
    If strWHERE = "" Then
        strSQL = strSelect
    Else
        strSQL = strSelect & " WHERE " & strWHERE
    End If

    strSQL = strSQL & strOrderBy
    Me.txtQuery = strSQL
 
'query for Excel
    If strWHERE = "" Then
        strSQL = strSelectForExport
    Else
        strSQL = strSelectForExport & " WHERE " & strWHERE
    End If
 
    strSQL = strSQL & strOrderBy
    Me.txtQueryExport = strSQL
End Sub
 
Last edited:

mikenyby

Member
Local time
Today, 13:07
Joined
Mar 30, 2022
Messages
87
@Pat Hartman
Thank you for this. I've got over half of the code done now (tedious copy/pasting and editing!), but I will have to do another DB for a different department after this one is done. I'll have a good long look at your example at that time. I appreciate it!
 

mikenyby

Member
Local time
Today, 13:07
Joined
Mar 30, 2022
Messages
87
Hi @Pat Hartman !

You commented on this post regarding an advanced search form that I'm making and included some example code for making it work without having to enter exponentially multiplying lines of code. I tried to apply your example to my db, but since my form's format is quite a bit different I'm having a hard time making it work. If you would be so kind, and have the available time, I would be very grateful if you could have a look at the attached dummy database with only a few non-sensitive records and provide some insight on how to adapt your model to my form. I'm only starting to use declared variables for some functions, and I haven't quite gotten the hang of how to use them to my benefit, so I think that's where I'm having trouble.

The form in question is named "frmAdvancedSearch" and as you can see, I've been asked to include boolean "AND", "OR" and "NOT" operators. I reverted to the code I was writing, and you can see how out of hand the If/ElseIf/Then statements are getting.

Thank you!
 

Attachments

  • WRMS Archives Dummy.accdb
    3 MB · Views: 44

MajP

You've got your good things, and you've got mine.
Local time
Today, 13:07
Joined
May 21, 2018
Messages
8,529
You may want to look at this. I imagine with this approach you could eliminate probably 80% of your code.
This makes it very easy to create a filter from a control and then combine those individual filters. This does away with all if thens.

To avoid all the Ifs my technique is to build a filter string for each control saved as variable. That string could be blank if the control is not used.
Then I pass all of these strings to a combiner that does nothing with the empty strings but combines the rest. This does away with all the If thens.
Now the real work is the methods to GetFilterFromControl.
So for example here is the code to handle seven different controls to include two controls acting together in a between criteria
Code:
Public Function FilterList()
  Dim fltrNonConID As String
  Dim fltrNonConType As String
  Dim fltrDates As String
  Dim fltrPlant As String
  Dim fltrLocation As String
  Dim fltrReported As String
  Dim fltr As String
  Dim AndOr As CombineFilterType
  Dim strSql As String

  Select Case frameAndOr
    Case 1
      AndOr = ct_And
    Case 2
      AndOr = ct_OR
  End Select

  fltrNonConID = GetFilterFromControl(Me.cmboID)
  fltrNonConType = GetFilterFromControl(Me.cmboType)
  fltrPlant = GetFilterFromControl(Me.cmboPlant)
  fltrLocation = GetFilterFromControl(Me.cmboLocation)
  fltrReported = GetFilterFromControl(Me.cmboReported)
  fltrDates = GetBetweenFilter(Me.txtBeginDate, Me.txtEndDate, "DateReported")
  fltr = CombineFilters(AndOr, fltrNonConID, fltrNonConType, fltrPlant, fltrLocation, fltrReported, fltrDates)
  Me.txtFilter = fltr


  strSql = "Select * from qry_SearchAll_NoCriteria"
  If fltr <> "" Then
    strSql = strSql & " WHERE " & fltr
  End If
  strSql = strSql & " Order By DateReported DESC"
  Me.SearchResults.RowSource = strSql
End Functio
 
Last edited:

Pat Hartman

Super Moderator
Staff member
Local time
Today, 13:07
Joined
Feb 19, 2002
Messages
43,275
@mikenyby As I mentioned in my earlier response, if you want to include more than one type of relational operator in your expressions, you almost certainly will also need to provide the ability to specify where the parentheses go. Your interface does not account for that. It looks smooth and professional to just keep adding more fields - up to three but if you want to use AND, OR, and NOT, then a better interface would be to have all the three options always visible and add spaces between each variable where parentheses can be placed. So:

RO1 - Paren - firstField - condition1 ( =, >, < , <>, Like) - value1 - paren - RO2 - paren - secondfield - condition2 - value2- paren - RO3 - paren - thirdfield - paren ---- even this is not flexible enough to cover all situations. It is basically a framework and it will intimidate many users.

There is no way YOU can decide how to bracket the expression. Only the user knows his objective as I pointed out with a very simple example.

My search form is fixed because once the application is developed, new columns do not get added frequently and not all columns are searchable anyway. Yours is also fixed but in a more limited fashion and is just as susceptible to future maintenance requirements as mine is should more fields get added. So, your solution is different but not necessarily better or worse. I considered the possibility of implementing some type of OR support but couldn't justify the complexity AND the users would be REQUIRED to understand Boolean logic in order to create successful criteria AND they would need to be able to place the parentheses correctly. Programmers have trouble with this concept. How are users going to get it right?

So, you have to figure out what is the real objective of the search form. In my case, the objective was to filter the recordset to find specific records that needed to be reviewed. Perhaps the rules for a state program were being changed and not all people who were benefiting from it would be eligible next year.

In the end, I elected to create exportable queries to solve the problems that the search form didn't solve. The users could then open the data in Excel and do additional filtering including on columns that were not included in the search form itself.

Using combos to select fields, may offer a slight coding advantage but the users actually like seeing their options laid out for them along with occasional comments regarding usage which you could do with the combo but it is harder.

And finally, if you decide to pursue this search variation, use tables for your combos, don't hard code them as Value Lists. Once you have more than a few items, Value Lists become very difficult to maintain. For example, are you prepared to embed the new option at the correct spot to maintain a logical sort order?

Although I occasionally write code to solve problems for posters, I don't write code that I would never have a need for myself. This falls into that category.

If you like your interface but are not welded to the idea of using relational operators other than AND, the code to implement your design is actually pretty simple and works pretty much like what you see in my code sample. The difference is you would abstract the code slightly and put it all in a separate procedure instead of in the click events of the controls. That way you pass in a reference to the control as you call the procedure so the code always refers to the control by the reference rather than the control name. So, the same physical code is used for all three or more combos. Obviously, the more columns you support, the more you gain from this simple method of reuse.

If you need to add code to handle different fields differently, for example, Year is in your list. You are now adding complexity because the sub is no longer a black box. It has to operate differently depending on the value passed to it. This goes against the principles of coupling and cohesion. When your "reusable" code has to take different paths depending on an input argument, it is technically no longer reusable.

Hopefully Year isn't the name of an actual field. It probably references the year of a date field so your code must know what the name of that field actually is. So, you would have to extract year by using the year function on whatever date field year refers to. This is another reason for using a table to hold the RowSource for the combo. You can display user friendly names but keep in the table the actual column name and table it comes from.
 
Last edited:

mikenyby

Member
Local time
Today, 13:07
Joined
Mar 30, 2022
Messages
87
You may want to look at this. I imagine with this approach you could eliminate probably 80% of your code.
This makes it very easy to create a filter from a control and then combine those individual filters. This does away with all if thens.

To avoid all the Ifs my technique is to build a filter string for each control saved as variable. That string could be blank if the control is not used.
Then I pass all of these strings to a combiner that does nothing with the empty strings but combines the rest. This does away with all the If thens.
Now the real work is the methods to GetFilterFromControl.
So for example here is the code to handle seven different controls to include two controls acting together in a between criteria
Code:
Public Function FilterList()
  Dim fltrNonConID As String
  Dim fltrNonConType As String
  Dim fltrDates As String
  Dim fltrPlant As String
  Dim fltrLocation As String
  Dim fltrReported As String
  Dim fltr As String
  Dim AndOr As CombineFilterType
  Dim strSql As String

  Select Case frameAndOr
    Case 1
      AndOr = ct_And
    Case 2
      AndOr = ct_OR
  End Select

  fltrNonConID = GetFilterFromControl(Me.cmboID)
  fltrNonConType = GetFilterFromControl(Me.cmboType)
  fltrPlant = GetFilterFromControl(Me.cmboPlant)
  fltrLocation = GetFilterFromControl(Me.cmboLocation)
  fltrReported = GetFilterFromControl(Me.cmboReported)
  fltrDates = GetBetweenFilter(Me.txtBeginDate, Me.txtEndDate, "DateReported")
  fltr = CombineFilters(AndOr, fltrNonConID, fltrNonConType, fltrPlant, fltrLocation, fltrReported, fltrDates)
  Me.txtFilter = fltr


  strSql = "Select * from qry_SearchAll_NoCriteria"
  If fltr <> "" Then
    strSql = strSql & " WHERE " & fltr
  End If
  strSql = strSql & " Order By DateReported DESC"
  Me.SearchResults.RowSource = strSql
End Functio

@mikenyby As I mentioned in my earlier response, if you want to include more than one type of relational operator in your expressions, you almost certainly will also need to provide the ability to specify where the parentheses go. Your interface does not account for that. It looks smooth and professional to just keep adding more fields - up to three but if you want to use AND, OR, and NOT, then a better interface would be to have all the three options always visible and add spaces between each variable where parentheses can be placed. So:

RO1 - Paren - firstField - condition1 ( =, >, < , <>, Like) - value1 - paren - RO2 - paren - secondfield - condition2 - value2- paren - RO3 - paren - thirdfield - paren ---- even this is not flexible enough to cover all situations. It is basically a framework and it will intimidate many users.

There is no way YOU can decide how to bracket the expression. Only the user knows his objective as I pointed out with a very simple example.

My search form is fixed because once the application is developed, new columns do not get added frequently and not all columns are searchable anyway. Yours is also fixed but in a more limited fashion and is just as susceptible to future maintenance requirements as mine is should more fields get added. So, your solution is different but not necessarily better or worse. I considered the possibility of implementing some type of OR support but couldn't justify the complexity AND the users would be REQUIRED to understand Boolean logic in order to create successful criteria AND they would need to be able to place the parentheses correctly. Programmers have trouble with this concept. How are users going to get it right?

So, you have to figure out what is the real objective of the search form. In my case, the objective was to filter the recordset to find specific records that needed to be reviewed. Perhaps the rules for a state program were being changed and not all people who were benefiting from it would be eligible next year.

In the end, I elected to create exportable queries to solve the problems that the search form didn't solve. The users could then open the data in Excel and do additional filtering including on columns that were not included in the search form itself.

Using combos to select fields, may offer a slight coding advantage but the users actually like seeing their options laid out for them along with occasional comments regarding usage which you could do with the combo but it is harder.

And finally, if you decide to pursue this search variation, use tables for your combos, don't hard code them as Value Lists. Once you have more than a few items, Value Lists become very difficult to maintain. For example, are you prepared to embed the new option at the correct spot to maintain a logical sort order?

Although I occasionally write code to solve problems for posters, I don't write code that I would never have a need for myself. This falls into that category.

If you like your interface but are not welded to the idea of using relational operators other than AND, the code to implement your design is actually pretty simple and works pretty much like what you see in my code sample. The difference is you would abstract the code slightly and put it all in a separate procedure instead of in the click events of the controls. That way you pass in a reference to the control as you call the procedure so the code always refers to the control by the reference rather than the control name. So, the same physical code is used for all three or more combos. Obviously, the more columns you support, the more you gain from this simple method of reuse.

If you need to add code to handle different fields differently, for example, Year is in your list. You are now adding complexity because the sub is no longer a black box. It has to operate differently depending on the value passed to it. This goes against the principles of coupling and cohesion. When your "reusable" code has to take different paths depending on an input argument, it is technically no longer reusable.

Hopefully Year isn't the name of an actual field. It probably references the year of a date field so your code must know what the name of that field actually is. So, you would have to extract year by using the year function on whatever date field year refers to. This is another reason for using a table to hold the RowSource for the combo. You can display user friendly names but keep in the table the actual column name and table it comes from.
Thanks. @Pat Hartman. Really appreciate the effort you put into this response. I'm going to talk to my higher-ups over here to see if they really need the "OR" and "NOT" operators. I suspect they don't, but have seen how they are used in research databases and would like to implement them here.

The idea of using the [Items] table as the row source for each field in the combo box makes perfect sense. I'll work on the page here and hopefully prevent myself from having to write thousands of lines of code!

@MajP, I'm going to have a very close look at your code as well, thank you for supplying it.
 

Pat Hartman

Super Moderator
Staff member
Local time
Today, 13:07
Joined
Feb 19, 2002
Messages
43,275
A frequent situation is the user wants A and (a or b or c or d) You can set this up using a form with fixed controls. It will be very difficult with your current vision. It is not the selection of the fields using the combos it is the building of the complete expression that becomes very complicated. For example, you could select Location as the A field and you could select Year as the multi-value and then give them a way to select multiple years. This allows YOU to write the code that formats the expression so it is evaluated correctly.
Where Location = Me.cbo1 And [Year] In (2001, 2002, 2005)

If you have users who want complex criteria, you can allow them to just type it into a box. This leaves it to them to create the expression correctly. Either it works or doesn't work or if the syntax is incorrect, you will have to return the error message.
 

mikenyby

Member
Local time
Today, 13:07
Joined
Mar 30, 2022
Messages
87
A frequent situation is the user wants A and (a or b or c or d) You can set this up using a form with fixed controls. It will be very difficult with your current vision. It is not the selection of the fields using the combos it is the building of the complete expression that becomes very complicated. For example, you could select Location as the A field and you could select Year as the multi-value and then give them a way to select multiple years. This allows YOU to write the code that formats the expression so it is evaluated correctly.
Where Location = Me.cbo1 And [Year] In (2001, 2002, 2005)

If you have users who want complex criteria, you can allow them to just type it into a box. This leaves it to them to create the expression correctly. Either it works or doesn't work or if the syntax is incorrect, you will have to return the error message.
@Pat Hartman Thank you for your continued assistance. I've now hit a roadblock as I'm having some syntax issues referencing the required variables in the OpenForm where clause. Here's a snippet of code I'm working on:
Code:
Public Sub BuildSQL()
    Dim FieldWhere1 As String
    Dim FieldWhere2 As String
    Dim FieldWhere3 As String
   
    If Me.cboItemField1 = "TITLE" Then
        FieldWhere1 = "ItemName Like '*" & [Forms]![frmAdvancedSearch]![txtItemSearch1] & "*' "
            ElseIf Me.cboItemField1 = "YEAR" Then
                FieldWhere1 = "ItemYearOfProvenance Like '*" & [Forms]![frmAdvancedSearch]![txtItemSearch1] & "*' "
            ElseIf Me.cboItemField1 = "LOCATION" Then
                FieldWhere1 = "ItemLocation = [Forms]![frmAdvancedSearch]![cboLocationSearch1]"
            ElseIf Me.cboItemField1 = "DESCRIPTION" Then
                FieldWhere1 = "ItemDescription Like '*" & [Forms]![frmAdvancedSearch]![txtItemSearch1] & "*' "
            ElseIf Me.cboItemField1 = "STATEMENT OF RESPONSIBILITY" Then
                FieldWhere1 = "ItemStatementOfResponsibility Like '*" & [Forms]![frmAdvancedSearch]![txtItemSearch1] & "*' "
    End If

End Sub

Private Sub cmdItemSearch_Click()
    DoCmd.OpenForm "frmAdvancedSearchSelectItem", acNormal, , " ' & FieldWhere1 & '", acFormPropertySettings, acWindowNormal
    DoCmd.Close acForm, "frmAdvancedSearch", acSavePrompt
    DoCmd.OpenForm "frmAdvancedSearch", acNormal, , , acFormPropertySettings, acWindowNormal
    Forms!frmAdvancedSearchSelectItem.SetFocus
End Sub

With the code as appears above, frmAdvancedSearchSelectItem opens displaying all records in the Items table. I've tried a number of variations, including setting the variable as just the field name and including the rest of the where clause in the DoCmd.OpenForm statement, like this:

Code:
If Me.cboItemField1 = "TITLE" Then
        FieldWhere1 = "ItemName"
    ...
   
Private Sub cmdItemSearch_Click()

    DoCmd.OpenForm "frmAdvancedSearchSelectItem", acNormal, , " ' & FieldWhere1 & ' Like '*" & [Forms]![frmAdvancedSearch]![txtItemSearch1] & "*' ", acFormPropertySettings, acWindowNormal
    DoCmd.Close acForm, "frmAdvancedSearch", acSavePrompt
    DoCmd.OpenForm "frmAdvancedSearch", acNormal, , , acFormPropertySettings, acWindowNormal
    Forms!frmAdvancedSearchSelectItem.SetFocus

End Sub

But this opens the form displaying no records. I've tried a bunch of different variations with ampersands and single quotes on either side of the variable name but most of those failed to open the form at all. Most variations I try give me a "Variable not defined" error.

Clearly I don't understand how to reference variables in a VBA WHERE condition. Any ideas that can help me with this?
 
Last edited:

Pat Hartman

Super Moderator
Staff member
Local time
Today, 13:07
Joined
Feb 19, 2002
Messages
43,275
Do NOT use ELSEIF in this situation. Use a Case statement. As I said I hate ElseIF. It is a muddy construct and much simpler as a case statement. Also remember that Like will ALWAYS force a full table scan when you have a leading asterisk and frequently without it. This pattern doesn't combine the values for fields 2 and 3 into a single search
Code:
Select Case Me.cboItemField1
    Case "TITLE"
        FieldWhere1 = "ItemName Like '*" & [Forms]![frmAdvancedSearch]![txtItemSearch1] & "*' "
    Case "YEAR"
        FieldWhere1 = "ItemYearOfProvenance Like '*" & [Forms]![frmAdvancedSearch]![txtItemSearch1] & "*' "
    Case "LOCATION"
        FieldWhere1 = "ItemLocation = [Forms]![frmAdvancedSearch]![cboLocationSearch1]"
    Case "DESCRIPTION"
        FieldWhere1 = "ItemDescription Like '*" & [Forms]![frmAdvancedSearch]![txtItemSearch1] & "*' "
    Case "STATEMENT OF RESPONSIBILITY"
        FieldWhere1 = "ItemStatementOfResponsibility Like '*" & [Forms]![frmAdvancedSearch]![txtItemSearch1] & "*' "
    Case Else
        MsgBox "Please enter a valid field name.",vbOkOnly
        Me.cboItemField1.SetFocus
End Select

The code doesn't make sense, but the problem is likely the way this statement is delimited. Change to:

DoCmd.OpenForm "frmAdvancedSearchSelectItem", acNormal, , FieldWhere1, acFormPropertySettings, acWindowNormal

NEVER, EVER use acSavePrompt. You don't want any user to accidentally make a change to a form and save it. If you distribute the FE as an .accdr or .accde, the point is moot since the save will be ignored but if you distribute as an .accdb, users should not be saving changes to objects. Perhaps you are confusing this argument with saving data. Access automatically saves the data when a form closes (and other times also) so this prompt has nothing to do with data. It is only referring to the object.
 

Pat Hartman

Super Moderator
Staff member
Local time
Today, 13:07
Joined
Feb 19, 2002
Messages
43,275
You're welcome.

If you go with a table driven solution, you can write this code instead of a Select Case that must be modified each time a new column needs to be added.

Code:
FieldWhere1 = Me.cboItemField1.Column(2) & " Like '*" & [Forms]![frmAdvancedSearch]![txtItemSearch1] & "*' "

Assuming you stick with Like even for columns where you should not be using like, the single line of code is all you need. .Column(2) is the third column of the RowSource combo. The first would be the unique ID for the table, the second would be the user friendly column name and the third would be the actual column name. The RowSource is a zero based array, hence - 0, 1, 2 -- so 2 is the third column in the RowSource.

Like ONLY makes sense when you have a partial string. With the year field, you always have a full value.
 

Users who are viewing this thread

Top Bottom