Body-Inhalt von ungesendeter Mail lesen?

  • Hallo,


    mittels

    Code
    Call uidoc.FieldAppendText("Body","irgendein Text")


    kann ich bei problemlos Text an den Body anhängen.


    Aber wie kann ich den vielleicht bereits eingegebenen Text auslesen?


    Code
    Set uidoc = ws.Currentdocument
        Set doc = uidoc.Document
    Set body = doc.GetFirstItem("Body")
    s_body = body.Getformattedtext(False,False)


    erzeugt leider den Fehler "Object variable not set", da body kein Object ist, sogar keinen Inhalt hat.




    LG Peter

  • "Ungesendet" heißt i.d.R. auch "ungepseichert", also kann es kein Backend-Dokument geben, also auch kein Item darin.
    Du hast eh schon das UI-Objekt, warum gehst du nicht per FieldGetText dran?

    Life is not a journey to the grave with the intention of arriving safely in a pretty and well-preserved body, but rather to skid in broadside, thoroughly used up, totally worn out, and loudly proclaiming "Wow, what a ride!!! :evil:
    Beschleunigung ist, wenn die Tränen der Ergriffenheit waagrecht zum Ohr hin abfliessen - Walter Röhrl

  • Komme ich denn auch das Body-RT-Object dran?
    Sonst scheitert es gleich danach beim

    Code
    Set rtnav = body.CreateNavigator                Set rtrange = body.CreateRange


    Habe es mit

    Code
    Set body = New NotesRichTextItem( uidoc.Document, "Body" )


    versucht, wobei ich auch vermute, dass ich hier auch nicht viel weiterkomme.
    Jetzt komm die Fehlermeldung: Richtext context position is not defined.


  • Richtext-Items bei ungespeicherten UI-Objekten sind alles andere als schön zu behandeln.
    Ich helfe mir i.d.R. damit, dass ich im Agentencode temporär das Dokument speichere und mir -sofern notwendig- die UNID merke. Dann komme ich ziemlich entspannt an die Backend-Methoden und -Eigenschaften dran.

    Life is not a journey to the grave with the intention of arriving safely in a pretty and well-preserved body, but rather to skid in broadside, thoroughly used up, totally worn out, and loudly proclaiming "Wow, what a ride!!! :evil:
    Beschleunigung ist, wenn die Tränen der Ergriffenheit waagrecht zum Ohr hin abfliessen - Walter Röhrl

  • Wie machst Du das mit dem Speichern?
    Prüfst Du vorher, ob das Dokument schon gespeichert wurde und wenn nicht, dann merkst Du Dir die UNID und löschst das Dokument wieder?
    Ansonsten würden doch nach und nach immer mehr Dokumente in den Entwürfen abgelegt werden, oder?
    Oder kann man auch das Dokument mit "speichern als" vielleicht immer in ein festes Dokument (z.B. persönliches Profildokument) speichern, das immer wieder überschrieben wird?
    Das wäre mir die liebste Methode.

    • Offizieller Beitrag

    Löschen ist so eine Sache ...


    Mit "ModifiedSinceSaved" aus der Klasse NotesUIDocument bekommst du einen boolischen Wert und kannst abfragen, ob das aktuelle UIDokument nach dem letzten speichern verändert wurde.
    Dabei fällt mir gerade auf, dass dies in der 8.x und 9.x Hilfe nicht mehr drin steht. Auf den Klassenpostern zur Version 7 taucht diese Eigenschaft noch auf.


    Wurde das Dokument schon einmal vom Anwender gespeichert, darfst du es auf keinem Fall löschen. Auch speichern ist hier nicht optimal, da du den Stand des Dokumentes änderst.
    Handelt es sich um ein neues Dokument hat das Löschen auch einen Nachteil. Wird danach am UI nichts mehr verändert, dann muss der Anwedner aktiv speichern, denn die Abfrage nach dem Speichern beim Schließen des UI-Dokumentes kommt nicht, denn das UI-Dokument wurde nach dem letzten Öffnen nicht verändert.
    Aber auch da gibt es eine Abhilfe - wieder mit anderen Nachteilen verbunden. Z.B. über ein Feld im UI, welches beim Öffnen verändert wird. Nachteil: jetzt kommt immer die Abfrage nach dem Speichern.


    Gruß
    Dirk

    Rein logisches Denken verschafft uns keine Erkenntnis über die wirkliche Welt.
    Alle Erkenntnis der Wirklichkeit beginnt mit der Erfahrung und endet mit ihr.
    Alle Aussagen, zu denen man auf rein logischen Wegen kommt, sind, was die Realität angeht, vollkommen leer.
    Albert Einstein

  • Deswegen die Frage, ob es die Möglichkeit gibt, das Dokument sozusagen als Kopie zu speichern.
    Dann würde das Original-Dokument, ob schonmal gespeichert oder nicht etc, unangetastet bleiben,
    also kein neuer Stand des Dokuments usw.
    Vielleicht hat jemand einen Code-Schnipsel für mich?

    • Offizieller Beitrag

    fertigen Code habe ich nicht.


    Aber der Ansatz wäre eine leere lokale DB (als temp. Datenbank) mit einer Maske und einem RT-Feld.
    Dort kannst du dann speichern und löschen wie du willst und in dem RT-Feld alles im Frontend oder Backend zusammenbauen und zum Schluß über die Zwischenablage in das "produktive" Dokument kopieren.


    Die temp.-Db kannst du auch noch automatisch anlegen, wenn diese nicht vorhanden ist.


    Gruß
    Dirk

  • Wäre folgender Code ein Ansatz? (Fliegt momentan aber noch mit der Fehlermeldung "Illegal Use of PROPERTY" raus)


  • Dabei fällt mir gerade auf, dass dies in der 8.x und 9.x Hilfe nicht mehr drin steht.


    In der Online-Hilfe ist die Property gelistet.


    Wäre folgender Code ein Ansatz? (Fliegt momentan aber noch mit der Fehlermeldung "Illegal Use of PROPERTY" raus)


    Du holst dir zwar das Profildokument, aber dein Code zeigt nicht, das du es im UI öffnest.

    Life is not a journey to the grave with the intention of arriving safely in a pretty and well-preserved body, but rather to skid in broadside, thoroughly used up, totally worn out, and loudly proclaiming "Wow, what a ride!!! :evil:
    Beschleunigung ist, wenn die Tränen der Ergriffenheit waagrecht zum Ohr hin abfliessen - Walter Röhrl

  • Du holst dir zwar das Profildokument, aber dein Code zeigt nicht, das du es im UI öffnest.


    Muss ich doch auch nicht, oder doch? Mit

    Code
    Set pdoc = db.GetProfileDocument("Dummy")

    öffne ich das Profildokument, sofern vorhanden.
    Und mit

    Code
    Call pdoc.save(False,False)

    lege ich es an, wenn es noch nicht existiert hat und habe in pdoc das aktuelle Profildokument.

  • Wieso musst du das nicht? Ein Computer ist seiner Wortbedeutung nach ein "Berechner" und kein "Rater" oder "Gedankenleser". Willst du, dass er etwas berechnet, sag ihm, was er berechnen soll. Nur zu denken, was er idealerweise berrechnen könnte, ihm das aber nicht zu sagen, ist beim gegenwärtigen Stand der Technik einigermaßen problematisch. Wenn es eines Tages brauchbare KIs gibt (hoffentlich sehr bald) und es dann auch den Domino noch gibt (hoffentlich kein Verse), dann können wir uns das gern nochmal anschauen.
    Bis dahin:

    Zitat

    Set pdoc = db.GetProfileDocument("Dummy")


    "pdoc" ist hier ein Objekt vom Typ NotesDocument, also Backend.


    Zitat

    uidoc.Gotofield("Body")


    Wann und wo hast du das NotesUIDocument, also das Frontend-Objekt, erzeugt?

    Zitat

    Set rtibody = New NotesRichTextItem(pdoc, "Body")
    pdoc.Body = ""
    -->pdoc.Gotofield("Body") ' hier fliegt er raus


    Ja, kein Wunder. Erstens ist -wie in der Hilfe zweifelsfrei nachzulesen ist- GotoField die Methode der NotesUIDocument-Klasse und nicht der NotesDocument-Klasse. Und zweitens: selbst wenn du auf ein NotesUIDocument abzielst, hast du das Objekt nirgendwo instanziiert. Ergo kann er nicht zu einem Feld gehen, das er nicht kennt in einem Dokument, von dem er nix weiß.



    NotesDatabase, NotesView, NotesDocument, ... = Backend.
    NotesUIDatabase, NotesUIView, NotesUIDocument, ... = Frontend.


    Mit "Backend" ist -sehr grob umrissen und technisch nicht einwandfrei- gemeint: alles, was irgendwo auf einem Server oder Client abgespeichert ist. Noch gröber umrissen und genauso wenig technisch vollumfänglich korrekt: das .NSF-File und alles, was da drin vergraben ist.
    Mit "Frontend" ist -sehr grob umrissen und technisch nicht einwandfrei- gemeint: alles, was der User im Client (Notesclient, Browser, ....) sieht, "anfassen" und manipulieren kann.


    Vom Frontend-Objekt aufs zugehörige Backend-Objekt kommen, ist kein Problem:
    NotesUIDatabase.Database => Backendobjekt (NotesDatabase)
    NotesUIDocument.Document => Backendobjekt (NotesDocument)


    Anders herum, also vom Backend- aufs Frontend-Objekt zu kommen, ist stellenweise nicht ganz so trivial, stellenweise auch gar nicht möglich.

    Life is not a journey to the grave with the intention of arriving safely in a pretty and well-preserved body, but rather to skid in broadside, thoroughly used up, totally worn out, and loudly proclaiming "Wow, what a ride!!! :evil:
    Beschleunigung ist, wenn die Tränen der Ergriffenheit waagrecht zum Ohr hin abfliessen - Walter Röhrl

    Einmal editiert, zuletzt von RockWilder ()

  • Ich als Anfänger überlese wohl gerne mal das winzige 'ui' in der Hilfe. Zumal es für mich nicht so recht nachvollziehbar ist, warum eine Funktion Gotofield, wenn es sie doch schon im Frontend gibt nicht auch im Backend geben sollte.
    Für mich bleibt es weiterhin die Herausfoderung, wie ich ein Richtext-Feld im Frontend verändern kann (Suchen und Ersetzen), ohne das eigentliche Dokument im Backend zu verändern z.B. speichern zu müssen.


    Meine Idee war es, das RT-Feld in einem Profildokument zu speichern. Scheitere aber auch hier daran, wie ich den unveränderten Inhalt des RT-Feldes darin speichern kann.
    Und wenn das geschafft sein sollte, werde ich wahrscheinlich auch wieder das Problem haben, wie ich nun den Inhalt des Profildokuments wieder in das Frontend-RT-Feld reinbekomme ohne zu speichern.


    Ich hätte gedacht, dass es im Internet haufenweise Beispiele geben müsste oder dass jeder hier, der ganz sicher besser programmieren kann als ich, mir ad hoc ein Code-Schnipsel zeigen könnte, wie RT-Felder im Frontend zu verändern sind.


    Im Moment komme ich keinen einzigen Schritt weiter, es müsste mal eine Art Wiki geben, wie man mit Richtext-Feldern umgehen kann, Frontend wie Backend.


    LG von einem etwas gefrustetem Peter

  • Zumal es für mich nicht so recht nachvollziehbar ist, warum eine Funktion Gotofield, wenn es sie doch schon im Frontend gibt nicht auch im Backend geben sollte.


    Weil es im Backend keine Felder gibt, sondern nur Items. Der Unterschied ist zugegebenermaßen nicht unbedingt auf Anhieb verständlich.
    Ein "Feld" ist ein Konstrukt, in dem der User etwas eingeben kann. So, wie bspw. das "Feld", in das ich gerade diese Antwort eintippe. Oder um im Beispiel zu bleiben: das "Body"-Feld der Mailmaske


    Im Backend kann ich naturgemäß nicht tippen. Deswegen heißen diese Konstrukte dort "Items" und sind im Grunde einfach nur eine Art von reserviertem Speicherplatz, wo etwas drinsteht (oder auch nicht). Erst im UI werden die Items gegen die "Felder" gemappt, die du in einer Maske zum Zwecke der Eingabe (im Falle von berechneten Feldern: zur Anzeige) angelegt hast. Ein "Item" wird in den Dokumenteneigenschaften in alphabetischer Relation zu den anderen Items gelistet. In einer Maske kann das "Feld" B vor dem "Feld" A kommen.


    Es kann durchaus Items geben, die durch keinerlei "Feld" in einer Maske widergespiegelt werden. Schau dir bspw. dazu einfach mal die Mail-Maske an, was es da an "Feldern" hat und vergleiche dazu die Dokumenteneigenschaften einer Mail. Du wirst auf eine Reihe von Items stoßen, die Inhalte speichern, die aber -zum Teil aus gutem Grunde- nicht zum Bearbeiten gedacht sind. Dazu gehören zuvorderst alle Items die mit einem oder mehreren Dollar-Zeichen anfangen. So ist bspw. das Item "$UpdatedBy" ein gutes Beispiel dafür, dass es zwar im Dokument diesen reservierten Speicherbereich gibt, ein User da aber keinesfalls dran rum zu editieren hat, in der Regel auch keine Möglichkeit dazu hat.


    Und wenn all das zu theoretisch sein sollte (sorry, meine pädagogischen Fähigkeiten sind eher ausbaufähig, deswegen mag dieser Erguss weniger verständlich rüberkommen, als geplant): "GoTo"<irgendwas> zeigt immer eine UI-Funktion an. Als Eselsbrücke lässt sich das so merken: wenn ich übers Ansichts-Menü hinnavigieren kann (Ansicht, Dokument, Feld, ...), hat es ein entsprechendes "GoTo"<irgendwas> Gegenstück. Das Ansichtsmenü habe ich naturlich nur im Client (sprich: im UI), auf dem Server, in den Speicherbereichen, kann ich nichts ansehen und nicht navigieren.


    Zitat

    Für mich bleibt es weiterhin die Herausfoderung, wie ich ein Richtext-Feld im Frontend verändern kann (Suchen und Ersetzen), ohne das eigentliche Dokument im Backend zu verändern z.B. speichern zu müssen.


    In dem Zusammenhang: google mal nach "SaveOptions".
    Die Möglichkeit, deine Anforderung zu realisieren, gibt es durch aus. Die Frage ist nur, "wozu?". Üblicherweise sollen Änderungen (Aktualisierungen) doch auch gespeichert werden, damit der nächste User den entsprechenden Stand der Dinge hat und nicht mit "veralteten" Daten arbeitet. Und wenn das Feld nur temporäre Daten halten soll: braucht es zwingend ein RT-Item dafür? RT-Items zu manipulieren, ist manchmal nicht ganz trivial. Reine Textfelder sind bedeutend einfacher...

    Life is not a journey to the grave with the intention of arriving safely in a pretty and well-preserved body, but rather to skid in broadside, thoroughly used up, totally worn out, and loudly proclaiming "Wow, what a ride!!! :evil:
    Beschleunigung ist, wenn die Tränen der Ergriffenheit waagrecht zum Ohr hin abfliessen - Walter Röhrl

    Einmal editiert, zuletzt von RockWilder ()

  • Erstmal danke an Torsten für das PDF-Dokument. Ich werde mich mal in die Beispiele dort vertiefen.
    Danke auch an RcokWilder für die ausführliche Erklärung. Ich glaube sonstwo ausser Notes wird nicht zwischen Feldern und Items unterschieden. Zumindest heissen bei mir die Datenbankfelder, egal ob MySQL, Oracle oder MSSQL auch Felder. Aber seis drum. Ich habs verstanden.



    Die Möglichkeit, deine Anforderung zu realisieren, gibt es durch aus. Die Frage ist nur, "wozu?". Üblicherweise sollen Änderungen (Aktualisierungen) doch auch gespeichert werden, damit der nächste User den entsprechenden Stand der Dinge hat und nicht mit "veralteten" Daten arbeitet. Und wenn das Feld nur temporäre Daten halten soll: braucht es zwingend ein RT-Item dafür? RT-Items zu manipulieren, ist manchmal nicht ganz trivial. Reine Textfelder sind bedeutend einfacher...


    Stell dir vor, ein Benutzer sendet eine Mail immer in der selben Form. Diese Vorlage ist in den Vorgaben als Signatur hinterlegt. Allerdings sind in der Vorgabe noch einige Platzhalter, die er durch korrekte Eingaben ersetzen muss. Das können Namen, eine Ressource oder auch Begründungstexte sein. Diese soll er der Bequenlichkeit halber über Buttons auswählen können. Am Ende wird das Ganze als Mail versendet. Erst dann soll das Dokument auch erst gespeichert werden.


    LG Peter

  • @PeterSchneider


    Nur um mal bei deinem Beispiel Datenbank zu bleiben:


    Es gibt dort Datenbankfelder, die entsprechen den Items in Notes, in ein Datenbankfeld kannst du aber nicht springen, sondern nur Daten hineinschreiben oder herauslesen.
    Für eine Datenbank gibt es dann ein Frontend mit entsprechenden Eingabefeldern, diese entsprechenden den Fields in Notes, in die du dann auch hineinspringen kannst.


    In die Datenbankfelder schreibst du dann mit Datenbankfunktionen, in Notes Backend Klassen, in die Frontendfelder schreibst du dagegen mit Frontendfunktionen, in Notes Frontend bzw UI Klassen.


    Und dann gibt es eine Programmlogik welche die Eingabefelder mit den Datenbankfeldern verbindet, d.h. welches Eingabefeld wird in welches Datenbankfeld geschrieben.


    Du siehst also, daß es die gleiche Logik überall gibt, wo es Frontend und Backend gibt. Es ist nur eine Frage der Benennung.


    Und was du als letztes beschreibst ist eine ganz klare Frontendgeschichte, d.h. bau den Text zusammen und verwende dann die Frontendfunktionen um diesen in das entsprechende Feld zu schreiben.


    Wenn du aus einer Vorlage auch Formatierungen übernehmen willst, dann musst du den Text von dort auch im Frontend kopieren, d.h. mit Frontendfunktionen.


    Stell dir einfach mal vor wie du es manuell machen würdest:


    - Öffnen Vorlage
    - Markieren Vorlagetext
    - Kopieren Vorlagetext in Zwischenablage
    - Schliessen Vorlage
    - Erstellen neues Dokument
    - Springen in Zielfeld
    - Einfügen von Text aus Zwischenablage


    Und genauso kannst du es auch per Script machen. Schau dir zu den genannten Schritten einfach mal die UI Klassen an

  • - Öffnen Vorlage
    Die Vorlage wird vom Benutzer automatisch geöffnet indem er eine neue Mail schreiben oder auf eine Mail antworten möchte.
    - Markieren Vorlagetext

    Code
    uidoc.Gotofield("Body")    Call uidoc.Selectall()


    - Kopieren Vorlagetext in Zwischenablage

    Code
    Call uidoc.Copy()


    - Schliessen Vorlage
    hier dürften wieder Probleme anfangen: Ich müssten so einiges an Infos mitkopieren: From-Feld, Datum, Betreff, Empfänger, CC, BCC, ...
    - Erstellen neues Dokument
    hier war mein Ansatz über das Profildokument, aber ich bekomme den Inhalt vom Body nicht gespeichert.
    Zudem weiß ich nicht, wie ich für mein Suchen&Ersetzen das UI-Body-Feld ansprechen könnte. Für das Backend-Body-Feld benutze ich die RT-Navigator und RT-Range Funktionen.
    - Springen in Zielfeld
    - Einfügen von Text aus Zwischenablage


    Wenn ich es denn schaffen würde, den Inhalt des UI-Body-Felds in ein eigenes TMP-Dokument (ob Profildokument oder "normales" Dokument) zu speichern, dürfte ich es geschafft haben.
    Dann könnte ich uidoc.importitem() verwenden, um den Inhalt des TMP-Dokuments in das UI-Body-Feld reinzubekommen.
    Wenn ich mit

    Code
    Set temp_doc = New NotesDocument(db)


    ein neues Dokument erstelle, komme ich nicht an das UI-Dokument ran um das temp_ui_doc.Paste() nutzen zu können, oder?
    Und

    Code
    Set body = New NotesRichTextItem(temp_doc, "Body")
    Call body.Appendrtitem(rtbody)


    funktioniert nicht, da ich nicht an den RT-Inhalt vom UI-Body-Feld bekomme, oder?


    LG Peter

    • Offizieller Beitrag

    Von einem Backend-Dokument kommst du über diese beiden Wege zum Frontend-Dokument:


    set uidoc = ws.Editdocument(...)
    set uidoc = ws.ComposeDocument(...)


    mit
    uidoc.GotoField ... gelangst du in ein Feld, mit
    uidoc.SelectAll ... markierst du alles, mit
    uidoc.Copy ... kopierst du den markierten Teil in die Zwischenablage und mit
    uidoc.Paste ... wird der Teil in der Zwischenablage eingefügt.


    Gruß
    Dirk