Seite 1 von 1

[erledigt] Base-Formular: Eingabe verwerfen

Verfasst: So, 21.10.2012 17:04
von juetho
Nach der Eingabe in einem Datumsfeld (an eine Tabelle gebunden) möchte ich prüfen, ob die Eingabe zulässig ist. Im Zweifelsfall wird der Anwender über einen Dialog gefragt: "Wollen Sie wirklich diese Änderung vornehmen?" Wenn ja, wird die Eingabe übernommen, andernfalls soll sie verworfen werden und der bisherige Feldinhalt unverändert bleiben.

Ich habe die Prüfung an das Ereignis "Vor dem Aktualisieren" gebunden, weil ich dort beide Werte (vorher und nachher) abfragen kann - siehe "ist modifiziert" prüfen. Das Makro sieht (verkürzt) so aus:

Code: Alles auswählen

dim bchange as Boolean
oForm = oEvent.Source.Parent
bchange = ...    ' einfache Prüfung liefert hier true oder false
oldDate = CDate(oEvent.Source.BoundField.String)    ' die beiden Vergleichswerte
newDate = CDate(oEvent.Source.Text)
rem bei manchen Situationen Rückfrage über Dialog
if not bchange then
  oDlgDesc = globalscope.DialogLibraries.Standard.dlgConfirm
  dlg = CreateUnoDialog( oDlgDesc )
  bchange = dlg.execute       ' OK = ja, andernfalls = Nein
end if

if bchange then     ' Änderung tatsächlich ausführen
  oForm.updateInt(3, newDate.Year)
   ...  
else
  rem Änderung rückgängig machen
' xray oEvent.Source.BoundField
' xray oldDate
' oEvent.Source.BoundField.updateDate(oldDate)
  oForm.updateDate(6, oldDate)
end if
Alles, was ich im else-Zweig versuche, führt zum Basic-Laufzeitfehler "Objektvariable nicht belegt". Einzelprüfungen über xray oder den Basic-Debugger zeigen, dass alle diese Variablen zur Verfügung stehen; vermutlich die Fehlermeldung falsch. Ich könnte verstehen, dass updateXXX im Ereignis "Vor dem Aktualisieren" nicht möglich ist. Ich finde aber keine Methode, die eine Änderung nur für diese einzelne Spalte (im aktuellen Datensatz) verhindert.

Was tun? Jürgen

Nachtrag: Auch im if-Zweig wird oForm.updateXXX benötigt. Ich habe jetzt festgestellt, dass diese Änderungen am gleichen Fehler scheitern. Als ich den Dialog noch nicht eingebaut hatte, hatte es funktioniert. Offensichtlich bringt der Dialog den Zugriff auf oForm durcheinander.

Nachtrag 2: Wenn es doch so einfach wäre. Es sieht so aus, als ob doch nicht der Dialog schuld wäre, sondern das Ereignis. Ich werde wohl doch auf "Fokusverlust" zurückgehen müssen und auf die genaue Anzeige (Zustand alt und neu) verzichten.

Nachtrag 3: Ich verzweifle noch. Jetzt bin ich bei "Fokusverlust" ohne Dialog - und oForm ist auch im if-Zweig nicht mehr belegt. Das war für heute mein letzter Versuch. :cry:

Aber vielleicht gibt es eine andere, saubere Lösung.

Re: Base-Formular: Eingabe verwerfen

Verfasst: So, 21.10.2012 19:49
von F3K Total
Hallo Jürgen,
dieses Makro scheint auf "vor dem Aktualisieren" zu funzen.

Code: Alles auswählen

Sub S_checkmodified (oEvent)
    dim newdate as new com.sun.star.util.Date

    oField = oEvent.Source
    oForm = oField.Parent
    snewdate = CDate(oField.Text)
    
    newDate.year = year(snewdate)
    newDate.month = month(snewdate)
    newDate.day = day(CDate(snewdate)

    if msgbox ("Soll das Datum wirklich auf "+snewDate+" geändert werden",36,"Datum ändern?") = 6 then
        oForm.updatedate(6, newDate)
        oForm.updaterow
    else
        nrow = oForm.row
        oform.reload
        oform.absolute(nrow)
    endif

end sub
Gruß R

Re: Base-Formular: Eingabe verwerfen

Verfasst: So, 21.10.2012 20:02
von DPunch
Servus

Wieso bist Du so sehr davon überzeugt, dass oForm nicht belegt sein soll?

Ich sehe z.B. in Deinem Code ein

Code: Alles auswählen

newDate.Year
obwohl die Objektvariable "newDate.Year" nicht belegt ist (newDate ist kein Date-Struct).
Ich sehe in Deinem else-Zweig ein

Code: Alles auswählen

oForm.updateDate(6, oldDate)
obwohl oldDate kein Date-Struct ist.

Beides Fehler im Quellcode, die die beschriebene Fehlermeldung hervorrufen.

Nachtrag: F3K hat Dir die vermutlich die Lösung Deiner Probleme schon mundgerecht vorgelegt 8)

Re: Base-Formular: Eingabe verwerfen

Verfasst: So, 21.10.2012 20:18
von F3K Total
DPunch hat geschrieben:F3K hat Dir die vermutlich die Lösung Deiner Probleme schon mundgerecht vorgelegt
Aber du hast es, wie schon so oft, mit zwei, drei Worten erklärt! :D
Ja, ja ... die Sache mit den Daten (Mehrzahl von Datum) ... ist doch immer wieder eine Freude, es gibt einfach zuviele verschiedene Formate.
Der Clou ist ja, dass man z.B. die Datumsspalte einer DB-Tabelle sowohl mit updateDate und einem wie oben gearteten Date-Struct befüllen kann, als auch z.B. mit einem updateString ala '2012-10-31'.

Gruß Rik

Re: Base-Formular: Eingabe verwerfen

Verfasst: Mo, 22.10.2012 09:54
von juetho
DPunch hat geschrieben:Wieso bist Du so sehr davon überzeugt, dass oForm nicht belegt sein soll?
Bei meinen Versuchen hatte ich verschiedene Anweisungen aufgeteilt und einzeln abgefragt (mit msgBox oder xray oder Debugger). Weil die beiden "Datümer" angezeigt wurden, habe ich vermutlich oForm die Schuld gegeben.
(newDate ist kein Date-Struct).
Einige Anzeigen in xray und Formulierungen in der OO-Hilfe ließen mich davon ausgehen, dass Date ein eigenständiger numerischer Datentyp ist (was ich in der API nicht überprüft hatte). Wenn es sich dagegen immer um ein Struct handelt, muss ich natürlich anders vorgehen - beispielsweise mit einer dim-Anweisung wie in Riks Vorschlag.
F3K Total hat geschrieben:

Code: Alles auswählen

    if msgbox ("Soll das Datum wirklich auf "+snewDate+" geändert werden",36,"Datum ändern?") = 6 then
Diese Lösung mit msgBox statt Dialog ist in der Tat einfacher. Ich hatte wohl Tomaten auf den Augen, als ich vergeblich nach einer entsprechenden msgBox-Gestaltung gesucht hatte (statt einfach in der OO-Hilfe nachzuschauen).
F3K Total hat geschrieben:

Code: Alles auswählen

        oForm.updatedate(6, newDate)
Warum muss/soll updateDate im if-Zweig benutzt werden? Wenn ich die Ereignisse richtig verstehe, wird durch Fokusverlust (einem späteren Ereignis) sowieso der neue Wert übernommen. Also ist es doch nicht notwendig, diesen Wert ausdrücklich zuzuweisen, oder?
F3K Total hat geschrieben:

Code: Alles auswählen

    else
        nrow = oForm.row
        oform.reload
reload wollte ich vermeiden (das ist einer der Auslöser für meine Lösungsversuche): In der Praxis ist das Datumsfeld, um das es hier geht, das erste Feld im Formular und wird in der Regel als erstes bearbeitet. Beim Arbeiten mit Maus könnte aber durchaus ein anderes Feld schon geändert worden sein; und diese Änderung wäre verloren. Aber wenn es keine ausdrückliche Anweisung wie oform.reset/reject oder einen Umweg gibt, muss es wohl so sein.

Recht herzlichen Dank jedenfalls euch beiden für Vorschläge, Fehlerhinweise und Erläuterungen! Gruß Jürgen

Re: Base-Formular: Eingabe verwerfen

Verfasst: Mo, 22.10.2012 11:36
von juetho
So, ich habe jetzt die Vorschläge beim Ereignis "Vor dem Aktualisieren" umgesetzt, Sowohl oldDate als auch newDate hole ich als Strings und übertrage die Werte (wie von F3K vorgeschlagen) in date-Strukturen:

Code: Alles auswählen

soldDate = CDate(oEvent.Source.BoundField.String)
snewDate = CDate(oEvent.Source.Text)
Das "Änderung verwerfen" im else-Zweig am Ende habe ich so gelöst:

Code: Alles auswählen

  oForm.updateDate(6, oldDate)
  oForm.updateRow
Alles funktioniert wunschgemäß; ich hoffe, dass nicht später irgendwelche unerwünschten Nebenwirkungen auftauchen. Nochmals herzlichen Dank für die Unterstützung! Jürgen

Re: Base-Formular: Eingabe verwerfen

Verfasst: Di, 23.10.2012 23:40
von DPunch
Servus
F3K Total hat geschrieben:die Sache mit den Daten (Mehrzahl von Datum) ... ist doch immer wieder eine Freude, es gibt einfach zuviele verschiedene Formate.
Der Clou ist ja, dass man z.B. die Datumsspalte einer DB-Tabelle sowohl mit updateDate und einem wie oben gearteten Date-Struct befüllen kann, als auch z.B. mit einem updateString ala '2012-10-31'.
Letztendlich ist die Möglichkeit, das Datumsfeld auch per "updateDate" mit einem Date-Struct befüllen zu können, eine Komfortfunktion, die genau diese "Freude" mit den Datumsformaten lindern soll.
Da vermutlich nicht ein einziges DBMS mit diesem Date-Struct umgehen kann, wird daraus vor der Weitergabe an die Datenbank sowieso ein zum verlangten Datumsformat kompatibler String generiert, was Dir eben den Ärger mit den verschiedenen Formaten erspart.
Intern wird aus der updateDate-Anweisung also eine updateString-Anweisung mit einem Wert ala

Code: Alles auswählen

dateStruct.Year & "-" & dateStruct.Month & "-" & dateStruct.Day
Daher auch die Fehlermeldung "Objektvariable nicht belegt", wenn man der updateDate-Anweisung eine Variable übergibt, die eine der Properties Year/Month/Day nicht kennt, wie z.B. einen einfachen String oder eine Zahl.

Re: [erledigt] Base-Formular: Eingabe verwerfen

Verfasst: Mi, 24.10.2012 09:02
von juetho
Das ist damit eine weitere Erklärung für meine Verwirrung: Ich habe Date/Datetime als eigenständigen Datentyp kennengelernt (der auf Zahlen basiert), und zwar sowohl bei Datenbanken als auch bei Programmiersprachen (Delphi, C# bzw. .NET). Damit kann es ebenfalls Probleme mit den String-Darstellungen geben; aber ein String ist eben kein Datum. Wenn in Xray ein Datum als Typ=date und Wert=20120927 angezeigt wird, hatte ich diesen Wert nicht als Struct (und erst recht nicht als String), sondern als einen eigenständigen Typ interpretiert. Aber jetzt weiß ich Bescheid, danke nochmals! Jürgen

Re: [erledigt] Base-Formular: Eingabe verwerfen

Verfasst: Mi, 24.10.2012 12:29
von DPunch
Servus
juetho hat geschrieben:Wenn in Xray ein Datum als Typ=date und Wert=20120927 angezeigt wird, hatte ich diesen Wert nicht als Struct (und erst recht nicht als String), sondern als einen eigenständigen Typ interpretiert.
Date ist weder ein Struct noch ein String, sondern ein eigenständiger Datentyp, so wie com.sun.star.util.Date ein Objekt ist.
Die updateDate-Anweisung erfordert dabei letzteres.

Re: [erledigt] Base-Formular: Eingabe verwerfen

Verfasst: Mi, 24.10.2012 13:19
von juetho
DPunch hat geschrieben:Date ist weder ein Struct noch ein String, sondern ein eigenständiger Datentyp, so wie com.sun.star.util.Date ein Objekt ist.
Siehe dagegen struct Date. In OOP sind sowieso alles Objekte. (Aber noch länger müssen wir uns wohl nicht über Begriffe streiten. :) ) Jürgen

Re: [erledigt] Base-Formular: Eingabe verwerfen

Verfasst: Mi, 24.10.2012 14:31
von DPunch
Servus
juetho hat geschrieben:Siehe dagegen struct Date
Und was soll der Link mir sagen? Ein Struct ist ein Objekt vom Typ Struct. Ein (Basic-)String dagegen ist kein Objekt vom Typ String, sondern ein String.

Code: Alles auswählen

	Dim a as new com.sun.star.util.Date
	MsgBox TypeName(a)
juetho hat geschrieben:In OOP sind sowieso alles Objekte
Das gilt vielleicht für eine handvoll Programmiersprachen und keine davon steht meines Wissens nach in irgendeiner Verbindung zu OOo.
juetho hat geschrieben:Aber noch länger müssen wir uns wohl nicht über Begriffe streiten
Meine Absicht ist nicht, zu streiten, sondern Dein Missverständnis aufzuklären, das Fass hast Du aufgemacht ;)