I have already seen a lot of posts related to that, both on the web overall or on stackoverflow. However, I didn't see people making too much changes and really playing with this macro.
Ok, it's possible to send emails through lotus notes using VBA, but how can I make these emails cooler? Change font format or color for example? Change the styles, choosing to insert picture as a link or embedding it?
Well, this is what I got so far by searching around and making a few changes:
Sub SendEmail(Subject, Text)
Dim Maildb As Object
Dim mailDoc As Object
Dim body As Object
Dim session As Object
'Start a session to notes
Set session = CreateObject("Lotus.NotesSession")
'This line prompts for password of current ID noted in Notes.INI
'Call session.Initialize
Call session.Initialize("Your Password Here")
'Open the mail database in notes
Set Maildb = session.GetDatabase("Mail Server", "mail\ .nsf")
If Not Maildb.IsOpen = True Then
Call Maildb.Open
End If
'Create the mail document
Set mailDoc = Maildb.CreateDocument
Call mailDoc.ReplaceItemValue("Form", "Memo")
'Set the recipient (you can write the name of a list you saved in your Lotus Notes)
Call mailDoc.ReplaceItemValue("SendTo", "email1#email.com.br")
'Set subject
Call mailDoc.ReplaceItemValue("Subject", Subject)
'Create and set the Body content
Set body = mailDoc.CreateRichTextItem("Body")
Call body.AppendText(Text)
'Example to create an attachment (optional)
Call body.AddNewLine(2)
'Insert an pdf attached
Call body.EmbedObject(1453, "", "C:\Desktop\Test.pdf")
Call body.AddNewLine(2) 'add line to separate text
'Message in the end of the email
Call body.AppendText("This is an automatic message.")
'Example to save the message (optional)
mailDoc.SaveMessageOnSend = True
'Send the document
'Gets the mail to appear in the Sent items folder
Call mailDoc.ReplaceItemValue("PostedDate", Now())
Call mailDoc.send(False)
'Clean Up
Set Maildb = Nothing
Set mailDoc = Nothing
Set body = Nothing
Set session = Nothing
End Sub
Btw, I use the Windows Task Scheduler to call a VBS which will then call a macro that will call the macro to send email with a specific subject and text. As I have several macros that generates emails and each one has its subject and text, I thought this would be better.
This is the vbs (this is probably useless and everyone knows here, but I will share anyway):
'Run VBA Using VBS
Option Explicit
On Error Resume Next
ExcelMacroExample
Sub ExcelMacroExample()
Dim xlApp
Dim xlBook
Set xlApp = CreateObject("Excel.Application")
Set xlBook = xlApp.Workbooks.Open("C:\Desktop\Macros.xlsm") 'Excel filename
xlApp.Run "SendEmail" 'Excel macro name
xlApp.Quit
Set xlBook = Nothing
Set xlApp = Nothing
End Sub
A couple of things here:
It's going to be easier if you can first write the code in Domino Designer (i.e. get a machine installed with the Notes Client and the Domino Designer Client). At the moment you are using Notes as a COM Server. The big disadvantage is that you have almost no debugging information if something fails. Write the code first in LotusScript, then port it to VBS (they are very similar dialects of BASIC).
You can create a Notes RichText E-Mail (this is what you are doing now with CreateRichTextItem). You can manipulate the RichTextItem with different methods, the most important one being NotesRichTextStyle, which you have to think of as 'bits of formatting that will change everything afterwards'. You need to create the NotesRichTextStyle Object, configure it (i.e. font, bold, etc) and insert it into the rich text field. If this sounds klunky, that's because it is.
Dim db As NotesDatabase
Dim session As New NotesSession
Set db = session.CurrentDatabas
Dim doc As New NotesDocument(db)
Call doc.AppendItemValue("From", session.UserName)
Call doc.AppendItemValue("Subject", _
"Meeting time changed")
Dim richStyle As NotesRichTextStyle
Set richStyle = session.CreateRichTextStyle
Dim richText As New NotesRichTextItem(doc, "Body")
Call richText.AppendText("The meeting is at ")
richStyle.Bold = True
Call richText.AppendStyle(richStyle)
Call richText.AppendText("3:00")
richStyle.Bold = False
Call richText.AppendStyle(richStyle)
Call richText.AppendText(" not 2:00")
Call doc.Save(True, False)
If you want even more control, then you can create an HTML E-Mail wrapped in Mime, but it's fiddly at best and you're looking at several days of painful steps until it works, and you really would need an experienced professional for this. This is a good start: other Stackoverflow question
The way you're referencing the user's mail reference is horrible. It's hardcoded and will only ever work for that one particular database, even if the person in question changes name, for instance. This is much better:
Dim db As New NotesDatabase( "", "" )
Call db.OpenMail
Related
I have a set of macros that have worked in Outlook 2003, 2007, and 2010. In fact, it still works in 2013 except in a specific case.
The macro brings up a dialog box whenever you try to send an email - to tag the subject line with key words. The problem is, if I just started Outlook, and I bring up a new email or reply - the default in Outlook 2013 is to bring it into the former "Reading Pane" rather than in a new window. If I do not hit "Pop Out" and I try to send, my macro crashes with this error:
"Run-time error '91' Object variable or with block variable not set"
I tried to check for loading the form first - but it seem ANY call to my userform, even userform.show, generates this error.
Oddly, if I remember to "Pop Out" my first email, it runs fine everytime after until I close/reopen Outlook. Even if I don't "Pop Out" other emails. It's only on the very first one that this occurs.
Here's the beginning of my Initialize Event:
Dim Tags() As String
Dim T As Variant
Dim PC As Variant
Dim Rent As String
Dim Child As String
Dim nsourcefile As Integer
Dim email As MailItem
Dim PD As Variant
Dim Proj As String
Dim Desc As String
'Set email = Application.ActiveInspector.CurrentItem
Set email = Application.ActiveExplorer.Selection.Item(1)
'Checks to see if a project number (that's not on the list) may be in the subject already
If Val(email.Subject) > 10000 Then
TagMsg.Height = tall
TagMsg.NewProjID = Format(Val(email.Subject), "00000")
TagMsg.NewProjDesc.SetFocus
Else
'Set height of form (prior to pressing "More" button
TagMsg.Height = short
End If
Noticed I changed Set email = Application.ActiveInspector.CurrentItem to Set email = Application.ActiveExplorer.Selection.Item(1). This seems to have fixed it, but the VBA help states "Do not make any assumptions about the Item method return type; your code should be able to handle multiple item types or a ConversationHeader object."
Note that the form is being invoked by the ItemSend event.
First off, putting that code into the Initialize event wasn't a good move. Needed to be moved into a click event where it was actually needed.
Then, I found the code I needed from two other posts, combined and shortened them.
Working with current open email
https://superuser.com/questions/795831/outlook-2013-vba-refer-to-editor-in-reading-pane
Final result
Dim oInspector As Inspector
Dim email As MailItem
Dim oexp As Explorer
Set oInspector = Application.ActiveInspector
Set oexp = Application.ActiveExplorer
If oInspector Is Nothing Then
'Set email = Application.ActiveExplorer.Selection.Item(1)
Set email = oexp.ActiveInlineResponse
If email Is Nothing Then
'MsgBox "No active inspector or inline response"
Exit Sub
End If
Else
Set email = oInspector.CurrentItem
End If 'oInspector is Nothing
If email.Sent Then
'MsgBox "This is not an editable email"
Else
'Checks to see if a project number (that's not on the list) may be in the subject already
If Val(email.Subject) > 10000 Then
TagMsg.Height = tall
TagMsg.NewProjID = Format(Val(email.Subject), "00000")
TagMsg.NewProjDesc.SetFocus
Else
'Set height of form (prior to pressing "More" button
TagMsg.Height = short
End If
End If 'email.sent
Note: This still relies on the fact that it is called by the ItemSend event and the active or current item will be the email I just pressed "send" on.
Thank you, retailcoder for your comments.
Can anyone help me figure out what's going wrong and how to fix it?
I'm trying to automate sending an email with some daily status information. I'd tried automating this from Access but kept running into (known but apparently unsolved) problems with GetObject(, "Outlook.Application") with Windows 8.1 64 and Outlook 2013. So I decided to automate starting from Outlook.
Anyway, I moved the mail message creation code into Outlook vba and had it start Access and run the Access code. This is all well and good until I get to creating the mail message. Everything starts just fine until it gets to writing to the body of message (using Word as the body editor). At the first "TypeText" command, I'm getting the error message in the title. If I click debug on the error notification dialog and then single-step through the line of code in question, it works just fine. I thought that there was some timing problem, so I stuck a 2-second wait in the code. No luck. The code in question, with some other oddities associated with testing (notably trying to type and then delete text), is below:
Public Sub CreateMetrics()
' Mail-sending variables
Dim mailApp As Outlook.Application
Dim accessApp As Access.Application
Dim mail As MailItem
Dim wEditor As Word.Document
Dim boolCreatedApp As Boolean
Dim i As Integer
Set mailApp = Application
' Create an Access application object and open the database
Set accessApp = CreateObject("Access.Application")
accessApp.OpenCurrentDatabase dbLoc
accessApp.Visible = True
' Open the desired form and run the click event hander for the start button
accessApp.DoCmd.OpenForm ("ProcessStatus")
accessApp.Forms![ProcessStatus].StartButton_Click
' Create the outgoing mail message
Set mail = Application.CreateItem(olMailItem)
mail.Display
mail.BodyFormat = olFormatHTML
Set wEditor = mailApp.ActiveInspector.WordEditor
With accessApp.Forms![ProcessStatus]
Debug.Print .lblToList.Caption
Debug.Print .lblSubject.Caption
Debug.Print .lblIntroduction.Caption
Debug.Print .lblAttachFilepath.Caption
End With
mail.To = accessApp.Forms![ProcessStatus].lblToList.Caption
mail.Recipients.ResolveAll
mail.Subject = accessApp.Forms![ProcessStatus].lblSubject.Caption
mail.Attachments.Add accessApp.Forms![ProcessStatus].lblAttachFilepath.Caption
Sleep 2000
' Error occurs in the next line ***********************************************
wEditor.Application.Selection.TypeText Text:="Test"
wEditor.Application.Selection.HomeKey
wEditor.Application.Selection.Delete Count:=4
wEditor.Application.Selection.PasteSpecial DataType:=wdPasteBitmap
wEditor.Application.Selection.HomeKey
wEditor.Application.Selection.TypeText accessApp.Forms![ProcessStatus].lblIntroduction.Caption
wEditor.Application.Selection.TypeText Text:=Chr(13) & Chr(13)
wEditor.Application.Selection.EndKey
' wEditor.Application.Selection.EndKey
' wEditor.Application.Selection.TypeText Text:=Chr(13)
' wEditor.Application.Selection.TypeText Text:=configs("EmailSignature")
' End With
With mailApp.Session.Accounts
i = 1
Do While i <= .Count
' Use either the specified email address OR the last outlook email address
If RegEx_IsStringMatching(.Item(i).SmtpAddress, accessApp.Forms![ProcessStatus].lblSenderRegex.Caption) Or i = .Count Then
mail.SendUsingAccount = .Item(i)
i = .Count + 1
Else
i = i + 1
End If
Loop
End With
mail.Save
accessApp.Quit
End Sub
I added a "mail.Display" just before the line that was causing the failure, which seemed, incorrectly, to have fixed the problem.
I have now solved this problem by executing a document.select on the document associated with the email I was creating. To select the right document (there doesn't seem to be any guarantee of which one that would be within the wEditor.Application.Documents collection, though it was typically the first one), I created an almost-certainly unique piece of text and assigned it to the body of the email, which I could then go and find. Here's the new code that I added to the code above:
Dim aDoc As Word.Document
Dim strUniqueID As String
. . .
mail.Attachments.Add accessApp.Forms![ProcessStatus].lblAttachFilepath.Caption
strUniqueID = accessApp.Forms![ProcessStatus].lblSubject.Caption & Rnd(Now()) & Now()
mail.Body = strUniqueID
' Search for the unique text. aDoc.Content has extra characters at the
' end, so compare only for the length of the unique text
For Each aDoc In wEditor.Application.Documents
If Left(aDoc.Content, Len(strUniqueID)) = strUniqueID Then
aDoc.Select
mail.Body = ""
End If
Next aDoc
wEditor.Application.Selection.TypeText Text:="Test"
. . .
I looked at a lot of examples of code that did this kind of thing. None of them performed a select or said anything about needing one. Debugging was made that much harder because the select occured implicitly when the debugger was invoked.
What I am trying to achieve is very simple, insert the body of an email above the signature in lotus notes. The code I have in vba, when run, opens a new email window in lotus notes pastes in the Subject, SendTo and Body fields. Everything works perfectly, but when the body is inserted it puts the text below my signature. I've done a ton of digging to try and find a solution, but haven't found anything that has worked just right. A few posts I've found suggest removing the signature, pasting the body and then rebuilding the signature into the email--not really the approach i'd like.
Here is my code:
Sub CreateEmail()
Dim Notes As Object
Dim Maildb As Object
Dim objNotesDocument As Object
Dim objNotesField As Object
Set Notes = CreateObject("Notes.NotesSession")
Set Maildb = Notes.GETDATABASE("", "")
Maildb.OPENMAIL
Set objNotesDocument = Maildb.CREATEDOCUMENT
Subject = "Hey look at my email!!"
Set objNotesField = objNotesDocument.APPENDITEMVALUE("Subject", Subject)
Set objNotesField = objNotesDocument.APPENDITEMVALUE("SendTo", GetPrimaryEmail) 'calls a function to return the SendTo
Set objNotesField = objNotesDocument.APPENDITEMVALUE("Body", bodyInfo) 'calls a function to return the body contents.
Set workspace = CreateObject("Notes.NotesUIWorkspace")
Call workspace.EDITDOCUMENT(True, objNotesDocument)
AppActivate "Lotus Notes"
End Sub
Thanks in advance for any help!
A different approach to set the Body content is to open the new document in edit mode (like you do at the end of your code) and then set cursor to Body field and insert the text. Your code could look like this:
...
Set objNotesField = objNotesDocument.APPENDITEMVALUE("SendTo", GetPrimaryEmail) 'calls a function to return the SendTo
Set workspace = CreateObject("Notes.NotesUIWorkspace")
Call workspace.EDITDOCUMENT(True, objNotesDocument)
Set uidocument = workspace.CurrentDocument
Call uidocument.GotoField("Body")
Call uidocument.InsertText(bodyInfo) 'calls a function to return the body contents.
AppActivate "Lotus Notes"
Ok. I edited the question to see if you can see where I'm making a mistake.
This is the email. It will come in ALWAYS with this structure except, after Job1. there could be six more lines. But I'll deal with that later.
here is the email:
email subject: "Report Of Property" (not part of email body. Line 1 is Name:. There are NO empty lines between paragraphs.)
Name: geo.
Time started: 03:10PM 10-Aug-2014
Time ended: 03:11PM 10-Aug-2014
Property: 48 Atlantic Close
Complete Checklist: No
Call out: Yes
Sage nº: 16
Jobs done:
Job1.worked1 after this paragraghs there could be more(job2,job3,etc.) but I'll deal with that later
*Item: . Price: 0£. Stock:0£.
*Item: . Price: 0£. Stock:0£.
*Item: . Price: 0£. Stock:0£.
*Item: . Price: 0£. Stock:0£.
*Item: . Price: 0£. Stock:0£.
*Item: . Price: 0£. Stock:0£.
All the bold fields are the ones I need to import to an excel file.
Date to column A, name to column B, sage to column D , complete checklist to column F and jobs done to column G.
this is the VBA code you gave me and I tried to edit it like this:
Sub Application_NewMailEx(ByVal EntryIDCollection As String)
'Excel objects
Dim xlApp As Excel.Application
Dim xlWB As Excel.Workbook
Dim xlSheet As Excel.Worksheet
Dim id As Variant 'used to iterate the EntryIDCollection
Dim email As Outlook.MailItem 'represents each email item
Dim msgText As Variant 'Array used to iterate the "lines" in the email:
'Create an instance of Excel that we can use:
Set xlApp = CreateObject("Excel.Application")
For Each id In Split(EntryIDCollection, ",")
'Assign a mailItem variable to this email:
Set email = Application.Session.GetItemFromID(id)
'Add some logic to ensure you only process the right emails.
' you could use a defined subject and/or sender name, etc.
' MODIFY AS NEEDED
If email.Subject = "Report of Property" Then
'Ignore the HTML format, just use the "Body". Parsing HTML can be a pain
' in the a$$ and it is *probably* not needed here since you control the
' format of the email anyways.
'This example simply prints the entire email contents in an Excel sheet
'Add a new workbook
Set xlWB = xlApp.Workbooks.Add
Set xlSheet = xlWB.Worksheets(1)
Dim line As Variant
For Each line In Split(email.Body, vbCrLf)
If Left(line, 1) = "Name:" Then
xlSheet.Range("B6").Value = Trim(Mid(line, 6))
ElseIf Left(line, 2) = "Time started:" Then
xlSheet.Range("A6").Value = DateValue(Trim(Mid(line, 14)))
ElseIf Left(line, 7) = "Sage Nº:" Then
xlSheet.Range("D6").Value = Trim(Mid(line, 6))
ElseIf Left(line, 5) = "Complete Checklist:" Then
xlSheet.Range("F6").Value = Trim(Mid(line, 6))
ElseIf Left(line, 5) = "Job1" Then
xlSheet.Range("G6").Value = Trim(Mid(line, 6))
End If
Next
Else
End If
Next
End Sub
Yes, Outlook can process incoming emails and then you can use that data to do just about anything that VBA is capable of doing, such as putting the data in an Excel spreadsheet, writing out to a plain text file, etc. etc.
You can use the Application-level event procedure for NewMail, which is raised any time a new email item is received (I believe this ignores other item types such as calendar appointments, tasks, etc., for which you can use the NewMailEx event which processes all incoming items).
The NewMailEx event receives a comma-delimted string of Unique IDs associated with each mail item. Use simple Split function to convert that to an iterable array.
Then bind Excel to Outlook, create a new spreadsheet, and input whatever information you need. This example uses early-binding which will require a reference to the Excel library.
Sub Application_NewMailEx(ByVal EntryIDCollection As String)
'Excel objects
Dim xlApp as Excel.Application
Dim xlWB as Excel.Workbook
Dim xlSheet as Excel.Worksheet
MsgBox "Mail received!" '## DELETE THIS LINE ONCE YOU VERIFY THAT THE MACRO RUNS
Dim id as Variant 'used to iterate the EntryIDCollection
Dim email as Outlook.MailItem 'represents each email item
Dim msgText as Variant 'Array used to iterate the "lines" in the email:
'Create an instance of Excel that we can use:
Set xlApp = CreateObject("Excel.Application")
For each id in Split(EntryIDCollection, ",")
'Assign a mailItem variable to this email:
Set email = Application.Session.GetItemFromID(id)
'Add some logic to ensure you only process the right emails.
' you could use a defined subject and/or sender name, etc.
' MODIFY AS NEEDED
If email.Subject = "PROCESS THIS EMAIL" Then
'Ignore the HTML format, just use the "Body". Parsing HTML can be a pain
' in the a$$ and it is *probably* not needed here since you control the
' format of the email anyways.
'This example simply prints the entire email contents in an Excel sheet
'Add a new workbook
Set xlWb = xlApp.Workbooks.Add
Set xlSheet = xlWB.Worksheets(1)
'Put the email contents in the worksheet:
xlSheet.Range("A1").Value = email.Body
'Or you could do something like this, MODIFY AS NEEDED:
'dim line as Variant
'For each line in Split(email.Body, vbCrLf)
' If Left(line, 5) = "Name:" Then
' xlSheet.Range("B1").Value = Trim(Mid(line, 6))
' ElseIf Left(line, 13) = "Time started:" Then
' xlSheet.Range("C1").Value = DateValue(Trim(Mid(line, 14)))
' EndIf
'Next
Else:
' do nothing for emails that don't need to be processed
End If
xlApp.Visible = True
Next
End Sub
Realistically, pulling all this various info from an email there are many different ways that it could be done, I show you a simple example above, some more reliable (and more complicated than others).
Do you want to use Regular Expressions?
Or can you get by using simple string functions like Left, Mid,
etc.
Outlook also supports using a WordEditor and Word's rich text object model to parse by paragraph, etc...
Specific implementations of any of these or other methods seems outside scope of this question, which I gather is: "how to export text from an Outlook email to an Excel spreadhseet?
This should be enough to get you started I hope :)
If you have specific trouble implementing it, parsing the needed information, etc., I would encourage you to ask additional (new) questions but not before browsing the Outlook Object Model Reference:
http://msdn.microsoft.com/en-us/library/office/ff870566(v=office.14).aspx
And the similar reference for Excel:
http://msdn.microsoft.com/en-us/library/office/ff846392(v=office.14).aspx
NOTE This code provided is not tested and may contain some typos, misplaced parentheses. I encourage you to always declare variables and use Option Explicit to force variable declaration in your modules.
NOTE This example will create a new file for each email, probably not desired. In order to tap an existing file, you need to know it's location and be able to open it. Instead of Set xlWb = xlApp.Workbooks.Add, do `Set xlWB = xlApp.Workbooks.Open("c:\path\to\file.xlsx"). Using an existing file creates a host of additional "problems" for someone who isn't versed in VBA, such as "how do I find the next empty row in a worksheet" (Asked & answered here dozens of times), etc.
So I would start with this, and obviously if you cannot "get it", when you get stuck, break it down in to small chunks or steps in the process. Try and figure out how to do each step, before trying to put them all together.
Good luck!
(I should have better things to do on a Saturday night, but I have a 2-year old and the wife's out of town...)
I'm trying to write a Excel VBA code which allows me to automatically create and send a Lotus Notes Email. The problem I face is the difficulty to create a rich text Email, so I think it would be easier to open a draft email, with a marker text which will be replaced (for exameple PASTE EXCEL CELLS HERE) and then just:
.GotoField ("Body")
.FINDSTRING "PASTE EXCEL CELLS HERE"'
and replace.
Any help on how to open a certain draft email? Perhabs something as .CreateDocument property?
Thank you very much!
Others have proposed interesting concepts, but the most robust approach would be to use HTML in a MIME enitity that is mapped to the Body Rich Text item. Using NotesSession..Convertmime = False you can build the body as HTML and then send the message. Based on the post by Joseph Hoetzl here, the LotusScript equivalent is this:
Sub Initialize()
Dim s As New NotesSession
Dim db As NotesDatabase
Dim stime as Single
Dim alog As New NotesLog("debug")
Call alog.OpenAgentLog()
stime = Timer
On Error GoTo eh
Dim doc As NotesDocument
Dim body As NotesMIMEEntity
Dim header As NotesMIMEHeader
Dim stream As NotesStream
Dim child As NotesMIMEEntity
Dim sendTo As String
Dim subject As String
s.Convertmime = False
sendto = s.Effectiveusername
subject = "Demo Message"
Set db= s.Currentdatabase
Set doc=db.Createdocument()
Set stream = s.CreateStream
Set body = doc.CreateMIMEEntity
Set header = body.CreateHeader({MIME-Version})
Call header.SetHeaderVal("1.0")
Set header = body.CreateHeader("Content-Type")
Call header.SetHeaderValAndParams({multipart/alternative;boundary="=NextPart_="})
'Add the to field
Set header = body.CreateHeader("To")
Call header.SetHeaderVal(SendTo)
'Add Subject Line
Set header = body.CreateHeader("Subject")
Call header.SetHeaderVal(subject)
'Add the body of the message
Set child = body.CreateChildEntity
Call stream.WriteText("<h1>Demo HTML Message</h1>")
Call stream.WriteText(|<table colspacing="0" colpadding="0" border="none">|)
Call stream.WriteText(|<tr><td>cell 1.1</td><td>cell 1.2</td><td>cell 1.3</td></tr>|)
Call stream.WriteText(|<tr><td>cell 2.1</td><td>cell 2.2</td><td>cell 2.3</td></tr>|)
Call stream.WriteText(|<tr><td>cell 3.1</td><td>cell 3.2</td><td>cell 3.3</td></tr>|)
Call stream.WriteText(|</table>|)
Call stream.WriteText(|<div class="headerlogo">|)
Call stream.WriteText(|<!-- ...some more HTML -->|)
Call child.setContentFromText(stream, {text/html;charset="iso-8859-1"}, ENC_NONE)
Call stream.Truncate 'Not sure if I need this
Call stream.Close
Call doc.CloseMIMEEntities(True)
Call doc.replaceItemValue("Form", "Memo")
Call doc.Send(False, sendTo)
es:
Exit Sub
eh:
Dim emsg$
emsg = Error & " at " & Erl & " in " & s.Currentagent.name
Call alog.logError(Err, emsg)
MsgBox "ERROR: " & Err & ": " & emsg
Resume es
End Sub
All of this should convert fairly easily to VBA in Excel. You can, of course be as complex as you want with your HTML.
The word "draft" is probably inappropriate here, but then again so is the word "template". Both have specific meanings in Lotus Notes that aren't what you really want. Users can delete drafts, and templates are an entirely different thing. So let's just call it a boilerplate message.
I would recomemnd creating a special mail database (NSF file) on the Domino server, which will just serve as a repository for your boilerplate. You can create a folder in that mail database called "Boilerplates". Using Domino Designer you can modify that folder's design so that the Subject column is the first column in the view, and it is sorted.
Once you have that done and you have created some boilerplates and saved them in the folder, you can use VBA to do a NotesSession.getDatabase call, NotesDatabase.getView call (this is used for folders as well as views), and then use NotesView.getDocumentByKey() to retrieve a specific boilerplate by the Subject you have assigned to it. Note that you do not have to copy this document to the user's mail database in order to mail it.
What you want to do is non-trivial, but you mention a draft email so there may be a workaround.
In your mail settings you can specify a signature file which can be an external html file on disk. So modify the signature file, then create your new mail which will then populate the body field the way you want it.
For sample code, within the memo form there should be a button to specify what signature file to use. You can use that as the baseline.
Rich text is not that hard to work with, but you need to look at the Domino Designer help, especially the classes NotesRichTextItem and NotesRichTextStyle. You also need to understand the DOM (Domino Object Model). Then you can create your mail content programatically.
Otherwise I think Richard's solution is the best, that you have a separate database where you get the rich text snippets, and use the AppendRTItem method of the NotesRichText class to put it into your email.
Thank you all guys!
But I found exactly what I wanted, without having to recreate the whole Email everytime:
Sub EditSelectedMail()
Dim NSession As Object
Dim NDatabase As Object
Dim NUIWorkspace As Object
Dim NUIdoc As Object
Set NSession = CreateObject("Notes.NotesSession")
Set NUIWorkspace = CreateObject("Notes.NotesUIWorkspace")
Set NDatabase = NSession.GetDatabase("", "")
If Not NDatabase.IsOpen Then NDatabase.OPENMAIL
Set NUIdoc = NUIWorkspace.EDITDOCUMENT(True)
With NUIdoc
'Find the marker text in the Body item
.GotoField ("Body")
.FINDSTRING "**PASTE EXCEL CELLS HERE**"
'Copy Excel cells to clipboard
Sheets("Sheet1").Range("A1:E6").Copy
'Create a temporary Word Document
Set WordApp = CreateObject("Word.Application")
WordApp.Visible = False
WordApp.Documents.Add
'Paste into Word document and copy to clipboard
With WordApp.Selection
.PasteSpecial DataType:=10
'Enum WdPasteDataType: 10 = HTML; 2 = Text; 1 = RTF
.WholeStory
.Copy
End With
'Paste from clipboard (Word) to Lotus Notes document
.Paste
Application.CutCopyMode = False
'WordApp.Quit SaveChanges:=False
Set WordApp = Nothing
End With
End Sub
I just select my "template", copy it into a new message, and then run the macro.