Das Notes Forum
Domino 9 und frühere Versionen => ND6: Entwicklung => Thema gestartet von: Tode am 01.08.06 - 13:34:06
-
Problem: Bei programmierbaren Tabellen springt der Focus nicht auf das Feld, das der Eingabevalidierung nicht entsprochen hat, wenn nicht der Tab auf dem sich das Feld befindet gerade sowieso den Focus hat...
Natürlich kann man die Eingabevalidierung einfach ins QuerySave auslagern, dort das entsprechende Tabellen- Feld setzen, dann per Refresh das Frontend aktualisieren und dann per GotoField ins richtige Feld springen, aber ich möchte eigentlich ungern bei der bestehenden Datenbank alle Eingabevalidierungen (leider nicht einfach Feld = "" sondern recht komplexe Abhängigkeiten) nach Script portieren...
Hat jemand eine Idee ?
Im Prinzip bräuchte ich ein "Event", das nach der Eingabevalidierung zuschlägt. Dann könnte ich in der Eingabevalidierung z.B. Umgebungsvariablen setzen und diese mit dem Event auslesen und dann quasi im "nachhinein" in das richtige Register / richtige Feld springen.
Leider gibt es so ein Event nicht: QuerySave kommt vorher, PostSave wird nicht ausgeführt, wenn die Validierung fehlschlägt, die Recalc- Events werden von "Strg + S" auch nicht getriggert...
Ich hatte schon überlegt im Querysave einen Notes- Timer zu triggern der quasi nach einer Sekunde in ner Endlosschleife nach der Umgebungsvariable sucht, aber wie Krank bitteschön ist das denn... :o ;D
Irgend jemand ne Idee, wie ich der Berechneten Tabbed- table sagen kann "spring in den tab, in dem der Fehler passiert ist..."
Thanx
Tode
-
hmmm... vielleicht ist die Idee mit dem Timer gar nicht sooo krank... funktionieren tut es jedenfalls... Ich muss also nur dafür sorgen, dass in jeder Validierungsformel im Fehlerfall die entsprechenden Werte ins Environment geschrieben werden... das ist verhältnismässig wenig Aufwand...
Ich mache das mal noch "Sauber" (sofern man hier überhaupt von Sauber sprechen darf) und poste dann mal das Ergebnis für interessierte Tüftler....
Tode
-
also hier mal meine "Krücke" bis mir eine bessere Lösung einfällt:
Bestandteile:
Scriptlibrary "evaluateLib":
Declarations:
Dim evalTimer As NotesTimer
2 Subs:
Sub initTimer
Set evalTimer = New NotesTimer( 1 , "Timer für Feld- Evaluierungen" )
On Event Alarm From evalTimer Call evalTimerHandler
End Sub
Sub evalTimerHandler( Source As NotesTimer )
'- Frontend
Dim ws As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
Dim doc As NotesDocument
'- Backend
Dim ses As New NotesSession
Dim tabName As String, tabCol As String, fieldName As String
Dim continue As Boolean
continue = True
While continue
tabName = ses.GetEnvironmentString( "EVAL_tabName" )
Call ses.SetEnvironmentVar( "EVAL_tabName" , "" )
tabCol = ses.GetEnvironmentString( "EVAL_tabCol" )
Call ses.SetEnvironmentVar( "EVAL_tabCol" , "" )
fieldName = ses.GetEnvironmentString( "EVAL_fieldName" )
Call ses.SetEnvironmentVar( "EVAL_fieldName" , "" )
If tabName <> "" Then continue = False
Wend
evalTimer.enabled = False
If tabName <> "<OK>" Then
Set uidoc = ws.CurrentDocument
Set doc = uidoc.Document
Call doc.ReplaceItemValue( "$" + tabName , tabCol )
Call uidoc.RefreshHideFormulas
Call uidoc.GotoField( fieldname )
End If
End Sub
dann im Querysave (oder auch ins QueryRecalc, wenn man die Validierung nicht nur beim speichern machen will) der Maske die das verwenden soll:
Call initTimer
und ins Feld, das evaluiert werden soll:
@If( !@IsDocBeingSaved | @ThisValue != "" ; @Return( @Success ) ; "" );
@Environment( "EVAL_tabName" ; "TestTable" );
@Environment( "EVAL_tabCol" ; "2" );
@Environment( "EVAL_fieldName" ; @ThisName );
@Failure( "TEST2 ausfüllen !!!" )
Ausserdem 1 bearbeitbares Feld ganz am Ende der Maske (nach allen zu validierenden Feldern) erstellen und in die Eingabevaliderung schreiben:
@Environment( "EVAL_tabName" ; "<OK>" );
@Success
Dieses Feld dient dem reset des Timers....
Funktioniert, schaltet die Table um, kann aber eben bis zu 1 Sekunde Verzögerung haben, aber in den sauren Apfel muss ich halt beissen...
Würde mich interessieren, was die Programmierer zu dieser Quick and (very) dirty- Methode sagen (abgesehen von der fehlenden Errorroutine und kommentierung des Codes....)
Tode
-
Eine Frage, was machst du mit mehrfach geschachtelten Tabellen
Das war ein Ansatz wie ich mir ihn für !!HELP!! bei der dort eingesetzten Validierung auch überlegt habe, aber das Problem ist, das man dann für jedes vorhandene Feld in einer Maske in einem Konfigurationsdokument festlegen muss wo es denn bitteschön zu finden ist. Das ist technisch zwar machbar, aber von der Konfiguration her ein Alptraum.
-
tja... mehrfach geschachtelt... das ist natürlich weniger schön...
Wenn man das konfigurierbar macht (ich würde dann pro Feld ein Dokument anlegen mit Feldname und eine Liste aus Tabellen und Tab- Nummern), dann müsste der Code in der Validierung schlicht per lookup nach den Werten schauen, die im Dokument so gespeichert sein könnten:
MainTable~2
SubTable~3
SubSubTable~2
Dann das ganze per Word auseinandernehmen und die einzelnen Tabs durchlaufen...
In meinem "QuickAndDirty" modell habe ich es ohne Konfig- Doks mal so umgesetzt (ein wenig anders als gerade beschrieben:
Evaluate des Feldes so geändert:
@If( !@IsDocBeingSaved | @ThisValue != "" ; @Return( @Success ) ; "" );
@Environment( "EVAL_tabName" ; "TestTable~SubTable" );
@Environment( "EVAL_tabCol" ; "2~2" );
@Environment( "EVAL_fieldName" ; @ThisName );
@Failure( "TEST2 ausfüllen !!!" )
und code der Sub so geändert:
Sub evalTimerHandler( Source As NotesTimer )
'- Frontend
Dim ws As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
Dim doc As NotesDocument
'- Backend
Dim ses As New NotesSession
Dim tabName As String, tabCol As String, fieldName As String
Dim continue As Boolean
continue = True
While continue
tabName = ses.GetEnvironmentString( "BEFR_EVAL_tabName" )
Call ses.SetEnvironmentVar( "BEFR_EVAL_tabName" , "" )
tabCol = ses.GetEnvironmentString( "BEFR_EVAL_tabCol" )
Call ses.SetEnvironmentVar( "BEFR_EVAL_tabCol" , "" )
fieldName = ses.GetEnvironmentString( "BEFR_EVAL_fieldName" )
Call ses.SetEnvironmentVar( "BEFR_EVAL_fieldName" , "" )
If tabName <> "" Then continue = False
Wend
evalTimer.enabled = False
If tabName <> "<OK>" Then
Set uidoc = ws.CurrentDocument
Set doc = uidoc.Document
Dim tabNames As Variant
Dim tabCols As Variant
Dim i As Integer
tabNames = Split( tabName , "~" )
tabCols = Split( tabCol , "~" )
i = 0
Forall tNam In tabNames
Call doc.ReplaceItemValue( "$" + tNam , tabCols( i ) )
i = i + 1
End Forall
Call uidoc.RefreshHideFormulas
Call uidoc.GotoField( fieldname )
End If
End Sub
EDIT: Durch das direkte setzen der Tabellennamen spare ich mir die Konfig- Dokumente und ausserdem muss ich - wenn ich Felder im Design zwischen Tabs hin und herschiebe- sowieso den Designer nehmen, und deshalb kann ich auch gleich die Umgebungs- Werte im Feld selbst ändern...