Цикл по определенным c подпапкам в Outlook, содержащим определенную c строку - PullRequest
0 голосов
/ 27 мая 2020

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

fldrname = "Clearing"
    Set objNS = GetNamespace("MAPI")
    Set ClearingFolders = Outlook.Folders("Clearing", objNS.Folders)
    For Each ClearingFolders In objParentFolderCollection
        For Each folder In ClearingFolders
            If InStr(1, fldrname, folder.Name, vbTextCompare) > 0 Then
                {findEmail}
            End If
        Next folder`

Спасибо за вашу помощь!

Ответы [ 2 ]

0 голосов
/ 27 мая 2020

Вам необходимо рекурсивно перебирать все папки:

Private Sub processFolder(ByVal oParent As Outlook.MAPIFolder)

        Dim oFolder As Outlook.MAPIFolder
        Dim oMail As Outlook.MailItem

        For Each oMail In oParent.Items

        'Get your data here ...

        Next

        If (oParent.Folders.Count > 0) Then
            For Each oFolder In oParent.Folders
                processFolder oFolder
            Next
        End If
End Sub

Кроме того, вы можете рассмотреть возможность использования метода AdvancedSearch класса Application, который выполняет поиск на основе указанного поиска и определения местоположения DAV (DASL ) строка поиска. Ключевые преимущества использования метода AdvancedSearch в Outlook:

  • Поиск выполняется в другом потоке. Вам не нужно запускать другой поток вручную, поскольку метод AdvancedSearch запускает его автоматически в фоновом режиме.
  • Возможность поиска любых типов элементов: почта, встреча, календарь, заметки и c. в любом месте, т.е. за пределами определенной папки. Методы Restrict и Find / FindNext могут применяться к конкретной коллекции Items (см. Свойство Items класса Folder в Outlook).
  • Полная поддержка DASL запросы (для поиска также можно использовать настраиваемые свойства). Подробнее об этом можно прочитать в статье Фильтрация в MSDN. Чтобы повысить производительность поиска, можно использовать ключевые слова мгновенного поиска, если для магазина включен мгновенный поиск (см. Свойство IsInstantSearchEnabled класса Store).
  • Вы можете остановить процесс поиска в любой момент с использованием метода Stop класса Search.

Подробнее о методе AdvancedSearch см. в Расширенный поиск в Outlook программно: C#, VB. NET .

Так, может быть, вам больше не нужно перебирать все папки и искать в них определенные c элементы?

0 голосов
/ 27 мая 2020

Приведенный ниже код демонстрирует, как получить доступ к каждому почтовому элементу в каждой папке и подпапке любой глубины в родительской папке. Он делает это, выводя список элементов и подпапок с отступом в окно Immediate Window. Формат вывода:

ParentFolderName
  Date Subject (of mail item within ParentFolder
  Date Subject (of mail item within ParentFolder
  Date Subject (of mail item within ParentFolder
  ChildFolder1Name
  Date Subject (of mail item within ChildFolder1Name
  Date Subject (of mail item within ChildFolder1Name
  GrandchildFolder1Name
    Date Subject (of mail item within GrandchildFolder1Name
    Date Subject (of mail item within GrandchildFolder1Name
  ChildFolder2Name
    Date Subject (of mail item within ChildFolder2Name
    Date Subject (of mail item within ChildFolder2Name
    GrandchildFolder2Name
      Date Subject (of mail item within GrandchildFolder2Name
      Date Subject (of mail item within GrandchildFolder2Name
      GreatgrandchildFolder1Name
        Date Subject (of mail item within GreatgrandchildFolder1Name
        Date Subject (of mail item within GreatgrandchildFolder1Name
  ChildFolder3Name
      :  :  :  :  :

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

Сначала рассмотрим:

Set Fldr = Session.Folders("StoreName").Folders("TopLevelFolderName")

Ваш эквивалент этого оператора:

Set objNS = GetNamespace("MAPI")
Set Fldr = objNS.Folders("StoreName").Folders("TopLevelFolderName")

С VBA часто существует несколько способов достижения того же эффекта. Я предпочитаю Session вместо objNS. Мой код - мой фаворит. Измените на свой любимый, если вы sh.

Хранилище - это файл на c, который Outlook использует для хранения сообщений электронной почты, задач, встреч и т. Д. Я предполагаю, что «Очистка» - это имя папки, а не имя магазина. Панель ваших папок будет выглядеть примерно так:

StoreName1
  Clearing1
  Deleted Items
  Inbox
  Sent Items
StoreName2
   Inbox
     Clearing2
  Sent
  Trash

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

Кажется, всегда есть «Входящие». Другие стандартные папки меняют свои имена от версии к версии, поэтому у вас могут быть «Удаленные», «Корзина» или что-то еще. Вы можете добавлять свои собственные папки где угодно.

Если ваш «Клиринг» - это магазин, вам потребуется:

Set Fldr = Session.Folders("Clearing")

Если ваш «Клиринг» находится на том же уровне, что и « Входящие », как и мой« Очистка1 », вам понадобятся:

Set Fldr = Session.Folders("StoreName1").Folders("Clearing1")

Если ваша« Очистка »находится в разделе« Входящие », как моя« Очистка2 », вам понадобится:

Set Fldr = Session.Folders("StoreName2").Folders("Inbox").Folders("Clearing2")

Измените мой оператор, чтобы он соответствовал вашей системе.

Обратите внимание, что я пишу:

Dim Fldr As Outlook.Folder

но

Dim ItemCrnt As MailItem

Этот код работает в Outlook, поэтому мне не нужно указывать c Outlook. Я мог бы написать Outlook.MailItem, но это не добавило бы ценности, потому что VBA имеет только один тип данных с именем MailItem. Однако Outlook как два типа данных Folder; один для папок DIS c и один для папок Outlook. Outlook VBA предполагает, что вы имеете в виду Outlook.Folder, когда пишете Folder, но однажды я запутался, когда не указал, какой Folder имел в виду. Я всегда стараюсь писать Outlook.Folder или Scripting.Folder, поэтому я не забуду, когда это важно.

Подложка ProcessChild рекурсивна. В сети есть отличные объяснения рекурсии, поэтому я не буду сейчас пытаться объяснять собственное. Однако, если вы запутались, я добавлю объяснение своей процедуры.

Теперь рассмотрим:

For InxI = 1 To FldrPrnt.Items.Count
  :  :  :
For InxF = 1 To FldrPrnt.Folders.Count

Вы использовали For Each. Я иногда использую For Each, но в большинстве случаев считаю For Index более удобным.

FldrPrnt - это папка, элементы почты и подпапки которой я sh могу получить. FldrPrnt.Items дает мне доступ к элементам, а FldrPrnt.Folders дает мне доступ к подпапкам.

Когда я пишу For InxI = 1 To FldrPrnt.Items.Count, я сначала обращаюсь к самым старым элементам. Если бы я написал For InxI = FldrPrnt.Items.Count to 1 Step -1, я бы сначала получил доступ к самым новым элементам. «Самый старый» и «Самый новый» здесь не относятся к дате элемента. Это относится к порядку, в котором элементы были добавлены в FldrPrnt.Items. Обычно почтовые отправления добавляются в порядке дат, поэтому эти два порядка совпадают. Однако, если вы случайно удалите старый почтовый элемент, а затем переместите его обратно из папки «Удаленные», он станет самым новым элементом в папке.

Часто вы можете написать либо For InxI = 1 To FldrPrnt.Items.Count, либо For InxI = FldrPrnt.Items.Count to 1 Step -1. Однако, если ваша обработка включает перемещение элементов в другую папку, вы должны использовать FldrPrnt.Items.Count to 1 Step -1. С помощью For Index вы идентифицируете элементы по их положению в пределах FldrPrnt.Items. Если вы переместите элемент 20 в другую папку, элемент 21 станет элементом 20, элемент 22 станет элементом 21 и так далее. При следующем повторении l oop вы проверите новый элемент 21, а не старый 21. Иногда мы получаем вопросы, когда кто-то проверяет только половину своих элементов. Это причина.

Уведомление If TypeName(FldrPrnt.Items(InxI)) = "MailItem" Then. Не каждый элемент является MailItem. Важно проверить тип элемента перед его обработкой, так как разные элементы имеют разные свойства.

Надеюсь, вам достаточно, чтобы понять мой код, но задать вопрос необходимо. Весь мой код отображает время получения и тему каждого письма. Вам придется заменить мой оператор Debug.Print любым кодом, который вам понадобится для достижения ваших целей.

Option Explicit
Sub Main()

  Dim Fldr As Outlook.Folder

  Set Fldr = Session.Folders("StoreName").Folders("TopLevelFolderName")

  Call ProcessChild(Fldr, 0)

End Sub
Sub ProcessChild(ByRef FldrPrnt As Outlook.Folder, ByVal Indent As Long)

  Dim InxF As Long
  Dim InxI As Long
  Dim ItemCrnt As MailItem

  Debug.Print Space(Indent * 2) & FldrPrnt.Name

  For InxI = 1 To FldrPrnt.Items.Count
    If TypeName(FldrPrnt.Items(InxI)) = "MailItem" Then
      Set ItemCrnt = FldrPrnt.Items(InxI)
      With ItemCrnt
        Debug.Print Space(Indent * 2 + 2) & .ReceivedTime & " " & .Subject
      End With
    End If
  Next
  For InxF = 1 To FldrPrnt.Folders.Count
    If FldrPrnt.Folders(InxF).DefaultItemType = olMailItem Then
      Call ProcessChild(FldrPrnt.Folders(InxF), Indent + 1)
    End If
  Next

End Sub
...