1. Liebe Forumsgemeinde,

    aufgrund der Bestimmungen, die sich aus der DSGVO ergeben, müssten umfangreiche Anpassungen am Forum vorgenommen werden, die sich für uns nicht wirtschaftlich abbilden lassen. Daher haben wir uns entschlossen, das Forum in seiner aktuellen Form zu archivieren und online bereit zu stellen, jedoch keine Neuanmeldungen oder neuen Kommentare mehr zuzulassen. So ist sichergestellt, dass das gesammelte Wissen nicht verloren geht, und wir die Seite dennoch DSGVO-konform zur Verfügung stellen können.
    Dies wird in den nächsten Tagen umgesetzt.

    Ich danke allen, die sich in den letzten Jahren für Hilfesuchende und auch für das Forum selbst engagiert haben. Ich bin weiterhin für euch erreichbar unter tti(bei)pcwelt.de.
    Dismiss Notice

O2k - VBA: UserForm Events kontrollieren

Discussion in 'Office-Programme' started by Eric March, Feb 1, 2012.

Thread Status:
Not open for further replies.
  1. Eric March

    Eric March CD-R 80

    Moin!

    Um auf Tabellenblättern Buttons lahmzulegen kann man Application.EnableEvents bemühen.

    Mit was aber erreiche ich dasselbe in UserForms? Es ist mehr als lästig, wenn ich über einen Button A eine CheckBox B als Vorgabe oder als Folge aktivieren will (schlichtes .Value = True) und dann der Code für für CheckBox B losrennt.
    Andere Makros prüfen ob B angehakt ist oder nicht, da passiert nichts weiter, es wird nur drauf reagiert. Bediene ich aber CheckBox B muss deren Code etwas tun, je nach dem ob False oder True. Nur darf er just das nicht machen wenn ich per Makro, nicht per Maus!, die Einstellung ändere.

    Kann man also pauschal verhindern, dass Maßnahmen eines Makros nicht mit den Events gleichgesetzt sind die ich per Maus auslöse?

    Wenn mein Häkchen ungesetzt ist und ich brauche es gesetzt als Vorgabe muss ich hier durch - da geht kein Weg vorbei. Mir hilft derzeit nur irgendeine Sorte Flagge (ich nehme mal den Locked-Zustand der CheckBox dafür her) die im CheckBox-Code eine Verzweigung bzw. einen Absprung herbeiführt. Geht so was nicht anders?

    Eric March
     
  2. Hascheff

    Hascheff Moderator

    Flagge ist doch in Ordnung! Ich würde es so lassen.

    Welchem Ereignis der Checkbox ist denn der Code zugeordnet? Es gibt zum Beispiel noch Exit oder MouseUp.
     
  3. Urs2

    Urs2 Megabyte

    Hallo Eric

    Verwende das MouseDown-Ereignis, dieses reagiert nur auf Mausclicks >>>

    Private Sub CheckBox1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)

    >>> das hier unsinnige Zeug in der Klammer muss dort stehen, sonst wird nicht kompiliert.


    Gruss Urs
     
    Last edited: Feb 2, 2012
  4. Eric March

    Eric March CD-R 80

    Hi!

    Danke für die Anregungen. Der große Haken bei der Aktion ist, dass ich da größere Codemengen übernommen habe (›worden bin‹…). Da scheint gewissermaßen auch die Falle drin zu stechen in die ich getappt bin.

    Sowohl @Hascheff als auch @Urs2
    Das Problem ist, dass da offenbar die Eigenschaft (für mich: Unsitte) von VBA ausgenutzt wurde, dass das Setzen von .Value eines OptionButtons dessen Click-Ereignis auslöst. Ein If in jenem Code (ob gesetzt oder nicht, True oder False) ändert u.a. auch eine Beschriftung (einer CheckBox - statt m.E. nach besser eines Buttons… - ob man alles Auswählen oder Abwählen wolle), das Einschalten unseres OptionButtons soll als Vorgabe alles auswählen [nun, für mich hier eben nicht alles] (und folgerichtig die Beschriftung ändern). →

    MouseDown hatte ich irgendwie versucht, aber die fremd-vorprogrammierte Systematik hustet mir was.
    Mein OptionButton hat einen Kollegen von denen nur einer aktiv sein kann (oder, hurra, beide nicht). Einfaches Umschalten klappt. Nun mag ich meinen Button drücken und seinen Funktionsbereich benutzen. Die UserForm geht zu, ich mache sie später wieder auf [Activate? Initialize??], der Button ist gedrückt, aber inaktiv/disabled (dito sein Funktionsbereich). Nun kann ich den Kollegen klicken und meinen dann wieder - alles klar. Ich kann aber nicht meinen gerdückten (gedrückt überwinterten) noch mal drücken; Enablen geht, aber da er Eingeschaltet (True) ist geht er nicht mehr Einzuschalten.
    Und das ist die Falle. Re-Aktiviere ich ihn tickt er bei Null los und zersäbelt vorgenommene Einstellungen.

    Vermutlich muss ich da alles umprogrammieren. Aber auch MouseUp u.ä. löst den Gordischen Knoten nicht, dass da eine Button gedrückt ist, aber nicht auch dessen Begleiterscheinungen und ich ihn nicht über-drücken kann. Zustand wäre Ture, also kann ein IF nur was manchen? False. Schalte ich bar brav zwischen den Buttons und meiner ist echt aktiv, was will das Programm tun - den anderen Einschalten?

    Ich will ja gerne das Klick-Ereignis eines Buttons (also den Code-Block) oder sonst was per Code aufrufen wenn ich es brauche, aber dass das Setzen eines Values auf True oder False (mithin eine intialisierende Voreinstellung innerhalb von Codeblöcken) identisch mit einem echten Klick ist, das nervt tierisch. Nur weiß (zum Kuckuck) ja kein Code ob der Meister höchstpersönlich geklickt hat oder ob er Opfer einer einfachen Umschaltung per Programmiersprache wurde.

    Diese Un-Geist würde ich gerne austreiben.

    Eric March
     
  5. Urs2

    Urs2 Megabyte

    Hallo Eric

    Ich denke, Du hast Dich in einer Schneewehe festgefahren... ohne Sicht nach draussen...
    Jetzt sind auch noch OptionButtons aufgetaucht... die sind etwas komplizierter, weil es ja 2 oder mehrere Buttons gibt.

    Ich habe einen Code entworfen, der Dir aus der Sackgasse helfen könnte.
    Mache ein Userform1 mit:
    - CommandButton1
    - CheckBox1
    - OptionButton1
    - OptionButton2

    Füge diesen Code in das Userform1 ein >
    Code:
    Private Sub CommandButton1_Click()
                'hier werden die Values von CheckBox/OptionButtons per Code geändert, ohne dass deren eigener Code ausgeführt wird
                'für Tests wird hier einfach der bestehende Zustand geändert
                'im RealLife muss dann nur der gewünschte Zustand übergeben werden
            'vorher, im UserFormInitialize können Defaultwerte per Code gesetzt werden...
    If CheckBox1 = True Then CheckBox1 = False Else CheckBox1 = True
            'hier müssen beide Buttons individuell geändert werden
    If OptionButton1 = True Then OptionButton1 = False Else OptionButton1 = True
    If OptionButton1 = True Then OptionButton2 = False Else OptionButton2 = True
    
    End Sub
    
    
    Private Sub CheckBox1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
                'diese Sub arbeitet nur wenn der User per Maus den Zustand ändert
            'weil der Code anspricht bevor der Zustand tatsächlich geändert wurde >>> den Zustand hier ändern
    If CheckBox1 = True Then CheckBox1 = False Else CheckBox1 = True
            'nur zum Simulieren Deines Codes
    MsgBox "User hat den Zustand geändert"
    
    '>>> hier Dein Code der ausgeführt werden soll
    
    End Sub
    
    
                'weil man beide OptionButtons clicken kann, müssen auch beide abgefragt werden
    Private Sub OptionButton1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
            'leitet weiter an  Sub OptionChange
    OptionChange
    End Sub
    Private Sub OptionButton2_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
            'leitet weiter an  Sub OptionChange
    OptionChange
    End Sub
    
    Private Sub OptionChange()
                'diese Sub arbeitet nur wenn der User per Maus den Zustand ändert, aber >>>
                'wenn der Experte den schon aktiven Button clickt, wird sein Zustand auf passiv gesetzt >>> kann man verschmerzen ???
            'weil der Code anspricht bevor der Zustand tatsächlich geändert wurde >>> den Zustand hier ändern
    If OptionButton1 = True Then OptionButton1 = False Else OptionButton1 = True
    If OptionButton1 = True Then OptionButton2 = False Else OptionButton2 = True
            
    If OptionButton1 = True Then
                'nur zum Simulieren Deines Codes
        MsgBox "User hat den Zustand auf Option1 = wahr gesetzt"
    
        '>>> hier Dein Code der ausgeführt werden soll, wenn die Option 1 wahr ist
    Else
                'nur zum Simulieren Deines Codes
        MsgBox "User hat den Zustand auf Option1 = falsch gesetzt"
    
        '>>> hier Dein Code der ausgeführt werden soll, wenn die Option 1 falsch ist
    End If
    
    End Sub
    
    Zum Aufrufen des Forms in ein Modul oder den Code des Arbeitsblattes >

    Sub FormStart()
    UserForm1.Show
    End Sub


    Gruss Urs
     
  6. Eric March

    Eric March CD-R 80

    Erst mal vielen Dank für die Mühe.

    Mir der Schneewehe (gottseidank im Moment keine) hast du insofern recht, dass ich in fremdem alten Code stecke beim dem irgendwie was zusammengefriemelt wurde und ich so viel Lust auch nicht habe das alles zurückzuentwicken oder praktisch neu zu verfassen.
    Es wäre herrlich könnte ich Codeblöcke einfach in MouseDowns umverlagern, aber das klappt halt nicht weil es diese ärgerlichen Bande zerrisse. →

    Das Kernproblem aber ist und bleibt unabhängig von CheckBoxen und OptionButtons VBA so doof ist eigene Befehle nicht als Programmierbefehle sondern fast schon als Tastatur/Maus-Makros organisiert.
    Das setzen auf True etwa löst das Click-Ereignis aus, das Ändern einer Zelle in XL das WorksheetChange (was herrliche Endlodskreisläufe verzapft). Kann man da noch mit EnableEvents den Stecker ziehen geht so was offenbar in UserForms nicht.
    Für die Zukunft werde ich wohl Click-Ereignisse über MouseDown realisieren, aber in der Tinte in der ich zz. sitze hoff(t)e ich anders rauszuzkommen.

    Eric March


    Nachschlag
    Es werden einige Textfelder eingesetzt die u.a. auch ein Datum anzeigen was auf SpinButtons horcht und über Label einen von einer Function gelieferten Wochentag anzeigt. Das Systemdatum steht auf international - JJJJ-MM-TT. Weise ich einer TextBox das Date per .Value zu ist die Rückgabe nicht mehr für Datumsberechnungen (erraten, SpinButton) zu gebrauchen. Nehme ich aber stattdessen .Text gehts problemlos. Ein Text also geht zum Datumsrechnen, ein Value aus Datum geht nicht mehr. Juhu…
     
  7. Urs2

    Urs2 Megabyte

    Hallo Eric

    Diese Check- und Optionsdinger waren ursprünglich nur zum Abfragen durch den Code da.
    Dass sie ein eigenes Ereignis auslösen ist wie bei allen Elementen halt so, dass man sie gleichzeitig noch per Code betätigt, war wohl nie geplant...

    Dein Code scheint ein wild gewachsenes Ding zu sein. Da ein bisschen dazu, dort ein bisschen anders und hier noch ein Zusatzding... irgendwann muss man dann wieder bei Null beginnen.

    Ist mir eben auch passiert >>>
    Weil es keine Code-Aenderung braucht, war die Idee mit MouseDown ideal.
    Für die zusätzlichen OptionButtons hatte ich das dann einfach erweitert... und das ist Mist. Mit mehreren Options wird das dann vollkommen unübersichtlich.

    - im Code des Userforms setze zuoberst im Blatt, über dem ersten Sub, diese Deklaration >>>
    Dim byCode As Boolean

    - im Code des Buttons setze alle Befehle an die Check/Options zwischen die byCode-Variable >>>
    '
    byCode = True
    Checkbox1 = True
    OptionButton1 = True
    usw
    byCode = False
    '
    - im Code jeder Check/Option_Click kommt als erste Zeile >>>
    If byCode = True Then Exit Sub
    ...und dann Dein Code


    Gruss Urs
     
  8. Eric March

    Eric March CD-R 80

    Tja, auch das ist nur eine Flagge. Und bei 20 unabhängig ferngesteuerten Buttons - mögliche quer durch den Garten - müsste ich wohl deren 20 ziehen…

    Da komme ich nicht ganz mit. Fangen wir mal primitiv an, dass immer das Click-Ereignis als Vorgabe kommt. Immerhin gibt es noch andere die vorher im Alphabet stehen, also ist Click schon mal Absicht.
    Unser Code löst offensichtlich dieses Click-Ereignis aus (oder Zellereignisse, wie erwähnt) und genau Click. Ich könnte mir mit etwas Fantasie vorstellen wozu ich explizit zwischen MouseDown und MouseUp unterscheiden wollte, aber ein ordentlicher Programmiere - wenn ihm das System nicht in die Parade fährt! - kommt, mindestens bei Buttons und CheckBoxen, mit dem Bedienen durch den User als Schlüsselfunktion aus: Da will einer was, ich tue das.

    Was ich hier mal gern hätte wären Details. Was genau bewirkt diese und jene Funktion bei unserem Beispiel…
    _MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)

    …ausrichtet. Was macht Button, was könnten bei einem Häkchen X und Y bewirken? F1 bei Button liefert nur Sch…rott.
    Private Sub ShapeEnteTaste_MouseDown(ByVal Button … Oder hier mal F1 auf MouseDown - ‹Begriff nicht gefunden›. Koppele ich es aber ab, Private Sub ShapeEnteTaste_ MouseDown(ByVal … und setze F1 auf das MouseDown an bekomme ich Hilfe. Was ein Irrsinn wo ein Laie völlig daneben bleibt und der Profi verzweifelt weils inkonsistent funktioniert.

    Eric March
     
  9. Urs2

    Urs2 Megabyte

    Hallo Eric

    Wie schon geschrieben, ist das Zeug in der Klammer hier unbrauchbar.
    Da es sich aber um eine in VBA fest "verdrahtete" Funktion handelt, muss es immer dort stehen, sonst wird beim Kompilieren gemeckert.

    MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)

    Die einzelnen Argumente geben zurück >>>
    Button = mit linker oder rechter Maustaste geclickt
    Shift = zusätzlich zum Mausclick die Shift- oder Alt- oder Ctrl-Taste gedrückt
    x und y sind die rechtwinkligen Koordinaten wo genau, im Steuerelement, geclickt wurde.

    Du könntest also eine Statistik machen und dann feststellen wo genau die User mehrheitlich auf den Button clicken...
    ...wegen der starken Abnützung sollte man dann an dieser Stelle die Farbe etwas dicker auftragen...

    Brauchbar wird das aber erst in Diagrammen oder Zeichnungen, zum Beispiel mit einer Karte >>>
    X und Y werden ausgewertet > die linke MausTaste meldet "dort ist die Kneipe XYZ", die rechte sagt wo die nächste Ausnüchterungszelle ist...


    Warum das Click-Ereignis zuerst angeboten wird? Keine Ahnung, vielleicht gab es im ersten Windows nur dieses...

    Bei den Option-Buttons muss man übrigens aufpassen, Click meldet nur den OptButton der gewählt wurde.
    Ein anderer Button hat aber gleichzeitig die Auswahl verloren. Wenn das auch Tätigkeiten auslösen sollte, muss man das Change-Ereignis nehmen.

    Gruss Urs
     
  10. Eric March

    Eric March CD-R 80

    Ich sag mal so - ich will je gerade das Gegenteil erreichen: nur wenn ich Button X klicke hat sich der Klick-Code von X zu rühren, gleich was ich im Code mit X anstelle. ;)

    Aus Neugier habe ich mir mal Click, DoubleClick, MouseUp und MouseDown zurechtgelegt. Jedes notiert per Debug.Print dass es bedient wurde. Was da protokolliert wurde widerspricht in Folge und Nutzung jeglicher Vernunft. Selbst eine echte Regel (und sei sie noch so behämmert) konnte ich nicht erkennen.

    Fazit - ich müsste zu viel Zeit haben um Lust zu entwickeln das übernommene neu zu entwickeln, entwirren halte ich für Verschwendung. Für die Zukunft werde ich dann gezielt Click vermeiden.

    Eric March
     
  11. Hascheff

    Hascheff Moderator

    Solche Parameter kommen durch Vererbung dahin, wo sie unnütz sind.
     
  12. Urs2

    Urs2 Megabyte

    Ich weiss nicht, was hier vererbt werden soll.
    Der Aufrufer einer Funktion muss die Argumente immer mitgeben - was dann der Empfänger damit macht, ist egal.

    Wenn es keine UserDefinedExcelFunction ist, sind beide, der Aufrufer und der Empfänger, immer der laufende VBA-Code.
    Aber hier nicht, es ist ja ein vordefiniertes Automakro.
    Das System selbst ruft bei Click die Function auf und muss die Argumente übergeben, der VBA-Code ist nur der Empfänger.

    Gruss Urs
     
  13. Eric March

    Eric March CD-R 80

    Ich gebe Urs2 Recht, diese vorgebackenen Funktionen muss man so schlucken, ob man die ›Variablen‹ die erzeugt werden braucht oder nicht.

    Ich hatte nur den Ärger, dass sich die Hilfe mal wieder hilflos präsentiert bis ich ihr auf die Sprünge half. Für meine Nöte kann ich, wer hätt's gedacht, keine der Variablen gebrauchen.

    Eric March
     
Thread Status:
Not open for further replies.

Share This Page