Articolo wiki
  • Questo articolo wiki è bloccato
Applicabile a 3312 visualizzazioni

Excel - UserForm collezioni di controlli - VBA

Livello tecnico : Base

Riepilogo

Livello tecnico: Conoscenza di base di Visual Basic for Applications Si applica a: Excel (2003/2007/2010/2013)

Dettagli

NOTA. Gli esempi ed il codice sono forniti *così come sono* e l’autore declina ogni responsabilità per un loro uso scorretto. Utilizzate gli esempi forniti o file di prova per i vostri test. La correzione delle eccezioni (errori) e il controllo del tipo di dati inserito è solo parziale. I file vogliono essere un semplice esempio che illustra come sia possibile automatizzare Excel e sono forniti solo a scopo dimostrativo.

Situazione.

Spesso ci può capitare di avere un certo numero di controlli che devono eseguire la stessa operazione e quindi ci troviamo a riscrivere n volte lo stesso codice per tutti i controlli. E' possibile creare collezioni di controlli che rispondono tutti allo stesso evento. Ad esempio una serie di CommandButton che se premuti utilizzano lo stesso evento click.

Come fare - Le classi.

Per prima cosa creiamo tante classi quanti sono i tipi di controlli che vogliamo raggruppare. Nell'esempio che potete scaricare da Riferimenti ho creato 3 classi:

Figura 1: I tre moduli di classe creati per l'esempio.

Ho dato alle tre classi nomi significativi per far capire a quale tipo di oggetti fanno riferimento. Analizziamo il codice di clsCommandButton:

Figura 2: Il codice della classe clsCommandButton.

La prima riga contiene WithEvents, che leggiamo nella guida vb essere una parola chiave che specifica che nomevariabile (in questo caso cmd) è una variabile oggetto utilizzata per rispondere agli eventi generati da un oggetto ActiveX. In pratica, l'oggetto cmd che andiamo a creare è un CommandButton che risponderà agli eventi tipici dei controlli ActiveX di tipo CommandButton.

La seconda riga crea un oggetto UserForm

Quindi andiamo a definire l'evento Click che risponderà al click sul CommandButton cmd e inseriamo al suo interno un semplice richiamo ad una MsgBox che restituirà il Name e la Caption del controllo.

Le altre due classi contengono le stesse righe iniziali (ovviamente cambia il riferimento al tipo di controllo ActiveX). In clsTextBox ho inserito due eventi, Change e DoubleClick. Posso inserire tutti gli eventi per lo specifico controllo ActiveX, con alcune limitazioni: ad esempio il per le TextBox gli eventi Exit, Enter, BeforeUpdate e AfterUpdate non rispondono se inseriti nel modulo di classe.

Figura 3: Il codice di clsTextBox con due eventi.

In questi esempi, nell'evento è contenuto un codice che definirei banale, ma all'interno del modulo di classe possono esserci Sub o Function ai quali l'evento fa riferimento.

Come fare - La UserForm.

Vediamo adesso come utilizzare queste classi con i controlli della UserForm. Partiamo da una UserForm così strutturata:

Figura 4: La UserForm con i controlli ActiveX.

Nel codice faremo in modo che i controlli del Frame1 facciano parte di tre Collection e che rispondano agli eventi delle nostre classi, i controlli del Frame2 avranno invece il comportamento di controlli standard (nei Riferimenti trovate il link ad un articolo Wiki che introduce i controlli Frame). Il codice della UserForm è commentato passo passo.

Option Explicit

'Dichiaro le variabili che sarranno disponibili
'in tutto il codice della UserForm
Dim colTextBox As Collection
Dim colCommandButton As Collection
Dim colOptionButton As Collection
Dim myTxt As clsTextBox
Dim myCmd As clsCommandButton
Dim myOpt As clsOptionButton

'evento che si scatena all'avvio della UserForm
Private Sub UserForm_Initialize()

    'dichiaro una variabile
    Dim ctl As MSForms.Control
   
    'creo tre nuove Collection
    Set colTextBox = New Collection
    Set colCommandButton = New Collection
    Set colOptionButton = New Collection
   
    'ciclo i controlli del Frame1
    For Each ctl In Me.Frame1.Controls
        'se il controllo è una TextBox
        If TypeOf ctl Is MSForms.TextBox Then
            'creo un nuovo oggetto clsTextBox
            Set myTxt = New clsTextBox
            'metto un riferimento all'oggetto txt
            'di myText
            Set myTxt.txt = ctl
            'metto come riferimento questa UserForm per
            'l'oggetto txt
            Set myTxt.frm = Me
            'aggiungo l'oggetto creato alla collection
            colTextBox.Add myTxt


        'come sopra ma per i controlli CommandButton
        ElseIf TypeOf ctl Is MSForms.CommandButton Then
            Set myCmd = New clsCommandButton
            Set myCmd.cmd = ctl
            Set myCmd.frm = Me
            colCommandButton.Add myCmd


        'come sopra ma per i controlli OptionButton
        ElseIf TypeOf ctl Is MSForms.OptionButton Then
            Set myOpt = New clsOptionButton
            Set myOpt.opt = ctl
            Set myOpt.frm = Me
            colOptionButton.Add myOpt
        End If
    Next

    'Set a Nothing delle variabili oggetto
    Set ctl = Nothing
    Set myTxt = Nothing
    Set myCmd = Nothing
    Set myOpt = Nothing
   
End Sub

''evento che, se togliamo i commenti, verrà
''eseguito assieme all'evento Click della classe
''clsCommandButton
'Private Sub CommandButton1_Click()
'    MsgBox "Ciao dall'evento Click del CommandButton"
'End Sub

'evento eseguito alla chiusura della UserForm
Private Sub UserForm_Terminate()
    'nel caso le Collections restituisse un errore
    'lo ignoro; sarebbe meglio però implementare
    'una vera gestione delle eccezioni
    On Error Resume Next
    Set colTextBox = Nothing
    Set colCommandButton = Nothing
    Set colOptionButton = Nothing
End Sub

C'è poco da aggiungere ai commenti del codice.

Figura 5: La MsgBox che appare facendo click sul CommandButton1.

Ma cosa succede se andiamo ad implementare *anche* l'evento Click del CommandButton1 nella UserForm (nel codice del file di esempio è commentato, per attivarlo eliminare i commenti)? Semplicemente verranno eseguiti due eventi, prima l'evento CommandButton1_Click della UserForm, quindi l'evento Click implementato nell'oggetto derivato dal modulo di classe.

Figura 6: L'evento CommandButton1_Click nel modulo di codice della UserForm.

Conclusioni.

Abbiamo visto come sia possibile creare collezioni di controlli che rispondono tutti agli stessi eventi. Pensiamo alla validazione dei dati per una serie di molte TextBox che altrimenti ci costringerebbero ad avere lo stesso codice scritto n volte per n TextBox. O ancora, la gestione dell'evento Click di una serie di CommandButton o OptionButton gestita all'interno del modulo di classe. Come accennato in precedenza, non è possibile implementare tutti gli eventi dei controlli ActiveX all'interno delle classi.

Riferimenti.

Il file di esempio di questo articolo Wiki è scaricabile da qui:

Altri articoli Wiki che riguardano il VBA di Excel e le UserForm:

Un altro esempio dell'utilizzo delle collezioni di controlli e dei controlli Frame è scaricabile da qui:

L'esempio è stato creato in risposta a questa domanda fatta nella Community sul forum di Excel:

Commenti.

Sono graditi i tuoi commenti a questo articolo Wiki e, se lo ritieni interessante, per favore spunta la voce : E' stato utile all'inizio della pagina.

Grazie.

NOTA. Excel non dispone nativamente di procedure assolutamente sicure per impedire la visualizzazione e la modifica del codice vb e/o per la protezione dei fogli. E’ una cosa da tenere sempre presente quando si distribuiscono file con contenuti ritenuti delicati. Ricordate anche che è possibile lanciare il file di Excel senza che vengano eseguite le macro.


Risorse.


 Avvio Pulito di Windows
(courtesy of Microsoft MVP Franco Leuzzi)


Computer infettato da malware (courtesy of Microsoft MVP Vincenzo Di Russo)




Commenti (0)

avanzamento