pythonpywin32win32com

Copy pasting Excel range to Outlook email - GetInspector Error


I don't recall making any changes to the code, but now my helper function for sending emails gets the following error:

com_error: (-2147352567, 'Exception occurred.', (4096, 'Microsoft Outlook', 'The operation failed.', None, 0, -2147467259), None)

The error happens at the GetInspector line of my function:

Cell In[78], line 9
      7 msg = outlook.CreateItem(0)
      8 msg.HTMLBody = ''
----> 9 msg.GetInspector.WordEditor.Range(Start=0, End=0).Paste()

File ~\AppData\Roaming\Python\Python310\site-packages\win32com\client\dynamic.py:620, in CDispatch.__getattr__(self, attr)
    616 debug_attr_print(
    617     "Getting property Id 0x%x from OLE object" % retEntry.dispid
    618 )
    619 try:
--> 620     ret = self._oleobj_.Invoke(retEntry.dispid, 0, invoke_type, 1)
    621 except pythoncom.com_error as details:
    622     if details.hresult in ERRORS_BAD_CONTEXT:
    623         # May be a method.

Code:

import win32com.client

path = 'C:\\Documents\\'
filename = 'Book1.xlsx'

excel = win32com.client.gencache.EnsureDispatch('Excel.Application')

def send_email(path, filename):
    book = excel.Workbooks.Open(path+filename)
    book.Sheets(1).Range("A1:B2").Copy()
    outlook = win32com.client.Dispatch("Outlook.Application")
    msg = outlook.CreateItem(0)
    msg.HTMLBody = ''
### msg.Display 
    msg.GetInspector.WordEditor.Range(Start=0, End=0).Paste()
    msg.To = 'myemail@outlook.com'
    msg.Send

send_email(path,filename)

If I display the mail item (commented out), paste from clipboard and press send myself, everything else works.

Sample Table (copy paste to range A1:B2)

Column A Column B
Cell 1 Cell 2
Cell 3 Cell 4

Ideally, the pasted table in Outlook should retain excel formatting.

Outlook email with pasted excel table


Solution

  • You can paste an Excel range into the body of an Outlook email using win32com.client without hitting the GetInspector error by considering the following:

    Here's a working version of your code. I've already tested it and it works.

    import time
    import win32com.client as win32
    
    excel = win32.gencache.EnsureDispatch('Excel.Application')
    
    
    def send_email(path, filename):
        # Open workbook and copy range
        book = excel.Workbooks.Open(path + filename)
        book.Sheets(1).Range("A1:B3").Copy()
        # Create Outlook email
        outlook = win32.Dispatch("Outlook.Application")
        msg = outlook.CreateItem(0)
        msg.HTMLBody = 'Hi There'
    
        # Display the email first (important for WordEditor to be available)
        msg.Display()
        time.sleep(0.5)  # Small delay for COM to be ready
    
        # Paste the copied Excel range
        msg.GetInspector.WordEditor.Range(Start=0, End=0).Paste()
    
        # Email details
        msg.To = "myemail@outlook.com"
        msg.Subject = "Excel Data"
        msg.BodyFormat = 2  # 2 = HTML format
    
        # Send the email
        msg.Send()
    
        # Close the Excel workbook
        book.Close(SaveChanges=False)
    
    path = r"D:\\"
    filename = "Book1.xlsx"
    # Update these to match your local Excel file
    send_email(path, filename )
    

    Why this fixes the error:

    1. msg.Display() before WordEditor

      • GetInspector.WordEditor only works after the email window is displayed or fully initialized.
    2. Small delay (time.sleep)

      • Gives COM enough time to prepare the Word editor inside Outlook.

    One more thing, In your code, you’re calling msg.Send without parentheses (msg.Send() is needed).

    here's a more optimised version of your code.