首页 > 解决方案 > 使用 VBA MarkAsUnread 函数打开 Outlook 对话而不将其标记为已读

问题描述

假设您按对话对 Outlook 邮件进行分组。双击对话的主标题时,如何防止对话中的任何邮件被标记为已读?

到目前为止我想出的代码:

  1. Application_ItemLoad用来获取任何选定邮件的对象
  2. 然后,myItem_Read存储所选邮件的UnRead属性,因为在ItemLoad
  3. 最后,我监听PropertyChange事件以将任何已读邮件更改回读邮件。但是,在下面的else分支中,表达式mySelection.Item(1).GetConversation.MarkAsUnread意外失败。据我了解,mySelection.Item(1)选择 Conversation Header 对象。然后我尝试使用GetConversation并调用MarkAsUnread理论上应该将所有对话消息标记为未读的方法来获取它的对话对象。只是理论。我不知道为什么。

1.

Public WithEvents myItem As Outlook.mailItem

Private Sub Application_ItemLoad(ByVal Item As Object)
    If EventsDisable = True Then Exit Sub
    If Item.Class = olMail Then
            Set myItem = Item
     End If
End Sub

2.

Private Sub myItem_Read()
    If EventsDisable = True Then Exit Sub
    unReadWhenSelected = myItem.UnRead
End Sub

3.

Private Sub myItem_PropertyChange(ByVal Name As String)
    Dim mySelection As Selection
    Dim oConvHeader As Outlook.ConversationHeader
    Dim oConv As Outlook.Conversation

    If EventsDisable = True Then Exit Sub

    If Name = "UnRead" Then
        If unReadWhenSelected = True And myItem.UnRead = False Then

            Set mySelection = Outlook.ActiveExplorer.Selection.GetSelection(Outlook.OlSelectionContents.olConversationHeaders)


            If mySelection.Count = 0 Then

                myItem.UnRead = True
                myItem.Save

            Else         
                mySelection.Item(1).GetConversation.MarkAsUnread

            End If

        End If
    End If    
End Sub

感兴趣的读者
的完整故事:假设您想通过双击标题来打开对话,而不会将对话的元素标记为read
我想将 Outlook 电子邮件用作任务,并将阅读邮件的含义更改为完成任务。因此,我使用带有“仅显示未读邮件”选项的搜索文件夹。一旦我完成一项任务,我就用一个宏将它标记为已读。
对于我只想阅读邮件等的所有其他情况,他们需要保持未读状态。

我编写了一个宏来为不属于对话的单个电子邮件完成此操作。当涉及到对话时,这个宏适用于它的所有元素——但不适用于第一个也称为主对话标题条目的元素。

编辑:

用于将对话中的所有电子邮件标记为已读的概念验证代码。为什么这在我上面的示例代码中不起作用?

Sub Testorino()

    Dim mySelection As Selection
    Set mySelection = Outlook.ActiveExplorer.Selection.GetSelection(Outlook.OlSelectionContents.olConversationHeaders)
    mySelection.Item(1).GetConversation.MarkAsUnread

End Sub

标签: vbaemailoutlook

解决方案


编辑:MS说这根本不应该做。Application.ItemLoad 的项目不打算再次使用。请注意此处的警告:https ://docs.microsoft.com/en-us/office/vba/api/outlook.application.itemload 它说:

在此事件中传递的 Item 对象不应被缓存以用于此事件范围之外的任何用途。

您应该能够改用Items.ItemChangeandItems.Add事件(在最初将其设置为收件箱的项目之后)并忽略所有未读更改,除非您的宏启动它。


旧答案-> 这似乎在 Outlook 2016 中的对话视图中有效。当项目关闭时,将对话标记为未读。这样,它不会跳过您在评论中提到的第一项。如果这会干扰您的宏,我可以查看是否可以在打开项目后让它工作,但我并没有走得太远。

Public WithEvents myItem As Outlook.MailItem
Dim EventsDisable As Boolean
Dim UnreadWhenSelected As Boolean

Private Sub Application_ItemLoad(ByVal Item As Object)
    If EventsDisable = True Then Exit Sub
    If Item.Class = olMail Then
            Debug.Print ("Item_Load")
            Set myItem = Item
     End If
End Sub

Private Sub myItem_Close(Cancel As Boolean)
    If EventsDisable = True Then Exit Sub
    Debug.Print ("Item_Close")
    If UnreadWhenSelected Then
        ' Ignore all events fired while marking the conversation as unread
        EventsDisable = True
        myItem.GetConversation.MarkAsUnread
        EventsDisable = False
    Else
        ' Ignore all events fired while marking the conversation as read
        EventsDisable = True
        myItem.GetConversation.MarkAsRead
        EventsDisable = False
    End If
End Sub

Private Sub myItem_Read()
    If EventsDisable = True Then Exit Sub
    UnreadWhenSelected = myItem.UnRead
    Debug.Print ("Item_Read. Unread: " & UnreadWhenSelected)
End Sub

推荐阅读