MS Access: Custom report parameterization with tempvars - ms-access

This report image shows a report which should open with tempVars set in place from a couple controls on a form which gets those values and therefore, assigns those to the named vars in the image. Currently, the WHERE clause is not working, some parameters do not match or are not getting the variables they should to read and therefore, open a report with the specified information in the WHERE condition clause. How might the where condition be modified to get the parameters to work?
(as you can see I erased some information to make is simpler.)
'------------------------------------------------------------
' Expirig_Click
'
'------------------------------------------------------------
Private Sub Expirig_Click()
On Error GoTo Expirig_Click_Err
DoCmd.OpenReport "Expiring", acViewPreview, "", "[DuesExpire]=[TempVars]![tempExpirationDate] And [Type]=[TempVars]![tempType]", acNormal
TempVars.Add "tempType", Combo164
TempVars.Add "tempExpirationDate", CutoffDate
DoCmd.OpenReport "Expiring", acViewReport, "", "[DuesExpire]=[TempVars]![tempExpirationDate] And [Type]=[TempVars]![tempType]", acNormal
Expirig_Click_Exit:
Exit Sub
ExpirigLabels_Click_Err:
MsgBox Error$
Resume Expirig_Click_Exit
End Sub

Use VBA variables instead of TempVars, and take them out of the constant WHERE string. Like this:
Dim myDate As Date
Dim myType As String
myDate = CutoffDate
myType = Combo164
DoCmd.OpenReport "Expiring", acViewPreview, , _
"[DuesExpire] = #" & Format(myDate, "mm\/dd\/yyyy") & "# AND [Type] = '" & myType & "'"
If Type is not string but number, it's simply [Type] = " & myType without the '
Filtering for dates in Access SQL needs a special format: = #mm/dd/yyyy#
Format(myDate, "mm\/dd\/yyyy") is only needed, if your regional settings have a date format different than mm/dd/yyyy (i.e. if you're not in the US)

Related

How To Pass a Filter Property to a Report AND Add More Criteria to that Filter (Access)

I'm currently running Access 2007. I have a reporting manager that allows for the user to set parameters. Customize dates and allows for selecting what date field needs to be modified (timecreated, timemodified, txndate). The reporting aspect works perfectly.
Within the report (totalshipped), the user can double click the body of the report and it'll go from "big picture" summary to a detailed report (totalshippeddetailed).
Basically in order for it to work properly, the dates from totalshipped and the customer name from the body (on double click) need to match in the totalshippeddetailed report when it opens. Here is an example of what I've tried:
Private Sub ftrReport_DblClick(Cancel As Integer)
DoCmd.OpenReport "TotalShippedDetailed", acViewReport, "", me.filter
End Sub
The report successfully opens up and passes the filter property (dates) onto the totalshipped detailed report, the problem is that I need to reference the [customerref_fullname] (customer) as well which I was doing by using this line:
[reports]![TotalShipped]![customerref_fullname] = [customerref_fullname]
This works as a reference to the customer but I need to combine the me.filter property with the reference to the customerref_fullname, an error occurs when I try:
Private Sub ftrReport_DblClick(Cancel As Integer)
DoCmd.OpenReport "TotalShippedDetailed", acViewReport, "", me.filter & _
[reports]![TotalShipped]![customerref_fullname] = [customerref_fullname]
End Sub
Another way I tried it which works but doesn't allow the detailed version the report to be filtered by anything but the [txndate] :
DoCmd.OpenReport "TotalShippedDetailed", acViewReport, "", _
"[reports]![TotalShipped]![customerref_fullname] = [customerref_fullname] and [txndate] >= [forms]![frmrptdatemanager]![txtstartdate] And [txndate] <= [forms]![frmrptdatemanager]![txtenddate] "
And lastly I took the above code and tried to reference the date field itself in the form which will give an error:
DoCmd.OpenReport "TotalShippedDetailed", acViewReport, "", _
"[reports]![TotalShipped]![customerref_fullname] = [customerref_fullname] and [forms]![frmrptdatemanager]![cboDateField] >= [forms]![frmrptdatemanager]![txtstartdate] And [forms]![frmrptdatemanager]![cboDateField] <= [forms]![frmrptdatemanager]![txtenddate] "
There are many more examples I've tried but none of them can accomplish my goal: allow the users to double click the body of the report to see the detailed report by customer with the same date range as the main report.
Please helP!!!!
Remember that the filter parameter is like a WHERE clause without the WHERE keyword at the front of it.
What you're doing here:
DoCmd.OpenReport "TotalShippedDetailed", acViewReport, "", me.filter & _
[reports]![TotalShipped]![customerref_fullname] = [customerref_fullname]
You're taking the existing filter condition and adding to it, but you didn't include an AND keyword to link the current filter condition and the next condition.
You would need to do:
DoCmd.OpenReport "TotalShippedDetailed", acViewReport, "", me.filter & _
" AND [reports]![TotalShipped]![customerref_fullname] = '" & [customerref_fullname] & "'"
Notice there, also, that you have to concatenate the variable or control name into the filter string to pick up the value of the variable or control rather than the name of the variable or control. The value also has to be offset with correct punctuation when it's a string or date: single-tick quotes for string values and hash tag/pound symbols for dates.
To help develop and debug things like this, I recommend using a string variable to build up the entire filter condition. Inspecting the contents of the string variable or dumping the value to the immediate window (Debug.Print) before you use it as the filter parameter in the OpenReport method will help you catch missing ANDs, missing spaces, and missing punctuation in the filter condition.
Your DblClick method will look something like this:
Private Sub ftrReport_DblClick(Cancel As Integer)
Dim FilterCondition as String
FilterCondition = me.filter
FilterCondition = FilterCondition & " AND [txndate] >= #" & [forms]![frmrptdatemanager]![txtstartdate] & "# AND [txndate] <= #" & [forms]![frmrptdatemanager]![txtenddate] & "#"
Debug.Print FilterCondition
DoCmd.OpenReport "TotalShippedDetailed", acViewReport, "", FilterCondition
End Sub

Ms Access filter reports in runtime mode

Does anyone knows how to filter reports the right way within Access runtime mode?
The usual code with DoCmd doesn't work.
This is what I tried for the report:
Private Sub Befehl217_Click()
DoCmd.OpenReport "Tagesbericht", acViewPreview
End Sub
Private Sub Bezeichnungsfeld26_Click()
DoCmd.GoToControl "DateFilter"
DoCmd.RunCommand acCmdFilterMenu
End Sub
This didn't work. Access complained that "FilterMenu isn't available".
I tried to create a context menu but this only displayed me cut, copy and paste.
You confirmed your report includes a control named Bezeichnungsfeld26 and when the user clicks in that control, you want to bring up the filter menu for that control.
When the user clicks in that control, it has the focus, so there is no need for GoToControl. And you don't want to go to a different control if you want the user to filter on Bezeichnungsfeld26.
Disable the GoToControl line ...
Private Sub Bezeichnungsfeld26_Click()
'DoCmd.GoToControl "DateFilter"
DoCmd.RunCommand acCmdFilterMenu
End Sub
You can use the Filter property:
Me.Filter = "[YourField] = " & somevalue & ""
Me.FilterOn = True
or, to expand on your current method:
DoCmd.OpenReport "Tagesbericht", acViewPreview, , "[YourField] = " & somevalue & ""
If you filter for a date you must pass a properly formatted string expression for the date:
Dim FilterDate As Date
FilterDate = Date
DoCmd.OpenReport "Tagesbericht", acViewPreview, , "[DateFilter] = #" & Format(FilterDate, "yyyy\/mm\/dd") & "#"

How to use a function in filter string in access report?

I have a function defined as this in VBA:
Function IsInWeek(RefDate As Date, checkDate As Date) As Boolean
StartDate = StartOfWeek(RefDate)
EndDte = EndOfWeek(RefDate)
If (checkDate >= StartDate And checkDate < Enddate) Then
IsInWeek = True
Else
IsInWeek = False
End If
End Function
I want to use it inside a filter clause of a report as follow:
strFilte = "IsInWeek(#" + Format(InDate, "dd/mm/yyyy") + "#, CalanderDate)"
DoCmd.OpenReport ReportName, acViewPreview,
With Reports(ReportName)
.Filter = strFilter
.FilterOn = True
End With
But it doesn't work. The report contains all records. What is the problem and how can I solve it? I am using access 2003.
Note: I can use between to implement function on filter string, but I am looking to find why the above technique doesn't work.
Edit 1
This is not working too:
strFilte = "IsInWeek(#" + Format(InDate, "dd/mm/yyyy") + "#, [CalanderDate])= True"
If Application.CurrentProject.AllReports(reportname).IsLoaded = True Then
DoCmd.Close acReport, reportname
End If
DoCmd.OpenReport reportname, acViewDesign, strFilter
DoCmd.OpenReport reportname, acViewPreview
The DoCmd.OpenReport method takes as it's last parameter an optional filter clause. So maybe:
DoCmd.OpenReport ReportName, acViewPreview, ,"IsInWeek(#" + Format(InDate, "dd/mm/yyyy") + "#, [CalanderDate]) = True"
As far as the reason the method you tried doesn't work, I remember Access being particularly fussy with Reports (as opposed to Forms) regarding the Filter property; not sure if you can do it on the fly like that. To achieve what you are trying to do without using DoCmd.OpenReport with a filter option, I think you have to open the report in Design mode, change the property, then change to Preview mode. I remember forms being more forgiving about this, however. That's just from memory, though.
EDIT: My syntax was incorrect, have added in an extra comma between the parameters; as per http://msdn.microsoft.com/en-us/library/office/aa220304%28v=office.11%29.aspx, FilterName is the third param, WhereCondition is the fourth. I was looking for WhereCondition.

Optimize VBA code that exports to PDF from MS Access

I have two functions that will open and save two diffrent reports based on the same criteria. They are identical except for the refrences:
Function Export_MLR()
On Error GoTo Export_MLR_Err
Dim strReportName As String
DoCmd.OpenReport "Market Rate Notification Final", acViewPreview
strReportName = "S:\National Installations\Market Labor Rates\MLR_INV\MLR\" & Format (Reports![Market Rate Notification Final].Market_ID, "00") & " " & Replace(Reports![Market Rate Notification Final].Product_Code, " / ", "_") & "-" & "Market Rate Notification Final" & "_" & Format(Date, "mmddyy") & ".pdf"
DoCmd.OutputTo acOutputReport, "Market Rate Notification Final", "PDFFormat(*.pdf)", strReportName, False, , , acExportQualityScreen
DoCmd.Close acReport, "Market Rate Notification Final", acSaveNo
Export_MLR_Exit:
Exit Function
Export_MLR_Err:
MsgBox Error$
Resume Export_MLR_Exit
End Function
Then I created this function to select the data and put it into the table that the reports refrence line by line:
Function MassMarket()
On Error GoTo MassMarket_ERR
Dim db As DAO.Database
Dim rs1 As DAO.Recordset
Dim rs2 As DAO.Recordset
'this query creates my rs1 recordset'
DoCmd.SetWarnings (warningsOff)
DoCmd.OpenQuery "mass_market", acNormal, acEdit
DoCmd.SetWarnings (warningsOn)
Set db = CurrentDb()
Set rs1 = db.OpenRecordset("Mass_market_Rate_change")
Set rs2 = db.OpenRecordset("tbl_Form_Auto")
'this checks and clears any records in rs2'
If rs2.EOF = False And rs2.BOF = False Then
rs2.MoveFirst
rs2.Delete
End If
rs1.MoveFirst
'loop goes through and adds 1 line runs reports saves them and deletes line'
Do Until rs1.EOF
Set rs2 = db.OpenRecordset("tbl_Form_Auto")
rs2.AddNew
rs2![MarketID] = rs1![MarketID]
rs2![Product_ID] = rs1![Product_ID]
rs2.Update
Call Export_Invoice
Call Export_MLR
rs1.MoveNext
rs2.MoveFirst
rs2.Delete
Loop
MassMarket_Exit:
Exit Function
MassMarket_ERR:
MsgBox Error$
Resume MassMarket_Exit
End Function
Now all of this worked like a charm but it created, on average 16 .pdf files per minute and I had to create 820 .pdf files(about 50 minutes). If this is the best I can do then I will take it but would love to cut this time in half if possible. Thanks for any and all input. NR
In a comment you indicated the bulk of the time is spent in your functions which export the reports to PDF. I'm uncertain whether we can speed those up.
It seems you open a report, reference a value in that report for use as part of the PDF file name, then call the OutputTo method with the same report name to save it as PDF.
In that situation, I'm uncertain what happens "under the hood" ... whether Access opens a second instance of the report object, or is smart enough to see that you already have an instance open and just use that one instead.
As a test, try to signal Access to use the first report instance. From the online help for the ObjectName parameter of the OutputTo method:
If you want to output the active object, specify the object's type for the ObjectType argument and leave this argument blank.
So what I'm suggesting is try this in your code:
DoCmd.OutputTo acOutputReport, , "PDFFormat(*.pdf)", _
strReportName, False, , , acExportQualityScreen
If Access complains, try it with an empty string for the ObjectName parameter.
DoCmd.OutputTo acOutputReport, "", "PDFFormat(*.pdf)", _
strReportName, False, , , acExportQualityScreen
I don't know how much (or even if) this suggestion will speed up your code. But if you can't speed up those export functions somehow, my hunch is your hope to cut the overall time by half is a shaky proposition.

List reports along with their description

Variety of ways to get a list of report names:
Query
SELECT [Name] FROM MsysObjects
WHERE ([Type] = -32764)
Or VBA
Dim rpt As AccessObject
Dim dB As Object
On Error GoTo Error_Handler
Set dB = Application.CurrentProject
For Each rpt In dB.AllReports
Debug.Print rpt.Name
Next rpt
A report can have a Description under the Properties (Right-Click on report object), but I cannot access with code.
I'd like to have a listbox display a user-friendly report name associated with the actual report name. I'm trying to avoid creating a separate table to manage this at this point.
CurrentProject is an ADO object, and I don't know how to do what you want from ADO. You can use DAO to retrieve the Description property.
? CurrentDb.Containers("Reports").Documents("rptFoo").Properties("Description")
Foo Report
Since Description is a user-defined property, it doesn't exist until you assign a value for it. Therefore the next line triggers error 3270 (Property not found) for rptLinks, since it doesn't have a Description assigned.
? CurrentDb.Containers("Reports").Documents("rptLinks").Properties("Description")
You could trap that error. Or see if you can make use of Allen Browne's HasProperty function
A totally different approach would be to create tblReports with report_name and friendly_name fields. You would have to maintain that table, but the workload should be roughly equivalent to maintaining the Description properties on the report objects. Then you could use a simple SELECT on the table as the RowSource for your list box.
Update: You could also SELECT from MSysObjects with a custom function to return the Description for each report.
Public Function ReportDescription(ByVal pName As String) As String
Dim strReturn As String
Dim strMsg As String
On Error GoTo ErrorHandler
strReturn = _
CurrentDb.Containers("Reports").Documents(pName).Properties("Description")
ExitHere:
On Error GoTo 0
ReportDescription = strReturn
Exit Function
ErrorHandler:
Select Case Err.Number
Case 3270 'Property not found.'
'strReturn = "(no Description)"'
'* no Description -> just echo report name *'
strReturn = pName
Case Else
strMsg = "Error " & Err.Number & " (" & Err.description _
& ") in procedure ReportDescription"
MsgBox strMsg
strReturn = vbNullString
End Select
GoTo ExitHere
End Function
Revise your original query to use the function.
SELECT
[Name] AS report_name,
ReportDescription([Name]) AS friendly_name
FROM MsysObjects
WHERE ([Type] = -32764);