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 derfloh on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Dynamic query/form field calling 2

Status
Not open for further replies.

Triacona

Technical User
Jun 11, 2009
462
GB
Dear all,

Please could you help me with the following problem.

I have a lot of queries using text from a form in their constraints.
Code:
between [forms]![MainSreen].[txtStartDate] and [forms]![MainSreen].[txtEndDate]

I have created another form BuildingControl with the same text fields:
txtStartDate
txtEndDate
But obviously it is another form...so therefore to call it
Code:
between [forms]![MainScreen].[txtStartDate] and [forms]![MainScreen].[txtEndDate]

Now we come to what I want to do...

I want to create within the query a dynamic or variable field call.

So instead of the form being listed, just
Code:
[txtStartDate] and [txtEndDate]
or
Code:
between [forms]![*].[txtStartDate] and [forms]![*].[txtEndDate]
So it gets the text field data from any form open that has those fields.

I.e.
Code:
between [forms]![any form open].[txtStartDate] and [forms]![any form open].[txtEndDate]

Is there a way to do this?

Please help, it will be greatly appreciated! [bigsmile]

Kind regards
Triacona
 
The request seems a little strange but it could be done. Although it is probably more efficient to do it the way you show for flexibility and reuses I never write form references in the query. I find it difficult and time consuming.

Instead I use a user defined function. I would change
Code:
between [forms]![MainSreen].[txtStartDate] and [forms]![MainSreen].[txtEndDate]
to
Code:
between getStartDate() and getEndDate()

And build functions like
Code:
public function getStartDate() as date
  getStartDate = nz([forms]![MainSreen].[txtStartDate],date())
end function
So taking that to the next step. The following would work
Code:
Public Function getStartDate() As Date
  Dim frm As Access.Form
  Dim ctl As Access.Control
  For Each frm In Forms
    For Each ctl In frm.Controls
      If ctl.name = "txtStartDate" Then
       getStartDate = ctl.Value
      End If
    Next ctl
  Next frm
End Function
 
Dear Majp,

Thank you so much for your help!!!![2thumbsup]

It works!!

I have implemented you solution as such...

Code:
Option Compare Database

Public Function getStartDate() As Date
  Dim frm As Access.Form
  Dim ctl As Access.Control
  For Each frm In Forms
    For Each ctl In frm.Controls
      If ctl.Name = "txtStartDate" Then
       getStartDate = ctl.Value
      End If
    Next ctl
  Next frm
End Function

Public Function getEndDate() As Date
  Dim frm As Access.Form
  Dim ctl As Access.Control
  For Each frm In Forms
    For Each ctl In frm.Controls
      If ctl.Name = "txtEndDate" Then
       getEndDate = ctl.Value
      End If
    Next ctl
  Next frm
End Function

I have put
Code:
getStartDate() And getEndDate()
in
the queries.

Thanks so much MajP!! It works!![bigsmile]

Kind regards

Triacona
 
The function is a little expensive because it loops all open forms and all controls. That was because my assumption was that you had many different forms open and the date form my not be the active form. But if the date form is always the active form when you run the query then you can make the code more streamlined by simply taking out all the loops and
...
getStartDate = Screen.Activeform.txtStartDate
...

If it is not necessarily the active form, but it can be a known set of forms you could check to see which form is loaded using the allforms collection.

if currentproject.allForms("formA").isloaded then
getStartDate = forms("formA").txtStartDate
elseif currentproject.allForms("formB").isloaded then
getStartDate = forms("formB").txtStartDate
elseif ....

end if

Both of these are much more efficient since you not looping everything. This could make a big difference if using the function in a select statement for each record in a very big query.
 
big difference if using the function in a select statement for each record in a very big query
I don't think so as the functions have no argument and thus will be evaluated only once.
 
PHV, good point. I know that is the case for parameterless queries, is it the same for a non changing parmeter?
I know this runs for each record
select someFunction([fieldName]) as something
But does this run once or for each record?
select someFunction("someNonChangingString") as s

In back of my mind I was assuming the real use for this would be the ability to pull a start date, end date from different types of date fields. Maybe the start date is the shipped date, end date is the received date. Other cases the start could be received and end disposed date. That would make a little more sense to me, but require a non changing parameter.
Code:
Public Function getDateFromForm(ctrlName as string) As Date
  Dim frm As Access.Form
  Dim ctl As Access.Control
  For Each frm In Forms
    For Each ctl In frm.Controls
      If ctl.name = CtlName Then
       getDateFromForm = ctl.Value
      End If
    Next ctl
  Next frm
End Function

between getDateFromForm("txtShipped") and getDateFromForm("txtReceived")

or more likely you know which form for which query versus randomly searching for a form
Code:
Public Function getDateFromForm(frmName as string, ctrlName as string) As Date
  getDateFromForm = forms(frmName).controls(ctrlName)
End Function
 
select someFunction("someNonChangingString") as s
For me, evaluated once by the Jet engine.
 
Thanks, I guess I could have tested too.
 
Dear MajP and PHV,

Thank you for all your help![bigsmile]

I have another question regarding this...

I have another field that a query calls from the active form.

It is a combo box field called cmbOfficer.
I have created another function...
Code:
Public Function getOfficer() As String
  Dim frm As Access.Form
  Dim ctl As Access.Control
  For Each frm In Forms
    For Each ctl In frm.Controls
      If ctl.Name = "cmbOfficer" Then
       getOfficer = ctl.Value
      End If
    Next ctl
  Next frm
End Function

I tried the above and the report is blank, no records, like it is not recognising the input??

Am I doing this correctly, I did try
Code:
 ...As ComboBox
in the function that gave me another error
undefined function getOfficer in expression.

Thanks for all your help, please can you help some more.

Kind regards
Triacona

 
Undefined function means it can not find it. Ensure the function is in a standard module not a form's module. Check your spelling. This would give you the error
... = getOficer()

If officer is a string then you need to enclose in single quotes.
where Officer = 'Smith'
Also make sure the combos bound field is the field you want.

Public Function getOfficer() As String
Dim frm As Access.Form
Dim ctl As Access.Control
For Each frm In Forms
For Each ctl In frm.Controls
If ctl.Name = "cmbOfficer" Then
getOfficer = "'" & ctl.Value & "'"
'To help debug use this and then delete after debugging
msgbox getOfficer
End If
Next ctl
Next frm
End Function
 
Dear MajP,

Sorry I did a bit of debugging...and the following works.
Code:
Public Function getOfficer() As String
  Dim frm As Access.Form
  Dim ctl As Access.Control
  For Each frm In Forms
    For Each ctl In frm.Controls
      If ctl.Name = "cmbOfficer" Then
       getOfficer = ctl.Value
      End If
    Next ctl
  Next frm
End Function
BUT NOT IF the field is blank, i.e. I want all the officers.

in my query the criteria is as such.
Code:
Like "*" & getOfficer() & "*"
I did this so that even if there was no input the query would continue...
But now it seems to require it as if I run it blank I get the following message.
Run-time error '94' invalid use of Null
I click on debug and
Code:
getOfficer = ctl.Value
is highlighted.

Please help...
Thanks for all the help![bigsmile]
Kind regards
Triacona
 
getOfficer = ctl.Value & ""

Hope This Helps, PH.
FAQ219-2884
FAQ181-2886
 
try
...
getOfficer = nz(ctl.Value,"")
...
 
Untested, but I think you can also do it so as not to use the like which could get you in trouble: John and Johnson.
... someField = getOfficer() or getOfficer() = ''

Public Function getOfficer() As String
Dim frm As Access.Form
Dim ctl As Access.Control
getOfficer = "''"
For Each frm In Forms
For Each ctl In frm.Controls
If ctl.Name = "cmbOfficer" Then
getOfficer = "'" & ctl.Value & "" & "'"
End If
Next ctl
Next frm
End Function
 
I used
Code:
Public Function getOfficer() As String

  Dim frm As Access.Form
  Dim ctl As Access.Control
  For Each frm In Forms
    For Each ctl In frm.Controls
      If ctl.Name = "cmbOfficer" Then
        [b]getOfficer = ctl.Value & ""[/b]
      End If
    Next ctl
  Next frm
  
End Function
This worked quite well [smile]
Kind regards
Triacona
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top