Das Notes Forum

Domino 9 und frühere Versionen => ND8: Entwicklung => Thema gestartet von: Boox am 23.04.17 - 16:04:22

Titel: Nachhilfe beim Exiting-Event
Beitrag von: Boox am 23.04.17 - 16:04:22
Hallo liebe Forum-Gemeinde,

ich (Script-Einsteiger) möchte über ein Exiting-Event eines Optionsfeldes realisieren, dass das Dokument bei der Auswahl des Wertes "OK" automatisch gespeichert wird (ich weiß, vermutlich alles andere als performant, stellt aber kein Problem dar).

Hier mein Code:

Sub Exiting(Source As Field)   
   Dim ws As New NotesUIWorkspace
   Dim uidoc As NotesUIDocument   
   Set uidoc = ws.CurrentDocument
   value = uidoc.FieldGetText(Source)
   
   If value = "OK" Then
      Call ws.CurrentDocument.Save
   End If
   
End Sub

Das "FieldGetText" haut nicht so hin und ich weiß auch, dass die Funktion eigentlich ein Feldnamen als String erwartet. Allerdings stehe ich auf dem Schlauch, wie ich das mit dem Source-Feld verknüpfen kann. Wenn ich hier den Namen des Feldes als String reinschreibe, funktioniert es wie gewünscht.

Aber: Ich möchte das ganze "portabel" haben, so dass ich das Feld samt Event kopieren kann, ohne jedes Mal den Code anzupassen.

Könnt ihr mir da weiterhelfen?


Viele Grüße


Gregor
Titel: Re: Nachhilfe beim Exiting-Event
Beitrag von: jBubbleBoy am 23.04.17 - 17:36:58
Bei Optionsfeldern geht kein FieldGetText, den Wert erhält man über's Backend, z.B.:
Code
ws.currentDocument.document.getFirstitem("FeldName").text

In deinem Fall würde ich aber ein Doc-Refresh (Eigenschaft Feld) anstoßen und im PostRecalc-Ereignis das Speichern regeln, mit:
Code
if source.document.getFirstitem("FeldName").text = "OK"  then source.save
Titel: Re: Nachhilfe beim Exiting-Event
Beitrag von: Boox am 24.04.17 - 19:05:19
Hallo Erik,

vielen Dank für den Hinweis. Allerdings funktioniert doch FieldGetText zumindest in Verbindung mit dem uidoc. Also zumindest klappt es bei mir, wenn ich es so schreibe:

Code
Sub Exiting(Source As Field)	
	Dim ws As New NotesUIWorkspace
	Dim uidoc As NotesUIDocument	
	Set uidoc = ws.CurrentDocument
	value = uidoc.FieldGetText("t_ok")
	
	If value = "OK" Then
		Call ws.CurrentDocument.Save
	End If
	
End Sub

Meinst Wie gesagt: Mein Ziel ist es, das Feld mehrfach kopieren zu können ("t_ok_1", "t_ok_2", "t_ok_3";...), ohne den Code immer anpassen zu müssen. Und das müsste ich dann ja im PostRecalc trotzdem...

Und nur zur Erklärung: Ich brauche das Feld zwar nur 15x und es wäre kein Problem, 15x das Script anzupassen...aber ich möchte ja auch was dazu lernen und daher frage ich, ob es auch einfacher geht ;D
Titel: Re: Nachhilfe beim Exiting-Event
Beitrag von: jBubbleBoy am 24.04.17 - 21:00:05
Ups, da hab ich doch in der erster Antwort etwas falsches geschrieben ;)

Um die spätere Codepflege zu vereinfachen würde ich eine Funktion schreiben, mit einem Parameter für das betreffende Feld. Den Feldnamen erhältst du mit: 
Code
ws.CurrentDocument.CurrentField

Mein Favorit wäre aber nach wie vor das PostRecalc-Ereignis, um nicht auf die Anzahl der vorhanden Felder zu  achten, würde ich eine Schleife in dieser Art schreiben:
Code
Dim i%, fName$
i = 1
If ws.CurrentDocument.Document.HasItem("feld_" & i) Then fName = "feld_" & i
Do Until fName = ""
	If ws.CurrentDocument.Document.GetFirstItem(fName).text = "OK" Then ws.CurrentDocument.save
	
	i = i + 1
	If ws.CurrentDocument.Document.HasItem("feld_" & i) Then fName = "feld_" & i Else fName = ""
Loop
Titel: Re: Nachhilfe beim Exiting-Event
Beitrag von: Peter Klett am 24.04.17 - 22:13:31
Mein Favorit wäre aber nach wie vor das PostRecalc-Ereignis, um nicht auf die Anzahl der vorhanden Felder zu  achten, würde ich eine Schleife in dieser Art schreiben:
Code
Dim i%, fName$
i = 1
If ws.CurrentDocument.Document.HasItem("feld_" & i) Then fName = "feld_" & i
Do Until fName = ""
	If ws.CurrentDocument.Document.GetFirstItem(fName).text = "OK" Then ws.CurrentDocument.save
	
	i = i + 1
	If ws.CurrentDocument.Document.HasItem("feld_" & i) Then fName = "feld_" & i Else fName = ""
Loop

Dann würde bei einem Postrecalc das Dokument 15 mal gespeichert, wenn alle 15 Felder auf OK stehen. Ich habe es so verstanden, dass nur beim Exiting des Feldes gespeichert werden soll, wenn dieses OK ist. Wobei die Frage erlaubt ist, was passieren soll, wenn ein Feld schon vorher OK war, dann der Cursor in das Feld gesetzt und das Feld danach unverändert verlassen wird. Dann ist das Feld zwar OK, m.E. soll dann aber nicht gespeichert werden. Entweder müsste man die Veränderung selbst feststellen, oder auf das OnChange-Event ausweichen.

Ohne es aktuell getestet zu haben, vermute ich, dass das CurrentField im Postrecalc das nächste Feld ausweist, und damit das falsche, denn das gerade eben verlassene Feld ist ja eigentlich relevant.

Wenn ich mich recht erinnere, habe ich vor vielen Jahren erfolglos versucht, etwas ähnliches allgemeingültig zu schreiben, und passe seither solche Scripte je Feld an. Ist ja in der Regel nur der Feldname zu aktualisieren.

Möglicherweise könnte man mit einem @ThisName im Entering etwas erreichen, das gab es damals noch nicht. Habe aber keine Ahnung, ob das über Evaluate einen sinnvollen Rückgabewert ergibt. Im Entering den aktuellen Feldnamen irgendwo hinschreiben, und im Exiting nach der Aktion wieder entfernen. Theoretisch immerhin denkbar.

EDIT: @ThisName ist natürlich nicht notwendig, sollte ja über CurrentField gehen, wie schon geschrieben wurde
Titel: Re: Nachhilfe beim Exiting-Event
Beitrag von: jBubbleBoy am 25.04.17 - 15:10:04
Dann würde bei einem Postrecalc das Dokument 15 mal gespeichert, wenn alle 15 Felder auf OK stehen.
das stimmt ;)  dabei ist mir eine viel einfachere Lösung eingefallen, im PostRecalc:
Code
If Instr(Lcase(source.CurrentField),"feldname_")=1 Then 
	If source.Document.GetFirstItem(source.CurrentField).text = "OK" Then source.Save
End If
Das Problem beim OnChange-Event ist, das dieser beim Klick (und setzen des Wertes) nicht ausgelöst wird, das passiert erst bei einem F9-Refresh, Feldeigenschaft "aktualisieren" reicht nicht. In so einer Konstellation (Wenn ich in das Feld klicke, wird ja immer gespeichert) könnte der Nutzer "rausgehen" ohne dabei zu speichern, das gleiche Problem gibt es aber auch beim Exit-Ereignis. Deshalb denke ich mal wäre PostRecalc, auch weil man nur einmal Code schreiben muss, der beste Weg ;)
Titel: Re: Nachhilfe beim Exiting-Event
Beitrag von: Boox am 02.05.17 - 21:22:52
Vielen Dank für die guten Tipps! Ich werde es mal testen :)

Vermutlich werde ich dann aber den Feldnamen einfach anpassen, das ist wohl dann doch am einfachsten ;)
Titel: Re: Nachhilfe beim Exiting-Event
Beitrag von: thkn777 am 03.05.17 - 14:57:01
Frage:
Warum nicht in der Maske auf die Änderung des Feldes reagieren?

Hintergrund:
Ein doc.Save speichert das ganze Dokument. Bevor ich das tue, möchte man vielleicht noch andere Prüfungen vornehmen. Ich stelle mir eine Datenbank mit Masken, in denen irgendwelche Felder eingebaut sind, die vielleicht bei bestimmten Wert-Änderungen das Dokument speichern, ziemlich support-unfreundlich vor.

Lösungsvorschlag:
In Deinem Fall (15 Optionsfelder feld1 .. feld15) könntest Du im QueryRecalc der Maske folgendes schreiben:
Code
Sub Queryrecalc(Source As Notesuidocument, Continue As Variant)
	If Left$(Lcase(source.CurrentField),4)="feld" Then
		Print "MACH WAS"
	Else
		Print "ist mir egal"
	End If
End Sub

Den Print Befehl kannst Du natürlich auch durch etwas anderes ersetzen ;)

Damit hast Du an einer Stelle Deine Prüfungen/Save's verwaltet, Schreibaufwand ist minimal und falls Du mal eines der Optionsfelder ganz zufällig ;) in eine andere Maske kopierst, fängt diese nicht einfach aus heiterem Himmel an, manchmal das Dokument zu speichern.

Viel Erfolg,
Th.
Titel: Re: Nachhilfe beim Exiting-Event
Beitrag von: JoeeoJ am 11.11.17 - 14:24:47
Hallo zusammen,

UIDocument.CurrentField liefert im Exiting Event des Feldes leider schon den Namen des nächsten Feldes(!) und nicht des Feldes das man gerade verlässt !!! Den muss man in Entering Event abgreifen, da stimmt es.

Nehem an, das bei IBM\Lotus bei der Programmierung jemand nicht so ganz die Uebersicht hatte und vor dem Exiting Event den nächsten Feldnamen ermittelt und(!) in Currentfield geschrieben hat.

Gruss, Joe
Titel: Re: Nachhilfe beim Exiting-Event
Beitrag von: koehlerbv am 11.11.17 - 22:13:32
Nehme an, daß bei IBM\Lotus bei der Programmierung jemand nicht so ganz die Uebersicht hatte und vor dem Exiting Event den nächsten Feldnamen ermittelt und(!) in Currentfield geschrieben hat.

Falsch. Im Entering-Event ist der Wert von NotesUIDocument.CurrentField das gerade erreichte Feld, im Exiting wird das Feld verwendet, wohin das Exiting geht. Oder eben keins, wenn beispielsweise eine Schaltfläche bestätigt wird. Im Entering kann man sich einfachst in einer globalen Variablen merken, wo man gerade herumhüpft. Somit weiss man im Exiting, woher man kommt und wohin man geht.
Genau das ist auch in der DesignerHelp dokumentiert.
Welche grundsätzliche Designentscheidung hättest Du denn für Entering und Exiting getroffen? Wie hättest Du gelöst, dass man als Programmierer erfahren kann, wohin im Exiting die Reise geht?

Bernhard
Titel: Re: Nachhilfe beim Exiting-Event
Beitrag von: JoeeoJ am 13.11.17 - 07:05:31
Hallo Bernhard,

es als falsch zu bezeichnen, ist  nicht korrekt. Ich denke man kann über die Interpreation diskutiere; das trifft es besser.

Meine Interpretation ist:

Der Entering und der Exiting Event gehören bei zu der Klasse Field. Wenn also das aktuelle Field Object seinen Exiting Event triggered, ist diese Object noch aktiv und wir befinden uns noch in diesem Object. Wäre es korrekt programmiert worden, wäre das Currentfield auch tatsächlich der Name des aktiven Feld Object. Wäre das Feld Object besser ausprogrammiert worden, zb. Name des Field Objektes als Property , dann wäre das auch jedem automatisch klar.

Es mag durchaus Fälle geben, wo es praktisch wäre, das nächste Feld zu kennen. Da stimme ich dir voll zu. Aber dann hätte man dies formal korrekt in die Field Klasse als Property NextActivField packen können.  Das wäre dann eine saubere Klassenkonstruktion.

Gruss, Joe