I've seen this asked a lot and I haven't seen a clear and comprehensive answer, so I thought I should post it here. I hope it can be added to the FAQ.
The code sample below shows how to write LotusScript code that makes changes to a rich text field in a document that the user is editing, and displays those changes immediately on-screen, without saving the changes. This also works if you need to repeat other operations that only occur when a document is opened, e.g. evaluating section editor formulas and computed subform formulas.
Of course, you can make some rich text changes using the NotesUIDocument methods, but it's not possible to do important things like add paragraph breaks, table rows and file attachments in that way.
Points to note:
- You can also use this for other applications that require the document be opened and closed but not saved, including repainting pass-thru HTML in the Notes client or recalculating subform formulas.
- A drawback to this approach is that it actually does close and reopen the document window, so any form event code in the Queryclose, Queryopen, Postopen, etc will trigger, and the cursor will end up in the default field. Workarounds are of course possible; it's just a pain.
- If you're already editing a document and there is a rich text field on the form, the rich text field already exists in Notes' memory, even if it's empty. You should not use CreateRichTextItem or New NotesRichTextItem to create another item with the same name. Instead, locate the already-existing item.
- The existing rich text field is not loaded into the back-end document automatically when you get NotesUIDocument.Document. You must explicitly request it by calling NotesUIDocument.Refresh(True). This, however, will also trigger all your computed fields, input translation and validation functions. The input validations are especially a problem because they'll put up a validation failure dialog, which is inappropriate when you're not actually saving the document yet. The solution to this is to use @If(@IsDocBeingRecalculated; @Success; ...) in your input translations. You should be doing this anyway so that the user doesn't get error messages when they press F9 or if you have a keyword field that's set to refresh on keyword change.
Here's the code, which should work in Notes 5.0.2 and higher:
Dim wksp As New NotesUIWorkspace
Dim session As New NotesSession
Dim uidoc As NotesUIDocument, uidocNew As NotesUIDocument
Dim doc As NotesDocument
Dim rti As NotesRichTextItem
Dim strFieldname As String
Set uidoc = wksp.CurrentDocument
uidoc.Refresh True ' do this if the rich text field is editable, to get the current contents in case user has modified them.
Set doc = uidoc.Document ' get the back-end document for the document open on screen.
strFieldname = uidoc.CurrentField ' remember the current field if any
Set rti = doc.GetFirstItem("fieldname") ' insert your fieldname here, generally "Body"
' Make your rich text changes here, for instance:
Call rti.AddNewLine(1, True)
Call rti.AppendText(Now & ": log entry.")
If session.NotesBuildVersion >= 190 Then
rti.Update ' ND6 and later
Call doc.ComputeWithForm(True, False) ' caution, as this may erase some field values if you have @Db functions in formulas.
doc.SaveOptions = "0" ' make it possible to close the document without a "do you want to save" prompt. If this is a mail-in doc you may need to set MailOptions="0" also to avoid being prompted.
Set uidocNew = wksp.EditDocument(True, doc, , , , True)
If strFieldname <> "" Then uidocNew.GotoField(strFieldname) ' return focus to field that was current before.
Note: this will cause Queryclose, Queryopen, Postopen (and so on) form events to trigger. Also, uidoc.Refresh will execute computed field formulas and input validations, so you should write the validation formulas to not return @Failure unless @IsDocBeingSaved | @IsDocBeingSent is true.