When I incorporate a filter into my VBA sub, it does not filter out all the gif files from being excluded.
The sub is to remove attachments from emails and replace them with a link.
I expect to skip all instances of the gif attachments. The reasoning is for email threads where users have gif pictures in their signature, and removing the gif files will ruin the cleanness of the thread, and make it difficult for users to see who wrote which part of the email.
Here is the entire sub.
Private Sub BrowseFolder()
Dim oShell As Object
Set oShell = CreateObject("Shell.Application")
Dim fsSaveFolder As Object
Set fsSaveFolder = oShell.BrowseForFolder(0, "Please Select a Save Folder:", 1)
'Set fsSaveFolder = oShell.BrowseForFolder(0, "Please Select a Save Folder:", NO_OPTIONS, "C:\users\" & Environ("Username") & "Documents\Outlook Files")
If fsSaveFolder Is Nothing Then Exit Sub
' Note: BrowseForFolder doesn't add a trailing slash
' Ask the user to select an Outlook folder to process
Dim olPurgeFolder As Outlook.MAPIFolder
Set olPurgeFolder = Outlook.GetNamespace("MAPI").PickFolder
If olPurgeFolder Is Nothing Then Exit Sub
Dim msg As Variant
Dim att As Outlook.Attachments
Dim sSavePathFS As String
Dim sDelAtts
For Each msg In olPurgeFolder.Items
On Error GoTo GetAttachments_err
sDelAtts = ""
If TypeName(msg) = "MailItem" Then
If msg.MessageClass <> "IPM.Note.SMIME.MultipartSigned" Then
If msg.MessageClass <> "IPM.Note.Secure.Sign" Then
'If msg.Attachments.Count > 0 Then '& olByValue <> 5 & olByValue <> 6 Then
Set att = msg.Attachments
lngCount = att.Count
DelAtts = ""
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 = att.Item(i).FileName
' This code looks at the last 4 characters in a filename
sFileType = LCase$(Right$(strFile, 4))
If att.Item(i).Size < 5234111 Then
Select Case sFileType
' Add additional file types below
Case ".gif", "gif"
Case Else
'While msg.Attachments.Count > 0
On Error GoTo GetAttachments_err
' Save the attachment to the file system
sSavePathFS = fsSaveFolder.Self.Path & "\"
attachName = msg.Attachments(1).FileName
msg.Attachments(1).SaveAsFile sSavePathFS & Format(msg.ReceivedTime, "mm-dd-yyyy-ss") & attachName
' Build up a string to denote the file system save path(s)
' Format the string according to the msg.BodyFormat.
If msg.BodyFormat <> olFormatHTML Then
sDelAtts = sDelAtts & vbCrLf & "<file://" & sSavePathFS & Format(msg.ReceivedTime, "mm-dd-yyyy-ss") & attachName & ">"
Else
sDelAtts = sDelAtts & "<br>" & "<a href='file://" & sSavePathFS & Format(msg.ReceivedTime, "mm-dd-yyyy-ss") & attachName & "'>" & sSavePathFS & Format(msg.ReceivedTime, "mm-dd-yyyy-ss") & attachName & "</a>"
End If
' Delete the current attachment. We use a "1" here instead of an "i"
' because the .Delete method will shrink the size of the msg.Attachments
' collection for us. Use some well placed Debug.Print statements to see
' the behavior. ~~
msg.Attachments(1).Delete
' Wend
End Select
End If
Next
' Modify the body of the msg to show the file system location of
' the deleted attachments.
If msg.BodyFormat <> olFormatHTML Then
msg.Body = vbCrLf & vbCrLf & "Attachments Deleted: " & Date & " " & Time & vbCrLf & vbCrLf & "Saved To: " & vbCrLf & sDelAtts & msg.Body
Else
msg.HTMLBody = "<p></p><p>" & "Attachments Deleted: " & Date & " " & Time & vbCrLf & vbCrLf & "Saved To: " & vbCrLf & sDelAtts & "</p>" & msg.HTMLBody
End If
' Save the edits to the msg. If you forget this line, the attachments will not be deleted. ~~
msg.Save
End If
End If
End If
End If
Next
GetAttachments_exit:
Set att = Nothing
Set fso = Nothing
Set olPurgeFolder = Nothing
Exit Sub
' Handle errors
GetAttachments_err:
If Err.Description = "Outlook cannot perform this action on this type of attachment." Then
Err.Clear
Resume Next
End If
MsgBox "An unexpected error has occurred." _
& vbCrLf & "Please note and report the following information." _
& vbCrLf & "Macro Name: GetAttachments" _
& vbCrLf & "Error Number: " & Err.Number _
, vbCritical, "Error!"
Resume GetAttachments_exit
End Sub
Your code had some syntax errors. Those have been corrected in the code below.
If lngCount > 0 Then
For i = lngCount To 1 Step -1
' Save attachment before deleting from item.
' Get the file name.
strFile = att.Item(i).Filename
' This code looks at the last 4 characters in a filename
sFileType = LCase$(Right$(strFile, 4))
If att.Item(i).Size < 5234111 Then
Select Case sFileType
Case ".gif", "gif"
End Select
End If
Next
End If
If your intention is to delete the gif attachments then you might want to try att.Item(i).Delete on the line after Case ".gif", "gif"
I have the following macro for saving attachments, it works fine but I would like it to move the emails to another folder once the attachments have been saved. Any help would be much appreciated!
Option Explicit
Public Sub SaveFolderAttachments()
' Ask the user to select a file system folder for saving the attachments
Dim oShell As Object
Set oShell = CreateObject("Shell.Application")
Dim fsSaveFolder As Object
Set fsSaveFolder = oShell.BrowseForFolder(0, "Please Select a Save Folder:", 1)
If fsSaveFolder Is Nothing Then Exit Sub
' Note: BrowseForFolder doesn't add a trailing slash
' Ask the user to select an Outlook folder to process
Dim olPurgeFolder As Outlook.MAPIFolder
Set olPurgeFolder = Outlook.GetNamespace("MAPI").PickFolder
If olPurgeFolder Is Nothing Then Exit Sub
' Iteration variables
Dim msg As Outlook.MailItem
Dim att As Outlook.Attachment
Dim sSavePathFS As String
Dim sDelAtts
For Each msg In olPurgeFolder.Items
sDelAtts = ""
' We check each msg for attachments as opposed to using .Restrict("[Attachment] > 0")
' on our olPurgeFolder.Items collection. The collection returned by the Restrict method
' will be dynamically updated each time we remove an attachment. Each update will
' reindex the collection. As a result, it does not provide a reliable means for iteration.
' This is why the For Each loops will not work.
If msg.Attachments.Count > 0 Then
' This While loop is controlled via the .Delete method
' which will decrement msg.Attachments.Count by one each time.
While msg.Attachments.Count > 0
' Save the file
sSavePathFS = fsSaveFolder.Self.Path & "\" & msg.Attachments(1).FileName
msg.Attachments(1).SaveAsFile sSavePathFS
' Build up a string to denote the file system save path(s)
' Format the string according to the msg.BodyFormat.
If msg.BodyFormat <> olFormatHTML Then
sDelAtts = sDelAtts & vbCrLf & "<file://" & sSavePathFS & ">"
Else
sDelAtts = sDelAtts & "<br>" & "<a href='file://" & sSavePathFS & "'>" & sSavePathFS & "</a>"
End If
' Delete the current attachment. We use a "1" here instead of an "i"
' because the .Delete method will shrink the size of the msg.Attachments
' collection for us. Use some well placed Debug.Print statements to see
' the behavior.
msg.Attachments(1).Delete
Wend
' Modify the body of the msg to show the file system location of
' the deleted attachments.
If msg.BodyFormat <> olFormatHTML Then
msg.Body = msg.Body & vbCrLf & vbCrLf & "Attachments Deleted: " & Date & " " & Time & vbCrLf & vbCrLf & "Saved To: " & vbCrLf & sDelAtts
msg
Else
msg.HTMLBody = msg.HTMLBody & "<p></p><p>" & "Attachments Deleted: " & Date & " " & Time & vbCrLf & vbCrLf & "Saved To: " & vbCrLf & sDelAtts & "</p>"
End If
' Save the edits to the msg. If you forget this line, the attachments will not be deleted.
msg.Save
End If
Next
End Sub
Call MailItem.Move(MAPIFolder) to move a message. Do not use a "for each' loop if youi move the messages (since the collection count changes), use a down loop (for I = Items.Count to 1 step -1)
EDIT:
Dim objItems as Outlook.Items
set objItems = olPurgeFolder.Items
for I = objItems.Count to 1 step -1
set msg = objItems.Item(i)
I put together some VBA code for Outlook 2007 which has been working predominantly fine.
Its basically designed to check incoming messages and store the subject, body etc into a database and the attachment into a folder. In general, it works fine, but out of 100 messages or so, it drops the odd email.
I previously had a problem where some emails were not being processed and stored in the database, but then discovered there was an issue with illegal characters, which i have solved now, so that cant be it. I've compared the emails being dropped to the one's that arent, in terms of message header, content to and from fields and i cant see any difference between the two emails at all, so am completely perplexed as to why they're being dropped. When i copy the content of the email and forward it back to the system again, the VBA code processes it fine.
I am pasting the code below (the code links to some modules which are used for checking illegal characters or concatenating strings)
Sub SaveIncomingEmails(Items As Outlook.MailItem) ' enable this to run macro inbound emails
Dim cnn As ADODB.Connection
Set cnn = New ADODB.Connection
' ================================================================
' Open a Connection using an ODBC DSN named "Delphi".
' ================================================================
cnn.Open "MyDB", "MyUsername", "MyPassword"
' ================================================================
' Constants declaration
' ================================================================
Const olFolderInbox = 6
Const olTxt = 0
' ================================================================
' variable declaration
' ================================================================
Dim ns As NameSpace
Dim Inbox As MAPIFolder
Dim Item As Object
Dim Atmt As Attachment
Dim FileName As String
Dim SenderName As String
Dim i As Integer
Dim strSQLquery As String
Dim strSQLquery1 As String
Dim strSQLGTDResourceQuery As String
Dim MessageHeader As String
Dim strCommandQuery As String
Dim strGTDIdQuery As String
Dim AttachmentStr As String
Dim strFailedRcp As String
Dim strSubject As String
Dim hasattachment As String
Dim AttachmentType As String
Dim SenderAuthorised As String
Dim strToEmail As String
Dim strFromEmail As String
Dim strBody As String
Dim strSentDate As String
Dim strReceivedDate As String
Dim StrUniqueID As String
Dim strCommandDate As String
Dim strDomain As String
Dim strBodyStripped As String
Dim strSubjectStripped As String
Dim rs As Object
Dim strGoalId As String
Dim strFile As String
Dim strSenderAccountDescription As String
Dim strContentType As String
Dim strMimeVersion As String
Dim strReceived As String
' ================================================================
' Intializing variables
' ================================================================
i = 0
Set objItem = Items
Set ns = GetNamespace("MAPI")
Set Inbox = ns.GetDefaultFolder(olFolderInbox)
Set objOutlook = CreateObject("Outlook.Application")
Set objNamespace = objOutlook.GetNamespace("MAPI")
Set objFolder = objNamespace.GetDefaultFolder(olFolderInbox)
Set colMailItems = objFolder.Items
Set Item = objItem
strToEmail = Items.To
strFromEmail = Items.SenderEmailAddress
strSubject = Items.Subject
strBody = Items.Body
strSentDate = Items.SentOn
strReceivedDate = Items.ReceivedTime
'Initialize variables in a given format
StrUniqueID = Format(Items.ReceivedTime, "ddmmyyyyhhnnss") & Items.SenderEmailAddress
strCommandDate = Format(Items.ReceivedTime, "mm/dd/yyyy_hh:nn:ss")
' Grab the sender domain by stripping the last portion of the email address using the getdomain function
strDomain = Module2.GetDomain(Items.SenderEmailAddress)
' Strip the body of illegal characters and replace with legal characters for insertion into SQL
strBodyStripped = Module3.RemoveIllegalCharacters(Items.Body)
strSubjectStripped = Module4.RemoveIllegalCharacters(Items.Subject)
AttachmentStr = "images/no_attachment.png"
' ================================================================
' ================================================================
' ================================================================
' =====================================================
' Check list of authorised senders for xsCRM commands.
' Populate email addresses here
' =====================================================
If (InStr(strFromEmail, "AuthorisedSender1#email.com") > 0) Or (InStr(strFromEmail, "AuthorisedSender2#email.com") > 0) Or (InStr(strFromEmail, "AuthorisedSender3#email.com") > 0) Then
SenderAuthorised = "true"
End If
' ======================================================
' ======================================================
' ======================================================
' ================================================================
' check if subject holds a command
' ================================================================
'check to see if email sender is authorised
If SenderAuthorised = "true" Then
' Check if the subject line contains the string xs4crm is true
If InStr(strSubject, "xs4crm") > 0 Then
'If its true then do this
strCommandQuery = "INSERT INTO XSCRMEMAILCOMMAND (" & vbCrLf & _
"FromEmail," & vbCrLf & _
"command," & vbCrLf & _
"date," & vbCrLf & _
"Body" & vbCrLf & _
") VALUES ('" & strFromEmail & "','" & strSubject & "',GETDATE(),'" & strBody & "')"
Set rs = cnn.Execute(strCommandQuery)
'Look for a GTDID string so that we can save data to resources table
If InStr(strSubject, "gtdid=") > 0 Then
'Set the hasattachment variable to zero since we only want to run this loop if there are no attachments
hasattachment = "0"
'Set the variable to 1 so that we that our next if statement can only run if there are no attachments
For Each Atmt In Item.Attachments
hasattachment = "1"
Next Atmt
If hasattachment = "0" Then
'Grab the GTDId so we know which goal this resource belongs too.
strGoalId = Module5.GetHeaderProperty(strSubject, "gtdid=", ";", 5)
'Save data to table
strGTDIdQuery = "INSERT INTO XSCRMGTDRESOURCES (" & vbCrLf & _
"GoalId," & vbCrLf & _
"insertdatetime" & vbCrLf & _
") VALUES ('" & strGoalId & "',GETDATE())"
Set rs = cnn.Execute(strGTDIdQuery)
End If
End If
End If
End If
' ================================================================
' ================================================================
' ================================================================
' ================================================================
' Create folders for atttachments
' ================================================================
' Save any attachments found
For Each Atmt In Item.Attachments
AttachmentStr = "images/attachment.png" 'because it has gone into attachment loop the icon is now required.
'Create the subfolder for the attachment if it doesnt exist based on sender domain
Dim fso
Dim fol As String
fol = "c:\OLAttachments\" & strDomain
Set fso = CreateObject("Scripting.FileSystemObject")
If Not fso.FolderExists(fol) Then
fso.CreateFolder (fol)
End If
' ================================================================
' ================================================================
' ================================================================
' ================================================================
' save attachments
' ================================================================
FileName = "C:\OLAttachments\" & strDomain & "\" & _
Format(Item.CreationTime, "ddmmyyyy-") & Items.SenderEmailAddress & "-" & Atmt.FileName
Atmt.SaveAsFile FileName
i = i + 1
strFile = Atmt.FileName
strSQLquery1 = "INSERT INTO XSCRMEMAILSATTACHMENTS (" & vbCrLf & _
"FileSavedIn," & vbCrLf & _
"ActualFileName," & vbCrLf & _
"UniqueIdentifier," & vbCrLf & _
"SendersEmail" & vbCrLf & _
") VALUES ('" & FileName & "','" & StrUniqueID & "','" & strFile & "','" & strFromEmail & "')"
Set rs = cnn.Execute(strSQLquery1)
'If there is a GTDCommand, then grab the GTDId so we know which goal this resource belongs too.
If InStr(strSubject, "gtdid=") > 0 Then
strGoalId = Module5.GetHeaderProperty(strSubject, "gtdid=", ";", 5)
End If
AttachmentType = ""
'If the attachment is png or jpg set attachment type string to image
If (InStr(Atmt.FileName, ".png") > 0) Or (InStr(Atmt.FileName, ".jpg") > 0) Then
AttachmentType = "image"
End If
'If attachment is .mov set attachment type string to video
If InStr(Atmt.FileName, ".mov") > 0 Then
AttachmentType = "video"
End If
'If the attachment is mp3 or m4a set attachment type string to audio
If (InStr(Atmt.FileName, ".mp3") > 0) Or (InStr(Atmt.FileName, ".m4a") > 0) Then
AttachmentType = "audio"
End If
'check to see if email sender is authorised
If SenderAuthorised = "true" Then
'If attachment type is an image, audio or video as per extensions above then populate the xscrmgtdresource table with following fields
If (InStr(Atmt.FileName, ".png") > 0) Or (InStr(Atmt.FileName, ".jpg") > 0) Or (InStr(Atmt.FileName, ".mov") > 0) Or (InStr(Atmt.FileName, ".m4a") > 0) Or (InStr(Atmt.FileName, ".mp3") > 0) Then
strSQLGTDResourceQuery = "INSERT INTO XSCRMGTDRESOURCES (" & vbCrLf & _
"GoalId," & vbCrLf & _
"Title," & vbCrLf & _
"Type," & vbCrLf & _
"insertdatetime," & vbCrLf & _
"ResourcePath," & vbCrLf & _
"UniqueIdentifier" & vbCrLf & _
") VALUES ('" & strGoalId & "','" & Atmt.FileName & "','" & AttachmentType & "',GETDATE(),'" & FileName & "','" & StrUniqueID & "')"
End If
Set rs = cnn.Execute(strSQLGTDResourceQuery)
End If
Next Atmt
' ================================================================
' ================================================================
' ================================================================
' ================================================================
' Setting up to work with the Email Message Header
' ================================================================
'This accesses the message header property and sets the variable MessageHeader
Const PR_TRANSPORT_MESSAGE_HEADERS = "http://schemas.microsoft.com/mapi/proptag/0x007D001E"
MessageHeader = objItem.PropertyAccessor.GetProperty(PR_TRANSPORT_MESSAGE_HEADERS)
If MessageHeader <> "" Then
End If
' ================================================================
' ================================================================
' ================================================================
' ================================================================
' Accessing the message header and collecting specific info for database tables
' ================================================================
strSenderAccountDescription = Module5.GetHeaderProperty(MessageHeader, "From:", "<", 5)
strContentType = Module5.GetHeaderProperty(MessageHeader, "Content-Type:", ";", 13)
strMimeVersion = Module5.GetHeaderProperty(MessageHeader, "MIME-Version:", vbNewLine, 13)
strReceived = Module5.GetHeaderProperty(MessageHeader, "Received:", "(", 9)
'As the x-failed-recipients property does not appear in ALL messageheaders, we have to first check if it is present
If InStr(MessageHeader, "X-Failed-Recipients:") > 0 Then
'Get the MessageHeader Property value
strFailedRcp = Module5.GetHeaderProperty(MessageHeader, "X-Failed-Recipients:", vbNewLine, 20)
'Else set the variable value to blank so that we still have something to supply to the SQL query
Else
strFailedRcp = ""
End If
' ================================================================
' ================================================================
' ================================================================
' ================================================================
' Save Email into the database DeplphiDude and table xsCRMEmails for attachment based emails and without attachments
' ================================================================
If InStr(strSubject, "xs4crm") = 0 Then 'only insert if the emails is not a command
strSQLquery = "INSERT INTO XSCRMEMAILS (" & vbCrLf & _
"XFailedRecipients," & vbCrLf & _
"Received," & vbCrLf & _
"MimeVersion," & vbCrLf & _
"ContentType," & vbCrLf & _
"SendersAccountDescription," & vbCrLf & _
"FromEmail," & vbCrLf & _
"ToEmail," & vbCrLf & _
"Subject," & vbCrLf & _
"Body," & vbCrLf & _
"SentDate," & vbCrLf & _
"ReceivedDate," & vbCrLf & _
"UniqueIdentifier," & vbCrLf & _
"Status," & vbCrLf & _
"AttachmentIcon," & vbCrLf & _
"AssignedToUser," & vbCrLf & _
"EmailHeader" & vbCrLf & _
") VALUES ('" & strFailedRcp & "','" & strReceived & "','" & strMimeVersion & "','" & strContentType & "','" & strSenderAccountDescription & "', '" & strFromEmail & "','" & strToEmail & "','" & strSubjectStripped & "','" & strBodyStripped & "','" & strSentDate & "','" & strReceivedDate & "','" & StrUniqueID & "','EmailStatus_New','" & AttachmentStr & "','','" & Module4.RemoveIllegalCharacters(MessageHeader) & "')"
Set rs = cnn.Execute(strSQLquery)
End If
' ================================================================
' final steps
' ================================================================
'Delete email
objItem.Delete
Set objItem = Nothing
Set Atmt = Nothing
' ================================================================
' close connection to the sql server and end the program
' ================================================================
cnn.Close
End Sub
You should add some logging to help track down the problem.
I haven't used this personally, but maybe give it a go: Log4VBA
Also, you should add error handling:
Error Handling and Debugging Tips for Access 2007, VB, and VBA
Error Handling In VBA
First you do not say which part of your process is not working. You have showed a routine that does not fire by itself, it must be called by something else. This something else must have some conditions attached to it to call your routine. What are they? Can you show the workings of this.
If you are using a rule then could you show the conditions of the rule. Further what about if instead of a rule we code for the event in the VBEditor so that you can maybe see this event happening as well? Here is what I am talking about and there is example code there on how to do it MSDN Application_New_MAIL
Next I agree with everyone else that you need some logging, there is so much going on and it is impossible to tell where you cod is falling over. If I were you I would get an email that does not work and send it to yourself and have a break point right at the beginning of your code so that you can see a. That your code is actually being called and then where it is failing.
Suppose i have my mailbox configured and i have a special folder for mails with attachments in outlook 2007. What i want to do is
i. either configure outlook to save the attachment of mails coming in a specified folder (Mails with Attachments) to specific folder in my computer drive in a desired folder
ii. Or if i can write some macro or script to copy those all to my computer location. If so can you please give me quick overview or refer me some where.
The code below will save attachments to a directory automatically. Use Outlook rules to run this macro automatically on each incoming message.
Sub AutoSaveAttachment(Item As Outlook.MailItem)
Dim olAtt As Attachment
Dim i As Integer
Dim FIleNamewithDate As String
Const FILE_PATH As String = "C:\"
If Item.Attachments.Count > 0 Then
For i = 1 To Item.Attachments.Count
Set olAtt = Item.Attachments(i)
olAtt.SaveAsFile FILE_PATH & olAtt.FileName
Next i
End If
Set olAtt = Nothing
End Sub
This subroutine will save all attachments found in a user specified Outlook folder to a user specified directory on the file system. It also updates each message with a link to the purged files.
It also contains extra comments to help highlight how the .Delete method will shrink Attachment containers dynamically (search for "~~" in the comments).
This macro is only tested on Outlook 2010.
' ------------------------------------------------------------
' Requires the following references:
'
' Visual Basic for Applications
' Microsoft Outlook 14.0 Object Library
' OLE Automation
' Microsoft Office 14.0 Object Library
' Microsoft Shell Controls and Automation
' ------------------------------------------------------------
Public Sub SaveOLFolderAttachments()
' Ask the user to select a file system folder for saving the attachments
Dim oShell As Object
Set oShell = CreateObject("Shell.Application")
Dim fsSaveFolder As Object
Set fsSaveFolder = oShell.BrowseForFolder(0, "Please Select a Save Folder:", 1)
If fsSaveFolder Is Nothing Then Exit Sub
' Note: BrowseForFolder doesn't add a trailing slash
' Ask the user to select an Outlook folder to process
Dim olPurgeFolder As Outlook.MAPIFolder
Set olPurgeFolder = Outlook.GetNamespace("MAPI").PickFolder
If olPurgeFolder Is Nothing Then Exit Sub
' Iteration variables
Dim msg As Outlook.MailItem
Dim att As Outlook.attachment
Dim sSavePathFS As String
Dim sDelAtts As String
For Each msg In olPurgeFolder.Items
sDelAtts = ""
' We check each msg for attachments as opposed to using .Restrict("[Attachment] > 0")
' on our olPurgeFolder.Items collection. The collection returned by the Restrict method
' will be dynamically updated each time we remove an attachment. Each update will
' reindex the collection. As a result, it does not provide a reliable means for iteration.
' This is why the For Each loops will not work.
If msg.Attachments.Count > 0 Then
' This While loop is controlled via the .Delete method
' which will decrement msg.Attachments.Count by one each time.
While msg.Attachments.Count > 0
' Save the file
sSavePathFS = fsSaveFolder.Self.Path & "\" & msg.Attachments(1).FileName
msg.Attachments(1).SaveAsFile sSavePathFS
' Build up a string to denote the file system save path(s)
' Format the string according to the msg.BodyFormat.
If msg.BodyFormat <> olFormatHTML Then
sDelAtts = sDelAtts & vbCrLf & "<file://" & sSavePathFS & ">"
Else
sDelAtts = sDelAtts & "<br>" & "<a href='file://" & sSavePathFS & "'>" & sSavePathFS & "</a>"
End If
' Delete the current attachment. We use a "1" here instead of an "i"
' because the .Delete method will shrink the size of the msg.Attachments
' collection for us. Use some well placed Debug.Print statements to see
' the behavior.
msg.Attachments(1).Delete
Wend
' Modify the body of the msg to show the file system location of
' the deleted attachments.
If msg.BodyFormat <> olFormatHTML Then
msg.Body = msg.Body & vbCrLf & vbCrLf & "Attachments Deleted: " & Date & " " & Time & vbCrLf & vbCrLf & "Saved To: " & vbCrLf & sDelAtts
Else
msg.HTMLBody = msg.HTMLBody & "<p></p><p>" & "Attachments Deleted: " & Date & " " & Time & vbCrLf & vbCrLf & "Saved To: " & vbCrLf & sDelAtts & "</p>"
End If
' Save the edits to the msg. If you forget this line, the attachments will not be deleted.
msg.Save
End If
Next
End Sub
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I have about 80 emails, all with attachments which I would like to save to a folder on my hard drive.
How this can be done with a script?
This subroutine will save all attachments found in a user specified Outlook folder to a user specified directory on the file system. It also updates each message with a link to the purged files.
It also contains extra comments to help highlight how the .Delete method will shrink Attachment containers dynamically (search for "~~" in the comments).
This macro is only tested on Outlook 2010.
' ------------------------------------------------------------
' Requires the following references:
'
' Visual Basic for Applications
' Microsoft Outlook 14.0 Object Library
' OLE Automation
' Microsoft Office 14.0 Object Library
' Microsoft Shell Controls and Automation
' ------------------------------------------------------------
Public Sub SaveOLFolderAttachments()
' Ask the user to select a file system folder for saving the attachments
Dim oShell As Object
Set oShell = CreateObject("Shell.Application")
Dim fsSaveFolder As Object
Set fsSaveFolder = oShell.BrowseForFolder(0, "Please Select a Save Folder:", 1)
If fsSaveFolder Is Nothing Then Exit Sub
' Note: BrowseForFolder doesn't add a trailing slash
' Ask the user to select an Outlook folder to process
Dim olPurgeFolder As Outlook.MAPIFolder
Set olPurgeFolder = Outlook.GetNamespace("MAPI").PickFolder
If olPurgeFolder Is Nothing Then Exit Sub
' Iteration variables
Dim msg As Outlook.MailItem
Dim att As Outlook.attachment
Dim sSavePathFS As String
Dim sDelAtts
For Each msg In olPurgeFolder.Items
sDelAtts = ""
' We check each msg for attachments as opposed to using .Restrict("[Attachment] > 0")
' on our olPurgeFolder.Items collection. The collection returned by the Restrict method
' will be dynamically updated each time we remove an attachment. Each update will
' reindex the collection. As a result, it does not provide a reliable means for iteration.
' This is why the For Each loops will not work.
If msg.Attachments.Count > 0 Then
' This While loop is controlled via the .Delete method
' which will decrement msg.Attachments.Count by one each time.
While msg.Attachments.Count > 0
' Save the file
sSavePathFS = fsSaveFolder.Self.Path & "\" & msg.Attachments(1).FileName
msg.Attachments(1).SaveAsFile sSavePathFS
' Build up a string to denote the file system save path(s)
' Format the string according to the msg.BodyFormat.
If msg.BodyFormat <> olFormatHTML Then
sDelAtts = sDelAtts & vbCrLf & "<file://" & sSavePathFS & ">"
Else
sDelAtts = sDelAtts & "<br>" & "<a href='file://" & sSavePathFS & "'>" & sSavePathFS & "</a>"
End If
' Delete the current attachment. We use a "1" here instead of an "i"
' because the .Delete method will shrink the size of the msg.Attachments
' collection for us. Use some well placed Debug.Print statements to see
' the behavior.
msg.Attachments(1).Delete
Wend
' Modify the body of the msg to show the file system location of
' the deleted attachments.
If msg.BodyFormat <> olFormatHTML Then
msg.Body = msg.Body & vbCrLf & vbCrLf & "Attachments Deleted: " & Date & " " & Time & vbCrLf & vbCrLf & "Saved To: " & vbCrLf & sDelAtts
Else
msg.HTMLBody = msg.HTMLBody & "<p></p><p>" & "Attachments Deleted: " & Date & " " & Time & vbCrLf & vbCrLf & "Saved To: " & vbCrLf & sDelAtts & "</p>"
End If
' Save the edits to the msg. If you forget this line, the attachments will not be deleted.
msg.Save
End If
Next
End Sub
Take a look here: Save and remove attachments from email items (VBA)
Sub SaveAttachment()
'Declaration
Dim myItems, myItem, myAttachments, myAttachment As Object
Dim myOrt As String
Dim myOlApp As New Outlook.Application
Dim myOlExp As Outlook.Explorer
Dim myOlSel As Outlook.Selection
'Ask for destination folder
myOrt = InputBox("Destination", "Save Attachments", "C:\")
On Error Resume Next
'work on selected items
Set myOlExp = myOlApp.ActiveExplorer
Set myOlSel = myOlExp.Selection
'for all items do...
For Each myItem In myOlSel
'point on attachments
Set myAttachments = myItem.Attachments
'if there are some...
If myAttachments.Count > 0 Then
'add remark to message text
myItem.Body = myItem.Body & vbCrLf & _
"Removed Attachments:" & vbCrLf
'for all attachments do...
For i = 1 To myAttachments.Count
'save them to destination
myAttachments(i).SaveAsFile myOrt & _
myAttachments(i).DisplayName
'add name and destination to message text
myItem.Body = myItem.Body & _
"File: " & myOrt & _
myAttachments(i).DisplayName & vbCrLf
Next i
'for all attachments do...
While myAttachments.Count > 0
'remove it (use this method in Outlook XP)
'myAttachments.Remove 1
'remove it (use this method in Outlook 2000)
myAttachments(1).Delete
Wend
'save item without attachments
myItem.Save
End If
Next
'free variables
Set myItems = Nothing
Set myItem = Nothing
Set myAttachments = Nothing
Set myAttachment = Nothing
Set myOlApp = Nothing
Set myOlExp = Nothing
Set myOlSel = Nothing
End Sub