Per quanto ci impegniamo, anzi appunto per questo, tante volte succede che una cosa che sembra chiarita mostra dei risvolti sconosciuti. E questo accade anche per alcuni componenti della nostra quotidiana vita di programmazione.
Per questo motivo questa volta vorrei approfondire un nuovo aspetto delle ComboBox o ListBox che in questi giorni ho dovuto affrontare.
Su come riempire e gestire le ComboBox e o le listBox oramai abbiamo scritto e letto abbastanza.
Questa volta vediamo come è possibile gestire una ComboBox da un'altra ComboBox.
La tabella
su cui intendo lavorare è visibile in questa pagina.
Come potete osservare il questa tabella ci sono i seguenti campi:
| ID | Cognome | Nome | CAP | PROV | CITTA' | INDIRIZZO |
|---|
Quel che vogliamo fare è semplice: scelta una città da una ComboBox, nell'altra ComboBox dovremmo poter selezionare solo i contatti ad essa abbinati.
Iniziamo quindi col costruire una bella UserForm come questa.
L'azione, detta semplicemente, la eseguiamo in due tempi:
Ora possiamo vedere in dettaglio come è organizzato il lavoro.
L'evento Activate dellUserForm
L'azione si svolge in tre fasi
L'evento Change della ComboBox1
Anche qui abbiamo tre fasi
L'evento Change della ComboBox2
Useremo questo Evento per eseguire il resto del lavoro su cui in questo contesto soprassiedo
L'evento Click del CommandButton1
Anche per questo evento per il momento non ci impegnamo più del necessario
Il codice visto in questa prospettiva risulterà più semplice.
Le variabili pubbliche
Teniamo presente che ci sono delle variabili che useremo in tutte le routine che useremo perciò, invece di ricominciare sempre d'accapo per valorizzare queste variabili le rendiamo pubbliche. Per far questo le dichiariamo nella zona dichiarazione delle variabili, ossia nelle primissine righe del modulo relativo alla UserForm:
Dim Intervallo As Range
Dim Righe, Colonne
L'evento Activate dellUserForm
Il codice che segue non necessita di commenti
Private Sub UserForm_Activate()
Dim Riga
Dim Elenco As New Collection
' 1 fase: determinare l'intervallo
With Range("A1").CurrentRegion
Righe = .Rows.Count - 1
Colonne = .Columns.Count
Set Intervallo = .Offset(1, 0).Resize(Righe, Colonne)
End With
' 2 fase; creare un elenco univoco delle città usando la Collection
On Error Resume Next
For Riga = 1 To Righe
Elenco.Add Intervallo(Riga, 6).Value, CStr(Intervallo(Riga, 6).Value)
Next
On Error GoTo 0
' 3 fase: riempimento della ComboBox1
For Riga = 1 To Elenco.Count
ComboBox1.AddItem Elenco(Riga)
Next
End Sub
L'evento Change della ComboBox1
La ComboBox2, contrariamente alla ComboBox1 che viene riempita una sola volta, viene riempita più volte durante l'uso della routine.
Per questo motivo, ogni volta che viene riempita con nuovi dati, prima deve essere svuotata, altrimenti il suo elenco diverrà così lungo da essere pressocchè inutilizzabile.
Dopo questa unica nota ecco il codice
Private Sub ComboBox1_Change()
Dim Citta, Riga
'1 fase: cancellazione del contenuto della ComboBox2
ComboBox2.Clear
' 2 fase: lettura del nome scelto
Citta = ComboBox1.Text
' 3 fase: reperimento di tutte le occorrenze della città nella tabella
' e riempimento della ComboBox2
With Intervallo
For Riga = 1 To Righe
If .Item(Riga, 6) = Citta Then
ComboBox2.AddItem (.Item(Riga, 2))
End If
Next
End With
End Sub
L'evento Change della ComboBox2
Dopo i lavori appena descritti possiamo usare questa ComboBox2 come più ci aggrada. In questo esempio lo uso semplicemente per riempire le TextBox correlati al nome scelto.
Private Sub ComboBox2_Change()
Dim Nome, Citta
Dim Riga
Nome = ComboBox2.Text
Citta = ComboBox1.Text
With Intervallo
For Riga = 1 To Righe
If .Item(Riga, 2) = Nome And .Item(Riga, 6) = Citta Then
TextBox1 = .Item(Riga, 2)
TextBox2 = .Item(Riga, 3)
TextBox3 = .Item(Riga, 4)
TextBox4 = .Item(Riga, 5)
TextBox5 = .Item(Riga, 6)
TextBox6 = .Item(Riga, 7)
End If
Next
End With
End Sub
L'evento Click del CommandButton1
Per il momento ci limitiamo ad usare il pulsante CommandButton1 per trasferire sul Foglio2 i dati che abbiamo raccolto nelle caselle di testo. Per complicarci leggermente la vita decidiamo di non trasferirvi il Codice che, nel foglio1 si trova nella prima colonna.
Private Sub CommandButton1_Click()
Dim Col, Riga, Uriga
' se la textbox1 è vuota non si fa nulla
With Worksheets("Foglio2")
If TextBox1 = "" Then
MsgBox "Occorre scegliere un nome"
Exit Sub
End If
' se nel Foglio2 mancano le intestazioni di colonna si provvede a scriverle copiandole dal Foglio1
If .Range("A1") = "" Then
For Col = 2 To Colonne
.Cells(1, Col - 1) = Intervallo(0, Col)
Next
End If
' ora si possono trasferire sul foglio2 i contenuti delle TextBox
Riga = .Range("A1").CurrentRegion.Rows.Count + 1
For Col = 1 To Colonne - 1
.Cells(Riga, Col) = Controls("Textbox" & Col)
Next
End With
End Sub
Questa routine ha già i commenti che servono quindi mi esimo dal farne altri.
Questo è tutto, per ora. Ci sentiamo la prossima volta