Name based hide-whens with nested groups
First, in the process of writing this post, I had a nagging feeling that I was missing something. I could not shake it but I wrote the post anyway and saved as a draft. I did some research and found that I had essentially done something the hard way. A new feature added to R6 @Formula language (hence why I could not remember it) gave me the functioanlity that I needed. So since the post was written, I’ll leave it and detail both methods at the end.
Ok, so I find myself hacking my way through an app written by a here-today gone-tomorrow consulting company to add in a feature where no forethought had been used. In a nutshell, the application had a list of names from a directory, and a key action button was hidden based upon the condition that the user is a member of that list. Easy enough when you list people individually, but when you add groups it gets more difficult. Add the idea of nested groups, or group names within groups, and alot of developers will simply get that blank stare on their face.
Funny how when you ask the original authors about the functionality (which to me should have been there to begin with), they are suddenly there to help…….for a price. Numbers are irrelevant, but their estimate was 2 days!!
Enter the concept of iteration, where a function can call itself. In the case of finding the members of a nested group, the function that looks at each group members name, will call itself when it comes upon another group name. All the while building a list of only user names. So we take the list of user/group names, and pass each list member into our function. If the list member is a user name, then we add that name to our list. If the name is a group name, we call our function again, passing it the group name, and it repeats itself.
Once we have that list of individual user names, all we need to do is alter the hide-when to use our new list when determining if to render the button, and we are all set. Total time to deliver…….4 hours (5 including my final method). Now you know why I left the consulting arena; I am too honest.
Here is a more detailed breakdown of the code and its execution. The exact usage of the lotusscript is dependant upon your situation, but I do the call when I am saving the document and change the hide-when to look at my new list. The @Formula option I used within the button hide-when formula.
First, the easy way. In R6 Domino we now have the function @UserNamesList which returns all names, groups, and roles that the present user belongs to. I eventually used this to determine if the present users name, or group memberships are listed in the invite list to allow button visibility. This method has to be coupled with another R6 addition which was @For.
This is the @Formula code to hide the button from someone not in the invite list. userCheck is a boolean value that is the determinator. If it is false (0) then it will hide the button.
userList := @UserNamesList; userCheck := 0; inviteList := @Explode(@UpperCase(@Implode(@Name([Abbreviate];invitees);":"));":"); @For(n := 1; n < = @Elements(userList); n := n + 1; @If(@IsMember(@UpperCase(@Name([CN];userList[n]));inviteList); userCheck := 1; "" ) ); @If(userCheck=0; @True ; @False);
So now we come to the much longer lotusscript solution that would only be needed if we did not have access to the credentials of the current user (i.e. a server process).
‘Here are some global objects:
Dim arrMemList() As String
Dim intMemListSize As Integer
‘ This is the code that calls the function originally, and sets the new field in the end
Dim s As New NotesSession Dim dbThis As NotesDatabase, dbNames As NotesDatabase Dim doc As NotesDocument Dim server As String Dim invitees As Variant Dim bSuccess As Boolean Set dbThis = s.CurrentDatabase server = dbThis.server Set dbNames = New NotesDatabase(server, "names.nsf") Set vw = dbNames.GetView("($VIMUsers)") Set doc = You_Set_This invitees = doc.ListFieldWithUserNames intMemListSize = -1 Forall member In invitees If createExplodedNameList(vw, Cstr(member)) Then bSuccess = True Else bSuccess = False End If End Forall If bSuccess Then doc.newListOfNames = arrMemList Else Messagebox "There seems to be a problem parsing the invitee names. " doc.newListOfNames = arrMemList End If
‘ finally the function that gets called everytime it has a group name to explode
Function createExplodedNameList(vw As NotesView, key As String) As Boolean On Error Goto errorCatch createExplodedNameList = False Dim docLoop As NotesDocument Dim nm As NotesName Dim varMembers As Variant Set docLoop = vw.GetDocumentByKey(key) If docLoop Is Nothing Then Exit Function Else varMembers = docLoop.Members Forall member In varMembers Set nm = New NotesName(Cstr(member)) ' check for Notes name or group name If nm.IsHierarchical Then ' this is a hierarchical notes name intMemListSize = intMemListSize + 1 Redim Preserve arrMemList(intMemListSize) arrMemList(intMemListSize) = nm.Abbreviated Else ' this is a group, go explode it Call createExplodedNameList(vw, Cstr(member)) End If End Forall End If createExplodedNameList = True Exit Function errorCatch: Messagebox "Error in getGroupMembers..createResultsNode in line: " & Erl() & " error$: " & Error$ Exit Function End Function