Usability - Productivity - Business - The web - Singapore & Twins

Cleanup your Domino Directory Group structure

When you run a large Domino Installation with a high fluctuation of people coming in and out, you might end up with a lot of Zombies in your groups. This might happen especially with part time administrators, who are to busy with their main jobs (and don't use AdminP to delete users). I had to do a clean-up exercise recently and I used the simplicity of @Formulas to remove user names that are no longer in the Domino Directory from all group entries where they might still be in:
Step 1: Create a new view named (GroupCleanup)|GroupCleanup with one column. Sort that column.
View selection formula: SELECT ( Type= "Person":"Group":"Server" )
Column formula: @If(Type = "Person"; @Subset(Fullname; 1);Type = "Server"; @Subset(Servername; 1); @Subset(ListName; 1))
Step 2:Create an agent, type formula to run against selected documents:
v := "GroupCleanup";
c := @Elements(Members);
good := "";
found := "";
current := Members[i];
found := @Trim(@DbLookup("Notes":"NoCache";"";v;current;1;[FailSilent]));
@If(@Contains(current;"*");good :=good:current;good :=good:found));
finalgood := @Trim(@Unique(good));
finalbad :=@Trim(@Replace(Members;finalgood;""));
FIELD removedMembers := @Trim(@Unique(removedMembers:finalbad));
FIELD Members := finalgood;

Step 3: Use an agent to remove groups that don't have members anymore. Run the agents multiple times to get rid of nested redundant groups:
SELECT type="Group" & @Trim(members)="";

Caveat: This will remove all user names that are not in the main addressbook. That means all users of external organizations might get lost too. You could extend the formula by adding more @dblookups to additional addressbooks.

Posted by on 17 May 2004 | Comments (6) | categories: IBM Notes Lotus Notes


  1. posted by Oswald on Monday 24 May 2004 AD:

    The @For in step 2 is not working in Notes R5. Do you or does someone know how to format this without @For?

    Thanks in advance
  2. posted by Stephan H. Wissel on Tuesday 25 May 2004 AD:
    Hi Oswald,
    neither @For nor [FailSilent] is working in R5. One of the reasons to upgrade. In R5 you have to resort to Lotus Script to achive similar results.
    Emoticon wink.gif stw
  3. posted by Patrick Tippner on Thursday 12 March 2009 AD:
    since i had some trouble with the above @formula-based agent whenever i dealt with really large groups, i decided to rewrite the whole agent in lotus script. here's how it looks (quick & dirty):

    Sub Initialize

    Dim session As New NotesSession
    Dim db As NotesDatabase
    Dim collection As NotesDocumentCollection
    Dim view As NotesView
    Dim item As notesitem
    Dim doc, vdoc As NotesDocument
    Dim count , max_count As Integer
    Dim viewname As String
    Dim mbrArray As Variant
    Dim rsltList_good() As String
    Dim rsltList_bad() As String
    Dim exceptionList List As String
    Dim listname, tmp

    'specify groups that you don't want the script to touch
    exceptionList("XXXDominoServer") = ""
    exceptionList("DeveloperDomainServers") = ""
    exceptionList("DeveloperServer2") = ""
    exceptionList("HostedDomainServers") = ""
    exceptionList("XNotes-NoAnswer") = ""

    count = 0

    Set db = session.CurrentDatabase
    Set collection = db.UnprocessedDocuments
    Set doc = collection.GetFirstDocument()
    Set view = db.GetView(viewname)

    'cycle through all selected documents
    While Not (doc Is Nothing)
    listname = doc.getitemvalue("Listname")
    If Iselement(exceptionList(listname(0))) = False Then
    mbrArray = doc.getitemvalue("Members")
    max_count = Ubound (mbrArray)
    Redim rsltList_good(max_count)
    Redim rsltList_bad(max_count)
    'cycle through all group members
    Dim gc,bc As Integer
    Forall member In mbrArray
    Set vdoc = view.GetDocumentByKey(member)
    If Not (vdoc Is Nothing) Or Instr(member,"@")>0 Or Instr(member,"*")>0 Then
    End If
    End Forall
    mbrArray = doc.getitemvalue("RemovedMembers")
    tmp = Arrayunique(Arrayappend(mbrArray, rsltList_bad),1)
    Set item = doc.replaceitemvalue("Members",Fulltrim(rsltList_good))
    Set item = doc.replaceitemvalue("RemovedMembers",Fulltrim(tmp))
    Call doc.save (True, False)
    End If
    Set doc = collection.GetNextDocument(doc)

    Set view = Nothing
    Set collection = Nothing
    Set doc= Nothing
    Set db= Nothing

    End Sub

    Insert the script as an agent with the target "selected documents" to your domino servers names.nsf. My lotus script relies on the same view the @formula-based script does, with one exception: I also included the mailin-databases in the view-formula, since they are also quite important:

    SELECT ( Type= "Person":"Group":"Server":"Database" )
  4. posted by Patrick Tippner on Thursday 12 March 2009 AD:
    I forgot to mention one point:

    the script also excludes internet-mail-addresses like abc@def.gh from processing (based on the @-sign contained in the string value). If you have mailing-lists or groups containing external email-addresses not defined in your directory, you'll need this Emoticon wink.gif
    Additionaly, the script won't process entries containing an asterisk '*', example: */Srv/DomainXYZ
  5. posted by Patrick Tippner on Wednesday 08 September 2010 AD:
    ...also make sure to be careful with users that have just been renamed by the admin-process! if the name in the person document has already changed, it doesn't mean that the corresponding entries in the group documents have done so, too Emoticon wink.gif
    in case that anything goes wrong, have a look at the "RemovedMembers"-field in each modified group document.
  6. posted by Gurmeet on Thursday 07 October 2010 AD:
    @2 Thanks Patric, exactly what I needed. You save me couple hours of code time...

    much appreciated.