Combobox - Listbox: scrittura - lettura

Ultima modifica: 27-05-2016

 

Questa pagina dovrebbe essere la sintesi di tutte quelle già presentate in precedenza e che riguardano i controlli ComboBox e ListBox disegnati su UserForm.

Cercherò di illustrare una gestione completa di ComboBox e ListBox ad una ea a più colonne.

Prima di iniziare con l'esposizione alcune piccole note.

  • Nota 1: Tra una ListBox ed una ComboBox ci sono solo piccole differenze. Quindi è lecito parlare di uno dei due controlli e riferirisi anche all'altro.
    La ComboBox tiene i valori nascosti da una tendina e si rendono visibili aprendo la tendina. Quando si sceglie una voce tra quelle elencate nella tendina, nell'area di testo viene visualizzata una sola voce (specie nelle ComboBox multicolonna). In una ComboBox è possibile selezionare una voce alla volta.
    La ListBox mostra tutti tutti i valori al suo interno, anche se si tratta di un elenco muilticolonna. Contrariamente alla ComboBox, in una ListBox è possibile selezionare più valori disposti su più righe.
  • Nota 2: Quel che verrà mostrato qui di seguito sono comuni a entrambi i controlli ListBox e ComboBox, dove non specificato altrimenti.
  • Nota 3: Negli esempi di seguito indicati, i codici vba devono essere inseriti nel modulo della UserForm su cui è disegnato il controllo, se non diversamente specificato.

 

Questa è la tabella su cui andremo a lavorare .

 

Creazione della UserForm usate per questo studio

Prima di passare al progetto finale, prepariamo una UserForm ed i controlli che ci servono durante questa esercitazione. Tra gli altri controlli metteremo sulla UserForm una ComboBox sulla quale si basa questa pagina.

Ora posso passare a descrivere le proprietà e i motodi più usati per una ComboBox o ListBox.

Questi due controlli possono essere di due tipi: Monocolonna e Multicolonna.

Per aggiungere Moduli in un progetto VBA, uno dei modi più veloci, è possibile usare il tasto destro del mouse nelle finestra VBAProject, come mostrato in questa immagine, e scegliere il tipo di modulo da aggiungere.

 

Popolare una ComboBox o ListBox monocolonna

Questi i tre modi più comuni per eseguire questa operazione.

Per ciascuno di questi, è necessario determinare l'intervallo o, se supportato, una matrice possibilimente ad una colonna. Tuttavia, se l'intervallo o la matrice sono a più colonne, solo la prima colonna verrà utilizzata per il riempimento del controllo.

E' buona norma, prima di riempire una ComboBox o ListBox cancellarne l'eventuale contenuto usando il metodo Clear con l'istruzione

ComboBox1.Clear.


Il metodo AddItem è forse il più conosciuto e più usato per aggiunge una riga ed eventualmente un nuovo elemento nell'elenco di in controllo ComboBox o ListBox.

Per inserire molti dati provenienti da una tabella o una matrice normalmente si usa un ciclo:

For R = 1 To Righe
ComboBox1.AddItem (Intervallo(R, 1))
Next

La ComboBox può essere aggiornata in qualsiasi momento con l'istruzione:

ComboBox1.AddItem "valore".

Per inserire un elemento in una posizione precisa di una ComboBox anzichè alla fine è possibile usare questa sintassi:

ComboBox1.AddItem "valore aggiunto", NumRiga

dove NumRiga è un numero valido compreso tra 0 ed il mumero di elementi contenuti nella ComboBox. Eseguendo questa operazione viene aggiunta una nuova voce nella posizione indicata e tutte le voci già presenti nel controllo, a partire da questa posizione, vengono spinti in basso.

In questa pagina possiamo vedere il codice usato.


La proprietà List restituisce o imposta le voci dell'elenco di un controllo ComboBox o ListBox.

Per inserire i dati contenuti in un intervallo o una matrice nella ComboBox senza usare alcun ciclo è possibile usare la istruzione:

ComboBox1.List() = Intervallo.Value (con o senza le parentesi tonde).

Una volta ottenuta la ComboBox coi suoi valori, è possibile aggiungere nuovi valori come fatto col metodo Additem.

Anche qui c'è la pagina col codice di esempio per usare questo codice.


La proprietà RowSource, come la proprietà List, accetta un intervallo da cui proviene l'elenco da aggiungere ad un controllo ComboBox o ListBox. L'istruzione da usare è

ComboBox1.RowSource = "A2:A21"

che nel nostro caso diventa:

ComboBox1.RowSource = Intervallo.Address

Differenze dall'uso della proprietà List

Come il solito ecco la pagina col codice usato.

Mentre col metodo Additem l'azione di inserimento dei valori in questi controlli è abbastanza trasparente, per inserire i dati con gli altri due modi, se l'intervallo o la matrice che si sta tentando di inserire nei controlli hanno più di una colonna, solo la prima viene realmente inserita.

 

Popolare una ComboBox o ListBox multicolonna

Anche per usare questi controlli nella modalità milticolonna sono validi i tre metodi appena visti nella modalità monocolonna ma con piccoli varianti, soprattutto per quanto riguarda il metodo Additem.

Intanto dobbiamo indicare la nostra intenzione di volere una ComboBox multicolonna usando la proprietà ColumnCount che specifica il numero di colonne da visualizzare in una ComboBox o ListBox.

L'istruzione per far questo è:

ComboBox1.ColumnCount = Colonne

dove Colonne, in base a questa tabella , vale 5 (da 0 a 4 perchè l'indice di questi controlli è a base 0).

Anche in questo caso è necessario determinare prima l'intervallo o una matrice da usare.

Tralasciando la descrizione del riempimento dei controlli tramite le proprietà List e RosSource che sono identiche a quelle appena viste, possiamo vedere cosa cambia se usiamo il metodo Additem.

Per riempire una ComboBx multicolonna occorre eseguire queste operazioni:

For R = 1 To Righe
ComboBox1.AddItem
For C = 1 To Colonne
ComboBox1.List(R - 1, C - 1) = Intervallo(R, C)
Next
Next

Anche per aggiungere semplicemente una riga in una ComboBox multicolonna, quindi in fondo alla lista, occorre usare la stessa tecnica dell'uso del metodo Additem e della proprietà List.

Combo_Count = ComboBox1.ListCount
ComboBox1.AddItem (TextBox1)
ComboBox1.List(Combo_Count, 1) = TextBox2
ComboBox1.List(Combo_Count, 2) = TextBox3
ComboBox1.List(Combo_Count, 3) = TextBox4
ComboBox1.List(Combo_Count, 4) = TextBox5

Come per la monocolonna è anche possibile inserire un elemento in una posizione precisa di una ComboBox anzichè alla fine con questa sintassi:

ComboBox1.AddItem "TextBox1", 5 ' 5 è il numero di riga scelto in maniera arbitraria e che si trova alla sesta posizione della ComboBox o ListBox.
ComboBox1.List(5, 1) = "TextBox2"
ComboBox1.List(5, 2) = "TextBox3"
ComboBox1.List(5, 3) = "TextBox4"
ComboBox1.List(5, 4) = "TextBox5"

In questa pagina è visibile il codice completo.

 

Lettura di ComboBox e ListBox

Come per l'invio di dati ad una ComboBox o ListBox, anche per la lettura ci sono più metodi.

I principali modi per leggere quel che una ComboBox o ListBox sono l'uso delle proprietà Value, proprietà Text, proprietà List.

In ComboBox o ListBox monocolonna queste proprietà restituiscono generalmente lo stesso valore.

Negli stessi controlli multicolonna il valore restituito dipende dalla proprietà TextColumn e dalla proprietà BoundColumn.

La proprietà BoundColumn identifica quale elemento della riga memorizzare come valore del controllo e viene restituito dalla proprietà Value.

La proprietà TextColumn identifica la colonna che viene visualizzata nell'area di immissione del testo di una casella combinata e viene restituito dalla proprietà Text.

Questi risultati senza usare la proprietà TextColumn e la proprietà BoundColumn sono visibili in queste due immagini: la scelta della voce e il risultato .

Qui è possibile visionare il codice completo.

Se usassimo la proprietà TextColumn e la proprietà BoundColumn avremmo questo diverso risultato: la scelta della voce e il risultato . La modifica al codice è visibile qui

La ListBox, contrariamente alla ComboBox, supporta la proprietà MultiSelect che, se impostata a fmMultiSelectMulti, consente di selezionare o deselezionare più elementi dell'elenco premendo la barra spaziatrice o facendo clic con il mouse. Qui una immagine che mostra la ListBox in azione.

Una volta impostata questa modalità è possibile usare questo:

ListBox1.MultiSelect = fmMultiSelectMulti
ListBox1.List = Intervallo.Value

Per leggere più elementi selezionati in una ListBox si può usare questo aiutandosi dalla proprietà Selected

For R = 0 To ListBox1.ListCount - 1
If ListBox1.Selected(R) = True Then
Range("A65536").End(xlUp)(2, 1) = ListBox1.List(R)
ListBox1.Selected(R) = False
End If
Next

Qui il codice.

 

Larghezza colonne per ListBox o ComboBox a più colonne

E' possibile usare la Proprietà ColumnWidths per aggiustare la larghezza delle colonne in ListBox o ComboBox a più colonne per evitare che alcune colonne vengano nascoste o troncate. L'istruzione da eseguire è questa:

Facendo alcune prove su come avvicinarmi il più possibile alla reale dimensione da dare a ciascuna colonna di una ListBox o ComboBox a più colonne sono arrivato a queste due conclusioni.

Una più semplice e veloce se i dati sono in una tabella del foglio e le sue colonne sono impostate a larghezza colonne adatte.

Una più complessa e articolata se la tabella del foglio non è correttamente formattata o se, addirittura, i dati provengono da altre fonti.

Nel primo caso:

Nel secondo caso:

Finite le operazioni preliminari indicate nel primo o nel secondo caso, si passa alla formattazione della UserForm e del controllo in esame:

UserForm6.Width = LenMax + 20 ' modifica della larghezza della UserForm
ComboBox1.ColumnWidths = Larg
' modifica della larghezza delle colonne della ListBox
ComboBox1.Width = LenMax + 10
' modifica della larghezza della ComboBox

Il risultato di questa operazione è visibile in questa immagine .

In questa pagina è visibile il codice completo per formattare le colonne di una ListBox o ComboBox a più colonne

 

Qui un elenco delle principali proprietà e metodi che possono essere usati coi due controlli

Dopo aver visto le due operazioni più importanti che si possono compiere con una ComboBox e/o una ListBox descriviamo alcune delle proprietà e metodi tra quelli più utili.

Questo è l'elenco di quelli che verranno qui esposti ed altri potrebbero esserne aggiunti in un prossimo futuro


Metodo AddItem: Con ListBox o ComboBox a colonna singola, aggiunge un elemento all'elenco, mentre con ListBox o ComboBox a più colonne aggiunge una riga.

Se si fornisce un valore valido per indicevar (List(Riga,Colonna)), il metodo AddItem aggiunge l'elemento o la riga nella posizione corrispondente all'interno dell'elenco. Se si omette indicevar, il metodo aggiunge l'elemento o la riga in fondo all'elenco.

Il valore di indicevar non deve essere maggiore del valore della proprietà ListCount.

La sintassi:

ComboBox1.AddItem ' Aggiunge una riga vuota in fondo alla lista

ComboBox1.AddItem "Valore" ' Aggiunge una riga in fondo alla lista e ne assegna subito un valore

ComboBox1.AddItem "Valore", NumRiga ' Aggiunge una riga nella posizione indicata da NumRiga spingendo tutte le righe sottostanti di una posizione verso il basso

Se il controllo è associato a dati (RowSource), il metodo AddItem non viene applicato ma genera un errore.


Metodo RemoveItem: elimina una riga dall'elenco di una ComboBox o ListBox.

Questo metodo non elimina la riga dall'elenco se il controllo ComboBox o ListBox è associato a dati, ovvero nei casi in cui la proprietà RowSource specifica una fonte dati per il controllo ComboBox o ListBox, anzi se si tenta di applicare questo metodo viene generato un errore di run-time.

La sintassi:

ComboBox1.RemoveItem (ComboBox1.ListIndex) ' oppure è possibile indicare un qualsiasi numero valido


Proprietà List: aggiunge un intero intervallo o una matrice di dati in una ListBox o ComboBox a colonna singola o multipla senza usare alcun ciclo.

La sintassi:

ComboBox1.List = Intervallo.Value

oppure

ComboBox1.List = MiaMatrice


Proprietà RowSource: specifica ed accetta intervalli di celle di fogli di lavoro di Microsoft Excel.

La sintassi:

ComboBox1.RowSource = Intervallo.Address

Contrariamente alla proprietà List, una volta caricati i dati con RowSource non è più possibile aggiungere o eliminare elementi da un controllo ListBox o ComboBox


Proprietà BoundColumn: identifica l'elemento nella colonna indicata dal valore attribuito a BoundColumn di un controllo ComboBox o ListBox a colonne multiple quale elemento della riga memorizzare come valore del controllo e viene restituito dalla proprietà Value.

Quando si sceglie una riga di un controllo ListBox o ComboBox a colonne multiple, la proprietà BoundColumn identifica quale elemento della riga memorizzare come valore del controllo. Con ComboBox1.Value si ottiene il valore della colonna indicata in BoundColumn.

La sintassi:

ComboBox1.BoundColumn = 3 ' Assegna al controllo il valore della colonna specificata col numero 3


Proprietà TextColumn: identifica la colonna di un controllo ComboBox o ListBox in cui viene memorizzata la proprietà Text quando l'utente seleziona una riga.

La colonna designata dalla proprietà TextColumn viene visualizzata nell'area di immissione del testo di una ComboBox.

La sintassi:

ComboBox1.TextColumn = 2


Proprietà ListRows: specifica il numero massimo di righe visualizzabili nell'elenco esposto da una ComboBox o ListBox.

La sintassi:

ComboBox1.ListRows = 10


Metodo Clear: rimuove tutte le voci dell'elenco di un controllo ListBox o ComboBox.

La sintassi:

ComboBox1.Clear ' rimuove tutte le voci dell'elenco


Proprietà ColumnHeads: Visualizza una singola riga di intestazioni di colonna per ListBox o ComboBox e non sarà possibile selezionarli

Nelle ComboBox le intestazioni vengono visualizzate solo quando viene aperta l'elenco a discesa.

La sintassi:

ComboBox1.ColumnHeads = True ' con True specifica che le intestazioni di colonna vengono visualizzate con False le intestazioni non vengono visualizzate

  • Nota 1: Le intestazioni di colonna in una ListBox o ComboBox sono supportate solo se i controlli prelevano i dati da un intervallo di un foglio di lavoro tramite la proprietà RowSource.
  • Nota 2: Nella scelta dell'intervallo da inserire in una ListBox o ComboBox occorre fare attenzione che l'intervallo nel foglio abbia già delle intestazioni immediatamente sopra la prima riga di dati validi.
  • Nota 3: In questo caso occorre che l'intervallo abbia un Offset(1, 0)
    Set Intervallo = Range("A1").CurrentRegion.Resize(Righe, Colonne).Offset(1, 0)
    in modo da escludere le intestazioni dall'intervallo, ma che rimangano comunque immediatamente sopra. In questo caso inserendo i dati nel controllo la riga esclusa dall'intervallo viene presa come intestazione di colonna. In caso contrario le intestazioni di colonna saranno delle anonime: Colonna A, Colonna B, Colonna C, ecc.

Proprietà ColumnWidths: Specifica la larghezza di ciascuna colonna in una casella combinata o casella di riepilogo a colonne multiple. La larghezza delle varie colonne è espressa da una stringa di questo genere: "55,5;51,75;121,5;35,25;108" dove le voci della colonna, sono separate da un punto e virgola (;). I numeri con virgole sono semplici numeri decimali.

La sintassi:

ComboBox1.ColumnWidths = String ' un valore possibile per String potrebbe essere "55,5;51,75;121,5;35,25;108"

La stringa può essere creata in un ciclo che legge la larghezza di ogni singola colonna:

For C = 1 To Colonne
A1 = Cells(1, C).Width
LenMax = LenMax + A1
Larg = Larg & A1 & ";"
Next
Larg = Left(Larg, Len(Larg) - 1)
' per togliere l'ultimo punto e virgola

Come spiegato più sopra si possono seguire 2 strade:

Il codice è, come il solito, in questa pagina già vista precedentemente


Proprietà Width: restituisce o determina la larghezza di un qualsiasi oggetto.

Nel progetto corrente questa proprietà viene usata più volte:

La sintassi:


Proprietà ListIndex: identifica o imposta l'elemento selezionato in un controllo ListBox o ComboBox.

La proprietà ListIndex contiene un indice della riga selezionata in un elenco. Quando non è selezionata alcuna riga, ListIndex restituisce –1.

Se la proprietà MultiSelect viene utilizzata per la creazione di un controllo ListBox che consente selezioni multiple, le righe selezionate vengono indicate dalla proprietà Selected di ListBox (anziché dalla proprietà ListIndex).

La sintassi:

Combo_index = ComboBox1.ListIndex

oppure

ComboBox1.ListIndex = ComboBox1.ListCount - 1


Proprietà MultiSelect: Indica se l'oggetto consente la selezione multipla. Di solito viene applicata al controllo ListBox e, per ovvi motivi, non al controllo ComboBox.

I possibili valori da assegnare alla Proprietà MultiSelect è:

fmMultiSelectSingle Consente la selezione di un solo elemento (impostazione predefinita)
fmMultiSelectMulti Consente di selezionare o deselezionare un elemento dell'elenco premendo la barra spaziatrice o facendo clic con il mouse
fmMultiSelectExtended Premendo MAIUSC e facendo clic con il mouse o premendo MAIUSC in combinazione con uno dei tasti di direzione, la selezione viene estesa dal primo elemento selezionato all'ultimo. Premendo CTRL e facendo clic con il mouse, è possibile selezionare o deselezionare un elemento

La sintassi:

ListBox1.MultiSelect = fmMultiSelectMulti


Proprietà Selected: è una matrice con un numero di valori equivalente al numero di righe di ListBox.

La proprietà è utile soprattutto se ad un controllo ListBox è stata applicata la proprietà MultiSelect.

Per ciascuna riga della casella di riepilogo, Selected è True se la riga è selezionata e False in caso contrario. In un controllo ListBox che consente selezioni multiple, ListIndex restituisce l'indice della riga in cui si trova lo stato attivo, indipendentemente dal fatto che tale riga sia o meno selezionata.

La proprietà Selected risulta utile quando gli utenti possono eseguire selezioni multiple. La proprietà consente di determinare le righe selezionate in una casella di riepilogo a selezione multipla. La proprietà consente inoltre di selezionare o deselezionare, tramite il codice, le righe desiderate di un elenco.

Il valore predefinito della proprietà si basa sullo stato di selezione corrente di ListBox.

La sintassi:

For R = 0 To ListBox1.ListCount - 1
If ListBox1.Selected(R) = True Then
.................
End If
Next

In questa pagina si legge il codice completo per gestire una ListBox a selezione multipla: