Looping through specific subfolders in outlook containing a specific string

被刻印的时光 ゝ 提交于 2020-08-10 19:16:55

问题


I want to look for specific items inside specific subfolders in Outlook (macro VBA) that can be in first or second level subfolder, however I cannot make it to work. I have found other questions that loop through all the items in all folders, but not that go through all items in specific subfolders.

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`

Thanks for your help!


回答1:


The code below demonstrates how to access every mail item within every folder, and sub-folder to any depth, within a parent folder. It does this by outputting an indented list of items and sub-folders to the Immediate Window. The format of the output is:

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
      :  :  :  :  :

There are statements within your code I do not understand so I have ignored your code and created my own.

Consider first:

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

Your equivalent of this statement is:

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

With VBA there is often more than one way of achieving the same effect. I prefer Session to objNS. My code so my favourites. Change to your favourite if you wish.

A store is a file on disc that Outlook uses to hold mail items, tasks, appointment items and so on. I assume “Clearing” is the name of a folder and not the name of a store. Your folder pane will look something like this:

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

You can have as many stores as you wish. There will be one per email address and perhaps one for archives. When I change computers, I add my old stores to my new Outlook installation, so I have access to all my old emails.

It seems there is always an “Inbox”. Other standard folders change their names from version to version so you might have “Deleted Items” or “Trash” or something else. You can add your own folders wherever you like.

If your “Clearing” is a store, you will need:

Set Fldr = Session.Folders("Clearing")

If your “Clearing” is at the same level as “Inbox” like my “Clearing1”, you will need:

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

If your “Clearing” is under “Inbox” like my “Clearing2”, you will need:

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

Change my statement to match your system.

Notice that I write:

Dim Fldr As Outlook.Folder

but

Dim ItemCrnt As MailItem

This code runs under Outlook so I do not need to specific Outlook. I could have written Outlook.MailItem but it would not add value because VBA only has one data type named MailItem. However, Outlook as two data types Folder; one for disc folders and one for Outlook folders. Outlook VBA will assume you mean Outlook.Folder when you write Folder but I once got myself into a muddle when I did not specify which Folder I meant. Now, I am always careful to write Outlook.Folder or Scripting.Folder so I will not forget when it is important.

The sub ProcessChild is recursive. There are excellent explanations of recursion on the web so I will not attempt my own explanation now. However, if you are confused, I will add an explanation of my routine.

Now consider:

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

You have used For Each. I sometimes use For Each but I find For Index more convenient most of the time.

FldrPrnt is the folder whose mail items and sub-folders I wish to access. FldrPrnt.Items gives me access to the items and FldrPrnt.Folders gives me access to the sub-folders.

When I write For InxI = 1 To FldrPrnt.Items.Count, I access the items oldest first. If I had written For InxI = FldrPrnt.Items.Count to 1 Step -1, I would have accessed the items newest first. “Oldest” and “Newest” here does not refer to the date of the item. It refers to the order in which items were added to FldrPrnt.Items. Normally mail items are added in date order so these two orders are the same. However, if you accidentally delete an old mail item then move it back from folder “Deleted Items”, it will become the newest item in the folder.

Often you can write either For InxI = 1 To FldrPrnt.Items.Count or For InxI = FldrPrnt.Items.Count to 1 Step -1. However, if your processing involves moving items to another folder, you must use FldrPrnt.Items.Count to 1 Step -1. With For Index, you are identifying items by their position within FldrPrnt.Items. If you move item 20 to another folder, item 21 becomes item 20, item 22 becomes item 21 and so on. For the next repeat of the loop, you will check the new item 21 not the old item 21. We sometimes get questions where someone is only checking half their items. This is the reason.

Notice If TypeName(FldrPrnt.Items(InxI)) = "MailItem" Then. Not every item is a MailItem. It is essential to check an item’s type before processing it since different items have different properties.

I hope the above, is enough for you to understand my code but ask question is necessary. All my code does is display the received time and subject of each mail item. You will have to replace my Debug.Print statement with whatever code you need to achieve your objectives.

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



回答2:


You need to iterate over all folders recursively:

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

Also, you may consider using the AdvancedSearch method of the Application class which performs a search based on a specified DAV Searching and Locating (DASL) search string. The key benefits of using the AdvancedSearch method in Outlook are:

  • The search is performed in another thread. You don’t need to run another thread manually since the AdvancedSearch method runs it automatically in the background.
  • Possibility to search for any item types: mail, appointment, calendar, notes etc. in any location, i.e. beyond the scope of a certain folder. The Restrict and Find/FindNext methods can be applied to a particular Items collection (see the Items property of the Folder class in Outlook).
  • Full support for DASL queries (custom properties can be used for searching too). You can read more about this in the Filtering article in MSDN. To improve the search performance, Instant Search keywords can be used if Instant Search is enabled for the store (see the IsInstantSearchEnabled property of the Store class).
  • You can stop the search process at any moment using the Stop method of the Search class.

Read more about the AdvancedSearch method in the Advanced search in Outlook programmatically: C#, VB.NET article.

So, maybe you don't need to iterate over all folders and search for specific items there any longer?



来源:https://stackoverflow.com/questions/62037900/looping-through-specific-subfolders-in-outlook-containing-a-specific-string

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!