Looping LotusScript Lists
LotusScript Lists are handy, but, if you've not used them for donkey's years and have completely forgotten how they work, then finding a refresher example can be hard.
I was in this position last week. I knew a List was the solution I needed, but could I find a decent reference on their use? Nope!
So, for my own benefit as much as future Googlers, here's a quick guide to the key principles involved in using them:
Dim Groups List As String Dim key As String, value As String Set doc = collection.GetFirstDocument() While Not(doc Is Nothing) If Not IsElement(Groups(doc.GroupUNID(0))) Then Groups(doc.GroupUNID(0)) = doc.GroupName(0) End if Set doc = collection.GetNextDocument(doc) Wend 'Now - here's how to loop through the List! ForAll Group In Groups key = ListTag(Group) 'UNID value = Groups(ListTag(Group)) 'Name Print key + " = " + value End ForAll
Might seem like an odd piece of code, but it's what I needed to do -- build a unique list of groups linked to a collection of Notes document and then for each of the groups do some other logic. Don't ask.
You can also access the value directly from the var in your For statement:
ForAll Group in Groups
value = Group
your value might be a number, String, or some object, whatever. So if your Group was an object, I "cast" the variable, so I have access to the type ahead, e.g.
dim myGroup as GroupObject
ForAll Group in Groups
myGroup = Group
int = myGroup.getGroupReductionRate()
See ya,
Nick
Reply
Aha. That explains why I had an issue at first. In my actual code I was trying to use "Group" like a string but it wasn't working. Didn't know about casting. Thanks for adding this tip to my future reference. Although, I'm always hopeful I have a future free of lotusscript...
Reply
You can also make lists of documents:
Dim Groups List as NotesDocument
...
Set Groups(doc.GroupUNID(0)) = doc
...
ForAll Group In Groups
'Now Group is a NotesDocument
value = Group.GroupName(0) 'or whatever
etc.
Btw, I think it's good practice to always end the script with the Erase statement.
Reply
Careful with this, as you run the risk of running out of document handles, depending on how large your database is.
If you want to collect Documents based on a criteria, use a DocumentCollection (via Call notesDocumentCollection.AddDocument( document [, checkDups ] ) ), that's what it's for.
If you just wanted the GroupName, just get that right away :)
Reply
I blogged about this a while back:
http://www.bleedyellow.com/blogs/texasswede/entry/lists_the_forgotten_gem_in
and
http://www.bleedyellow.com/blogs/texasswede/entry/more_fun_with_lists2
I also wrote an article for The View back in the December 2006 issue about lists. Lists are very powerful, and way too few programmers use them.
Reply
The flexibility that lists provide in Notes is amazing. I'm constantly frustrated when working in other languages and I have one of those 'if only I could use a list' moments!
Reply
Which language are you talking about? :-)
It seems to me that the LotusScript "lists" are just hashtables, which is a feature found in most modern programming languages.
Reply
I'm into performance every time I write code...
Instead of getting the values using the . notation, I would use the getitemvalue method. (kept me away of nasty issues when there are field names the same as a property of the notesdocument objects.
Also, there are cases in which there are lots of documents, in that case there may be helpful to store a temporary value of the key field value (in this case, there would be less requests to field values from document)
something like
dim vTmp as Variant
While Not(doc Is Nothing)
vTmp = doc.getitemvalue("GroupUNID")(0)
If Not IsElement(Groups(vTmp)) Then
Groups(vTmp) = doc.getitemvalue("GroupName")(0)
End if
Set doc = collection.GetNextDocument(doc)
Wend
Reply
I lurrve Lists. Lurrrrrve them. Especially combined with user types or classes, and ForAll loops
In Java, the closest I could find were Hashsets, although they still confuse me (especially when viewed in the debugger)
Reply
In Java, you can use a HashMap:
http://download.oracle.com/javase/1.4.2/docs/api/java/util/AbstractMap.html
HashMaps are "regular" LS Lists, while TreeMaps are sorted.
So you can use:
Map<String,Document> docs = new HashMap<String, Document>();
(to store Notes documents), or:
Map<String,Document> docs = new TreeMap<String, Document>();
to have them sorted.
It's not wise to store Notes Documents without recycling them, though, so don't do that.
If you were using Groovy, then you could simply do:
def docs = [:]
docs[doc.getUniversalId()] = doc
Reply
My latest use case for lists in LotusScript has been a home-grown "replication" mechanism between Notes and Oracle.
Each document holds the key and a hash (created by Oracle). In a first step, I populate a list of a custom data type (for key and hash) from all Notes documents.
While navigating through the Oracle result set, I delete each element from the list, where key and hash do match.
If the hash does not match, I update the document.
If the key is not in the list, I create a new document.
Finally, every element still found in the list after looping through the result set, must refer to a document, that no longer has a corresponding record in Oracle, so it gets marked for deletion.
Works like a charm and it's fast! Comparing 70000+ documents and records takes between 30 and 60 seconds, mainly depending on network traffic. I love lists.
Reply
The gift that just keeps on giving!
Thank you, that is exactly my situation. I haven't used lists in a decade.
Reply