0

I would like to send an email with Python automatically everyday. In the email I want to have an equation explaining how the number inside my email are calculated.

All of my recipients use Outlook as their email desktop clients. Is there any way to enclose the formula in an equation instead of currently a plain text with the simple equation $f(A)-f(B)$.

Any hints will be highly appreciated!

Summer_More_More_Tea
  • 12,740
  • 12
  • 51
  • 83
  • Yes. Use http://s1.daumcdn.net/editor/fp/service_nc/pencil/Pencil_chromestore.htm, for instance, to convert `$f(A)-f(B)$` into a jpeg image. Embed your message with that image into HTML and send that. I suspect we need more details. – Bill Bell Jun 18 '17 at 14:44
  • @BillBell thanks for your reply and really brilliant solution. Is it possible to encode the equation directly into email as what Outlook "insert equation" itself does? – Summer_More_More_Tea Jun 19 '17 at 10:22
  • Quite possibly, I haven't tried it. (1) MS Office products have COM interfaces that can be accessed and manipulated using Python. (2) Since Outlook can be manipulated via its GUI an equation could be encoded using keystrokes using Python via a library such as https://pyautogui.readthedocs.io/en/latest/. – Bill Bell Jun 19 '17 at 14:48
  • @BillBell cool stuff! This is actually an excellent answer rather than a commnet ;) – Summer_More_More_Tea Jun 19 '17 at 15:14
  • I can take a hint. – Bill Bell Jun 19 '17 at 15:16

2 Answers2

1

Here are some possibilities:

MS Outlook can send email in the form of HTML. HTML can contain embedded images and mathematical formulae can be encoded in LaTex then converted to images that are embeddable in HTML. Thus, one approach would be to use a product such as the Daum Equation Editor to encode formulae into LaTex and to save the result as, say, a Jpeg file. Depending on the application, it might be possible to parameterise formulae so that elements of the LaTex could be substituted without the need for using the Daum product and then converted to an image, using Python code.

MS Office products have COM interfaces that are accessible using Python using the win32com library. A good way of exploring this is to use the PythonWin REPL.

Since Outlook can be manipulated via its GUI an equation can be encoded using keystrokes and mouse gestures using Python via a library such as PyAutoGUI.

EDIT:

I just looked for other possibilities and was reminded of this: https://stackoverflow.com/a/36249956/131187.

Bill Bell
  • 21,021
  • 5
  • 43
  • 58
1

i assembled a lot of bits and pieces from the web

here is a working test program

just open "new email" then run the program (or single-step)

the second half of the program is just to show how to manipulate text in the email body

it is only VBA, but it may give you a starting point

i will have a look at the python interface next

regards

js:)

' NOTE:    make sure that you have a reference to "microsoft word object library"

'          go to "tools" ... "references" ... find microsoft word object library in dropdown and click on checkmark box 



' this is just some test text
Const a1 = "1111111111 1234567890 1111111133 1111111144 1111111155"
Const a2 = "2222222211 2222222222 2222222233 2222222244 2222222255"
Const a3 = "3333333311 3333333322 3333333333 3333333344 3333333355"
Const a4 = "3333333366 3333333377 3333333388 3333333399 3333333300"
Const a5 = "4444444411 4444444422 4444444433 4444444444 4444444455"





Sub test1234()

    Dim wordDoc As Document
    Set wordDoc = Application.ActiveInspector.WordEditor

    wordDoc.Range.Delete                 ' clean page
    wordDoc.Paragraphs.Space1            ' single space paragraph
    wordDoc.Paragraphs.SpaceBefore = 0   ' no space before paragraph
    wordDoc.Paragraphs.SpaceAfter = 0    ' no space after paragraph
    wordDoc.Range.InsertAfter (a1)
    wordDoc.Range.InsertParagraphAfter   ' paragraph mark
    wordDoc.Range.InsertAfter (a2)
    wordDoc.Range.InsertParagraphAfter
    wordDoc.Range.InsertAfter (a3)
    wordDoc.Range.InsertAfter Chr(11)    ' linebreak
    wordDoc.Range.InsertAfter (a4)
    wordDoc.Range.InsertParagraphAfter
    wordDoc.Range.InsertAfter (a5)
    wordDoc.Range.InsertParagraphAfter

    Stop

    Dim objRange As Range
    Dim rng As Range
    Dim objEq As oMath
    Dim formula As String

    ' check this webpage re. problems with oMath
    ' https://stackoverflow.com/questions/20068212/excel-word-equations-using-omath-buildup-method#20072757

    'formula = "Celsius = (5/9)(Fahrenheit - 32)"
    formula = "Celsius = " & ChrW(&H221A) & "(x+y) + sin(5/9 × (Fahrenheit – 23 (" & ChrW(&H3B4) & ")^2))"

    wordDoc.Range.InsertParagraphAfter
    wordDoc.Range.InsertAfter (formula)
    wordDoc.Range.InsertParagraphAfter

    Stop        

    Offset = Len(formula)

    Set rng = wordDoc.Range(wordDoc.Sentences(5).Characters(1).Start, wordDoc.Sentences(5).Characters(Offset).End)
    rng.Select    ' this line is not necessary, but it shows size and position of the range when single-stepping through the program

    Set objRange = wordDoc.OMaths.Add(rng)
'    objRange.OMaths(1).BuildUp
    wordDoc.OMaths(1).BuildUp

    Application.ActiveInspector.currentItem.Display       ' not sure what this does, exactly ... may not be necessary
    Application.ActiveInspector.currentItem.Save          ' save email draft
'   Application.ActiveInspector.currentItem.Close olSave

    Stop

' the equation should be in the email body at this point
' ------------------------------------------------------



' ------ following is just code that "plays around" with the text

' ------ it may be of interest to someone


    response = InputBox("Type some text")
    With wordDoc.Paragraphs(wordDoc.Paragraphs.Count).Range
        .InsertAfter "1." & vbTab & response
        .InsertParagraphAfter
    End With

    Stop

    wordDoc.Undo
    wordDoc.Undo

    Stop

    wordDoc.Range.Delete
    wordDoc.Undo
    wordDoc.Paragraphs(1).Range.Delete unit:=wdWord, Count:=3    ' delete 1st three words
    wordDoc.Undo
    wordDoc.Sentences(1).Words(2).Delete unit:=wdWord, Count:=2  ' delete words 2 and 3
    wordDoc.Undo
    wordDoc.Sentences(1).Words(2).Characters(4).Delete unit:=wdCharacter, Count:=2  ' delete characters in second word
    wordDoc.Undo

'    Debug.Print wordDoc.Sentences(1).Characters.Count

'    Debug.Print wordDoc.Words.Count       ' EOL counts as a word
'    For i = 1 To wordDoc.Words.Count
'        Debug.Print wordDoc.Words(i)
'    Next
    Stop

'    Dim word As Range
'    Debug.Print wordDoc.Sentences(2).Words.Count       ' EOL counts as a word
'    For Each word In wordDoc.Sentences(2).Words
'        Debug.Print word
'    Next
    Stop

'   these two are the same
'   Application.ActiveInspector.currentItem.GetInspector.WordEditor.Characters(2).InsertBefore "___xxxxxx___"
'   Application.ActiveInspector.WordEditor.Characters(2).InsertBefore "___xxxxxx___"

    wordDoc.Characters(1).Select               ' 1st character from top of page
    wordDoc.Characters(10).Select              ' 10th character from top of page
    wordDoc.Range(0, 5).Select                 ' 1nd to 5th character
    wordDoc.Range(1, 5).Select                 ' 2nd to 5th character

    Debug.Print wordDoc.Characters(1)          ' 1
    Debug.Print wordDoc.Characters(1).Start    ' 0
    Debug.Print wordDoc.Characters(1).End      ' 1
    Debug.Print wordDoc.Characters(1)          ' 1


'    wordDoc.Sentences(3).Select                     ' all of 3rd sentence (paragraph)
'    wordDoc.Sentences(4).Characters(5).Select       ' 5th character of 4th sentence

'    Debug.Print wordDoc.Sentences(4).Characters(3)  ' !!!! position of 2nd character on PAGE !!!!

'    Debug.Print wordDoc.Sentences(2).Characters(3).Start   ' position of 3rd character in 2nd sentence
'    Debug.Print wordDoc.Sentences(2).Characters(3).End     ' position AFTER 3rd character in 2nd sentence

'    wordDoc.Range(wordDoc.Sentences(2).Characters(3).Start, wordDoc.Sentences(3).Characters(5).End).Select
'    wordDoc.Range(wordDoc.Sentences(2).Characters(3).End, wordDoc.Sentences(3).Characters(5).End).Select

'    wordDoc.Sentences(2).InsertBefore "__ before sentence #2 __"
'    wordDoc.Sentences(3).InsertAfter "__ after sentence #3 __"


End Sub
jsotola
  • 2,238
  • 1
  • 10
  • 22