VBA: save to PDF and send it with a specific title to pre-selected email addresses - vba

I have the following code that saves to the current folder and opens the file:
Dim myFile As Variant
Dim strFile As String
On Error GoTo errHandler
Set ws = Worksheets("mysheet")
'enter name and select folder for file
' start in current workbook folder
strFile = Replace(Replace(ws.Name, " ", ""), ".", "_") _
& "_" _
& Format(Now(), "yyyymmdd\_hhmm") _
& ".pdf"
strFile = ThisWorkbook.Path & "\" & strFile
ws.ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
strFile, _
Quality:=xlQualityStandard, IncludeDocProperties:=True, IgnorePrintAreas _
:=False, From:=1, To:=3, OpenAfterPublish:=True
exitHandler:
Exit Sub
errHandler:
MsgBox "Could not create PDF file"
Resume exitHandler
End Sub
However, I do not want to open the file and want to send an email with the file as an attachment to some email addresses with a specified title on Outlook.
How can I do this?

If you don't want to open the file, then when you save it you should turn this to false:
OpenAfterPublish:=False '<-- in your code is now True
To send it as an attachment, you only need to attach the string you created:
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With OutMail
.to = "test#gmail.com"
.Subject = "Testfile"
.Body = "Hi"
.Attachments.Add strFile
.Send 'Or use .Display to see the mail and send it manually
End With
Find more about usage of Outlook with Excel VBA here.

Related

Convert excel tabs to PDF and send in separate emails

I am trying to convert excel tabs to PDF and send each tab as a single attachment on different emails in outlook with different email recipients.
For example, Tab A would correspond to a "Vendor Emails" Tab with a To, Cc, and Bcc for each tab. Same would go for Tab B but a different set of recipients.
My Code:
Option Explicit
Sub create_and_email_pdf()
Dim EmailSubject As String, EmailSignature As String
Dim CurrentMonth As String, DestFolder As String, PDFFile As String
Dim Email_To As String, Email_CC As String, Email_BCC As String
Dim OpenPDFAfterCreating As Boolean, AlwaysOverwritePDF As Boolean, DisplayEmail As Boolean
Dim OverwritePDF As VbMsgBoxResult
Dim OutlookApp As Object, OutlookMail As Object
CurrentMonth = ""
EmailSubject = "Invoice Attached for "
OpenPDFAfterCreating = True
AlwaysOverwritePDF = False
DisplayEmail = True
Email_To = ThisWorkbook.Sheets("Vendor Emails").Range("B2").Value
Email_CC = ""
Email_BCC = ""
'Prompt for file destination
With Application.FileDialog(msoFileDialogFolderPicker)
If .Show = True Then
DestFolder = .SelectedItems(1)
Else
MsgBox "You must specify a folder to save the PDF into." & vbCrLf & vbCrLf & "Press OK to exit this macro.", vbCritical, "Must Specify Destination Folder"
Exit Sub
End If
End With
'Current month/year
CurrentMonth = Mid(ThisWorkbook.Sheets("Vendor Emails").Range("E1").Value, InStr(1, ThisWorkbook.Sheets("Vendor Emails").Range("E1").Value, " ") + 1)
'Create new PDF file name including path and file extension
PDFFile = DestFolder & Application.PathSeparator & ActiveSheet.Name _
& "-" & CurrentMonth & ".pdf"
'If the PDF already exists
If Len(Dir(PDFFile)) > 0 Then
If AlwaysOverwritePDF = False Then
OverwritePDF = MsgBox(PDFFile & " already exists." & vbCrLf & vbCrLf & "Do you want to overwrite it?", vbYesNo + vbQuestion, "File Exists")
On Error Resume Next
'If you want to overwrite the file then delete the current one
If OverwritePDF = vbYes Then
Kill PDFFile
Else
MsgBox "OK then, if you don't overwrite the existing PDF, I can't continue." _
& vbCrLf & vbCrLf & "Press OK to exit this macro.", vbCritical, "Exiting Macro"
Exit Sub
End If
Else
On Error Resume Next
Kill PDFFile
End If
If Err.Number <> 0 Then
MsgBox "Unable to delete existing file. Please make sure the file is not open or write protected." _
& vbCrLf & vbCrLf & "Press OK to exit this macro.", vbCritical, "Unable to Delete File"
Exit Sub
End If
End If
'Create the PDF
ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:=PDFFile, Quality:=xlQualityStandard, IncludeDocProperties:=True, IgnorePrintAreas _
:=False, OpenAfterPublish:=OpenPDFAfterCreating
'Create an Outlook object and new mail message
Set OutlookApp = CreateObject("Outlook.Application")
Set OutlookMail = OutlookApp.CreateItem(0)
'Display email and specify To, Subject, etc
With OutlookMail
.Display
.To = Email_To
.CC = Email_CC
.BCC = Email_BCC
.Subject = EmailSubject & CurrentMonth
.Attachments.Add PDFFile
If DisplayEmail = False Then
.Send
End If
End With
End Sub
I keep having an issue with this line, I keep getting a run-time 1004 and that the file may be open/error while saving:
'Create the PDF
ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:=PDFFile, Quality:=xlQualityStandard, IncludeDocProperties:=True, IgnorePrintAreas _
:=False, OpenAfterPublish:=OpenPDFAfterCreating
If I don't use the reference ThisWookbook.Sheets(), I dont get an issue, but it only sends out the tab that I'm currently active on, not sure how to specify which tabs to convert.
For more context these tabs I'm converting would be part of a bigger worksheet with additional backup tabs that would not get sent as they are for internal purposes.
Thanks.

How can I Include additional code to then send email via Vba through Gmail?

I have seen similar questions but mine is quite specific let me explain.
I have this code that runs from a button if clicked it prints the active sheet as a pdf to the same pathway as my workbook, this works as it should as the active sheet information changes via a list to present each customer info for each financial period.
Each month i then need to attach each of these pdf files to emails and send to customers which is a long winded process, if i input the email to appear in a cell eg ("E1") automatically when the customer is selected can i then adapt my code to open an email and send the pdf to that email address?
Sub PDFActiveSheet()
Dim ws As Worksheet
Dim strPath As String
Dim myFile As Variant
Dim strFile As String
On Error GoTo errHandler
Set ws = ActiveSheet
'enter name and select folder for file
' start in current workbook folder
strFile = Replace(Replace(Range("B1"), "", ""), "", "") _
& " Period " _
& Format(Now(), Cells.Range("J1")) _
& ".pdf"
strFile = ThisWorkbook.Path & "\" & strFile
myFile = Application.GetSaveAsFilename _
(InitialFileName:=strFile, _
FileFilter:="PDF Files (*.pdf), *.pdf", _
Title:="Select Folder and FileName to save")
If myFile <> "False" Then
ws.ExportAsFixedFormat _
Type:=xlTypePDF, _
Filename:=myFile, _
Quality:=xlQualityStandard, _
IncludeDocProperties:=True, _
IgnorePrintAreas:=False, _
OpenAfterPublish:=False
End If
exitHandler:
Exit Sub
errHandler:
MsgBox "Could not create PDF file"
Resume exitHandler
End Sub
You can automate email sending through Outlook, but it seems like accessing Gmail and sending mail through the web would be a whole different ballpark. Gmail does have an API, which you can get documentation for here: https://developers.google.com/gmail/api/.
My suggestion is to setup Outlook with your Gmail account and then send through that, which is more likely way easier.
From Ron DeBruins website I found this and tested successfully. I did have to enable "All less secure apps" in my gmail settings. Here's the code in case his site ever goes down.
Sub CDO_Mail_Small_Text_2()
Dim iMsg As Object
Dim iConf As Object
Dim strbody As String
Dim Flds As Variant
Set iMsg = CreateObject("CDO.Message")
Set iConf = CreateObject("CDO.Configuration")
iConf.Load -1 ' CDO Source Defaults
Set Flds = iConf.Fields
With Flds
.Item("http://schemas.microsoft.com/cdo/configuration/smtpusessl") = True
.Item("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 1
.Item("http://schemas.microsoft.com/cdo/configuration/sendusername") = "Your gmail address"
.Item("http://schemas.microsoft.com/cdo/configuration/sendpassword") = "gmail pw"
.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "smtp.gmail.com"
.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
.Update
End With
strbody = "Hi there" & vbNewLine & vbNewLine & _
"This is line 1" & vbNewLine & _
"This is line 2" & vbNewLine & _
"This is line 3" & vbNewLine & _
"This is line 4"
With iMsg
Set .Configuration = iConf
.To = ""
.CC = ""
.BCC = ""
' Note: The reply address is not working if you use this Gmail example
' It will use your Gmail address automatic. But you can add this line
' to change the reply address .ReplyTo = "Reply#something.nl"
.From = """FROM??"" <Reply#something.nl>"
.Subject = "Important message"
.TextBody = strbody
.Send
End With
End Sub

Outlook blank 'To' field from Excel VBA on some computers

We have an Excel spreadsheet that we use to create quotations for potential customers. Through the use of VBA, it generates PDFs and emails them to the customer using Outlook. It takes the customer's email address from a cell on the main sheet where the user fills in the customer's details.
A couple of weeks ago, it stopped filling the customer's email address in the 'To' field in Outlook, even though it had been filled in on the main sheet.
When we change anything on this spreadsheet, including code, we save it as a new 'revision' (keeping all previous revisions.) Going back through the previous revisions, I now find that none of them work. This is odd as they definitely did before. I am using Office 2016 (although I upgraded a while ago, but this issue is recent.) A machine running Office 2013 is also not working. However, a machine running Office 2007 DOES work.
Any ideas as to why this is an issue now, and why it is only an issue on certain versions of Office? Here is a snippet of the code:
Private Sub send_as_pdf_Click()
On Error GoTo ErrMsg
Dim strPath As String, strFName As String
Dim OutApp As Object, OutMail As Object
strPath = Environ$("temp") & "\"
strFName = Sheets("Quotation").Name & " " & Range("G18") & ".pdf"
Sheets("Quotation").ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
strPath & strFName, Quality:=xlQualityStandard, _
IncludeDocProperties:=True, IgnorePrintAreas:=False, OpenAfterPublish:=False
strPath2 = Environ$("temp") & "\"
strFName2 = Sheets("Quotation Offer Letter").Name & " " & Range("G18") & ".pdf"
Sheets("Quotation Offer Letter").ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
strPath2 & strFName2, Quality:=xlQualityStandard, _
IncludeDocProperties:=True, IgnorePrintAreas:=False, OpenAfterPublish:=False
strPath3 = Environ$("temp") & "\"
strFName3 = Sheets("Additional Works Required").Name & " " & Range("G18") & ".pdf"
Sheets("Additional Works Required").ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
strPath3 & strFName3, Quality:=xlQualityStandard, _
IncludeDocProperties:=True, IgnorePrintAreas:=False, OpenAfterPublish:=False
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
strbody = "<p style='color:#2C3E50;font-family:Calibri;font-size:11pt;'>Hi " & Range("C9") & ",</p>"
strbody2 = "<p style='color:#2C3E50;font-family:Calibri;font-size:11pt;'>The content of the email goes here.</p>"
On Error Resume Next
With OutMail
.Display
.To = Range("C19")
.CC = ""
.BCC = "first#person.com" & ";" & "second#person.com" & ";" & Range("I6") & ";"
.Subject = "Quotation"
.HTMLBody = strbody & strbody2 & .HTMLBody
.Attachments.Add strPath & strFName
.Attachments.Add strPath2 & strFName2
.Attachments.Add strPath3 & strFName3
.Attachments.Add ("C:\Terms and Conditions of Business of Our Business.pdf")
.Attachments.Add ("C:\Warranty Statement of Our Business.pdf")
End With
Kill strPath & strFName
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
Exit Sub
ErrMsg:
MsgBox ("MUST enter Issue Number, Date & Customer Info."), , "Customer Email Error Message"
End Sub
Try this:
Comment this line so you can see what the error is and debug.
'On Error Resume Next
After doing that you should be able to see the error within the line:
.To = Range("C19")
In excel this returns the value of the range, however you are sending that value to another application Outlook which is expecting a string.
I changed that line to this:
.To = Range("C19").Value2
and it worked

Emailing an Excel sheet as a PDF directly

My aim is to be able to click a button and for my Excel sheet to PDF a range of my spreadsheet and to email this to an email address which is in one of the cells in the sheet. For starters, I have the code which can turn a range of cells into a PDF file and allows me to save it:
Option Explicit
Sub savePDF()
Dim wSheet As Worksheet
Dim vFile As Variant
Dim sFile As String
Set wSheet = ActiveSheet
sFile = Replace(Replace(Range("D11"), " ", ""), ".", "_") _
& "_" _
& Range("H11") _
& ".pdf"
sFile = ThisWorkbook.Path & "\" & sFile
With Excel.Application.FileDialog(msoFileDialogSaveAs)
Dim i As Integer
For i = 1 To .Filters.Count
If InStr(.Filters(i).Extensions, "pdf") <> 0 Then Exit For
Next i
.FilterIndex = i
.InitialFileName = sFile
.Show
If .SelectedItems.Count > 0 Then vFile = .SelectedItems.Item(.SelectedItems.Count)
End With
If vFile <> "False" Then
wSheet.Range("A1:BF47").ExportAsFixedFormat _
Type:=xlTypePDF, _
Filename:=vFile, _
Quality:=xlQualityStandard, _
IncludeDocProperties:=True, _
IgnorePrintAreas:=False, _
OpenAfterPublish:=False
End If
End Sub
Can anybody manipulate this code (attached to a button) so it will email an email address, which is in a particular cell, when the button is clicked and as an added bonus, have the subject of the email work from a cell in the spreadsheet too?
I have a solution which is below. After I set my print area by going into page payout and then set print area, I successfully managed to email the excel sheet as a PDF file:
Sub savePDFandEmail()
Dim strPath As String, strFName As String
Dim OutApp As Object, OutMail As Object
strPath = Environ$("temp") & "\" trailing "\"
strFName = ActiveWorkbook.Name
strFName = Left(strFName, InStrRev(strFName, ".") - 1) & "_" & ActiveSheet.Name & ".pdf"
ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
strPath & strFName, Quality:=xlQualityStandard, _
IncludeDocProperties:=True, IgnorePrintAreas:=False, OpenAfterPublish:=False
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.to = Range("CB4")
.CC = Range("CB6")
.BCC = ""
.Subject = Range("CB8")
.Body = Range("BW11") & vbCr
.Attachments.Add strPath & strFName
'.Display 'Uncomment Display and comment .send to bring up an email window before sending
.Send 'Keep this the same if you want to send the email address out on click of the button
End With
Kill strPath & strFName
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
I also needed to put a little emailing tool into my sheet too which looks like this:
Clicking the button will now send the email with the PDF file attached.

vba failing to export from excel to pdf if the file already exists

Sub printPdf()
Dim strPath As String
Dim myFile As Variant
Dim strFile As String
'On Error GoTo errHandler
Set ws = Application.ActiveSheet
'enter name and select folder for file
' start in current workbook folder
strFile = Replace(Replace(ws.Name, " ", "_"), ".", "_") _
& ".pdf"
strfolder = ThisWorkbook.Path & "\myPdfFiles"
If Len(Dir(strfolder, vbDirectory)) = 0 Then
MkDir (strfolder)
End If
strFile = strfolder & "\" & strFile
ws.ExportAsFixedFormat _
Type:=xlTypePDF, _
Filename:=strFile, _
Quality:=xlQualityStandard, _
IncludeDocProperties:=True, _
IgnorePrintAreas:=False, _
OpenAfterPublish:=False
Call closews
exitHandler:
Exit Sub
errHandler:
MsgBox "Could not create PDF file " & Err & ": " & Error(Err)
Resume exitHandler
End Sub
I am having an issue with saving the pdf files.
If the file already exists in the folder and has some changes made to it the macro will crash with the debugger pointing at the openAfterPulish line and display the following runtime error.
-2214701887(80071779)
"Document not saved."
My goal is that excel should automatically overwrite the old files. Excel will prompt me if I want to overwrite the file when I am saving it manually but crashes when I run the above code.
Check if it exists and delete it. In you VBA IDE go to the tools menu and selecte references. Select "Microsoft scripting runtime"
Dim Response As Integer
Dim fs As FileSystemObject
'We can come back to here after an error.
TryAgain:
If fs.FileExists(strFile) = True Then
On Error Goto DeleteError
fs.DeleteFile(strFile, True)
End If
DeleteError:
Response = MsgBox("Error deleting file. Do you have it open? Try again?", vbYesNo)
' If statement to check if the yes button was selected.
If Response = vbYes Then
Goto TryAgain
Else
Exit sub
End If
On Error Goto 0
ws.ExportAsFixedFormat _
Type:=xlTypePDF, _
Filename:=strFile, _
Quality:=xlQualityStandard, _
IncludeDocProperties:=True, _
IgnorePrintAreas:=False, _
OpenAfterPublish:=False
Call closews