1

I am trying to save outlook attachments to a folder and where the filename already exists save the newer file under a different name so as not to save over the existing file....perhaps just give an extension "v2" or even "v3" if "v2" exists.

I came across this answer but am finding that the newer file is saved over the existing file

Save attachments to a folder and rename them

I have used the below code;

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 = "C:\Users\Owner\my folder is here"
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 & "\my subfolder is here\"

' 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


        ' 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

I am relatively new to vba so perhaps the solution is there but am not seeing it!

Community
  • 1
  • 1
b2001
  • 11
  • 2
  • I've just posted some code that will generate a unique file name - http://stackoverflow.com/questions/36178243/update-the-file-name-on-workbook-beforesave. Paste the `GenerateUniqueName` function into a module and on the line after `strFile = strFolderpath & strFile` in your code add `strFile = GenerateUniqueName(strFile)`. – Darren Bartrup-Cook Mar 23 '16 at 15:20

1 Answers1

0

Take a look at my code below. It goes through all of the items in a specific Outlook folder (that you designate), goes through each attachment in each item, and saves the attachment in a specified file path.

'Establish path of folder you want to save to

Dim FilePath As Variant

FilePath = "C:\Users\Owner\my folder is here\my subfolder is here\"

    Set FSOobj = CreateObject("Scripting.FilesystemObject")

    'If path doesn't exist, create it. If it does, either do nothing or delete its contents
    If FSOobj.FolderExists(FilePath) = False Then
        FSOobj.CreateFolder FilePath
    Else
        ' This code is if you want to delete the items in the existing folder first. 
        ' It's not necessary for your case.
        On Error Resume Next
        Kill FilePath & "*.*"
        On Error GoTo 0
    End If

'Establish Outlook folders, attachments, and other items

Dim msOutlook As Outlook.NameSpace 'Establish Outlook NameSpace
Dim Folder As Outlook.MAPIFolder 'Establish Folder as a MAPIFolder
Dim messageAttachments As Outlook.Attachments

Set msOutlook = Application.GetNamespace("MAPI")

'Set the folder that contains the email with the attachment
Set Folder = msOutlook.GetDefaultFolder(olFolderInbox).Folders("FOLDER NAME HERE")

Set folderItems = Folder.Items

Dim folderItemsCount As Long
folderItemsCount = folderItems.Count

Dim number as Integer
number = 1

For i = 1 To folderItemsCount
    'If you want to pull the attachments on some criteria, like the Subject of the email or 
    'the date received, you need to write an IF statement like:
    'If InStr(Folder.Items(i).Subject, "SPECIFIC SUBJECT TEXT") Then

    Set messageAttachments = folderItems.item(i).Attachments
    lngCount = messageAttachments.Count 'This lets you pull more than one attachment per message
    For thisAttachment = 1 To lngCount
        messageAttachments.item(thisAttachment).SaveAsFile FilePath & "YOUR_CHOSEN_FILENAME" & number & ".xlsx"
        number = number + 1
    Next thisAttachment
Next i

EDIT

In order to delete the items after scraping the attachments, you would use the same code as above except you would also include folderItems.item(i).Delete. Also, since you are moving items, I switched to looping backwards in your for loop as to not mess up your iteration. I've written it below:

For i = folderItemsCount To 1 Step -1
    'If you want to pull the attachments on some criteria, like the Subject of the email or 
    'the date received, you need to write an IF statement like:
    'If InStr(Folder.Items(i).Subject, "SPECIFIC SUBJECT TEXT") Then

    Set messageAttachments = folderItems.item(i).Attachments
    lngCount = messageAttachments.Count 'This lets you pull more than one attachment per message
    For thisAttachment = 1 To lngCount
        messageAttachments.item(thisAttachment).SaveAsFile FilePath & "YOUR_CHOSEN_FILENAME" & number & ".xlsx"
        number = number + 1
    Next thisAttachment
    folderItems.item(i).Delete
Next i

I hope this helps!

  • @ A Taylor....appreciate the response but that code doesn't seem get going. I'm getting 'compile error' at the 'Set messageAttachments.item(i).Attachments' step. I saved the code as you posted under a new module and changed only the name of the folders. What am i doing wrong? Going back to the code i posted, would it be easier to add an 'if' step at the point where the attachment is saved to the folder to check for an existing file name and if already exists then add a variation.. e.g "v2"? – b2001 Mar 23 '16 at 13:02
  • @b2001 I had an error in my code. Instead of `Set messageAttachments.item(i).Attachments` it would be: `Set messageAttachments = folderItems.item(i).Attachments` Hope this fixes it! – Austin Taylor Mar 23 '16 at 14:59
  • @b2011 Also, that would be a good idea to add a "v2" to your file name that you are saving the attachment under. You can see that I included a `number = 1` to the file name (i.e. "File1.xlsx"), and then every time it saved, I added 1 to the integer `number`. Then, when it saved again, it would save as "File2.xlsx". However, you can do this any way you'd like. – Austin Taylor Mar 23 '16 at 15:07
  • @ATaylor....that seems to have worked. Thank you. If i could improve the code it would be to delete the outlook message or attachment less I copy the same attachment again the next time i run the macro.The original code I used did do that....any way i can incorporate something similar? Thanks once again – b2001 Mar 25 '16 at 00:09
  • @b2011 Then you would use: `folderItems.item(i).Move DestFolder` after setting your DestFolder earlier. I've edited my code in my original post above to demonstrate. – Austin Taylor Mar 25 '16 at 00:32
  • @b2001 Apologies. You could use `folderItems.item(i).Delete`, as you had previously in your code. Just add it at the end of the loop, and remember to loop backwards. – Austin Taylor Mar 25 '16 at 00:49