pythonvbaoutlook-restapi

Send Graphs in Outlook


I wanted to create better automated reports by including visuals rather than just text. The specific way I wanted to do it was by referencing outlook.application via win32com.client.

I know the basics of sending an email, and I've tried reading through the VBA reference and the closest I found was a View Object, but what I was looking for was the ability to add pie charts, bar graphs etc.

I know through the GUI, once in an open message popped out from the application you can Insert > Chart and select the desired chart to load into the message.

Is there a way in the outlook API to be able to utilize these graphs/charts that are available in the Insert Chart window? Or is the API relatively limited in features available compared to the application when it comes to message styling/formatting?

Here's the bare-bones code for how the message is created/sent, I was wanting to add these visuals to the message body.

import win32com.client as win32

outlook = win32.Dispatch('outlook.application')
mail = outlook.CreateItem(0)

mail.To = 'some@name'
mail.Subject = 'Subject'
mail.Body = 'Body'
# or 
mail.HTMLBody = '<h2>HTML body</h2>' 

mail.Send()

Update

I'm currently looking into it more, but I found this for vba that's supposed to do what I'm looking for. I've been messing around with chart objects a bit in excel as well. Here's the code I need to understand

Sub CopyAndPasteToMailBody()
    Set mailApp = CreateObject("Outlook.Application")
    Set mail = mailApp.CreateItem(olMailItem)
    mail.Display
    Set wEditor = mailApp.ActiveInspector.wordEditor
    ActiveChart.ChartArea.Copy
    wEditor.Application.Selection.Paste
End Sub

Here's some bare bones code I have that will create a chart object:

from win32com import client

excel = client.Dispatch("excel.application")
excel.Visible = True
wb = excel.Workbooks.Add()
ws = wb.Worksheets.Add()
chs = ws.ChartObjects()
co = chs.Add(0,0,500,500)

Update

Below I have answered how to spawn a chart in Excel and have it sent through Outlook. It is not the 'Outlook API', as it's Office as a whole that must be utilized. If you were confused like I was by a lack of documentation for using win32com to interact with Office applications, that's because it's all here in the VBA Reference and just needs to be converted into python accordingly.


Solution

  • After doing more testing, I've figured it out. Here's a piece of what I made with sample data I had laying around. Note the line ch.ChartType = 5 # Pie chart as this answers the question. Yes, the graphs and charts can be accessed via the API, and ChartTypes can be found here. This answers the specific question, as well as the greater question of how to take data that exists outside of Office and load it into a chart to be sent through Outlook via the API.

    from win32com import client
    from random import randint
    
    labels  = []
    ch_data = []
    
    for x,y in _data:
        labels.append(x)
        ch_data.append(y)
    
    _range = range(1,len(labels)+1)
    l_plot = map(lambda x: 'A'+str(x),_range)
    d_plot = map(lambda x: 'B'+str(x),_range)
    start_end = '{}:{}'.format(l_plot[0],d_plot[-1])
    
    excel         = client.Dispatch('excel.application')
    excel.Visible = True # optional
    wb            = excel.Workbooks.Add()
    ws            = wb.Worksheets.Add()
    
    cnt           = 0
    for i in l_plot:
        ws.Range(i).Value = labels[cnt]
        cnt += 1
    
    cnt           = 0
    for i in d_plot:
        ws.Range(i).Value = ch_data[cnt]
        cnt += 1
    
    chs             = ws.ChartObjects()
    co              = chs.Add(100,0,250,250)
    ch              = co.Chart
    ch.HasTitle     = True
    ch.ChartTitle.Text = 'Chart Title'
    ch.ChartType    = 5 # Pie chart
    
    series          = ch.SeriesCollection()
    series.Extend(ws.Range(start_end))
    co.Copy()
    
    outlook = client.Dispatch('outlook.application')
    mail = outlook.CreateItem(0)
    mail.Display() # required to paste chart
    mail.To = 'alias@email.com'
    mail.Subject = 'Test Mail Item with Chart'
    mail.HTMLBody = '<h3>Hello sir. This is a test</h3><br><br>'
    
    inspector = mail.GetInspector
    editor = inspector.WordEditor
    editor.Select()
    editor.Application.Selection.Start = editor.Application.Selection.End
    editor.Application.Selection.Paste()
    
    mail.HTMLBody += '<p>I\'m glad this is finally figured out</p>'
    mail.Send()