DB-Update über Formulare

Antwort erstellen


BBCode ist eingeschaltet
[img] ist ausgeschaltet
[url] ist eingeschaltet
Smileys sind ausgeschaltet

Die letzten Beiträge des Themas
   

Ansicht erweitern Die letzten Beiträge des Themas: DB-Update über Formulare

Re: DB-Update über Formulare

von F3K Total » Di, 22.03.2011 19:59

Hallo DPunch,

vielen, vielen Dank für die ausführliche Beschreibung und dafür, dass Du Dir die Mühe gemacht hast.
Selbstverständlich ist das nicht.

Mir und vielen anderen werden Deine guten Erklärungen definitiv helfen, gute Formulare zu gestalten.

Klasse !!!

Beste Grüsse von Rik

PS:
habe die Nummer mit dem .Command:

Code: Alles auswählen

        oForm.Command = sql
        oForm.CommandType = 2
        oForm.execute
        oForm.reload
gerade ausprobiert um verschiedene "Filter" zu setzen, klappt prima!
Dabei habe ich festgestellt, dass man den CommandType auf 0 setzen muß wenn man den "Filter" wieder entfernen will.

Re: DB-Update über Formulare

von DPunch » Di, 22.03.2011 18:17

Aloha

Code: Alles auswählen

oform.updateString(3,"neuerString")
Aktualisiert das gebundene Feld der Spalte 3 mit dem String "neuerString". updateInt, updateBoolean etc funktionieren analog dazu.
Dabei ist zu beachten, dass z.B. ein Text (bzw Char/Varchar)-Feld in der Datenbank auch entsprechend mit updateString angesprochen werden sollte.
Intern passiert dies bei jedem Tastendruck in einem gebundenen Feld automatisch, in einem Makro muss zwingend dafür gesorgt werden, dass tatsächlich das gebundene Feld geändert wird, nicht nur z.B. der angezeigte Text in einer TextBox. Ansonsten "weiss die Datenbank nicht", dass überhaupt Änderungen vorgenommen wurden. Alternative Möglichkeiten zum updateX hatte ich ja bereits etwas weiter oben genannt.

Code: Alles auswählen

oform.UpdateRow()
Schreibt die aktuellen Daten aller gebundenen Felder in die Datenbank zurück. Im normalen Formularnavigator passiert dies z.B. durch einen Wechsel des Datensatzes.

Code: Alles auswählen

oform.RefreshRow()
Liest die aktuellen Daten des Datensatzes aus der Datenbank aus. Vergleichbar mit der Navigator-Funktion "Änderungen rückgängig". Änderungen am aktuellen Datensatz gehen verloren, wenn sie nicht vor in die Datenbank geschrieben wurden.

Code: Alles auswählen

oform..Reload()
Lädt das Formular neu. Ist z.B. notwendig nach dem Setzen von Filtern per Makro.

Code: Alles auswählen

oform.isNew
Überprüft, ob ein neuer Datensatz angelegt wurde.
So kannst Du z.B. mit der Abfrage

Code: Alles auswählen

If oForm.isNew Then
  oForm.insertRow
ElseIf oForm.isModified Then
  oForm.updateRow
End If
einen Datensatz ändern oder anlegen, je nachdem, wo sich der Cursor gerade befindet.
oForm.isNew wird immer dann als True ausgewertet, wenn sich der Cursor auf InsertRow befindet (also Datensatz anlegen) und ein Eintrag in mind. einem gebundenen Feld stattgefunden hat - s.o., das kann z.B. durch einen Tastendruck oder durch die updateX-Methode geschehen.
oForm.isModified wird entsprechend als True ausgewertet, wenn Änderungen an mind. einem gebundenen Datenfeld eines bestehenden Datensatzes stattgefunden haben.
Das Aufrufen von .updateRow bei einem neuen Datensatz führt zu einem Fehler, andersherum genauso.

Code: Alles auswählen

oForm.setString
Wird benötigt zur Arbeit mit Parametern.
z.B. wäre folgendes möglich:

Code: Alles auswählen

	oDoc = thisComponent
	oForm = oDoc.Drawpage.Forms(0)
	oForm.Command = "SELECT * FROM ""meineTabelle"" WHERE ""ID"" = ?"
	oForm.CommandType = 2
	oForm.setInt(1,2)
	oForm.execute
Das Fragezeichen steht dabei als Platzhalter für einen Parameter, per .setInt(1,5) wird beim Ausführen der Abfrage (.execute) das 1. gefundene Fragezeichen durch eine 5 ersetzt.
Anstatt direkt mit Filtern o.Ä. zu arbeiten und jedes Mal einen neuen Filtertext setzen zu müssen, kannst Du einfach nur entsprechend einmal die Abfrage festlegen (.Command) und beim Setzen der Filter brauchst Du dann lediglich den Paramter anzupassen (.setInt(1,x)) - analog dazu bei setString etc.
Der Unterschied zum Filter ist, dass per Filter nur die darauf zutreffenden Datensätze des ResultSets im Formular angezeigt werden und durch einfaches Deaktivieren alle Daten wieder sichtbar werden, whrend bei dieser Methode das ResultSet, und somit quasi das Formular selber, nur die zutreffenden Datensätze enthält.

Re: DB-Update über Formulare

von F3K Total » So, 20.03.2011 20:01

Hallo, ja, das ist schade, ich habe auch noch keine Dokumentation dazu gefunden.

Mich würde vor allem interessieren, wann und in welcher Reihenfolge man die folgenden Befehle verwendet:

Code: Alles auswählen

.UpdateInt(), .UpdateBoolean(),.UpdateString ...
.UpdateRow()
.RefreshRow()
.Reload()
.isnew
Kannst Du vielleicht in wenigen Worten beschreiben, was die machen?
Was genau ist der Unterschied zwischen UpdateRow und RefreshRow?

Danke
Gruß Rik

Re: DB-Update über Formulare

von DPunch » So, 20.03.2011 14:21

Aloha
F3K Total hat geschrieben:Kann mir vielleicht einer von Euch einen Tip geben, wo ich eine verständliche (Klartext, deutsch) Beschreibung der Properties und Methoden herbekomme? Und vielleicht einfache Beispiele, wie meines, für die Anwendung?
Dafür wüsste ich keine Quelle.
XRay bietet aber einen Knopf "SDK documentation", der direkt die entsprechende Seite der API im Browser öffnet - dort findet sich die Beschreibung zu der ausgewählten Methode / Eigenschaft - allerdings auf englisch und nur selten mit Beispielen.

Re: DB-Update über Formulare

von F3K Total » Do, 17.03.2011 20:37

Hallo DPunch, hallo Maddin,

da ich Autodidakt bin, ist mir die Verwendung einiger der Methoden und Properies, die ich über XRay sehen kann, nicht klar. Ich benutze sie zwar, weiß aber manchmal nicht genau was passiert, muß daher insbesondere bei der Reihenfolge oft herumprobieren.

Besonders über die Datenbeeinflussenden möchte ich gerne mehr wissen:
Was ist z.B der Unterschied zwischen SetString und UpdateString?
Wann und in welcher Reihenfolge führt man z.B. UpdateBoolean, UpdateRow, InsertRow, RefreshRow, Reload aus?

Kann mir vielleicht einer von Euch einen Tip geben, wo ich eine verständliche (Klartext, deutsch) Beschreibung der Properties und Methoden herbekomme? Und vielleicht einfache Beispiele, wie meines, für die Anwendung?
Darum bedeutet der Befehl:

Code: Alles auswählen

 oform.updateString(3,oKostenstelle)
eigentlich nicht weiter als: Trage den eben aus dem Listenfeld ausgelesenen String "oKostenstelle" in die Spalte "3" der an das Formular gebundenen Tabelle ein.
Danke Rik

Re: DB-Update über Formulare

von MaddinR » Do, 17.03.2011 19:33

Aloha ahiahi
DPunch hat geschrieben:Die Arbeit mit der Datenbank geschieht allerdings auf einer anderen Ebene als der der blossen Darstellung des GridControls in Deinem Formular.
Ja... jetzt schliesst sich der Kreis... und mit dem von Dir erklärten Hintergrund ist das auch nicht unkomfortabel. Ich habe mehr als 1 Jahrzehnt mit der MFC gearbeitet, u.a. mit der CRecordSet-Klasse und dem MSFlexGrid unter Visual C++ auf MS-SQL-Server. DA ist das ja genauso, das Grid hat auch erst mal nix mit dem Recordset zu tun, lesen und schreiben von Feldinhalten findet primär ebenso direkt auf dem Recordset statt, das Grid dient allenfalls dazu, die RecordID des aktuellen Satzes zu liefern. Aber irgendwie hatte ich hier eine vielleicht etwas verquere Erwartungshaltung... und wenn man jahrelang mit eigenen, selbsterstellten und hoch-komfortablen Wrappern arbeitet, dann etabliert sich im Geiste eine Realität, die in Wahrheit nur eine subjektive Realität ist....

Ich hab mich gerade erst mal geschüttelt, bei der Erkenntnis wie einfach die Gridzelle ersetzt werden kann... Du (und natürlich auch F3KTotal) hast mir viel geholfen.

Danke!

vg, Maddin

Re: DB-Update über Formulare

von DPunch » Do, 17.03.2011 15:15

Aloha
MaddinR hat geschrieben:getByName ( aName as string ) ergibt komfortabel den (Zell-)Wert des Grids(...)sowas wie setByName(string ColumName, Variant NewVal)
Du wirfst da etwas durcheinander.
Mit "getByName" erhältst Du nicht den Wert der über "aName" identifizierten Spalte, sondern das "Spalten"-Objekt selber, von daher ist der Dir vorschwebende Weg eben nicht gangbar.
Das Interface (bzw die Interfaces), das die Methoden wie "getByName", "replaceByName", "getByIndex" etc bereitstellt hat erstmal rein gar nichts mit dem DataGrid oder der Datenbank per se zu tun und kann daher natürlich auch keine derartige Methode "setByName" beinhalten. Das hat auch nichts mit Gettern und Settern zu tun, denn es geht hier nicht um Werte, die gesetzt oder ausgelesen werden - "getByName" ist lediglich eine komfortable Methode, auf eine Liste von Elementen zuzugreifen, da man in der Regel ja nunmal nicht immer weiss, an welcher Stelle dieser Liste sich das gewünschte Element befindet.
Was natürlich ausser Frage steht, ist, dass man einem GridControl theoretisch eine solche Methode zur Verfügung stellen könnte - ob das notwendig ist, sei mal dahingestellt.
MaddinR hat geschrieben:Gibt es eine Funktion, die genauso komfortabel den alten Zellwert mit einem neuen ersetzen kann
Nun, genauso wie Du mit

Code: Alles auswählen

x = oGrid.getbyName("dbTextfeld").Value
"komfortabel" Deinen Spalten- bzw Zellwert auslesen kannst, kannst Du natürlich auch mit

Code: Alles auswählen

oGrid.getbyName("dbTextfeld").Value = x
diesen Wert setzen, zumindest was das GridControl angeht.

Die Arbeit mit der Datenbank geschieht allerdings auf einer anderen Ebene als der der blossen Darstellung des GridControls in Deinem Formular.
Insofern musst Du dem GridControl auch noch mitteilen, dass die Daten zurückgeschrieben werden müssen, z.B. per

Code: Alles auswählen

oGrid.getbyName("dbTextfeld").Value = x
oGrid.getbyName("dbTextfeld").Commit(True)
oder Du gehst direkt über des gebundene Feld dieser Spalte per

Code: Alles auswählen

oGrid.getbyName("dbTextfeld").BoundField.updateInt(x)
Die Notwendigkeit dieser Zeilen mag in Deinen Augen den Komfort mindern, unlogisch oder schlecht ist daran allerdings nichts.
Die einfachste und kürzeste Variante bleibt aber dennoch die von F3K Total schon erwähnte ohne den Umweg über das GridControl, nämlich direkt über das ResultSet des Formulars.

Re: DB-Update über Formulare

von MaddinR » Do, 17.03.2011 13:24

Aloha kakahiaka
DPunch hat geschrieben:Aloha
Das GridControl hält in diesem Container die vorhandenen Spalten vor. Daraus ergibt sich, dass getByName und replaceByName den Zugriff auf diese Spalten des GridControls erlaubt.
So kannst Du z.B. per....*snip*
Ok... soweit habe ich das nun auch verstanden. Nur ein Frage ist geblieben... getByName ( aName as string ) ergibt komfortabel den (Zell-)Wert des Grids, also aktueller Record (Row) und Spalte (Column).
Gibt es eine Funktion, die genauso komfortabel den alten Zellwert mit einem neuen ersetzen kann... sowas wie setByName(string ColumName, Variant NewVal) auf dem aktuellen Satz? Ich meine... ich habe ja bereits 'ne Lösung.... die von F3K Total funktioniert ja... aber dennoch habe ich da noch ein Loch, eine offene Baustelle... ich meine einfach, dass muss doch auch komfortabler gehen... Get und Set nach gleicher Methodik....

vg, Maddin

Re: DB-Update über Formulare

von DPunch » Mi, 16.03.2011 11:28

Aloha
MaddinR hat geschrieben:Schau Dir noch mal die beiden Prototypen an....:
getByName ( aName as string ) AS variant
replaceByName ( aName as string, aElement as variant )

Dann fällt Dir bestimmt auf, dass bei getByName der Rückgabewert erwartungsgemäß ein Variant-Type ist, und bei replaceByName wird erwartungsgemäß eine Variant-Type als neuer Wert übergeben
(...)also eigentlich genau das, was beim Replace oder bei der Rückgabe des DB-Feldes benötigt wird.
Das ist schlicht und ergreifend dem UNO-Model zuzuschreiben und hat nichts mit der Arbeit mit Datenbanken zu tun.
"getByName ist" ist eine Methode des Interfaces XNameAccess, welches von unzähligen Services implementiert wird, analog dazu ist "replaceByName" Teil des Interfaces XNameReplace.
Dies muss naturgemäss einen Variant annehmen und zurückgeben (also einen beliebigen Datentyp), da es natürlich wenig Sinn machen würde, einem von unterschiedlichsten Services verwendeten Interface feste Auflagen zu machen bezüglich des Datentyps. Der Rückgabewert hängt lediglich davon ab, wie der entsprechende Container verwendet wird... es kann in einem Calc-Dokument ein Tabellenblatt-Objekt sein, es kann in einem anderen Fall aber auch genauso ein String oder ein numerischer Wert sein.

Das GridControl hält in diesem Container die vorhandenen Spalten vor. Daraus ergibt sich, dass getByName und replaceByName den Zugriff auf diese Spalten des GridControls erlaubt.
So kannst Du z.B. per

Code: Alles auswählen

oNewColumn = oGrid.createColumn("TextField")
oNewColumn.Name = "Spaltenname"
oNewColumn.Label = "Spaltenanzeigename"
oGrid.replaceByName("meineSpalte",oNewColumn)
die Spalte mit dem Namen "meineSpalte" durch eine andere Spalte mit dem Namen "Spaltenname" vom Typ TextField ersetzen. Entsprechend lassen sich auch Spalten hinzufügen oder entfernen.

Re: DB-Update über Formulare

von MaddinR » Di, 15.03.2011 20:36

F3K Total hat geschrieben:Du schreibst es ja selber:
replaceByName ( aName as string, aElement as variant )
Bei "aElement" handelt es ich definitiv nicht um einen Wert sondern um ein Objekt. Also in Deinem Fall um das "Grid".
Schau Dir noch mal die beiden Prototypen an....:
getByName ( aName as string ) AS variant
replaceByName ( aName as string, aElement as variant )


Dann fällt Dir bestimmt auf, dass bei getByName der Rückgabewert erwartungsgemäß ein Variant-Type ist, und bei replaceByName wird erwartungsgemäß eine Variant-Type als neuer Wert übergeben. Was ist ein Variant-Type...?... im übertragenen Sinne ein Multi-Typ-Variablen-Objekt (Structure)... also eigentlich genau das, was beim Replace oder bei der Rückgabe des DB-Feldes benötigt wird. Variant nimmt eben jeden Daten-Typ auf, ohne explizit vorher prüfen zu müssen, was das DB-Feld für ein Typ ist. Guckstu: http://msdn.microsoft.com/de-de/library ... S.80).aspx

Da der Variant-Type natürlich nicht nur ein einfacher Datentype ist, ist er auch nicht nur ein neuer Wert, sondern eben mehr ein Objekt, welches den neuen Wert enthält. Nach meiner Meinung kann replaceByName() als Methode der Gridklasse nicht das Grid-Himself austauschen .... das geht nicht. Mit der "Zerstörung" der Grid-Klasse beim release/delete bereinigt der Klassen-Destruktor das Objekt.... und damit wäre replaceByName() selber nicht mehr existent, um weiterzuarbeiten... also das geht wirklich nicht... replaceByName als Methode der Grid-Klasse muss sich einfach auf die Daten-Manipulation beziehen. Ansonsten würde meine Vorstellungswelt jetzt ziemlich ins Wanken geraten... *lacht*... nur diese Drecksmethode tut nicht, was ich will *fg*

vg, Maddin

Re: DB-Update über Formulare

von F3K Total » Di, 15.03.2011 17:30

Hallo Maddin,
wie ich oben schon geschrieben haben:
... werden meiner Meinung nach Objekte ersetzt, z.B. ein Listenfeld auf einem Formular.
Also, ich verstehe es so: Du hast z.B. ein Listenfeld, also das was Du siehst, und willst es durch ein anderes, geändertes Listenfeld ersetzen. Dann nimmst Du "replaceByName (<Name>,neues Listenfeld)".
Du schreibst es ja selber:
replaceByName ( aName as string, aElement as variant )
Bei "aElement" handelt es ich definitiv nicht um einen Wert sondern um ein Objekt.
Also in Deinem Fall um das "Grid".

Vielleicht hilft Dir das hier:

http://wiki.services.openoffice.org/wik ... id_Control

G R

Re: DB-Update über Formulare

von MaddinR » Di, 15.03.2011 08:43

Hallo

Ist ja interessant... anscheinend gibt es immer mehrere Möglichkeiten der Einflussname. Einerseits über die Methoden des Forms, dann weitere Methoden direkt über das Grid, und dann sogar noch über das RowSet. Nun ja... das macht es nicht einfacher. Aber um noch mal mein Problem zu präzisieren:

Schau Dir mal mit xray die oGrid-Methoden an. Da gibts u.a. die beiden folgenden Methoden:
getByName ( aName as string ) AS variant
replaceByName ( aName as string, aElement as variant )


Das hier funktioniert tadellos:

Code: Alles auswählen

oGrid 	= oForm.getByName("FehlerTabelle")
oColumn	= oGrid.getbyName("dbTextfeld")
Value 	= oColumn.CurrentValue
Aber oGrid.replaceByName("dbTextfeld", "Neuerwert") funkioniert nicht, obwohl beide Methoden von xray im oGrid identifiziert werden.

Un nu... ? ... woran mag das liegen... ?... irgend 'ne idee?

vg, Maddin

Re: DB-Update über Formulare

von F3K Total » Mo, 14.03.2011 21:15

Hallo Maddin,
vielleicht machst Du mal folgendes:
Du schaust Dir Dein Formular

Code: Alles auswählen

oForm   = oDoc.drawpage.forms.getByName("SubForm2")
einfach mal mit Xray an, also so:

Code: Alles auswählen

xray oForm
dann gehst Du von "Properties" auf "Methods".
Hier siehst Du dann alle Methoden, mit denen Du das Formular manipulieren kannst.
z.B:

Code: Alles auswählen

isBeforeFirst
isAfterLast
isFirst
isLast
beforeFirst
afterLast
first
last
getRow
absolute
relative
previous
refreshRow
rowUpdated
rowInserted
rowDeleted
getStatement
execute
addRowSetListener
removeRowSetListener
Sind die unteren beiden das, was Du suchst?

G R

Re: DB-Update über Formulare

von MaddinR » Mo, 14.03.2011 10:20

F3K Total hat geschrieben:Dann versuche ich mal das zu erklären:
:) Klasse! Danke! Sehr hilfreich.
F3K Total hat geschrieben:Die Sache mit dem Rowset verstehe ich wiederum nicht so richtig,
aber mit dem Befehl replaceByName(,)werden meiner Meinung nach Objekte ersetzt, z.B. ein Listenfeld auf einem Formular.
Ich hatte früher schon mit DB und Programmierung zu tun. Ich kenne z.B. RecordSet für ein gesamtes Abfrageergebnis als ein Objekt mit eigenen
Methoden. Und darin als eigenes Child-Object ist eine RowSet-Klasse mit eigenen Methoden und Eigenschaften eingebettet. RowSet enthält eben die
Funktionalität für einen einzelnen Record, wie lesen, schreiben, löschen, usw. Und auch z.B. für MoveNext(), MovePrevious(), MoveFirst(), MoveLast(),
IsEof(), IsBof() usw.usw.

Wenn doch das folgende funktioniert:

Code: Alles auswählen

		
oDoc 	= ThisComponent
oForm 	= oDoc.drawpage.forms.getByName("SubForm2")     // SubForm2 ist in meinem ÜbungsForm die upzudatende Tabelle/Grid
oGrid 	= oForm.getByName("FehlerTabelle")
oColumn	= oGrid.getbyName("RecID")
Value2 	= oColumn.Value                            // Value2 enthält jetzt den akteullen Feldinhalt der Tabelle
hätte ich einfach angenommen, das SetByName("Kst", VARIANT neuerwert) oder ReplaceByName(x,x) auf das Grid bzw. RowSet auch funktioniert.... *hmmm*

vg, Maddin

Re: DB-Update über Formulare

von F3K Total » So, 13.03.2011 20:06

Hallo Maddin
Danke! Das funktioniert prima... mir ist zwar nicht so ganz einsichtig, warum, aber es funktioniert.... :-)
Dann versuche ich mal das zu erklären:

Code: Alles auswählen

oKostenstelle=event.source.model.currentvalue
"event.source.model" ist das Listenfeld, über dass das Makro "insert_Kostenstelle" gestartet wird.
D.h, man muß nicht erst über "ThisComponent.drawpage.Forms ... " zu dem Listenfeld navigieren, sondern es findet sich quasi über "event.source" selbst. Es ginge natürlich auch über "ThisComponent.drawpage.Forms ... "
Das ".currentvalue" ist dann der gerade ausgewählte Wert in der Liste des Listenfeldes, also die gewählte Kostenstelle.

Code: Alles auswählen

oform=event.source.model.parent
ist der Vater/parent des Listenfeldes, also unser Formular.
Es handelt sich nicht um das physische Formular, was du siehst, sondern um das Formular welches du mit dem Formularnavigator (im Bearbeitungsmodus des physischen Formulares) ändern kannst.
An dieses Formular ist die Tabelle "Umsatz" gebunden.
Die 3. Spalte der Tabelle "Umsatz" ist "Kostenstelle"
Darum bedeutet der Befehl:

Code: Alles auswählen

oform.updateString(3,oKostenstelle)
eigentlich nicht weiter als: Trage den eben aus dem Listenfeld ausgelesenen String "oKostenstelle" in die Spalte "3" der an das Formular gebundenen Tabelle ein.

Die Sache mit dem Rowset verstehe ich wiederum nicht so richtig,
aber mit dem Befehl

Code: Alles auswählen

replaceByName(,)
werden meiner Meinung nach Objekte ersetzt, z.B. ein Listenfeld auf einem Formular.
So, ich hoffe das war etwas verständlicher.
Beste Grüsse R

Nach oben