Utilizzo di Event



  • Utilizzo di Event
    di Zer0Kelvin data: 09/03/2014 09:51:42

    Ciao a tutti.
    Mi capita a volte di utilizzare delle classi per personalizzare i controlli all'interno di una Userform.
    In un paio di occasioni ho dovuto fare in modo che i controlli in questione interagissero con la Userform inviandole dei messaggi.
    Finora ho risolto nel modo che potete vedere nel file di esempio allegato; cioè il controllo richiama una procedura Public all'interno della Userform.
    Ultimamente ho scoperto l'esistenza dell'istruzione Event; purtroppo l'esempio fornito dall'help di Excel non mi è stato di aiuto e la ricerca in rete ha restituito i soliti 10^9 risultati non inerenti al mio problema.
    Mi chiedevo se qualcuno di voi ne abbia fatto uso ed eventualmente dare qualche suggerimento per il mio caso specifico, oppure indicarmi una fonte utile.



  • di isy data: 09/03/2014 12:08:54

    Ciao

    Dal Link:
    h t t p://answers.microsoft.com/it-it/office/wiki/office_2013_release-excel/excel-userform-collezioni-di-controlli-vba/8f47b6f5-b845-4403-a2f0-c885eb91447f?tm=1382250832604
    Ho allegato collezionecontrolli.zip



  • di Zer0Kelvin data: 09/03/2014 16:15:26

    Ciao Isy e grazie per la risposta, ma non era questo che intendevo.
    So bene come realizzare un array di controlli e ne faccio spesso uso.
    Il mio dilemma era trovare il modo di far sì che un evento della classe definita scateni a sua volta un evento (definito da me) della Userform a cui il controllo appartiene.
    Attualmente uso questo sistema.
    - Definisco nella userform una procedure public (HandleEvent, vedi es. 1)
    - Nella classe del controllo (in questo caso una chekbox) inserisco in un gestore eventi la chiamata a HandleEvent (vedi es. 2)

    Tutta la faccenda funziona comunque bene, ma sono costretto a fare un riferimento diretto ad UserForm1, il chè limita di molto la flessibilità del programma.
    Il mio problema è semplicemente quello di non essere costretto a far riferimento ad una userform in particolare ed ho pensato che l'Istruzione Event
     
    '1)
    ===================== questo è nel modulo della userform
    Public Sub HandleEvent(ByVal Evento As clsEvent, Sender As Object)
        Select Case Evento.eEvType
            Case eCBchange
                MsgBox "Il valore di  " & Sender.cmd.Name & "è  " & Evento.eValue
        End Select
    End Sub
    
    2)
    ===================== e questo nel modulo di classe del controllo
    Private Sub cmd_Change()
        cEvent.eValue = cmd.Value
        UserForm1.HandleEvent cEvent, Me
    End Sub
    



  • di Zer0Kelvin data: 09/03/2014 16:17:55

    PS: clsEvent è una classe definita da me con due proprietà: tipoevento e valore, Sender è l'oggetto che ha invocato la sub HandleEvent.



  • di isy data: 09/03/2014 17:01:06

    Cit Zer0Kelvin: Il mio problema è semplicemente quello di non essere costretto a far riferimento ad una userform in particolare

    Vedi se può esser utile l'esempio OnExitEventCtl6.xls



  • di scossa data: 09/03/2014 18:49:58

    ciao,

    credo di non aver capito bene, però potresti aggiungere la proprietà eParent alle proprietà della tua classe (vedi codice sotto)

    N.B.: ho aggiunto un secondo checkbox alla userform.

    Non so se quanto proposto rispecchia il tuo obiettivo.

    Allego file "Test Eventi2.xlsb"
     
    '---------------------------------
    'nel modulo di classe clsEvent
    '---------------------------------
    Public Enum tEvent
        eNoEvent = 0
        eTBchange = 1
        evMouseClick = 2
        eCBchange = 4
    End Enum
    
    Private eValue_ As Variant
    Private eEvType_ As tEvent
    Private eParent_ As MSForms.UserForm
    '
    Property Get eParent() As MSForms.UserForm
        Set eParent = eParent_
    End Property
    Property Let eParent(Papa As MSForms.UserForm)
        Set eParent_ = Papa
    End Property
    
    Property Get eValue() As Variant
        eValue = eValue_
    End Property
    
    Property Let eValue(Value As Variant)
        eValue_ = Value
    End Property
    
    Property Get eEvType() As tEvent
        eEvType = eEvType_
    End Property
    
    Property Let eEvType(evtype As tEvent)
        eEvType_ = evtype
    End Property
    
    
    '---------------------------------
    'nel modulo di classe clsCHKB
    '---------------------------------
    
    Public WithEvents cmd As MSForms.CheckBox
    Private cEvent As clsEvent
    
    Private Sub Class_Initialize()
        Set cEvent = New clsEvent
        cEvent.eEvType = eCBchange
    End Sub
    
    Private Sub Class_Terminate()
        Set cEvent = Nothing
    End Sub
    
    Private Sub cmd_Change()
        cEvent.eParent = Me.cmd.Parent
        With cEvent.eParent.ActiveControl
          MsgBox "Il valore del controllo " & .Name & " è " & .Value
        End With
    End Sub
    
    '---------------------------------
    'nel modulo di classe della Userform
    '---------------------------------
    Dim CKB1 As clsCHKB
    Dim CKB2 As clsCHKB
    
    Private Sub UserForm_Initialize()
        Set CKB1 = New clsCHKB
        Set CKB1.cmd = Me.CheckBox1
        Set CKB2 = New clsCHKB
        Set CKB2.cmd = Me.CheckBox2
        
    End Sub
    


  • errata corrige
    di scossa data: 09/03/2014 19:10:42

    errata: Non so se quanto proposto rispecchia il tuo obiettivo.

    corrige: Non so se quanto proposto rispecchi il tuo obiettivo.



  • di Zer0Kelvin data: 09/03/2014 19:54:19

    Grazie ad entrambi per le risposte.
    Credo che la soluzione di Isy sia quello che stavo cercando, dal momento che la mia intenzione era di gestire l'evento proprio dall'"interno" della userform.
    Per il momento ho dato un'occhiata veloce, ma penso che dovrò "masticare" un pò prima di riuscire a digerirla.
    Per il momento lascio il post come "irrisolto".



  • di scossa data: 09/03/2014 20:35:19

    L'avevo detto che non avevo (ho) capito la tua necessità



  • di Zer0Kelvin data: 10/03/2014 08:01:42

    Rieccomi.
    Mi sono un pò chiarito le idee, ed alla fine quello che cercavo di ottenere è il codice in esempio 1; piuttosto semplice in realtà, ma mi ero "incartato" proprio su questo.
    Il problema che mi si pone adesso è: come potrei fare a gestire gli eventi generati da una Collection di controlli?
     
    **esempio 1**
    
    Questo nel modulo della form
    __________________________
    Option Explicit
    
    Public WithEvents CKB1 As clsCHKB
    
    Private Sub CKB1_HandleEvent(ByVal Evento As clsEvent, ByVal Sender As Object)
        Select Case Evento.eEvType
            Case eCBchange
                MsgBox "Il valore di  " & Sender.cmd.Name & "è  " & Evento.eValue
        End Select
    End Sub
    
    Private Sub UserForm_Initialize()
        Set CKB1 = New clsCHKB
        Set CKB1.cmd = Me.CheckBox1
    End Sub
    
    Private Sub UserForm_Terminate()
        Set CKB1 = Nothing
    End Sub
    ___________________________________
    
    
    Questo nel modulo della classe
    _________________________
    Option Explicit
    
    Public Event HandleEvent(ByVal Evento As clsEvent, ByVal Sender As Object)
    
    Public WithEvents cmd As MSForms.CheckBox
    Private cEvent As clsEvent
    
    Private Sub Class_Initialize()
        Set cEvent = New clsEvent
        cEvent.eEvType = eCBchange
    End Sub
    
    Private Sub Class_Terminate()
        Set cEvent = Nothing
    End Sub
    
    Private Sub cmd_Change()
        cEvent.eValue = cmd.Value
        RaiseEvent HandleEvent(cEvent, Me)
    End Sub
    _______________________________________________________________
    
    
    **esempio 2**
    Questo nel modulo della form
    __________________________
    Private Sub UserForm_Initialize()
    Dim ctl As MSForms.Control
    Set obkColl = New Collection
        For Each ctl In Me.Controls '<==== in realtà i controlli verranno creati in runtime uno a uno
            If TypeOf ctl Is OptionButton Then
                Set ctl = New clsCHKB
                Set ctl.cmd = ctl
                obkColl.Add ctl
            End If
        Next ctl
    End Sub
    



  • di Zer0Kelvin data: 10/03/2014 08:04:58

    Dimenticavo: vedi esempio 2
     
    **esempio 2**
    Questo nel modulo della form
    __________________________
    dim obkColl as Collection
    
    Private Sub UserForm_Initialize()
    Dim ctl As MSForms.Control
    Set obkColl = New Collection
        For Each ctl In Me.Controls '<==== in realtà i controlli verranno creati in runtime uno a uno
            If TypeOf ctl Is OptionButton Then
                Set ctl = New clsCHKB
                Set ctl.cmd = ctl
                obkColl.Add ctl
            End If
        Next ctl
    End Sub



  • di scossa data: 10/03/2014 08:51:57

    cit isy: "Vedi se può esser utile l'esempio OnExitEventCtl6.xls"

    Ciao isy,

    ho visto l'esempio che hai postato: interessante.
    Potresti cortesemente indicare il link da cui l'hai tratto, potrebbe contenere informazioni interessanti.



  • di isy data: 10/03/2014 11:25:16

    Ciao scossa
    Cit: Potresti cortesemente indicare il link da cui l'hai tratto, potrebbe contenere informazioni interessanti.

    Purtroppo il file che ho allegato era stato scaricato tempo fà e non saprei quale fosse il sito originale.
    Oggi per curiosità ho fatto una ricerca e un simile codice lo troviamo qui...
    h t t p://www.experts-exchange.com/Software/Office_Productivity/Office_Suites/MS_Office/Excel/Q_27968237.html

    per scaricare l'ultimo file della discussione in:
    h t t p://filedb.experts-exchange.com/incoming/2013/01_w02/625975/Upload-Form-Jan-6.xlsm
    nel codice è inoltre riportato un collegamento a:
    h t t p://www.mrexcel.com/forum/excel-questions/519492-cannot-setfocus-userform-control-4.html

    Sicuramente un bel mattoncino da masticare



  • di scossa data: 10/03/2014 13:41:07

    @isy: grazie