How to extract PDF attachments from Outlook and save to Folder - vba

I need VBA code to use in Outlook to extract the PDF attachments from emails and save into a designated folder. The user will choose the emails.
I have the below code but need it amended.
Public Sub SaveAutoAttach(item As Outlook.MailItem)
Dim object_attachment As Outlook.Attachment
Dim saveFolder As String
' Folder location when I want to save my file
saveFolder = "D:\Data\Archive"
For Each object_attachment In item.Attachments
' Criteria to save .doc files only
If InStr(object_attachment.DisplayName, ".doc") Then
object_attachment.SaveAsFile saveFolder & "\" & object_attachment.DisplayName
End If
Next
End Sub

As per your request, the following macro will save any PDF attachments from one or more user selected items.
Option Explicit
Sub SaveAttachmentsFromSelectedItemsPDF()
Dim currentItem As Object
Dim currentAttachment As Attachment
Dim saveToFolder As String
Dim savedFileCountPDF As Long
saveToFolder = "c:\users\domenic\desktop" 'change the path accordingly
savedFileCountPDF = 0
For Each currentItem In Application.ActiveExplorer.Selection
For Each currentAttachment In currentItem.Attachments
If UCase(Right(currentAttachment.DisplayName, 4)) = ".PDF" Then
currentAttachment.SaveAsFile saveToFolder & "\" & _
Left(currentAttachment.DisplayName, Len(currentAttachment.DisplayName) - 4) & "_" & Format(Now, "yyyy-mm-dd_hh-mm-ss") & ".pdf"
savedFileCountPDF = savedFileCountPDF + 1
End If
Next currentAttachment
Next currentItem
MsgBox "Number of PDF files saved: " & savedFileCountPDF, vbInformation
End Sub

Related

How do I add date to attachment name?

My VBA code downloads attachments from emails to my local drive. I would like to rename the attachments to include the date. The date should be the day before the email was received.
Public Sub SaveAutoAttach(item As Outlook.MailItem)
Dim object_attachment As Outlook.Attachment
Dim saveFolder As String
' Folder location when I want to save my file
saveFolder = "\\gbhxxxx\Groups\Shared\EBS\Post Go-Live\Auto MT940 download Test"
For Each object_attachment In item.Attachments
' Criteria to save .940 files only
If InStr(object_attachment.DisplayName, "UKAutoMT940") Then
object_attachment.SaveAsFile saveFolder & "\" & object_attachment.DisplayName
End If
Next
End Sub
Updated your code below to append the date BEFORE the display file name. We do this by using DATEADD and adding -1 days to the recieved date and FORMATting the datetime value into a date value with "-"s instead of "/"s.
If you're looking to add it AFTER the filename but before the extension, we'll need to parse to filename.
Public Sub SaveAutoAttach(item As Outlook.MailItem)
Dim object_attachment As Outlook.Attachment
Dim saveFolder As String
' Folder location when I want to save my file
saveFolder = "\\gbhxxxx\Groups\Shared\EBS\Post Go-Live\Auto MT940 download Test"
For Each object_attachment In item.Attachments
' Criteria to save .940 files only
If InStr(object_attachment.DisplayName, "UKAutoMT940") Then
object_attachment.SaveAsFile saveFolder & "\" & Format(DateAdd("d", -1, item.ReceivedTime), "dd-mm-yyyy") & "_" & object_attachment.DisplayName
End If
Next
End Sub

Select email that triggers script

I am working on a Outlook script that will automatically select an email, and download the attachments, from a specific sender.
Reports are generated on a database and emailed to a specified address.
The next step is to automatically download those reports to a specified folder. Currently if an email comes in from the specified sender the script downloads attachments from the currently selected email.
I need the script to run on the email that triggers the script.
Public Sub SaveAttachments(Item As Outlook.MailItem)
Dim objOL As Outlook.Application
Dim objMsg As Outlook.MailItem 'Object
Dim objAttachments As Outlook.Attachments
Dim objSelection As Outlook.Selection
Dim i As Long
Dim lngCount As Long
Dim strFile As String
Dim strFolderpath As String
Dim strDeletedFiles As String
'Get the path to the target folder
strFolderpath = CreateObject("WScript.Shell").SpecialFolders(16)
On Error Resume Next
'Instantiate an Outlook Application Object
Set objOL = CreateObject("Outlook.Application")
'Get the collection of selected objects
Set objSelection = objOL.ActiveExplorer.Selection
'Set the Attachment folder
strFolderpath = strFolderpath & "\Attachments\"
'Check each selected item for attachements. If attachments exist, save them
'to the strFOlderPath folder and strip them from the item.
For Each objMsg In objSelection
'This code only strips attachments from mail items.
'If objMsg.class=olMail Then
'Get the Attachments collection of the item
Set objAttachments = objMsg.Attachments
lngCount = objAttachments.Count
strDeletedFile = ""
If lngCount > 0 Then
'A count down loop needs to be used for removing items
'from a collection. Otherwise the loop counter gets
'confused and only every other item is removed
For i = lngCount To 1 Step -1
'Save attachment before deleting from item.
'Get the file name
strFile = objAttachments.Item(i).FileName
'Combine with the path to the Temp folder.
strFile = strFolderpath & strFile
'Save the attachment as a file
objAttachments.Item(i).SaveAsFile strFile
'Delete the attachment
objAttachments.Item(i).Delete
'write the save as path to a string to add to the
'message check from html and use html tags in link
If objMsg.BodyFormat <> olFormatHTML Then
strDeletedFile = strDeletedFiles & vbCrLf & "<file://" & strFile & ">"
Else
strDeletedFiles = strDeletedFiles & "<br>" & "<a href='file://" & _
strFile & "'>" & strFile & "</a>"
End If
'use the MsgBox command to troubleshoot. Remove it from the final code.
'MsgBox strDeletedFiles
Next i
'Adds the filename string to the message body and save it
'Checks for HTML body
If objMsg.BodyFormat <> olFormatHTML Then
objMsg.Body = vbCrLf & "The File(s) were saved to " & strDeletedFiles & vbCrLf & objMsg.Body
Else
objMsg.HTMLBody = "<p>" & "The file(s) were saved to " & strDeletedFiles & "</p>" & objMsg.HTMLBody
End If
objMsg.Save
End If
Next
Exit Sub:
Set objAttachments = Nothing
Set objMsg = Nothing
Set objSelection = Nothing
Set objOL = Nothing
End Sub
I made some changes and this code does the intended purpose.
Public Sub SaveAttachments(Item As Outlook.MailItem)
Dim objOL As Outlook.Application
Dim objAttachments As Outlook.Attachments
Dim i As Long
Dim lngCount As Long
Dim strFile As String
Dim strFolderpath As String
Dim strDeletedFiles As String
'Get the path to the target folder
strFolderpath = CreateObject("WScript.Shell").SpecialFolders(16)
On Error Resume Next
'Instantiate an Outlook Application Object
Set objOL = CreateObject("Outlook.Application")
'Set the Attachment folder
strFolderpath = strFolderpath & "\Attachments\"
'Check each selected item for attachements. If attachments exist, save them
'to the strFOlderPath folder and strip them from the item.
For Each objAttachments In Item.Attachments
'This code only strips attachments from mail items.
'If objMsg.class=olMail Then
'Get the Attachments collection of the item
Set objAttachments = Item.Attachments
lngCount = objAttachments.Count
strDeletedFile = ""
If lngCount > 0 Then
'A count down loop needs to be used for removing items
'from a collection. Otherwise the loop counter gets
'confused and only every other item is removed
For i = lngCount To 1 Step -1
'Save attachment before deleting from item.
'Get the file name
strFile = objAttachments.Item(i).FileName
'Combine with the path to the Temp folder.
strFile = strFolderpath & strFile
'Save the attachment as a file
objAttachments.Item(i).SaveAsFile strFile
'Delete the attachment
objAttachments.Item(i).Delete
'write the save as path to a string to add to the
'message check from html and use html tags in link
If Item.BodyFormat <> olFormatHTML Then
strDeletedFile = strDeletedFiles & vbCrLf & "<file://" & strFile & ">"
Else
strDeletedFiles = strDeletedFiles & "<br>" & "<a href='file://" & _
strFile & "'>" & strFile & "</a>"
End If
'use the MsgBox command to troubleshoot. Remove it from the final code.
'MsgBox strDeletedFiles
Next i
'Adds the filename string to the message body and save it
'Checks for HTML body
If Item.BodyFormat <> olFormatHTML Then
Item.Body = vbCrLf & "The File(s) were saved to " & strDeletedFiles & vbCrLf & Item.Body
Else
Item.HTMLBody = "<p>" & "The file(s) were saved to " & strDeletedFiles & "</p>" & Item.HTMLBody
End If
Item.Save
End If
Next objAttachments
Exit Sub:
Set objAttachments = Nothing
Set objOL = Nothing
End Sub
To apply code to the item, do not select anything.
Instead use Item passed in (Item As MailItem).
In the question and the answer posted by the OP, if strFolderpath does not exist, the error when saving will be bypassed.
The attachments will be unrecoverably deleted without being saved.
This is due to improper use of On Error Resume Next.
"There are specific occasions when this is useful. Most of the time you should avoid using it."
https://excelmacromastery.com/vba-error-handling#On_Error_Resume_Next
Option Explicit ' Consider this mandatory
' Tools | Options | Editor tab
' Require Variable Declaration
' If desperate declare as Variant
Private Sub test()
SaveAttachments ActiveInspector.currentItem
End Sub
Public Sub SaveAttachments(Item As MailItem)
'Check the Item passed in (Item As MailItem) for attachments.
'
'If attachments exist,
' save them to the strFolderpath folder and
' strip them from the item.
Dim objAttachment As Attachment
Dim objAttachments As Attachments
Dim i As Long
Dim lngCount As Long
Dim strFile As String
Dim strFolderpath As String
Dim strDeletedFiles As String
'Get the path to the target folder
strFolderpath = CreateObject("WScript.Shell").SpecialFolders(16)
Debug.Print strFolderpath
'Set the Attachment folder
strFolderpath = strFolderpath & "\Attachments\"
Debug.Print strFolderpath
'Get the Attachments collection of the item
Set objAttachments = Item.Attachments
lngCount = objAttachments.Count
'A count down loop for removing items, through move or delete, from a collection.
'Otherwise only every other item is removed.
For i = lngCount To 1 Step -1
'Save attachment before deleting from item.
'Get the file name
strFile = objAttachments(i).fileName
Debug.Print strFile
'Combine the path to the folder with file name.
strFile = strFolderpath & strFile
Debug.Print strFile
'Save the attachment as a file
'If strFolderpath does not exist there will be an error.
'This is good.
objAttachments.Item(i).SaveAsFile strFile
'Delete the attachment
' Uncomment after verifying attachments are being saved
'objAttachments.Item(i).Delete
'Write the save as path to a string to add to the message
'Check from html and use html tags in link
If Item.BodyFormat <> olFormatHTML Then
strDeletedFiles = strDeletedFiles & vbCrLf & "<file://" & strFile & ">"
Else
strDeletedFiles = strDeletedFiles & "<br>" & "<a href='file://" & _
strFile & "'>" & strFile & "</a>"
End If
Next
'Add the filename string to the message body and save it
'Check for HTML body
If Item.BodyFormat <> olFormatHTML Then
Item.body = vbCrLf & "The File(s) were saved to " & strDeletedFiles & vbCrLf & Item.body
Else
Item.HtmlBody = "<p>" & "The file(s) were saved to " & strDeletedFiles & "</p>" & Item.HtmlBody
End If
Item.Display 'Item.Save
End Sub
You pass the mailitem that triggers the script as a parameter.
If, for example, you pass Item then process Item.
Sub CustomMailMessageRule(Item As MailItem)
MsgBox "Mail message arrived: " & Item.Subject
End Sub

Rule/Macro to rename pdf files and resend to different recipient?

How do I rename a pdf attachment the same as the subject line and then email the renamed file to a different recipient.
For instance, the email I receive will have a subject line of "123456-CHM78912" but the attachment pdf name will be "INV-5".
Public Sub saveAttachtoDisk(itm As Outlook.MailItem)
Dim objAtt As Outlook.Attachment
Dim saveFolder As String
saveFolder = "C:\Temp\"
For Each objAtt In itm.Attachments
objAtt.SaveAsFile saveFolder & "\" & objAtt.DisplayName
Set objAtt = Nothing
Next
End Sub
Set your outlook rule and call the following scrip,
Option Explicit
Public Sub SaveAtmts(Item As Outlook.MailItem)
Dim Atmt As Outlook.Attachment
Dim Path As String
Dim SaveAtmt As String
Dim AtmtName As String
Path = "C:\Temp\"
AtmtName = Item.Subject & ".pdf"
For Each Atmt In Item.Attachments
If Right(Atmt.FileName, 3) = "pdf" Then
SaveAtmt = Path & AtmtName
Atmt.SaveAsFile SaveAtmt
End If
Next
' // Email the file
Set Item = Application.CreateItem(olMailItem)
With Item
.Subject = "Subject"
.body = AtmtName & " Report Attached "
.To = "0m3r#Email.com"
.Attachments.Add SaveAtmt
' // Display msg
' .Display
' ' Or Send
.Send
End With
End Sub

Save Attachments from Outlook with ReceivedTime on file name

I'm trying to create a macro where I can save the attachments from an email. The problem I'm currently having is that I want the macro to add the ReceivedTime of the email on the file name it saves (i.e.: File TESTSHEET.xls was received on 2016-01-01 3:02AM. I want the saved file to show 201601010302AM-TESTSHEET.xls or something similar)
Here's my current code:
Public itm As Object
Public Sub saveAttachtoDisk()
Dim objAtt As Outlook.Attachment
Dim saveFolder As String
saveFolder = "C:\Users\Username\Documents\TEST REPORTS"
For Each objAtt In itm.Attachments
objAtt.SaveAsFile objAtt.DisplayName
Next objAtt
End Sub
Public Sub SaveAttachments()
Dim objOL As Outlook.Application
Dim objMsg As Outlook.MailItem 'Object
Dim objAttachments As Outlook.Attachments
Dim objSelection As Outlook.Selection
Dim objDate As String
Dim i As Long
Dim lngCount As Long
Dim strFile As String
Dim StrDate As String
Dim strFolderpath As String
Dim strDeletedFiles As String
Set itm = Application.CreateItem(olMailItem)
Dim CurrentMsg As Outlook.MailItem
' Get the path to your My Documents folder
strFolderpath = CreateObject("WScript.Shell").SpecialFolders(16)
On Error Resume Next
' Instantiate an Outlook Application object.
Set objOL = CreateObject("Outlook.Application")
' Get the collection of selected objects.
Set objSelection = objOL.ActiveExplorer.Selection
' Set the Attachment folder.
strFolderpath = strFolderpath & "\TEST REPORTS\"
' Check each selected item for attachments. If attachments exist,
' save them to the strFolderPath folder and strip them from the item.
For Each objMsg In objSelection
' This code only strips attachments from mail items.
' If objMsg.class=olMail Then
' Get the Attachments collection of the item.
Set objAttachments = objMsg.Attachments
lngCount = objAttachments.Count
strDeletedFiles = ""
If lngCount > 0 Then
' We need to use a count down loop for removing items
' from a collection. Otherwise, the loop counter gets
' confused and only every other item is removed.
For i = lngCount To 1 Step -1
' Save attachment before deleting from item.
' Get the file name.
strFile = objAttachments.Item(i).FileName
' Combine with the path to the Save folder.
StrDate = Format(itm.ReceivedTime, "yyyy-mm-dd Hmm ")
strFile = strFolderpath & StrDate & strFile
' Save the attachment as a file.
MsgBox strFile
objAttachments.Item(i).SaveAsFile strFile
' Delete the attachment.
objAttachments.Item(i).Delete
'write the save as path to a string to add to the message
'check for html and use html tags in link
If objMsg.BodyFormat <> olFormatHTML Then
strDeletedFiles = strDeletedFiles & vbCrLf & "<file://" & strFile & ">"
Else
strDeletedFiles = strDeletedFiles & "<br>" & "<a href='file://" & _
strFile & "'>" & strFile & "</a>"
End If
'Use the MsgBox command to troubleshoot. Remove it from the final code.
'MsgBox strDeletedFiles
Next i
' Adds the filename string to the message body and save it
' Check for HTML body
If objMsg.BodyFormat <> olFormatHTML Then
objMsg.Body = vbCrLf & "The file(s) were saved to " & strDeletedFiles & vbCrLf & objMsg.Body
Else
objMsg.HTMLBody = "<p>" & "The file(s) were saved to " & strDeletedFiles & "</p>" & objMsg.HTMLBody
End If
objMsg.Save
End If
Next
ExitSub:
Set objAttachments = Nothing
Set objMsg = Nothing
Set objSelection = Nothing
Set objOL = Nothing
End Sub
Thank you in advance for your help!!
Use objMsg not itm.
' StrDate = Format(itm.ReceivedTime, "yyyy-mm-dd Hmm ")
StrDate = Format(objMsg.ReceivedTime, "yyyy-mm-dd Hmm ")
Additionally drop other code with itm and as well objOL
' Set itm = Application.CreateItem(olMailItem)
' Dim CurrentMsg As Outlook.MailItem
' On Error Resume Next
' Instantiate an Outlook Application object.
' Set objOL = CreateObject("Outlook.Application")
Do not use On Error Resume Next until you know what you are doing.

Trying to setup a VBA module in Outlook 2013 that saves the attachments to a folder automatically

I'm setting up a script in outlook that saves some PDF attachments as the date they were received. This will save the file to the desired location but it wont name it as the date received how would i add this in?
There is probably a lot of unused code in here as i got it from another website and have removed a few things i don't want such as deleting the attachment after its saved.
Public Sub SaveAttachments()
Dim objOL As Outlook.Application
Dim objMsg As Outlook.MailItem 'Object
Dim objAttachments As Outlook.Attachments
Dim objSelection As Outlook.Selection
Dim i As Long
Dim lngCount As Long
Dim strFile As String
Dim strFolderpath As String
Dim strDeletedFiles As String
' Get the path to your My Documents folder
strFolderpath = "D:\Documents\"
On Error Resume Next
' Instantiate an Outlook Application object.
Set objOL = CreateObject("Outlook.Application")
' Get the collection of selected objects.
Set objSelection = objOL.ActiveExplorer.Selection
' Set the Attachment folder.
strFolderpath = strFolderpath
' Check each selected item for attachments. If attachments exist,
' save them to the strFolderPath folder and strip them from the item.
For Each objMsg In objSelection
' This code only strips attachments from mail items.
' If objMsg.class=olMail Then
' Get the Attachments collection of the item.
Set objAttachments = objMsg.Attachments
lngCount = objAttachments.Count
strDeletedFiles = ""
If lngCount > 0 Then
' We need to use a count down loop for removing items
' from a collection. Otherwise, the loop counter gets
' confused and only every other item is removed.
For i = lngCount To 1 Step -1
' Save attachment before deleting from item.
' Get the file name.
strFile = objAttachments.Item(i).FileName
' Combine with the path to the Temp folder.
strFile = strFolderpath & strFile
' Save the attachment as a file.
objAttachments.Item(i).SaveAsFile strFile
'write the save as path to a string to add to the message
'check for html and use html tags in link
If objMsg.BodyFormat <> olFormatHTML Then
strDeletedFiles = strDeletedFiles & vbCrLf & "<file://" & strFile & ">"
Else
strDeletedFiles = strDeletedFiles & "<br>" & "<a href='file://" & _
strFile & "'>" & strFile & "</a>"
End If
'Use the MsgBox command to troubleshoot. Remove it from the final code.
'MsgBox strDeletedFiles
Next i
' Adds the filename string to the message body and save it
' Check for HTML body
If objMsg.BodyFormat <> olFormatHTML Then
objMsg.Body = vbCrLf & "The file(s) were saved to " & strDeletedFiles & vbCrLf & objMsg.Body
Else
objMsg.HTMLBody = "<p>" & "The file(s) were saved to " & strDeletedFiles & "</p>" & objMsg.HTMLBody
End If
objMsg.Save
End If
Next
ExitSub:
Set objAttachments = Nothing
Set objMsg = Nothing
Set objSelection = Nothing
Set objOL = Nothing
End Sub
Anything you want to change with the filename would be in this modified snippet,
strFile = strFolderpath & objAttachments.Item(i).FileName 'Add the folder and filename
strFile = left(strfile, len(strFile)-4) 'Strip the .PDF
strFile = strFile & format(Date, "MMddYYYY") & ".PDF" 'Add the date and readd .PDF
objAttachments.Item(i).SaveAsFile strFile
For different date formatting to try out, check out this
add the following function to your code:
Function Dateiendung(vDateiname As String) As String
Dim Wortlaenge As Integer
Dim StellePunkt As Integer
Wortlaenge = Len(vDateiname) ' Anzahl Zeichen des Dateinamens
StellePunkt = InStrRev(vDateiname, ".") ' Anzahl Zeichen vor dem letzten Punkt
Dateiendung = Right(vDateiname, Wortlaenge - StellePunkt) ' Dateiendung wird extrahiert
End Function
add this line at the beginning of your code:
dim fileext as string
Instead of:
strFile = objAttachments.Item(i).FileName
you have to put:
fileext = Dateiendung(objMailSel.Attachments.item(i).FileName)
strfile = Mid(objMailSel.Attachments.item(i).FileName, 1, Len(objMailSel.Attachments.item(i).FileName) - Len(fileext) - 1) & " " & Format(Date, "MMddYYYY") & " ." & fileext