Search code examples
vbaoutlookcastingoutlook-2016

Treating Item As MailItem


I am creating an VBA application in Outlook 2016. It analyzes an incoming email and takes its subject line to search for duplicate (or close to duplicate) subject lines. I use a for-each loop to go through a list of Items (which are emails within the inbox) and analyze each one for the criteria.

Once a response is required, both the incoming email and the duplicate email are flagged so show that I have already responded to them.

I know both Item and olItem should both be Item objects. The problem I am having is in the line:

If InStr(1, GetPreceedingSubject(olItem.Subject), GetPreceedingSubject(SubjectString)) <> 0 _
                And olItem.FlagRequest <> "Follow up" Then

It gives me the error

"Run-time error '438': Object doesn't support this property or method"

I know it is the olItem because it is the only part of the function that I had changed before I got the error. This strikes me as odd because the following snippet still works:

' flag both the emails that prompted the response
                    With Item
                        ' due this week flag
                        .MarkAsTask olMarkThisWeek
                        ' sets a specific due date
                        .TaskDueDate = Now + 3
                        .FlagRequest = "Follow up"
                        .FlagStatus = 2
                        .ReminderSet = False
                        .Save
                    End With
                    With olItem
                        ' due this week flag
                        .MarkAsTask olMarkThisWeek
                        ' sets a specific due date
                        .TaskDueDate = Now + 3
                        .FlagRequest = "Follow up"
                        .FlagStatus = 2
                        .ReminderSet = False
                        .Save
                    End With

So in the first code snippet, it appears that it is treating the olItem as an object, but in the next one it allows me to treat it like a MailItem object. Any suggestions? I have looked up ways to cast from Item to MailItem, even just temporarily for that line of code, but obviously to no avail. Full subroutine below:

Private Sub myOlItems_ItemAdd(ByVal Item As Object)
    If ParsingEnabled = False Then
        Exit Sub
    End If

    Dim SubjectString As String     ' tracks the control word to search the subject line for
    Dim pingCount As Integer        ' tracks the number of copies found.
    Dim TimeDiff As Double
    Dim Protocol As Variant
    Dim FlagStatus As Integer

    pingCount = 0
    SubjectString = Item.Subject   ' searches subject line for this word


    ' If the email is a read receipt, then move it to a different folder
    If TypeName(Item) = "ReportItem" Then
        NullPrompt = MoveFolders(Item, "Read")
        If NullPrompt >= 0 Then
            setLblDebug ("Read receipt: " & Mid(SubjectString, 7, Len(SubjectString)))
            Item.UnRead = False
        Else
            NullPrompt = setLblDebug("Error when moving read receipt. Please check inbox and correct", lngRed)
        End If
    End If

    ' Check to make sure it is an Outlook mail message, otherwise
    ' subsequent code will probably fail depending on what type
    ' of item it is.
    If TypeName(Item) = "MailItem" Then
        ' display the message
        setLblDebug ("Incoming Message: " & Item.Subject)
        Item.UnRead = False     ' mark message as read
        ' Iterate through each item of the list
        For Each olItem In myOlItems
            If InStr(1, GetPreceedingSubject(olItem.Subject), GetPreceedingSubject(SubjectString)) <> 0 _
                    And olItem.FlagRequest <> "Follow up" Then
                Protocol = ProtocolCode(Item.Subject)
                If Protocol(0) <> 0 Then
                    ' Time difference between the 2 emails
                    TimeDiff = (Item.ReceivedTime - olItem.ReceivedTime) * 24   ' Gives the hour difference
                    ' If time difference is 0, then it is the same email
                    If Protocol(0) >= TimeDiff And TimeDiff <> 0 Then
                        ' flag both the emails that prompted the response
                        With Item
                            ' due this week flag
                            .MarkAsTask olMarkThisWeek
                            ' sets a specific due date
                            .TaskDueDate = Now + 3
                            .FlagRequest = "Follow up"
                            .FlagStatus = 2
                            .ReminderSet = False
                            .Save
                        End With
                        With olItem
                            ' due this week flag
                            .MarkAsTask olMarkThisWeek
                            ' sets a specific due date
                            .TaskDueDate = Now + 3
                            .FlagRequest = "Follow up"
                            .FlagStatus = 2
                            .ReminderSet = False
                            .Save
                        End With

                        ' email and call if required
                        RenderMail (olItem)
                        If Protocol(1) = 1 Then
                            NullPrompt = RenderCallPrompt(olItem.Subject, Item.ReceivedTime)
                        End If
                        ' set the debug prompt message
                        NullPrompt = setLblDebug("Response Made: " & Item.Subject & " [" & Item.ReceivedTime & "]", lngBlue)
                        If True Then Exit For   ' Reponse made, stop looking for additional emails
                    End If
                End If
            End If
        Next olItem
    End If
End Sub

Solution

  • You cannot treat an Object which is not a MailItem as a MailItem.

    MailItem is a subset of Object. Object encompasses TaskItem, AppointmentItem and others.

    Other types will not necessarily have the properties of a MailItem.

    In your code:

    ' Check to make sure it is an Outlook mail message, otherwise
    ' subsequent code will probably fail depending on what type
    ' of item it is.
    If TypeName(Item) = "MailItem" Then
    

    Add the same test to ensure olItem is a MailItem.

    For Each olItem In myOlItems
    
    ' Check to make sure it is an Outlook mail message, otherwise
    ' subsequent code will probably fail depending on what type
    ' of item it is.
    
    If TypeName(olItem) = "MailItem" Then
    '   
    End If
    
    Next olItem