Tip: How to update rich text in a document that's open and redisplay it without saving

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

Else

Call doc.ComputeWithForm(True, False) ' caution, as this may erase some field values if you have @Db functions in formulas.

End If

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.

Call uidoc.Close(True)

Set uidocNew = wksp.EditDocument(True, doc, , , , True)

Delete uidoc

uidocNew.Document.RemoveItem(“SaveOptions”)

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.

Subject: BUG!

Bonjour, André!

Nice tip, but I’m having a LOT of problems getting it to work with something else.

First of all, in 6.5.5, “uidoc.Close(true)” causes an NSD. I dropped the “true”.

Your script works well on it’s own. I use it to select a template, then grab info from it, put it into various fields and attach the template to a rich-text field. The document doesn’t get saved. All is well! :slight_smile:

So, now I have an editable document with some info from the template I selected. I want to add more info to the document, and click a “Submit” button. This button uses LS to get info from the doc, change authors, change workflow info, send an e-mail and save & close. (All of it pretty simple code, and pretty much irrelevant).

However, the changes I made after attaching the template are lost! =8O The template is attached, as well as the template information, but not all the other stuff I added.

Can you just try it out, and see if there’s something extra I’m missing in my “Submit” button? Here are the steps:

  1. open a blank, new doc,

  2. run your code to modify the RT field,

  3. manually modify the values in a couple of fields (could be editable, lists, whatever),

  4. run a LS “save & close” button (i.e. NotesUIDocument.Save & .Close).

  5. open the document again, and see if your changes (in #3) were saved.

    Did it work? If you could just “test drive” it and let me know, that would be greatly appreciated. If it doesn’t work for you, either, then I know I’m not completely insane. (Just partially!). :wink:

Thanks, in advance!

Steve in NYC

“Madness takes it’s toll. Please have exact change.”

Subject: Tip: How to update rich text in a document that’s open and redisplay it without saving

Andre saves the day again! Thank you for the useful tip - you helped me today!

Subject: RE: Tip: How to update rich text in a document that’s open and redisplay it without saving

this tips help me a lot…but the problem is, when i try to change to different selection, the previous attachment is not deleted but it goes under the form…

can u check if my code is wrong??

Sub Click(Source As Button)

On Error Goto ErrHandlr



Dim session As New NotesSession

Dim ws As New NotesUIWorkspace

Dim uidoc As NotesUIDocument

Dim uidocNew As NotesUIDocument

Dim doc As NotesDocument

Dim db As NotesDatabase 

Dim tserver As String

Dim dbfilename As String

Dim viewname As String

Dim columnNo As Integer

Dim lkpView As NotesView

Dim sessionDoc As NotesDocument

Dim key  As String

Dim newkey  As String



Dim rti As NotesRichTextItem

Dim attach_file As String

Dim rtitemB As NotesRichTextItem





Set db = session.CurrentDatabase

Set uidoc = ws.CurrentDocument

Set doc = uidoc.Document





'>>>>>>>>>>>>>>>>>>>>>>>

Set uidoc = ws.CurrentDocument

uidoc.Refresh True

Set doc = uidoc.Document  ' get the back-end document for the document open on screen.

attach_file = uidoc.CurrentField' remember the current field if any

'>>>>>>>>>>try baru



If uidoc.EditMode Then

	

	sReturnvalue = getdbserverpath(db,"Training Records Management")	'lookup server and db

	tserver = Strleft(sReturnvalue,"~") 	'lookup server and db

	dbfilename = Replace(Strright(sReturnvalue,"~"), "\", "/") 	'lookup server and db

	

	Set svrName = session.CreateName(tserver)

	

	cnLookup = Arrayunique(DbColumn(tserver, dbfilename, "lsvCourseSession", 0))

	cnOther = Arrayappend(cnLookup, "-Others-") 

	

	cnPrompt = ws.Prompt(PROMPT_OKCANCELLIST, "Course Name", "Select course name...",  " ", Arrayunique( cnOther))

	

	key = cnPrompt 

	newkey =cnPrompt2 

	Set lkpView = db.GetView("lsvCourseSession")

	Set sessionDoc = lkpView.GetDocumentByKey( key, True)

	

	' to check sessiondoc exist

	If Not (sessionDoc Is Nothing)  Then

		doc.CourseName = cnPrompt

		doc.TypeOfTraining = sessionDoc.TypeOfTraining

		doc.AppCat = sessionDoc.AppCat 

		doc.Objectives=sessionDoc.Objectives

		doc.CourseLocation = sessionDoc.CourseLocation 

		doc.Facilitator=sessionDoc.Facilitator

		doc.StartDate =sessionDoc.StartDate 

		doc.EndDate= sessionDoc.EndDate

		doc.Duration = sessionDoc.Duration

		doc.attach_file = sessionDoc.attach_file		

		doc.Act_CF =  sessionDoc.Act_CF

		doc.Refreshment	= sessionDoc.Refreshment

		doc.nFees= sessionDoc.nFees

		doc.TotalCFees= sessionDoc.TotalCFees

		doc.Payment= sessionDoc.Payment

		doc.Payable = sessionDoc.Payable

		

		

		'************* attachment section********

		Set rti = New NotesRichTextItem(doc,"attach_file")

		Set rti = doc.GetFirstItem("attach_file") ' insert your fieldname here, generally "Body"

		Set rtitemB = sessionDoc.GetFirstItem( "attach_file" )

		'************* attachment section********

		'>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>test baru

		' Make your rich text changes here, for instance:

		'Call rti.AddNewLine(1, True)

		Call rti.AppendRTItem(rtitemB)

		If session.NotesBuildVersion >= 190 Then

			rti.Update ' ND6 and later

		Else

			Call doc.ComputeWithForm(True, False) ' caution, as this may erase some field values if you have @Db functions in formulas.

		End If

		

		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.

		Call uidoc.Close(True)

		Set uidocNew = ws.EditDocument(True, doc, , , , True)

		Delete uidoc

		uidocNew.Document.RemoveItem("SaveOptions")

		If attach_file <> "" Then uidocNew.GotoField(attach_file) ' return focus to field that was current before.

	End If	

	

End If			



If (cnPrompt  ="-Others-") Then

	cnPrompt2  = ws.Prompt(PROMPT_OkCancelEdit, "Course Name",  "Please enter new course name", " ")

	doc.CourseName= cnPrompt2

	doc.SessionID="NA" 

	doc.TypeOfTraining = "In-house training"

	doc.AppCat = "No"

	doc.Objectives=""

	doc.CourseLocation = ""

	doc.Facilitator=""

	doc.StartDate =""

	doc.EndDate= ""

	doc.Duration = ""

	doc.SpecificTime = ""

	doc.attach_file=""

	attach_file_old=""

	doc.Act_CF =  ""

	doc.nFees= ""

	doc.TotalCFees= ""

	doc.Payment= "Cash"

	doc.Payable = ""

	

End If

		

Exit Sub





Exit Sub

ErrHandlr :

If Err = 4411 Then Exit Sub

Msgbox "ERROR : " & Err & " - " & Error & " at line " & Cstr(Erl),16,"Select Course Name Button"

Continue = False

Exit Sub

End Sub

Subject: Dynamic HTML table with links that calls a @Funcs or LS code (Sample DB)

Dynamic HTML table with links that calls a @Funcs or LS code

Sample Database

http://www.intertrust.ru/Site/ITForum.nsf/0/f9bc0eb50274d89cc32570540045f802/$FILE/PaulSukhodolskiy.zip

Subject: Tip: How to update rich text in a document that’s open and redisplay it without saving

Can the same be done in formula language?

Subject: TY!!! How to update rich text in a document that’s open and redisplay it without saving

Thank you! Thank you! Thank you! — I have found this code particularly useful.

Subject: Tip: How to update rich text in a document that’s open and redisplay it without saving

Re: rich text field with embedded objects; chg "Display As"How can I change the value for Display As on embed object from “Icon” to “RichText” using code?

Here is a link to the question I posted on Notes.net It explains my question more fully:

http://www-10.lotus.com/ldd/nd6forum.nsf/0/56add41ec84d1482852571530041ea5d?OpenDocument

Subject: RE: Tip: How to update rich text in a document that’s open and redisplay it without saving

All you said works well for saved documents. But i wanted to attach a fixed named file (in this particular case an scanned image) without saving the document because the user could change his mind and don´t want to save the document. So i didn’t want to save the doc and have to delete it later.Here is my solution… i hope it´ll be useful to somebody

@ Action:

@Command([ToolsRunMacro]; “(ScanImage)”);

@Command([ToolsRunMacro]; “(InsertImage)”)

Agent1: ScanImage written in LS scans image. Writes the filename (and filepath) in a computed for display hidden field named ImageFileName

Agent2: InsertImage

@Command([EditGotoField]; “Imagen”);

@Command([EditInsertFileAttachment]; ImageFileName);

Imagen is the rich text field that will have the attachment.

Gets filepath and filename from the computed for display field. As it is not written to disk when the document is saved there is no problem of non desirable data.

I frecuently use Computed for Display hidden fields as parameters when need to make interact different kinds of agents.

Hope this is useful for somebody

Subject: RE: Tip: How to update rich text in a document that’s open and redisplay it without saving

I got fooled here as well.The original code does NOT save the background document and it works a treat!

Subject: Tip: How to update rich text in a document that’s open and redisplay it without saving

Just wanted to thank you for sharing your code. It is a fantastic tip. It accomplished exactly what I was trying to resolve i.e., adding an attachment to a doc that is open (current doc). After reading the forums for two days, I fortunately ran into your post. Many, Many thanks!!!

Subject: Tip: How to update rich text in a document that’s open and redisplay it without saving

I was trying to add an attachment in computed richtext field through a button and your code did it for me. I did some small modification according to my requirement. However this is an excellent code.

Dim ss As New NotesSession

Dim ws As New NotesUIWorkspace

Dim db As NotesDatabase

Dim uidoc As NotesUIDocument

Dim uidocNew As NotesUIDocument

Dim doc As NotesDocument

Dim rtitem As NotesRichTextItem

Dim object As NotesEmbeddedObject

Set db = ss.CurrentDatabase

Set uidoc = ws.CurrentDocument

Set doc = uidoc.Document

uidoc.EditMode = True

FileName = ws.OpenFileDialog(Talse, “Authorised Signatures Specimen”)

Set rtitem = doc.GetFirstItem(“Signature_Approved”)

Set object = rtitem.EmbedObject( EMBED_ATTACHMENT, “”, FileName(0))

rtitem.Update

doc.SignatureModified = “Yes”

doc.SaveOptions = “0”

uidoc.Close True

Set uidocNew = ws.EditDocument(True, doc)

Delete uidoc

uidocNew.Document.RemoveItem(“SaveOptions”)

Thank you all…

Dinesh.

Subject: RE: Tip: How to update rich text in a document that’s open and redisplay it without saving

But your code is not working when the form is new, it works only if the form is already saved in the DB. I get an Error:Cannot locate Default form when the form is new.

Subject: re: How to update rich text (Save Conflict message)

In my case, I have code that saves my uidoc while it’s open. My code is used to send an email message from a previously unsaved document, so I’m forcing the save to make sure the link I send in the email actually exists. Then I’m writing some details to a history section that’s displayed via pass thru HTML. So, I’m using this trick to re-paint the HTML.

Call uidoc.Close(True) ← when I include the “True” I get a system generated message that says, “Another copy of this document was saved while you were editing it. Save your changes also as a Save Conflict document?”

Call uidoc.Close() ← when I remove “True” I don’t get that message

According to a previous post by AJP, using “True” causes the doc to become null. This sort of makes sense then why I’m getting the conflict message while using “True” and don’t get it without “True.”

Thanks, Paul.

Subject: Tip: How to update rich text in a document that’s open and redisplay it without saving

Thanks much for your help. It did shed a little new light. Here’s what I came up with, after merging our code (in case anyone else is running into similar problems). By the way, I do specify a target frame for the document, so I don’t know if that may make a difference.

Sub Initialize

Dim session As New NotesSession

Dim workspace As New NotesUIWorkspace

Dim db As NotesDatabase

Set db = session.CurrentDatabase

Dim uidoc As NotesUIDocument

Dim uidocNew As NotesUIDocument

Dim doc As NotesDocument

Set uidoc = workspace.CurrentDocument

uidoc.Refresh True

Set doc = uidoc.Document



Dim rti As NotesRichTextItem

Set rti = doc.GetFirstItem("RevHist")

Dim rtnav As NotesRichTextNavigator

Set rtnav = rti.CreateNavigator

. . .

RT field manipulation

. . .

If session.NotesBuildVersion >= 190 Then

	rti.Update				'ND6 only

Else

	Call doc.ComputeWithForm(True, False)

End If



docUNID = doc.UniversalID



doc.SaveOptions = "0"			'close document without save prompt

Call doc.Save(True, True)		'get rid of old doc

Call uidoc.Close(True)			'close and reopen doc so changes appear on table

Dim docNew As NotesDocument

Set docNew = db.GetDocumentByUNID(docUNID)

Set uidocNew = workspace.EditDocument(True, docNew, False)

uidocNew.Document.RemoveItem("SaveOptions")

uidocNew.GotoField("RevHist")

End Sub

Subject: Tip: How to update rich text in a document that’s open and redisplay it without saving

Hi, Tried the code, and it seems to work fine except for what I want it to do, which is change the color the field.

Is there a way to change the color of the field (the whole field is fine) in the front end?

Subject: Tip: How to update rich text in a document that’s open and redisplay it without saving

Best tip on this site!Thanks.

Subject: Thank you! But what are possible workarounds for the default cursor position?

Thank you so much, this post is extremely useful and I have been using the code without a problem to generate a dynamic HTML table in the client.

However, I’m trying to figure out some good workarounds for the default cursor position when the document is reopened. The problem is that, since my table is entirely dynamic, I don’t have any notes fields I can use in an @Command([EditGotoField]).

I was trying to use the javascript .focus() method with some of my dynamically generated fields, but the focus() method doesn’t seem to work in the notes client.

I could put a notes field at the very end of the dynamic table and set the focus on that, but that isn’t an ideal solution either, since the table might be very long, and the user would then have to scroll up.

Am I trying to do the impossible? :stuck_out_tongue:

Subject: RE: Thank you! But what are possible workarounds for the default cursor position?

Yes, you can.

  1. Store current field name : strFldName = NotesuiDoc.CurrentField

  2. your operation here… close reopen

  3. NotesuiDoc.gotofield(strFldName)

hope this will help u…

Subject: Code correction for 6.5.4

The Original Code fails on 6.5.4 with ’ Object Expected’ when trying to reopen the uidoc

doc.SaveOptions = “0” ’ make it possible to close the document without a “do you want to save” prompt.

Call uidoc.Close(True) '<-- THIS CAUSES doc TO BECOME NULL

Set uidocNew = wksp.EditDocument(True, doc, , , , True) '<---- THEN THIS FAILS WITH ‘Object expected’

Delete uidoc

The following code works. Remove the (True) from the Call UiDoc.Close

doc.SaveOptions = “0” ’ make it possible to close the document without a “do you want to save” prompt.

Call uidoc.Close ’ ← REMOVED THE (TRUE) PARAMETER

Set uidocNew = wksp.EditDocument(True, doc, , , , True)

Delete uidoc

That said brillant code tip.

AJP