Access 2010 PDF, Save and Email a Report Using VBA Code - vba

I'm using Access 2010 and found the Send to Email as PDF command indispensable. However, I have a problem in that I've hidden the main ribbon from my users which means they can't actually click that button.
Can anyone tell me the VBA code that will let me PDF, save the file and email via Gmail an individual report based on a given unique ID? I am happy for the user to add the email address, subject and message body and for them to click send.
I begin with the following code, but it doesn't work.
Dim myPath As String
Dim strReportName As String
DoCmd.OpenReport "rptsuivi", acViewPreview, , "tblsuivi.[NĀ°Suivi] = '" & Me.[CompanyName] & "' "
myPath = "C:\"
strReportName = "Raport de suivi" + "-" + ".pdf"
DoCmd.OutputTo acOutputReport, acFormatPDF, , myPath + strReportName, True
DoCmd.Close acReport, "rptsuivi"

looks like you can create a macro that just runs the ribbon command
https://msdn.microsoft.com/en-us/library/office/ff862419.aspx
http://www.ribboncreator2010.de/Onlinehelp/EN/_2el0osmon.htm
you'll need to find the right idMso for the ribbon function you're trying to use.
Sub SendToEmailAsPDF()
Application.CommandBars.ExecuteMso "FileSendAsAttachment"
End Sub

Related

When creating a pdf from a report, sub-reports won't show if they have no data and I want it to

I have a report that is made up of 4 sub-reports. This report is made up of multiple physicians, and I've been successful creating a button that will take this large report, break it up by the physicians [EPIC_ID], and create a pdf file with each physicians specific information.
My problem is, when 1 of those 4 sub-reports has no data, the report with no data isn't shown in the final pdf.
When I run and view the report (in report view), it will show all 4 reports with the physician information regardless if there is data for each report, but when I go to print view, it will only show the reports that have data.
I need to be able to create a pdf that will show the subreports even if there is no data in it.
I've tried creating a text box that only shows when there is no data. And it works in the report view, but not in print view or when I make it a pdf. I've also tried using a label and the "On No Data" portion of the sub-reports, but that didn't work.
Any help would be appreciated! Below is the code to the button that opens the report and makes them in to pdf files:
Private Sub Command0_Click()
Dim rst As DAO.Recordset
Dim strFolder1 As String, strFolder2
DoCmd.OpenQuery "qryPhysicianID_Range_tbl"
Set rst = CurrentDb.OpenRecordset("SELECT DISTINCT [Prov_Order_Name],[EPIC_ID] FROM [tblPhysicianID_Range] ORDER BY [EPIC_ID];", dbOpenSnapshot)
If rst.RecordCount > 0 Then ' make sure that we have data
rst.MoveFirst
Do While Not rst.EOF
strFolder1 = "U:\Co\Physician\Reappointment\Jordans Test\" 'common folder for files to go
strFolder2 = strFolder1 & rst.Fields("[Prov_Order_Name]") & "\" 'creates folder by Provider Name
If Dir(strFolder2, vbDirectory) = "" Then MkDir strFolder2 'determines if folder exists or not, and if it doesn't it makes one
DoEvents
rst.MoveNext
Loop
End If
If rst.RecordCount > 0 Then ' make sure that we have data
rst.MoveFirst
Do While Not rst.EOF
strRptFilter = "[EPIC_ID] = " & rst![EPIC_ID]
strFolder1 = "U:\Co\Physician\Reappointment\Jordans Test\" 'common folder for files to go
DoCmd.OpenReport "rptCombined", acViewPreview, , strRptFilter, acHidden ' open the report hidden in preview mode setting the where parameter
DoCmd.OutputTo acOutputReport, "rptCombined", acFormatPDF, _
strFolder1 & rst.Fields("[Prov_Order_Name]") & "\" & rst.Fields("[Prov_Order_Name]") & ".pdf", _
, , , acExportQualityScreen ' save the opened report
DoCmd.Close acReport, "rptCombined" ' close the report
DoEvents
rst.MoveNext
Loop
End If
rst.Close
Set rst = Nothing
End Sub
Use code behind main report to manage display of label or textbox control when subreport does not have data. Example:
Private Sub Detail_Format(Cancel As Integer, FormatCount As Integer)
Me.lblOU.Visible = Not Me.ctrOU.Report.HasData
Me.lblCO.Visible = Not Me.ctrCO.Report.HasData
Me.lblRC.Visible = Not Me.ctrRC.Report.HasData
End Sub
Procedure is OnFormat event of main report Detail section. Example shows use of label control. Use whatever you prefer and modify code as appropriate for your objects and their names. Add the 4th control code.

MS Access: Command button to save as a report as PDF

I try to create a code for a button in Access that opens the Save as dialog box to save a report with the predefined file name with a filter to PDF file type in which the user can manually select the desired folder.
I also used below code for a different button to save it as Excel file type, which works, but I don't get it to work for PDF.
Can you guys help me. Thanks.
Private Sub PrintButton_Click()
CurrentTime = Format(Now(), "DD_MM_YYYY hh:mm")
cmdlgOpenFile.filename = "Stock overview " & MonthMFiling & " " & YearMFiling & " " & CurrentTime & ".pdf"
cmdlgOpenFile.Filter = "PDF Files (*.pdf)|*.pdf"
cmdlgOpenFile.FilterIndex = clngFilterIndexAll
cmdlgOpenFile.DialogTitle = "Save Report As"
'this is where the dialog opens
cmdlgOpenFile.ShowSave
'returns your full file name.
filename = cmdlgOpenFile.filename
End Sub
Your code gets the filename. To output a report to PDF use this command:
DoCmd.OutputTo acOutputReport, "ReportName", acFormatPDF, filename
Replace "ReportName" with the name of the report you are using.
DOC: https://learn.microsoft.com/en-us/office/vba/api/Access.DoCmd.OutputTo

Add parameter entered to pull report to PDF file name

In the small section of coding the DoCmd command creates a PDF of a report "VRRrep222". I enter the "VRR#" that I need to create. After this an e-mail is created and sent.
In filename = the name of the PDF will be "VRRrep222" and today's date. I need the VRR# that I entered to pull the report to also be the number in the file name (and also the subject line in my code which I did not paste here).
Is there a way to associate the report # being pulled so that it can be added to the PDF name and subject line without having to manually enter it?
Sub SendEmail()
Dim filename As String, todaydate As String
Dim Msg As Object
Dim Supplier As String
Supplier = InputBox("Supplier E-mail?")
todaydate = Format(Date, "MMDDYYYY")
filename = Application.CurrentProject.Path & "\VRRrep222_" & todaydate & ".pdf"
DoCmd.OutputTo acReport, "VRRrep222", acFormatPDF, filename, False
Set Msg = CreateObject("CDO.Message")
With Msg
Msg.To = Supplier
Msg.From = ""
Msg.cc = ""
Msg.bcc = ""
Msg.Subject = ""
Msg.TextBody = "This is an automated email that is being sent as an ALERT only. If the disposition is RETURN TO VENDOR, you will be notified with another email."
Msg.addattachment filename
Msg.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
Msg.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = ""
Msg.Configuration.Fields.Update
Msg.Send
End With
Kill filename
Set Msg = Nothing
End Sub
I'm new to VBA as of yesterday.
Pulling value from report data would require report be open first. Current code doesn't do that.
Don't use dynamic parameterized query with popup prompt. Query popup inputs are poor design because input cannot be validated and cannot be referenced for other purpose, such as your requirement. Use a control on form for input of criteria parameter. Either have query parameter reference form control or apply filter to report with OpenReport method. Then code can reference that control to build file name and subject. Perhaps a combobox would be best then users can only select valid VRR#.
filename = Application.CurrentProject.Path & "\" & Me.cbxVRR & "_" & todaydate & ".pdf"
DoCmd.OpenReport "VRRrep222", acViewPreview, , "YOURfieldname=" & Me.cbxVRR, acHidden
DoCmd.OutputTo acReport, "VRRrep222", acFormatPDF, filename, False
DoCmd.Close acReport, "VRRrep222", acSaveNo
...
.Subject = Me.cbxVRR
I never use dynamic parameters in query.

How to stop DoCmd.OutputTo from printing file?

I have created report in MS Access and an on_click command to save the mentioned report as a PDF on the user's desktop.
The problem is that after running this command not only save PDF version, but also prints it.
I am confused, which part of my code gives command to print whole thing?
Private Sub Oldsys_atask_isorei_Click()
'file name
ReportName = "Report_" & Format(Now, "_yyyy-mm-dd") & ".pdf"
'path to Users desktop
DTAddress = CreateObject("WScript.Shell").SpecialFolders("Desktop") & "/"
'opens report in background (without it OutputTo did not seemed to work)
DoCmd.OpenReport "rprtOldsys_isorei", acViewNormal, , , acHidden
'saves report in PDF on Users desktop
DoCmd.OutputTo acOutputReport, "rprtOldsys_isorei", acFormatPDF, DTAddress & ReportName, True
'closes opened report
DoCmd.Close acReport, "rprtOldsys_isorei", acSaveNo
End Sub
acViewNormal means print this for a report, that's the default view.
Either use acViewReport (report view) or acViewPreview (print preview) to not print the report.

How to Send an Email with a PDF attached with Outlook using MS Access VBA?

I am working with an Access application within Access 2016. The application outputs to a PDF file via the DoCmd.OutputTo method.
I want to either send this PDF attached to an email I build in code, or open a new Outlook email with the file attached.
When I click the button in the form which triggers the code that includes my sub(s) (which are located in separate modules), the email window is never displayed nor is an email sent (depending on the use of .Display vs .Send). I also do not receive any errors.
I think it may also be worth noting that the Call to the sub inside of a module that creates the PDF works as expected.
I am running Access 2016 and Outlook 2016 installed as part of Office 2016 Pro Plus on a Windows 7 64-bit machine. The Office suite is 32-bit.
The Module & Sub
(Email Address Redacted)
Dim objEmail As Outlook.MailItem
Dim objApp As Outlook.Application
Set objApp = CreateObject("Outlook.Application")
Set objEmail = oApp.CreateItem(olMailItem)
With objEmail
.Recipients.Add "email#domain.com"
.Subject = "Invoice"
.Body = "See Attached"
.Attachments.Add DestFile
.Display
End With
The Sub Call
MsgBox "Now saving the Invoice as a PDF"
strInvoiceNbr = Int(InvoiceNbr)
strWhere = "[InvoiceNbr]=" & Me!InvoiceNbr
strDocName = "Invoice Print One"
ScrFile = "Invoice Print One"
DestFile = "Inv" + strInvoiceNbr + " - " + Me.GetLastname + " - " + GetLocation
MsgBox DestFile, vbOKOnly
DoCmd.OpenForm strDocName, , , strWhere
Call ExportToPDF(SrcFile, DestFile, "INV")
Call EmailInvoice(DestFile)
Based on the fact that the PDF is being output within a sub in a Module file, should I be creating the email (or calling the sub) within the sub that creates the PDF?
NOTE: I have looked over this accepted answer here on Stack Overflow, as well as many others. My question differs due to the fact that I am asking why the message is not being displayed or sent, not how to build and send a message as the others are.
EDIT:
Outlook does not open and nothing occurs if Outlook is already open.
Final Note:
To add to the accepted answer, in the VBA editor for Access, you will likely have to go to Tools > References and enable Microsoft Outlook 16.0 Object Library or similar based on your version of Office/Outlook.
To pass full path try using Function EmailInvoice
Example
Option Explicit
#Const LateBind = True
Const olFolderInbox As Long = 6
Public Sub ExportToPDF( _
ByVal strSrcFileName As String, _
ByVal strNewFileName As String, _
ByVal strReportType As String _
)
Dim PathFile As String
Dim strEstFolder As String
strEstFolder = "c:\OneDrive\Estimates\"
Dim strInvFolder As String
strInvFolder = "c:\OneDrive\Invoices\"
' Export to Estimates or Invoices Folder based on passed parameter
If strReportType = "EST" Then
DoCmd.OutputTo acOutputForm, strSrcFileName, acFormatPDF, _
strEstFolder & strNewFileName & ".pdf", False, ""
PathFile = strEstFolder & strNewFileName & ".pdf"
ElseIf strReportType = "INV" Then
DoCmd.OutputTo acOutputForm, strSrcFileName, acFormatPDF, _
strInvFolder & strNewFileName & ".pdf", False, ""
PathFile = strEstFolder & strNewFileName & ".pdf"
End If
EmailInvoice PathFile ' call function
End Sub
Public Function EmailInvoice(FldrFilePath As String)
Dim objApp As Object
Set objApp = CreateObject("Outlook.Application")
Dim objNS As Object
Set objNS = olApp.GetNamespace("MAPI")
Dim olFolder As Object
Set olFolder = objNS.GetDefaultFolder(olFolderInbox)
'Open inbox to prevent errors with security prompts
olFolder.Display
Dim objEmail As Outlook.MailItem
Set objEmail = oApp.CreateItem(olMailItem)
With objEmail
.Recipients.Add "email#domain.com"
.Subject = "Invoice"
.Body = "See Attached"
.Attachments.Add FldrFilePath
.Display
End With
End Function
Your issue is with probably Outlook security. Normally Outlook would show a popup that says that a 3rd party application is attempting to send email through it. Would you like to allow it or not. However since you are doing this programmatically that popup never appears. There used to be a way to bypass this.
Test your program while the user is logged on and has Outlook open. See if there will be any difference in behavior. If that popup does come up, google the exact message and you will probably find a way to bypass it.
Any reason why you not using sendOject?
The advantage of sendobject, is that you not restriced to Outlook, and any email client should work.
So, this code can be used:
Dim strTo As String
Dim strMessage As String
Dim strSubject As String
strTo = "abc#abc.com;def#def.com"
strSubject = "Your invoice"
strMessage = "Please find the invoice attached"
DoCmd.SendObject acSendReport, "rptInvoice", acFormatPDF, _
strTo, , , strSubject, strMessage
Note that if you need to filter the report, then open it first before you run send object. And of course you close the report after (only required if you had to filter, and open the report before - if no filter is to be supplied, then above code will suffice without having to open the report first).
There is no need to separate write out the pdf file, and no need to write code to attach the resulting pdf. The above does everything in one step, and is effectively one line of code.