views:

515

answers:

5

Hi to all, I'm trying to get a query working that takes the values (sometimes just the first part of a string) from a form control. The problem I have is that it only returns records when the full string is typed in.

i.e. in the surname box, I should be able to type gr, and it brings up

green grey graham

but at present it's not bringing up anything uless the full search string is used.

There are 4 search controls on the form in question, and they are only used in the query if the box is filled in.

The query is :

SELECT TabCustomers.*,
       TabCustomers.CustomerForname AS NameSearch,
       TabCustomers.CustomerSurname AS SurnameSearch,
       TabCustomers.CustomerDOB AS DOBSearch,
       TabCustomers.CustomerID AS MemberSearch
FROM TabCustomers
WHERE IIf([Forms]![FrmSearchCustomer]![SearchMember] Is Null
          ,True
          ,[Forms]![FrmSearchCustomer]![SearchMember]=[customerid])=True
      AND IIf([Forms]![FrmSearchCustomer].[SearchFore] Is Null
              ,True
              ,[Forms]![FrmSearchCustomer]![SearchFore] Like [customerforname] & "*")=True
      AND IIf([Forms]![FrmSearchCustomer]![SearchLast] Is Null
              ,True
              ,[Forms]![FrmSearchCustomer]![SearchLast] Like [customersurname] & "*")=True
      AND IIf([Forms]![FrmSearchCustomer]![Searchdate] Is Null
              ,True
              ,[Forms]![FrmSearchCustomer]![Searchdate] Like [customerDOB] & "*")=True;
A: 

My only thoguht is that maybe a () is needed to group the like

For example a snippet on the first part

,[Forms]![FrmSearchCustomer]![SearchFore] Like ([customerforname] & "*"))=True

It has been a while since I've used access, but it is the first thing that comes to mind

Mitchel Sellers
Unfortunately it didn't do the trick Mitchel, thanks for looking though :)
Paul Green
Darn! I thought i'd give it a shot, I don't have access on all of my machines so I couldn't test
Mitchel Sellers
A: 

This is a complete re-write to allow for nulls in the name fields or the date of birth field. This query will not fail as too complex if text is entered in the numeric customerid field.

SELECT TabCustomers.CustomerForname AS NameSearch, TabCustomers.CustomerSurname AS SurnameSearch, TabCustomers.CustomerDOB AS DOBSearch, TabCustomers.customerid AS MemberSearch
FROM TabCustomers
WHERE TabCustomers.customerid Like IIf([Forms]![FrmSearchCustomer].[Searchmember] Is Null,"*",[Forms]![FrmSearchCustomer]![Searchmember])
AND Trim(TabCustomers.CustomerForname & "") Like IIf([Forms]![FrmSearchCustomer].[SearchFore] Is Null,"*",[Forms]![FrmSearchCustomer]![SearchFore] & "*")
AND Trim(TabCustomers.CustomerSurname & "") like IIf([Forms]![FrmSearchCustomer].[Searchlast] Is Null,"*",[Forms]![FrmSearchCustomer]![SearchLast] & "*")
AND (TabCustomers.CustomerDOB Like IIf([Forms]![FrmSearchCustomer].[SearchDate] Is Null,"*",[Forms]![FrmSearchCustomer]![SearchDate] ) Or TabCustomers.CustomerDOB Is Null)
Remou
+2  A: 

Two things are going on - the comparisions should be reversed and you are not quoting strings properly.

It should be [database field] like "partial string + wild card"

and all strings need to be surrounded by quotes - not sure why your query doesn't throw errors

So the following should work:

,[customerforname] Like  """" & [Forms]![FrmSearchCustomer]![SearchFore] & "*""" )=True

Note the """" that is the only way to append a single double-quote to a string.

DJ
Hi DJ, I've tried changing the query to your suggestions, and it doesn't want to know - it now returns no records at all... As for errors, I'd rather it threw an error than acted like it was working and wasted everyones time :(
Paul Green
This is similar to my example, except the quotes shown assume it is inline code (SQL built from strings), not a record source to a form. I recommend eliminating the IIF as shown in my example by using OR, as I find it much cleaner to read than IIF expressions.
Godeke
Well normally I would dynamically build a search query so it's hard to tell what's going on.It could be that your other terms being Null and you don't really need all those IIFs
DJ
Rather than [database field] like "partial string + wild card"I think it should be [database field] like "partial string" + "wild card"
onedaywhen
onedaywhen
OK - Chr(39) works too :-)
DJ
+4  A: 

You have your LIKE expression backwards. I have rewritten the query to remove the unnecessary IIF commands and to fix your order of operands for the LIKE operator:

SELECT TabCustomers.*
FROM TabCustomers
WHERE (Forms!FrmSearchCustomer!SearchMember Is Null Or Forms!FrmSearchCustomer!SearchMember=[customerid]) 
And (Forms!FrmSearchCustomer.SearchFore Is Null Or [customerforname] Like Forms!FrmSearchCustomer!SearchFore & "*") 
And (Forms!FrmSearchCustomer!SearchLast Is Null Or [customersurname] Like Forms!FrmSearchCustomer!SearchLast & "*") 
And (Forms!FrmSearchCustomer!Searchdate Is Null Or [customerDOB] Like Forms!FrmSearchCustomer!Searchdate & "*");

I built that query by replicating the most likely circumstance: I created a dummy table with the fields mentioned and a form with the fields and a subform with the query listed above being refreshed when the search button was pushed. I can provide a download link to the example I created if you would like. The example works as expected. J only picks up both Jim and John, while John or Jo only pulls the John record.

Godeke
This has been bounced around UtterAccess for about 2 weeks, and hasn't come close!!!
Paul Green
This query will fail as too complex if a user enters text in a numeric field. Also, if any of the fields are null, the record will not be returned.
Remou
The search form has a pretty robust parity check - everything's had to be written with user friendly error messages, so that shouldn't happen...
Paul Green
+3  A: 

There is an Access Method for that!

If you have your "filter" controls on the form, why don't you use the Application.buildCriteria method, that will allow you to add your filtering criterias to a string, then make a filter out of this string, and build your WHERE clause on the fly?

selectClause = "SELECT TabCustomers.* FROM TabCustomers"
if not isnull(Forms!FrmSearchCustomer!SearchMember) then
    whereClause = whereClause & application.buildCriteria(your field name, your field type, your control value) &  " AND "
endif
if not isnull(Forms!FrmSearchCustomer!SearchFore) then
    whereClause = whereClause & application.buildCriteria(...) &  " AND "
endif
if not isnull(Forms!FrmSearchCustomer!SearchLast) then
    whereClause = whereClause & application.buildCriteria(...) &  " AND "
endif
if not isnull(Forms!FrmSearchCustomer!SearchDate) then
    whereClause = whereClause & application.buildCriteria(...) & " AND "
endif
--get rid of the last "AND"
if len(whereClause) > 0 then
     whereClause = left(whereClause,len(whereClause)-5)
     selectClause = selectClause & " WHERE " & whereClause
endif
-- your SELECT instruction is ready ...

EDIT: the buildCriteria will return (for example):

  • 'field1 = "GR"' when you type "GR" in the control
  • 'field1 LIKE "GR*"' when you type "GR*" in the control
  • 'field1 LIKE "GR*" or field1 like "BR*"' if you type 'LIKE "GR*" OR LIKE "BR*"' in the control

PS: if your "filter" controls on your form always have the same syntax (let's say "search_fieldName", where "fieldName" corresponds to the field in the underlying recordset) and are always located in the same zone (let's say formHeader), it is then possible to write a function that will automatically generate a filter for the current form. This filter can then be set as the form filter, or used for something else:

For each ctl in myForm.section(acHeader).controls
    if ctl.name like "search_"
        fld = myForm.recordset.fields(mid(ctl.name,8))
        if not isnull(ctl.value) then
           whereClause = whereClause & buildCriteria(fld.name ,fld.type, ctl.value) & " AND "
        endif
    endif
next ctl
if len(whereClause)> 0 then ...
Philippe Grondier
I would definitely recommend this approach: it is much easier to support, particularly if you add additional criteria to your form. I've used it on a form that had up to 20 criteria (searching a database of hockey players using different combinations of stats).
Dave DuPlantis
Excellent point. My response was to fix the queries error, but this is a better overall solution over time. Note that I have seen bugs in BuildCriteria regarding date handling.
Godeke
I find a helper function that prepends the " AND " only if passed a non null string can avoid that last scan. whereClause = AddAnd(whereClause...). For searches the extra cost of the calls is negligible.
Godeke