Find And Append In LotusScript
A couple months ago we posted a tip talking about doing a find and replace in LotusScript using the new Notes 6 rich text classes. Someone wanted to add an asterisk to the front of the text instead of actually replacing the text. Since the original string of text would still be there, this presented a new challenge. The first thought we had was that two distinct find and replace operations could happen as outlined by the tip from a couple months ago. In the first pass, you would replace the text with a unique set of characters that doesn't otherwise exist in the rich text field. Then, on the second pass, you would replace that unique set of characters with an asterisk followed by the original string of characters.
Naturally, that would work, but we wanted to take it a step further and see if there was another way to accomplish this task. For example, what if you wanted the asterisk to be bold and red, when the original text is plain black? The two step find and replace wouldn't be sufficient in that case.
If you haven't read the find and replace tip from a couple months ago, you should go read it first. We're going to expand on the method where the text is found, new text is inserted, then the rich text field is compacted and updated. But instead of removing the range that we find, we're going to leave it and insert our new text.
The important thing to remember is that when you compact and update the rich text field, you have to reset your pointers. So that means you're pointing back to the start of the field. Since we didn't actually remove the string of text to find, finding the first occurrence won't be sufficient. We have to find the "nth" occurrence, where "n" increases by one each time. Unfortunately, there doesn't exist a method to find that when you're talking about strings. (There is a FindNthElement method in the NotesRichTextNavigator class, but that is only applicable to paragraphs, tables, table cells, sections, links, attachments, and OLE objects - it won't work for a specific string of text). So we have to write our own block of code to find the "nth" occurrence of our string of text.
We want to update every occurrence, so the best way to do this is through an "infinite" While loop where our code uses a flag to know when to end:
Dim count As Integer
Dim continue As Boolean
count = 0
continue = True
If Not nav.FindFirstString("text to find") Then continue = False
While continue
So the variable continue will be set to False when we are done replacing every occurrence. The variable count is used to keep track of the value of "n" so we can find the "nth" occurrence.
If count >= 1 Then
For i = 1 To count
If Not nav.FindNextString("text to find") Then
continue = False
i = count+1
End If
Next
End If
This block of code is the "FindNthString" code. The first time through our While loop (when count is zero), the navigator object is already pointing to the first occurrence. So we don't need to check for any more. Every subsequent time through, it is also pointing at the first occurrence, so we need to perform the FindNextString method "n-1" times. The variable count isn't updated until the bottom of the outer While loop, so here at the top we can loop from 1 to count.
This code also tells us when we have found the last string of text. When that happens, set continue to False (so the outer loop will terminate) and set the variable i to the value count+1 (so the script won't try to find another occurrence when the last one couldn't be found).
The next thing we need to do is insert the asterisk character in front of the text that the NotesRichTextNavigator object points to.
If continue Then
Call range.SetBegin(nav)
Call range.SetEnd(nav)
Call body.BeginInsert(nav)
Call body.AppendText("*")
Call body.EndInsert
Call body.Compact
Call body.Update
Set range = body.CreateRange
Set nav = body.CreateNavigator
count = count+1
If Not nav.FindFirstString("text to find") Then continue = False
End If
Wend
If count <> 0 Then Call doc.Save(True, False, True)
This is similar to the tip a couple months ago except we are only inserting one character and we aren't removing the range before inserting. The code above will insert the asterisk at the beginning of the range. If you would want to insert it at the end of the range, then I suppose you could remove the range, and do the insert with "text to find" followed by the asterisk.
If you wanted to have the asterisk appear bold and in a different color, then you should define a NotesRichTextStyle object and use the AppendStyle method in the NotesRichTextItem class before appending the text.
At the bottom of the loop, the counter in increased and the navigator is pointed to the first occurrence of the text to be found.