• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1583
  • Last Modified:

Search a user by shortname

Hello,

I am trying to modify the Lotus Script I have got (in a Web Service Provider) to find a user in the names.nsf > $Users view > ShortName column

At the moment I was getting the User document using this line of code:

'OPEN USER DOCUMENT IN USERS VIEW
Set person = view.GetDocumentByKey(userID,False)

Open in new window


I checked what this function does and it is doing a lookup on the first Categorized and Sorted column in the view (ie: Name)

Now since ShortName is neither the first nor categorized or sorted column of $Users, how can I find this UserID in the ShortName column?

Your help is much appreciated
0
jmlacoste
Asked:
jmlacoste
  • 12
  • 8
  • 5
1 Solution
 
Sjef BosmanGroupware ConsultantCommented:
Try the ($NamesFieldLookup) view...
0
 
jmlacosteAuthor Commented:
Hello,

Thank you for your reply, unfortunately I dont see this view in names.nsf, and since I need to retrieve the address book of this user, I don't know if the remaining of my code will need to be changed if I get the document from another view than $Users?

Here are the views I see in names.nsf:

 Names.nsf available views
thanks again
0
 
Sjef BosmanGroupware ConsultantCommented:
In a web service provider? I assume it runs on the server, so you must have all user address books on the server as well.

Or do you use iNotes? In that case, you'll find the contacts inside the mail database.

Try the ($EmailAddresses) view in a Personal Address book...
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
doninjaCommented:
The database design you are looking at is for a personal address book rather than a public address book.
Is this intentional as part of the application design as most servers would use public address book design databases that has the view Sjef refers to.

As an alternative just make a copy of the view ($users) in your design and call it say ($shortnames)
You could then just move the shortname field to the beginning in the designer and make that the sorted catagorised column.

In brief there is no way to use .getdocumentbykey() on any column except the first sorted column. That is why customised views are required.
0
 
jmlacosteAuthor Commented:
Thank you for your replies.

I'll give a little bit of context then. My web service provider is on the server hosting names.nsf also.

When I call this web service I used to pass the Name as a parameter (UserID in the LS code)

Then I retrieve the User personal address book, from iNotes indeed. But I need to find the User from the $User view first.

I thought there was an easy way to look for a ShortName instead of Name, I don't need to use GetDocumentByKey necessarily, I just don't know what other functions would let me do something similar with ShortName...

Creating a new view to find the Name from the ShortName and then going back to my original code seems very very complicated for me :-(

Any other options??

Fingers crossed
0
 
Sjef BosmanGroupware ConsultantCommented:
> But I need to find the User from the $User view first.
What user do you need to find, why, and where? If you need to know his details, they are in the server N&A book, and then you'd use the NamesFieldLookup view.
0
 
jmlacosteAuthor Commented:
OK more details because my old code was doing this (by Name lookup)
and probably this wasn't optimal and maybe if I want to look for ShortName it's totally different!

The main steps were:
'OPEN DATABASE
'OPEN $USERS VIEW
'OPEN USER DOCUMENT IN USERS VIEW <<
'CHECK ROAMING FLAG, AND GET MAILFILE PATH
'OPEN MAILFILE
'CHECK MAILFILE DATE
'OPEN INOTES_CONTACTS VIEW
'COUNT CONTACTS IN INOTES_VIEW
'READ INOTES_CONTACTS
'FORMAT CONTACTS TO RETURN      

full code excerpt:

'OPEN DATABASE
		
		Set session = New NotesSession
		Set db = session.Getdatabase("",notesBase,False)
		
		If db Is Nothing Then
			Call ConsoleWrite( "Can't open database. Exit.")
			msg="Unable to open database file: "+notesBase
			Goto ProcessEnd
		End If
		
		Call ConsoleWrite( "Database opened. Getting view $Users...")
		
		scriptStepsCounter=scriptStepsCounter+1
		
		
		Dim person As New NotesDocument(db)		
		Dim view As  NotesView	
		
'OPEN $USERS VIEW
		Set view= db.GetView("($Users)")
		scriptStepsCounter=scriptStepsCounter+1
		
		If(Isnull(view)) Then
			Call ConsoleWrite( "View not found. Exit")
			msg="Unable to open the $Users view "
			Goto ProcessEnd
		Else			
			Call ConsoleWrite( "View opened. Searching for user...")			
		End If	
		
		
		
'OPEN USER DOCUMENT IN USERS VIEW
		
		Set person = view.GetDocumentByKey(userID,False)
		
		If person Is Nothing Then
			Call ConsoleWrite("User not found. Exit")
			msg="User not found in $Users view"
			Goto ProcessEnd
		Else
			scriptStepsCounter=scriptStepsCounter+1
			Call ConsoleWrite( "User found. Checking if user is roaming...")
		End If
		
'CHECK ROAMING FLAG, AND GET MAILFILE PATH
		
		If (person.GetItemValue("RoamingUser")(0)="1") Then
			Call ConsoleWrite( "User is roaming. Getting Mail file path..."					)
			mailFilePath=person.GetItemValue("MailFile")(0)
			
		Else
			Call ConsoleWrite( "User is not Roaming. Getting Mail file path..."	)
			mailFilePath=person.GetItemValue("MailFile")(0)
			
		End If		
		
		Call ConsoleWrite("Mail file path found: "+mailFilePath+". Opening Mail file...")
		scriptStepsCounter=scriptStepsCounter+1 'MailFile path stored
		
'OPEN MAILFILE
		
		If mails.Open("", mailFilePath) Then
			Call ConsoleWrite( "Mail file opened. Checking file date ...")
			scriptStepsCounter=scriptStepsCounter+1 'MailFile opened			
		Else
			Call ConsoleWrite("Cannot open Mail File. Exit")
			msg="Could not open mail file: "+ mailFilePath
			Goto ProcessEnd
		End If
		
		
		
		
'CHECK MAILFILE DATE
		Call ConsoleWrite( "Mail file date compare: File date: "+mails.LastModified+". Last Sync date: "+Cstr(sentDate)+", original last sync date: "+lastSyncDate)
		
		If (mails.LastModified>sentDate) Then
			Call ConsoleWrite( "Mail file has changed since last sync. File date: "+mails.LastModified+". Opening iNotes_Contacts view in Mail File ...")	
		Else
			Call ConsoleWrite( "Mail file hasn't changed since last sync. File date: "+mails.LastModified+". Exit")
			msg="0"
			'msg="Mail file hasn't changed since last sync. File date: "+mails.LastModified
			Goto ProcessEnd
		End If
		
		
'OPEN INOTES_CONTACTS VIEW
		
		Set view=mails.GetView("iNotes_Contacts")
		Call ConsoleWrite( "View opened. Counting contacts...")
		scriptStepsCounter=scriptStepsCounter+1 'iNotes_Contacst view opened
		
'COUNT CONTACTS IN INOTES_VIEW
		
		If(view.EntryCount<1) Then
			Call ConsoleWrite( "No contacts for this user. Exit.")
			msg="0"
			'msg= "No contacts for this user."
			Goto ProcessEnd
		Else
			Call ConsoleWrite( "Contacts found: "+ Cstr(view.EntryCount)+". Opening first contact...")
		End If
		
'READ INOTES_CONTACTS
		
		Set doc = view.GetFirstDocument
		
		Dim currentContactModDate As  String '  NotesDateTime("01/01/1970 00:00:00") 'holds the current notes contact last modified date to compare with last sync date
		currentContactModDate=doc.LastModified	'record modification date of first contact
		
		Set addressBook = mails.GetProfileDocCollection("ProfileThatDoesntExist") ' Creates an empty documents collection the fastest way
		
		Call ConsoleWrite("First contact opened. Entering loop to collect them all in a NotesCollection... ")
		While Not ( doc Is Nothing )
			If (doc.LastModified>sentDate) Then
				currentContactModDate=doc.LastModified ' record date of any contact more recent than last sync
			End If
			Call addressBook.AddDocument(doc)		
			
			Set doc = view.GetNextDocument( doc )
		Wend
		Call ConsoleWrite( "Loop finished, contacts retrieved: "+Cstr(addressBook.Count)+". Create a contacts array to store them...")
		
		scriptStepsCounter=scriptStepsCounter+1 'all contacts read
		
		
'FORMAT CONTACTS TO RETURN		
ProcessEnd:			
		Call ConsoleWrite("Step reached: "+Cstr(scriptStepsCounter))
		
		If (Err >0) Then
			msg=msg+ " Error nb: "+Cstr(Err)_ 
			+"; Description: "+Error(Err)_ 
			+"; Line nb: "+ Cstr(Erl)_ 
			+"; ERROR!"
		End If
		
		Call ConsoleWrite("Msg="+msg)
		
		Set getAllContacts = New ContactDetailsArray
		Call ConsoleWrite("Contacts array created. Converting contacts documents collection into an address book...")
		
		Call getAllContacts.setArrayFromCollection(addressBook, userID,msg)
		Call ConsoleWrite("Array converted. Sending result.")
		
		
		Set getUserContacts = getAllContacts
		
		
		Call ConsoleWrite( "========================= END =================================")
		Exit Function
		
	End Function
	
	
End Class






%REM
**********************************************************************
*****************CONTACT FORMAT DEFINITION *****************
**********************************************************************
%END REM


Class ContactDetails
	
	Public A As String
	Public B As String
	Public C As String
	Public D As String
	Public E As String
	Public F As String
	Public G As String
	Public H As String
	Public I As String
	Public J As String
	Public K As String
	Public L As String
	Public M As String
	Public N As String
	Public O As String
	Public P As String
	Public Q As String
	Public R As String
	
	Public Function getContactDetails (doc As NotesDocument) As Integer		
		A = doc.GetItemValue("Title")(0)
		B= doc.GetItemValue("LastName")(0)
		C = doc.GetItemValue("FirstName")(0)
		D = doc.GetItemValue("JobTitle")(0)
		E = doc.GetItemValue("Department")(0)
		F = doc.GetItemValue("Location")(0)
		G = doc.GetItemValue("CompanyName")(0)
		H = doc.GetItemValue("OfficePhoneNumber")(0)
		I = doc.GetItemValue("CellPhoneNumber")(0)
		J = doc.GetItemValue("OfficeFAXPhoneNumber")(0)
		K = doc.GetItemValue("PhoneNumber")(0)
		L = doc.GetItemValue("MailAddress")(0)
		M = doc.GetItemValue("OfficeStreetAddress")(0)
		N = doc.GetItemValue("OfficeZIP")(0)
		O = doc.GetItemValue("OfficeCity")(0)
		P = doc.GetItemValue("OfficeCountry")(0)
		Q = doc.GetItemValue("Manager")(0)
		R = doc.NoteID		
		getContactDetails=True
	End Function
	
End Class


Class ContactDetailsArray 
	Public details() As ContactDetails '//returns all the details from one contact
	Public count As Integer '//number of contacts for this user
	Public msg As String '//sends error message or OK
	
	Private Sub ConsoleWrite (ConsoleMsg As String)
		If (DEBUG_MODE="1") Then 
			Print "[telisca] "+ConsoleMsg
		End If
	End Sub
	
	Public Sub setArrayFromCollection (addressBook As NotesDocumentCollection, username As String, message As String)
		On Error Goto skipFunction
		Call ConsoleWrite("(setArrayFromCollection) Start ...")
		msg=message	
		If(msg<>"") Then
			If (msg="0") Then msg="" ' 0 is passed when no sync is needed or user has no contacts, we return an empty msg
			Goto skipFunction		
		End If
		
		count=addressBook.Count
		
		If (count=0) Then
			Redim details(0)
		Else
			Redim details(count-1)
			
			Dim doc As NotesDocument
			Dim currentLastModDate As Variant
			Dim contactCounter As Integer
			
			Set doc=addressBook.GetFirstDocument
			
			Do Until (doc Is Nothing)
				Dim contact As New ContactDetails
				Call contact.getContactDetails(doc)
				Set details(contactCounter)=contact
				Set doc = addressBook.GetNextDocument(doc)
				contactCounter= contactCounter+1
			Loop		
		End If
		Exit Sub
		
skipFunction:		
		Call  ConsoleWrite ( "setArrayFromCollection Function Skipped"	)
		If (Err >0) Then
			Call  ConsoleWrite ( "setArrayFromCollection Error nb: "+Cstr(Err)_ 
			+"; Description: "+Error(Err)_ 
			+"; Line nb: "+ Cstr(Erl)_ 
			+"; ERROR!")
		End If
		Exit Sub	
	End Sub	
End Class

Open in new window

0
 
doninjaCommented:
Ok assuming that you have to use this addressbook and not a public then a custom view is just as easy to use as the existing $users view.
A view is just a collection of documents, the same documents if you use $users or a custom $shortnames.
So once you have got the document using .getdocumentbykey then the underlying Notesdocument returned will have all the same fields that your remaining code would require with no changes required. Assuming you are looking up document fields and not using document.columnvalues(x)
So only one change to your code is just the name of the view to get.

Am I right in saying that your application looks up users in a custom address book and not the Servers Primary address book ? as that would explain the difference in views shown in your screen shot.
As your explanation above seems to suggest your looking in a public addressbook on the server to find the users mailfile. Of course your service provider could have set this all up differently to normal which makes it  pita.

Otherwise if you must use $users for some reason then you could pull the column into an array using .evaluate("@dblookup("";"";"($users)",columnnumber)") and then search it using .getarrayindex but this would be slow and painful to manipulate compared to a custom view or namesfieldlookup.

First I would absolutely confirm the deign of the server address book your trying to interogate and what template it uses and what views it has. Also what rights do you have to modify this database or template to add your own views etc.
May help to dispel some of the confusion here.
0
 
doninjaCommented:
Just looking at your code, no issue with using a custom view as you only refernce it once to get the document. After that you just refernce the doc.

so create custom view with the sort order you want and just chnage name in code n the one place you get the view by it's name.
0
 
jmlacosteAuthor Commented:
OK thanks doninja

Here are my comments:

Assuming you are looking up document fields and not using document.columnvalues(x)
>I do use person.GetItemValue("RoamingUser")(0) for instance or doc.GetItemValue("LastName")(0)
doc being addressBook = mails.GetProfileDocCollection

Am I right in saying that your application looks up users in a custom address book and not the Servers Primary address book ?
>no I'm using the default names.nsf on the server, but I'm not too sure my Lab domino is correctly set, am I missing some default Views I could use in there?


Otherwise if you must use $users for some reason then you could pull the column into an array using .evaluate("@dblookup("";"";"($users)",columnnumber)") and then search it using .getarrayindex but this would be slow and painful to manipulate compared to a custom view or namesfieldlookup.
I won't do this because performance is quite important

Also what rights do you have to modify this database or template to add your own views etc.
>As I am able to install my xxWebService.nsf containing the Web Service provider on the server with access to names.nsf and then personnal address books I hope adding a view in their names.nsf will be possible...

I'll confirm with them if I will use the standard names.nsf or something custom and see how how comfortable they'll be adding a view in there...

In the meantime, would you let me know how to create a $shortnames view which is an exact replica of $users at the difference that only the ShortName column is Categorized and Indexed please?

I am not an experimented Domino user at all :p

Thanks again
0
 
Sjef BosmanGroupware ConsultantCommented:
I"m still confused, I still have trouble understanding why NamesFieldLookup can't be used. The database you open on line 4 (notesBase) is the server's N&A book, right? And the lookup you do on line 36 is in that database as well? Did you try/test your code with the NamesFieldLookup view?
0
 
jmlacosteAuthor Commented:
sjef_bosman

Sorry for the confusion notesBase is passed as a parameter to the WebService and we usually use names.nsf

What do N&A book stand for?

I'm starting to get confused now as to why it is working now...as it is!

:-s
0
 
doninjaCommented:
From the comment above I think your lab system is a Lotus Notes client not a Domino Server.

Therfore it is using a Lotus Personal Address book template for Names.nsf
On the Server it will use a Public Addressbook or Domino Directory template for names.nsf.

This will add in the extra views that Sjef is reffering to.

Before continuing I would recommend creating a new address book on your local machine using the template "Domino Directory (pubnames.ntf)" which will be availbale if you select a server as a template source not your workstation. Or copy the NTF file to your local machine.
Call this new database say testnames.nsf and adjust your code to look at this database during your testing on the workstation.

You will need to do this otherwise your testing will not be valid as it will be looking at the wrong database design and you could make assumptions in your code that will not be valid on the server.
0
 
jmlacosteAuthor Commented:
Did you try/test your code with the NamesFieldLookup view?
I haven't tested yet since I don't seem to see this view in names.nsf (cf screenshot above)

But I'll try anyway, hopefully I'll be able to do it :)
0
 
jmlacosteAuthor Commented:
doninja

Thanks I see some light.
I am actually on the server itself but the Names.nsf I opened is indeed the Administrator's personnal address book rather than the public names thing...

I've got NamesFieldLookup  now!!
So how do I retrieve the user from his SHortName, as it seems to only have 3 columns none of which are shortname?



Thanks :-)

 names.nsf
0
 
jmlacosteAuthor Commented:
http://www.experts-exchange.com/Software/Office_Productivity/Office_Suites/Lotus_SmartSuite/Lotus_Notes/Q_22782075.html

Bill-Hanson seems to imply that his function

  '/**
      ' * Locates and returns the NotesDocument for a specific person, group, or mail-in database.
      ' * @param userName The name of the user profile to locate.  This can be a person's name (full, common, abbreviated, short, or email), a group name (list name, abbreviated or email), a database name (full, abbreviated or email), or a certifier name (full or abbreviated).  If this parameter is an empty string, the current user will be used.
      ' * @return If the profile was found, a NotesDocument containing the profile is returned; otherwise the return value is Nothing.
      ' */

      Public Function GetUserDoc(Byval userName As String) As NotesDocument
            
            Dim vwUsers As NotesView
            Dim docUser As NotesDocument
            
            ' Init
            If (TRAP_ERRORS) Then On Error Goto CATCH
            userName = Trim(userName)
            If (userName = "") Then userName = mSess.UserName
            
            ' Check each address book.
            Forall db In mSess.AddressBooks
                  
                  Set mDb = db
                  If (mDb.Open("", "")) Then
                        
                        ' Make sure the database is supported by the current settings.
                        If (Me.IsDatabaseSupported(mDb)) Then
                              
                              Set vwUsers = mDb.GetView("($Users)")
                              If (Not vwUsers Is Nothing) Then

Open in new window


So according to this my code is already looking for all of these columns !?!? And should work no matter if I pass Name or ShortName as my variable UserID

Please confirm, it seems too good to be true !!!

:)
0
 
jmlacosteAuthor Commented:
I missed the important bit of Bill's code:

 Public Function GetUserDoc(Byval userName As String) As NotesDocument
            
            Dim vwUsers As NotesView
            Dim docUser As NotesDocument
            
            ' Init
            If (TRAP_ERRORS) Then On Error Goto CATCH
            userName = Trim(userName)
            If (userName = "") Then userName = mSess.UserName
            
            ' Check each address book.
            Forall db In mSess.AddressBooks
                  
                  Set mDb = db
                  If (mDb.Open("", "")) Then
                        
                        ' Make sure the database is supported by the current settings.
                        If (Me.IsDatabaseSupported(mDb)) Then
                              
                              Set vwUsers = mDb.GetView("($Users)")
                              If (Not vwUsers Is Nothing) Then
                                    
                                    Set docUser = vwUsers.GetDocumentByKey(userName, True)
                                    If (Not docUser Is Nothing) Then
                                          
                                          ' Found!
                                          Set GetUserDoc = docUser
                                          Exit Function
                                          
                                    End If
                                    
                              End If ' END - Get the person lookup view.
                              
                        End If ' END - Database is supported.
                        
                        ' Close and release the datbase handle.
                        Call mDb.Close()
                        Set mDb = Nothing
                        
                  End If ' END - Open an address book.
                  
            End Forall ' END - Check each address book.
            
            ' Profile was not found.
            Exit Function
            
CATCH:
            
            Call Me.ThrowError("")
            
      End Function

Open in new window

0
 
doninjaCommented:
The first column is actually an accumilation of all the names used on any person document.
so it has their shortname, long name, and aliases etc.

It is a good source of finding a name no matter which format was entered.
The doc returned by .getdocumentbykey() will be the same no matter if you give short name, full name etc.

Press the refresh swirl in upper left to get a look at the views contents on the server.
0
 
jmlacosteAuthor Commented:
Greatt, even if we got misleaded in the beginning
Thanks a lot
0
 
Sjef BosmanGroupware ConsultantCommented:
... or open the hidden view in the Notes client (type and hold Ctrl-Shift, then click View/Goto)

I think the problem in your code is on line 4:
            Set db = session.Getdatabase("",notesBase,False)

When you change the "" in your server's name, you always take the server's N&A book (Name & Address book, or Domino Directory):
            Set db = session.Getdatabase("MyServer/ACME",notesBase,False)


PS
> I am not an experimented Domino user at all :p
1/ Mon oeil ;-)
2/ experienced
0
 
Sjef BosmanGroupware ConsultantCommented:
Hey, what did you do? What made you accept that specific answer, and not my first one??
0
 
jmlacosteAuthor Commented:
Hey  french bosman

Try the ($NamesFieldLookup) view...  
was your first response, and in the end my initial code is Looking in the ShortName column so I don't have to change anything in it!!!

I just learned what the Names column contains and what GetDocumentByKey is doing and that's what solved my problem.

We got lost because I didn't find the view you suggested when I was looking in a user names.nsf on the server and not the Server's Directory names.nsf, but again my code was great :-p so it's working no matter where I'm looking for my UserID

Thanks for your support though I know you've helped me in the past and I gave you some points for that so I don't feel too guilty on that one :)

0
 
Sjef BosmanGroupware ConsultantCommented:
Baffled... :-O

Which line in your original code did you change, and what is it now? Ref. ID:35482417
0
 
jmlacosteAuthor Commented:
I did not change anything my code isn't moving, it is just able to do something new (search by ShortName instead of Nmae) that I thought would require some development.

Ligne 39:
Set person = view.GetDocumentByKey(userID,False)

Open in new window

Where view is (server's directory)names.nsf>$users
And UserID was the Name and now I realise can also be the ShortName, that I pass as a parameter to my WebService to retrieve his/her personnal address book (via iNotes...)

Have we got communication problems here? :-p
I know I end up writing a lot more when I am too concise to start with
0
 
Sjef BosmanGroupware ConsultantCommented:
So you didn't have a problem with the code? It worked all along, and you didn't test it before you asked? So the real problem was your understanding of the code?

Mince...
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 12
  • 8
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now