Save pdf attachment using a field from the pdf - vba

The code below finds my Subfolder from my Inbox then opens the email in the active window.
I would like to "Open" the pdf form attached to this email so I could save the attachment using one of the text fields from the pdf form.
The only code I can find saves the attachment to the temp folder but does not get the content from the pdf form.
Sub OpenMailAttachment()
Dim ns As NameSpace
Dim Inbox As MAPIFolder
Dim openMsg As Outlook.MailItem
Dim mySubFolder As MAPIFolder
Dim myAttachment As Outlook.Attachment
Dim FileName As String
Dim myInspector As Outlook.Inspector
Set ns = GetNamespace("MAPI")
Set Inbox = ns.GetDefaultFolder(olFolderInbox)
Set mySubFolder = Inbox.Folders("PdfTest")
mySubFolder.Display
Set openMsg = mySubFolder.Items(1)
openMsg.Display
mySubFolder.Application.ActiveExplorer.Close
openMsg.Application.ActiveWindow
For Each myAttachment in Item.Attachment
FileName = "C:\temp\" & myAttachment.FileName
myAttachment.SaveAsFile FileName
myAttachment = openMsg.Attachments.Item.DisplayName
'(I get Compile error: *.Item* argument not optional)
myAttachments.Application.ActiveInspector.Display
End Sub

This should it...
Option Explicit
' use Declare PtrSafe Function with 64-bit Outlook
Private Declare PtrSafe Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" ( _
ByVal hwnd As Long, _
ByVal lpOperation As String, _
ByVal lpFile As String, _
ByVal lpParameters As String, _
ByVal lpDirectory As String, _
ByVal nShowCmd As Long _
) As Long
Sub OpenMailAttachment()
Dim ns As NameSpace
Dim Inbox As MAPIFolder
Dim openMsg As Outlook.MailItem
Dim mySubFolder As MAPIFolder
Dim Attachment As Outlook.Attachment
Dim myAttachments As Outlook.Attachments
Dim FileName As String
Dim myInspector As Outlook.Inspector
Dim Item As Object
Dim sFileType As String
Set ns = GetNamespace("MAPI")
Set Inbox = ns.GetDefaultFolder(olFolderInbox)
Set mySubFolder = Inbox.Folders("PdfTest")
mySubFolder.Display
Set openMsg = mySubFolder.Items(1)
openMsg.Display
mySubFolder.Application.ActiveExplorer.Close
openMsg.Application.ActiveWindow
Set myAttachments = openMsg.Attachments
If myAttachments.Count Then
For Each Attachment In myAttachments
'Last 4 Characters in a Filename
sFileType = LCase$(Right$(Attachment.FileName, 4))
Select Case sFileType
' Add additional file types below
Case ".pdf" ', ".doc", "docx", ".xls"
FileName = "C:\temp\" & Attachment.FileName
Attachment.SaveAsFile FileName
ShellExecute 0, "open", FileName, vbNullString, vbNullString, 0
End Select
Next
End If
End Sub
Option Explicit Statement (Visual Basic)
Setting Option Explicit to Off is generally not a good practice. You could misspell a variable name in one or more locations, which would cause unexpected results when the program is run.

Related

save attachment to ftp in outlook with vba

I wanted to save an attached excel file in outlook to a ftp space with VBA.
I have mapped ftp folder in Windows 10 and I can reach it.
But macro cannot save attachment in that folder. The code is
Public Sub CheckEmail_BlueRecruit()
Dim outlookApp As Outlook.Application
Dim outlookNamespace As Outlook.NameSpace
Dim outlookFolder As Outlook.MAPIFolder
Dim filterKeywords As String
Dim filter As String
Set outlookApp = New Outlook.Application
Set outlookNamespace = Outlook.GetNamespace("MAPI")
Set outlookFolder = outlookNamespace.GetDefaultFolder(olFolderInbox)
filterKeywords = "I: Reservations"
filter = "#SQL=" & Chr(34) & "urn:schemas:httpmail:subject" & Chr(34) & " LIKE '%" & filterKeywords & " %'"
LoopFolders outlookFolder, filter
End Sub
Private Sub LoopFolders(ByVal outlookFolder As Outlook.MAPIFolder, ByVal filter As String)
Dim outlookSubFolder As Outlook.MAPIFolder
Dim outlookMail As Outlook.MailItem
ProcessFolder outlookFolder, filter
If outlookFolder.Folders.Count > 0 Then
For Each outlookSubFolder In outlookFolder.Folders
LoopFolders outlookSubFolder, filter
Next
End If
End Sub
Private Sub ProcessFolder(ByVal outlookFolder As Outlook.MAPIFolder, ByVal filter As String)
Dim outlookItems As Outlook.Items
Dim outlookMail As Outlook.MailItem
Set outlookItems = outlookFolder.Items.Restrict(filter)
If Not outlookItems Is Nothing Then
For Each outlookMail In outlookItems
If outlookMail.Attachments.Count <> 0 Then
For i = outlookMail.Attachments.Count To 1 Step -1
'Debug.Print outlookMail.Subject
strFile = outlookMail.Attachments.Item(i).FileName
Debug.Print strFile
strFolderpath = "ftp://myserverexample.it/public_html/check/import/drive/"
outlookMail.Attachments.Item(i).SaveAsFile strFolderpath & strFile
Next i
End If
Next outlookMail
End If
End Sub
Manually I can navigate the FTP folder as a normal Window folder, but macro cannot save in that position, Why?
Thx a lot
The Attachment.SaveAsFile method takes a string as a parameter which stands for the location at which to save the attachment. The string should be represented by a local file path. After saving the file on the hard drive locally you can upload it to any ftp server programmatically.

Excel VBA, "Print" secured pdf to another pdf file using Shell

I have searched inside a folder in outlook, found all emails with a defined title, and downloaded their attachments into a folder via Excel VBA.
I now need to print those to new pdfs via Adobe Reader XI through VBA - as they are password protected- to be able to convert to RFT (I use VBA to get data from the PDF converted to RFT).
Somehow the correct RF layout is only created if the already saved pdf file is printed to a secondary pdf- Saving doesn't work - whether by explorer pdf viewer, Nitro or Adobe makes no difference.
I have tried Attachment.Printout but get error that the object does not support, am not able to find the option within a Shellexecute that will allow printing to file, as the main advice online allows printing via:
Call apiShellExecute(Application.hwnd, "print", strPathAndFilename, vbNullString, vbNullString, 0)
with options /p and /h for printing. any help on how to accomplish this with or without shell (or directly convert secured pdf to rft is appreciated).
The code I use ( borrowed and edited from VBA to loop through email attachments and save based on given criteria) for automatically downloading the files is listed bellow:
Sub email234()
Application.ScreenUpdating = False
Dim sPSFileName As String
Dim sPDFFileName As String
Dim olApp As Object
Dim ns As Namespace
Set olApp = CreateObject("Outlook.Application")
Set ns = olApp.GetNamespace("MAPI")
Dim oItem As Object
Dim olMailItem As Outlook.MailItem
Dim olNameSpace As Object
Dim olFolder As Object
Dim olFolderName As String
Dim olAtt As Outlook.Attachments
Dim strName As String
Dim sPath As String
Dim i As Long
Dim j As Integer
Dim olSubject As String
Dim olSender As String
Dim sh As Worksheet
Dim LastRow As Integer
olFolderName = "\\Subscriptions\Inbox" 'ThisWorkbook.Worksheets("Control").Range("D10")
olSender = "Argus Alerts" 'ThisWorkbook.Worksheets("Control").Range("D16")
sPath = Application.FileDialog(msoFileDialogFolderPicker).Show
sPathstr = Application.FileDialog(msoFileDialogFolderPicker).SelectedItems(1)
Set olNameSpace = olApp.GetNamespace("MAPI")
'check if folder is subfolder or not and choose olFolder accordingly
Set olFolder = ns.Folders("Subscriptions").Folders("Inbox")
strName = "Argus Ammonia"
h = 2
For i = 1 To olFolder.Items.Count
If olFolder.Items(i).Class <> olMail Then
Else
Set olMailItem = olFolder.Items(i)
'check if the search name is in the email subject
'If (InStr(1, olMailItem.Subject, olSubject, vbTextCompare) <> 0) Then
If (InStr(1, olMailItem.Sender, olSender, vbTextCompare) <> 0) Then
With olMailItem
For j = 1 To .Attachments.Count
strName = .Attachments.Item(j).DisplayName
'check if file already exists
If Not Dir(sPathstr & "\" & strName) = vbNullString Then
strName = "(1)" & strName
Else
End If
If Err.Number <> 0 Then
Else
.Attachments(j).SaveAsFile sPathstr & "\" & strName
End If
Err.Clear
Set sh = Nothing
'wB.Close
On Error GoTo 0
h = h + 1
Next j
End With
End If
End If
Next i
Application.ScreenUpdating = True
MsgBox "Download complete!", vbInformation + vbOKOnly, "Done"
End Sub
You can hard code the path to your EXE, please refer to the below code:
Declare Function FindExecutable Lib "shell32.dll" Alias "FindExecutableA" _
(ByVal lpFile As String, ByVal lpDirectory As String, ByVal lpResult As String) As Long
Sub Test_Printpdf()
Dim fn$
fn = "C:\Users\Ken\Dropbox\Excel\pdf\p1.pdf"
PrintPDf fn
End Sub
Sub PrintPDf(fn$)
Dim pdfEXE$, q$
pdfEXE = ExePath(fn)
If pdfEXE = "" Then
MsgBox "No path found to pdf's associated EXE.", vbCritical, "Macro Ending"
Exit Sub
End If
q = """"
'http://help.adobe.com/livedocs/acrobat_sdk/10/Acrobat10_HTMLHelp/wwhelp/wwhimpl/common/html/wwhelp.htm?context=Acrobat10_SDK_HTMLHelp&file=DevFAQ_UnderstandingSDK.22.31.html
'/s/o/h/p/t
Shell q & pdfEXE & q & " /s /o /h /t " & q & fn & q, vbHide
End Sub
Function ExePath(lpFile As String) As String
Dim lpDirectory As String, sExePath As String, rc As Long
lpDirectory = "\"
sExePath = Space(255)
rc = FindExecutable(lpFile, lpDirectory, sExePath)
sExePath = Left$(sExePath, InStr(sExePath, Chr$(0)) - 1)
ExePath = sExePath
End Function
Sub Test_ExePath()
MsgBox ExePath(ThisWorkbook.FullName)
End Sub
Added an API method to find the path, the command line parameters don't work as well with the newer Adobe Acrobat Reader DC.
For more information, please refer to these links:
Printing a file using VBA code
Print a PDF file using VBA

VBA Outlook Run-time error '438': Object doesn't support this property or method

I am trying to run this to macro to move an email attachment from a folder in my inbox (called toolkit downloads) into a folder on my desktop and rename the attachment.
I get
Run-time error '438': Object doesn't support this property or method
Sub OSP()
Dim oOutlook As Outlook.Application
Dim oNs As Outlook.NameSpace 'Main Outlook Today
Dim oFldrSb As Outlook.MAPIFolder 'Sub Folder in Outlook Today
Dim oFldrSbSb As Outlook.MAPIFolder 'Sub in Sub Folder
Dim oFldrSbSbsb As Outlook.MAPIFolder 'Sub in Sub in Sub Folder
Dim oMessage As Object
Dim sPathName As String
Dim oAttachment As Outlook.Attachment
Dim Ictr As Integer
Dim iAttachCnt As Integer
sPathName = "H:\Desktop\Toolkit Downloads\" 'My Folder Path where to save attachments
Set oOutlook = New Outlook.Application
Set oNs = oOutlook.GetNamespace("MAPI")
Set oFldrSb = oNs.Folders("Joe.Bloggs#test.co.uk")
Set oFldrSbSb = oFldrSb.Folders("Inbox")
Set oFldrSbSbsb = oFldrSbSb.Folders("Toolkit Downloads")
For Each oMessage In oFldrSbSbsb.Items
With oMessage.Attachments
iAttachCnt = .Count
If iAttachCnt > 0 Then
For Ictr = 1 To iAttachCnt
.Item(Ictr).SaveAsFile sPathName _
& .Item(Ictr).Parent
Next Ictr
End If
End With
DoEvents
Next oMessage
SaveAttachments = True
MsgBox "All Indepol Download files have been moved !!" & vbCrLf & vbCrLf & "It worked... Yahoo"
End Sub
You are trying to use the MailItem object as a string in the method SaveAsFile, ergo the error.
I'm guessing that you want to include the mail's subject into the new file name :
.Item(Ictr).SaveAsFile sPathName _
& .Item(Ictr).Parent.Subject
And if you have multiples attachments, I'd add the initial file name in there :
.Item(Ictr).SaveAsFile sPathName _
& .Item(Ictr).Parent.Subject
& .Item(Ictr).FileName
Full code :
Sub OSP()
Dim oOutlook As Outlook.Application
Dim oNs As Outlook.NameSpace 'Main Outlook Today
Dim oFldrSb As Outlook.MAPIFolder 'Sub Folder in Outlook Today
Dim oFldrSbSb As Outlook.MAPIFolder 'Sub in Sub Folder
Dim oFldrSbSbsb As Outlook.MAPIFolder 'Sub in Sub in Sub Folder
Dim oMessage As Object
Dim sPathName As String
Dim oAttachment As Outlook.Attachment
Dim Ictr As Integer
Dim iAttachCnt As Integer
sPathName = "H:\Desktop\Toolkit Downloads\" 'My Folder Path where to save attachments
Set oOutlook = Application
Set oNs = oOutlook.GetNamespace("MAPI")
Set oFldrSb = oNs.Folders("Joe.Bloggs#test.co.uk")
Set oFldrSbSb = oFldrSb.Folders("Inbox")
Set oFldrSbSbsb = oFldrSbSb.Folders("Toolkit Downloads")
For Each oMessage In oFldrSbSbsb.items
With oMessage.Attachments
iAttachCnt = .Count
If iAttachCnt > 0 Then
For Ictr = 1 To iAttachCnt
.Item(Ictr).SaveAsFile sPathName _
& .Item(Ictr).Parent.Subject
& .Item(Ictr).FileName
Next Ictr
End If
End With
DoEvents
Next oMessage
SaveAttachments = True
MsgBox "All Indepol Download files have been moved !!" & vbCrLf & vbCrLf & "It worked... Yahoo"
End Sub
First of all, there is no need to create a new Outlook Application instance if you run the VBA macro in Outlook:
Set oOutlook = New Outlook.Application
Instead, use the Application property available in the defualt module.
The SaveAsFile method of the Attachment class accepts a string which stands for the location at which to save the attachment. Make sure a string is passed there.
In general, I'd suggest debugging the code line by line and find which property or method exactly generates an error. You may find the Getting Started with VBA in Outlook 2010 article helpful.

Reference messages and access attachments

I am writing a program to track the current status of projects.
The users would like to save relevant documents to the current project. I can do this for files that are residing in a folder with FileSaveDialog. However, many times the file is an e-mail message or an attachment to a message. I would like to grab this directly from Outlook and either save the message as an MSG or save the attachment.
I have code like below to reference Outlook messages from VB.NET but I can't figure out how to reference an entire message to save as msg or attachment filename.
Dim objOutlook As Outlook._Application
objOutlook = New Outlook.Application()
Dim objSelection As Outlook.Selection = objOutlook.ActiveExplorer.Selection
Dim iCount As Int16 = objSelection.Count
For i = iCount To 1 Step -1
Console.WriteLine(objSelection.Item(i).Subject)
Console.WriteLine(objSelection.Item(i).Attachments)
Next
Use the Outlook Object Library for this.
An example on how to download an attachment from an unread mail:
Private Sub ThisAddIn_NewMail() Handles Application.NewMail
Dim inBox As Outlook.MAPIFolder = Me.Application.ActiveExplorer() _
.Session.GetDefaultFolder(Outlook. _
OlDefaultFolders.olFolderInbox)
Dim inBoxItems As Outlook.Items = inBox.Items
Dim newEmail As Outlook.MailItem
inBoxItems = inBoxItems.Restrict("[Unread] = true")
Try
For Each collectionItem As Object In inBoxItems
newEmail = TryCast(collectionItem, Outlook.MailItem)
If newEmail IsNot Nothing Then
If newEmail.Attachments.Count > 0 Then
For i As Integer = 1 To newEmail.Attachments.Count
Dim saveAttachment As Outlook.Attachment = _
newEmail.Attachments(i)
newEmail.Attachments(i).SaveAsFile _
("C:\TestFileSave\" & (newEmail _
.Attachments(i).FileName))
Next i
End If
End If
Next collectionItem
Catch ex As Exception
If Left(ex.Message, 11) = "Cannot save" Then
MsgBox("Create Folder C:\TestFileSave")
End If
End Try
End Sub
Good luck!
Source: msdn
Having the same problem as you on saving an e-mail message I ended up with the following solution:
Sub SaveEmail()
'Save e-mail from Outlook
Dim objOL As Outlook.Application
Dim objMsg As Outlook.MailItem 'Object
Dim objSelection As Outlook.Selection
Dim strFile As String
'Instantiate an Outlook Application object.
objOL = CreateObject("Outlook.Application")
'Get the collection of selected objects.
objSelection = objOL.ActiveExplorer.Selection
'Set the target folder
Dim FilePath1 as String
FilePath1 = "C:\tmp\"
'Save each selected e-mail to disk
For Each objMsg In objSelection
'Save attachment before deleting from item.
'Get the file name using "objMsg.Subject" and remove special characters.
strFile = Regex.Replace(objMsg.Subject, "[^a-zA-Z0-9_ -]", "-",_
RegexOptions.Compiled)
'Combine with the path to the Temp folder.
strFile = FilePath1 & strFile & ".msg"
'Save the attachment as a file.
objMsg.SaveAs(strFile, Outlook.OlSaveAsType.olMSG)
Next
End Sub
For a bit of input on the regex.replace function please see the following links:
https://www.regular-expressions.info/charclass.html
https://learn.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regex.replace?view=netframework-4.7.2#System_Text_RegularExpressions_Regex_Replace_System_String_System_String_System_String_

VBA/Outlook extracting attachments from .eml files

I'm trying to take a folder full of .eml messages with attachments and then extract/rename/save the attachments in another folder. My code :
Sub SaveAttachments()
Dim OlApp As Outlook.Application
Set OlApp = GetObject(, "Outlook.Application")
Dim MsgFilePath
Dim Eml As Outlook.MailItem
Dim att As Outlook.Attachments
Dim Path As String
Path = "C:\Users\richard\Desktop\Inbox\"
If OlApp Is Nothing Then
Err.Raise ERR_OUTLOOK_NOT_OPEN
End If
Dim fs As Object
Set fs = CreateObject("Scripting.FileSystemObject")
Dim temp As Object
Set temp = fs.GetFolder(Path)
For Each MsgFilePath In temp.Files
Set Eml = OlApp.CreateItemFromTemplate(Path & MsgFilePath.Name)
Set att = Eml.Attachments
If att.Count > 0 Then
For i = 1 To att.Count
fn = "C:\Users\richard\Desktop\cmds\" & Eml.SenderEmailAddress
att(i).SaveAsFile fn
Next i
End If
Set Eml = Nothing
Next
Set OlApp = Nothing
End Sub
But I'm getting straightaway this error on the first file in the loop, ie the line
Set Eml = OlApp.CreateItemFromTemplate(Path & MsgFilePath.Name) :
-2147286960 (80030050) %1 already exists.
Any ideas on what is going on much appreciated !
Try this (TRIED AND TESTED)
Private Declare Function ShellExecute Lib "shell32.dll" Alias _
"ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As _
String, ByVal lpFile As String, ByVal lpParameters As String, _
ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
Private Const SW_SHOWNORMAL As Long = 1
Private Const SW_SHOWMAXIMIZED As Long = 3
Private Const SW_SHOWMINIMIZED As Long = 2
Sub SaveAttachments()
Dim OlApp As Outlook.Application
Set OlApp = GetObject(, "Outlook.Application")
Dim MsgFilePath
Dim Eml As Outlook.MailItem
Dim att As Outlook.Attachments
Dim sPath As String
sPath = "C:\Users\richard\Desktop\Inbox\"
If OlApp Is Nothing Then
Err.Raise ERR_OUTLOOK_NOT_OPEN
End If
sFile = Dir(sPath & "*.eml")
Do Until sFile = ""
ShellExecute 0, "Open", sPath & sFile, "", sPath & sFile, SW_SHOWNORMAL
Wait 2
Set MyInspect = OlApp.ActiveInspector
Set Eml = MyInspect.CurrentItem
Set att = Eml.Attachments
If att.Count > 0 Then
For i = 1 To att.Count
fn = "C:\Users\richard\Desktop\cmds\" & i & "-" & Eml.SenderEmailAddress
att(i).SaveAsFile fn
Next i
End If
sFile = Dir$()
Loop
Set OlApp = Nothing
End Sub
Private Sub Wait(ByVal nSec As Long)
nSec = nSec + Timer
While nSec > Timer
DoEvents
Wend
End Sub