2

I am developing a VBA / VSTO script that interacts with Outlook.

I have a process that should, essentially, do this:

  1. Read in an .oft file that is in Rich Text Format
  2. Parse the RTFBody array into a String
  3. Replace some elements of the String (so a line that says "%SUBJECT%" will instead be "IMPORTANT MEETING")
  4. Convert that String back into the RTF array format (this uses a Rich Text Box)
  5. Replace the RTFBody with the updated RTF array
  6. Display the finished email

This is all done. Except the finished email is just RTF garbage with no formatting.

So what is meant to be a lovely table is instead this:

{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff37\deff0\stshfdbch0\stshfloch37\stshfhich37\stshfbi37\deflang2057\deflangfe2057\themelang2057\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304

(You can imagine the rest.)

The code is:

Dim objMsg As AppointmentItem
' 1. Read in an .oft file that is in Rich Text Format
objMsg = Application.CreateItemFromTemplate(currentLocation & "\template.oft")

' 2. Parse the RTFBody array into a String
Dim rtfArray = objMsg.RTFBody
Dim Encoding = New System.Text.ASCIIEncoding()
Dim rtfBody = Encoding.GetString(rtfArray)

' 3. Replace some elements of the String (so a line that says "%SUBJECT%" will instead be "IMPORTANT MEETING")
rtfBody = Replace(rtfBody, "%SUBJECT%", "Important Meeting")

' 4. Convert that String back into the RTF array format (this uses a Rich Text Box)
Dim rtb = New System.Windows.Forms.RichTextBox()
rtb.Text = rtfBody
Dim newArray = System.Text.Encoding.ASCII.GetBytes(rtb.Rtf)

'5. Replace the RTFBody with the updated RTF array
objMsg.RTFBody = newArray

'6. Display the finished email
objMsg.Display()

Does anyone have any awareness of what the solution to this problem is?

And before anyone suggests HTML... I would love to! But this is an AppointmentItem so it doesn't support HTMLBody.

RFarrar
  • 21
  • 2
  • Why are you using RTF editor? You are also mismatching text encodings (ASCII vs UTF8). – Dmitry Streblechenko Sep 06 '22 at 18:42
  • I need to edit the RTF because I need to regenerate the template programmatically, as mentioned in the post, and I am unable to use HTML for the reasons mentioned in the post. Thank you for noticing the mismatched text encodings, unfortunately that has not actually made a difference. – RFarrar Sep 12 '22 at 08:07
  • You can generate an RTF file once in WordPad with a placeholder and just replace the placeholder in the data at run-time. – Dmitry Streblechenko Sep 12 '22 at 17:42
  • I am not sure what you mean. I have the .otf (RTF-based template with placeholders) already developed. The issue is that the replacement doesn't work here. Are you suggesting there's another method to do this and, if so, can you demonstrate it in a full answer? – RFarrar Sep 13 '22 at 14:39
  • No, I am suggesting having a standalone (or an embedded resource) RTF file. You can do the necessary replacement at run-time and set the RTFBody property without ever using an RTF control. – Dmitry Streblechenko Sep 13 '22 at 17:28

1 Answers1

1

To parse the RTFBody array into a string you have dealt with ASCII encoded string:

Dim rtfArray = objMsg.RTFBody
Dim Encoding = New System.Text.ASCIIEncoding()
Dim rtfBody = Encoding.GetString(rtfArray)

But to set the RTFBody you deal with UTF8 for an unknown reason:

Dim newArray = System.Text.Encoding.UTF8.GetBytes(rtb.Rtf)

Try to use the same encoding:

Dim newArray = System.Text.Encoding.ASCII.GetBytes(rtb.Rtf)

Be aware, The Outlook object model supports three main ways of customizing the message body:

  1. The Body property returns or sets a string representing the clear-text body of the Outlook item.
  2. The HTMLBody property of the MailItem class returns or sets a string representing the HTML body of the specified item. Setting the HTMLBody property will always update the Body property immediately. For example:
     Sub CreateHTMLMail() 
       'Creates a new e-mail item and modifies its properties. 
       Dim objMail As Outlook.MailItem 
       'Create e-mail item 
       Set objMail = Application.CreateItem(olMailItem) 
       With objMail 
        'Set body format to HTML 
        .BodyFormat = olFormatHTML 
        .HTMLBody = "<HTML><BODY>Enter the message <a href="http://google.com">text</a> here. </BODY></HTML>" 
        .Display 
       End With 
     End Sub
  1. The Word object model can be used for dealing with message bodies. See Chapter 17: Working with Item Bodies for more information.

Note, the MailItem.BodyFormat property allows you to programmatically change the editor that is used for the body of an item.

Eugene Astafiev
  • 47,483
  • 3
  • 24
  • 45
  • Thank you for noticing the incorrect encoding. I have updated that in the code and in the post but unfortunately it has not resolved the issue. – RFarrar Sep 12 '22 at 08:10
  • Sadly, it is not possible to use HTMLBody on AppointmentItems as Microsoft's Outlook team prevent it in their infinite wisdom. HTMLBody was my first attempt at this, but it does not work even with late binding or polymorphic inheritance of properties. The requirement is to include some graphical qualities on this template so they need to be preserved. – RFarrar Sep 12 '22 at 08:11
  • Have you tried using other approaches mentioned in my post? – Eugene Astafiev Sep 12 '22 at 08:17
  • Hello Eugene, I have tried all three of the approaches. The first two in detail (Body does not work because I need to preserve formatting, HTMLBody does not work because AppointmentItems do not allow for programmatic HTML) and the latter one provisionally (where the complexity seems very out of bounds and there is minimal support for it wherever I look). – RFarrar Sep 12 '22 at 14:43