Using Xpages, you can do many neat things in Notes. But I am still doing all my development in classic Notes, despite being on Notes/Domino 8.5.2. The reason is simple. Memory. There is just not enough memory to run the standard client in our Citrix environment, so all users are using the basic client. And Xpages is not working in the basic client.
So how do I solve issues like multiple documents tied to a main document, being displayed inline in the main document? Well, I solved this a long time ago by using a rich text field and building the document list on the fly. I am sure many other Notes developers use this technique. I know it was discussed in a session at Lotusphere several years ago, perhaps as long ago as 7-8 years ago. So this is of course not anything I came up with myself.
In this post I just want to share how I am using this, and perhaps this can help someone.
The database (download it here) is very simple. It contains three (3) forms and two (2) views. In addition I have some icon as image resources, but that is just to make things pretty.
Forms
The ‘MainDoc’ form is the main document, being displayed in the view ‘By Last Change’. It contains a few fields:
‘Title’ – a text field where the user can enter a title/description
‘Data’ – a rich text field where the rendered table rows will be displayed
‘ParentUNID’ – a hidden computed-when-composed field where the UniversalID of the document is stored
‘EntryCount’ – a hidden text field used to count the number of entries (to display in the views)
‘LastEntry’ and ‘LastEntryDate’ – Hidden text fields to keep track of the last person who edded an entry
The form also contains some regular action buttons (‘Save’, ‘Edit’, ‘Close’), as well as ‘Add entry…’, an action button with two lines of Formula language:
@Command([FileSave]);
@Command([Compose];”Entry”)
The QueryOpen event, which executes before the form is opened in the front-end and displayed to the user, contains some Lotusscript code. This event let us modify the document in the backend, which is where rich text fields can be updated. The code – which I will post at the end of this article – is very simple, it is just over 50 lines of code.
The ‘Entry’ form is where the entries are created. It is set to let fields inherit values from the document it is created from, and contains a couple of fields, some action buttons and some Lotusscript code as follows:
‘ParentUNID’ – editable, default value is “ParentUNID”, to inherit the value from MainDoc
‘Created’ and ‘Creator’ – computed-when-composed to store date/time and user name of creator
‘ItemDate’, ‘Issue’ and ‘Action’ – user data fields.
The ‘Entry’ form contains the following Lotusscript code:
(Declarations)
Dim callinguidoc As NotesUIDocument
Dim callingdoc As NotesDocument
Sub Initialize
Dim ws As New NotesUIWorkspace
Set callinguidoc = ws.CurrentDocument
If Not callinguidoc Is Nothing Then
Set callingdoc = callinguidoc.Document
End If
End Sub
Sub Terminate
Dim ws As New NotesUIWorkspace
If Not callingdoc Is Nothing Then
Call ws.EditDocument(False,callingdoc)
End If
If Not callinguidoc Is Nothing Then
Call callinguidoc.Close(True)
End If
End Sub
The code simply store the calling document (MainDoc) in a global variable when being opened/created, and then force a save and reopen of it when closing. This will trigger the QueryOpen event in the MainDoc document to rebuild the rich text content.
The action button ‘Delete’ contains some code to flag the current document for later deletion. I normally do not allow users to delete document in production databases, instead I use a field to indicate that the document should be ignored in views and lookups. Later I run a scheduled agent to actually delete the flagged documents.
Sub Click(Source As Button)
Dim ws As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
Dim session As New NotesSession
Dim doc As NotesDocument
Dim unid As String
Dim result As Integer
result = Msgbox("Are you sure you want to delete this document?",_
4+32,"Delete Document")
If result = 7 Then
Exit Sub
End If
Set uidoc = ws.CurrentDocument
unid = uidoc.Document.UniversalID
Call uidoc.Close(True)
Set doc = session.CurrentDatabase.GetDocumentByUNID(unid)
doc.flagDelete = "Yes"
Call doc.Save(True, False)
End Sub
The final and last form is a repeat of the Entry form, but formatted the way you want each entry/row to be displayed in the rich text field. I call the form ‘RecTemplate’:
Views
In addition to the forms, there are two views. ‘By Last Change’ is just a normal view to display the documents based on the ‘MainDoc’ form. The other one is the one used by the code. It is a hidden view called ‘(LookupEntry)’. The first column is sorted (to allow lookups using col.GetAllDocumentsByKey() and contains the ParentUNID field. I have the column categorized as well, but that is really not needed. I also added two additional columns to make it easier for you as developer to look at the content. The view selection is as follows:
SELECT Form=”Entry” & flag_Remove=””
Lotusscript for QueryOpen on ‘MainDoc’ form
Finally the code that makes it all happen. The code simply perform a lookup in the view (LookupEntry) to get all entries associated with the current document and updates a few fields (mainly for view display purposes). The code then loop through the entries and for each entry creates a template document and render it into the rich text field. That is basically it.
Sub Queryopen(Source As Notesuidocument, Mode As Integer, Isnewdoc As Variant, _
Continue As Variant)
Dim session As New NotesSession
Dim db As NotesDatabase
Dim view As NotesView
Dim col As NotesViewEntryCollection
Dim entry As NotesViewEntry
Dim entrydoc As NotesDocument
Dim thisdoc As NotesDocument
Dim datafield As NotesRichTextItem
Dim templatedata As NotesRichTextItem
Dim entrydata As NotesRichTextItem
Dim doclink As NotesRichTextItem
Dim template As NotesDocument
Dim parentunid As String
If source.IsNewDoc Then
Exit Sub ' Exit if new document, we do not have a ParentUNID or entries yet
End If
Set thisdoc = source.Document
Set datafield = New NotesRichTextItem(thisdoc,"Data")
parentunid = thisdoc.GetItemValue("ParentUNID")(0)
Set db = session.CurrentDatabase
Set view = db.GetView("(LookupEntry)")
Set col = view.GetAllEntriesByKey(parentunid,True)
Call thisdoc.ReplaceItemvalue("EntryCount",Cstr(col.Count))
Set entry = col.GetFirstEntry
If Not entry Is Nothing Then
Call thisdoc.ReplaceItemvalue("LastEntryBy", _
entry.Document.GetItemValue("Creator")(0))
Call thisdoc.ReplaceItemvalue("LastEntryDate", _
Format$(Cdat(entry.Document.GetItemValue("ItemDate")(0)),"mm/dd/yyyy"))
Call thisdoc.Save(True,True)
Else
Call thisdoc.ReplaceItemvalue("LastEntryBy","")
Call thisdoc.ReplaceItemvalue("LastEntryDate","")
Call thisdoc.Save(True,True)
End If
Do While Not entry Is Nothing
Set entrydoc = entry.Document
Set template = New NotesDocument(db)
Call template.ReplaceItemValue("Form","RowTemplate")
Call template.ReplaceItemValue("ItemDate", _
Format$(Cdat(entrydoc.GetItemValue("ItemDate")(0)),"mm/dd/yyyy"))
Call template.ReplaceItemValue("Creator", _
entrydoc.GetItemValue("Creator")(0))
Call template.ReplaceItemValue("Issue", _
entrydoc.GetItemValue("Issue")(0))
' *** Copy Rich text Field "Issue"
Set entrydata = entrydoc.GetFirstItem("Issue")
Set templatedata = New NotesRichTextItem(template,"Issue")
Call templatedata.AppendRTItem(entrydata)
' *** Copy Rich text Field "Action"
Set entrydata = entrydoc.GetFirstItem("Action")
Set templatedata = New NotesRichTextItem(template,"Action")
Call templatedata.AppendRTItem(entrydata)
' *** Add doclink to entry
Set doclink = New NotesRichTextItem(template,"DocLink")
Call doclink.AppendDocLink(entrydoc,"Open Entry")
Call template.ComputeWithForm(True,False)
' *** Refresh form
Call template.RenderToRTItem(datafield)
Set entry = col.GetNextEntry(entry)
Loop
Call thisdoc.ComputeWithForm(True,False)
End Sub
And this is what it looks like after adding three entries:
It is of course easy to change the sort order, field to use for sorting, etc.
Update: 2011-08-17 – Fixed download link.




The nsf file is missing not able to download
Should be working now.
Hi,
Yes, i am able to download the zip file.
But After download,when I open this NSF into designer it is showing me error:
“This database has local access protection(encrypted) and you are not authorized to access it.”
I will check it in the morning. The nsf file was not encrypted, but due to some server changes it seems like it can’t be downloaded directly. I thought the zip file contained the same file.
I took the un-encrypted .nsf I linked to previously and put hat one in the zip file, you should be able to access it now.
Let me know how it works.
I tried to download but I get Invalid NSF Version.
You need Notes 8.5 or higher, the file was created in ODS 51.