VBA функция или макрос для перемещения выбранного(ых) сообщения(й) в папку беседы

Вопрос или проблема

Я организую все свои сообщения в Outlook в виде бесед. Я ищу функцию для перемещения текущего выбранного сообщения(ий) из входящих в соответствующие папки.

Например, если у меня есть письмо с темой “Еженедельный отчет о статусе”, которое было помещено в папку “Инженерия”, и я получаю ответ во входящих, я хотел бы запустить макрос и переместить ответ в папку “Инженерия”.

Я использую Outlook в Microsoft Office Professional Plus 2010.

Моя первая попытка решения проблемы работает в какой-то степени, но я хотел бы:

  1. Добавить функциональность для объектов, не являющихся MailItem;
  2. Упорядочить цикл For Each, сначала проверяя, указаны ли все корневые элементы для беседы в одной и той же таблице. Если нет, я хотел бы предложить пользователю выбрать нужную папку через диалоговое окно.

Вот моя текущая попытка:

Sub moveMailToConversationFolder()

    Dim olNs As NameSpace
    Dim Inbox As Outlook.MAPIFolder
    Dim selectedItem As Object
    Dim item As Outlook.mailItem ' Почтовый элемент
    Dim folder As Outlook.MAPIFolder ' Папка текущего элемента
    Dim conversation As Outlook.conversation ' Получить беседу
    ' Dim ItemsTable As Outlook.table ' Объект таблицы беседы
    Dim mailItem As Object
    Dim mailparent As Object

    Set olNs = Application.GetNamespace("MAPI")
    Set Inbox = olNs.GetDefaultFolder(olFolderInbox)

    ' On Error GoTo MsgErr
    ' // Должен быть выбран элемент.
    Set selectedItem = Application.ActiveExplorer.Selection.item(1)

    ' // Если элемент = MailItem.
    If TypeOf selectedItem Is Outlook.mailItem Then
        Set item = selectedItem
        Set conversation = item.GetConversation

        If Not IsNull(conversation) Then
            ' Set ItemsTable = conversation.GetTable

            ' MsgBox conversation.GetRootItems.Count

            For Each mailItem In conversation.GetRootItems ' Элементы в беседе.
                If TypeOf mailItem Is Outlook.mailItem Then
                    Set folder = mailItem.Parent
                    item.move GetFolder(folder.FolderPath)
                End If
            Next
        End If
    End If

End Sub

Function GetFolder(ByVal FolderPath As String) As Outlook.folder

    Dim TestFolder As Outlook.folder
    Dim FoldersArray As Variant
    Dim i As Integer

    On Error GoTo GetFolder_Error
    If Left(FolderPath, 2) = "\\" Then
        FolderPath = Right(FolderPath, Len(FolderPath) - 2)
    End If

    'Преобразовать путь к папке в массив
    FoldersArray = Split(FolderPath, "\")
    Set TestFolder = Application.Session.Folders.item(FoldersArray(0))
    If Not TestFolder Is Nothing Then
        For i = 1 To UBound(FoldersArray, 1)
            Dim SubFolders As Outlook.Folders
            Set SubFolders = TestFolder.Folders
            Set TestFolder = SubFolders.item(FoldersArray(i))
            If TestFolder Is Nothing Then
                Set GetFolder = Nothing
            End If
        Next
    End If

    'Вернуть TestFolder
    Set GetFolder = TestFolder
    Exit Function

GetFolder_Error:
    Set GetFolder = Nothing
Exit Function

End Function

Вот похожий скрипт, который может помочь.

Мой случай использования немного отличается – я вручную выбираю элементы в настраиваемом представлении, а затем запускаю скрипт с кнопки на панели инструментов. (Я обнаружил, что беседы плохо отслеживаются, плюс иногда беседа расходится на разные проекты.)

Option Explicit
Option Base 0

Public Sub MoveToFirstFolder()
  Dim oNamespace As Outlook.NameSpace, oSelection As Outlook.Selection
  Dim oFolder As Outlook.MAPIFolder
  Dim oItem As Object, i As Integer

  Set oNamespace = Application.GetNamespace("MAPI")

  Set oSelection = oNamespace.Application.ActiveExplorer.Selection
  If oSelection.Count < 2 Then Exit Sub

  Set oFolder = getFirstNonDefaultFolder(oSelection)
  If oFolder Is Nothing Then Exit Sub

  ' перемещение элементов
  For i = 1 To oSelection.Count
    Set oItem = oSelection.Item(i)
    If Not oItem.Parent = oFolder Then
      oSelection.Item(i).Move oFolder
    End If
  Next i
End Sub

Private Function getFirstNonDefaultFolder(oSelection As Outlook.Selection) As Outlook.Folder
  Dim oItem As Object
  Dim oFolder As Outlook.Folder
  Dim i As Integer

  ' получить папку
  For i = 1 To oSelection.Count
    Set oFolder = oSelection.Item(i).Parent
    Debug.Print ">" & oFolder.FullFolderPath
    If Not isDefaultFolder(oFolder) Then
      Set getFirstNonDefaultFolder = oFolder
      Exit Function
    End If
  Next i
End Function

Private Function isDefaultFolder(oFolder As Outlook.Folder) As Boolean
  Dim oNamespace As Outlook.NameSpace
  Dim defaultFolders, fldrNum

  isDefaultFolder = False

  defaultFolders = Array( _
    olFolderInbox, olFolderSentMail, _
    olFolderDrafts, _
    olFolderDeletedItems, olFolderJunk, _
    olFolderOutbox, _
    olFolderCalendar, _
    olFolderContacts, olFolderSuggestedContacts, _
    olFolderNotes, _
    olFolderTasks, olFolderToDo, _
    olFolderJournal, _
    olFolderConflicts, olFolderLocalFailures, olFolderServerFailures, olFolderSyncIssues, _
    olFolderManagedEmail, olPublicFoldersAllPublicFolders _
  )

  Set oNamespace = Application.GetNamespace("MAPI")

  On Error Resume Next  ' Не существующие стандартные папки вызывают ошибки
  For Each fldrNum In defaultFolders
    If oFolder = oNamespace.GetDefaultFolder(fldrNum) Then
      If Err.Number Then
        Err.Clear
      Else
        isDefaultFolder = True
        Exit Function
      End If
    End If
  Next fldrNum
End Function

Ответ или решение

Конечно, вот полное решение задачи перемещения выбранных сообщений в соответствующие папки обсуждений в Outlook с использованием VBA.

Полный код для функции и макроса

Option Explicit

Sub MoveMailToConversationFolder()
    Dim olNs As Outlook.NameSpace
    Dim Inbox As Outlook.MAPIFolder
    Dim selectedItems As Outlook.Selection
    Dim item As Object
    Dim conversation As Outlook.Conversation
    Dim rootItems As Outlook.Items
    Dim itemFolder As Outlook.MAPIFolder
    Dim targetFolder As Outlook.MAPIFolder

    Set olNs = Application.GetNamespace("MAPI")
    Set Inbox = olNs.GetDefaultFolder(olFolderInbox)
    Set selectedItems = Application.ActiveExplorer.Selection

    If selectedItems.Count < 1 Then Exit Sub

    Dim firstFolderPath As String
    Dim allSameFolder As Boolean
    allSameFolder = True
    Dim firstFolder As Outlook.MAPIFolder

    Set item = selectedItems.Item(1)

    ' Получаем папку первого выбранного элемента
    Set firstFolder = item.Parent
    firstFolderPath = firstFolder.FolderPath

    ' Проверка всех выбранных элементов на соответствие папке
    For Each item In selectedItems
        If Not item.Parent.FolderPath = firstFolderPath Then
            allSameFolder = False
            Exit For
        End If
    Next item

    ' Если все элементы в одной папке, перемещаем их
    If allSameFolder Then
        Set conversation = selectedItems.Item(1).GetConversation
        If Not conversation Is Nothing Then
            Set rootItems = conversation.GetRootItems
            For Each item In rootItems
                If TypeOf item Is Outlook.MailItem Then
                    Set itemFolder = item.Parent
                    targetFolder = GetFolder(itemFolder.FolderPath)
                    If Not targetFolder Is Nothing Then
                        For Each selectedItem In selectedItems
                            If TypeOf selectedItem Is Outlook.MailItem Then
                                selectedItem.Move targetFolder
                            End If
                        Next selectedItem
                    End If
                End If
            Next item
        End If
    Else
        MsgBox "Выбранные сообщения находятся в разных папках. Пожалуйста, выберите сообщения из одной папки.", vbExclamation
    End If
End Sub

Function GetFolder(ByVal FolderPath As String) As Outlook.Folder
    Dim TestFolder As Outlook.Folder
    Dim FoldersArray As Variant
    Dim i As Integer

    On Error GoTo GetFolder_Error
    If Left(FolderPath, 2) = "\\" Then
        FolderPath = Right(FolderPath, Len(FolderPath) - 2)
    End If

    ' Преобразование пути к папке в массив
    FoldersArray = Split(FolderPath, "\")
    Set TestFolder = Application.Session.Folders.Item(FoldersArray(0))

    For i = 1 To UBound(FoldersArray, 1)
        Dim SubFolders As Outlook.Folders
        Set SubFolders = TestFolder.Folders
        Set TestFolder = SubFolders.Item(FoldersArray(i))
        If TestFolder Is Nothing Then
            Set GetFolder = Nothing
            Exit Function
        End If
    Next

    ' Возвращаем найденную папку
    Set GetFolder = TestFolder
    Exit Function

GetFolder_Error:
    Set GetFolder = Nothing
End Function

Объяснение кода

  1. Основной макрос MoveMailToConversationFolder:

    • Инициализирует необходимые объекты для работы с Outlook.
    • Получает текущее выбранное сообщение или сообщения.
    • Проверяет, находятся ли все выбранные сообщения в одной папке. Если нет, выводится сообщение об ошибке.
    • Если все сообщения находятся в одной папке, программа извлекает корневые элементы беседы и перемещает все выбранные сообщения в соответствующую папку.
  2. Функция GetFolder:

    • Принимает путь к папке и возвращает объект папки. Она обрабатывает ошибки и проверяет, существует ли запрашиваемая папка.

Замечания

  • Убедитесь, что в VBA установлены соответствующие ссылки на библиотеку Outlook.
  • При использовании макроса, выбирайте сообщения из одной папки, чтобы избежать ошибок.
  • Если какие-либо сообщения не являются элементами почты, они будут проигнорированы.

Этот код должен решить вашу проблему, позволяя эффективно управлять сообщениями Outlook в соответствии с их разговорами. Если у вас есть дополнительные вопросы или нужно внести изменения, не стесняйтесь обращаться.

Оцените материал
Добавить комментарий

Капча загружается...