Autor Thema: Feldänderungen im Hauptdokument automatisch auf Antwortdokumente übertragen  (Gelesen 5234 mal)

Offline SaSaWu

  • Aktives Mitglied
  • ***
  • Beiträge: 140
  • Geschlecht: Männlich
Hallo!

Unter http://atnotes.de/index.php?topic=13984.0 ist ein Script abgebildet (s.u.), mit dem Änderungen von Feldwerten im Hauptdokument automatisch auf die Antwortdokumente übertragen werden. Ich bin kein "Script'ler", es funktioniert dennoch halbwegs. Allerdings werden die Werte erst bei Aufruf der Antwortdokumente (Bearbeitungsmodus) geändert und diese müssen dann noch gespeichert werden. Welche Einstellungen muss ich vornehmen, um auch dies automatisiert hinzubekommen? Oder muss/kann ich einen Agenten laufen lassen, der dies vollzieht?



Code
3.4 Felder in allen Antwortdokumenten aktualisieren, sobald sich diese im Hauptdokument ändern

Wenn Änderungen im Hauptdokument auf alle Antwortdokumente übertragen werden sollen, kann man dies über den Query Save – Event in der Hauptdokument-Maske steuern.

Hilfreich sind hierbei „Responses property“ und „StampAll method“  in der „NotesDocumentCollection“.


Beispiel:


Code:
Sub Querysave(Source As Notesuidocument, Continue As Variant)
'------------------------------------------------------------------------------------------------------------------   
'Zweck: Feldwerte werden beim Speichern in alle Antwort-Dokumente übernommen   
'------------------------------------------------------------------------------------------------------------------   
   Dim session As New NotesSession
   Dim db As NotesDatabase
   Dim dc As NotesDocumentCollection
   Dim doc As NotesDocument
   Set db = session.CurrentDatabase
   
   If Source.IsNewDoc Then Exit Sub 'Wenn UIDoc neu ist dann verlasse Script
   
   Set doc = Source.Document 'UIDoc zu Backend-doc
   
   
   'alle Antwortdocs des Backend-Docs werden in die Collection aufgenommen
   Set dc = doc.Responses
   
   'Setze alle Felder der Collection, gespeichert wird automatisch   
   Call dc.StampAll( "Re_Feld1" , doc.Feld1(0) )
   Call dc.StampAll( "Re_Feld2" , doc.Feld2(0) )
   Call dc.StampAll( "Re_Feld3" , doc.Feld3(0) )
   
End Sub

Dieses Script kann man - etwas angepasst - auch in einem Agenten verwenden, der beispielsweise täglich alle Antwortdokumente aktualisiert.


Driri

  • Gast
Mit StampAll werden die Items aber gesetzt. Ich vermute mal, daß dein Problem berechnete Felder sind, die sich aus den "gestampten" Items ableiten.

Da müßtest Du entweder die berechneten Felder in dem Script mit berücksichtigen oder das Script so umbauen, daß die Dokumente aus der Collection alle noch einmal mit ComputeWithForms bearbeitet werden.

Offline SaSaWu

  • Aktives Mitglied
  • ***
  • Beiträge: 140
  • Geschlecht: Männlich
Danke für die Antwort!

Ok, die Felder im Antwortdokument sind "berechnet"
Code
@If (@IsNewDoc ; Aufgabe ; @GetDocField( $Ref; "Aufgabe") )
und haben denselben Feldnamen wie im Hauptdokument. "Mein" Script sieht an dieser Stelle so aus:
Code
   
	Call dc.StampAll( "Re_Aufgabe" , doc.Aufgabe(0) )
Eine "Berücksichtigung" der Felder im Script oder auch ein "Umbauen" bekomme ich nicht hin. Wie gesagt: "bin kein Sript'ler"!

Offline DAU-in

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 1.129
  • Geschlecht: Weiblich
  • - unterwegs -
Danke für die Antwort!

Ok, die Felder im Antwortdokument sind "berechnet"
Code
@If (@IsNewDoc ; Aufgabe ; @GetDocField( $Ref; "Aufgabe") )
und haben denselben Feldnamen wie im Hauptdokument. "Mein" Script sieht an dieser Stelle so aus:
Code
   
	Call dc.StampAll( "Re_Aufgabe" , doc.Aufgabe(0) )


Du schreibst sowohl bei neuen als auch  bei alten Dokumenten den Inhalt des Feldes Aufgabe rein?
Wenn du den Wert setzt über Stampall, sollte der Wert enthalten sein.

Sind die Feldwerte alle korrekt geschrieben?
Hast du in deinem Script mehrere Stampalls nacheinander?

Ich hatte einmal den Fall, dass mehrere Aufrufe von Stampall nacheinander nicht durchgelaufen sind bei einer grösseren Collection, das war aber unter 6.5.4.

Wie sieht dein Script denn aus?
Hast du das die Dokumente geöffnet im Frontend?
mühsam ernährt sich das Eichhörnchen

aktuelle Tätigkeit: Feldschubse

Offline SaSaWu

  • Aktives Mitglied
  • ***
  • Beiträge: 140
  • Geschlecht: Männlich

Zitat
Du schreibst sowohl bei neuen als auch  bei alten Dokumenten den Inhalt des Feldes Aufgabe rein?
Ja!
Zitat
Wenn du den Wert setzt über Stampall, sollte der Wert enthalten sein.

Sind die Feldwerte alle korrekt geschrieben?
Denke schon!
Zitat
Hast du in deinem Script mehrere Stampalls nacheinander?
Nein!

Zitat
Ich hatte einmal den Fall, dass mehrere Aufrufe von Stampall nacheinander nicht durchgelaufen sind bei einer grösseren Collection, das war aber unter 6.5.4.

Wie sieht dein Script denn aus?
s.u.
Zitat
Hast du das die Dokumente geöffnet im Frontend?
Nein

Danke schonmal für die Unterstützung!



Code
Code:
Sub Querysave(Source As Notesuidocument, Continue As Variant)
'------------------------------------------------------------------------------------------------------------------   
'Zweck: Feldwerte werden beim Speichern in alle Antwort-Dokumente übernommen   
'------------------------------------------------------------------------------------------------------------------   
   Dim session As New NotesSession
   Dim db As NotesDatabase
   Dim dc As NotesDocumentCollection
   Dim doc As NotesDocument
   Set db = session.CurrentDatabase
   
   If Source.IsNewDoc Then Exit Sub 'Wenn UIDoc neu ist dann verlasse Script
   
   Set doc = Source.Document 'UIDoc zu Backend-doc
   
   
   'alle Antwortdocs des Backend-Docs werden in die Collection aufgenommen
   Set dc = doc.Responses
   
   'Setze alle Felder der Collection, gespeichert wird automatisch   
   Call dc.StampAll( "Re_Aufgabe" , doc.Aufgabe(0) )
   
   
End Sub


Driri

  • Gast
Hast Du mal den Debugger mitlaufen lassen und geprüft, ob die DocumentCollection korrekt gefüllt wird ?

Sind das wirklich Antwortdokumente oder werden die evtl. irgendwie "künstlich" verlinkt ?


Offline cg-home

  • Aktives Mitglied
  • ***
  • Beiträge: 172
  • Geschlecht: Männlich
  • atnotes = Retter in der Not
Hi,

was mir gerade noch aufgefallen ist, ist das Du beim StampAll
  - Call dc.StampAll( "Re_Aufgabe" , doc.Aufgabe(0) )
das Feld "Re_Aufgabe" für die Antworten verwendest aber weiter
oben geschrieben hast, das die Feldenamen identisch sind.
Dann müsste es eher
  - Call dc.StampAll( "Aufgabe" , doc.Aufgabe(0) )
sein, vielleicht liegt es ja daran.

mfg Christian
11     Server R11.0.1FP3 - Windows Server 2012R2
700   Clients R11.0.1FP3 - Windows Server 2012R2 über Citrix
Traveler R11 | PowerTools 14 | Ytria | DomNavigator

Offline SaSaWu

  • Aktives Mitglied
  • ***
  • Beiträge: 140
  • Geschlecht: Männlich
Hallo Christian,

genau das ist es gewesen  ;D ;D ;D

Bin begeistert, vielen Dank!

Stefan

Offline Peter Klett

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.713
  • Geschlecht: Männlich
Ich weiß, dass Du kein "Script'ler" bist, trotzdem ein paar Verbesserungsvorschläge:

Mit Deinem jetzigen Script schreibst Du bei jedem Speichern des Hauptdokuments das Feld Aufgabe in die Antwortdokumente. Ich würde zumindest in dem Script überprüfen, ob das Feld überhaupt geändert wurde. Weiterhin würde ich das Script ins Postsave verlagern (ich persönlich würde es sogar in das Queryclose setzen und mir im Postsave merken, ob eine Veränderung stattgefunden hat).

Folgendes Szenario kann passieren:

Hauptdokument wird geöffnet und das Feld Aufgabe geändert
Mitarbeiter speichert das Dokument (z.B. STRG+S)
Das geänderte Feld Aufgabe wird in alle Antwortdokumente geschrieben (Zeitpunkt: Anfrage zur Speicherung -> QuerySave)
Eine Validierung verhindert das Speichern
Mitarbeiter verlässt das Hauptdokument ungespeichert

-> Ergebnis: Hauptdokument hat den alten Feldinhalt von Aufgabe, Antwortdokumente den temporären, der nicht gespeichert werden konnte

Dieses Problem umgehst Du mit dem Postsave.

Das unnötige Stampall (falls sich Aufgabe nicht geändert hat) bringt Dir Performancenachteile, höheren Replizieraufwand und eine erhöhte Gefahr von Replizier- und Speicherungskonflikten

Offline SaSaWu

  • Aktives Mitglied
  • ***
  • Beiträge: 140
  • Geschlecht: Männlich
OK, Peter!

Deine Hinweise erscheinen mir sinnvoll, sind aber so (ohne Kenntnisse meinerseits) nicht für mich umsetzbar. Aber: Das Scriptseminar steht für Oktober auf dem Plan und ist dann hoffentlich mein Einstieg in diese "Sphäre"!

Offline Peter Klett

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.713
  • Geschlecht: Männlich
Scriptseminar hört sich gut an.

Trotzdem solltest Du das Script vom Querysave ins Postsave verschieben, damit ist Problem 1 beseitigt.

In Declaration nimmst Du auf:

Dim aufgabe As String

Ins Postopen schreibst Du:

Dim workspace As NotesUIWorkspace
Dim uidoc As NotesUIDocument
Set uidoc = workspace.CurrentDocument
Dim doc As NotesDocument
Set doc = uidoc.Document
aufgabe = doc.Aufgabe (0)

Dein Script (im POSTSave) passt Du so an (das rote ist neu)

If aufgabe <> doc.Aufgabe (0) Then
   'alle Antwortdocs des Backend-Docs werden in die Collection aufgenommen
   Set dc = doc.Responses
   
   'Setze alle Felder der Collection, gespeichert wird automatisch   
   Call dc.StampAll( "Re_Aufgabe" , doc.Aufgabe(0) )
     
   aufgabe = doc.Aufgabe (0)
End If


Mehr ist es nicht ...

Offline SaSaWu

  • Aktives Mitglied
  • ***
  • Beiträge: 140
  • Geschlecht: Männlich
Danke, Peter!

Jetzt fangen aber leider die "Problemchen" schon an:

Im Postsave habe ich die erste Zeile abgeändert in:

Sub Postsave(Source As Notesuidocument, Continue As Variant)

Sonst wäre es ja ein Querysave, richtig? So bekomme ich aber die Meldung "wrong number of arguments". Ohne Kenntnisse kann ich das nicht anpassen!

Außerdem habe ich im Originalscript noch ein weiteres Feld (Mitarbeiter) aufgenommen, das bei Aktualisierungen berücksichtigt wird (siehe Code) und wohl in die If-Schleife integriert werden müsste.

Code
Sub Querysave(Source As Notesuidocument, Continue As Variant)
'------------------------------------------------------------------------------------------------------------------   
'Zweck: Feldwerte werden beim Speichern in alle Antwort-Dokumente übernommen   
'------------------------------------------------------------------------------------------------------------------   
	Dim session As New NotesSession
	Dim db As NotesDatabase
	Dim dc As NotesDocumentCollection
	Dim doc As NotesDocument
	Set db = session.CurrentDatabase
	
	If Source.IsNewDoc Then Exit Sub 'Wenn UIDoc neu ist dann verlasse Script
	
	Set doc = Source.Document 'UIDoc zu Backend-doc
	
	
   'alle Antwortdocs des Backend-Docs werden in die Collection aufgenommen
	Set dc = doc.Responses
	
   'Setze alle Felder der Collection, gespeichert wird automatisch   
	Call dc.StampAll( "Aufgabe" , doc.Aufgabe(0) )
	Call dc.StampAll( "Mitarbeiter" , doc.Mitarbeiter )
	
	
End Sub

Offline Peter Klett

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.713
  • Geschlecht: Männlich
Ok, soweit zu der Aussage von weiter oben, dass Du nur ein StampAll hast ...

Zum PostSave:

Du änderst auf keinen Fall die erste Zeile des QuerySave in PostSave, die Sub PostSave gibt es schon (schau mal links ...), da muss das Script, das zwischen "Sub QuerySave (...)" und "End Sub" steht, rein.

Mitarbeiter ist vermutlich ein Mehrfachwert. Also

(Declarations)

Dim aufgabe As String
Dim mitarbeiter As Variant

Postopen

Dim workspace As NotesUIWorkspace
Dim uidoc As NotesUIDocument
Set uidoc = workspace.CurrentDocument
Dim doc As NotesDocument
Set doc = uidoc.Document
aufgabe = doc.Aufgabe (0)
mitarbeiter = doc.Mitarbeiter '-> hier ohne (0), da Mehrfachwert möglich

PostSave

...
If aufgabe <> doc.Aufgabe (0) Or Join (mitarbeiter) <> Join (doc.Mitarbeiter) Then
   'alle Antwortdocs des Backend-Docs werden in die Collection aufgenommen
   Set dc = doc.Responses
   
   'Setze alle Felder der Collection, gespeichert wird automatisch
   If aufgabe <> doc.Aufgabe (0) Then
      Call dc.StampAll( "Aufgabe" , doc.Aufgabe(0) )
      aufgabe = doc.Aufgabe (0)
   End If
   If Join (mitarbeiter) <> Join (doc.Mitarbeiter) Then
      Call dc.StampAll( "Mitarbeiter" , doc.Mitarbeiter )
      mitarbeiter = doc.Mitarbeiter
   End If
End If


Das ist jetzt nur mal "so schnell eben", damit es funktioniert. Die Ergebnisse des Join würde ich mir natürlich in einer separaten Variablen merken, um das nicht zweimal rechnen zu müssen, und auf ein mehrfaches Verwenden von StampAll würde ich immer verzichten und stattdessen durch die Dokumente gehen, die einzeln anpassen und nur EINMAL speichern. Aber um es verständlicher zu lassen und nicht alles umreißen zu müssen, geht das so natürlich auch.

Offline SaSaWu

  • Aktives Mitglied
  • ***
  • Beiträge: 140
  • Geschlecht: Männlich
Hallo Peter,

nett, dass Du Dich "kümmerst"!

Ich bekomme nun die Meldung "object cariable not set" bei Aufruf des Hauptdokuments. Hier meine aktuellen Einstellungen:

(Declarations)
Code
Dim aufgabe As String
Dim mitarbeiter As Variant

Postopen
Code
Sub Postopen(Source As Notesuidocument)
	
	Dim workspace As NotesUIWorkspace
	Dim uidoc As NotesUIDocument
	Set uidoc = workspace.CurrentDocument
	Dim doc As NotesDocument
	Set doc = uidoc.Document
	aufgabe = doc.Aufgabe (0)
	mitarbeiter = doc.Mitarbeiter 
	
End Sub


Postsave
Code
Sub Postsave(Source As Notesuidocument)
	
	'------------------------------------------------------------------------------------------------------------------   
'Zweck: Feldwerte werden beim Speichern in alle Antwort-Dokumente übernommen   
'------------------------------------------------------------------------------------------------------------------   
	Dim session As New NotesSession
	Dim db As NotesDatabase
	Dim dc As NotesDocumentCollection
	Dim doc As NotesDocument
	Set db = session.CurrentDatabase
	
	If Source.IsNewDoc Then Exit Sub 'Wenn UIDoc neu ist dann verlasse Script
	
	Set doc = Source.Document 'UIDoc zu Backend-doc
	
	
   'alle Antwortdocs des Backend-Docs werden in die Collection aufgenommen
	Set dc = doc.Responses
	
	If aufgabe <> doc.Aufgabe (0) Or Join (mitarbeiter) <> Join (doc.Mitarbeiter) Then
   'alle Antwortdocs des Backend-Docs werden in die Collection aufgenommen
		Set dc = doc.Responses
		
   'Setze alle Felder der Collection, gespeichert wird automatisch
		If aufgabe <> doc.Aufgabe (0) Then
			Call dc.StampAll( "Aufgabe" , doc.Aufgabe(0) )
			aufgabe = doc.Aufgabe (0)
		End If
		If Join (mitarbeiter) <> Join (doc.Mitarbeiter) Then
			Call dc.StampAll( "Mitarbeiter" , doc.Mitarbeiter )
			mitarbeiter = doc.Mitarbeiter
		End If
	End If
	
	
End Sub

Offline Peter Klett

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.713
  • Geschlecht: Männlich
Sorry, habe Deinen Beitrag übersehen.

Im Postopen ist ein Fehler, da fehlt ein New

Sub Postopen(Source As Notesuidocument)
   
    Dim workspace As New NotesUIWorkspace
    Dim uidoc As NotesUIDocument
    Set uidoc = workspace.CurrentDocument
    Dim doc As NotesDocument
    Set doc = uidoc.Document
    aufgabe = doc.Aufgabe (0)
    mitarbeiter = doc.Mitarbeiter
   
End Sub

Besser (und kürzer) wäre allerdings folgendes PostOpen (da Source übergeben wird, hatte ich nicht dran gedacht)

Sub Postopen(Source As Notesuidocument)
   
    Dim doc As NotesDocument
    Set doc = Source.Document
    aufgabe = doc.Aufgabe (0)
    mitarbeiter = doc.Mitarbeiter
   
End Sub

Offline SaSaWu

  • Aktives Mitglied
  • ***
  • Beiträge: 140
  • Geschlecht: Männlich
Sorry? Wer ist denn hier der Hauptnutznießer?  :)

Vielen, vielen Dank! So funktioniert es einwandfrei!

Offline Peter Klett

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.713
  • Geschlecht: Männlich
Sorry? Wer ist denn hier der Hauptnutznießer?  :)
Ich, weil es mir Spaß macht ;)

Offline SaSaWu

  • Aktives Mitglied
  • ***
  • Beiträge: 140
  • Geschlecht: Männlich
Das ist die richtige Einstellung!

Und: ganz meinerseits!

 

Impressum Atnotes.de  -  Powered by Syslords Solutions  -  Datenschutz