API
@-Formulas
JavaScript
LotusScript
Reg Exp
Web Design
Notes Client
XPages
 
Recursive Updating Of Children
There are a few tips floating around the internet that talk about updating the children of a document. The easiest is using the StampAll method of the NotesDocumentCollection object. However, what about the situation where you not only have children, but also grandchildren? This generic code will take care of updating all children, no matter how many "great-great's" are in front of them.

To use this function, make a call to RecursiveUpdateChildren and pass in a handle to the current database, the top-level parent document, the field name to be updated, and the value (a variant) to be placed into all the parent's children, grandchildren, great grandchildren, etc.

Here is the main function that starts the recursion:
Sub RecursiveUpdateChildren(db As NotesDatabase, doc As NotesDocument, fieldName As String, value As Variant)
   ' Update all of this document's children documents with the same value in the same field. Since the
   ' parameter is a variant, it could be a number or a string or an array or anything.
   Dim unidList List As Integer
   Dim updateDoc As NotesDocument
   
   ' This function only needs to process if there are children
   If doc.Responses.Count <> 0 Then
      Call UpdateChildren(doc, unidList)   ' Start the recursion
      Forall unid In unidList
         On Error Resume Next
         Set updateDoc = db.GetDocumentByUNID(Listtag(unid))
         If Not updateDoc Is Nothing Then
            Call updateDoc.ReplaceItemValue(fieldName, value)
            Call updateDoc.Save(True, False)
         End If
         On Error Goto 0
      End Forall
   End If
End Sub


The first thing the function does is to check to see if there are children from the document. If there are, the recursion is started by calling another function. A list array of unique ID's is kept containing the UNID's of all the documents to be updated. Once the recursion has finished, this list is processed. Each document is found, then the values are updated.

Here is the recusive function:

Private Sub UpdateChildren(doc As NotesDocument, unidList List As Integer)
   ' Recursively update the children of this document. If there are no children, then there is nothing to do.
   ' If there are children, add those children to the list and recursively update their children.
   Dim children As NotesDocumentCollection
   Dim child As NotesDocument
   
   Set children = doc.Responses
   If children.count <> 0 Then
      Set child = children.GetFirstDocument
      While Not child Is Nothing
         unidlist(child.universalid) = 1
         Call UpdateChildren(child, unidlist)
         Set child = children.GetNextDocument(child)
      Wend
   End If
End Sub


This function just keeps adding to the UNID list with all the children and if there is another level of children then those children are processed recursively.

You may be wondering why the children weren't just immediately processed with the new value? Well, that could have been done. And it would end up processing a bit faster. However, this listing just needs one small change to be modified from a "Recursive Update Children" function into a "Recursive Delete Children" function, which is also needed quite often.

In the main (parent) function, change:
            Call updateDoc.replaceItemValue(fieldName, value)
            Call updateDoc.save(True, False)

into:
            Call updateDoc.remove(True)

And the rest of the function (and the second function) can remain the same.

In fact, this code isn't used as is by us. Since the "Update" and "Delete" are so similar, we end up passing an empty string for the field name to flag that the children should be deleted instead of updated. So the main function checks to see if the field name is blank and, if so, deletes all the children or (if the field name is not blank) updates all the children.