4

I wrote an Excel macro to send email from a spreadsheet. It works on Office 2013, but not Office 2016.

I looked at the VBA differences between Office 2013 and 2016, but couldn't see anything about changes to the inspector or word editor for message objects.

Once it gets to .GetInspector.WordEditor it throws:

Run-time error '287':
Application-defined or object defined error

Here is the relevant part of the macro:

Sub SendEmail()
    Dim actSheet As Worksheet
    Set actSheet = ActiveSheet

    'directories of attachment and email template
    Dim dirEmail as String, dirAttach As String

    ' Directory of email template as word document
    dirEmail = _
        "Path_To_Word_Doc_Email_Body"

    ' Directories of attachments
    dirAttach = _
        "Path_To_Attachment"

    ' Email Subject line
    Dim subjEmail As String
    subjEmail = "Email Subject"

    Dim wordApp As Word.Application
    Dim docEmail As Word.Document

    ' Opens email template and copies it
    Set wordApp = New Word.Application
    Set docEmail = wordApp.Documents.Open(dirEmail, ReadOnly:=True)
    docEmail.Content.Copy

    Dim OutApp As Outlook.Application
    Set OutApp = New Outlook.Application
    Dim OutMail As MailItem
    Dim outEdit As Word.Document

    ' The names/emails to send to
    Dim docName As String, sendEmail As String, ccEmail As String, siteName As String
    Dim corName As String

    Dim row As Integer
    For row = 2 To 20

        sendName = actSheet.Cells(row, 1)
        sendEmail = actSheet.Cells(row, 2)
        ccEmail = actSheet.Cells(row, 3)
        siteName = actSheet.Cells(row, 4)

        Set OutMail = OutApp.CreateItem(olMailItem)
        With OutMail
            .SendUsingAccount = OutApp.Session.Accounts.Item(1)
            .To = sendEmail
            .CC = ccEmail
            .Subject = subjEmail & " (Site: " & siteName & ")"

            Set outEdit = .GetInspector.WordEditor
            outEdit.Content.Paste

            outEdit.Range(0).InsertBefore ("Dear " & sendName & "," & vbNewLine)

            .Attachments.Add dirAttach

            .Display
            '.Send

        End With
        Debug.Print row

        Set OutMail = Nothing
        Set outEdit = Nothing
    Next row

    docEmail.Close False
    wordApp.Quit
End Sub

Things I've tried based on suggestions:

  • Checked Outlook settings - default is HTML text
  • Moved .display over .GetInspector.WordEditor
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Falthazar
  • 85
  • 1
  • 1
  • 10
  • https://social.msdn.microsoft.com/Forums/vstudio/en-US/3525b526-0717-43c6-b266-bd5d6dce6ddc/mailitemgetinspectorwordeditor-is-null-in-applicationitemsend-in-outlook-2007?forum=vsto – braX Jul 28 '17 at 14:50
  • What are your Outlook email settings -- plain text or rich text/html? If plain text, [that might be the problem](https://www.mrexcel.com/forum/excel-questions/878724-trying-copy-range-worksheet-outlook-2013-email-msg.html). Also ensure that Word is the default email editor (same thread mentions that). – David Zemens Jul 28 '17 at 14:56
  • @reply Yea, I've already checked those settings and they are set to html. – Falthazar Jul 28 '17 at 15:28
  • Which operating system are on? – 0m3r Jul 28 '17 at 17:19
  • We're on Windows 7 – Falthazar Jul 28 '17 at 18:26
  • Can you post complete code? – 0m3r Jul 29 '17 at 02:15
  • The rest of the code is just copying from a word doc. I'll add it in the OP – Falthazar Jul 31 '17 at 14:29
  • I'm experiencing something similar. Is the problem that you are getting the WordEditor before Word has finished opening? – Matt Fitzmaurice Aug 17 '22 at 07:23

4 Answers4

3

Ensure Word is the default email editor. From the Inspector.WordEditor dox:

The WordEditor property is only valid if the IsWordMail method returns True and the EditorType property is olEditorWord . The returned WordDocument object provides access to most of the Word object model...

Further, ensure that Outlook is configured to send Rich Text or HTML emails, not plain text.

David Zemens
  • 53,033
  • 11
  • 81
  • 130
  • That is the weird thing. I saw that and checked both of those properties and they are both correct: ![Locals Window](http://imgur.com/0hhcpZ7) – Falthazar Jul 28 '17 at 15:18
  • Try adding an `outEdit.Display` before attempting to handle the Inspector? – David Zemens Jul 28 '17 at 15:43
  • Or maybe it's `.Show`, I can't remember what it's called. – David Zemens Jul 28 '17 at 15:44
  • It is display, and I moved that above the '.GetInspector.WordEditor' and still same issue. – Falthazar Jul 28 '17 at 16:00
  • Weird. Your code works for me in 2016 (tested using late-bound Outlook). I notice in screenshot your WordEditor is an empty object, but mine is clearly an Object/Document that I can expand... Have you made sure the proper reference is ticked for the 2016 version of Outlook and/or Word? If the Excel file was built with previous reference library, maybe that could be a problem? – David Zemens Jul 28 '17 at 16:34
  • This is what I have in references: [references](http://imgur.com/hDAhDgv) – Falthazar Jul 28 '17 at 16:59
  • @Daniel I'm all out of guesses at this point, other than checking the security/trust center settings in Outlook, Word... is the Outlook Application visible at runtime? – David Zemens Jul 28 '17 at 17:49
  • Yea, weirdly. Everything else seems to work, except that. As long as I'm not getting the word editor it'll work. Only issue is that I can't paste with formatting without getting the word editor – Falthazar Jul 28 '17 at 18:26
  • I would open a ticket with Microsoft if possible, this may be some sort of bug and there is at least [one similar question posted earlier this month](https://stackoverflow.com/questions/45003214/run-time-error-287-outlook-when-set-inspector-wordeditor#comment77714961_45003214) that hasn't been answered – David Zemens Jul 28 '17 at 18:28
  • I seem to recall some situations where Outlook is stuck waiting for user input -- i.e., from automation requests like this it will have a msgbox alerting the owner that "Another program is trying to send emails through Outlook" and the Outlook application will probably be unresponsive until/unless you allow that. Make sure that something like that isn't happening, if outlook is minimized you might not notice it, etc. Probably that's not the problem here, but I figured I'd mention it as it's kinda related. – David Zemens Jul 28 '17 at 18:31
  • Thanks! Also, do you know where I file a bug with Microsoft? [I was thinking here](https://github.com/OfficeDev/VBA-content/issues), but not sure if there is a better place. – Falthazar Jul 28 '17 at 18:52
1

I am not entirely sure if I had the same issue as you, but the call to GetInspector started failing for me after upgrading Office 2016. So to be clear it worked with Office 2016 and then stopped working after the latest update.

The following workaround worked for me

dim item : set item = Addin.Outlook.CreateItemFromTemplate(Filename)
Outlook.Inspectors.Add(item) ' Outlook is the application object

it only appears to work if I add the item straight after creating it, setting properties on it and then adding it did not work.

Note: I have not tested with CreateItem instead of CreateItemFromTemplate. The second line was added and unnecessary prior to the Office update.

Marcus
  • 5,987
  • 3
  • 27
  • 40
1

Problem: For security purposes, the HTMLBody, HTMLEditor, Body and WordEditor properties all are subject to address-information security prompts because the body of a message often contains the sender's or other people's e-mail addresses. And, if Group Policy does not permit then these prompts do not come on-screen. In simple words, as a developer, you are bound to change your code, because neither registry changes can be made nor group policy can be modified.

Hence, if your code suddenly stopped working after migrating to Office 365 or for any other reasons, please refer to the solutions below. Comments have been added for easy understanding and implementation.

Solution 1: If you have administrative rights then try the registry changes given at below link: https://support.microsoft.com/en-au/help/926512/information-for-administrators-about-e-mail-security-settings-in-outlo

However, as developer, I recommend a code that's rather compatible with all versions of Excel instead of making system changes because system changes will be required on each end user's machine as well.

Solution 2: VBA Code Code Compatible: Excel 2003, Excel 2007, Excel 2010, Excel 2013, Excel 2016, Office 365


Option Explicit

Sub Create_Email(ByVal strTo As String, ByVal strSubject As String)


    Dim rngToPicture As Range
    Dim outlookApp As Object
    Dim Outmail As Object
    Dim strTempFilePath As String
    Dim strTempFileName As String

    'Name it anything, doesn't matter
    strTempFileName = "RangeAsPNG"

    'rngToPicture is defined as NAMED RANGE in the workbook, do modify this name before use
    Set rngToPicture = Range("rngToPicture")
    Set outlookApp = CreateObject("Outlook.Application")
    Set Outmail = outlookApp.CreateItem(olMailItem)

    'Create an email
    With Outmail
        .To = strTo
        .Subject = strSubject

        'Create the range as a PNG file and store it in temp folder
        Call createPNG(rngToPicture, strTempFileName)

        'Embed the image in Outlook
        strTempFilePath = Environ$("temp") & "\" & strTempFileName & ".png"
        .Attachments.Add strTempFilePath, olByValue, 0

        'Change the HTML below to add Header (Dear John) or signature (Kind Regards) using newline tag (<br />)
        .HTMLBody = "<img src='cid:DashboardFile.png' style='border:0'>"


        .Display

    End With

    Set Outmail = Nothing
    Set outlookApp = Nothing
    Set rngToPicture = Nothing

End Sub

Sub createPNG(ByRef rngToPicture As Range, nameFile As String)

    Dim wksName As String

    wksName = rngToPicture.Parent.Name

    'Delete the existing PNG file of same name, if exists
    On Error Resume Next
        Kill Environ$("temp") & "\" & nameFile & ".png"
    On Error GoTo 0

    'Copy the range as picture
    rngToPicture.CopyPicture

    'Paste the picture in Chart area of same dimensions
    With ThisWorkbook.Worksheets(wksName).ChartObjects.Add(rngToPicture.Left, rngToPicture.Top, rngToPicture.Width, rngToPicture.Height)
        .Activate
        .Chart.Paste
        'Export the chart as PNG File to Temp folder
        .Chart.Export Environ$("temp") & "\" & nameFile & ".png", "PNG"
    End With
    Worksheets(wksName).ChartObjects(Worksheets(wksName).ChartObjects.Count).Delete

End Sub
jainashish
  • 4,702
  • 5
  • 37
  • 48
0

Try moving the editor to the first action... ...

     With OutMail

        Set outEdit = .GetInspector.WordEditor
        outEdit.Content.Paste

        .SendUsingAccount = OutApp.Session.Accounts.Item(1)
        .To = sendEmail
        .CC = ccEmail
        .Subject = subjEmail & " (Site: " & siteName & ")"

...

  • 1
    Thanks! Sorry I actually solved this a while ago. Turns out it was an extra security setting either because of Office 2016 or through a group policy. You can check with `outApp.isTrusted`. Ended up creating a separate VSTO add-in that just returned the trusted outlook application. – Falthazar Aug 02 '18 at 21:08
  • Hi @Falthazar, I'm running into the same issue and was wondering how you solved it. I'm a bit new to VBA. – student Mar 10 '22 at 21:39
  • @Eli It's been so long but what I think i ended up doing is creating a separate Outlook VBA addon that exposed the trusted Outlook object, and accessed that from the Excel VBA addon. I might be able to find it if you still need help! – Falthazar Mar 23 '22 at 15:54
  • Thank you so much @Falthazar! I simply open Outlook before I run the macro and it works fine now. – student Apr 06 '22 at 02:15