I would greatly appreciate it if you could help me with this, I am creating a dynamic excel sheet and I managed so far to create excel charts using Excel vba.
However, I am struggling with exporting all of the charts and one additional sheet to one pdf. I have around 15 excel charts and one excel sheet that I need to put in one pdf. And I need the excel sheet to be the first page in the pdf. Then email this pdf (all using vba).
Could you please help me on this! Your help is much appreciated. Thank you in advance!
Well you could Publish the workbook to PDF, just make sure your fist page is the first sheet
Option Explicit
Sub PDF_And_Mail()
Dim FileName As String
'// Call the function with the correct arguments
FileName = Create_PDF(Source:=ActiveWorkbook, _
OverwriteIfFileExist:=True, _
OpenPDFAfterPublish:=False)
If FileName <> "" Then
Mail_PDF FileNamePDF:=FileName
End If
End Sub
'// Create PDF
Function Create_PDF(Source As Object, OverwriteIfFileExist As Boolean, _
OpenPDFAfterPublish As Boolean) As String
Dim FileFormatstr As String
Dim Fname As Variant
'// Test If the Microsoft Add-in is installed
If Dir(Environ("commonprogramfiles") & "\Microsoft Shared\OFFICE" _
& Format(Val(Application.Version), "00") & "\EXP_PDF.DLL") <> "" Then
'// Open the GetSaveAsFilename dialog to enter a file name for the pdf
FileFormatstr = "PDF Files (*.pdf), *.pdf"
Fname = Application.GetSaveAsFilename("", filefilter:=FileFormatstr, _
Title:="Create PDF")
'// If you cancel this dialog Exit the function
If Fname = False Then
Exit Function
End If
'If OverwriteIfFileExist = False we test if the PDF
'already exist in the folder and Exit the function if that is True
If OverwriteIfFileExist = False Then
If Dir(Fname) <> "" Then Exit Function
End If
'Now the file name is correct we Publish to PDF
Source.ExportAsFixedFormat _
Type:=xlTypePDF, _
FileName:=Fname, _
Quality:=xlQualityStandard, _
IncludeDocProperties:=True, _
IgnorePrintAreas:=False, _
OpenAfterPublish:=OpenPDFAfterPublish
'If Publish is Ok the function will return the file name
If Dir(Fname) <> "" Then
Create_PDF = Fname
End If
End If
End Function
'// Email Created PDF
Function Mail_PDF(FileNamePDF As String)
Dim GMsg As Object
Dim gConf As Object
Dim GmBody As String
Dim Flds As Variant
Set GMsg = CreateObject("CDO.Message")
Set gConf = CreateObject("CDO.Configuration")
gConf.Load -1 ' CDO Source Defaults
Set Flds = gConf.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") = "GmailAddress#gmail.com"
.Item("http://schemas.microsoft.com/cdo/configuration/sendpassword") = "password"
.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
GmBody = "Hi there" & vbNewLine & vbNewLine
With GMsg
Set .Configuration = gConf
.To = "recip#email.com"
.CC = ""
.BCC = ""
.From = "Reply#something.com"
.Subject = "Important message"
.TextBody = GmBody
.AddAttachment FileNamePDF
.Send
End With
End Function
Most codes from Ron de Bruin
Related
So I have been trying to use a the below macro to split a mail-merged document into individual documents. When I run the macro, I receive "Runtime Error '5852' Requested object is not available." The issue is highlighted as .Destination = wdSendToNewDocumentwhen using the debug action.
I though that perhaps the issue was with the file being located on my OneDrive but after moving the files to a local drive, I recieved the same issue. Any insight into how to resolve this error would be helpful.
If more info is necessary, please let me know and I would be happy to answer as best I could.
Code for reference:
Sub MailMergeToDoc()
'
' MailMergeToDoc Macro
' Collects the results of the mail merge in a document
'
' Sourced from: https://www.msofficeforums.com/mail-merge/21803-mailmerge-tips-tricks.html
Application.ScreenUpdating = False
Dim StrFolder As String, StrName As String, MainDoc As Document, i As Long, j As Long
Const StrNoChr As String = """*./\:?|"
Set MainDoc = ActiveDocument
With MainDoc
StrFolder = .Path & "\"
With .MailMerge
.Destination = wdSendToNewDocument
.SuppressBlankLines = True
On Error Resume Next
For i = 1 To .DataSource.RecordCount
With .DataSource
.FirstRecord = i
.LastRecord = i
.ActiveRecord = i
If Trim(.DataFields("Last_Name")) = "" Then Exit For
'StrFolder = .DataFields("Folder") & "\"
StrName = .DataFields("Last_Name") & "_" & .DataFields("First_Name")
End With
On Error GoTo NextRecord
.Execute Pause:=False
For j = 1 To Len(StrNoChr)
StrName = Replace(StrName, Mid(StrNoChr, j, 1), "_")
Next
StrName = Trim(StrName)
With ActiveDocument
'Add the name to the footer
'.Sections(1).Footers(wdHeaderFooterPrimary).Range.InsertBefore StrName
.SaveAs FileName:=StrFolder & StrName & ".docx", FileFormat:=wdFormatXMLDocument, AddToRecentFiles:=False
' and/or:
.SaveAs2 FileName:=StrFolder & StrName & ".pdf", FileFormat:=wdFormatPDF, AddToRecentFiles:=False
.Close SaveChanges:=False
End With
NextRecord:
Next i
End With
End With
Application.ScreenUpdating = True
End Sub
This is pretty basic troubleshooting. You can't just copy code without understanding what it's doing.
Your MailMerge object does not exist when you're trying to run the mail merge.
You need to create a Mail Merge first in your Word doc - just use the Wizard - and that object will be magically filled. Then you'll have to progress to your next error.
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.
I wish to mail merge and email from an Access query and pre setup word doc. It appears to work fine, as a the merged data document appears along with a new merged document that I have (for now) save. BUT what I really want it to do is send the actual email, rather than having to manually go to 'Finish & Merge" from MsWord. Simply it just doesn't actually send the email(s).
Function runMerge()
Dim StrFullDocPath As String
Dim oApp As Object
'Path to the word document
StrFullDocPath = "merge.docx" 'have removed the full path
'to save file name
outFileName = "Renewals_" & Format(Now(), "dd-mm-yyyy")
If Dir(StrFullDocPath) = "" Then
MsgBox "Document not found"
Else
'Create an instance of MS Word
Set oApp = CreateObject("Word.Application")
oApp.Visible = True
'Open the Document
oApp.Documents.Open FileName:=StrFullDocPath
End If
With oApp
With .ActiveDocument.MailMerge
.MainDocumentType = wdEMail
.OpenDataSource _
Name:="myDB.accdb", _
LinkToSource:=True, _
AddToRecentFiles:=False, _
Connection:="QUERY qryCheckRenews", _
SQLStatement:="SELECT * FROM [qryCheckRenews]"
.Destination = wdSendToEmail
.MailAddressFieldName = "EmailAddress"
.MailFormat = wdMailFormatHTML
.MailAsAttachment = False
.MailSubject = "testing testing 1, 2, 3"
.SuppressBlankLines = True
.Execute Pause:=False
MsgBox "Mail Merge Complete ", vbOKOnly, "myDB"
End With
oApp.ActiveDocument.SaveAs2 FileName:="Renewal" & outFileName & ".docx"
'oApp.Documents.Close savechanges:=False
Set oApp = Nothing
End With
'Exit Sub
'ErrTrap:
' MsgBox Err.Description, vbCritical
End Function
Any help gratefully received
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
I made the code (as shown below) which send one PDF by email correctly, but I need to send one more PDF.
Dim varFindThis As Variant
Dim rngLookIn As Range
varFindThis = Worksheets("Suivi").Range("B1")
Set rngLookIn = Worksheets("Suivi").Range("A:A")
If Not rngLookIn.Find(varFindThis, LookIn:=xlValues) Is Nothing Then
Dim f As String
f = Worksheets("Suivi").Range("B1").Value
'Since i didn't got that clear, here above you must create a code to declare "f" as whatever you want
Set c = Worksheets("Suivi").Range("A:A").Find(f)
Worksheets("Suivi").Range(c.Address).EntireRow.Delete
End If
'Do not forget to change the email ID
'before running this code
Dim OlApp As Object
Dim NewMail As Object
Dim TempFilePath As String
Dim TempFileName As String
Dim FileFullPath As String
' With Application
' .ScreenUpdating = False
' .EnableEvents = False
' End With
Application.DisplayFullScreen = False
ThisWorkbook.Worksheets("PDF").Activate
Range("B1:BG46").Select
ActiveSheet.PageSetup.PrintArea = "$B$1:$BG$46"
' Temporary file path where pdf
' file will be saved before
' sending it in email by attaching it.
TempFilePath = Environ$("temp") & "\"
' Now append a date and time stamp
' in your pdf file name. Naming convention
' can be changed based on your requirement.
TempFileName = ActiveSheet.Name & "-" & Format(Now, "dd-mmm-20yy") & ".pdf"
'Complete path of the file where it is saved
FileFullPath = TempFilePath & TempFileName
'Now Export the Activesshet as PDF with the given File Name and path
On Error GoTo err
With ActiveSheet
.ExportAsFixedFormat _
Type:=xlTypePDF, _
Filename:=FileFullPath, _
Quality:=xlQualityStandard, _
IncludeDocProperties:=True, _
IgnorePrintAreas:=False, _
OpenAfterPublish:=False
End With
'Now open a new mail
Set OlApp = CreateObject("Outlook.Application")
'Loop through the rows
For Each cell In ThisWorkbook.Sheets("Envoie").Columns("C").Cells.SpecialCells(xlCellTypeVisible)
If cell.Value Like "*#*" Then
EmailAddr1 = EmailAddr1 & ";" & cell.Value
End If
Next
For Each cell In ThisWorkbook.Sheets("Envoie").Columns("G").Cells.SpecialCells(xlCellTypeVisible)
If cell.Value Like "*#*" Then
EmailAddr2 = EmailAddr2 & ";" & cell.Value
End If
Next
Subj = "N°Article" & ThisWorkbook.Sheets("CalculInfo").Range("A10")
Set NewMail = OlApp.CreateItem(0)
On Error Resume Next
With NewMail
.To = EmailAddr1
.CC = EmailAddr2
.BCC = "gaetan.affolter#he-arc.ch"
.Subject = Subj
.Body = "Bonjour, il vous reste 24 heures pour vérifier les données du PDF et de confirmer dans Octopus. Merci"
.Attachments.Add FileFullPath '--- full path of the pdf where it is saved
.Send 'or use .Display to show you the email before sending it.
End With
On Error GoTo 0
'Since mail has been sent with the attachment
'Now delete the pdf file from the temp folder
Kill FileFullPath
'set nothing to the objects created
Set NewMail = Nothing
Set OlApp = Nothing
'Now set the application properties back to true
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
MsgBox ("Email a été envoyé")
Exit Sub
err:
MsgBox err.Description
Unload Me
The PrintArea I situated in the Worksheets("CalcGammeControle") and more precisely in "$G$2:$G$35"
How can I add it?