Приведенный ниже код демонстрирует, как получить доступ к каждому почтовому элементу в каждой папке и подпапке любой глубины в родительской папке. Он делает это, выводя список элементов и подпапок с отступом в окно 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