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 =
PubView.GetDocumentByKey
( 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
Else
' 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( item.name,1 ) <> "$" _
And item.name <> "Form" _
And item.name <> "Type" _
And Left( item.name,4 ) <> "HTTP" _
And Left( item.name,4 ) <> "INet" _
And Left( item.name,8 ) <> "Password" _
Then
' Track the number of fields being processed
itemCntr = itemCntr + 1
Set PubItem =
PubDoc.GetFirstItem( item.name )
' Check if the Local Document has the
' same field as the Public document
If Lcldoc.HasItem( item.name ) 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( item.name, PubValue )
saveFlag = True
Exit For
End If
' LclValue( valno ) <> PubValue( valno )
Next valno
Else
' If it does not have the same number
' of values, then copy the item
Set PubItem =
PubDoc.GetFirstItem( item.name )
Call PubItem.
CopyItemToDocument( LclDoc, item.name )
saveFlag = True
End If ' Ubound( PubValue ) =
Ubound( LclValue )
Else
' If the Local document does not contain the field,
' then copy the field from the Public document
Set PubItem = PubDoc.GetFirstItem( item.name )
Call PubItem.
CopyItemToDocument( LclDoc, item.name )
saveFlag = True
End If ' Lcldoc.HasItem( item.name )
Else
' Track the number fields not being processed
skipCntr = skipCntr + 1
End If ' Left( item.name,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
Wend
Exit_syncNab:
Exit Sub
Error_syncNab:
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 SearchDomino.com 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.