Das Notes Forum

Domino 9 und frühere Versionen => ND8: Entwicklung => Thema gestartet von: ThomasHB am 07.02.11 - 12:08:39

Titel: Historie anlegen
Beitrag von: ThomasHB am 07.02.11 - 12:08:39
Hallo Zusammen,

wir würden gerne innerhalb einer Notes DB / Anwendung etwas einführen, das man als Historie sehen kann. Und zwar geht es im konkreten Fall um Hardware. Wer hatte welche Hardware, wann zugewiesen... Also ab welchem Datum.

Da Notes nicht relational ist, hatte ich folgende Überlegung, die ich einfach mal versucht habe umzusetzen... Und zwar dafür ein neues Form zu nehmen, welches Ref die DocUniqueID erhält.
Für jede Änderung wird ein neues Dokument angelegt, mit der ID als Referenz.

Dazu habe ich ins PostSave folgenden Code gebaut:

Code
Sub Postsave(Source As Notesuidocument)
	Dim DocUnID As NotesItem
	Dim person As NotesItem
	Dim Datum As NotesDateTime
	Dim v As NotesView
	Dim s As New NotesSession
	Dim doc As NotesDocument
	Dim db As NotesDatabase
	Dim doc2 As NotesDocument
	Dim composed1, composed2 As String
	
	composed1 = Source.FieldGetText("DocUnID")
	composed2 = Source.FieldGetText("person")
	Set db = s.CurrentDatabase
	Set v = db.GetView("nHist_Hardware")
	Set doc = v.GetFirstDocument
	Set Datum = doc.GetItemValue("HistHW_Datum")
	Set doc2 = New NotesDocument(db)
	
	While Not (doc Is Nothing)
		If composed1 = doc.GetItemValue("HistHW_DocUnID") And Not Today() = Datum.DateOnly Then
			Call doc2.AppendItemValue("HistHW_DocUnID", composed1)
			Call doc2.AppendItemValue("HistHW_Name", composed2)
			Call doc2.AppendItemValue("HistHW_Datum", Today())			
		End If
	Wend
End Sub

Das Programm hängt sich allerdings, immer wieder hier auf:
Code
Set Datum = doc.GetItemValue("HistHW_Datum")

Die Meldung ist Type Mismatch.

Nur verstehe ich den Grund nicht, mal abgesehehn davon, der Code vermutlich auch noch weiter fehlerhaft ist... Das Feld was abgefragt wird, ist ein Datumsfeld... Und Datum ist auch als NotesDateTime deklariert...

Hat da jemand eine Idee?
Das ist ein Punkt, da komme ich nicht weiter.

Falls jemand weitere Fehler sieht, bitte NICHT nennen.
Ein Satz wie, da sind weitere Fehler drin ist ok, aber bennent diese mal nicht.
Ich will das schon selber rauskriegen. Im Zweifel kann ich ja dann noch mal fragen.
Nur will ich versuchen meine Entwicklerfähigkeiten aufzubessern.

Nur bei dieser Datumssache da komme ich nicht dahinter...

Viele Grüße,
Thomas
Titel: Re: Historie anlegen
Beitrag von: ascabg am 07.02.11 - 12:10:50
Hallo,

Weil Dir doc.GetItemValue("HistHW_Datum") einen Array zurueckliefert.

Versuch mal folgendes

Dim varDatumswerte As Variant

varDatumswerte = doc.GetItemValue("HistHW_Datum")

oder

Set Datum = doc.GetFirstItem("HistHW_Datum")


Andreas
Titel: Re: Historie anlegen
Beitrag von: koehlerbv am 07.02.11 - 12:19:10
Kein Fehler im eigentlichen Sinne, aber eine grosse Unsauberkeit, die man sich gar nicht erst angewöhnen sollte:
Code
Dim composed1, composed2 As String

composed1 wird hier nicht explizit deklariert und wird daher Variant gesehen. Korrekt wäre
Dim composed1 As String, composed2 As String

Bernhard
Titel: Re: Historie anlegen
Beitrag von: ThomasHB am 07.02.11 - 14:27:15
Hallo,

super vielen Dank für die Hilfe...

@Andreas

Set Datum = wurde schon während der Code Eingabe rot hinterlegt mit dem Hinweis Type Mismatch. Mit der zweiten Möglichkeit hat es jetzt geklappt.

@Bernhard

Danke für die Info... Aber ich könnte schwöre, das ich genau diese Schreibweise aus der Designerhelp habe...

Der Code schaut jetzt so aus, funktioniert.
Ist trotzdem irgendwo noch was faul bzw. eine Unsauberkeit?

Code
Sub Postsave(Source As Notesuidocument)
	Dim DocUnID As NotesItem
	Dim person As NotesItem
	Dim Datum As Variant
	Dim v As NotesView
	Dim s As New NotesSession
	Dim doc As NotesDocument
	Dim db As NotesDatabase
	Dim doc2 As NotesDocument
	Dim composed1 As String, composed2 As String
	
	composed1 = Source.FieldGetText("DocUnID")
	composed2 = Source.FieldGetText("person")
	Set db = s.CurrentDatabase
	Set v = db.GetView("nHist_Hardware")
	Set doc = v.GetFirstDocument
	Datum = doc.GetItemValue("HistHW_Datum")
	Set doc2 = New NotesDocument(db)
	While Not (doc Is Nothing)
		If composed1 = doc.GetItemValue("HistHW_DocUnID")(0) And composed2 <> doc.GetItemValue("HistHW_Name")(0) Then
			Call doc2.AppendItemValue("Form", "Hardware_Historisierung")
			Call doc2.AppendItemValue("HistHW_DocUnID", composed1)
			Call doc2.AppendItemValue("HistHW_Name", composed2)
			Call doc2.AppendItemValue("HistHW_Datum", Today())	
			Call doc2.Save(0,0)
		End If
		Set doc = v.GetNextDocument(doc)
	Wend
End Sub

Danke.

Grüße,
Thomas
Titel: Re: Historie anlegen
Beitrag von: koehlerbv am 07.02.11 - 14:32:37
Nicht nur als unsauber, sondern sogar als falsch würde ich bezeichnen, dass Du Objekte instantiiertst, aber deren Existenz danach nicht überprüfst. Was ist, wenn es die Ansicht nicht (mehr) gibt? Was ist, wenn es noch gar kein erstes Dokument gibt? Was ist, wenn dem Ausführenden die Rechte fehlen, doc2 zu erzeugen?

Und vor allem natürlich: Es fehlt jegliches ErrorHandling!

Bernhard

PS: Ich finde es aber sehr gut, wie Du an die Einarbeitung in LS vorgehst!
Titel: Re: Historie anlegen
Beitrag von: ThomasHB am 07.02.11 - 14:47:05
Nicht nur als unsauber, sondern sogar als falsch würde ich bezeichnen, dass Du Objekte instantiiertst, aber deren Existenz danach nicht überprüfst.

OK... Kannst Du das etwas genauer definieren, wie eine solche Überprüfung aussehen sollte...

Zitat
Was ist, wenn es die Ansicht nicht (mehr) gibt? Was ist, wenn es noch gar kein erstes Dokument gibt? Was ist, wenn dem Ausführenden die Rechte fehlen, doc2 zu erzeugen?

Wenn es die Ansicht nicht mehr gibt, dann wüsste ich spontan da jetzt auch nichts zu ehrlich gesagt...
Ein erstes Dokument wird es Initial geben, das macht ein Agent.
Da diese kleine DB nur im kleinen Kreis genutzt wird, weil ich meine Fähigkeiten in LS nicht als gut genug für Productive DBs einschätze, wäre das erst mal kein Problem.

Trotzdem versuche ich, das so gut wie möglich auf die Beine zu stellen.

Was würdest du empfehlen? Rechteprüfung vorher?

Grüße,
Thomas
Titel: Re: Historie anlegen
Beitrag von: m3 am 07.02.11 - 15:10:17
Naja, ein Test, ob ein Object überhaupt instanziert wurde oder einfach "nichts" ist, wäre mal ein guter Anfang. ;)
Titel: Re: Historie anlegen
Beitrag von: Peter Klett am 07.02.11 - 15:10:38
Ein paar Dinge noch zusätzlich zu dem bereits geschriebenen:

Du setzt Datum (hattest ja auch Deine Probleme damit), aber nutzt es nirgendwo.

Im PostSave hängst Du immer Werte an. Speichere das Dokument mal mehrfach (STRG+S), dann werden die Listen immer länger

Du speicherst doc2 innerhalb der Schleife, gibt es 25 Dokumente von doc, speicherst Du doc2 25 mal. Einmal außerhalb der Schleife sollte völlig ausreichen

Du dimensionierst Variablen, die Du nicht brauchst: DocUnID, person

In der Schleife durchläufst Du alle Dokumente der Ansicht und suchst Dir die passenden anhand des Namens heraus. Das wird auf Dauer ein Langläufer. Besser wäre, die Ansicht entsprechend zu sortieren, darin das erste Dokument anhand des Namens zu suchen (v.GetDocumentByKey ...), von dort weitersuchen und stoppen, sobald es nicht mehr passt

Sehe es genauso wie Bernhard, dass Du so weitermachen solltet. Erstmal selber probieren, dann helfen lassen. Das ist ein guter Ansatz.


EDIT: Das mit den länger werdenden Listen habe ich falsch interpretiert. Aber Du erstellst bei jedem Speichern ein doc2. Willst Du das wirklich?
Titel: Re: Historie anlegen
Beitrag von: Axel am 07.02.11 - 15:18:06
Nicht nur als unsauber, sondern sogar als falsch würde ich bezeichnen, dass Du Objekte instantiiertst, aber deren Existenz danach nicht überprüfst.

OK... Kannst Du das etwas genauer definieren, wie eine solche Überprüfung aussehen sollte...

Im Fall der Ansicht kann das so aussehen:

Set v = db.GetView("nHist_Hardware")
If v Is Nothing Then
  'Ansicht nicht vorhanden -> Fehlerbehandlung
End If

Hier findest du jede Menge Infos zur Fehlerbehandlung in LotusScript: http://atnotes.de/index.php/topic,11980.0.html (http://atnotes.de/index.php/topic,11980.0.html)

Axel
Titel: Re: Historie anlegen
Beitrag von: koehlerbv am 07.02.11 - 15:19:31
Bei der Programmierung gibt es (fast) kein "nie". Aus dem "kleinen Kreis" wird ein grosser, der Server, der immer nur mit deutschen Einstellungen laufen wird, bekommt auf einmal einen englischsprachigen Bruder, der code, der "so schön läuft", wird kopiert und in einer anderen DS auch verwendet usw. usf.

Minimum: ErrorHandling. Das ist auch und gerade Programmiers Eigenschutz. Warum da plötzlich "Object variable not set" angezeigt wird, kannst Du nach einem halben Jahr nicht mehr spontan zuordnen.

Bernhard
Titel: Re: Historie anlegen
Beitrag von: ThomasHB am 07.02.11 - 15:42:16
...ok, verstehe was ihr mir sagen wollt.
Danke für die Unterstützung. Ich werde versuchen das zu beachten.

Mal sehen wie weit ich das Script mit den Tipps noch optimieren kann.

Grüße,
Thomas
Titel: Re: Historie anlegen
Beitrag von: ThomasHB am 09.02.11 - 18:12:40
Hallo Zusammen,

ich habe jetzt noch mal weiter gemacht... Ich habe mich auch mal am Error Handling veruscht ala on Error Goto... Das klappt nur offenbar nicht, weil er eine Rückmeldung gibt:

Hardware: Postsave: 26: Illegal executable code oustide procedure.
Ich hatte mich bei der Angabe an dem verlinkten Thread orientiert...

Auf die Existenz der Objekte will ich Morgen mal zurückgreifen, sprich das mal versuchen...

Aber vielleicht kann man ja noch mal über das aktuelle Eregnis sprechen.
Da interessiert mich, kann man das so machen... Grundlegend falsch, solche Dinge eben.
Tipps zur Verbesserung...

Der Code so wie er jetzt ist, tut aber genau das was ich will... Das macht mich ja irgendwo trotzdem ein bisschen Stolz...   ;D

Also so sieht das PostSave Event jetzt aus:

Code
Sub Postsave(Source As Notesuidocument)	
	Dim v As NotesView
	Dim s As New NotesSession
	Dim doc As NotesDocument
	Dim db As NotesDatabase
	Dim doc2 As NotesDocument
	Dim composed1 As String, composed2 As String, PersName As String
	
	composed1 = Source.FieldGetText("DocUnID")
	composed2 = Source.FieldGetText("person")
	Set db = s.CurrentDatabase
	Set v = db.GetView("nHist_Hardware")
	Set doc = v.GetDocumentByKey(composed1)
	Set doc2 = New NotesDocument(db)
	
	PersName = getLastDocument(composed1)
	
	If composed1 = doc.GetItemValue("HistHW_DocUnID")(0) And Strcomp(composed2, PersName) <> 0 Then
		Call doc2.AppendItemValue("Form", "Hardware_Historisierung")
		Call doc2.AppendItemValue("HistHW_DocUnID", composed1)
		Call doc2.AppendItemValue("HistHW_Name", composed2)
		Call doc2.AppendItemValue("HistHW_Datum", Today())	
		Call doc2.Save(0,0)
	End If
End Sub

So sieht die Funktion getLastDocument aus:

Code
Function getLastDocument(ID As String) As String
	Dim v As NotesView
	Dim s As New NotesSession
	Dim doc As NotesDocument
	Dim db As NotesDatabase
	Dim NamePers As String
	
	Set db = s.CurrentDatabase
	Set v = db.GetView("nHist_Hardware")
	Set doc = v.GetDocumentByKey(ID)
	
	While Not (doc Is Nothing)
		NamePers = doc.GetItemValue("HistHW_Name")(0)
		Set doc = v.GetNextDocument(doc)
	Wend
	getLastDocument = NamePers
End Function

Gefühlt wäre diese Funktion unnötig... Da war natürlich auch Spielerei dabei und das eigene Training, was geht wie etc.

Bin auf Kommentare gespannt.

Viele Grüße,
Thomas
Titel: Re: Historie anlegen
Beitrag von: Axel am 09.02.11 - 19:11:54
Stichpunktartig was mir aufgefallen ist:

1. Jegliche Fehlerbehandlung fehlt.
2. Objekte werden instantiiert, aber die Existenz danach nicht überprüft, besonders in Postsave.


ich habe jetzt noch mal weiter gemacht... Ich habe mich auch mal am Error Handling veruscht ala on Error Goto... Das klappt nur offenbar nicht, weil er eine Rückmeldung gibt:

Hardware: Postsave: 26: Illegal executable code oustide procedure.
Ich hatte mich bei der Angabe an dem verlinkten Thread orientiert...

Ohne zu sehen wie du das programmiert hast lässt sich dazu nichts sagen.

Axel
Titel: Re: Historie anlegen
Beitrag von: Peter Klett am 09.02.11 - 21:04:24
Sorry, wahrscheinlich fehlt mir der intellektuelle Zugang zu Deinem Werk.

Stiere nun seit 10 Minuten auf das Script und verstehe nicht, was es eigentlich machen soll.

Sub Postsave(Source As Notesuidocument)   
   Dim v As NotesView
   Dim s As New NotesSession
   Dim doc As NotesDocument
   Dim db As NotesDatabase
   Dim doc2 As NotesDocument
   Dim composed1 As String, composed2 As String, PersName As String
   
   composed1 = Source.FieldGetText("DocUnID") -> irgendeinde ID aus dem aktuellen Dokument
   composed2 = Source.FieldGetText("person") -> die Person aus dem aktuellen Dokument
   Set db = s.CurrentDatabase -> die aktuelle Datenbank
   Set v = db.GetView("nHist_Hardware") -> eine Ansicht, was für Dokumente werden da ausgegeben?
   Set doc = v.GetDocumentByKey(composed1) -> das erste Dokument aus dieser Ansicht mit der ID des aktuellen Dokuments (was für ein Dokument?)
   Set doc2 = New NotesDocument(db) -> ein neues Dokument
   
   PersName = getLastDocument(composed1) -> der Name der Person aus dem letzen Dokument der Ansicht, die übergebene ID ist wirkungslos, da damit nur in der Ansicht das Einstiegsdokument gesucht wird und dann die Ansicht bis zum letzten Dokument durchgehechelt wird
   
   If composed1 = doc.GetItemValue("HistHW_DocUnID")(0) And Strcomp(composed2, PersName) <> 0 Then -> die erste Bedingung wird immer erfüllt sein, außer es gibt das Dokument nicht, die zweite Bedingung wird nur erfüllt, wenn die Person mit der aus dem letzten Dokument der Ansicht übereinstimmt. Sinn?
      Call doc2.AppendItemValue("Form", "Hardware_Historisierung")
      Call doc2.AppendItemValue("HistHW_DocUnID", composed1)
      Call doc2.AppendItemValue("HistHW_Name", composed2)
      Call doc2.AppendItemValue("HistHW_Datum", Today())   
      Call doc2.Save(0,0)
   End If
End Sub

Und das führst Du bei jedem Speichern des Dokuments aus. Dass das funktioniert, liegt vermutlich nur an den Laborbedingungen: immer der gleiche User und niemals das Dokument zwischenspeichern (STRG+S).
Du solltest Dir mal den gewünschten Ablauf analog vorstellen, ohne Überlegung, mit welchem Befehl Du das umsetzt. Wenn der Ablauf steht, setze es in Script um.
Titel: Re: Historie anlegen
Beitrag von: ThomasHB am 10.02.11 - 10:34:32
Hallo Peter und hallo alle anderen,

danke zunächst für die Kommentare.
@Axel: Wie ich schon schrieb, diese Punkte sollen heute dann noch folgen.

@Peter:

Du musst dir vorstellen, das ist eine Database, die einen Hardwarebestand erfasst, also zu jedem Rechner, zu jedem Notebook zisch versch. Hardwaremerkmale speichert.
Anschaffungsdatum, Garantiezeit etc.
Ausserdem Bildschirme und viele weitere Dinge.

Diese Hardware wird immer wieder versch. Personen zugewiesen.
Allerdings kann man nach 2 Jahren nicht mehr sagen, wer hatte das mal...

Und genau da kommt das Script ins Spiel... Es ist für eine Historie gebaut.
Ich habe das an dieser Stelle nicht mit Children Documents aufgebaut.

Im Hardware Formular, gibt es das Feld DocUnID, welches die Unique ID des Dokuments enthält.
Ein Agent, hat zu jeder Hardware, genauer zu jedem Dokument ein weiteres, in einem neuen Form angelegt.

Ein Feld in dem neuen Dokument enthält die Document Unique ID des ersten Hardwaredokuments.
Der Agent holt sich ähnlich wie die Postsave Funktion, die benötigten Daten und trägt sie damit als erstes Dokument einmal Initial ein. Damit existieren dann die Dokumente und mein Programm im Postsave kann nie auf diesen Fehler stossen, beim anlegen eines neuen Hardwaredokuments, wird ein Historiendokument direkt mit angelegt.

Dieses Script im Postsave geht jetzt hin und ermittelt zunächst mal ein paar Werte...
Die Unique ID, die Person... Dann guckt es in die Historien View, die entsprechend aufgebaut ist und geht dann diese durch...

Dann holt es sich den Namen der letzten Person, welche diese Hardware zugewiesen hatte...

Danach guckt dann das IF, ob beide IDs stimmen und ob die Person ungleich der zuletzt zugewiesen ist... Sonst würde ja ständig ein neues Historiendok angelegt werden.

Viele Grüße,
Thomas
Titel: Re: Historie anlegen
Beitrag von: Peter Klett am 10.02.11 - 11:01:11
Ok, vom Ansatz verstanden.

Dann solltest Du diese Funktion nochmal überdenken

Function getLastDocument(ID As String) As String
   Dim v As NotesView
   Dim s As New NotesSession
   Dim doc As NotesDocument
   Dim db As NotesDatabase
   Dim NamePers As String
   
   Set db = s.CurrentDatabase
   Set v = db.GetView("nHist_Hardware")
   Set doc = v.GetDocumentByKey(ID) -> hier suchst Du das erste Dokument mit der passenden ID
   
   While Not (doc Is Nothing)
      NamePers = doc.GetItemValue("HistHW_Name")(0) -> hier setzt Du NamePers, unabhängig von der ID
      Set doc = v.GetNextDocument(doc)
   Wend
   getLastDocument = NamePers -> NamePers beinhaltet den Namen des letzten Dokuments der Ansicht, welche ID das Dokument hat, spielt in Deinem Script fälschlicherweise keine Rolle
End Function

Wenn Du die Ansicht mit den IDs so aufbaust, dass die Dokumente nach ID sortiert sind, die neuesten zuoberst, findest Du mit einem Zugriff (das erste Dokument mit der ID) das gewünschte Dokument. Das spart viel Zeit.

Deine Hauptroutine wird dann kürzer:

Set doc = v.GetDocumentByKey(composed1) -> das jüngste "Parallel"-Dokument
Set doc2 = New NotesDocument(db)
   
PersName = doc.HistHW_Name (0)
   
If composed1 = doc.GetItemValue("HistHW_DocUnID")(0) And Strcomp(composed2, PersName) <> 0 Then
 
Die erste Bedingung ist unnötig.

EDIT: Fehlerhandling, wie nicht gesetzte Objekte, habe ich ignoriert
Titel: Re: Historie anlegen
Beitrag von: ThomasHB am 10.02.11 - 11:11:11
Hallo Peter,

danke für deinen Kommentar...
Ich brösel das noch mal etwas weiter auf...

Ich hatte ja schon geschrieben, das die View, in welche geschaut wird, entsprechend eingestellt ist, damit meine ich folgendes... Es gibt eine Kategorisierung nach der UniqueID, weil es ja mehrere Hostoriendokumente zu einem Hardware Dokument (UniqueID) geben kann.

Zitat
Set doc = v.GetDocumentByKey(ID) -> hier suchst Du das erste Dokument mit der passenden ID

Ja genau... Und zwar innerhalb der Kategorie nach UniqueID.

Zitat
NamePers = doc.GetItemValue("HistHW_Name")(0) -> hier setzt Du NamePers, unabhängig von der ID

Kann ich so aber nicht stehen lassen... Die Aussage so stimmt schon, ich gebe eine ID nicht explizit an... Aber "doc." bezieht sich auf GetDocumentByKey und dieses wiederrum auf die genannte View.

Durch die Angabe von GetDocumentByKey und der Kategorisierung der View nach UniqueID bleibt er in der Kategorie... Deshalb kann mir das da egal sein, weil nur Dokumente zu dieser Unique ID gefunden werden.

Zitat
Set doc = v.GetNextDocument(doc)

Holt sich an dieser Stelle nämlich auch nur noch die Dokumente, zu dieser UniqueID Kategorie innerhalb der View... Und es stehen zisch Dokumente in X UniqueID Kategorien.

Was ich will, ist das letzte Dokument, das angelegt wurde...

Ich bin mir nicht sicher, aber ich glaube, das GetLastDocument diese Schleife ersetzen könnte, denn es müsste sich ja ähnlich wie GetNextDocument verhalten...

Viele Grüße,
Thomas
Titel: Re: Historie anlegen
Beitrag von: Peter Klett am 10.02.11 - 11:15:41
Eine viel elegantere Lösung wäre aber, nicht in den Historierendokumenten suchen zu müssen.

Du willst ein neues Historiendokument erstellen, wenn sich die Person geändert hat? Dann merke Dir im PostOpen die aktuelle Person, im QueryClose vergleichst Du die Person im Dokument mit der gemerkten. Bei Abweichung schreibst Du das Historiendokument.

Declarations
Dim vglperson As String

PostOpen
Dim doc As NotesDocument
Set doc = Source.Document
vglperson = doc.Person (0)

QueryClose
Dim doc As NotesDocument
Set doc = Source.Document
If vglperson <> doc.Person (0) Then
   ' -> neues Historiendokument schreiben
End If

2 Vorteile:

1. Performanter, da kein Zugriff auf andere Dokumente nötig
2. Es wird nur die Person protokolliert, die beim Schließen des Dokuments gespeichert war, zwischenzeitliche Falscheingaben, die gespeichert, aber vorm Verlassen korrigiert wurden, werden nicht protokolliert
Titel: Re: Historie anlegen
Beitrag von: ThomasHB am 10.02.11 - 11:21:23
Hah... Na hätte ich das mal vorher gewusst.
Da macht man sich dann die riesen Mühe...  ;D

Ich glaube, ich sollte doch noch mal mehr tun in Richtung, was gibts für Events...

Schöner Hinweis, vielen Dank!

Tja, dann verbuche ich wohl diese Aktion einfach mal unter Learning LotusScript.  :P

Aber ich finde das gerade sehr interessant, deshalb würde ich das Script noch mal weiterführen und mir dann noch mal Tipps abholen, wenn das ErrorHandling und die Prüfung auf Objekte drin sind.

Viele Grüße,
Thomas
Titel: Re: Historie anlegen
Beitrag von: Peter Klett am 10.02.11 - 11:21:35
Zitat
NamePers = doc.GetItemValue("HistHW_Name")(0) -> hier setzt Du NamePers, unabhängig von der ID

Kann ich so aber nicht stehen lassen... Die Aussage so stimmt schon, ich gebe eine ID nicht explizit an... Aber "doc." bezieht sich auf GetDocumentByKey und dieses wiederrum auf die genannte View.

Durch die Angabe von GetDocumentByKey und der Kategorisierung der View nach UniqueID bleibt er in der Kategorie... Deshalb kann mir das da egal sein, weil nur Dokumente zu dieser Unique ID gefunden werden.

Zitat
Set doc = v.GetNextDocument(doc)

Holt sich an dieser Stelle nämlich auch nur noch die Dokumente, zu dieser UniqueID Kategorie innerhalb der View... Und es stehen zisch Dokumente in X UniqueID Kategorien.

Was ich will, ist das letzte Dokument, das angelegt wurde...

Das ist ein Irrtum, GetNextDocument (doc) stoppt nicht, wenn sich die ID ändert, bleibt also nicht innerhalb der Kategorie (wäre mir jedenfalls völlig neu).
Titel: Re: Historie anlegen
Beitrag von: Peter Klett am 10.02.11 - 11:23:06
Tja, dann verbuche ich wohl diese Aktion einfach mal unter Learning LotusScript.  :P
Sehr gute Einstellung, weiter so !  ;)
Titel: Re: Historie anlegen
Beitrag von: ThomasHB am 10.02.11 - 11:28:47
Zitat
Das ist ein Irrtum, GetNextDocument (doc) stoppt nicht, wenn sich die ID ändert, bleibt also nicht innerhalb der Kategorie (wäre mir jedenfalls völlig neu).

Doch, so wie ich das verstanden habe... Wenn Du nach GetDocumentByKey die Dokumente suchst und dabei aber eine Kategorisierte View hast, dann tritt genau dieser Effekt ein.

Die Designerhelp 8.5.2 für die GetDocumentbyKey Methode sagt unter Punkt 5 für mich genau das aus... Aber vielleicht habe ich das auch nicht richtig verstanden... Wenn das so ist, dann korrigiert mich gerne, damit ich hier nichts falsches im Gedächtnis halte...  :)

Grüße,
Thomas
Titel: Re: Historie anlegen
Beitrag von: Peter Klett am 10.02.11 - 11:37:38
In der 7er Hilfe steht davon nichts. Falls das eine Änderung in 8 oder 8.5 ist, kann das eine böse Falle für ältere Scripte sein. Gut zu wissen ...

Nachtrag: Auszug aus Hilfe 7 zu diesem Thema (in GetDocumentByKey):

"If you use a GetNextDocument loop, you must explicitly check to make sure the next document is a match"
Titel: Re: Historie anlegen
Beitrag von: ThomasHB am 10.02.11 - 11:40:08
Lies es dir gerne mal durch... Ich habe es so verstanden.  :)
Und dann eben für meine Zwecke so gebaut, wie ich dachte, das es sein muss...

Das es auch elegant geht, habe ich erst heute erfahren...  ;)

Zitat von: IBM Lotus Designer 8.5.2
This script gets all of the documents in the category "Spanish leather" in the By Category view of the current database, and puts them in the Boots folder. The script finds the first document in the category using GetDocumentByKey, and the remaining documents in the category using GetNextDocument. The script uses the ColumnValues property in NotesDocument to check each document's column values: as long as a document's value for the first sorted column in the view equals "Spanish leather," the script places the document in the Boots folder. If the document's value for the first sorted column does not equal "Spanish leather," or if there are no more documents in the view, the script ends.
See GetAllDocumentsByKey for an easier way to do this. The only advantage to this technique is that it correctly sets the ColumnValues property in the retrieved documents while GetAllDocumentsByKey does not.

Code
Dim session As New NotesSession
Dim db As NotesDatabase
Dim view As NotesView
Dim column As NotesViewColumn
Dim doc As NotesDocument
Set db = session.CurrentDatabase
Set view = db.GetView( "By Category" )
' get the first sorted and categorized column in the view
Forall c In view.Columns
  If ( c.IsSorted And c.IsCategory ) Then
    Set column = c
    Exit Forall
  End If
End Forall
' get the first document that matches the key
Set doc = view.GetDocumentByKey( "Spanish leather" )
' get the remaining documents that match the key
' since ColumnValues array starts at 0 for position 1,
' subtract 1 from the column position
Do While Not ( doc Is Nothing )
  If ( doc.ColumnValues( column.Position - 1 ) =  _
  "Spanish leather" ) Then
    Call doc.PutInFolder( "Boots" )
  Else
    Exit Do
  End If
  Set doc = view.GetNextDocument( doc )
Loop
Titel: Re: Historie anlegen
Beitrag von: klaussal am 10.02.11 - 11:44:41
Aus der 8er-Hilfe:
Zitat
This script gets all of the documents in the category "Spanish leather" in the By Category view of the current database, and puts them in the Boots folder. The script finds the first document in the category using GetDocumentByKey, and the remaining documents in the category using GetNextDocument. The script uses the ColumnValues property in NotesDocument to check each document's column values: as long as a document's value for the first sorted column in the view equals "Spanish leather," the script places the document in the Boots folder. If the document's value for the first sorted column does not equal "Spanish leather," or if there are no more documents in the view, the script ends.
See GetAllDocumentsByKey for an easier way to do this. The only advantage to this technique is that it correctly sets the ColumnValues property in the retrieved documents while GetAllDocumentsByKey does not.
Titel: Re: Historie anlegen
Beitrag von: Peter Klett am 10.02.11 - 11:45:33
Prima, Fehlalarm

Do While Not ( doc Is Nothing )
  If ( doc.ColumnValues( column.Position - 1 ) =  _
  "Spanish leather" ) Then
    Call doc.PutInFolder( "Boots" )
  Else
    Exit Do
  End If
  Set doc = view.GetNextDocument( doc )
Loop

Die Beschreibung zu dem Beispielscript sagt, dass dort geprüft wird, ob die Kategorie die gleiche ist. Sprich, Du musst es selber prüfen (wie bisher in den alten Versionen auch). Und genau das hast Du in Deiner Routine nicht getan und deshalb durfte die nicht funktionieren.

Puh, Blutdruck wieder senken ...
Titel: Re: Historie anlegen
Beitrag von: ThomasHB am 10.02.11 - 11:50:40
Und genau das hast Du in Deiner Routine nicht getan und deshalb durfte die nicht funktionieren.

Tja, dann ist es mir ein Rätsel... Ich habe genau das gerade noch mal versucht.
Das Programm funktioniert und für mich sieht es so aus, als wenn das schon direkt geprüft würde...

Zitat
Puh, Blutdruck wieder senken ...

Ich wäre immer vorsichtig, wenn Neulinge versuchen mit klugen Weißheiten anzugeben.  ;D
Titel: Re: Historie anlegen
Beitrag von: Peter Klett am 10.02.11 - 11:52:12
Du siehst, hier wird jeder ernst genommen  ;)
Titel: Re: Historie anlegen
Beitrag von: ThomasHB am 10.02.11 - 11:56:02
Jetzt wurmt es mich aber trotzdem...
Warum funktioniert dann mein Programm?

Der Verhält sich genau so wie beschrieben, ohne explizite Prüfung...  ???

Was kann es denn sein? Mein Code ist ja bekannt, die View Settings jetzt auch.
Stimmt die Help möglicherweise nicht...

Die DB bzw. das Script verhält sich ja nicht so, weil es gerade Lust dazu hat.  ;)
Titel: Re: Historie anlegen
Beitrag von: Peter Klett am 10.02.11 - 12:03:18
Vielleicht testest Du mit der letzten ID (also mit der, die ganz unten in der Ansicht steht). Nimm' mal eine andere. Trag mal als Person denjenigen ein, der im letzten Dokument enthalten ist, dann wird keine Historie erstellt, auch wenn der Name geändert wurde.

Es wäre mir auch unerklärlich, woher GetNextDocument wissen sollte, nach welcher Kategorie mittels GetDocumentByKey gesucht wurde. Ich glaube daher, dass Dein Script nur zufällig funktioniert.
Titel: Re: Historie anlegen
Beitrag von: ThomasHB am 10.02.11 - 12:09:20
Vielleicht testest Du mit der letzten ID (also mit der, die ganz unten in der Ansicht steht). Nimm' mal eine andere. Trag mal als Person denjenigen ein, der im letzten Dokument enthalten ist, dann wird keine Historie erstellt, auch wenn der Name geändert wurde.

Es wäre mir auch unerklärlich, woher GetNextDocument wissen sollte, nach welcher Kategorie mittels GetDocumentByKey gesucht wurde. Ich glaube daher, dass Dein Script nur zufällig funktioniert.

Tja... Das glaube ich jetzt auch.  ;D
Ich habe das natürlich sofort mal gemacht.

Schlägt natürlich mit aller Härte zurück und verhält sich exakt wie du es beschreibst.
Es wird kein Historiendokument erzeugt.

Gut, dann konnte das aber jetzt auch geklärt werden.
Das muss ich mir unbedingt merken, schöne Konversation. Hat mir einiges gebracht, Vielen Dank !

Viele Grüße,
Thomas
Titel: Re: Historie anlegen
Beitrag von: Peter Klett am 11.02.11 - 06:35:56
Hier noch eine Korrektur zu meiner vorgeschlagenen Lösung:

Im Queryclose ist der Name natürlich der, der aktuell im Dokument eingetragen ist, unabhängig davon, ob das Dokument gespeichert wurde. Deshalb würde ich mir im PostSave den Namen merken und im QueryClose nur dann ein Historiendokument erstellen, wenn 1. im PostSave ein Name gemerkt wurde (sonst wurde nicht gespeichert) und 2. dieser Name sich gegenüber dem Öffnen geändert hat. Meine Erweiterungen in blau:

Declarations
Dim vglperson As String
Dim merkperson As String

PostOpen
Dim doc As NotesDocument
Set doc = Source.Document
vglperson = doc.Person (0)

PostSave
Dim doc As NotesDocument
Set doc = Source.Document
merkperson = doc.Person (0)

QueryClose
Dim doc As NotesDocument
Set doc = Source.Document
If merkperson <> "" And  vglperson <> merkperson Then
   ' -> neues Historiendokument schreiben
End If

 
Titel: Re: Historie anlegen
Beitrag von: koehlerbv am 11.02.11 - 10:52:02
Ich bin der Meinung, das eine solche Aktion nicht in das PostSave, sondern ins QuerSave gehört - zusammen mit einem passenden ErrorHandling. Geht im PostSave etwas schief, ist zwar die Änderung im Inventar-Dokument gespeichert, das History-Dokument wird aber nicht angelegt.

Bernhard
Titel: Re: Historie anlegen
Beitrag von: Peter Klett am 11.02.11 - 11:47:53
Es kommt immer darauf an, was sonst noch in einem Dokument abläuft. Wenn in irgendeinem QuerySave mit Continue = False eine Validierung das Speichern verhindert (z.B. in einer Teilmaske), wird die Historie gespeichert, obwohl das Dokument nicht gespeichert wurde. Wenn das PostSave läuft, ist definitiv das Dokument gespeichert worden /zumindest gehe ich davon aus).

Die Wahl besteht nur, ob ich im Fehlerfall ein Dokument zu viel oder zuwenig habe, ansonsten muss man dafür sorgen, dass möglichst keine Fehler auftreten können