maurogsc.eu
|
![]() |
home ==> Excel: articoli ==> UserForm - Array di controlli
UserForm - Array di controlliSituazione.
Ci troviamo nella necessità di dover gestire n controlli
in una UserForm e vorremmo avere uno o più
eventi comuni. Vediamo di fare un esempio.
La nostra UserForm contiene 4 CommandButton e facendo click
su uno dei pulsanti, vorremmo chiamare una Sub passando il nome del pulsante,
in modo da eseguire codice diverso per ogni CommandButton. Dovremmo scrivere
codice all'interno di 4 eventi Click, uno per pulsante.
In Visual Basic(il tool di programmazione) c'è
la possibilità di creare in modo facile e veloce
array(matrici) di controlli che condividono gli eventi.
Nel Visual Basic di Excel dobbiamo invece ricorrere ad un *trucco*.
Nota.
Il codice dell’esempio è scaricabile a questo link.
Il codice ed i files sono forniti *così come sono* e
l’autore declina ogni responsabilità su eventuali
problemi causati dal codice o dai files se usati
impropriamente. Utilizzate gli esempi forniti o files
di test per le vostre prove. Codice e file sono stati
testati con(e quindi validi per) Excel 2000/Xp(2002)/2003/2007/2010.
Una classe...
ALT+F11 e siamo nell'editor del Visual Basic.
Creiamo un modulo di classe(Inserisci-->Modulo di classe) e
rinominiamolo clsCommandButton. Mettiamo questo codice:
Option Explicit
'dichiarazione variabili visibili all'esterno
'della classe
'WithEvents specifica che la variabile
'è una variabile oggetto utilizzata
'per rispondere agli eventi generati '
'da un oggetto ActiveX.
Public WithEvents cmd As MSForms.CommandButton
Public frm As UserForm
'evento Click
Private Sub cmd_Click()
'chiamata alla routine mEsegui
'viene passato come parametro
'il Name del CommandButton
'sul quale si è fatto Click
Call mEsegui(cmd.Name)
End Sub
'routine chiamata dall'evento Click
Private Sub mEsegui(ByVal s As String)
'MsgBox che identifica il
'nome del CommandButton passato
'come parametro
MsgBox "Hai premuto: " & s
End Sub
Le due variabili Public(quindi visibili ed utilizzabili dall'esterno dell'oggetto che andremo a creare). La prima è preceduta da WithEvents, una parola chiave che specifica che la variabile cmd è una variabile oggetto utilizzata per rispondere agli eventi generati da un oggetto ActiveX(il nostro CommandButton) e che è valida solo nei moduli di classe. La seconda variabile è una variabile oggetto di tipo UserForm. L'evento cmd_Click() sarà quello che risponderà al click sull'oggetto cmd, eseguendo la routine mEsegui().
...e una Collection.
Inseriamo una UserForm(Inserisci-->UserForm) al progetto e aggiungiamole 4 CommandButton.
Questo il codice della UserForm:
Option Explicit
'dichiaro le variabili a livello
'di UserForm(visibili cioè da
'tutta la UserForm)
Dim colCommandButton As Collection
Dim myCmd As clsCommandButton
'evento eseguito all'avvio della userForm
Private Sub UserForm_Initialize()
'dichiarazione variabile
Dim ctl As MSForms.Control
'controllo non vi sia già un
'oggetto colCommandButton
'(in questo specifico caso,
'non servirebbe)
If Not colCommandButton Is Nothing Then
'se non c'è, creo l'oggetto
Set colCommandButton = Nothing
End If
'creo l'oggetto Collection
Set colCommandButton = New Collection
'per ogni Control dell'insieme
'Controls della UserForm
For Each ctl In Me.Controls
'se il controllo è un CommandButton
If TypeOf ctl Is MSForms.CommandButton Then
'creo un nuovo oggetto
Set myCmd = New clsCommandButton
'metto come riferimento alla variabile
'cmd dell'oggetto creato, l' Item
'(ctl) dell'insieme Controls a cui
'fa riferimento il ciclo in questo momento
Set myCmd.cmd = ctl
'metto come riferimento alla variabile
'frm dell'oggetto creato, la UserForm
Set myCmd.frm = Me
'aggiungo l'oggetto alla Collection
colCommandButton.Add myCmd
End If
Next
'Set a Nothing della variabile oggetto
Set ctl = Nothing
End Sub
'evento eseguito alla distruzione della UserForm
Private Sub UserForm_Terminate()
'Set a Nothing delle variabili oggetto
Set myCmd = Nothing
Set colCommandButton = Nothing
End Sub
Abbiamo dichiarato e istanziato una Collection(colCommandButton) visibile da tutta la UserForm e dichiarato una variabile oggetto di tipo clsCommandButton(myCmd) che è la classe che abbiamo creato in precedenza. Nell'evento Initialize della UserForm, dichiariamo un'altra variabile oggetto di tipo MSForm.Control(ctl) che ci servirà per ciclare tutti controlli presenti sulla UserForm. Se i controlli sono di tipo CommandButton, andiamo a creare e ad aggiungere un nuovo oggetto alla Collection. Alla variabile oggetto cmd viene assegnato per riferimento il controllo e alla variabile oggetto frm viene assegnata per riferimento la UserForm. Sarà sufficiente lanciare la UserForm e fare click su uno dei pulsanti per vedere il risultato. Se aggiungiamo altri CommandButton alla nostra UserForm, non dobbiamo modificare nulla nel codice perché verranno aggiunti alla Collection alla prima apertura della UserForm.
Un array di OptionButton.
Potrei aver necessità di avere un array per controlli
che si trovano all'interno di un Frame, ad esempio degli OptionButton.
Aggiungiamo una nuova UserForm al progetto. Inseriamo un Frame(Frame1)
e al suo interno posizioniamo due OptionButton.
Molto spesso ci si dimentica dei Frame che risultano invece utilissimi per
dividere i controlli sulla UserForm sia dal punto di vista del layout, sia dal
punto di vista della programmazione. All'esterno del Frame mettiamo altri 2 OptionButton.
Ci serve una nuova classe(Inserisci-->Modulo di classe) e
modifichiamone il nome in clsOptionButton.Questo il codice per la classe:
Option Explicit
'dichiarazione variabili visibili all'esterno
'della classe
'WithEvents specifica che la variabile
'è una variabile oggetto utilizzata
'per rispondere agli eventi generati '
'da un oggetto ActiveX.
Public WithEvents opt As MSForms.OptionButton
Public frm As UserForm
'evento Click
Private Sub opt_Click()
'chiamata alla routine mEsegui
'viene passata come parametro
'la Caption del'OptionButton
'sul quale si è fatto Click
Call mEsegui(opt.Caption)
End Sub
'routine chiamata dal dall'evento Click
Private Sub mEsegui(ByVal s As String)
'MsgBox che identifica la
'Caption del'OptionButton passato
'come parametro
MsgBox "Hai selezionato: " & s
End Sub
E questo il codice per la UserForm:
Option Explicit
'dichiaro le variabili a livello
'di UserForm(visibili cioè da
'tutta la UserForm)
Dim colOptionButton As Collection
Dim myOpt As clsOptionButton
'evento eseguito all'avvio della userForm
Private Sub UserForm_Initialize()
'dichiarazione variabile
Dim ctl As MSForms.Control
'controllo non vi sia già un
'oggetto colOptionButton
'(in questo specifico caso,
'non servirebbe)
If Not colOptionButton Is Nothing Then
'se non c'è, creo l'oggetto
Set colOptionButton = Nothing
End If
'creo l'oggetto Collection
Set colOptionButton = New Collection
'per ogni Control dell'insieme
'Controls del Frame1 di questa
'UserForm
For Each ctl In Me.Frame1.Controls
'se il controllo è un OptionButton
If TypeOf ctl Is MSForms.OptionButton Then
'creo un nuovo oggetto
Set myOpt = New clsOptionButton
'metto come riferimento alla variabile
'cmd dell'oggetto creato, l' Item
'(ctl) dell'insieme Controls a cui
'fa riferimento il ciclo in questo momento
Set myOpt.opt = ctl
'metto come riferimento alla variabile
'frm dell'oggetto creato, la UserForm
Set myOpt.frm = Me
'aggiungo l'oggetto alla Collection
colOptionButton.Add myOpt
End If
Next
'Set a Nothing della variabile oggetto
Set ctl = Nothing
End Sub
'evento eseguito alla distruzione della UserForm
Private Sub UserForm_Terminate()
'Set a Nothing delle variabili oggetto
Set myOpt = Nothing
Set colOptionButton = Nothing
End Sub
Se seleziono gli OptionButton racchiusi nel Frame1, ottengo un MsgBox di risposta. Selezionando gli OptionButton all'esterno del Frame1 non ottengo nulla in quanto sto ciclando solo i controlli dell'insieme Controls del Frame1 e solo quelli fanno parte della mia Collection.
Concludendo.
Alcuni eventi non possono essere utilizzati quando si creano
array di controlli. Ad esempio per la TextBox non è possibile
utilizzare Exit, Enter, BeforeUpdate e AfterUpdate.
Quando inserite un evento, generatelo prima nel codice della UserForm
per essere poi sicuri di scriverlo correttamente nel modulo
di classe(alcuini eventi si aspettano degli
argomenti). E' possibile definire più eventi per lo stesso oggetto all'interno di una classe.
Nel file di esempio, scaricabile qui, si trova un esempio relativo
alle TextBox con più eventi(il codice non è commentato, ma valgono gli stessi
commenti che trovate negli altri moduli del progetto).
Per ulteriori informazioni su Microsoft Excel ed il suo Visual Basic, utilizzate
questo forum:
http://social.answers.microsoft.com/Forums/it-IT/officeexcelit/threads
Ultimo aggiornamento di questa pagina: 14/10/2009 - mauro gamberini