Change NAB while maintaining integrity of documents

With this code, a user devised a method of updating the information in his personal Notes Address Book without changing the fields he did not want touched.

I have always maintained documents in my private Notes Address Book (NAB) to save access time using the type-ahead feature. I have also added new fields to my personal documents to maintain other information about my contacts. My problem was that the public NAB is updated daily, while my private NAB is not.

Generally this is not an issue, but my company merged with another and everyone's e-mail address changed, causing my e-mails to fail. This situation magnified when the company issued me a laptop and I often worked offline. Not having access to the public NAB all the time, I had to make sure my personal NAB was kept up to date.

I could not do a full replication because I did not want the entire public NAB on my laptop. I could not do a partial replication because my added fields would be eliminated. I had to devise a method of updating the information in my personal NAB without changing the fields I did not want touched.

The following code accomplished just that while maintaining the integrity of the documents. I run this on a daily schedule so each time I am connected to the network, my private NAB is updated with the most recent information.

Basically I do a GetDocumentByKey using the employee ID as the key. With this, I retrieve all the fields in the public document (excluding the Notes maintained fields that begin with "$", plus a couple others I am not interested in) and match them to the same fields in my private documents.

In doing this, there are 4 scenarios that can happen:

1) Both the public and private fields are identical, in which case I do nothing.
2) The public and private fields have the same number of entries (fields are returned as arrays), but have different values, in which case I roll through the values in the field and copy only the items that do not match.
3) The field in the public document has a different number of entries than the field in the private document, in which case I replace the entire field in the private document with the corresponding field in the public document.
4) A public document is not found because the person left the company and their document has been removed from the public NAB, in which case I clear the field containing the employee ID in the private document to prevent processing the document in the future (I do not delete the private document because of the added fields being maintained).

The only prerequisite to this process is that you need a view in both the public and private NABs that list the documents by the key you are using. In my case, the public NAB has a hidden view called "(ByCellPhoneNumber)" (this contains the Employee ID (go figure?!)) and I created a hidden view in my private NAB called "(byEmpID)". Both identify documents with {Type = ("Person" : "Company") & CellPhoneNumber != ""}.

One other thing: To add a new document to the process, simply copy the Public Document to the private NAB and it will be automatically processed in the next cycle.

(Note: I have Msgbox's embedded for clarity. Since I run this on a schedule, I use Notes Logging and send the log to my mailbox to trap messages.)

Sub syncNab
  Dim s As New NotesSession

  ' My Local NAB
  Dim LclNab As New 
NotesDatabase( "", "names.nsf" )   
  If Not LclNab.IsOpen Then 
' Check if the local NAB is available  
    Msgbox "Local Names.nsf 
not available, cannot process update.",,"Error!"
    Goto Exit_syncNab
  End If
  ' The Public NAB
  Dim PubNab As New 
NotesDatabase( "ServerNameHere", "names.nsf" )
  If Not PubNab.IsOpen Then 
' Check if the server NAB is available  
    Msgbox "Server not available, 
cannot process update.",,"Warning!"
    Goto Exit_syncNab
  End If

  On Error Goto Error_syncNab
  Dim LclView As NotesView 
' Define the Local NAB Stuff
  Dim LclDoc As NotesDocument
  Dim nextDoc As NotesDocument
  Dim LclValue As Variant
  ' This view contains documents that are
  '  of the types "Person" or "Company" and the
  '  "CellPhoneNumber" field is not blank. 
  Set LclView = LclNab.GetView( "( byEmpID )" )
  Dim PubView As NotesView
 ' Define the Public NAB Stuff
  Dim PubDoc As NotesDocument
  Dim PubItem As NotesItem
  Dim PubValue As Variant
  ' Same criteria as LclView
  Set PubView = 
PubNab.GetView( "( byCellPhoneNumber )" )
  ' Set up some counters for tracking
  Dim docCntr As Integer, 
itemCntr As Integer, skipCntr As Integer
  Dim updCntr As Integer,
 saveFlag As Integer, removeCntr As Integer
  Dim valno As Integer
  updCntr = 0
  removeCntr = 0
  Set LclDoc = LclView.GetFirstDocument
  docCntr = 1

  While Not LclDoc Is Nothing
    saveFlag= False ' Assume a no save situation
    itemCntr = 0 
' Reset the counters for the next document
    skipCntr = 0
    ' Reserve the next Local Document
    Set nextDoc = LclView.GetNextDocument( LclDoc )
    ' Find the Public Document
    Set PubDoc = 
( LclDoc.CellPhoneNumber( 0 ) )
    If PubDoc Is Nothing Then       
      ' This means the person 
is no longer in the Public NAB  
      '  This will remove 
the document from the Local view
      '  so it will not 
be processed in future runs
      LclDoc.CellPhoneNumber =
 "" ' Blank the field
      ' Track the number of 
Fields being Updated
      itemCntr = itemCntr + 1
      ' Track how many documents
 are removed from processing
      removeCntr = removeCntr + 1
      saveFlag = True

      ' This means a Public document 
was found and will be processed
      ' Roll through the fields in the Public document
      '  and compare them to the Local document
      Forall item In PubDoc.Items
        ' Skip all the Notes fields ( and some extra stuff )
        If Left(,1 ) <> "$" _
        And <> "Form" _
        And <> "Type" _
        And Left(,4 ) <> "HTTP" _
        And Left(,4 ) <> "INet" _
        And Left(,8 ) <> "Password" _
          ' Track the number of fields being processed
          itemCntr = itemCntr + 1 

          Set PubItem = 
PubDoc.GetFirstItem( )

          ' Check if the Local Document has the 
          '  same field as the Public document
          If Lcldoc.HasItem( ) Then
            ' If the field exists, get the value from 
            '   both Public and Local documents
            PubValue = 
PubDoc.GetItemValue( item.Name )  
            LclValue = 
LclDoc.GetItemValue( item.Name )  
            If Ubound( PubValue ) = 
Ubound( LclValue ) Then
              ' If it has the same number of values, 
              '  then compare each value            
              For valno = 0 To Ubound( LclValue )
                If LclValue( valno ) 
<> PubValue( valno ) Then                  
                  ' If any value is different, replace it
                  Call Lcldoc.
ReplaceItemValue(, PubValue )
                  saveFlag = True
                  Exit For
                End If 
' LclValue( valno ) <> PubValue( valno )                 
              Next valno

              ' If it does not have the same number 
              '  of values, then copy the item
              Set PubItem = 
PubDoc.GetFirstItem( )
              Call PubItem.
CopyItemToDocument( LclDoc, )
              saveFlag = True
            End If ' Ubound( PubValue ) = 
Ubound( LclValue ) 

' If the Local document does not contain the field, 
'  then copy the field from the Public document
Set PubItem = PubDoc.GetFirstItem( )
Call PubItem.
CopyItemToDocument( LclDoc, )
            saveFlag = True
          End If ' Lcldoc.HasItem( ) 
          ' Track the number fields not being processed
          skipCntr = skipCntr + 1
        End If ' Left(,1 ) <> "$" _
      End Forall        
    End If ' PubDoc Is Nothing
    If saveFlag Then 
' Only save if the the document changed
      Call LclDoc.Save( True, False )
' Track how many documents are being updated
      updCntr = updCntr + 1        
    End If ' saveFlag 

    Set LclDoc = nextDoc 
' Set the next document to current
    ' Track how many 
document are being processed
    docCntr = docCntr + 1
  Exit Sub
  Msgbox "Err#: " & Str( Err ) & " at line " & Str( Erl ) _
  & Chr( 10 ) & "ErrorDesc: " & Error$,,"Error!"
  Resume Exit_syncNab
End Sub

Do you have comments on this tip? Let us know.

This tip was submitted to the tip exchange by member Bob Vezzuso. Please let others know how useful it is via the rating scale below. Do you have a useful Notes/Domino tip or code to share? Submit it to our monthly tip contest and you could win a prize and a spot in our Hall of Fame.

Dig Deeper on Lotus Notes Domino Mailbox Management

Start the conversation

Send me notifications when other members comment.

Please create a username to comment.




  • iSeries tutorials's tutorials provide in-depth information on the iSeries. Our iSeries tutorials address areas you need to know about...

  • V6R1 upgrade planning checklist

    When upgrading to V6R1, make sure your software will be supported, your programs will function and the correct PTFs have been ...

  • Connecting multiple iSeries systems through DDM

    Working with databases over multiple iSeries systems can be simple when remotely connecting logical partitions with distributed ...