简体   繁体   中英

From excel vba, count only original emails

I am just beginning to get my feet under me in Excel VBA and now I need to (from Excel) count emails in Outlook over a specific timeframe. I hardcoded that timeframe in for now. That part seems to work - at least the count is correct.

The issue is that it's counting every single email, rather than just the originals. I need the count for just new emails. I have looked at.GetConversation and then read that conversationIDs change with each email, so the original has 44 characters. I thought that would be a good way to filter, but I do not understand what is in that property because it's not working.

Now I dont know if I'm barking up the wrong tree or if I'm just around the corner from getting this. It works fine until it tries to filter by the conversation ID.

Sub cntEmail()
'I WILL NEVER COUNT EMAILS AGAIN, dangit
    Dim ns As Namespace: Set ns = GetNamespace(Type:="MAPI")
    Dim fldr As Folder, fldrDone As Outlook.Folder
    Dim inboxItems As Items, doneItems As Items, sFilter As String
    
    Set fldr = ns.Folders("Call Center").Folders("Inbox")
    Set fldrDone = ns.Folders("Call Center").Folders("DONE")
    Set inboxItems = fldr.Items
    Set doneItems = fldrDone.Items
    sFilter = "[LastModificationTime] > '" & Format("1/13/2023 17:00", "ddddd h:mm AMPM") & "' AND [LastModificationTime] < '" & Format("1/20/2023 16:59", "ddddd h:mm AMPM") & "'"
    Set inboxItems = inboxItems.Restrict(sFilter)
    Set doneItems = doneItems.Restrict(sFilter)
    
    Debug.Print "Total Inbox Count: " & inboxItems.Count
    Debug.Print "Total Done Count: " & doneItems.Count
    
    'Everything above this comment works

    Set inboxItems = inboxItems.Restrict("[ConversationID] < 45")
    Set doneItems = doneItems.Restrict("[ConversationID] < 45")
    
    Debug.Print "Total Inbox Count: " & inboxItems.Count
    Debug.Print "Total Done Count: " & doneItems.Count

    Set fldr = Nothing
    Set fldrDone = Nothing
    Set ns = Nothing
End Sub

ConversationID

From what I understand ConversationID is a property that will have the same value for all the mailItems that belong to the same conversation (more here ).

This means that if you reply to an email and the person replies to your reply, the second email you receive from them should have the same ConversationID .

I'm assuming that when you say that you want to count "original emails", you mean that you want to avoid counting the second email as it's part of the conversation initiated by the first (original) email.

So basically, you want to count how many unique values of ConversationID you have among your mailItems.

I haven't used .Restrict , so I'm not sure if you can use it for this purpose, but there are ways to get the total count of unique values for ConversationID by looping on the MailItems and counting the unique values.


Option 1: Using a Collection

One way to do it would be to use a collection. Since a collection can't contain two elements with the same key, we can use it to count the number of unique values.

For example:

    Dim UniqueConversations As New Collection
    
    Dim inboxItem As MailItem
    For Each inboxItem In inboxItems
        On Error Resume Next
            'This line will return an error when the key already matches an item in the collection
            'and the item won't be added to the collection.
            UniqueConversations.Add 1, inboxItem.ConversationID
        On Error GoTo 0
    Next inboxItem

    Debug.Print "Total Inbox Count: " & UniqueConversations.Count

Option 2: Using a Dictionary

The dictionary solution is a little more elegant as we don't need to use On error statements.

The reason why we don't get an error when we use a dictionary is that we'll just overwrite the stored value when the key already exists in the dictionary.

For example:

    'Make sure to include Microsoft Scripting Runtime Library or use the drop-in replacement VBA-tools/VBA-Dictionary on Mac
    Dim dict As Dictionary
    Set dict = New Dictionary
    
    Dim inboxItem As MailItem
    For Each inboxItem In inboxItems
        dict.Item(inboxItem.ConversationID) = 1
    Next inboxItem
    
    Debug.Print "Total Inbox Count: " & dict.Count

If you have a lot of emails, the dictionary approach is usually faster, but I haven't noticed a big difference for the small tests I've done.

You cannot create a restriction on property length like [ConversationID] < 45 (you can in Extended MAPI, but it is only available from C++ or Delphi). Try to create a restriction on PR_SUBJECT_PREFIX MAPI property being an empty string. On replies it is "RE" and "FW" on forwards.

@SQL="http://schemas.microsoft.com/mapi/proptag/0x003D001F" = ''

in your code:

Set inboxItems = inboxItems.Restrict("@SQL=""http://schemas.microsoft.com/mapi/proptag/0x003D001F"" = ''")
Set doneItems = doneItems.Restrict("@SQL=""http://schemas.microsoft.com/mapi/proptag/0x003D001F"" = ''")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM