4

I'm a beginner to VBA macros in Excel, and this is the first attempt in Outlook, but here's what I am trying to do:

In Outlook 2010, assign a macro to a button that, when pushed,

  1. Gets the entire body of the active email
  2. Copies the body including all formatting and html to the clipboard
  3. Opens a new word document
  4. Pastes the content of the clipboard to this word doc
  5. Clears the clipboard

So far, all I have are steps 1 and 3 (and I wonder if I'm going about this the wrong way in step 1) below:

Sub pasteToWord()

    Dim activeMailMessage As Outlook.MailItem 'variable for email that will be copied.
    Dim activeBody
    Dim clearIt As String 'Intended to eventually clear clipboard.

'Code to get to the body of the active email.
    If TypeName(ActiveExplorer.Selection.Item(1)) = "MailItem" Then _
    Set activeMailMessage = ActiveExplorer.Selection.Item(1)
    activeBody = activeMailMessage.Body
    'MsgBox activeBody
    '^This displayed what I want in plaintext form,
    'so I think im on the right track

'Code to copy selection to clipboard

'Code to open new Word doc
    Set WordApp = CreateObject("Word.Application")
    WordApp.Documents.Add
    WordApp.Visible = True

'Code to paste contents of clipboard to active word document

'Code to clear clipboard

End Sub

Any guidance to fill in the blanks above would be much appreciated.

Edit:

Here is what has come the closest so far, thanks to David Zemens. I think I am missing some reference though, because my compiler doesn't understand "DataObject" for the ClearClipboard() function. It does copy and paste into word with formatting though, as is below (though I had to comment out the last function to avoid errors):

Sub pasteToWord()

    Dim WordApp As Word.Application  'Need to link Microsoft Word Object library
    Dim wdDoc As Word.Document       'for these to be understood by compiler
    Dim activeMailMessage As Outlook.MailItem
    Dim activeBody As String

If TypeName(ActiveExplorer.Selection.Item(1)) = "MailItem" Then

    'Get a handle on the email
    Set activeMailMessage = ActiveExplorer.Selection.Item(1)

    'Ensure Word Application is open
    Set WordApp = CreateObject("Word.Application")

    'Make Word Application visible
    WordApp.Visible = True

    'Create a new Document and get a handle on it
    Set wdDoc = WordApp.Documents.Add

    'Copy the formatted text:
    activeMailMessage.GetInspector().WordEditor.Range.FormattedText.Copy

    'Paste to the word document
    wdDoc.Range.Paste

    'Clear the clipboard entirely:
     Call ClearClipBoard

End If

End Sub

Public Sub ClearClipBoard()
    Dim oData As New DataObject 'object to use the clipboard -- Compiler error, 
                                'I think I'm missing a reference here.

    oData.SetText Text:=Empty 'Clear
    oData.PutInClipboard 'take in the clipboard to empty it
End Sub
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
AnthonyJS
  • 153
  • 1
  • 3
  • 10

2 Answers2

4

This method will copy the formatted text from the selected mailitem, and paste it in to word document:

Dim WordApp As Word.Application
Dim wdDoc As Word.Document
Dim activeMailMessage As MailItem

If TypeName(ActiveExplorer.Selection.Item(1)) = "MailItem" Then

    'Get a handle on the email
    Set activeMailMessage = ActiveExplorer.Selection.Item(1)

    'Ensure Word Application is open
    Set WordApp = CreateObject("Word.Application")

    'Make Word Application visible
    WordApp.Visible = True

    'Create a new Document and get a handle on it
    Set wdDoc = WordApp.Documents.Add

    'Copy the formatted text:
    activeMailMessage.GetInspector().WordEditor.Range.FormattedText.Copy

    'Paste to the word document
    wdDocument.Range.Paste

    'Clear the clipboard entirely:
     Call ClearClipBoard

End If

NOTE Clearing the clipboard entirely can be done pretty easily with a function like the one described here:

Public Sub ClearClipBoard() 
    Dim oData   As New DataObject 'object to use the clipboard

    oData.SetText Text:=Empty 'Clear
    oData.PutInClipboard 'take in the clipboard to empty it
End Sub 
David Zemens
  • 53,033
  • 11
  • 81
  • 130
  • Hello, Thanks for this! The first line works great even if Word is already open. That second attempt doesn't work, it gives me: error '91', Object variable or With block variable not set. I tried saying "Set wdDoc.Range.Text = activeBody" but same error. One problem though with solution #1, all the formatting is gone. Any way to keep it? I was able to use "activeBody = activeMailMessage.HTMLBody" to get the HTML formatting, but I think using "WordApp.Documents(1).Range.Text = activeBody" kills it. I think I Need to replace "Text" with something like "FormatedText" that actually exists. – AnthonyJS Jan 12 '15 at 20:53
  • Second method shouldn't raise any error, I just double-checked. Can you please revise your question to show the code you are currently using/attempting to use? – David Zemens Jan 12 '15 at 20:55
  • 1
    No, you're right, it does work, I screwed up copy-pasting. Any ideas on maintaining formatting? I tried replacing "wdDoc.Range.Text = activeBody" with "wdDoc.Range.FormattedText = activeBody" and I get error 13: type mismatch, both when I set activeBody to Body or HTMLBody. – AnthonyJS Jan 12 '15 at 21:27
  • I think you need to use the Inspector class as @Eugene Asafiev mentions below. Let me see if I have it... – David Zemens Jan 12 '15 at 21:49
  • 1
    OK, I will give that a shot and let you know. I went through the MailItem properties list and tried BodyRTF which also didn't work (even after trying a StrConv() with Unicode. I also used the BodyFormat property and that confirmed what we knew, that the body was html, but I couldn't find any function to convert the HTML to something useable. Even saving the output as .HTML didn't help. – AnthonyJS Jan 12 '15 at 22:15
  • You've tried a lot of things but you're not trying them with purpose/understanding of what they are. For example, the `StrConv` function converts *encoded* text to another format; it is not something that you can use to make raw HTML appear as Rich Text. There is no function that I'm aware of which will do that sort of *conversion*, you need to work with the objects directly in your code :) – David Zemens Jan 12 '15 at 22:22
  • 1
    Oh absolutely, I really don't understand a lot of what I'm doing, I'm just doing and trying to gain an understanding along the way. The merits or lack thereof of this approach are debatable, but I'm no computer scientist and don't plan on needing a deep understanding of VBA, just want to get this thing to work. I really appreciate your help too. please see my revision of the initial post. I have since found the library I was missing for the Word.x objects, but it worked without them... – AnthonyJS Jan 12 '15 at 22:30
  • 1
    FWIW, I was trying to get the body as rtf (activeBody = activeMailMessage.RTFBody) then encode it so that it would look formatted by following this example here: http://msdn.microsoft.com/en-us/library/office/ff867828%28v=office.14%29.aspx but I couldn't bridge the gap. And I should say I have a basic understanding of some of what I'm doing hahaha, but certainly not a complete grasp of even the fundamentals of VBA. – AnthonyJS Jan 12 '15 at 22:42
  • I see what the example with encoding does, but it is not a conversion of HTML to Rich Text, it is about *character* encoding, i.e., Unicode versus Double-byte versus Ascii, etc... Anyways, glad I could help you with this, cheers! – David Zemens Jan 12 '15 at 22:50
0

You can use the Word object model when dealing woth item bodies.

Word is used as an email editor in Outlook. The WordEditor property of the Inspector class returns an instance of the Document class from the Word object model which represents the Body of your email. See Chapter 17: Working with Item Bodies for more information.

As you may see, there is no need to use any extra tools or classes (Clipboard and etc.). You can copy the document using built-in mechanisms or save the document as is.

Eugene Astafiev
  • 47,483
  • 3
  • 24
  • 45
  • Cool, thanks for this. I have learned about BodyHTML (see above comment) from this, but it's pretty in depth for a novice like me, so I'm going to try reading it more slowly and seeing if I get anything more from it. – AnthonyJS Jan 12 '15 at 20:58