Selezioni interessanti e precise

Ultima modifica: 29-05-2016

 

Iniziamo col prendere in esame questa tabella. In questa le "X" rappresentano i dati già inseriti nella tabella che è quella zona colorata.

Perchè la tabella sia riconosciuta in tutta la sua ampiezza, è importante che, anche se la tabella non è completamente riempita in tutte le sue celle, come indicato nella prima tabella, i dati non lascino righe o colonne vuote come nelle altre due tabelle a fianco.

 

  A B C D E F G H I J K L M
1                          
2                          
3     X     X              
4       X             X    
5         X         X      
6           X   X          
7             X   X        
8                          
9                          
10                          
        
  A B C D E F G H I J K L M
1                          
2                          
3     X     X              
4       X             X    
5         X         X      
6                          
7             X   X        
8                          
9                          
10                          
        
  A B C D E F G H I J K L M
1                          
2                          
3     X     X              
4       X             X    
5         X         X      
6           X   X          
7                 X        
8                          
9                          
10                          

Dopo queste premesse possiamo vedere come le seguenti proprietà dell'oggetto Range possano aiutarci ad effettuare precise ed importanti selezioni. Ognuna di esse ha un modo diverso di lavorare (e di farci lavorare). Visto che gli argomenti che sto per esaminare sono abbastanza numerosi, passo subito ad elencarli.

Se teniamo conto di queste considerazioni potremmo essere più sicuri sugli effetti che le seguenti proprietà avranno nelle nostre tabelle: End, CurrentRegion, UsedRange, Count, Cells, Rows, Columns.

 

La proprietà End

Proprietà End equivale a premere CTRL+ FRECCIA SU, CTRL+ FRECCIA GIÙ, CTRL+ FRECCIA SINISTRA o CTRL+ FRECCIA DESTRA e si composta come è descritto in questo grafico:

 

  A B                                    
1       Range("A1").End(xlDown).Select   seleziona la cella "A4"
2            
3            
4 X     Range("A4").End(xlDown).Select   seleziona la cella "A7"
5 X     Range("A4", Range("A4").End(xlDown)).Select   seleziona l'intero intervallo "A4:A7"
6 X          
7 X     Range("A7").End(xlDown).Select   seleziona la cella "A11"
8            
9            
10            
11 X     Range("A11").End(xlDown).Select   seleziona l'ultima cella del foglio
12            
13            

 

Una delle selezioni da mettere in evidenzia è quella che, qui sopra nello schema, è evidenziata.

Questa effettua una selezione che va dalla "A4" per finire in "Range("A4").End(xlDown)". La sintassi dell'istruzione rispecchia quella classica di base che è:

Proprietà CurrentRegion

Restituisce un oggetto Range, che rappresenta l'area corrente, cioè l'area che circonda o è vicina alla cella di riferimento.

Perchè questa particolare proprietà funzioni non è necessario che tutte le celle della tabella in esame siano non vuote, ma che le celle non vuote occupino tutte le righe e le colonne della tabella (vedi la prima tabella qui in alto).

Non è necessario che la cella di partenza sia nell'angolo superiore sinistro della tabella, ma in una qualsiasi locazione all'interno della tabella o esternamente ad essa purché nella immediata vicinanza ci sia una cella appartenente alla tabella stessa. In quest'ultimo caso il riferimento si allarga al di fuori della tabella.

Tuttavia la selezione eseguita con questo metodo funziona a grappolo: se una o più celle non sono a contatto con con le altre che verrebbero incluse dalla selezione, verranno escluse.

A conclusione si ha che la proprietà CurrentRegion esige che la cella da cui parte l'azione sia:

Vediamo qui sotto alcuni esempi:

  A B C D E F G H I J K L M
1                          
2                          
3     X     X              
4       X             X    
5         X         X      
6           X   X          
7             X   X        
8                          
9                          
10                          
Range("C3").CurrentRegion.Select   restituisce l'intervallo "C3:K7"
Range("E3").CurrentRegion.Select   restituisce l'intervallo "C3:K7"
Range("C2").CurrentRegion.Select   restituisce l'intervallo "C2:K7"
Range("B2").CurrentRegion.Select   restituisce l'intervallo "B2:K7"
Range("B3").CurrentRegion.Select   restituisce l'intervallo "B3:K7"
Range("L4").CurrentRegion.Select   restituisce l'intervallo "J4:L5"
    perchè la "J5" non ha una cella limitrofa valida nella colonna "I"
Range("F3").CurrentRegion.Select   restituisce l'intervallo "F3"
    stessa osservazione di sopra
Range("L8").CurrentRegion.Select   restituisce l'intervallo "L8"
Range("H3").CurrentRegion.Select   restituisce l'intervallo "H3"

 

Non a caso ho presentato la tabella di esempio. A seconda della cella di origine le celle con la "X" in rosso potrebbero essere escluse dalla selezione. Provate ad eseguire "CurrentRegion" partendo dalla cella "F3" o dalle celle "J5" o "K4".

Un'altra caratteristica richiesta da questa proprietà è che la cella da cui parte l'azione sia:

 

Proprietà UsedRange

Restituisce un oggetto Range, che rappresenta l'intervallo utilizzato del foglio di lavoro specificato anche se i dati sono sparsi in più parti del foglio.

Contrariamente a "CurrentRegion" la proprietà UsedRange esegue una selezione su tutte le celle non vuote presenti sul foglio inglobando nella selezione anche le celle vuote tra quelle comprese.

Un'altra particolarità è che CurrentRegion si applica ad un oggetto range, mentre UsedRange si applica al foglio.

Questa proprietà non solo restituisce un riferimento a tutte le celle non vuote, ma anche a qualsiasi cella che, anche se vuota, in qualche modo ha una qualsiasi formattazione: formato, formato carattere, bordo, riempimento, ecc.

Nella tabella che stiamo trattando come esempio restituirà l'intervallo "C3:K7" se nel foglio è presente la sola tabella che in questa esercitazione, ma se ci fosse in un posto qualsiasi del foglio anche una sola cella che, anche se vuota, abbia una qualche formattazione che non sia quella predefinita del foglio, si estenderebbe sino a comprendere quella determinata cella.

Questa è la sua sintassi:

ActiveSheet.UsedRange.Select

Worksheets("Foglio2").UsedRange.Select

 

Count

E' questa una proprietà che si applica a moltissimi oggetti che incontriamo in VBA. Se applicata all'oggetto Range ci restituisce il numero di celle, righe o colonne in esso compreso.

Vediamo alcuni esempi applicati alla tabella che stiamo esaminando:

NumEl = Range("C3").CurrentRegion.Cells.Count
restituisce il numero "45"

Riga = Range("C3").CurrentRegion.Rows.Count
restituisce il numero "5"

Colonna = Range("C3").CurrentRegion.Columns.Count
restituisce il numero "9"

 

Cells - Range

Queste sono proprietà sia dell'oggetto Worksheet che all'oggetto Range.

Usandoli come proprietà dell'oggetto Worksheet vengono usati in questo modo (che è il nostro modo più usuale:

Cells(Riga, Colonna).Select

per selezionare la cella che incontriamo alle coordinate indicate da "Riga" e "Colonna", oppure

Range("A1").Select

per selezionare la prima cella in alto a sinistra del foglio di lavoro.

 

Ma possiamo usarli anche con le seguentiistruzioni:

Range("C3:K7").Cells(1, 1).Select

Range("C3:K7").Range("A1").Select

per selezionare la prima cella e cioè la cella C3

Queste selezioni non ci restituiscono l'intervallo che ci aspetteremmo, infatti ci restituiscono la cella "C3" e non "A1".

Questo potrebbe essere un modo di esplorare tutte le celle dell'intervallo compreso in Range("C3").CurrentRegion, che nel nostro esempio è rappresentato dall'intervallo C3:K7:

With Range("C3").CurrentRegion
Riga = .CurrentRegion.Rows.Count
Colonna = .CurrentRegion.Columns.Count
For R = 1 To Riga
For C = 1 To Colonna
.Cells(R, C).Select
Next
Next
End With

In queste istruzioni occorre porre attenzione al . (punto) posto prima di Cells(R, C). Se questo punto viene omesso le selezioni non vengono più effettuate dalla cella C3 alla cella K7, bensì dalla della A1 del foglio.

Importante:

A questo punto si potrebbe creare della confusione perchè "Range" è, a seconda dei casi, sia una proprietà dell'oggetto "Worksheet" che dello stesso oggetto "Range".

Ma rifacciamoci un attimo alla sintassi canonica da usare per selezionare una determinata cella.

Object.Cells(Riga,Colonna).

Se nell'usare questa proprietà ci riferiamo all'oggetto "Worksheet", possiamo semplificare l'istruzione ommettendo la descrizione dell'Object.

Ma se ci riferiamo ad un oggetto "Range" la descrizione dell'Object "Range va sempre espressa.

 

Come il solito alcuni esempi possono chiarirci le idee.

Con riferimento al Foglio

Worksheets("foglio1").Range("A1").Select   per la cella A1
Worksheets("foglio1").Cells(5, 3).Select   per la cella C5
Worksheets("foglio1").Cells(1, 180).Select   per la cella FX1
Worksheets("foglio1").Cells(1, 260).Select   Questa non si può usare in quanto il limite massimo per le colonne è 256

Forse è il caso di ribadire che il numero limite per indicare una colonna è 256 mentre quello per indicare una riga è 65536 ma c'è anche un altro modo di riferirsi alle celle, indicando un solo indice, anzichè due.

Worksheets("foglio1").Cells(265).Select   per la cella I2
Worksheets("foglio1").Cells(2650).Select   per la cella CL11
Worksheets("foglio1").Cells(16777216).Select   per la cella IV65536 che è l'ultima cella del foglio

In questo caso il numero più grande che viene accettato è 16.777.216 che risulta dal prodotto 256 * 65.536 che sono i limiti massimi consentiti per le colonne e per le righe.

In tutti questi casi possiamo scrivere le stesse istruzioni senza far riferimento all'oggetto padre (in questo caso Worksheets che se omesso è comunque sottinteso).

Range("A1").Select   per la cella A1
Cells(5, 3).Select   per la cella C5
Cells(1, 180).Select   per la cella FX1
Cells(2650).Select   per la cella CL11

 

Con riferimento a Range

Come dicevo prima posso riferirmi ad un range partendo da un intervallo ben preciso:

Range("C3:K7").Range("A1").Select   per la cella C3
Range("C3:K7").Cells(5, 3).Select   per la cella E7
Range("C3:K7").Cells(1).Select   per la cella C3
Range("C3:K7").Cells(260).Select   per la cella J31
Range("C3:K7")(1).Select   per la cella C3
Range("C3:K7")(1, 1).Select   per la cella C3

Ma in questi casi si può usare anche l'istruzione With in questo modo:

With Range("C3:K7")
.Range("A1").Select
.Cells(5, 3).Select
' ecc.
End With

Ma attenzione al . (punto) da anteporre a Range o a Cells. Se si omette il punto si torna a lavorare sulle celle come appartenenti all'intero foglio e non più all'intervallo di riferimento.

 

Interessante è lavorare con intervalli denominati.

Dim Intervallo As Range
Set Intervallo = Range("C3:K7")
With Intervallo
.Range("A1").Select
.Cells(5, 3).Select
End With
' oppure
Intervallo(1, 1).Select
Intervallo(5, 3).Select

Con questi ultimi esempi è possibile spaziare oltre i limiti di 5 Righe e 9 Colonne di cui è composto l'intervallo in oggetto, ma si può andare ben oltre.

Ne consegue che è possibile creare l'intervallo anche facendo riferimento ad una sola cella come nella seguente istruzione:

Set Intervallo = Range("C3")

In entrambi i casi, per i vari spostamenti si fa riferimento sempre alla cella C3.

 

"Cells" è senz'altro più flessibile di "Range". Tanto per dirne una possiamo comodamente usare "Cells" in un ciclo "For ... Next" usandone il contatore come indice di riga e/o colonna.

 

Rows - Columns

Lo stesso discorso si può applicare sulle altre due proprietà, Rows e Columns. Anche queste due proprietà possono riferirsi sia all'oggetto Worksheets che alloggetto Range, per cui non mi dilungo ulteriormente sull'argomento. Ecco alcuni esempi:

Worksheets("foglio1").Rows(5).Select   restituisce la riga "5" - con Oggetto omesso si sottintende il riferimento a "Worksheets"
Columns(7).Select   restituisce la colonna "G"
Range("C3:K7").Rows(1).Select   restituisce la prima riga dellintervallo "C3:K3" (la 3)- qui l'oggetto è rappresentato da "Range"
Range("C3:K7").Rows(Range("C3:K7").Rows.Count).Select   restituisce l'ultima riga dell'intervallo "C3:K7" (la 7)
Range("C3:K7").Columns(1).Select   restituisce la prima colonna dell'intervallo "C3:K7" (la C)
Range("C3:K7").Columns(20).Select   nella colonna 22 (la ventesima da "C3") tra la terza e la settima riga

L'uso combinato di tutte o qualche proprietà appena viste ci daranno dei risultati interessanti.

 

Ora una piccola chicca sulla selezione di più colonne usando delle variabili.

Lavorando su Righe e/o colonne si potrebbero incontrare delle difficoltà.

Sappiamo che la sintassi canonica è:

Rows("3:8").Select
Columns("H:K").Select

Ma se volessimo selezionare più righe o colonne contemporaneamente, usando magari delle variabili per coordinate o indici, ci troveremmo in difficoltà.

Allora, o ricorriamo ad istruzioni del genere:

Range(Cells(A, 1), Cells(B, 1)).EntireRow.Select
Range(Cells(1, A), Cells(1, B)).EntireColumn.Select

o dobbiamo costruire manualmente la stringa di cui abbiamo bisogno.

Per le righe possiamo usare questo:

A = 3: B = 5
Rows(A & ":" & B).Select

Per le colonne non possiamo usare la stessa espressione: "Columns(A & ":" & B).Select" in quanto l'espressione produrrebbe un errore.

Allora dobbiamo ricorrere ad un espediente:

 

Set Intervallo = Range("C3").CurrentRegion
A = Split(Intervallo(1).Address, "$")(1)
B = Split(Intervallo(Colonne).Address, "$")(1)
Columns(A & ":" & B).Select

 

Semplici esempi di utilizzo

Contare il numero di celle, righe e colonne

NumEl = Range("C3:K7").Cells.Count

Ci restituisce "45" che è il numero complessivo delle celle contenute nell'intervallo

NumEl = Range("C3:K7").Count

Ci restituisce "45" (le due istruzioni sono equivalenti)

Riga = Range("C3:K7").Rows.Count

Ci restituisce "5"

Colonna = Range("C3:K7").Columns.Count

Ci restituisce "9"

 

Trovare la prima cella, riga o colonna della tabella:

Range("C3:K7").Cells(1).Select

Ci restituisce la cella "C3" la prima cella dell'intervallo

Range("C3:K7")(1).Select

Ci restituisce la cella "C3" ancora la prima cella

Range("C3:K7").Rows(1).Select

Ci restituisce l'intervallo "C3:K3" la prima riga

Range("C3:K7").Columns(1).Select

Ci restituisce l'intervallo "C3:C7" la prima colonna

 

Trovare l'ultima cella, riga o colonna della tabella

Riga = Range("C3:K7").Rows.Count

restituisce "5" che è il numero di righe dell'intervallo

Colonna = Range("C3:K7").Columns.Count

restituisce "9" che è il numero di colonne

Range("C3:K7")(Range("C3:K7").Count).Select

Ci restituisce la cella "K7" che è l'ultima cella dell'intervallo

Range("C3:K7")(Riga, Colonna).Select

Ci restituisce "K7" che è l'ultima cella dell'intero intervallo

Range("C3:K7")(Range("C3:K7").Rows.Count, Range("C3:K7").Columns.Count).Select

Anche questo ci restituisce "K7"

Range("C3:K7").Rows(Riga).Select

Ci restituisce "C7:K7" che è l'ultima riga dell'intera tabella

Range("C3:K7").Columns(Colonna).Select

Ci restituisce "K3:K7" che è l'ultima colonna dell'intera tabella

 

Conclusioni

 

Per ogni argomento trattato ho cercato di passare in rassegna vari metodi e dove possibile ho cercato anche di esporre metodi alternativi. Questo perchè molte volte è capitato anche a me di cercare una soluzione alternativa a quella standard e di non trovarne. Spero perciò di aver dato delle soluzioni valide per la maggior parte delle situazioni in cui potremmo venere a trovarci. Ma il discorso sulle selezioni non si esaurisce qui. Prossimamente a completamento cercheremo di illustrare altre nuove situazioni e soluzioni.

 

Buon lavoro