Issues with Forall and user-defined type list

Hi,

My current issue with Lotusscript progamming is a broken Forall routine.

I want to create a type list with all unique items from two documents.

The user-defined type list works fine, but I am unable to loop through with a Forall loop (marked in the example code). I do not understand why…

Declarations

Type ItemsToCompare

varItemTestDocument As Variant

varItemReferenceDocument As Variant

End Type

Dim gTypeCompareItems List As ItemsToCompare 'Liste mit allen Feldern aus den beiden Vergleichsdokumenten

initialize

While Not docFromDocumentCollection Is Nothing

	Print "Prüfe Artikel " & docFromDocumentCollection.ItemManufacturerNumber(0) & " " & docFromDocumentCollection.ItemName3(0)

	Set docReference = viewDocReference.getdocumentbyKey(docFromDocumentCollection.ItemManufacturerNumber(0), True)

	If Not docReference Is Nothing Then 

		Print "Referenzartikel gefunden! " & docReference.ItemManufacturerNumber(0) & " " & docReference.ItemName3(0)

	End If

	Print "Anzahl Items Test / Referenzartikel: "  &  Cstr(Ubound(docFromDocumentCollection.Items) + 1) & " / " & Cstr(Ubound(docReference.Items) + 1)

	

	Call CreateTypeCompareItems(docFromDocumentCollection,docReference)

	Forall itemnames In gTypeCompareItems '/ THIS DOES NOT WORK!!!WHY???

		intNumberOfUniqueItems =  intNumberOfUniqueItems +1

	End Forall

	

	Print "Unique Items: " & intNumberOfUniqueItems

Sub CreateTypeCompareItems(docFromDocumentCollection As Notesdocument ,docReference As notesdocument)

Forall item In docFromDocumentCollection.items

	Set gTypeCompareItems(item.name).varItemTestDocument = item

End Forall

Forall item In docReference.items

	Set gTypeCompareItems(item.name).varItemReferenceDocument = item

End Forall

End Sub

Maybe there is something about itemnames like $UpdateBy…

I just do not get the number of unique items of both documents.

Thank you in advance.

Regards

ingo beyer

Subject: RE: Issues with Forall and user-defined type list.

I don’t understand why you think the problem is with Forall. Did you debug the code? Did you see how many items are in the list? You have to do these things. This is not Texas; you can’t just pick a culprit at random.

What exactly is the code doing wrong? What output do you get? How do you know that the output is wrong? Why are you guessing that the $UpdatedBy and so on are a problem? Why not put in code to look at the listtag of the iterator variable in Forall, and make sure what names it’s finding?

If all you want to do is count the unique field names, I don’t see why you need to record a whole structure for each name. Why not make it List As Integer and record the value 0?

The other thing to watch out for, is that you’re remembering the values of objects (NotesItems) whose parent objects (NotesDocuments) are going to be deleted from memory when you fetch the next pair of documents. When a NotesSomething is deleted from memory, its dependent objects are also deleted, and any variables that refer to them are changed to Nothing. So only one element of your list will contain anything at the end – all the others, both their members will be Nothing. This should not remove them from the list; they’re just useless records; so your count should still be fine. I just mention this because I assume you’re remembering all those NotesItem objects for a reason that will be important later.

I created a button with this code:

Type ItemsToCompare

varItemTestDocument As Variant

varItemReferenceDocument As Variant

End Type

Dim gTypeCompareItems List As ItemsToCompare

Sub Click(Source As Button)

Dim tmp As ItemsToCompare

Dim intNumberOfUniqueItems%

Dim wksp As New notesuiworkspace

Dim doc As NotesDocument

Dim session As New NotesSession

Dim db As notesdatabase

Set db = session.CurrentDatabase

Set doc = db.CreateDocument

Call wksp.CurrentDocument.Document.CopyAllItems(doc)

Dim items

items = doc.Items

Forall itum In items

	Set gTypeCompareItems(itum.name).varItemTestDocument = itum

End Forall

Dim strNames$

Delete doc ' just as an experiment

Forall peeque In gTypeCompareItems

	intNumberOfUniqueItems =  intNumberOfUniqueItems +1

	strNames = strNames & ", " & intNumberOfUniqueItems & ": " & Listtag(peeque)

End Forall

Msgbox intNumberOfUniqueItems & " items" & strNames, 0, "items contains " & (Ubound(items)+1) & " elements"	

End Sub

It works just fine for all items, including those that begin with “$”. The number of elements we count in the list equals the number that were in the Items array, and we can see the list of names.

Maybe something similar to this would help you resolve your mystery. If not, you could post again, but please refer to the C R I S P Y document first for additional debugging tips and suggestions what information to include in what you tell us.

  • Andre Guirard, IBM/Lotus Development

Useful blog: Best Practice Makes Perfect

Subject: RE: Issues with Forall and user-defined type list.

Hello.

Thank you VERY MUCH for your reply and your support. The last view days since my

post over here in Germany were holidays (at least in some

parts of the country)

As noted I refer to C R I S P Y / crispy.

Yes, debugged the code more than once.

In the Type list are approximately 75 item names with 2 items

“attached” to them.

The following part (complete code follows after the body of this post) make me headaches. For two reasons.

I am unable to access the items in my type list and I

am unable to loop through (e.g. for counting) Error messages

Call CreateTypeCompareItems(docFromDocumentCollection,docReference)

	Dim test As Variant

	test = gTypeCompareItems("ItemManufacturerNumber").varItemTestDocument

	'/ ERROR Variant does not contain an Object.... 

	Print  "test ="  test.value

	

	'/ NO ERROR THROWN, just walks over to the following Print statement. For loop not used

	'/ but in debugger is a Type  List with items visible.... 

	Forall itemnames In gTypeCompareItems

		intNumberOfUniqueItems =  intNumberOfUniqueItems +1

	End Forall

	

	Print "Unique Items: " & intNumberOfUniqueItems

What I want to do?

Problem:

Our colleques changed there article exports without testing.

Now, our Domino based shop has problem to import the items.

It is a total mess. Fortunately we have an old import as reference.

My Assumptions/What I want to do?

I want to compare the new an the old imports. At first pretty superficial (compare number of fields)

and refine it step by step (name of the fields, field values etc.)

As expected,. we are a little bit under pressure.

At first I count the number of fields on the new imported articles and the same old article (if there is one)

After this I want to create a unique list of related items from the old and the new articles.

For comparision I have to loop my type list only once and can check for differences.

Because field names and number and values may be different, I think, the other way is to check based

on both documents (e.g. walk through the new and old document)

Questions / Hints

"Why are you guessing that the $UpdatedBy and so on are a problem? "

Hm, I thought to access an item like $UpdatedBy in extended script you have to use doc.~$UpdatedBy(0) instead of doc.$UpdatedBy(0).

This might be false remembrance. I will check asap… In my hurry, I thought this might be an issue for the loop.

"The other thing to watch out for, is that you’re remembering the values of objects (NotesItems) whose

parent objects (NotesDocuments) are going to be deleted from memory when you fetch the next pair of documents."

As you can see in the complete code I do not delete any document or item. My debugger shows all elements before and after

the loop.

So, thank you for your patience. Next I will try your code example… My complete starting code follows

Best regards

-ingo

'/ Sorry, Comments are in German. I think the code is pretty simple…

'PriamosArtikelvergleich:

Option Public

Option Declare

Type ItemsToCompare

varItemTestDocument As Variant

varItemReferenceDocument As Variant

End Type

Dim gTypeCompareItems List As ItemsToCompare 'Liste mit allen Feldern aus den beiden Vergleichsdokumenten

Sub Initialize

On Error Goto Errorhandler

Dim session As New NotesSession '/ aktuelle Session

Dim dbTest As NotesDatabase '/ aktuelle Datenbank mit den Artikeln, die zu vergleichen sind

Dim dbReference As NotesDatabase '/ Referenzdatenbank mit den Originalartikeln

Dim colSelectedDocuments As NotesDocumentCollection '/ Ausgewählte Artikel

Dim docFromDocumentCollection As NotesDocument '/ aktuelles Dokument aus der Auswahl

Dim docReference As NotesDocument '/ Referenzartikeldokument 

Dim viewDocReference As NotesView '/ Ansicht um die Referenzaritkeldokumente zu finden... 

Dim strMessage As String '/ Auswertungsergebnis

Dim varAllitemsReference '/ Alle Items (Array) des Referenzdokuments

Dim varAllItemsTest '/ Alle Items (Array) des Testdokuments

Dim varArrayIndex As Variant '/ Indexzahl im array

Dim gTypeCompareItems List As ItemsToCompare  'Liste mit allen Feldern aus den beiden Vergleichsdokumenten

Dim intNumberOfUniqueItems As Integer



Set dbTest = session.Currentdatabase

Set dbReference = session.getdatabase("LNSSHOP2/DSVShopTest/DE", "shop\priamos\test\referenzProduktion\prod.nsf")

Set viewDocReference = dbReference.GetView("vItemsBGArtikelNumber")

Set colSelectedDocuments= dbTest.UnprocessedDocuments

Print "Arikel ausgewählt: "  & colSelectedDocuments.Count



Set docFromDocumentCollection = colSelectedDocuments.getfirstDocument

While Not docFromDocumentCollection Is Nothing

	Print "Prüfe Artikel " & docFromDocumentCollection.ItemManufacturerNumber(0) & " " & docFromDocumentCollection.ItemName3(0)

	Set docReference = viewDocReference.getdocumentbyKey(docFromDocumentCollection.ItemManufacturerNumber(0), True)

	If Not docReference Is Nothing Then 

		Print "Referenzartikel gefunden! " & docReference.ItemManufacturerNumber(0) & " " & docReference.ItemName3(0)

	End If

	Print "Anzahl Items Test / Referenzartikel: "  &  Cstr(Ubound(docFromDocumentCollection.Items) + 1) & " / " & Cstr(Ubound(docReference.Items) + 1)

	

	Call CreateTypeCompareItems(docFromDocumentCollection,docReference)

	Dim test As Variant

	test = gTypeCompareItems("ItemManufacturerNumber").varItemTestDocument

	'/ ERROR Variant does not contain an Object.... 

	Print  "test ="  test.value

	

	'/ NO ERROR THROWN, just walks over to the following Print statement. For loop not used

	'/ but in debugger is a Type  List with items visible.... 

	Forall itemnames In gTypeCompareItems

		intNumberOfUniqueItems =  intNumberOfUniqueItems +1

	End Forall

	

	Print "Unique Items: " & intNumberOfUniqueItems

	

	

	

	

	

	Set docFromDocumentCollection = colSelectedDocuments.getnextdocument(docFromDocumentCollection)

Wend

Finish:

Exit Sub

Errorhandler:

Print Error &  " in " & Erl

Resume Finish

End Sub

Sub CreateTypeCompareItems(docFromDocumentCollection As Notesdocument ,docReference As notesdocument)

Forall item In docFromDocumentCollection.items

	Set gTypeCompareItems(item.name).varItemTestDocument = item

End Forall

Forall item In docReference.items

	Set gTypeCompareItems(item.name).varItemReferenceDocument = item

End Forall

End Sub

Subject: Issues with Forall and user-defined type list.SOLUTION

at least for now!

gTypeCompareItems was declared twice. Once unter the Globals and once in the initialize.

So I had the same variable twice and the script used local variable first.

Thank you!

-i