Hallo,
ich habe einen komischen Fehler, den ich mir nicht erklären kann und an dem ich gerade verzweifle.
Ich habe ein Popup, um für ein Produkt einen Preis festzulegen oder zu ändern. Danach mache ich ein Requery auf das Unterformular um den neuen oder geänderten Preis anzuzeigen.
Beim Anlegen eines neuen Preises funktioniert das wunderbar, aber beim Ändern des Preises bekomme ich einen "Anwendungs- oder objektdefinierten Fehler". Irgendwie kann ich nach dem edit scheinbar kein Requery machen. Muss ich hier noch irgendwie extra speichern oder woran kann das liegen??
Ich habe es mit me.dirty = false, db = nothing, verschiedene Positionen von rs.close im Code probiert, aber irgendwie verstehe ich hier was nicht.
Anbei der Code. Für strIDPrice = 0 (neuer Preis) läuft alles problemlos durch. bei else / strIDPrice <> 0 geht auch alles, bis auf das requery. Komisch.
frm2 ist als globale Variable im Module definiert und beinhaltet das Ursprungs-Formular, welches ich bei Button-klick als Variable übergeben und dann in die "globale" Variable schreibe.
Sub AddNewProductPrice(strIDPrice As Variant, strIDProduct As Variant, strProductPrice As Variant, strIDUnit As Variant, strIDCurrency As Variant, strIDIncoterm As Variant, strIncotermCity As Variant, strPriceDate As Date, strProductPriceNotes As Variant)
On Error GoTo Goto_Err
Dim db As Database
Dim rs As Recordset
Set db = CurrentDb
'write new record into the tblPrices table
Set rs = db.OpenRecordset("tblPrices", dbOpenDynaset)
If strIDPrice = 0 Then 'if it is a new record
rs.AddNew
rs!Product_Price = strProductPrice
rs!ID_Unit = strIDUnit
rs!ID_Currency = strIDCurrency
rs!ID_Incoterm = strIDIncoterm
rs!Incoterm_City = strIncotermCity
rs!Price_Date = strPriceDate
rs!Product_Price_Notes = strProductPriceNotes
rs.update
'move to last modified = new record
rs.Bookmark = rs.LastModified
'set ID_Price to the new record
strIDPrice = rs.Fields("ID_Price")
rs.Close
Set rs = Nothing
'write new record in the Product-Price m:n Table
DoCmd.RunSQL "INSERT INTO tblProductPrice(ID_Product,ID_Price) VALUES (" & strIDProduct & "," & strIDPrice & ")"
Else
rs.FindFirst "ID_Price = " & strIDPrice & ""
If Not rs.NoMatch Then
'It's okay to keep processing.
End If
rs.Edit
rs!Product_Price = strProductPrice
rs!ID_Unit = strIDUnit
rs!ID_Currency = strIDCurrency
rs!ID_Incoterm = strIDIncoterm
rs!Incoterm_City = strIncotermCity
rs!Price_Date = strPriceDate
rs!Product_Price_Notes = strProductPriceNotes
rs.update
rs.Close
Set rs = Nothing
End If
frm2.fsubProductPrice.Form.Requery
Goto_Exit:
Exit Sub
Goto_Err:
MsgBox Error$
Resume Goto_Exit
End Sub
Zitatfrm2 ist als globale Variable im Module definiert ...
Das ist nicht überzeugend. Du könntest die Formularreferenz direkt als Argument an die Prozedur übergeben, um sie zu verwenden. Da wäre sicher auch besser sichergestellt, dass die Objektvariable einen und dann noch den richtigen Inhalt hat.
Der Ablauf ist nicht überzeugend. Übersichtlicher und kürzer:
Dim sSQL As String
Dim MerkeID
sSQL = "SELECT [Feldliste] FROM tblPrices WHERE ID_Price = " & strIDPrice
Set rs = db.OpenRecordset(sSQL, dbOpenDynaset)
With rs
If .EOF Then ' kein Eintrag vorhanden
.Addnew
MerkeID = .Fields("ID_Price")
Else
.Edit
End If
' Feldliste mit Werten versorgen
.Update
.Close
End With
frm.Controls("fsubProductPrice").Form.Requery rs!ID_Currency = strIDCurrency
' ...
rs!Price_Date = strPriceDateBei Datentypen bevorzugst Du das Prinzip Verwirrung? SQL und Deine Tabellen werden sich aber nicht verwirren lassen, sondern meckern und streiken, wenn ihnen etwas vorbei an der Definition nicht passt.
Hallo,
verstehe den Aufwand als solches nicht...
Vorschläge:
-- Halte Dich konsequent an Datentypen und deklariere nicht alle Variablen als Variant. Prefix "str" ist auch nicht gerade förderlich für die Transparenz und insgesamt fehlerträchtig.
--
.
.
rs.FindFirst "ID_Price = " & strIDPrice & ""
If Not rs.NoMatch Then
'It's okay to keep processing.
End If
rs.Edit
.
.
1) Was, denkst Du, passiert hier, wenn kein Datensatz gefunden wird?
2)
If strIDPrice = 0 Then 'if it is a new record
Bist Du sicher, dass 0 in strIDPrice steht? Enthält die Variable vielleicht "NULL" (nichts, leer) ?
3) Wozu verwendest Du überhaupt Recordsets? Alle Eingaben/Speicherungen können mit einem gebundenen Form erledigt werden. Vermutlich muss nicht mal eine Anfügeabfrage bemüht werden.
Zitat von: ebs17 am August 31, 2020, 15:30:20Das ist nicht überzeugend. Du könntest die Formularreferenz direkt als Argument an die Prozedur übergeben, um sie zu verwenden. Da wäre sicher auch besser sichergestellt, dass die Objektvariable einen und dann noch den richtigen Inhalt hat.
Die Formularreferenz direkt zu übergeben wäre schön, hat aber zwei Probleme:
1. Ich rufe das Ganze von zwei Formularen auf, d.h. es wären zwei unterschiedliche Referenzen notwendig. Es sei denn, ich könnte direkt nur das UFo ansprechen. Das ist ja bei beiden Formularen das gleiche. Ich bezweifle, dass das geht.
2. Das Formular übergebe ich schon an die Prozedur, ich habe aber bisher noch keine gute Möglichkeit gefunden, die Formularreferenz dann später abzurufen. Daher übergebe ich die Referenz via "globaler" Modul-Variable set frm2 = frm damit ich die Referenz dann wenigstens im Modul habe. Ich schaffe es einfach nicht die Referenz bis auf das Popup Formular zu übergeben, so dass ich dann nach docmd.close ein frm.requery oder anderes machen könnte. Ich versuche dieses Problem schon seit Wochen zu lösen, weil ich damit ständig Probleme habe.
Zitat von: ebs17 am August 31, 2020, 15:30:20Der Ablauf ist nicht überzeugend. Übersichtlicher und kürzer:
Danke, wieder was gelernt und so sieht das Ganze nun bei mir aus. Deutlich aufgeräumter. Du wirst sicher über das MerkeID = 0 meckern, aber das ist mir sicherer als mit Sachen wie "ID not isNull(MerkeID)" oder ähnlich Mysteriösem zu arbeiten. LOL
Das eigentlich Problem ist damit allerdings nicht gelöst. Bei dem .Edit funktioniert das Requery komischerweise nicht. ("Access kann das in dem Ausdruck angesprochene Feld "FsubProductPrice" nicht finden" - bei .AddNew gibt es KEIN Problem und die Zeile funktioniert und das Requery wird ausgeführt...)
Sub AddNewProductPrice(strIDPrice As Variant, strIDProduct As Variant, strProductPrice As Variant, strIDUnit As Variant, strIDCurrency As Variant, strIDIncoterm As Variant, strIncotermCity As Variant, strPriceDate As Date, strProductPriceNotes As Variant)
On Error GoTo Goto_Err
Dim db As Database
Dim rs As Recordset
Dim sSQL As String
Dim MerkeID As Integer
Set db = CurrentDb
sSQL = "SELECT ID_Price, Product_Price, ID_Unit, ID_Currency, ID_Incoterm, Incoterm_City, Price_Date, Product_Price_Notes " _
& "FROM tblPrices " _
& "WHERE ID_Price = " & strIDPrice & ";"
Set rs = db.OpenRecordset(sSQL, dbOpenDynaset)
With rs
If .EOF Then ' kein Eintrag vorhanden
.AddNew
MerkeID = .Fields("ID_Price")
Else
.Edit
MerkeID = 0
End If
.Fields("Product_Price") = strProductPrice
.Fields("ID_Unit") = strIDUnit
.Fields("ID_Currency") = strIDCurrency
.Fields("ID_Incoterm") = strIDIncoterm
.Fields("Incoterm_City") = strIncotermCity
.Fields("Price_Date") = strPriceDate
.Fields("Product_Price_Notes") = strProductPriceNotes
.update
.Close
End With
'write new record in the Product-Price m:n Table
If MerkeID <> 0 Then DoCmd.RunSQL "INSERT INTO tblProductPrice(ID_Product,ID_Price) VALUES (" & strIDProduct & "," & MerkeID & ")"
frm2.Controls("fsubProductPrice").Form.Requery
Goto_Exit:
Exit Sub
Goto_Err:
MsgBox Error$
Resume Goto_Exit
End SubZitat von: ebs17 am August 31, 2020, 15:30:20Bei Datentypen bevorzugst Du das Prinzip Verwirrung? SQL und Deine Tabellen werden sich aber nicht verwirren lassen, sondern meckern und streiken, wenn ihnen etwas vorbei an der Definition nicht passt.
haha, äh, ja. Nachdem ich mich totgesucht habe, wieso ich keine leeren (geänderten) Text-Felder als String in eine Funktion übergeben kann und dann herausgefunden habe, dass nur Variant das lösen kann, lasse ich die Variablen als Variant übergeben. Sicherlich nicht die feine Art aber bisher habe ich für das Problem auch noch keine richtige Lösung gefunden... Werde dies aber noch überarbeiten. Das war ein "bewusster Fehler" und ich gelobe Besserung.
Zitat von: DF6GL am August 31, 2020, 15:37:48Halte Dich konsequent an Datentypen und deklariere nicht alle Variablen als Variant. Prefix "str" ist auch nicht gerade förderlich für die Transparenz und insgesamt fehlerträchtig
Str schreibe ich idR als Zeichen, dass es eine Variable ist (strIDPrice = ID_Price) - String ist hier zwar gemeint aber nicht im "as String" Sinn:) Sicherlich nicht optimale Notation.
Zitat von: DF6GL am August 31, 2020, 15:37:48Was, denkst Du, passiert hier, wenn kein Datensatz gefunden wird?
em, hüstel. Ich bin ja noch nicht fertig! *breites, angespanntes Lächeln* Eberhard hat mich ja zum Glück von diesem Problem befreit.
Zitat von: DF6GL am August 31, 2020, 15:37:48If strIDPrice = 0 Then 'if it is a new record
Bist Du sicher, dass 0 in strIDPrice steht? Enthält die Variable vielleicht "NULL" (nichts, leer) ?
Bin ich. Ich starte das Ganze mit Id_Price = 0 bzw. mit Reference strIDPrice = 0 in Funktion, wenn der "add new Price" Button gedrückt wird. Dann werden auch keine Daten in das Formular geladen. D.h. den Teil habe ich hoffentlich richtig gemacht haha Mit der neuen EOF Variante sollte das strIDPrice = 0 ja auch solide funktionieren. Wobei Ihr sicherlich das prinzipiell nicht gut findet.
Zur Info noch die entsprechende Funktion bei Aufruf des Formulars:
'--------------------------------------------------------------------------------------------------------------
'Function to run the price popup
'--------------------------------------------------------------------------------------------------------------
Function PricePopup(frm As Form, strIDProduct As Variant, strIDPrice As Variant)
On Error GoTo Goto_Err
Dim strCaption As String
Dim oForm As Form
Dim sSQL As String
Dim db As Database
Dim rs As Recordset
Set oForm = Form_fsubProductPricePopup
Set db = CurrentDb
Set frm2 = frm
'fill the textboxes on the form
oForm.txtIDProduct = strIDProduct
oForm.txtIDPrice = strIDPrice
oForm.txtPricingDate = Date
sSQL = "SELECT ID_Product, Product_Code, Product_Name " _
& "FROM tbl_Product " _
& "WHERE ID_Product = " & strIDProduct & ";"
Set rs = db.OpenRecordset(sSQL, dbOpenDynaset)
With rs
If .EOF Then ' kein Eintrag vorhanden
MsgBox ("Cannot find ID_Product")
Exit Function
Else
oForm.txtProductCode = .Fields("Product_Code")
oForm.txtProductName = .Fields("Product_Name")
End If
'change name of the new form's caption to the current product name
If IsNull(rs.Fields("Product_Name")) Then
strCaption = "Product Price"
Else: strCaption = .Fields("Product_Name")
End If
.Close
End With
If strIDPrice <> 0 Then 'Price already exists -> fill in current data
'show current info
sSQL = "SELECT ID_Price, Product_Price, ID_Unit, ID_Currency, ID_Incoterm, Incoterm_City, Price_Date, Product_Price_Notes " _
& "FROM tblPrices " _
& "WHERE ID_Price = " & strIDPrice & ";"
Set rs = db.OpenRecordset(sSQL, dbOpenDynaset)
With rs
If .EOF Then ' kein Eintrag vorhanden
MsgBox ("Cannot find ID_Price")
Exit Function
Else
oForm.txtProductPrice = .Fields("Product_Price")
oForm.cboUnit = .Fields("ID_Unit")
oForm.cboCurrency = .Fields("ID_Currency")
oForm.cboInco = .Fields("ID_Incoterm")
oForm.txtIncotermCity = .Fields("Incoterm_City")
oForm.txtPricingDate = .Fields("Price_Date")
oForm.txtProductPriceNotes = .Fields("Product_Price_Notes")
End If
.Close
End With
End If
Set rs = Nothing 'release from memory
oForm.Caption = strCaption
'oForm.InsideHeight = 6000
'oForm.InsideWidth = 4500
'make the form appear
oForm.Visible = True
oForm.SetFocus
Goto_Exit:
Exit Function
Goto_Err:
MsgBox Error$
Resume Goto_Exit
End FunctionZitat von: DF6GL am August 31, 2020, 15:37:48Wozu verwendest Du überhaupt Recordsets? Alle Eingaben/Speicherungen können mit einem gebundenen Form erledigt werden. Vermutlich muss nicht mal eine Anfügeabfrage bemüht werden.
Die tblprices steht mit tblproduct via tblproductprice (m:n) in Verbindung. D.h. ich übergebe Formular, ID_Product und ID_Price (bei neu = 0) und mache den Rest per Hand. Ich hatte den "add new price" Part zuerst mit gebundenem Formular probiert, aber irgendwie nicht hinbekommen. Spätestens bei der Frage, wie ich die ID_Price des neu angelegten Preises bekomme scheitere ich dann.
Das mit den ungebunden Textfeldern finde ich eigentlich gut.
Die Filterfunktionen und Übergabe von PK-ID etc insb bei einem Popup ist mir noch etwas und zum Teil sehr suspekt... Ich habe da schon Tage mit verbracht herumzuprobieren.
Das kann auch daran liegen, dass ich Popups idR via visible = true und nicht via docmd.openform öffne. Siehe Code oben. Vielleicht ist das aber auch das gleiche... Jedenfalls finde ich es bei Popups einfacher die Daten direkt in VBA zu laden, als die richtigen Filter an den unterschiedlichen Stellen zu setzen. Da bin ich noch nicht richtig in Access durchgestiegen, obwohl ich eigentlich weiß wo die Verknüpfung bzw. Filter zu setzen sind. Bei Subforms habe ich da beispielsweise keine größeren Probleme.
Ganz herzlichen Dank für die Hilfe, die wie immer super lehrreich ist!
Function PricePopup(frm As Form, strIDProduct As Variant, strIDPrice As Variant)
On Error GoTo Goto_Err
' ...
Set frm2 = frm
' ...Irgendwo fällt eine Formularreferenz vom Himmel und wird dann verwendet.
Hallo,
irgendwie suspekt...
Zitat von: undefined"Access kann das in dem Ausdruck angesprochene Feld "FsubProductPrice" nicht finden"
ist doch eindeutig.. Setz mal einen Haltepunkt an die Codezeile und untersuche im Direktfenster die frm2-Variable, ob sie überhaupt noch gültig ist (globale Variablen verlieren bei einigen Gelegenheiten (Fehlersituationen) ihren Inhalt.). Versuche auch, auf das UFO-Steuerelement (!, nicht Formularname) "fsubProductPrice" zuzugreifen.
Ansonsten lad die DB mal hier hoch. Datenreduziert, komprimiert/repariert und gezippt.
btw:
Verzichte auf das Access-Makro DoCmd.RunSQL und benutze stattdessen Currentdb.Execute
Die Benamsung halte ich für nicht brauchbar und der Argumentation zu einer globalen Variablen für eine Form-Referenz kann ich nicht zustimmen.
Natürlich kannst Du das so machen, bringt aber eher mehr Schlaglöcher denn Vorteile.
Zitat von: ebs17 am September 01, 2020, 11:43:40Irgendwo fällt eine Formularreferenz vom Himmel und wird dann verwendet.
frm2 habe ich mit
dim frm2 as form oben im Modul definiert - als globale Modul-Variable oder wie man das richtig nennt.
Zitat von: DF6GL am September 01, 2020, 11:49:03und der Argumentation zu einer globalen Variablen für eine Form-Referenz kann ich nicht zustimmen
Gefällt mir auch nicht, ich weiß aber nicht, wie man das besser machen kann.
Das Problem ist, dass ich die Funktion, etc. von unterschiedlichen Formularen aufrufe. D.h. eine "hard-coded" Formularreferenz geht so nicht. (Ggf. gingen IFs - wenn ich denn dann wissen könnte, von wo der Aufruf kam. Aber wenn ich das weiß, dann kann ich das ja auch gleich dynamisch machen... :) )
Im Moment übergebe ich das Formular in die Funktion, die das Popup öffnet. Aber auf dem Popup-Formular bzw. dort wo ich dann die Events des Popup-Formulars bearbeite, habe ich keinen Zugriff mehr auf die Formular-Referenz.
Auch wenn ich dann wieder - z.B. zum Schreiben von Daten - zurück ins Module gehe (Funktion aufrufe), habe ich dort keinen Zugang zur Formular-Referenz. Hier kann ich dann aber mit frm2 = frm "überbrücken".
Ich hoffe Ihr versteht was ich meine. An dem Problem knabbere ich schon seit Wochen.
Werde jetzt erstmal mit Haltepunkt und Direktfenster spielen... :)
Wie sieht das aus?
Sub UseFormReference(ByRef MyForm As Access.Form)
MyForm.Requery
End Sub
Sub aufruf_UseFormReference()
UseFormReference Forms.HFoName.UFoCtrlName.Form
End SubDie Prozedur übernimmt das, was ihr als Argument übergeben wird. Wo ist da etwas hardcodiert?
Die Aufrufprozedur bestimmt, was übergeben wird (und sollte da vorab sichergestellt haben, dass verwendete Formulare vorhanden und geöffnet sind). Da das unmittelbar vor der Übergabe erfolgt, ist das sicherer als ein Umweg über globale Variablen.
Die Übergabe einer Objektreferenz ist auch daher sicherer als bspw. die Namen der Formulare, da möglicherweise mehrere Instanzen des Formulars gleichzeitig aktiv sein könnten. Die Referenz ist der Zeiger auf genau das gemeinte Objekt.
ZitatRequery nach Recordset .edit bringt Fehler
Dem Requery ist die Codevorgeschichte egal, es sei denn, der Code ändert etwas am Formular oder an der Datenherkunft (designmäßig, nicht datenbezogen).
boah, ihr dürft mich schlagen!
?frm2.Name
fsubProductPopup
?frm2.Name
fsubProductPrice
Die Buttons für Add-Price und Change-Price sind auf unterschiedlichen Formularen. Das ist mal peinlich und doof.
D.h. ein kleines ".parent" an das me der Formular-Referenz angefügt und schon flutsch das alles! Ahhhh.
Zitat von: ebs17 am September 01, 2020, 12:50:53Die Prozedur übernimmt das, was ihr als Argument übergeben wird. Wo ist da etwas hardcodiert?
Die Aufrufprozedur bestimmt, was übergeben wird (und sollte da vorab sichergestellt haben, dass verwendete Formulare vorhanden und geöffnet sind).
Im Grunde mache ich dies im Moment ja so, oder?
Private Sub cmdChange_Click()
Call PricePopup(Me.Parent, Me.ID_Product, Me.ID_Price)
End SubFunction PricePopup(frm As Form, strIDProduct As Variant, strIDPrice As Variant)D.h. ich habe dann das richtige Formular in frm. In diesem Fall das Parent, idR "me".
Probleme habe ich, wenn ich dann auf dem neu geöffneten Formular (in diesem Fall PricePopup) bin. Dort gibt es dann ja kein frm mehr und ich muss wieder "manuell" eine Referenz auf das Urspungsformular herstellen was schwierig ist, weil es mehrere "Ursprungsformulare" gibt von denen das PricePopup aufgerufen werden kann. Ich müsste jetzt frm nochmal an das Popup "übergeben" so dass ich frm unter "Form_fsubProductPricePopup" nutzen kann.
Ich war schon am überlegen, ob ich eine unsichtbare Textbox mit frm fülle. Dann könnte man diese nutzen. Habe ich aber praktisch nicht hinbekommen (natürlich Variablenkonflikt LOL)
Deine Rede verstehe ich nicht. Man muss gedanklich und auch codemäßig trennen, von wo man etwas aufruft und was man aufruft.
Susi, wenn sie eindeutig ist (eine Referenz ist eindeutig), wird reagieren, unabhängig, wenn ich vom Oberboden oder vom Keller aus rufe oder wenn ich ihr so nahe stehe, dass ich ihr ins Ohr beißen könnte, und es sollte auch egal sein, ob sie auf einem Stuhl steht oder auf dem Sofa liegt oder in einer Menschenmenge steht.
Ich hatte das Requery-Problem auf das Allernötigste heruntergebrochen. Versuche es damit, wenn Du diesem Problem etwas anhaben möchtest.
Deine Versuche und Gedanken sind Dir selbstredend wichtig, da Du investiert hast. Aber diese könntest Du mal kurz außer Acht lassen.
"Wenn man Rühreier machen will, muss man Eier zerschlagen." (Lenin)
Lieber Eberhard,
herzlichen Dank für den unterhaltsamen Vergleich!
Mir fehlt wohl noch etwas das Vokabular um klar sagen zu können, was ich meine. Rein codetechnisch habe ich das Problem, dass ich "frm" (ehemals "me") nur in einer Variable in einer Funktion in einem Modul (ModPrice) zugänglich habe (jetzt ganz unabhängig von der Requery-Geschichte). Wenn ich jetzt diese Variable in dem in der Funktion aufgerufenem Popup (Form_fsubProductPricePopup) benutzen möchte, kann ich dies natürlich nicht, weil "frm" in keinsterweise definiert ist. Gleichzeitig habe ich das Problem dass - zumindest ich - große Schwierigkeiten habe herauszufinden wie ich an das ursprüngliche "me" komme um damit zu arbeiten. D.h. ich tue mich schwer auf das ursprünglich Formular ("me") zu verweisen, weil es mehrere Formulare gibt, von denen die Funktion aufgerufen wird.
Salopp formuliert, möchte ich "Me" "durchschleifen", so dass ich - eben ohne Verwendung einer globalen Variable - Zugriff auf diese Formularreferenz habe.
Ich habe dieses Problem unabhängig von der Requery-Frage, die ja soweit gelöst ist.
Ich habe wieder viel gelernt und der Salm oben nur als Versuch irgendwie verständlich zu machen, was ich meine und nicht, um Euch hier weiter zu malträtieren. Für den Moment funktioniert ja die komische frm2 = frm Brücke. Die wird dann abgerissen, wenn ich eine gute Alternative gefunden habe:)
Lieben Dank für Eure Hilfe!
Zitatweil es mehrere Formulare gibt, von denen die Funktion aufgerufen wird
Ein Formular kennt sich selber. Wenn es etwas aufruft, kann es seinen Namen, besser seine Referenz mitgeben bei diesem Ruf. Wenn dann nicht Vergesslichkeit eintritt, muss ein Externer nicht ermitteln, woher der Ruf kam.
Me ist doch ein treffliches Beispiel. Es ist eine Referenz auf sich selber, und für jedes Formular, jeden Bericht, jede Klasse doch etwas anderes als die beiden Buchstaben.
Zitatnur in einer Variable in einer Funktion
Das Argument, das an eine Funktion oder Prozedur übergeben wird, ist unmittelbar als Variable im Codekörper nutzbar. Da muss man nicht extra etwas von draußen hereinholen.
Zitatunabhängig von der Requery-Geschichte
Requery ist nur eine Methode des Formularobjektes, stellvertretend. Selbstredend hat man mit dem Formularobjekt alle dessen Methoden, alle dessen Steuerelemente usw.
Zitatum klar sagen zu können, was ich meine
Wenn man seine Aufgabe wirklich klar formulieren kann, hat man oft schon die halbe Lösung => Tun, was man will, mit einem praktikablen Ablauf(plan) und korrekter Syntax der benutzten Sprache(n).