I've got an existing Access MDB. I'm adding a command button to an existing Form that runs an existing report. The change being made is that this button needs to pass in a parameter containing the ID of the record being reported on - currently the report runs on every record in the MDB.
I've altered the Query that the report runs on to use a parameter for the ID value, so that now when the button is clicked Access prompts for the record ID to report on, and the report displays like it should.
However, I can't for the life of me figure out how to pass a parameter into the report for the query to use. How can I do this?
The DoCmd.OpenReport method has various arguments, one of which is a Where statement:
DoCmd.OpenReport"rptReport", acViewPreview,,"ID=" & Me.ID
That is
expression.OpenReport(ReportName, View, FilterName, WhereCondition, WindowMode, OpenArgs)
My general approach to this type of problem is to save the criteria in the database, typically a control table that has one row. Then to reference your criteria you put a query in paranthesis that returns one value, of the criteria you want. In your case, it would be something like:
(select reportID from control)
The advantage of this techinque is that the control table remembers the settings for the next time you run the report. Of course, ReportID would be tied to a field in a form. I also like the fact that your queries are isolated from forms; they can be run independently of forms.
The Where clause of the docmd.openreport is a string that uses the same format as the where clause in a SQL statement.
The reason to put parameterize you query at the docmd instead of the RecordSource of the report is flexibility. You may have a need to open the report without any paremeter/return all the records or have the ability to filter on different fields.
Why everyone wants to make this so complicated, I don't know.
save your report's recordsource without parameters.
as suggested by Remou, pass the criteria in the appropriate argument of DoCmd.OpenReport.
Trying to do it any other way is going to be a matter of resisting the natural methods for accomplishing tasks in Access.
I know this is an old post but this took me a bit. Error was "Invalid use of parren" however the issue was the space in the field name. I was creating a report from a db that someone did the common mistake, spaces.
To pass a param to a query through the where clause when the database field has a space use this example:
DoCmd.OpenReport "rptByRegionalOffice", acViewPreview, , "[" & "Regional Office" & "]" & "=" & "'" & cmboOffices.Value & "'"
If you think about this you can see that this will produce where [Regional Office]='string value' just as you would expect in access sql.
Related
I recently posted this answer as a way to get user input when creating a MS Access query or report. The general behaviour is that if an undeclared variable is placed in SQL query code or a report (e.g. [UndeclaredVariable]), a small input/dialog box appears for the user to input the variables value.
I have been unable to find any mention of this functionality in documentation or elsewhere. All discussion is about using InputBox() in the standard way.
This functionality is unexpected/unusual for several reasons:
(In my limited knowledge) Using undeclared variables in MS Access generally causes an error
The input/dialog box is different than the one created when InputBox() is used
The functionality seems to transcend standard behavior (e.g. when an two undeclared variable are used in this way as the "ifTrue" and "ifFalse" components of an IIf() statement, BOTH dialog boxes are created sequentially!)
Does anyone know what this functionality is called or why it works in these ways?
To summarize the above comments:
the behavior is called a "parameter query" and is like normal parameterized queries (see here)
The behavior with IIf() is because Access requires a parameter to be given whether or not the value is used (in this case for both [ifTrue] and [ifFalse])
There seems to be no way to conditionally parameterize a query or report
Ok, as to why they work the way they do? Well a lot of people use Access for just working with data tables. They don't necessary build forms and reports. So, if you place a [parm] box in a query, it will prompt you, and you don't need code. So, a really handy feature.
And of course if you do build a report, and need a quick and dirty way to prompt for some criteria then once again, super handy, and again no code or forms need be written.
And if you do create a form, then you can place criteria in a query like this:
select * from tblCustomers where City = Forms!MyPromptForm!City
once again, no code. And using a forms! expression like above means no prompt when you run the query (or a report based on that query).
The only real downside of using these parameters is they are not without effort to make them optional.
As you are finding out, putting forms! expression in queries can get really messy real fast. And such queries can prompt you when you don't want to.
Even worse, is now that the query is now "married" and attached to that ONE form (if you use forms! expressions for parameters). Often, I have a nice query that I could use MANY times for different reports, and often even that same query could be used for reports...but then someone comes along and puts in a expression or paramter(s) that means the query is ONLY good when that form is opened, or you get nasty prompts for some parameter that you now don't want. Or you want DIFFERENT criteria on a different column.
So hard coding the number of parameters in such a query is REALLY painful, not flexible, and really starts to fall down.
So, if you have 5 combo boxes on a form, but the user only selects restrictions in 3 of the combo boxes...and wants the other 2 to be ignored?
I could probably write another 10 or pages as to why putting forms expressions in queries or shoving in parameters is bad (besides...it makes the queries real ugly, and hard to read. and, the sql then is not standard anymore (it will not work with server based systems either).
So, the solution use now is simply to take the values from the form, and build your own where clause in code. That way, you simply design the reports (or forms), and attached them to the query, BUT NO FORMS! conditions are placed in the query. And the SQL is clean without garbage in it.
To "send" the conditions to the report (or form), you simply use the "where" clause. This is exactly why ms-access has this featureā¦and it solves a zillion problemsā¦and will reduce your development costs by a substantial amount.
Take a look at the following screen shots to see what I mean:
So in above we have a start date, and end date. And the user can select 1, or several tours and THEN click on the report view button. Trying to deal with a easy and clean "prompt" form for user and THEN attempt to use a query with parmaters is sheer folly.
The code to make those above screens work and launch the report with the selected restrictions when you hit the "print" button is easy:
Or take this screen:
So in the above we have a combo box to select the sales rep.
But, you can leave it blank.
So, code to deal with above will work like this:
dim strWhere as string
'select sales rep combo
if isnull(cboSalesRep) = false then
strWhere = "SalesRep = " & cboSalesRep & ""
end if
' select "status" for the report
if isnull(lstStatus) = false then
if strWhere <> "" then
strWhere = strWhere " and "
end if
strWhere = strWhere & "Status = '" & litStatus & "'"
end if
Note how the 2nd list box is checked for a value. You can add as "many" more conditions you want. Lets say we have a check box to only include Special Customers. We can add to our very nice prompt screen a check box to
[x] Show Only Special customers
The code we add would be:
if chkSpeicalOnly = True then
if strWhere <> "" then
strWhere = strWhere " and "
endif
strWhere = strWhere & "SpecialCust = true"
end if
For sure, each combo and control we add to the nice report screen takes a bit of code, but no more messy then the query builder..and this way, each query is nice and clean, and free of a bunch of HIGHLY un-maintainable forms! expressions or "optional" paramters.
Further, it means you can re-use the same query for different reports, and have no worries about some form that is supposed to be open or some nasty out of the blue prompt for a parameter. So, a tiny bit more code eliminates the messy query problem.. For me, this is very worth while trade.
So parameters are quick and dirty. But if REALLY going to start building a decent user interface and some nice report prompt forms? Dump the use of parameters - you be glad you did. And you only have to go to the ONE code spot, add another code block for a new and optional critera. You don't have to change the report, and and you don't have to go and modify the SQL either. So, a bit of code goes a LONG way to attacking this problem.
At the end of your code, we now have a valid SQL where clause. So, now just launch the report with with this:
Docmd.OpenReport "ReportName",acViewPreview,,strWhere
And the above also works for searching and launching a form. So the form can be based on such queries, and again no prompts or paramters means the form can be used to edit that data.
So the concept of filter data and launching forms (or reports) can and should be detached from the concept of some query that pulls data from a table. Over time, software will change, and then the boss will ask how about a filter or prompt for invoice number, but that again has to be optional. Over time your business rules will change. And you can often apply that filter to "many" reports. So in this form, the critea is built up, but the list box allows you to select one of "many" reports, and not all are based on the same SQL, but they all accept the same "filter" or better term used is the "where" clause of the open report or form command.
In above, the user can hold down the ctrl-key to select 1 or 2 or hit the "select all" button. In that form, the user is actually selecting the bus tour ID for a given tour. And then they can choose the report in the lower left. Again, attempting to acheive the above multiple critera simply can't work with sql paramets anyway.
I am using a TourID = some value and Busid in (LIST OF buses selected).
once again, you can simply pass that complex "where" clause to the report - and that where clause can even have a sub-query, or a Field in (LIST OF ID'S) criteria (which can't be done with parameters anyway).
I have a simple database I am developing in MS Access 2010 where I have a form with a "view specific" command button and a "view all" command button. Both buttons will run a query: the specific one should apply a criteria to one of the fields, and the all one should run the query with no criteria, or with a * criteria in that field. There is another field that requires criteria for both queries, so essentially the specific button should run a query with two criteria and the all button should run a query with one criteria (or one and an * criteria). The query is a stored query I created via Design View. The "all" SQL statement is something to the effect of:
SELECT tableA.field1, tableA.field2, tableB.field1, tableB.field2
FROM tableA INNER JOIN tableB ON tableA.field3=tableB.field2
WHERE tableB.field1=True;
I want the specific query to run based off of an option chosen in a combo box on the form, so it's SQL statement should look the same, except the WHERE clause would change to:
WHERE tableB.field1=True AND tableB.field2=Forms!ViewQryResults!comboSelectSpecific;
Problem
My problem is that the specific query, I'll call it Query2, works as intended, but the all query, Query1, doesn't change the results viewed on the form. Neither query throws an error message, and it seems that the query is running again as the record total at the bottom of the screen goes away, and then comes back after the query finishes and gets a total number of records again.
Attempted Solutions
I have tried multiple different solutions to attempt to get it to work, none of which have.
I first tried to establish a parameter, but then Access prompts the user for the parameter value as soon as the form opens, which I do not want. If I simply declare the parameter using the parameter button in the ribbon in design view for the query, but do not assign it to a field as a criterion in the design grid, Access no longer prompts me for the parameter value, and I can assign its value via VBA, but then I do not know how to assign the parameter to a field criteria using VBA. My attempts throw errors that say Access doesn't recognize the name of my parameter.
I then tried altering the SQL string for the query and then requerying. I used text manipulation functions to find the WHERE clause, and replace it with a WHERE clause that has both criteria, then requeryed. To determine the proper context for the SQL string, I changed the query in Design View to do what I wanted, and then switched to SQL View and copied the SQL string that Access created to represent the query.
I then inserted a Debug.Print line to print the SQL string at each step, and compared them character by character and they match exactly, meaning the text manipulation is doing what it should be doing and creating the SQL strings correctly, or at least as Access would if I wasn't messing with them at all. I tried this from both directions, i.e. I made the stored query in the way it should be for one button, and then used code to change it for the other button, and then swapped, but neither method was successful in getting both queries to work. The basic code I tried for manipulating the SQL string is as follows:
Private Sub Query2_OnClick()
Dim d As Database
Dim q As Query
Dim strSQL As String
Dim strSQLSelectFrom As String
Dim strSQLWhereNew As String
Set d = CurrentDb
Set q = d.QueryDefs("Query2")
strSQL = q.SQL 'Saves original SQL statement
'Text Manipulations to create strSQLSelectFrom as just the SELECT and FROM portions
strSQLWhereNew = "tableB.field1=True AND tableB.field2=Forms!ViewQryResults!comboSelectSpecific;"
q.SQL = strSQLSelectFrom & strSQLWhereNew
DoCmd.Requery
Me.Refresh
Debug.Print q.SQL 'Verify text manipulations created SQL String I expect
q.SQL = strSQL 'Returns SQL to original statement
Debug.Print q.SQL 'Verify SQL statement properly returned to original statement
End Sub
This arrangement works to allow me to query specifics based on my combo box. When I click the other button, whose code just does a requery because the first button should reset SQL to the way it was, the results do not change. The query appears to run as indicated by the total records counter going away and coming back, but it never changes the results. If I go back and choose another option from my combo box, and query specific, the results update to the new specific selection.
Again, if I click the All Query button, the results remain based on the combo box selection. If I change the combo box selection, and then click All Query (which shouldn't care at all about the combo box because it isn't listed anywhere in the code for that button), the results change to the new selection, like both buttons are running specific queries. That part is the most puzzling, I can figure out why it is doing that.
I know a simple solution would be just to create a second query and stop trying to change one back and forth, but I really feel I am missing a fundamental piece that I am going to need to understand at some point, so I am really looking for that fundamental piece that will make this work.
IIUC - Simply change the form's RecordSource to point to needed saved query with .Requery:
Private Sub ViewAll_OnClick()
Me.Form.RecordSource = "Query1"
Me.Requery
End Sub
Private Sub ViewSpecific_OnClick()
Me.Form.RecordSource = "Query2"
Me.Requery
End Sub
Alternatively, you can keep the same query recordsource and filter form using DoCmd.ApplyFilter, assuming criteria controls are on same form requiring filtering. Any valid SQL WHERE clause can be used in second argument and even dynamically created.
DoCmd.ApplyFilter , "field1 = True AND field2 = '" & Forms!ViewQryResults!comboSelectSpecific & "'"
And to remove filter:
DoCmd.RunCommand acCmdRemoveAllFilters
I am trying to build the front end for a Mysql database application using linked tables in MS Access. Currently, I have a button on a form which executes a query that allows the user to search for records by a person's name. On the form, there is a subform which displays the results of the executed query.
My problem is that whenever I open the form, the subform only displays the query results for the first time the query is executed. If I try to search for another name, it will open the results set in a separate sheet and not update my subform.
How can I get the subform to update on every search?
Disclaimer: I am new to Access and do not know any VBA code.
Query:
SELECT employees.FNAME, employees.LNAME, access.NAME, access.USERNAME, access.CREATED_BY, access.ACCESS_GRANTED, access.ACCESS_TERMINATED, access.ADMIN
FROM employees INNER JOIN access ON EMPLOYEES.ID = ACCESS.ID
WHERE (((employees.FNAME) Like "*" & Forms![Form1]!FNameTxt & "*"));
Picture of my form after query with name "chase" is executed
I never use dynamic parameterized query. I would use VBA code to set Filter and FilterOn properties, like:
Me.Filter = "[FName] LIKE '*" & Me.cbxFNames & "*'"
Me.FilterOn = True
If you prefer dynamic parameterized query the VBA would be: Me.Requery
If code is behind the main form then need to reference subform through container control. Recommend giving the container control a name different from the object it holds, like ctrEmps
Me.ctrEmps.Requery
The real trick is figuring out what event to put code into.
I am not able to encode any entries to the Sub-form data grid on the Main form when I inserted the following SQL field. If I remove this column, the system allows me to the new data record creation. Can anyone look into this issue please!
Advance Payment Balance:
(SELECT SUM(NZ(T1.AdvancePayment,0)-
NZ(([GrossInv-WorksCertified-61110]*
[SubCon-BasicInfo].[Advance-409130-%]/100),0))
FROM [InvoiceMaster] AS T1
WHERE T1.[SubConName]=[InvoiceMaster].[SubconName]
AND T1.[ID]<=[InvoiceMaster].[ID])
Using calculations in a query make the underlying recordset not updateable.
See this question for an excellent list why queries (and forms based on them) sometimes are not updateable.
The proper way to include calculations on a datasheet form is to open it in design view, add a new text box control to them, and set the controls control source equal to an = equal sign followed by your calculation.
You also will need to rewrite the subquery to a domain aggregate or use a combo box to use a query.
Rewrite example:
DSUM("NZ(InvoiceMaster.AdvancePayment,0)- NZ(([GrossInv-WorksCertified-61110]*[SubCon-BasicInfo].[Advance-409130-%]/100),0)", "InvoiceMaster", "[SubConName] = """ & [InvoiceMaster].[SubconName] & """ AND ID = " & [InvoiceMaster].[ID])
I guess this is a silly question, but I'm having problems figuring this out.
I have two tables with loads of information used to make reports.
I have a query that joins these two tables.
The same query adds two simple filters: A date range and an ID checker.
The reports are supposed to be printed withing a date range with a specific ID.
Every time I need to change the query data range I need to manually edit it and change the parameters.
How can I make a form and pass this information to the query so I won't have to manually update the query every week?
I made a new form with two date fields and I would need some code to pass this information to the query before opening it, but DoCmd.OpenQuery Method doesn't permit I pass any information.
Ideally I'd prefer to use a SQL command to set the query and then open it, is this even possible?
Actually, I am using this method often:
Declare variables in a Module and write a function for each one that simply returns the value. You can then use the function call within the Query-Designer (e. g. criteria = Between getMyValue1() AND getMyValue2())
You can then set the global variables before opening the query.
(This has worked better for me than Query-Parameters or direct references to form fields within queries.)
You could also put a condition in your query that refers to a field in your form:
SELECT ... WHERE ID = [Forms]![FormName]![TextField]
Open the report with a filter:
Dim sWhere as String
sWhere = "Tbl_Swift.Data >= #10/01/2012# AND Tbl_Swift.Data <= #10/10/2012#"
DoCmd.OpenReport "rptMyReportName", acViewPreview, ,sWhere
(I'm not sure if "BETWEEN" will work or not, although I think it should if you'd write it properly.)
You have two options.
Do not put values of parameters in the query. Access will always ask for these values on every execution of query.
use DATE() function to get the current date and calculate the week start and end accordingly. This way, you will never have to provide the date.