Neuigkeiten:

Ist euer Problem gelöst, dann bitte den Knopf "Thema gelöst" drücken!

Mobiles Hauptmenü

.onclick Event von Popup direkt in Funktion verarbeiten

Begonnen von maddhin, August 10, 2020, 06:21:07

⏪ vorheriges - nächstes ⏩

maddhin

Hallo,

ich habe eine globale Funktion/Modul in der ich Daten aus dem Internet hole und ein Popup (fsubImport) zum Kontrollieren und Bestätigen der Daten öffne. Nun möchte ich bei einem Button (cmdOK) bzw. .onclick Event die neuen Informationen in dem Hauptformular (= frm) speichern.
 
Ich möchte dies gerne direkt in der Funktion machen und den Code nicht in der _Click() Sub des Popup-Formulars haben. Erstens wegen der Übersichtlichkeit und zweitens, weil ich nicht richtig weiß, wie man das Hauptformular ordentlich and das _Click Event übergibt (ich rufe diese Funktion von zweit unterschiedlichen Hauptformularen aus auf).

So sieht das im Moment aus:
Function Import(frm As Form)
[...]
Dim oForm As Form
Set oForm = Form_fsubImport
   
    oForm.InsideHeight = 5000
    oForm.InsideWidth = 10000
    'make the form appear
    oForm.Visible = True
   
    oForm.txtCorpName = StrCorpName
    oForm.txtStreet = StrStreet
    oForm.txtCity = StrCity
     
    Dim ctlOK As Control
    Set ctlOK = oForm.Controls("cmdok")
    ctlOK.OnClick = "=ParseImport()"
    Set ctlOK = Nothing
     
End Function

Function ParseImport()
    MsgBox ("Hallo")
End Function


Ich schaffe das "Hallo" zu bekommen, wenn man den OK Button drückt. Was ich aber gerne machen würde ist, anstatt die Function ParseImport aufzurufen, direkt einige Befehle wie
frm.CorpName = oForm.txtCorpName
frm.Street = oForm.txtStreet
frm.City = oForm.txtCity
hinter ctlOK.OnClick = zu schreiben. D.h. die importierten Infos zu schreiben/speichern.

Kann man das irgendwie so vereinfachen?

Alternativ würde ich gerne die Variable für das Hauptformular ("frm") a la ctlOK.OnClick = "=ParseImport(frm)" (dann in der Funktion: Function ParseImport(frm As Form)) übergeben. Aber das scheint auch nicht zu funktionieren.

Ggf. ist es das Beste das Ganze ganz anders zu lösen. Würde mich über Kommentare freuen!

PhilS

Zitat von: maddhin am August 10, 2020, 06:21:07Was ich aber gerne machen würde ist, anstatt die Function ParseImport aufzurufen, direkt einige Befehle wie
frm.CorpName = oForm.txtCorpName
frm.Street = oForm.txtStreet
frm.City = oForm.txtCity
hinter ctlOK.OnClick = zu schreiben. D.h. die importierten Infos zu schreiben/speichern.

Wenn man "Einige Befehle" zusammen ausführen möchte, dann fasst man diese in einer Prozedur zusammen und ruft diese Prozedur auf. Dein bisheriger Ansatz mit dem Aufruf deiner ParseImport Funktion ist also schon der richtige Weg.


Zitat von: maddhin am August 10, 2020, 06:21:07Alternativ würde ich gerne die Variable für das Hauptformular ("frm") a la ctlOK.OnClick = "=ParseImport(frm)" (dann in der Funktion: Function ParseImport(frm As Form)) übergeben. Aber das scheint auch nicht zu funktionieren.

Auch hier hast du bereits den richtigen Denkansatz. Unter "normalen" Umständen würde man tatsächlich das Formular als Argument an eine Prozedur übergeben. In diesem konkreten Fall hast du aber das Problem dass die Signatur (=Argumente und Rückgabewert) der OnClick-Ereignisprozedur bereits fest vorgegeben ist. Du kannst also keine eigenen, zusätzliche Argumente, wie z.B. frm, übergeben.

Als Workaround kannst du in diesem Fall die Eigenschaft Screen.ActiveControl verwenden, um eine Referenz auf den geklickten Button zu bekommen. Dessen Parent-Eigenschaft verweist dann auf das gewünschte Form. Ausnahme: Der Buttons sitt auf einem Registersteuerelement, dann ist dieses der Parent des Button und der Parent des Register das Form.

Alternativ gibt es auch Screen.ActiveForm das dann das gewünschte Form liefert, wenn es sich dabei nicht um ein Unterformular handelt.

Soweit zu deinem bisherigen Ansatz.
Insgesamt ist mir die Wahl dieses konkreten Ansatzes nicht ganz klar. Warum muss du überhaupt die OnClick-Ereignisprozedur zur Laufzeit zuweisen? Warum nicht bereits fest in dem Entwurf des/der Formulare? Dort reicht ja eine einzelne Zeile, die deine ParseImport-Prozedur aufruft und dabei das richtige Form übergibt.
Neue Videoserie: Windows API in VBA

Klassische CommandBars visuell bearbeiten: Access DevTools CommandBar Editor

maddhin

Zitat von: PhilS am August 10, 2020, 08:47:08Insgesamt ist mir die Wahl dieses konkreten Ansatzes nicht ganz klar. Warum muss du überhaupt die OnClick-Ereignisprozedur zur Laufzeit zuweisen? Warum nicht bereits fest in dem Entwurf des/der Formulare? Dort reicht ja eine einzelne Zeile, die deine ParseImport-Prozedur aufruft und dabei das richtige Form übergibt.

Lieben Dank schonmal für die Hilfe.

Ich habe jetzt nochmal die Screen.ActiveForm/Control probiert, das geht aber wohl nicht oder ich habe was falsch gemacht.

Die Gedanke die Prozedur direkt im Formular aufzurufen ist eine gute Lösung, darauf bin ich nicht gekommen:) Dann muss ich zwar alle zu schreibenden Werte auch übergeben, aber das ist ja machbar.

Aber das mit dem frm bekomme ich trotzdem leider nicht hin.

Ich bin auf dem Formular frmCompany und rufe von dort wie oben gesehen die Funktion Import via Button (call Import(me)) und indirekt das Formular/Popup fsubImport auf und übergebe die Werte in ungebundene Txt-Felder. Diese sollen dann kontrolliert und ggf. geändert werden können und die jeweiligen txtCorpName, etc sollen dann unter den echten Variablen im frmCompany gespeichert werden, d.h. me.CorpName = txtCorpName.

Auf dem Popup fsubImport kann ich das nur schreiben, wenn ich explizit das Formular mit forms!frmCompany.CorpName = txtCorpName angebe. Da ich aber die Import-Funktion bzw. das fsubImport-Popup von 3 verschiedenen Formularen aufrufen will (einmal frmCompany, einmal frmCompany in Navigationsmenu und einmal in einem CompanyInfoPopup), muss ich irgendwie den richtigen Formularnamen übergeben.

Und der Formularname geht dann in die ParseImport Funktion oder man schreibt direkt in das fsubImport Formular.

Die Import-Funktion rufe ich mit Import(me) / Import(frm as form) auf. D.h. da funktioniert frm. Aber das scheint sich nicht auf fsubImport zu übertragen.

Ich hoffe mir dem halben Roman hier wird mein Problem deutlich(er). Lieben Dank

DF6GL

Hallo,

vielleicht versteh ich ja etwas falsch, aber warum importierst Du nicht alle Daten auf einmal (ich nehme an, es handelt sich um mehrere Datensätze) mit SQL, bzw. mit einer Docmd.TransferXXX-Methode  in eine passende Importtabelle, die dann mit einem geeigneten gebundenen Formular datenmäßig geprüft werden können. Danach werden die korrigierten Ds in der Importtabelle in einem Rutsch mittels Anfügeabfrage in die Zieltabelle übertragen.

Viele Grüße vom Bodensee
Franz, DF6GL

Hilfestellung:  http://www.access-o-mania.de/forum/index.php?topic=6969.msg118738#msg118738

Links und Tipps:
1.   http://v.hdm-stuttgart.de/~riekert/lehre/db-kelz/
1a. http://www.tinohempel.de/info/info/datenbank/normalisierung.htm
1b. https://support.office.com/de-de/article/Grundlagen-des-Datenbankentwurfs-eb2159cf-1e30-401a-8084-bd4f9c9ca1f5#bmterms
2.   http://www.donkarl.com
3.   https://web.archive.org/web/20201201233522/http://www.dbwiki.net/
4.   http://www.access-tutorial.de/
5.   http://www.tty1.net/smart-questions_de.htm
6.   http://access.joposol.com/accept

Last but not least:   < F1 > für Hilfe
;) Learning by doing not by spoon-feed ;)

Tipp: Find and Replace for Access

maddhin

Zitat von: DF6GL am August 10, 2020, 09:59:57warum importierst Du nicht alle Daten auf einmal

Ich hole nur - bei Neuanlage einer Firma - Firmenname und Adresse von einer Webseite via Button auf dem Firmenstammdaten Formular (frmCompany) (Dim IEDocument As HTMLDocument, Set IEDocument = IEObject.Document etc). D.h. statt manuell Copy & Paste von der Webseite läuft das (dann) automatisiert. Das fsubImport Formular schalte ich nur dazwischen, um ggf. Änderungen vornehmen zu können oder um den Vorgang abzubrechen, wenn die heruntergeladenen Daten falsch sind. Eigentlich recht simple haha

Das mit der Importtabelle ist auch eine gute Idee, wobei mir das für meinen Fall zu kompliziert erscheint.

DF6GL

Hallo,

komplizierter als das Instanzierungs-Getöse und dynamischer Zuordnung an Events ist das wohl nicht...


Und wenn es sich nur um das Übertragen von ein paar Kontakt-Daten von einer Website aus handelt, dann kannst Du gleich das an die Zieltabelle gebundene Form im "Daten eingeben"-Modus benutzen und die einzelnen Werte in die Standardwert-Eigenschaften der Formular-Steuerelemente schreiben. Dadurch wird erst dann ein neuer realer DS erzeugt, wenn irgendein Wert tatsächlich manuell geändert oder eingetragen wurde.  Wird nichts manuell eingeben, besteht die Möglichkeit, den Vorgang ohne irgendwelche Datenänderungen (auch Import-Eingaben) abzubrechen.

Viele Grüße vom Bodensee
Franz, DF6GL

Hilfestellung:  http://www.access-o-mania.de/forum/index.php?topic=6969.msg118738#msg118738

Links und Tipps:
1.   http://v.hdm-stuttgart.de/~riekert/lehre/db-kelz/
1a. http://www.tinohempel.de/info/info/datenbank/normalisierung.htm
1b. https://support.office.com/de-de/article/Grundlagen-des-Datenbankentwurfs-eb2159cf-1e30-401a-8084-bd4f9c9ca1f5#bmterms
2.   http://www.donkarl.com
3.   https://web.archive.org/web/20201201233522/http://www.dbwiki.net/
4.   http://www.access-tutorial.de/
5.   http://www.tty1.net/smart-questions_de.htm
6.   http://access.joposol.com/accept

Last but not least:   < F1 > für Hilfe
;) Learning by doing not by spoon-feed ;)

Tipp: Find and Replace for Access

PhilS

Zitat von: maddhin am August 10, 2020, 09:36:06Ich habe jetzt nochmal die Screen.ActiveForm/Control probiert, das geht aber wohl nicht oder ich habe was falsch gemacht.
[...]
Aber das mit dem frm bekomme ich trotzdem leider nicht hin.
Solche Aussagen helfen leider nicht weiter.
Bitte zeig, was du genau gemacht/versucht hast (Code).
Dann beschreibe warum das nicht funktioniert (z.B. Fehlermeldung).
Neue Videoserie: Windows API in VBA

Klassische CommandBars visuell bearbeiten: Access DevTools CommandBar Editor

ebs17

Zitatdie neuen Informationen in dem Hauptformular (= frm) speichern
Bei Datenbanken, die ich kenne, erfolgt eine Speicherung grundlegend in Tabellen. Formulare sind nur vorübergehende temporäre Objekte ohne eigenes Speichervermögen.

Den Inhalt einer Tabelle kann man dann beliebig in vielen unterschiedlichen Formularen anzeigen und Verwendungen verarbeiten.

Wenn man diese beiden Zusammenhänge für sich verarbeitet, kommt man auch zu ganz einfachen Abläufen.
Mit freundlichem Glück Auf!

Eberhard

maddhin

Zitat von: DF6GL am August 10, 2020, 10:30:01komplizierter als das Instanzierungs-Getöse und dynamischer Zuordnung an Events ist das wohl nicht...

LOL - naja, ich bin immer noch dabei ein Gefühl für Access zu bekommen :)

Ich werde mit Deinen/Euren Tipps das mal weiter probieren und dann ggf. erstmal aufgeben und erstmal ohne fsubImport-Zwischenformular implementieren.

Lieben Dank!

maddhin

Zitat von: ebs17 am August 10, 2020, 10:45:34
Zitatdie neuen Informationen in dem Hauptformular (= frm) speichern
Bei Datenbanken, die ich kenne, erfolgt eine Speicherung grundlegend in Tabellen. Formulare sind nur vorübergehende temporäre Objekte ohne eigenes Speichervermögen.
Gut, das habe ich falsch bzw. ungenau formuliert. Was ich damit meinte ist sowas wie me.CorpName = txtCorpName. D.h. das wird dann natürlich in tblCompany gespeichert und nicht im Formular :)

Danke für den Hinweis.

DF6GL

#10
Hallo,


was ich meinte, ist ( bei Ereignis "Form_Load" und Neuanlage einer Firma oder vor  "Docmd.GotoRecord ,, acNewrec", bzw. Me.DataEntry =True) :

Me!CorpName.DefaultValue  = """" & ParseImport("CorporateName") & """"
Sofern "ParseImport("CorporateName")" den Firmennamen von der Website liefert.
Viele Grüße vom Bodensee
Franz, DF6GL

Hilfestellung:  http://www.access-o-mania.de/forum/index.php?topic=6969.msg118738#msg118738

Links und Tipps:
1.   http://v.hdm-stuttgart.de/~riekert/lehre/db-kelz/
1a. http://www.tinohempel.de/info/info/datenbank/normalisierung.htm
1b. https://support.office.com/de-de/article/Grundlagen-des-Datenbankentwurfs-eb2159cf-1e30-401a-8084-bd4f9c9ca1f5#bmterms
2.   http://www.donkarl.com
3.   https://web.archive.org/web/20201201233522/http://www.dbwiki.net/
4.   http://www.access-tutorial.de/
5.   http://www.tty1.net/smart-questions_de.htm
6.   http://access.joposol.com/accept

Last but not least:   < F1 > für Hilfe
;) Learning by doing not by spoon-feed ;)

Tipp: Find and Replace for Access

maddhin

Ich habe jetzt erstmal das Popup rausgenommen, weil mir das zu viel Zeit kostet (bin an der ganzen Import-Geschichte schon 2 Tage dran :) ). Das muss ich über die nächsten Tage nochmal probieren und besser verstehen.

Soweit bin ich aber erstmal schon sehr stolz, dass ich das überhaupt hinbekommen habe... :)

Im Moment ist meine Funktion eigentlich ziemlich direkt: IE öffnen, Daten holen und etwas bearbeiten und anzeigen bzw. "speichern". Popup mit den neuen Daten wäre schön, aber eher Luxus - v.a. wenn das so kompliziert wird:)

Function Import(frm As Form)
Dim IEObject As InternetExplorer
Dim waituntil As Double
Dim i As Integer
Dim AName As String
Dim j As Integer
Dim StrCorpName As String
Dim StrStreet As String
Dim StrCity As String
Dim StrIDState As String
Dim StrStateName As String
Dim StrIDCountry As String
Dim StrCountry As String
Dim StrWebsite As String
Dim StrWebsite2 As String
Dim StrWebA As String


    If IsNull(frm.Corp_Name) Then
        MsgBox ("Please put short name into company name field and try again")
        Exit Function
    Else
        AName = frm.Corp_Name
    End If

Set IEObject = New InternetExplorer

    IEObject.Visible = True

    IEObject.navigate ("https://" & AName & ".xyz.com/contactinfo.html")

    'Do While IEObject.Busy = True Or IEObject.ReadyState <> READYSTATE_COMPLETE
   
     '   Application.Now TimeValue("00:00:01")
       
    'Loop

    waituntil = Now + TimeValue("00:00:10")
    Do
      DoEvents
    Loop Until Now >= waituntil

    Debug.Print IEObject.LocationURL
   
    'Get the HTML document for the page
    Dim IEDocument As HTMLDocument
    Set IEDocument = IEObject.Document
   
    'Grab Company Information

    'Grab a elements collection
    Dim IEElements As IHTMLElementCollection
    Dim IEElements2 As IHTMLElementCollection
    Set IEElements = IEDocument.getElementsByClassName("title-text")
    Set IEElements2 = IEDocument.getElementsByClassName("item-value")
        Debug.Print IEElements2.Length

    'Grab a specific element.
    Dim IEElement As IHTMLElement
    Dim IEElement2 As IHTMLElement

     
        For i = 0 To (IEElements2.Length - 1) Step 1

        Set IEElement = IEElements.item(i)
        Set IEElement2 = IEElements2.item(i)

        If i = 0 Then
        StrCorpName = IEElement2.innerText
        ElseIf i = 1 Then
       
            Dim WrdArray() As String
            Dim text_string As String
            Dim strg As String
            Dim strg2 As String
                                   
            text_string = IEElement2.innerText
           
            'getting address as word array
            WrdArray() = Split(text_string, ", ")
                   
            'put back together the street
            For j = LBound(WrdArray) To (UBound(WrdArray) - 3)
                If j = (UBound(WrdArray) - 3) Then
                StrStreet = StrStreet & WrdArray(j)
                Else
                StrStreet = StrStreet & WrdArray(j) & ", "
                End If
            Next j
                     
            StrCity = WrdArray(UBound(WrdArray) - 2)
            StrStateName = WrdArray(UBound(WrdArray) - 1)
            StrIDState = DLookup("[id_state]", "tbl_countrystatelist", "[state_name] = '" & StrStateName & "'")
            StrCountry = WrdArray(UBound(WrdArray))
       
        ElseIf i = 2 Then
        StrWebsite = IEElement2.innerText
        ElseIf i = 3 Then
        StrWebA = IEElement2.innerText
        End If
    Next i
   
    'close IE window
    'IEObject.Quit

    '---------------
    'Parsing
    frm.Corp_Name = StrCorpName
    frm.Corp_Street = StrStreet
    frm.Corp_City = StrCity
    frm.ID_State = StrIDState
    frm.cboState.Requery
    frm.Manu_Website = StrWebsite
    'frm.Manu_Website_Contactform = StrWebsite2
    frm.Manu_Website_A = StrWebA

''-------------------------------------------------------------------------------------------------------------
''run the Import popup
''-------------------------------------------------------------------------------------------------------------
'Dim oForm As Form
'Dim strCaption As String
'Set oForm = Form_fsubimport
'
'    oForm.InsideHeight = 5000
'    oForm.InsideWidth = 10000
'    'make the form appear
'    oForm.Visible = True
'
'    oForm.txtCorpName = StrCorpName
'    oForm.txtstreet = StrStreet
'    oForm.txtCity = StrCity
'    oForm.txtIDState = StrIDState
'    StrStateName = DLookup("[State_Name]", "tbl_countrystatelist", "[ID_State] = " & StrIDState)
'    oForm.txtStateName = StrStateName
'    oForm.txtCountry = StrCountry
'    oForm.txtWebsite = StrWebsite
'    'oForm.Manu_Website_Contactform = StrWebsite2
'    oForm.txtWebA = StrWebA
'
''    Dim ctlOK As Control
''    Set ctlOK = oForm.Controls("cmdok")
''    ctlOK.OnClick = "=ParseImport()"
''    Set ctlOK = Nothing
     
End Function

crystal

Hallo maddhin,

ein paar allgemeine Bemerkungen zu deinen Wünschen und gut angedachten Ideen (wiedermal etwas länglich).

Ich bin ja ein Freund von globalen Variablem, mit denen man "beliebig" Daten zwischen Formularen, Funktionen und Subs hin- und herreichen kann. (Stimmt eigentlich nicht, weil die Variablen bzw. deren Inhalt ja nicht z. B. als Call-Parameter übergeben werden, sondern "einfach" [durchaus im doppelten Wortsinn] im Speicher vorhanden sind.)

Wenn du also ein paar Variablen in einem Modul deklarierst, z. B.
public g_sName as string
public g_bStatus as boolean
usw.
kannst du sie z. B. in einem Formular vorbelegen
g_sName="Mein Name ist Hase" ' oder was sinnvolleres wie g_sName=me.form.name
g_bStatus=false
call Irgendwas
if g_bStatus = true then
usw.

In "Irgendwas" kannst du dann auch auf diese Variablen zugreifen,
If g_sName = "Mein Name ist Hase" then
...
  g_sStatus=true
endif

Globale Variable sind von überall zugreifbar, natürlich lesend und schreibend. Steuernde Variablen wie hier g_sName können beliebigen Inhalt haben, man ist nicht gezwungen, hier z. B. den Namen eines Formulars zu benutzen. Oft reicht es aus, einen einfachen beschreibenden Wert zu benutzen, damit du weißt, von wo der Aufruf gekommen ist. das müssen auch keine Strings sein, Zahlen machen genauso Sinn. Du kannst auch Arrays oder Collections global benutzen, so dass die Initialisierung/Löschung etwas einfacher ist und mit Loops erledigt werden kann.

Ich benutze globale Variable ganz gern, weil ich die Zuordnung zu Feldern meines Formulars bzw. meiner zugrunde liegenden Tabelle dann eben im aufrufenden Code machen kann und so sehe, was passiert, immer nach dem Muster
1. globale variable leeren/nullen
2. Funktion/Sub aufrufen
3. neue Werte der globalen Variablen prüfen, verarbeiten und zuordnen

Globale Variable sind vor allem deshalb interessant, weil sie nicht den OpenArgs-Restriktionen unterliegen und auch nicht von vordefinierten Aufruf-Parametern z. B. bei Events beeinflusst werden.

Nachteil: man muss sich selbst darum kümmern, sie zu initialisieren, zu löschen, zu interpretieren.

Globale Variable sind m. E. ein erster Schritt zur objekt-orientierten Denkweise. Das Objekt ist hierbei die Applikation selbst, irgendeine Funktion bearbeitet Variable dieses Objekts, eine andere Funktion stellt sie optisch dar und speichert sie in die Tabelle. Der nächste Schritt ist es dann, diese globalen Variablen und zugehörige Funktionen gewissen Bereichen oder Kontexten zuzuordnen - und schon nähert man sich dem Konzept "Klassen, Eigenschaften und Methoden".

So kann man durchaus auch in "linearen" oder prozeduralen Programmiersprachen objekt-ähnliche Strukturen realisieren, Funktionen bestimmten Daten zuordnen, selbst wenn es Fortran-77 wäre... oder eben VBA (das schon recht viele Grundprinzipien objektorientierter Programmierung enthält). Aber das nur nebenbei.


Noch ein anderer Hinweis:
In Access gibt es eine Reihe von Collections, z. B. auch für Formulare. Diese Collections sind über Indizes, aber auch über Namen ansprechbar. Du brauchst einer Sub oder Funktion also nicht das Objekt Formular selbst zu übergeben, sondern nur dessen Namen. In der Funktion kannst du dann auf das betreffende Formular-Objekt z. B. mit
me.application.forms(g_sFormName).controls(g_sControlName).Color = vbGreen
oder
me.application.forms("frmMyForm")...
zugreifen.
Ggf. musst du da im Debug-Modus mal einen Haltepunkt setzen und einfach im Direktfenster ein paar prints versuchen:
?me.application.forms("frmMyForm").controls("txtKunde")
?me.application.forms("frmMyForm").activecontrol.name
usw.

Der Objekt-Katalog, aber auch schon Intellisense hilft hier recht gut.


Einem Steuerelement erst im FormOpen-Event, also zur Laufzeit, eine OnClick-Prozedur zuzuweisen, halte ich auch für eher falsch, zumal ich darin keinen Vorteil sehe. Ich denke, da wolltest das nur machen, weil du Parameter übergeben wolltest.


Ich habe das alles jetzt nicht in Code-Blöcke geschrieben und auch nicht real getestet, weil ich einen kleinen PC-Crash hatte und erstmal alles neu intallieren muss...

Noch ein kleiner Tipp am Rande zum Thema Parsing:

https://stackoverflow.com/questions/47592151/how-do-i-parse-html-without-creating-an-object-of-internet-explorer-in-vba

Viel Erfolg weiterhin mit deiner wohl wohl durchdachten Anwendung (ja, 2* wohl)...

Gruß,
crystal
Wer Fehler in meinen Antworten findet, darf sie behalten, muss sie aber kommentieren. ;-)
Dies ist keineswegs arrogant gemeint, sondern soll nur unterstreichen, dass meine Antworten - natürlich - nicht immer fehlerfrei sind und sein können.
Devise: bitte immer erst selbst probieren!

Aus gesundheitlichen Gründen nur noch selten dabei...

PhilS

Zitat von: crystal am August 10, 2020, 15:16:40Globale Variable sind vor allem deshalb interessant, weil sie nicht den OpenArgs-Restriktionen unterliegen und auch nicht von vordefinierten Aufruf-Parametern z. B. bei Events beeinflusst werden.

Nachteil: man muss sich selbst darum kümmern, sie zu initialisieren, zu löschen, zu interpretieren.
Korrekt.
Der Nachteil ist nicht zu unterschätzen. In einer ereignisbasierenden Anwendung, wie es alle Access-Anwendungen sind, ist das "sich selbst darum kümmern" praktisch nur schwer realisierbar. Du musst bei jedem, auch indirektem, Zugriff auf eine globale Variable deren Zustand und aktuellen Verwendungszweck, auch in jeder möglichen Konstellation durch andere Ereignisreihenfolgen, vollständig überblicken. - Das ist mental nicht leistbar!

Die o.a. OpenArgs-Restriktionen finde ich da im Vergleich als Problem geradezu schon trivial.

Zitat von: crystal am August 10, 2020, 15:16:40Globale Variable sind m. E. ein erster Schritt zur objekt-orientierten Denkweise.
Nein, nein, nein!
Globale Variablen sind die absolute Antithese zu einer objekt-orientierten Denkweise!
Ein sinnvolles, verständliches und wartbares objektorientiertes Design entsteht dadurch, interne (private) Abläufe zu kapseln und von allem außerhalb des Objektes strikt zu trennen. Die Kommunikation zwischen verschiedenen Objekte erfolgt ausschließlich über klar definierte öffentliche APIs (Methoden / Nachrichten).
Globale Variablen widersprechen jedem einzelnen Aspekte eines sinnvollen objektorientierten Designs!

Ein toller, allerdings englischer, Talk zu diesem Thema: hafentalks #7 - Sandi Metz: "Go Ahead, Make a Mess"
Neue Videoserie: Windows API in VBA

Klassische CommandBars visuell bearbeiten: Access DevTools CommandBar Editor

crystal

@PhilS
Sicher hast du Recht mit deinen Anmerkungen. Streng genommen.

Sicher würden globale Variable jeden strengen objektorientierten Ansatz behindern oder zerstören. Streng genommen.
Ich behaupte ja auch nur, dass ein Nachdenken über globale Variable letztlich zu einer objektorientierten Denkweise führen muss. Denn es wird und muss schnell klar werden, dass solche globalen Variablen sinnvoll gekapselt werden müssen und nicht "einfach so" existieren sollten/dürften.

Ich denke nur darüber nach, wie die "Objekt-Orientierung" irgendwann einmal entstanden ist. Damals wollte man ja zunächst nur Objekte (Strukturen von Daten) und deren Bearbeitung sinnvoll miteinander verbandeln. Erste Ansätze dazu habe ich vor vielen Jahren in Fortran-77 und sogar in der VMS-Commandosprache DCL versucht, freilich ohne nachhaltigen Erfolg...

Naja - das führt aber zu weit und ist hier sicher nicht angebracht.


Deinen ersten Einwand kann ich auch nicht ganz teilen. Natürlich sind globale Variable per se nur schwierig zu überwachen und zu kontrollieren. Ich muss stets genau wissen, was ich tue (siehe mein einfaches Schema). Aber genau das sollte man als Entwickler ja immer wissen. Statt z. B. mühsam über verschachtelte Referenzen auf irgendwelche Formular-Bestandteile (z.B. mit .parent.form.parent) zuzugreifen, geht es unter Verwendung globaler Variablen oft etwas einfacher.

Ich habe z. B. eine kleine private Anwendung, in der an verschiedenen Stellen Bilder vorkommen. Bei allen diesen Bild-Elementen reagiere ich auf das Click-Event mit einem Popup-Dialog, das das kleine Bild groß darstellt. Ohne globale Variable hätte ich das wohl nicht ohne weiteres geschafft. Jetzt steht im On-Click-Event aller Bilder nur noch "Call GrossAnzeigen(me.name)", den Rest macht diese Funktion. Dazu wird im Form-Load-Event (aufrufendes Formular) nur eine globale Variable gesetzt, in der der Name des Formulars steht. Die aufgerufene Funktion benutzt dann nur den Namen des Bild-Elements, um dessen Inhalt schön groß in einem neuen Popup-Formular darzustellen. (Ähnliches habe ich auch mit Textfeldern gemacht, bei denen nach Click ein großer Text-Editor aufgerufen wird. Und durch den Parameter "me.Name"" weiß ich auch, wohin ich das Ergebnis der Bearbeitung zurückgeben muss..., etwas vereinfacht.)

Es gibt m. E. zwei grundsätzlich unterschiedliche Wege der Programmierung in Access:
1. man analysiert, woher man gekommen ist - oder
2. man bestimmt, wohin man gehen möchte (ohne schon zu wissen, ob man das Ziel auch erreicht [vorheriger Abbruch].

(1) funktioniert deterministisch und nachträglich über in Access eingebaute Referenzen und Hilfs-Konstruktionen wie "CurrentControl",
(2) funktioniert über "zielorientierte" Codierung (ich bin es, der dich aufruft, ich nenne dir meinen Namen, geb mir dein Ergebnis, wenn keines kommt - auch OK - da kann ich ja dann reagieren)


All das soll nur dazu beitragen und bewirken, über Möglichkeiten in Access nachzudenken. Ich vertrete kein Dogma, sondern empfehle eher, situationsabhängig die eine oder andere Variante zu wählen. Insbesondere der TS maddhin verfolgt m. E. recht gute Ansätze und verdient es, Alternativen aufgezeigt zu bekommen.

Meine Kommentare stelle ich immer zur Diskussion - der Leser soll und muss daraus lesen, was jeweils wichtig ist oder sein könnte.

Und statt nur zu antworten "ja das geht" (was für dich, lieber PhilS, natürlich nicht zutrifft), versuche ich ein paar Hintergründe aufzuzeigen und zum weiteren Nachdenken anzuregen sowie mögliche Alternativen aufzuzeigen. Es gibt in Access nicht DEN richtigen oder falschen Weg. Access ist m. E. eine "Spielwiese", auf der es auch erlaubt ist, Verfahren und Techniken anzuwenden, die in "echten" SQL-Datenbanken und Entwicklungs-Umgebungen nicht möglich oder erlaubt sind.

Gruß,
crystal
Wer Fehler in meinen Antworten findet, darf sie behalten, muss sie aber kommentieren. ;-)
Dies ist keineswegs arrogant gemeint, sondern soll nur unterstreichen, dass meine Antworten - natürlich - nicht immer fehlerfrei sind und sein können.
Devise: bitte immer erst selbst probieren!

Aus gesundheitlichen Gründen nur noch selten dabei...