Search code examples
vbaoutlookms-word

How to capture the text in an Outlook email, whilst the email is being edited to send using VBA


When a user replies to an email, and starts writing some text (either in a new window or a preview window), I wish to capture this new text.

I found:

  • if the user highlights some of their new text, I can capture this highlighted text
  • if I try to capture all the text (the whole email as it appears in the window, including the new text), my code will only capture the text from the original email that is being replied to, not the new text as well

My code, with comments.

Function GetCurrentMail() As Object
' I use this to get the current mail object that is being edited, this works
Dim CurrentMail As Object

Select Case TypeName(ActiveWindow)

    Case Is = "Explorer"
        Set CurrentMail = ActiveExplorer.Selection.Item(1)
    Case Is = "Inspector"
        Set CurrentMail = ActiveInspector.CurrentItem
    Case Else
        GoTo CE

End Select

If CurrentMail Is Nothing Or TypeName(CurrentMail) <> "MailItem" Then GoTo CE

Set GetCurrentMail = CurrentMail

CE:

End Function

Code to capture any highlighted text. This works on new text the user may have entered.

Function GetHighlighted() As String

Dim olInsp As Object
Dim wdDoc As Object
Dim strText As String

With GetCurrentMail
    Set olInsp = .GetInspector
    Set wdDoc = olInsp.WordEditor
    strText = wdDoc.Application.Selection.Range.Text
End With

GetHighlighted = strText

Set olInsp = Nothing
Set wdDoc = Nothing

End Function

How do I get all the new text (or the whole email, new and original text).

I tried:

GetCurrentMail.Body

This returns the text from the original email before it was replied to.


Solution

  • The Outlook object model doesn't (or may not) propagate changes made in the UI to the OOM until the item is saved or focus is moved to another field in the UI (for example, switch from the body to the Subject line by clicking there). This is a known issue when dealing with the Outlook object model.

    Also there are some tricks when accessing items edited in Outlook. For example, to get items that are being edited or composed in the Explorer window you need to use the Explorer.ActiveInlineResponse property:

    So, instead of the following code:

    Case Is = "Explorer"
            Set CurrentMail = ActiveExplorer.Selection.Item(1)
    

    You need to use:

    Case Is = "Explorer"
            Set CurrentMail = ActiveExplorer.ActiveInlineResponse 
    

    Also I'd suggest handling the item-level events so you could check the message body right after the item is saved (or auto-saved). See Implement a wrapper for inspectors and track item-level events in each inspector for more information about that.

    But I'd suggest handling the [ItemSend][3] event of the Outlook Application class which is fired whenever an Microsoft Outlook item is sent, either by the user through an Inspector (before the inspector is closed, but after the user clicks the Send button) or when the Send method for an Outlook item, such as MailItem, is used in a program. In the event handler you may check the message body and cancel the sending process if required by setting the Cancel parameter to true.