DB-Update über Formulare

Datenbanklösungen mit AOO/LO

Moderator: Moderatoren

MaddinR
***
Beiträge: 61
Registriert: So, 06.03.2011 11:15

DB-Update über Formulare

Beitrag von MaddinR »

Hallo liebe Leute

Ich habe zwei einfache Tabellen, eine mit Vorschlagswerten (Kostenstellenplan, relativ konstant), eine zweite ständig anwachsende Tabelle mit Umsätzen. Ich möchte jetzt gerne ein Formular entwickeln, welches in einer Listbox die Tabelle1->Vorschlagswerte enthält und die markierte Tabelle1->Kostenstelle bei "Click" auf den danebenstehenden markierten Tabelle2->Umsatz schreibt. Also eigentlich was ganz triviales.

Und jetzt suche ich schon den ganzen Nachmittag im Web den "Workshop", den ich gestern abend zufällig gefunden habe, dessen URL ich nicht gesichert habe, und den ich somit wieder verloren habe. Vielleicht hat jemand in seiner Link-Sammlung noch einen Tip für eine Beschreibung, die ich stattdessen irgendwo im Web finden kann und die ich einfach mal durcharbeiten kann, um zu vertehen, wie man das macht.

Danke im Voraus.

vg, Maddin
F3K Total
********
Beiträge: 3720
Registriert: Mo, 28.02.2011 17:49

Re: DB-Update über Formulare

Beitrag von F3K Total »

MaddinR
***
Beiträge: 61
Registriert: So, 06.03.2011 11:15

Re: DB-Update über Formulare

Beitrag von MaddinR »

Hallo
Danke für den Tip. Aber die wars leider nicht. Es war eine Seite, die nicht auf der ersten Google-Seite steht, sondern ein Link in irgendeinem Posting... und ich habe keine Ahnugn mehr, wo ich das gelsen habe. Aber egal, ist nicht so schlimm. Habe heute schon ein wenig rumexperimentiert... und so ganz langsam gehts...

vg, Thomas
F3K Total
********
Beiträge: 3720
Registriert: Mo, 28.02.2011 17:49

Re: DB-Update über Formulare

Beitrag von F3K Total »

So, ich hab da mal was versucht, scheint gut zu klappen:
Datensatz im Grid markieren, Kostenstelle im Listfed auswählen, fertig.

Das Macro startet, wenn das Listfeld geändert wird:

Code: Alles auswählen

Sub insert_Kostenstelle(Event)
oKostenstelle=event.source.model.currentvalue
oform=event.source.model.parent
oform.updateString(3,oKostenstelle)' 3 ist die Ordinal-Position der Spalte "Kostenstelle" in Tabelle "Umsatz"
if oform.isnew=true then
oform.insertRow()
oform.updateRow()
else
oform.updateRow()
endif
End Sub
gR
MaddinR
***
Beiträge: 61
Registriert: So, 06.03.2011 11:15

Re: DB-Update über Formulare

Beitrag von MaddinR »

F3K Total hat geschrieben:So, ich hab da mal was versucht, scheint gut zu klappen:
Datensatz im Grid markieren, Kostenstelle im Listfed auswählen, fertig.
Hallo

Danke! Das funktioniert prima... mir ist zwar nicht so ganz einsichtig, warum, aber es funktioniert.... :-)

Allerdings hatte ich irgendwie sowas erwartet:

oRowset = oGrid.RowSet
oRowset.replaceByName("Kst", ListboxEintrag)
oRowset.refreshRow
oRowset.Next()

Aber der ReplaceByName klappt nacht. Gibts denn überhaupt eine Funtkionalität, die sinngemäß so aussieht, wie mein nicht-funktionierendes Beispiel?

vg, Maddin
F3K Total
********
Beiträge: 3720
Registriert: Mo, 28.02.2011 17:49

Re: DB-Update über Formulare

Beitrag von F3K Total »

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
MaddinR
***
Beiträge: 61
Registriert: So, 06.03.2011 11:15

Re: DB-Update über Formulare

Beitrag von MaddinR »

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
F3K Total
********
Beiträge: 3720
Registriert: Mo, 28.02.2011 17:49

Re: DB-Update über Formulare

Beitrag von F3K Total »

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
MaddinR
***
Beiträge: 61
Registriert: So, 06.03.2011 11:15

Re: DB-Update über Formulare

Beitrag von MaddinR »

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
F3K Total
********
Beiträge: 3720
Registriert: Mo, 28.02.2011 17:49

Re: DB-Update über Formulare

Beitrag von F3K Total »

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
MaddinR
***
Beiträge: 61
Registriert: So, 06.03.2011 11:15

Re: DB-Update über Formulare

Beitrag von MaddinR »

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
DPunch
*******
Beiträge: 1112
Registriert: Mo, 02.11.2009 16:16
Wohnort: Marburg

Re: DB-Update über Formulare

Beitrag von DPunch »

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.
MaddinR
***
Beiträge: 61
Registriert: So, 06.03.2011 11:15

Re: DB-Update über Formulare

Beitrag von MaddinR »

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
DPunch
*******
Beiträge: 1112
Registriert: Mo, 02.11.2009 16:16
Wohnort: Marburg

Re: DB-Update über Formulare

Beitrag von DPunch »

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.
MaddinR
***
Beiträge: 61
Registriert: So, 06.03.2011 11:15

Re: DB-Update über Formulare

Beitrag von MaddinR »

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
Antworten