VBA not working for saved query parameters (1 Viewer)

RWilliams500

New member
Local time
Yesterday, 19:16
Joined
May 22, 2024
Messages
20
Howdy. I'm messing around with parameters in a query and setting them via VBA and I've hit a problem. I think I'm setting them right, but when I open or execute the query, it still asks for the parameters. If I enter them in the prompt, it works fine. Also, the For Each debug.print section does print both the proper parameter name and value assigned through VBA.

First is the code for the sub that's assigning the parameters and trying to open the query.

Following that is the query itself.

Thanks for any advice.

Code:
    Dim db As DAO.Database
    Dim qdf As DAO.QueryDef
    Dim strQueryName As String
    Dim rs As DAO.RecordSet
    Dim prm As DAO.Parameter

    Dim sPar1 As String, sPar2 As String
   
    Dim sFreq As String
   
    Dim dDate As Date
   
    sPar1 = "[parExamFreq]"
   
    sPar2 = "[parExamPeriod]"
   
    sFreq = "Weekly"
   
    dDate = Date

    strQueryName = "qry_Par_Start_Date_In_Range" ' Replace with your query's name

    Set db = CurrentDb
   
    Set qdf = db.QueryDefs(strQueryName)

    qdf.Parameters(sPar1).Value = sFreq

    qdf.Parameters(sPar2).Value = dDate
   
    Set rs = qdf.OpenRecordset(dbOpenDynaset)

    For Each prm In qdf.Parameters
        'Now you can access properties of each parameter, like its Name and Value
        Debug.Print "Parameter Name: " & prm.Name
        Debug.Print "Parameter Value: " & prm.Value
    Next prm

    'db.Execute strQueryName

    DoCmd.OpenQuery strQueryName, acViewNormal
   'DoCmd.OpenQuery qdf.Name, acViewNormal


    If Not rs.EOF Then
        rs.MoveFirst
        Do While Not rs.EOF
            Debug.Print "Equipment ID: " & rs!EquipmentID
            rs.MoveNext
        Loop
    End If

    ' Close the recordset and clean up objects
    rs.Close
    Set rs = Nothing
    Set qdf = Nothing
    Set db = Nothing


Query

SQL:
SELECT
    tblEquipment.EquipmentID,
    (
        DatePart("yyyy", [tblEquipment].[StartOfServiceDate]) * 1000
    ) + DatePart("ww", [tblEquipment].[StartOfServiceDate]) AS StartDate
FROM
    tblEquipment
WHERE
    ((([parExamFreq]) = "Weekly"))
GROUP BY
    tblEquipment.EquipmentID,
    (
        DatePart("yyyy", [tblEquipment].[StartOfServiceDate]) * 1000
    ) + DatePart("ww", [tblEquipment].[StartOfServiceDate])
HAVING
    (
        (
            (
                (
                    DatePart("yyyy", [tblEquipment].[StartOfServiceDate]) * 1000
                ) + DatePart("ww", [tblEquipment].[StartOfServiceDate])
            ) <= fExamPeriod ([parExamPeriod], "Weekly")
        )
    );
 
Debug.Print qdf.sql
I would not expect to use double quotes in the parameters, just their values.
 
Leave out the brackets in the parameter name string.

Code:
    sPar1 = "parExamFreq"
  
    sPar2 = "parExamPeriod"
 
Debug.Print qdf.sql
I would not expect to use double quotes in the parameters, just their values.
I'm not sure what you mean about the double quotes. But here is the qdf.sql

SQL:
FROM tblEquipment
WHERE ((([parExamFreq])="Weekly"))
GROUP BY tblEquipment.EquipmentID, (DatePart("yyyy",[tblEquipment].[StartOfServiceDate])*1000)+DatePart("ww",[tblEquipment].[StartOfServiceDate])
HAVING ((((DatePart("yyyy",[tblEquipment].[StartOfServiceDate])*1000)+DatePart("ww",[tblEquipment].[StartOfServiceDate]))<=fExamPeriod([parExamPeriod],"Weekly")));

Leave out the brackets in the parameter name string.

Code:
    sPar1 = "parExamFreq"
 
    sPar2 = "parExamPeriod"

I had tried that in the past, and it does the exact same thing. I just ran it again to be sure, and it still prompts for the parameters.
 
Try defining the parameters at the top of your query.

Code:
PARAMETERS [parExamFreq] Text ( 255 ), [parExamPeriod] Text ( 255 )
SELECT
    tblEquipment.EquipmentID,
    (
        DatePart("yyyy", [tblEquipment].[StartOfServiceDate]) * 1000
    ) + DatePart("ww", [tblEquipment].[StartOfServiceDate]) AS StartDate
FROM
    tblEquipment
WHERE
    ((([parExamFreq]) = "Weekly"))
GROUP BY
    tblEquipment.EquipmentID,
    (
        DatePart("yyyy", [tblEquipment].[StartOfServiceDate]) * 1000
    ) + DatePart("ww", [tblEquipment].[StartOfServiceDate])
HAVING
    (
        (
            (
                (
                    DatePart("yyyy", [tblEquipment].[StartOfServiceDate]) * 1000
                ) + DatePart("ww", [tblEquipment].[StartOfServiceDate])
            ) <= fExamPeriod ([parExamPeriod], "Weekly")
        )
    );

I am a bit confused by what you are trying to accomplish with this query.

([parExamFreq]) = "Weekly")

The query will only return results if you pass it "Weekly", so why open it if you know before had it will return nothing?
 
Try defining the parameters at the top of your query.

Code:
PARAMETERS [parExamFreq] Text ( 255 ), [parExamPeriod] Text ( 255 )
SELECT
    tblEquipment.EquipmentID,
    (
        DatePart("yyyy", [tblEquipment].[StartOfServiceDate]) * 1000
    ) + DatePart("ww", [tblEquipment].[StartOfServiceDate]) AS StartDate
FROM
    tblEquipment
WHERE
    ((([parExamFreq]) = "Weekly"))
GROUP BY
    tblEquipment.EquipmentID,
    (
        DatePart("yyyy", [tblEquipment].[StartOfServiceDate]) * 1000
    ) + DatePart("ww", [tblEquipment].[StartOfServiceDate])
HAVING
    (
        (
            (
                (
                    DatePart("yyyy", [tblEquipment].[StartOfServiceDate]) * 1000
                ) + DatePart("ww", [tblEquipment].[StartOfServiceDate])
            ) <= fExamPeriod ([parExamPeriod], "Weekly")
        )
    );

I am a bit confused by what you are trying to accomplish with this query.

([parExamFreq]) = "Weekly")

The query will only return results if you pass it "Weekly", so why open it if you know before had it will return nothing?
The query, originally, had more options. But with it having trouble, I paired it down to try to eliminate variables on what the issue could be. If I can get this to work, I'll just add the other options back in.
 
The query, originally, had more options. But with it having trouble, I paired it down to try to eliminate variables on what the issue could be. If I can get this to work, I'll just add the other options back in.
so you are saying

([parExamFreq]) = "Weekly")

will not exist in your final query?


I would think something like

([tblEquipment].[ExamFreq] =[parExamFreq])

would be more likely.
 
so you are saying

([parExamFreq]) = "Weekly")

will not exist in your final query?


I would think something like

([tblEquipment].[ExamFreq] =[parExamFreq])

would be more likely.

This is the full query.


SQL:
SELECT tblEquipment.EquipmentID
FROM tblEquipment
WHERE ((([parExamFreq])="Weekly") AND (((DatePart("yyyy",[tblEquipment].[StartOfServiceDate])*1000)+DatePart("ww",[tblEquipment].[StartOfServiceDate]))<=fExamPeriod([parExamPeriod],"Weekly"))) OR ((([parExamFreq])="Bi-Weekly") AND (((DatePart("yyyy",[tblEquipment].[StartOfServiceDate])*1000)+Round((DatePart("ww",[tblEquipment].[StartOfServiceDate])\2)+0.04))<=fExamPeriod([parExamPeriod],"Bi-Weekly"))) OR ((([parExamFreq])="Monthly") AND (((DatePart("yyyy",[tblEquipment].[StartOfServiceDate])*1000)+DatePart("m",[tblEquipment].[StartOfServiceDate]))<=fExamPeriod([parExamPeriod],"Monthy"))) OR ((([parExamFreq])="Quarterly") AND (((DatePart("yyyy",[tblEquipment].[StartOfServiceDate])*1000)+DatePart("q",[tblEquipment].[StartOfServiceDate]))<=fExamPeriod([parExamPeriod],"Quarterly")))
GROUP BY tblEquipment.EquipmentID;
 
So did adding the defined parameters help?
Adding line breaks makes it much easer to see what you are doing.

Code:
PARAMETERS [parExamFreq] Text ( 255 ), [parExamPeriod] Text ( 255 );
SELECT tblEquipment.EquipmentID
FROM tblEquipment
WHERE ((([parExamFreq])="Weekly")
  AND (((DatePart("yyyy",[tblEquipment].[StartOfServiceDate])*1000)+DatePart("ww",[tblEquipment].[StartOfServiceDate]))
       <=fExamPeriod([parExamPeriod],"Weekly")))
  OR ((([parExamFreq])="Bi-Weekly")
 AND (((DatePart("yyyy",[tblEquipment].[StartOfServiceDate])*1000)+Round((DatePart("ww",[tblEquipment].[StartOfServiceDate])\2)+0.04))
    <=fExamPeriod([parExamPeriod],"Bi-Weekly")))
  OR ((([parExamFreq])="Monthly")
 AND (((DatePart("yyyy",[tblEquipment].[StartOfServiceDate])*1000)+DatePart("m",[tblEquipment].[StartOfServiceDate]))
    <=fExamPeriod([parExamPeriod],"Monthy")))
  OR ((([parExamFreq])="Quarterly")
 AND (((DatePart("yyyy",[tblEquipment].[StartOfServiceDate])*
    1000)+DatePart("q",[tblEquipment].[StartOfServiceDate]))<=fExamPeriod([parExamPeriod],"Quarterly")))
GROUP BY tblEquipment.EquipmentID;

ps.
You can get rid of the function call
fExamPeriod([parExamPeriod],"Weekly")
by passing it's value as a parameter.
 
Here is how I have seen parameters populated
 
So did adding the defined parameters help?
Adding line breaks makes it much easer to see what you are doing.

Code:
PARAMETERS [parExamFreq] Text ( 255 ), [parExamPeriod] Text ( 255 );
SELECT tblEquipment.EquipmentID
FROM tblEquipment
WHERE ((([parExamFreq])="Weekly")
  AND (((DatePart("yyyy",[tblEquipment].[StartOfServiceDate])*1000)+DatePart("ww",[tblEquipment].[StartOfServiceDate]))
       <=fExamPeriod([parExamPeriod],"Weekly")))
  OR ((([parExamFreq])="Bi-Weekly")
 AND (((DatePart("yyyy",[tblEquipment].[StartOfServiceDate])*1000)+Round((DatePart("ww",[tblEquipment].[StartOfServiceDate])\2)+0.04))
    <=fExamPeriod([parExamPeriod],"Bi-Weekly")))
  OR ((([parExamFreq])="Monthly")
 AND (((DatePart("yyyy",[tblEquipment].[StartOfServiceDate])*1000)+DatePart("m",[tblEquipment].[StartOfServiceDate]))
    <=fExamPeriod([parExamPeriod],"Monthy")))
  OR ((([parExamFreq])="Quarterly")
 AND (((DatePart("yyyy",[tblEquipment].[StartOfServiceDate])*
    1000)+DatePart("q",[tblEquipment].[StartOfServiceDate]))<=fExamPeriod([parExamPeriod],"Quarterly")))
GROUP BY tblEquipment.EquipmentID;

ps.
You can get rid of the function call
fExamPeriod([parExamPeriod],"Weekly")
by passing it's value as a parameter.

Adding the defined parameters did not. It still asks for the parameters again.

As far as getting rid of the function call... How do I figure out the value of the function without calling it?
 
Adding the defined parameters did not. It still asks for the parameters again.

As far as getting rid of the function call... How do I figure out the value of the function without calling it?

A 2nd look at your function, you opened the query 2 times, the 2nd time without providing values for the parameters.

1st time as a record set with the parameters pre-filled.
Set db = CurrentDb
Set qdf = db.QueryDefs(strQueryName)
qdf.Parameters(sPar1).Value = sFreq
qdf.Parameters(sPar2).Value = dDate
Set rs = qdf.OpenRecordset(dbOpenDynaset)

2nd time directly to view
DoCmd.OpenQuery strQueryName, acViewNormal
 
A 2nd look at your function, you opened the query 2 times, the 2nd time without providing values for the parameters.

1st time as a record set with the parameters pre-filled.
Set db = CurrentDb
Set qdf = db.QueryDefs(strQueryName)
qdf.Parameters(sPar1).Value = sFreq
qdf.Parameters(sPar2).Value = dDate
Set rs = qdf.OpenRecordset(dbOpenDynaset)

2nd time directly to view
DoCmd.OpenQuery strQueryName, acViewNormal

So you cannot open it to view with the parameters already filled out? You have to do it as a recordsource or like as a recordset of a form? Because getting rid of the 'Set rs =' line doesn't make it work.
 
So you cannot open it to view with the parameters already filled out? You have to do it as a recordsource or like as a recordset of a form? Because getting rid of the 'Set rs =' line doesn't make it work.
Those are 2 independent instances of the same query; setting parameters in 1 instance has no affect on another.
 
This should work using temp vars.

Code:
Dim db As DAO.Database
    Dim qdf As DAO.QueryDef
    Dim strQueryName As String
    Dim rs As DAO.RecordSet
    Dim prm As DAO.Parameter
    Dim sFreq As String
    Dim dDate As Date
 
    sFreq = "Weekly"
    dDate = Date

    TempVars![parExamFreq] = sFreq
    TempVars![parExamPeriod] = sDate

    strQueryName = "qry_Par_Start_Date_In_Range" ' Replace with your query's name

    Set db = CurrentDb
    Set rs = qdf.OpenRecordset(dbOpenDynaset)

    DoCmd.OpenQuery strQueryName, acViewNormal

    If Not rs.EOF Then
        rs.MoveFirst
        Do While Not rs.EOF
            Debug.Print "Equipment ID: " & rs!EquipmentID
            rs.MoveNext
        Loop
    End If

    ' Close the recordset and clean up objects
    rs.Close
    Set rs = Nothing
    Set qdf = Nothing
    Set db = Nothing

Code:
SELECT tblEquipment.EquipmentID
FROM tblEquipment
WHERE ((([TempVars]![parExamFreq])="Weekly")
  AND (((DatePart("yyyy",[tblEquipment].[StartOfServiceDate])*1000)+DatePart("ww",[tblEquipment].[StartOfServiceDate]))
       <=fExamPeriod([TempVars]![parExamPeriod],"Weekly")))
  OR ((([TempVars]![parExamFreq])="Bi-Weekly")
 AND (((DatePart("yyyy",[tblEquipment].[StartOfServiceDate])*1000)+Round((DatePart("ww",[tblEquipment].[StartOfServiceDate])\2)+0.04))
    <=fExamPeriod([TempVars]![parExamPeriod],"Bi-Weekly")))
  OR ((([TempVars]![parExamFreq])="Monthly")
 AND (((DatePart("yyyy",[tblEquipment].[StartOfServiceDate])*1000)+DatePart("m",[tblEquipment].[StartOfServiceDate]))
    <=fExamPeriod([TempVars]![parExamPeriod],"Monthy")))
  OR ((([TempVars]![parExamFreq])="Quarterly")
 AND (((DatePart("yyyy",[tblEquipment].[StartOfServiceDate])*
    1000)+DatePart("q",[tblEquipment].[StartOfServiceDate]))<=fExamPeriod([TempVars]![parExamPeriod],"Quarterly")))
GROUP BY tblEquipment.EquipmentID;
 
Last edited:
You can also lean up your code like...
Code:
Sub YourCode_Simplified()
    ShowData GetRecordset
End Sub

Private Function GetRecordset() As DAO.Recordset
    With CurrentDb.QueryDefs("qry_Par_Start_Date_In_Range")
        .Parameters("[parExamFreq]") = "Weekly"
        .Parameters("[parExamPeriod]") = Date
        Set GetRecordset = .OpenRecordset(dbOpenDynaset)
    End With
End Function

Private Sub ShowData(rst As DAO.Recordset)
    With rst
        Do While Not .EOF
            Debug.Print "Equipment ID: " & !EquipmentID
            .MoveNext
        Loop
        .Close
    End With
End Sub
 
So how do I set the parameters so that when I have (as an example) DoCmd.OpenQuery "QueryName", acViewNormal it does not prompt for the parameters?

That is the question I'm trying to get answered.

If that is not possible, fine, I'll figure out alternatives. I'm not just trying to solve this problem, I'm trying to learn the ways to do things.
 
So how do I set the parameters so that when I have (as an example) DoCmd.OpenQuery "QueryName", acViewNormal it does not prompt for the parameters?

That is the question I'm trying to get answered.

If that is not possible, fine, I'll figure out alternatives. I'm not just trying to solve this problem, I'm trying to learn the ways to do things.
The easiest is with temp vars per my example in post #15. You will always need to pre-fill the temp vars before opening a query referencing a temp var.
 
Your function could be as simple as this.

Code:
    Dim strQueryName As String

    TempVars![parExamFreq] = "Weekly"
    TempVars![parExamPeriod] = Date

    strQueryName = "qry_Par_Start_Date_In_Range" e

    with CurrentDb
    with .QueryDefs(strQueryName)
    with .OpenRecordset(dbOpenDynaset)
    If Not .EOF Then
        .MoveFirst
        Do While Not .EOF
            Debug.Print "Equipment ID: " & .Fields("EquipmentID")
            .MoveNext
        Loop
    End If
    .Close
    End With
    End With
    End With
    DoCmd.OpenQuery strQueryName, acViewNormal
 
So how do I set the parameters so that when I have (as an example) DoCmd.OpenQuery "QueryName", acViewNormal it does not prompt for the parameters?
Almost invariably I would use controls in a form, which could be a bound form or an unbound dialogue form, as each parameter. You can either enter the values into the controls manually or assign them with code. The important thing is that the form is open and the values have been inserted into the controls before calling the OpenQuery method. Parameters can be made optional by testing each for IS NULL in a parenthesized OR operation. The following query, in this case used as a report's RecordSource, is an example in which the query's result table can be restricted by City and/or Employer by referencing two controls in a dialogue form as parameters:

SQL:
SELECT [FirstName] & " " & [LastName] AS FullName, Address, City, Region,
Country, Employer, LastName, FirstName, Contacts.ContactID
FROM (Countries INNER JOIN Regions ON Countries.CountryID = Regions.CountryID)
INNER JOIN (Employers INNER JOIN ((Cities INNER JOIN Contacts
ON Cities.CityID = Contacts.CityID) INNER JOIN ContactEmployers
ON Contacts.ContactID = ContactEmployers.ContactID)
ON Employers.EmployerID = ContactEmployers.EmployerID)
ON Regions.RegionID = Cities.RegionID
WHERE (Cities.CityID = Forms!frmReportDialogue!cboCity
    OR Forms!frmReportDialogue!cboCity IS NULL)
AND (Employers.EmployerID = Forms!frmReportDialogue!cboEmployer
    OR Forms!frmReportDialogue!cboEmployer IS NULL);

If necessary the controls can be hidden by setting their Visible property to False (No) where they are assigned values in code.
 

Users who are viewing this thread

Back
Top Bottom