ShowTable of Contents
IBM® Lotus® Notes® rich text fields are better for formatted text, large amounts of text, or for embedding or attaching objects. As important as this field type is, it has some issues that need special handling, including copying from one rich text field to another, especially if it contains attachments, validation, and hide/when formulas.
There are straightforward ways to do this; however, many times they do not work as expected, and that's why this article presents some of the best practices for rich text fields to help developers work with them more easily. In the example shown in figure 1 the Body field is a rich text field.
Figure 1. Rich text field example
Copying content from one rich text field to another
This is also known as inheritance and can be done in the same document or from one document to another. Here are the steps for copying the content from one rich text field to another:
- Set the richtext field rtitem. To access an existing NotesRichTextItem object, use the method in NotesDocument. Because NotesRichTextItem inherits from NotesItem, all the NotesItem properties and methods can also be used on a NotesRichTextItem.
- Define a new temporary richtext field "TMP_Attachments_dsp".
- Copy the content from the original rtitem "Attachments" to the temporary richtext field "TMP_Attachments_dsp".
- Copy the temporary richtext field "TMP_Attachments_dsp" to TargetFieldName "Attachments_dsp". The Copyitem method, Given an item, copies it into the current document and optionally assigns the copied item a new name.
- Remove the temporary richtext field "TMP_Attachments_dsp".
- Set a new richtext field TempItem with the TargetFieldName "Attachments_dsp" and update to Processes all pending operations on the rich text item.
- Use the ComputeWithForm method to confirm that the data you've placed in a document meets a form's requirements; also, refresh all fields, to make sure all changes are reflected.
Listing 1 shows sample code for copying the content from one rich text field to another.
Listing 1. Sample code for copying content
Dim flag As Boolean
flag = False
Dim rtitem As NotesRichTextItem
Set rtitem = doc.GetFirstItem( "Attachments" )
If Not ( rtitem Is Nothing) Then
flag = True
tmp = "TMP_"
Dim TargetFieldName As String
TargetFieldName = "Attachments_dsp"
Dim TmpItem As New NotesRichTextItem( doc, tmp + TargetFieldName )
Call TmpItem.AppendRTItem( rtitem )
Call doc.RemoveItem( TargetFieldName )
Call doc.CopyItem( TmpItem, TargetFieldName )
Call doc.RemoveItem( tmp + TargetFieldName )
Call doc.RemoveItem("Attachments" )
Dim TempItem As NotesRichTextItem
Set TempItem = doc.getFirstItem("Attachments_dsp")
Call doc.ComputeWithForm( False, False )
Validation types for rich text fields
There are three validation methods for rich text fields:
- First method. Validates a text field in which any text (including a single-space character) is an acceptable input.
- Second method. Validates a field in which at least some non-space text is required.
- Third method. Validates a field that may contain no text, but may contain an attachment, embedded object, or link.
The complexity, however, lies in checking for the three types all together, that is, validating whether the rich text field has text, formatted text, or any attachments.
Listing 2 shows some sample code for the validation.
Listing 2. Code for validation
dim ws as New NotesUIWorkspace
dim rtn As NotesRichTextNavigator
dim rt As Variant
dim fieldname as string
dim uidoc as NotesUIDocument
dim doc as NotesDocument
set uidoc = ws.CurrentDocument
set doc = uidoc.Document
fieldname = "RichText1"
Set rt = doc.GetFirstItem(fieldname)
If Not rt Is Nothing Then
Set rtn = rt.CreateNavigator
Function validate(uidoc As NotesUIDocument, rtn As NotesRichTextNavigator, fieldname As String) As Integer
validate = False
If (rtn.FindFirstElement(RTELEM_TYPE_DOCLINK) Or _
rtn.FindFirstElement(RTELEM_TYPE_FILEATTACHMENT) Or _
rtn.FindFirstElement(RTELEM_TYPE_OLE)) Or _
rtn.FindFirstElement(RTELEM_TYPE_SECTION) Or _
rtn.FindFirstElement(RTELEM_TYPE_TABLE) Or _
rtn.FindFirstElement(RTELEM_TYPE_TABLECELL) Or _
rtn.FindFirstElement(RTELEM_TYPE_TEXTPARAGRAPH) Or _
validate = True
If Not emptyRTField(uidoc, fieldname) Then validate = True
Function emptyRTField(uidoc As NotesUIDocument, fieldname As String) As Integer
dim item As NotesItem
dim doc As NotesDocument
dim length As Long
emptyRTField = True
Set doc= uidoc.Document
Set item = doc.GetFirstItem(fieldname)
length = item.ValueLength
If length > 200 Then
emptyRTField = False
Let's now discuss some common issues.
Several problems have been reported regarding the hide/when formula for rich text fields as documented in the IBM Support Technote #1084873, “'Hide When' formulas do not work correctly with Rich Text Fields.”
Sometimes the hide/when formula for rich text fields works by adding a space before that rich text field, but the most efficient way to avoid any problems is to put the rich text field in a subform, and then use a Computed Subform formula to include or not include the subform, based on whether the hiding conditions are met.
Another problem with the rich text fields is that Notes views cannot directly display a Rich Text field. However, you can create a formula that extracts the text content of the Rich Text field to store that text in a hidden field that is defined as a simple Text field. Then, within the view you wish to create, you would define a column that displays the hidden field instead of the Rich Text field.
You can do this by using an @ function called @Abstract with the TextOnly command:
Figure 2. HiddenUserField
- Create the hidden text field on the form that you want to display in your view. In our example, let's call this field HiddenUserField, which should be defined as a "Computed when composed" field (see figure 2).
2. Within the "Value" definition of this field, enter the following formula, using the @Abstract function:
@Abstract( [TextOnly] ; 64000 ; "" ; "$Body" )
Now, when the $Body field is created or changed within the form, the text contained within that field will be extracted and placed into the HiddenUserField. If you subsequently create a Notes and/or IBM Lotus Domino® view, you can create a column that displays the HiddenUserField, and the contents will be made available within the view.
This technique works for every newly created or changed $Body field within the form. However, for older documents that have not been updated, the value of HiddenUserField will remain uncomputed until you refresh the values of the $Body field within the document.
Do this manually by opening each document in edit mode and pressing F9 or by writing an agent that goes through the database performing an @Command([RefreshHideFormulas] ) command for the form.
Updating rich text in an open document
Another common scenario that needs special handling is updating rich text in a document that's open and then re-displaying it without saving.
The code sample in listing 3 shows how to make changes to a rich text field in a document that a user is editing and display those changes immediately on-screen, without saving the changes. This also works if you need to repeat other operations that occur only when a document is opened, for example, when evaluating section editor formulas and computed subform formulas.
Listing 3. Code for updating rich text in open document
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")
' 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) ' This may erase some field values if you have @Db functions in formulas.
doc.SaveOptions = "0" ' In order 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)
The GotoField method returns focus to the field that was current previously, which will cause Queryclose, Queryopen, Postopen (and so on) form events to trigger.
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.
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 backend document automatically when you get NotesUIDocument.Document. You must explicitly request it by calling NotesUIDocument.Refresh(True).
Note, however, that this will also trigger all your computed fields, input translation, and validation functions. The input validations are especially problematic because they display a validation failure dialog box, which is inappropriate when you're not yet actually saving the document.
The solution is to use @If(@IsDocBeingRecalculated; @Success; ...) in your input translations. You should be doing this anyway so that users do not get error messages when they press F9 or if you have a keyword field that's set to refresh on keyword change.
Also, uidoc.Refresh will execute computed field formulas and input validations, so you should write the validation formulas not to return @Failure, unless @IsDocBeingSaved | @IsDocBeingSent is true.
Notes rich text fields are important and warrant special techniques that should be used to accomplish functionalities like copying content from one rich text field to another, validation, and updating rich text in an open document. There are also some common issues that need workarounds, like hide/when formulas and displaying the value of rich text fields in views.
Tell us what you think
Please visit this link to take a one-question survey about this article:
developerWorks® Lotus Notes and Domino product page:
IBM Lotus Notes/Domino 8.5 Forum (includes Lotus Notes Traveler):
About the author
Menat Allah Abdel-Aziz is an IT Specialist at IBM's Cairo, Egypt Lab, working for IBM since 2005 as a senior Notes/Domino Developer and Technical Lead. Her areas of expertise include Notes development, maintenance, support, and administration. She is a Certified Professional and Advanced Developer for Lotus Notes/Domino and holds a Bachelor's degree in Computer Science from Ain Shams University, Cairo, Egypt. You can reach her at MENATA@eg.ibm.com.