Das Notes Forum

Domino 9 und frühere Versionen => ND6: Entwicklung => Thema gestartet von: DaWutz am 01.03.05 - 18:33:47

Titel: [LotusScript] Type Mismatch
Beitrag von: DaWutz am 01.03.05 - 18:33:47
In einem Agenten zum kopieren von Dokumenten von einer DB in einer andere bekomme ich eine Fehlermeldung "Type Mismatch".

Im Debugger kann ich nun sehen, dass das Feld das ich auslese (Categories) vom Value her Variant ist, der Wert Categories[0] aber vom Typ String. Aus dem [] schliesse ich, das das aber doch ein Array ist, oder?

Wie bringe ich ihn den nun dazu, den Wert einfach so zu splitten, wie ich das gerne hätte?

Code:
Sub Initialize
   Dim session As New NotesSession
   Dim SourceDB As NotesDatabase
   Dim DestinationDB As NotesDatabase
   Dim coll As NotesDocumentCollection
   Dim docOld As NotesDocument
   Dim docNew As NotesDocument
   Dim counter As Integer
   Dim splitPart1 As String
   Dim splitPart2 As String
   
   Set SourceDB = session.CurrentDatabase
   Set DestinationDB = session.GetDatabase(SourceDB.Server,"IT\it-kb.nsf")
   
   Set coll = SourceDB.UnprocessedDocuments
   Set docOld = coll.GetFirstDocument()   
   counter = 0
   
   Do While Not docOld Is Nothing
      Set docNew = New NotesDocument(DestinationDB)
      docNew.Form = "Documentation"
      docNew.Title = docOld.Subject
      docNew.CreatedBy = docOld.From
      docNew.CreatedOn = docOld.Date
      docNew.Content = docOld.Body
      splitPart1 = Strtoken(docOld.Categories, "/", 1 , 5)
      splitPart2 = Strtoken(docOld.Categories, "/", 2 , 5)
      docNew.Category = splitPart1
      docNew.SubCategory = splitPart2
      
      Call docNew.Save(True,True)
      Set docOld= coll.GetNextDocument(docOld)
      counter = counter + 1
   Loop
   Msgbox( counter & " Dateien kopiert!")
   
End Sub
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: koehlerbv am 01.03.05 - 18:37:28
Irgendwie fehlt hier noch massgeblicher Code und die Angabe, in welcher Zeile es knallt.

Und: Wenn du "Categories [ 0]" siehst, ist es ein Array.

Bernhard
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: TMC am 01.03.05 - 18:38:20
Du schreibst leider nicht, in welcher Zeile der Fehler auftritt.

Aber StrToken (also @Word in LS) erwartet ein String.

docOld.Categories (als Kurzform von docOld.GetItemValue("Categories")) ist aber immer ein Array. Ich schätze also, dass das der Grund ist.
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: koehlerbv am 01.03.05 - 18:48:19
Matthias, Du hast wahr, und ich habe Blödsinn geschrieben (abgesehen davon, dass die Angabe der explosiven Zeile mir abging).

Bernhard
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: DaWutz am 01.03.05 - 18:50:44
Hallo zusammen,

also, die Zeile ist (natürlich) eben jene die Matthias identifiziert hat. Ich dachte meine Ausführung auf eben jenes Item würde das schon "erschlagen".
Viel mehr Code existiert in dem Agenten bis jetzt auch nicht, ausser halt den Deklarationen usw..

Das mit dem splitten habe ich nun so gelöst, das ich ihn einfach den ersten Wert des Arrays, also Categories(0), nehmen lasse.

Genau:
      splitPart1 = Strtoken(docOld.Categories(0), "\", 1)
      splitPart2 = Strtoken(docOld.Categories(0), "\", 2)
      If splitPart2 = "" Then
         splitPart2 = splitPart1
         splitPart1 = "!! Kontrollieren !!"
      End If
      docNew.Category = splitPart1
      docNew.SubCategory = splitPart2

Warum ist das aber ein Array, der da ankommt? Ich weiß nu wie´s gemacht wird, aber ich verstehe nicht, warum.

Danke auch schonmal für die wirklich prompten Antworten!!

PS:
Der nächste Böller kommt aber noch, denn ich muss ihn noch dazu bringen auch Attachments mitzuschleppen, aber das schaffe ich auch noch...  ;)
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: TMC am 01.03.05 - 19:04:27
Warum ist das aber ein Array, der da ankommt? Ich weiß nu wie´s gemacht wird, aber ich verstehe nicht, warum.

Liest Du per LotusScript mit der GetItemValue - Methode ein Item aus, so bekommst Du IMMER ein Array. Auch wenn das Item ein SingleValue-Feld ist.
Das ist definiert in der NotesDocument-Klasse.
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: koehlerbv am 01.03.05 - 19:08:06
Jo, jedes NotesItem ist par definitionem ein Array, wenn es (im Backend) ausgelesen wird. Weil: Es könnte ja eines sein. Es wäre ja andererseits übel, wenn Du bei jedem Zugriff selber prüfen müsstest: "Was habe ich jetzt bekommen ?".

Auch "andersherum" macht das Sinn: Du definierst in einer Maske ein Feld als "Text", "Mehrfachwerte zulassen" ist nicht erlaubt.
Was Dich (oder andere) nicht hindern würde, dort im backend ein Array 'reinzuschreiben  ;D

Wenn Dui da noch Fragen hast, stelle sie: Das sind Dinge, die anfangs übel verwirren könne, bis sie dann doch ganz klar erscheinen.

Bernhard
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: Marinero Atlántico am 01.03.05 - 19:13:14
es gibt allerdings die leicht kryptische Abkürzung:
doc.getItemValue("feldName")(0)
Durch die (0) am Ende kommt der erste Wert zurück.
Kann den code übersichtlicher machen, wenn man sicher weiss, dass man es hier sowieso mit Einfach-Werte-Feldern zu tun hat. Was oft der Fall ist.
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: koehlerbv am 01.03.05 - 19:16:18
Naja, Axel, das hat Daniel ja schon gemacht  ;)

Bernhard
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: TMC am 01.03.05 - 19:20:22
Und noch zur Ergänzung:
Wenn Du per Script auf Felder zugreifst (also über Frontend-Klassen), bekommst Du Strings (völlig egal, ob das Feld auf 'Mehrfachwerte' etc. eingestellt ist).
Wenn Du auf Itemebene (also Backend-Dokumentenseitig) zugreifst, bekommst Du immer ein Array - auch wenn das ursprünglich zugrunde liegende Feld z.B. vom Typ "Zahl, ohne Mehrfachwerte" war.

Ich würde immer doc.GetItemValue nehmen, und die "Extended class" Syntax (doc.Itemname) mir gar nicht erst angewöhnen, auch wenn es bequemer erscheint.
Grund:
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: koehlerbv am 01.03.05 - 19:37:55
Und noch zur Ergänzung:
Ich würde immer doc.GetItemValue nehmen, und die "Extended class" Syntax (doc.Itemname) mir gar nicht erst angewöhnen, auch wenn es bequemer erscheint.
Grund:
  • Performanceeinbußen (soll massiv sein, hab ich zumindest mal gelesen, leider keine Quelle mehr parat)
  • Probleme, wenn der Itemname = einer Notes-internen Bezeichnung entspricht
  • Du kannst den Itemnamen auch als String (Variable oder Konstante) übergeben.

Dazu folgende Anmerkungen:
- Die Quelle würde mich auch interssieren !
- NotesItem = Intern verwendete Konstante: Das sollte man sowieso und immer vermeiden.
- Itemname als Variable: Jo, das hat was.

Wegen den Performance-Einbrüchen: Da der Zugiff auf Items von Dokumenten ja immer das Lesen von Platte bedeutet, ist diese Umsetzung (die sowieso schnell bei der selben API-Routine wie GetItemValue landen wird) im RAM eine vernachlässigbare Grösse. Ich habe dazu (als das auch hier im Forum schon mal hochkochte) mal Tests gemacht: Die Ergebnisse waren nicht signifikant (mal war das eine etwas (!) schneller, mal das andere. Und da ging es um Zugiffe auf Items aus > 50.000 Docs.

Bernhard

EDIT: Es sei aber auch darauf hingewiesen, dass von Lotus / IBM gelieferte Schablonen in der Regel mit GetItemValue etc. hantieren und nicht mit der Kurznotation.
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: TMC am 01.03.05 - 19:53:14
- NotesItem = Intern verwendete Konstante: Das sollte man sowieso und immer vermeiden.

Ich denke Du meinst NotesItemName. Unter manchen Umständen kann das durchaus praktikabel sein, den Namen eines Items als Konstante zu definieren, z.B. innerhalb einer ScriptLibrary, die z.B. auf (Teil-)Masken verweist, welche immer wiederkehrende Items enthält (Lösch-Flag, Historie, etc. etc.). Sollte sich der Itemname ändern: -> Anpassung an 1 zentralen Stelle.

Ich muss nochmal wühlen bezügl. des Performance-Problems. Aber der Artikel den ich dazu mal gelesen hatte, klang sehr überzeugend. Es ging speziell um das Auflösen (Also die Abfrage: "ist das nun ein Itemname oder passiert da was mit einer Methode/Property. Wenn Itemname, dann kippen wir das ganze mal in GetItemValue").

Erwähnenswert für DaWutz ist auch noch in dem Kontext, dass bei Itemnamen, die ein vorangestelltes $ haben (z.B. $REF), ein ~ vorangestellt werden muss bei der Extended Class Syntax (z.B. doc.~$REF).
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: Marinero Atlántico am 01.03.05 - 20:06:01
Bzgl. der Performance stimme ich mit Bernhard überein.
Die Literatur rät dazu, dass Performance-Optimierungen immer auf ein Ziel hin gerichtet sein sollen.
Also für Notes: Das Querysave dieser Maske darf auf der und der Standardhardware nicht länger als sagen wir 0.5 Sek. dauern. Wenn ja, muss optimiert werden.
Hier nicht unbedingt aber performance-optimierter code kann schnell auch gleichzeitig nicht so übersichtlicher code sein. Und man sollte nur dort optimieren, wo es einen Mehrwert für den Anwender verspricht.
Ob ein Skript jetzt 0.680 oder 0.681 sek dauert, ist nicht so interessant.

Aber - wie Mathias schon im Kontext von "Konstante" angedeutet hat - hat getItemValue den Vorteil, dass es parametrisierbarer ist. Ich benutz das oft, wenn es darum geht eine Reihe von Feldern eines docs zugreifen muss. Nur dann schreib ich es in einen Array und tue diesen nach oben im Skript.
Es gibt auch manchmal Situationen, wo man diese Feldnamen sinnvoll in ein externes Konfigurationsdokument externalisieren kann. Nur kann man es damit auch übertreiben.
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: TMC am 01.03.05 - 20:30:50
Bzgl. der Performance stimme ich mit Bernhard überein.
Die Literatur rät dazu, dass Performance-Optimierungen immer auf ein Ziel hin gerichtet sein sollen.
Also für Notes: Das Querysave dieser Maske darf auf der und der Standardhardware nicht länger als sagen wir 0.5 Sek. dauern. Wenn ja, muss optimiert werden.
Hier nicht unbedingt aber performance-optimierter code kann schnell auch gleichzeitig nicht so übersichtlicher code sein. Und man sollte nur dort optimieren, wo es einen Mehrwert für den Anwender verspricht.
Ob ein Skript jetzt 0.680 oder 0.681 sek dauert, ist nicht so interessant.

Guter Einwand, Axel.
Zumal ich ja auch sehr oft die Extended Class Syntax verwende  :P
Aber ich will DaWutz gleich mal in die richtige Richtung weisen, sonst haben wir noch morgen einen Thread von ihm, warum {doc.Authors = "Hans Huber/Org"} nicht funktioniert  ;D

Den Artikel hab ich leider jetzt nicht gefunden, aber der Performance-Einbruch klang bemerkenswert.

Feldnamen in Konfig-Dokumenten: Wenn dann nur vorgegeben: nicht änderbare Liste mit festen Vorgabewerten. Keinesfalls sollte man das frei definierbar machen, da IMHO Konfig-Doks nicht für Entwickler, sondern für Admins und/oder Endanwender sind. Da würde ich allerhöchstens auswählen lassen: Schreibe XY in Item A oder Item B.
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: Glombi am 01.03.05 - 20:38:28
Leider finde ich den Artikel auch nicht, aber ich kann mich erinnern, dass die Performance der Extended Class Syntax signifikant schlechter ist.

Im net habe ich das hier bei der ersten Suche gefunden:
http://www.martinscott.com/home.nsf/0/C7F5B845A9E6C76385256C180007FBEF?opendocument

einiges davon stammt wohl hieraus:
http://www-12.lotus.com/ldd/doc/bp/46bpg.nsf/

Bemerkenswert u.a.:
Using the ColumnValues property is about 10 percent faster than getting a handle to a document and using the extended class syntax-- e.g., x=doc.fieldname.


Andreas
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: koehlerbv am 01.03.05 - 20:53:19
Leider finde ich den Artikel auch nicht, aber ich kann mich erinnern, dass die Performance der Extended Class Syntax signifikant schlechter ist.

Komisch, keiner findet den Artikel  ;D

Bemerkenswert u.a.:
Using the ColumnValues property is about 10 percent faster than getting a handle to a document and using the extended class syntax-- e.g., x=doc.fieldname.

Bemerkenswert finde ich hier eher die Aussage, dass der Zugriff via ColumnValues nur 10% schneller sein soll, als das Dokument selber auszulesen - immerhin greift man hier auf den ViewIndex zu. Auch mit dieser Aussage wäre ich vorsichtig.

Das wäre was für einen BP-Artikel. In das Thema Massendatenverarbeitung spielt ja noch viel mehr hinein. Wenn es nur um ein Dokument geht, lohnt wegen Millionstel Sekunden die Diskussion sowieso nicht.

Bernhard
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: Marinero Atlántico am 01.03.05 - 21:10:27
Bemerkenswert u.a.:
Using the ColumnValues property is about 10 percent faster than getting a handle to a document and using the extended class syntax-- e.g., x=doc.fieldname.

Fragt sich natürlich 10% von was.
Wenn in einem Skript die Zugriffe auf Items insgesamt nur 10% der Zeit ausmachen, ist der Performance-Gewinn insgesamt nur ungefähr 1%.
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: TMC am 01.03.05 - 21:17:32
Gesucht, und was gefunden, meinte aber einen anderen Artikel.

Code
Although we prefer to use the "GetItemValue" method of the NotesDocument object to retrieve a field value, we know that many developers prefer to use the extended syntax to retrieve a field value. If you aren't familiar with the extended syntax, these two statements are equivalent:
result = doc.GetItemValue("MyField")(0)
result = doc.MyField(0)

The true difference between the above statements is performance. The first line will be slightly faster than the second line. In the first line, the LotusScript interpreter knows that "GetItemValue" is a method so it immediately finds the method and runs it. The second line looks to the interpreter like a property, so it tries to find the property. When that isn't found, it says, "oh, it must be a field" and then finds the field. So the first statement is just a little faster. One trial we did ended up with a 4% time savings, but that's not the point of this tip.

If you still would like to use the extended syntax, and have a need to access some reserved fields (like $UpdatedBy or $Ref), if you try to put this statement in your script:
result = doc.$UpdatedBy(0)
The compiler will immediately give you an error:
Unexpected: $UpdatedBy; Expected: Identifier

To access a reserved field with the extended syntax, there's a little trick you can use:
result = doc.~$UpdatedBy(0)

The tilde character in front of the dollar sign satisfies the compiler and the interpreter knows to ignore that tilde when it's going through the code. So it gets the "$UpdatedBy" field off the document.

Quelle: http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256BD6004B7868

BreakingPar meint: 4%.
Meist also zu vernachlässigen.

Aber aufgrund o.g. Vorteile von GetItemValue IMHO ein kleiner weiterer Grund, GetItemValue immer auszuschreiben. Geht ja auch um Pflege des Codes. Was, wenn sich doch z.B. der Itemname von "Autoren" auf "Authors" ändert? Bei konsequent verwendetem GetItemValue 2 Mausklicks (Suchen/Ersetzen), bei Extended Class Syntax: u.U. sehr viel zu tun. Natürlich sollte man "Authors" eh nicht als Itemname nehmen.
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: Glombi am 01.03.05 - 21:24:02
Fragt sich natürlich 10% von was.
Von der Zeit denke ich  ;)

Zitat
Natürlich sollte man "Authors" eh nicht als Itemname nehmen.
Warum nicht? Nur interesse halber.

Natürlich sollte man in R5 auch kein Feld Lock nennen  ;D
Tja leider kann man nicht in die Zukunft blicken. Was IBM da so veranstaltet mit reservierten Feldnamen, die kein $$ vorangestellt haben, ist schon sehr nachlässig wenn nicht fahrlässig.

Andreas
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: TMC am 01.03.05 - 21:32:03
Da hast Du Recht Andreas: Warum nicht? Eben da Authors auch gleichzeitig eine Property von NotesDocument ist  :P

Schwierig abzuschätzen, welche internen Bezeichnungen IBM in der Zukunft noch einsetzen wird.

Also noch ein Grund für GetItemValue, eben um sicher zu gehen.  :)
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: DaWutz am 02.03.05 - 18:13:09
Ich nochmal...  ;)

ich hab mein Problem jetzt soweit gelöst, Code steht unten, ABER ich habe es nicht hinbekommen, das ich nur das Richtextfeld Body aus dem alten Dok bekommen habe, sondern ich musste (aus Unkenntnis wie anders) das ganze alte Doc in das "Content"-Feld der neuen DB hauen. Damit habe ich zwar alles erschlagen, alle Attachments, allen Text usw., aber wirklich befriedigen tut mich dieser Weg nicht. Zum einen hab ich nu viel Müll im Content-Feld, zum anderen hat das kopieren bei 360 Docs mal knappe 4 Min gedauert - performant ist also was anderes... (oder irre ich mich da)

Wie müsste ich vorgehen, wenn ich wirklich nur das komplette RT-Feld Body (mit allen Attachments, Text, etc.) in das neue RT-Feld kopieren wollte?

Mein Code:

Dim...

Set SourceDB = session.CurrentDatabase
   Set DestinationDB = session.GetDatabase(SourceDB.Server,"IT\it-kb.nsf")
   Set coll = SourceDB.UnprocessedDocuments
   Set docOld = coll.GetFirstDocument()   
   counter = 0
   
   Do While Not docOld Is Nothing
      Set docNew = New NotesDocument(DestinationDB)
      
      docNew.Form = "Documentation"
      docNew.Title = docOld.Subject
      docNew.CreatedBy = docOld.From
      docNew.CreatedOn = docOld.Date
      docNew.LastModifiedBy = docOld.LastEditor
      
      Set rtitem = New NotesRichTextItem(docNew,"Content")
      Call docOld.RenderToRTItem(rtitem)
      
      splitPart1 = Strtoken(docOld.getItemValue("Categories")(0), "\", 1)
      splitPart2 = Strtoken(docOld.getItemValue("Categories")(0), "\", 2)
      If splitPart2 = "" Then
         splitPart2 = splitPart1
         splitPart1 = "!! Kontrollieren !!"
      End If
      docNew.Category = splitPart1
      docNew.SubCategory = splitPart2
      
      Call docNew.Save(True,True)
      Set docOld= coll.GetNextDocument(docOld)
      counter = counter + 1
   Loop
   Msgbox( counter & " Dateien kopiert!")
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: koehlerbv am 02.03.05 - 18:25:16
Warum verwendest Du nicht NotesItem.CopyItemToDocument ? Das zieht Dir auch Anhänge mit etc.

Bernhard
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: DaWutz am 02.03.05 - 18:33:00
Hmm... weil ich nur die Methoden copyItem und copyAllItems finde.

Und mit copyItem habe ich es versucht, aber dann habe ich das zwar kompilieren können, aber die Content Felder waren einfach immer leer.  :(

Deshalb ja diese "um die Ecke"-Lösung...
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: koehlerbv am 02.03.05 - 18:40:36
Daniel, hallo ! Lesen ! Von welcher Klasse und Methode habe ich gesprochen ? Was Du erwähnst, ist doch was völlig anderes (was natürlich auch nicht das von Dir gewünschte Resultat bringen kann).

Bernhard
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: DaWutz am 02.03.05 - 18:49:23
Aua...

ja, da fällt es mir wie Schuppen aus den Haaren... ich war so vernagelt auf das NotesDocument.  :P

Aber nun... Hmmm - ok, das werde ich nachher daheim gleich mal probieren - nu gehts erstmal heimwärts.

Danke!  :D
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: koehlerbv am 02.03.05 - 18:58:01
Gern geschehen, Daniel  ;)

Mit der Erfahrung sinkt auch die Zahl solcher Fehler - aber nie die generelle Möglichkeit, verbohrt auf der falschen Schiene zu fahren (dann eben auf "höherem Niveau). Ich kann das also lebhaft nachvollziehen.

Good luck,

Bernhard
Titel: Re: [LotusScript] Type Mismatch
Beitrag von: DaWutz am 03.03.05 - 13:30:59
Ich mal wieder...  ::)

Also nu hab ich das ganze so hinbekommen wie es sich wohl eigentlich gehört. 2 simple Zeilen, und daran habe ich nun ewig rumgedoktort. Aber mit dem Schubs in die richtige Richtung war´s dann kein Problem mehr!  ;D

Danke Bernhard!
(und auch allen anderen die sich beteiligt haben!)

PS: hier auch die "Lösung" meines Problems

...
   Set bodyOld = docOld.GetFirstItem( "Body" )
   Call bodyOld.CopyItemToDocument( docNew, "Content" )
...