I am trying to add a watermark to an Access report using the "Picture" property and have run into an issue. The following code works and the image is displayed/printed when the report is previewed and printed but does not work when the report is directly printed from a macro (nothing visible on-screen). "GrandTotal" is a bound text box on the report that is the sum of a field in the record source. I would appreciate any suggestion to print the watermark from both the print preview and the print macro.
Private Sub Report_Load
' put up the watermark if needed
If GrandTotal.Value < 2000 Then
Me.Picture = <<picture file name including full path>>
End If
End Sub
Since you are printing the report without it ever rendering to the screen the open/load events are never fired because they are never used. An alternative could be to open the report in print preview and use the OpenArgs to indicate you want to print it
Private Sub SomeButton_Click()
DoCmd.OpenReport "DetailView", acViewPreview, , , acHidden, "Print"
End Sub
then do your normal loading stuff
Private Sub Report_Load
' put up the watermark if needed
If GrandTotal.Value < 2000 Then
Me.Picture = <<picture file name including full path>>
End If
End Sub
and when the loading is done your form will Activate which is when you can print
Private Sub Report_Activate()
If Me.OpenArgs = "Print" Then
On Error GoTo ErrorHandler
DoCmd.OpenReport "Report1", acViewPreview
'Opens print dialog for current screen (report in this case):
DoCmd.RunCommand acCmdPrint
End If
DoCmd.Close
ErrorHandler:
If Err.Number <> 0 And Err.Number <> 2501 Then
MsgBox "Error: " & Err.Number & vbNewLine & Err.Description
Exit Sub
End If
End Sub
The form is never shown so it looks like you had it set up before but the load/open events will fire like normal because the report is actually rendered.
Related
In my MS-Access Database I Got a LoginForm, which checks If a User has Access to a specific form or Not.
My main, called "NavigationsFormular" has 4 Tabs
A normal User can access the 1st tab called "Bautagesbericht".
A ControlingUser can access the 2nd, 3d, 4th tab, but not the 1st!
The Login Form is a pop-up at start, I dont want to change it to a tab too,that would be ugly and not optimal.
After the Login succeeded, it loads up the Navigationform.
For the normal user its no problem, but for the controlling part it always says " No access " because it tried to open a tab he's not permitted to.
Thats the Code btw:
If Globals.UserAccess(Me.Name) = False Then
MsgBox " No access!"
DoCmd.Close acForm, Me.Name
End If
Now my idea was, that the Login Form open the form, which the user got permissions to by following code:
If Globals.UserAccess("frm_Räumstellenerfassung") = False Then
DoCmd.BrowseTo ObjectType:=acBrowseToForm, _
ObjectName:="frm_Taetigkeitseingabe_Büro", _
PathToSubformControl:="Navigationsformular.NavigationsUnterformular>frm_Taetigkeitseingabe_Büro.NavigationsUnterformular"
DoCmd.Close acForm, Me.Name
Else
DoCmd.OpenForm "Navigationsformular"
DoCmd.Close acForm, Me.Name
End If
End Sub
The Problem is that the Path is not right..
Hauptformular1 / MainFormular1 = "NavigationsFormular"
Unterformular1 / SubForm1 = "NavigationsUnterformular" (in German)
Formular1 = "frm_Taetigkeitseingabe_Büro"
Tried all combinations nothing helped.
BTW: A Button in my Naviagtion form with this Code is working. Apparently not when trying from an other form.
DoCmd.BrowseTo acBrowseToForm, "frm_Taetigkeitseingabe_Büro","Navigationsformular.NavigationsUnterformular"
ok I followed #June7 tipps. thanks for that. Here my solution:
Edited my form "frm_Räumstellenerfassung" ( Bautagesbericht) to
Private Sub Form_Open(Cancel As Integer)
DoCmd.GoToRecord , , acNewRec
If Globals.UserAccess("frm_Räumstellenerfassung") = False Then
DoCmd.BrowseTo acBrowseToForm, "frm_Taetigkeitseingabe_Büro", "Navigationsformular.NavigationsUnterformular"
End If
End Sub
So msg " No Access " is not popping up anymore and if the User has no rights to see this form, its browsing to the 2nd tab(Tätigkeitserfassung) without seeing any details of the 1st form.
My Login button just navigate to the navigationform
DoCmd.OpenForm "Navigationsformular"
DoCmd.Close acForm, Me.Name
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") & "#"
I'm selecting some record and I have option to view them as a report (by pushing Command33 button)
Private Sub Command33_Click()
DoCmd.OpenReport "repAwariaOtwarta", acViewPreview, , "[dbAwarieOtwarte].[ID] =" & Me![ID]
End Sub
After clicking the button I have report pop up.
What I should do to print that report without overwiewing it after clicking Command33?
I was trying to use DoCmd.PrintOut, but I seem to failed.
Just combine your ideas:
Open the report, use the print command.
Private Sub Command33_Click()
DoCmd.OpenReport "repAwariaOtwarta", acViewPreview, , _
"[dbAwarieOtwarte].[ID] =" & Me![ID]
DoCmd.PrintOut , , , , 1
End Sub
Here are the paramteres for Printout command
https://msdn.microsoft.com/en-us/library/office/ff192667.aspx
If you want, you can do a close method for the report after the print commmand like
DoCmd.Close acReport, "repAwariaOtwarta"
Is there any way to export a report in MS Access to PDF based on a certain criteria/field on the report?
I have created a productivity report in MS Access. Instead of exporting 50 pages into 1 PDF, is there a way to export based on the manager's name? The field for the managers name is included on the actual report.
You can take this idea and play with it. Insert this into a Module
Option Explicit
Dim g_ManagerReportFilterEnabled As Boolean
Dim g_ManagerReportFilter As String
Public Function IsManagerReportFilterEnabled() As Boolean
IsManagerReportFilterEnabled = g_ManagerReportFilterEnabled
End Function
Public Function GetManagerReportFilter() As String
GetManagerReportFilter = g_ManagerReportFilter
End Function
Public Sub ExportFilteredManagerReportToPDF(strManagerName As String)
On Error GoTo ExportFilteredManagerReportToPDF_ErrorHandler
g_ManagerReportFilterEnabled = True
g_ManagerReportFilter = "[MyManagerNameField] = " & Chr(34) & strManagerName & Chr(34)
DoCmd.OutputTo acOutputReport, "MyReportName", acFormatPDF, "MyPath:\MyFileName.PDF", False
GoTo ExitMe
ExportFilteredManagerReportToPDF_ErrorHandler:
Debug.Print err.Number & ": " & err.Description
ExitMe:
g_ManagerReportFilterEnabled = False
Exit Sub
End Sub
and review the variables you need to replace. And this into Report_Open of your report:
Private Sub Report_Open(Cancel As Integer)
If IsManagerReportFilterEnabled = True Then
Me.Filter = GetManagerReportFilter
Me.FilterOn = True
End If
End Sub
So the issue this code is trying to solve is that we want to use DoCmd.OutputTo to output our PDF, but it does not take a Filter parameter. So we work around this by setting up two global variables (I know...) which let us know if we should use the Manager filter and what that filter is. When we run ExportFilteredManagerReportToPDF and pass through a name, the sub will output the report to PDF. Because of the code attached the report, when OutputTo runs, the report will detect whether the filter is enabled, and if it is, apply it. Then OutputTo finishes its work and the PDF is output.
To run this for manager John Smith, say, you can run this from the debug window:
ExportFilteredManagerReportToPDF "John Smith"
I am using David-W-Fenton's answer to this question to try to allow users to print a report when they click on a control, but I am getting the following error message:
runtime error 2448: you cannot assign a value to this object.
The line of code triggering the error is:
Me.txtPageTo.Value = numPages
Here is the full code of the OnLoad event handler for the form:
Private Sub Form_Load()
Dim varPrinter As Printer
Dim strRowsource As String
Dim strReport As String
If Len(Me.OpenArgs) > 0 Then
strReport = Me.OpenArgs
Me.Tag = strReport
For Each varPrinter In Application.Printers
strRowsource = strRowsource & "; " & varPrinter.DeviceName
Next varPrinter
Me!cmbPrinter.RowSource = Mid(strRowsource, 3)
' first check to see that the report is still open
If (1 = SysCmd(acSysCmdGetObjectState, acReport, strReport)) Then
With Reports(strReport).Printer
Me!cmbPrinter = .DeviceName
Me!optLayout = .Orientation
End With
Dim numPages As String
numPages = Reports(strReport).Pages
Debug.Print "numPages = " & numPages
TypeName(Me.txtPageTo) 'added this line as a test after
Me.txtPageTo.Value = numPages
End If
End If
End Sub
numPages prints out to equal 0 just before the error is thrown, even though the report should have at least one page. Also, the error does not get thrown when the form is already open. The error only gets thrown when the form has to be opened. (Probably because the offending code is in the onload event.)
When I added TypeName(Me.txtPageTo) , it triggered runtime error 2424: The expression you entered has a field, control, or property name that mydatabasename cant find.
I think the problem is that I need to set the control source for txtPageFrom and txtPageTo. But how do I do that? This form will only be loaded by a vba method that is trying to print a report, so the values for txtPageFrom and txtPageTo will come from the calling method, not from some underlying data table. (there is no underlying data table for this dialog form.)
cmbPrinter and optLayout seem to be populating correctly using the code above.
Can anyone show me how to get past the error messages so that the form loads properly?
CORRECT, COMPLETE ANSWER:
The answer to this problem was to greatly simplify the code. The code in the link at the top of this posting is WAY TOO COMPLEX, and tries to reinvent things that are already done well by the tools built into Access and VBA. I was able to print reports without any of the complicated solutions by simply using the following code in the on-click event of a control on a form associated with the report:
Private Sub txtPrintReport_Click()
On Error GoTo Error_Handler
Dim commNum As Long
commNum = Me.CommunicationNumber
Dim strReport As String
Dim strVarName As String
strReport = "rptCommunicationFormForPrinting"
strVarName = "CommunicationNumber"
DoCmd.OpenReport strReport, acViewPreview, , strVarName & " = " & commNum, acWindowNormal, acHidden
DoCmd.RunCommand acCmdPrint
DoCmd.Close acReport, strReport
Exit_Point:
Exit Sub
Error_Handler: 'this handles the case where user clicks cancel button
If Err.Number <> 2501 Then
MsgBox Err.Description, _
vbExclamation, "Error " & Err.Number
End If
DoCmd.Close acReport, strReport
End Sub
That is all the code that was required. Much less than the link at the start of this question. And also much less than the answer below. I am marking John Bingham's answer as the accepted answer because he clearly worked a lot on this, and I am very grateful for that. But I ended up solving the problem with A LOT LESS CODE. My solution does not require the custom dialog form because it uses the Windows print dialog form. As such, the on load event code in my posting (taken from the link above), is not necessary.
The code posted cannot work, because when a form is opened as a dialog:
DoCmd.OpenForm "dlgPrinter", , , , , acDialog, strReport
no other logic after this line is executed until the form has been closed, at which point control returns to the next line after this one, and logic continues on - except of course you can no longer reference anything in that form, because it is now closed.
Ok, now there is a question, where is the button the user clicks to print a report?
What I'm thinking is to split the logic in PrintReport into two methods, one that launches it, and tells the form to configure itself (doing the stuff suggested in the comment), but the rest of PrintReport then needs to happen after the user clicks OK (or Cancel);
So if I assume that you've got a form which can launch one or more reports, and the button is on this form, what I would suggest is this:
In the click event for that button - no changes to what you've got.
In that buttons form, add this:
Public Sub DialogAccept()
With Forms!dlgPrinter
If .Tag <> "Cancel" Then
Set Reports(strReport).Printer = Application.Printers((!cmbPrinter))
Reports(strReport).Printer.Orientation = !optLayout
Application.Echo False
DoCmd.SelectObject acReport, strReport
DoCmd.PrintOut acPages, !txtPageFrom, !txtPageTo
PrintReport = True
End If
End With
DoCmd.Close acForm, "dlgPrinter"
DoCmd.Close acReport, strReport
Application.Echo True
End Sub
Change PrintReport to:
Public Function PrintReport(strReport As String, strVarName As String, numVal As Long) As Boolean
' open report in PREVIEW mode but HIDDEN
DoCmd.OpenReport strReport, acViewPreview, , strVarName & " = " & numVal, acHidden
'DoCmd.OpenReport strReport, acViewPreview, , , acHidden
' open the dialog form to let the user choose printing options
DoCmd.OpenForm "dlgPrinter", , , , , , strReport
Forms!dlgPrinter.Configure
End Function
In the OK/Cancel button click events on dlgPrinter put (after existing code, but removing any instances of "Docmd.close"):
Forms!Calling_Form_Name.DialogAccept
This then calls that method, to do the stuff that is meant to happen after the user says "I'm done with the dialog".
Finally add the configure method to dlgPrinter:
Public Sub Configure()
With Reports(Me.Tag).Printer
Me!cmbPrinter = .DeviceName
Me!optLayout = .Orientation
End With
Dim numPages As String
numPages = Reports(Me.Tag).Pages
Debug.Print "numPages = " & numPages
TypeName(Me.txtPageTo) 'added this line as a test after
Me.txtPageTo.Value = numPages
End Sub
And remove this code section from Form_Load.
Hoep this helps.
Lastly, if the form on which the button launching dlgPrinter can vary, change this line:
DoCmd.OpenForm "dlgPrinter", , , , , acDialog, strReport
to:
DoCmd.OpenForm "dlgPrinter", , , , , acDialog, strReport & ";" & me.Name
In form_load of dlgPrinter, break up me.Openargs using left() & mid() with instr(), and save me.Name into the tag of something on the form (which you're not already using the tag of).
In the OK/Cancel button click events, change the code above to:
Forms(Object.Tag).DialogAccept