首页 > 解决方案 > 循环浏览包含特定字符串的 Outlook 中的特定子文件夹

问题描述

我想在 Outlook(宏 VBA)中的特定子文件夹中查找可以位于第一级或第二级子文件夹中的特定项目,但是我无法使其工作。我发现其他问题遍历所有文件夹中的所有项目,但不是遍历特定子文件夹中的所有项目。

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`

谢谢你的帮助!

标签: vbaoutlook

解决方案


下面的代码演示了如何访问每个文件夹中的每个邮件项目,以及父文件夹中任何深度的子文件夹。它通过将项目和子文件夹的缩进列表输出到即时窗口来实现这一点。输出格式为:

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. 我的代码是我的最爱。如果你愿意,可以换成你最喜欢的。

存储是 Outlook 用来保存邮件项目、任务、约会项目等的磁盘上的文件。我假设“Clearing”是文件夹的名称,而不是商店的名称。您的文件夹窗格将如下所示:

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

您可以拥有任意数量的商店。每个电子邮件地址将有一个,也许还有一个用于档案。当我更换计算机时,我会将旧商店添加到新的 Outlook 安装中,因此我可以访问所有旧电子邮件。

似乎总是有一个“收件箱”。其他标准文件夹的名称因版本而异,因此您可能有“已删除项目”或“垃圾箱”或其他内容。您可以随意添加自己的文件夹。

如果您的“清算”是一家商店,您将需要:

Set Fldr = Session.Folders("Clearing")

如果您的“清算”与“收件箱”(如我的“清算1”)处于同一级别,您将需要:

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

如果您的“Clearing”像我的“Clearing2”一样位于“Inbox”下,您将需要:

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

更改我的声明以匹配您的系统。

请注意,我写道:

Dim Fldr As Outlook.Folder

Dim ItemCrnt As MailItem

此代码在 Outlook 下运行,因此我不需要特定的 Outlook。我本可以写Outlook.MailItem,但它不会增加价值,因为 VBA 只有一种名为MailItem. 但是,Outlook 作为两种数据类型Folder;一个用于磁盘文件夹,一个用于 Outlook 文件夹。Outlook VBA 会假设您的意思是Outlook.Folder当您写作时,Folder但是当我没有具体说明Folder我的意思时,我曾经让自己陷入混乱。现在,我总是很小心地写Outlook.FolderScripting.Folder所以我不会忘记重要的时候。

subProcessChild是递归的。网络上有很好的递归解释,所以我现在不会尝试自己的解释。但是,如果您感到困惑,我将添加对我的例程的解释。

现在考虑:

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

你用过For Each。我有时会使用,但大多数时候For Each我觉得更方便。For Index

FldrPrnt是我希望访问其邮件项目和子文件夹的文件夹。 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.CountFor InxI = FldrPrnt.Items.Count to 1 Step -1。但是,如果您的处理涉及将项目移动到另一个文件夹,则必须使用FldrPrnt.Items.Count to 1 Step -1. 使用For Index,您可以通过它们在 中的位置来识别项目FldrPrnt.Items。如果您将项目 20 移动到另一个文件夹,项目 21 将成为项目 20,项目 22 将成为项目 21,依此类推。对于循环的下一次重复,您将检查新项目 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

推荐阅读