For Each loop: Just deletes the very first attachm

2020-05-06 14:21发布

I've been trying to delete the attachments in Outlook after copying them using for each loop. It just deletes the very first attachment after copying it but does not go for the second attachment to work on! It just goes down to the End Sub.

Private Sub Items_ItemAdd(ByVal item As Object)

    On Error GoTo ErrorHandler

    'Only act if it's a MailItem
    Dim Msg As Outlook.MailItem
    If TypeName(item) = "MailItem" Then
        Set Msg = item

    'Change variables to match need. Comment or delete any part unnecessary.
        'If (Msg.SenderName = "Name Of Person") And _
        '(Msg.Subject = "Subject to Find") And _
        '(Msg.Attachments.Count >= 1) Then

    'Set folder to save in.
    Dim olDestFldr As Outlook.MAPIFolder
    Dim myAttachments As Outlook.Attachments
    Dim olAttch As Outlook.Attachment
    Dim Att As String

    'location to save in.  Can be root drive or mapped network drive.
    Const attPath As String = "C:\Users\pkshahbazi\Documents\EmailAttachments\"
    Set myAttachments = Msg.Attachments
        For Each olAttch In myAttachments
            Att = olAttch.DisplayName
            If Right(olAttch.FileName, 3) = "zip" Then
            olAttch.SaveAsFile attPath & Att
            olAttch.Delete
            End If
        Next olAttch
    Msg.UnRead = False

End If

ProgramExit:
  Exit Sub

ErrorHandler:
  MsgBox Err.Number & " - " & Err.Description
  Resume ProgramExit
End Sub

I figured out that the OlAttch.delete statement confuses the For Each loop.

Any idea how I can delete the attachments.

标签: vba outlook
2条回答
Root(大扎)
2楼-- · 2020-05-06 14:30

Try this. I added code/comments to iterate through and remove all the attachments after you do your saving. The reasons you should do this are explained very well here by David Zemens.

You also should get in the habit of saving messages you modify in Outlook VBA as sometimes this is important, sometimes it's not, but it can confuse the heck out of you if you don't use Save when you need to.

 'location to save in.  Can be root drive or mapped network drive.
    Const attPath As String = "C:\Users\pkshahbazi\Documents\EmailAttachments\"
    Set myAttachments = Msg.Attachments
        For Each olAttch In myAttachments
            Att = olAttch.DisplayName
            If Right(olAttch.FileName, 3) = "zip" Then
            olAttch.SaveAsFile attPath & Att
            'olAttch.Delete
            End If
        Next olAttch
        'iterate through all attachments, going backwards
        dim j as integer
        For j = Msg.Attachments.Count To 1 Step -1
            Msg.Attachments.Remove (j)
        Next j

        'make sure to save your message after this
        Msg.save
    Msg.UnRead = False




End If
查看更多
▲ chillily
3楼-- · 2020-05-06 14:52

In your previous question we changed from an indexed loop to a non-indexed loop, because you did not have any .Delete requirement. Unfortunately, deleting items from a collection requires an indexed iteration.

This is because, when you have 3 items:

  • Item 1 = Attachment 1
  • Item 2 = Attachment 2
  • Item 3 = Attachment 3

Then when you delete the first item (Item 1/Attachment 1), it takes you to item 2, but when the delete happens, you are left with the collection that looks like:

  • Item 1 = Attachment 2
  • Item 2 = Attachment 3

So your loop will delete items 1 and 3, but it will never touch item 2.

The simplest way to fix this for you, without using an indexed loop and re-writing your script, is to just add another loop to do the delete method.

@Enderland provides the example for this. I will not duplicate his effort, but I did want to explain what is happening for you. This is always the case when deleting items from a collection, you have to step through the collection in reverse order.

查看更多
登录 后发表回答