Outlook 2010 VBA将选定的电子邮件保存到该对话中的其他电子邮件已被移动到该文件夹

时间:2015-03-27 15:52:34

标签: vba outlook outlook-vba

我正在尝试编写一种自动提交电子邮件的方法。我将所有电子邮件归档到收件箱中的一组非常详细的子文件夹中。我有很多子文件夹可以帮助我整理我的电子邮件,但这会导致花费大量额外时间来清理我的收件箱(通过将电子邮件归档到相关的子文件夹)。我想自动执行此操作,以便我可以在收件箱中选择一封电子邮件并运行宏来显示已在同一对话线程中存储电子邮件的文件夹列表,并允许我选择保存所选电子邮件的文件夹至。我发现有几个示例代码很接近但没有真正做到这一点。

http://blog.saieva.com/2010/03/27/move-messages-to-folders-with-outlook-vba/ 显示当您知道要将电子邮件发送到哪个子文件夹时如何将邮件移动到子文件夹。这对我的情况不起作用,因为我希望宏给我一个"推荐的列表"文件夹。

我认为下面的代码可能是一个很好的起点,如果我能找到一种方法来遍历每个孩子"如果用户选择"是"在MsgBox中。

Public Sub GetItemsFolderPath()
  Dim obj As Object
  Dim F As Outlook.MAPIFolder
  Dim convItemFolders As Outlook.MAPIFolder
  Dim msg$
  Dim rootitemcount

  Set obj = Application.ActiveWindow
  If TypeOf obj Is Outlook.Inspector Then
    Set obj = obj.CurrentItem
  Else
    Set obj = obj.Selection(1)
  End If

  Set F = obj.Parent
  msg = " The path is: " & F.FolderPath & rootitemcount & vbCrLf
  msg = msg & "Switch to the folder?"
  If MsgBox(msg, vbYesNo) = vbYes Then
    Set Application.ActiveExplorer.CurrentFolder = F
  End If
End Sub

我无法整合可以使这项工作的循环。有没有人对如何使用上述或任何其他选项有任何建议?


修改

不确定如何在没有"回答"的情况下如何展示我的下一步我自己的问题。这是我的第一个问题,所以我还不知道所有的规则,如果这是错的,请告诉我,以便我可以解决它。我还没完成,但是在下面的答案的帮助下,我已经接近了很多。以下是我更新的代码:

Public Sub GetConverstationInformation()

    Dim host As Outlook.Application
    Set host = ThisOutlookSession.Application

    ' Check for Outlook 2010
    If Left(host.Version, 2) = "14" Then
        Dim selectedItem As Object
        Dim theMailItem As Outlook.mailItem

        ' Get the user's currently selected item.
        Set selectedItem = host.ActiveExplorer.Selection.item(1)

        ' Check to see if the item is a MailItem.
        If TypeOf selectedItem Is Outlook.mailItem Then
            Set theMailItem = selectedItem
            ' Check to see that the item's current folder
            ' has conversations enabled.
            Dim parentFolder As Outlook.folder
            Dim parentStore As Outlook.store
            Set parentFolder = theMailItem.Parent
            Set parentStore = parentFolder.store
            If parentStore.IsConversationEnabled Then
                ' Try and get the conversation.
                Dim theConversation As Outlook.conversation
                Set theConversation = theMailItem.GetConversation
                If Not IsNull(theConversation) Then
                    ' Outlook provides a table object
                    ' the contains all of the items in the
                    ' conversation.
                    Dim itemsTable As Outlook.table
                    Set itemsTable = theConversation.GetTable

                    ' Get the Root Items
                    ' Enumerate the list of items
                    ' only writing out data for MailItems.
                    ' A conversation can contain other items
                    ' like MeetingItems.
                    ' Then use a helper method and recursion
                    ' to walk all the items in the conversation.
                    Dim group As Outlook.simpleItems
                    Set group = theConversation.GetRootItems
                    Dim obj As Object
                    Dim fld As Outlook.folder
                    Dim mi As Outlook.mailItem
                    'Dim i As Long
                    For Each obj In group
                        If TypeOf obj Is Outlook.mailItem Then
                        Set mi = obj
                        Set fld = mi.Parent

                   'For i = 1 To group.Count
                        Me.ListBox1.AddItem fld.Name

                'mi.Sender & _
                    '" sent the message '" & mi.Subject & _
                    '"' which is in '" &
                     '& "'."
                 'Next i
                        End If
                            GetConversationDetails mi, theConversation
                   Next obj
                Else
                    MsgBox "The currently selected item is not a part of a conversation."
                End If
            Else
                MsgBox "The currently selected item is not in a folder with conversations enabled."
            End If
        Else
            MsgBox "The currently selected item is not a mail item."
        End If
    Else
        MsgBox "This code only works with Outlook 2010."
    End If
End Sub

Private Sub GetConversationDetails(anItem As Object, theConversation As Outlook.conversation)
    Dim group As Outlook.simpleItems
    Set group = theConversation.GetChildren(anItem)

    If group.Count > 0 Then
        Dim obj As Object
        Dim fld As Outlook.folder
        Dim mi As Outlook.mailItem
         'Dim i As Long
        'For i = 1 To group.Count(obj)
        For Each obj In group
            If TypeOf obj Is Outlook.mailItem Then

                Set mi = obj
                Set fld = mi.Parent
                'Dim counter

                Me.ListBox1.AddItem fld.Name

                'mi.Sender & _
                    '" sent the message '" & mi.Subject & _
                    '"' which is in '" &
                     '& "'."

            End If
            GetConversationDetails mi, theConversation
        Next obj
        'Next i
    End If
End Sub



Private Sub UserForm_Initialize()
GetConverstationInformation
End Sub

我将其放入带有列表框的用户表单中。我的目的是只允许添加唯一的文件夹名称。完成后,我想添加一个按钮,可以单击该按钮将所选电子邮件归档到从列表框中选择的文件夹中。有没有人在接下来的步骤中有任何笔记/良好的起点?我一直在网上寻找不同的方法来做到这一点,但我不断遇到长期的问题,我不得不想象有一个更优雅的解决方案。如果我发现有效的话,我会再次更新。再次感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

您似乎对GetConversation方法感兴趣,该方法返回一个Conversation对象,该对象代表此项目所属的对话。

Private Sub DemoConversation()
  Dim selectedItem As Object = Application.ActiveExplorer().Selection(1)
  ' For this example, you will work only with 
  'MailItem. Other item types such as
  'MeetingItem and PostItem can participate 
  'in Conversation.
  If TypeOf selectedItem Is Outlook.MailItem Then
    ' Cast selectedItem to MailItem.
    Dim mailItem As Outlook.MailItem = TryCast(selectedItem, Outlook.MailItem)


    ' Determine store of mailItem.
    Dim folder As Outlook.Folder = TryCast(mailItem.Parent, Outlook.Folder)
    Dim store As Outlook.Store = folder.Store
    If store.IsConversationEnabled = True Then
        ' Obtain a Conversation object.
        Dim conv As Outlook.Conversation = mailItem.GetConversation()
        ' Check for null Conversation.
        If conv IsNot Nothing Then
            ' Obtain Table that contains rows 
            ' for each item in Conversation.
            Dim table As Outlook.Table = conv.GetTable()
            Debug.WriteLine("Conversation Items Count: " + table.GetRowCount().ToString())
            Debug.WriteLine("Conversation Items from Table:")
            While Not table.EndOfTable
                Dim nextRow As Outlook.Row = table.GetNextRow()
                Debug.WriteLine(nextRow("Subject") + " Modified: " + nextRow("LastModificationTime"))
            End While
            Debug.WriteLine("Conversation Items from Root:")
            ' Obtain root items and enumerate Conversation.
            Dim simpleItems As Outlook.SimpleItems = conv.GetRootItems()
            For Each item As Object In simpleItems
                ' In this example, enumerate only MailItem type.
                ' Other types such as PostItem or MeetingItem
                ' can appear in Conversation.
                If TypeOf item Is Outlook.MailItem Then
                    Dim mail As Outlook.MailItem = TryCast(item, Outlook.MailItem)
                    Dim inFolder As Outlook.Folder = TryCast(mail.Parent, Outlook.Folder)
                    Dim msg As String = mail.Subject + " in folder " + inFolder.Name
                    Debug.WriteLine(msg)
                End If
                ' Call EnumerateConversation 
                ' to access child nodes of root items.
                EnumerateConversation(item, conv)
            Next
        End If
    End If
   End If
 End Sub

Private Sub EnumerateConversation(item As Object, conversation As Outlook.Conversation)
  Dim items As Outlook.SimpleItems = conversation.GetChildren(item)
  If items.Count > 0 Then
    For Each myItem As Object In items
        ' In this example, enumerate only MailItem type.
        ' Other types such as PostItem or MeetingItem
        ' can appear in Conversation.
        If TypeOf myItem Is Outlook.MailItem Then
            Dim mailItem As Outlook.MailItem = TryCast(myItem, Outlook.MailItem)
            Dim inFolder As Outlook.Folder = TryCast(mailItem.Parent, Outlook.Folder)
            Dim msg As String = mailItem.Subject + " in folder " + inFolder.Name
            Debug.WriteLine(msg)
        End If
        ' Continue recursion.
        EnumerateConversation(myItem, conversation)
    Next
  End If
End Sub

答案 1 :(得分:0)

感谢您的辛勤工作!我想要相同的功能,并在您的代码上进行了扩展,以添加一个列表框以选择一个文件夹,并且只允许将唯一的文件夹名称添加到该列表框。我还添加了代码,以在选择文件夹后移动电子邮件。由于列表框文件存储为二进制文件且无法在此处显示,因此完成的代码可在Outlook 2016中工作并托管在GitHub上。

GitHub: outlook-move-to-thread

要更新列表框,并且不允许在GetConversationInformation()中重复,

For Each obj In group
    If TypeOf obj Is Outlook.mailItem Then
        ' If ROOT item is an email, add it to ListBox1
        Set mi = obj
        Set fld = mi.Parent

        ' Don't include duplicate folders
        IsInListBox = False
        For i = 0 To Me.ListBox1.ListCount - 1
            If Me.ListBox1.Column(0, i) = fld.FolderPath Then
                IsInListBox = True
            End If
        Next

        If (InStr(fld.FolderPath, "Inbox") = 0) And _
            (InStr(fld.FolderPath, "Sent Items") = 0) And _
            (IsInListBox = False) Then
            Me.ListBox1.AddItem fld.FolderPath
        End If
    End If
        GetConversationDetails mi, theConversation
Next obj

要更新列表框,并且不允许在GetConversationDetails()中重复,

' Don't include generic folders
If (InStr(fld.FolderPath, "Inbox") = 0) And _
    (InStr(fld.FolderPath, "Sent Items") = 0) Then

    ' Don't include duplicate folders
    IsInListBox = False
    For i = 0 To Me.ListBox1.ListCount - 1
        If Me.ListBox1.Column(0, i) = fld.FolderPath Then
            IsInListBox = True
        End If
    Next

    ' Add to ListBox1
    If IsInListBox = False Then
        Me.ListBox1.AddItem fld.FolderPath
    End If

End If