Cancellare righe se vuote

Ultima modifica: 30-05-2016

Sembra banale, ma in realtà non lo è. Infatti dobbiamo superare alcuni ostacoli.

Ma prima di addentrarci in questa problematica presentiamo un ipotetico aspetto del foglio ed una altrettanto ipotetica routine VBA.

A B
1 Visual Basic 6.0 Visual Basic 2005 Equivalent
2
3 vbKeyLButton (1) LButton
4
5 vbKeyRButton (2) RButton
6
7 vbKeyCancel (3) Cancel
8
9 vbKeyMButton (4) MButton
10
11
12
13
14
15
16
17 Visual Basic 6.0 Visual Basic 2005 Equivalent
18
19 VbKeyA (65) A
20
21 VbKeyB (66) B
22
23 VbKeyC (67) C
24
25 VbKeyD (68) D
26
27 VbKeyE (69) E

Questa tabella non ha assolutamente i dati disposti in maniera ordinata. Dobbiamo cancellare le righe colorate in giallo.

Vediamo perciò come si comporta una normale routine con questa tabella.

Per questa routine c'è da dire solo che, data la natura della tabella, non si può usare la proprietà CurrentRegion, perchè si fermerebbe alla prima riga. Per questo motivo va usato la proprietà UsedRange riferendosi all'oggetto ActiveSheet.

Per altre considerazioni la routine è sufficientemente commentata.

Sub Elimina_righe_prova()
Dim Intervallo As Range
Dim FL As Boolean
Dim Righe, R, Colonne, C
Sheets("Foglio2").Select
Set Intervallo = ActiveSheet.UsedRange
Righe = Intervallo.Rows.Count
Colonne = Intervallo.Columns.Count
For R = 1 To Righe
' pongo qui un FLAG per controllare che tutte le celle della riga siano vuote
' se le celle sono vuote il FLAG rimarrà con valore False
FL = False
For C = 1 To Colonne
If Intervallo(R, C) <> "" Then
FL = True
End If
Next
' se il FLAG rimane False la riga viene cancellata
If FL = False Then
Intervallo(R, 1).EntireRow.Delete
End If
Next
End Sub

Tuttavia la tabella, dopo l'esecuzione di questa routine avrà questo aspetto:

elimina righe

Come si vede dall'immagine, non sono state cancellate tutte le righe.

Questo comportamento è facilmente spiegabile.

Data la tabella iniziale verrà istruito un ciclo che spazzoli la tabella dalla riga 1 alla riga 27

For R = 1 To Righe ' Righe è pari a 27

Al primo giro del ciclo ci troviamo alla riga 1 e vengono rilevati dei valori nelle corrispondenti celle e non succede nulla

Al secondo giro ci troviamo alla riga 2 e vengono trovate le celle vuote, quindi la riga viene cancellata

Cancellando la riga n° 2 il suo posto sarà preso dalla riga n° 3 che di conseguenza dinenta la 2

Il ciclo intanto continua la sua corsa e passa al terzo giro.

Al terzo giro ci si sposta alla riga 3. Ma a causa della cancellazione della riga 2 avvenuta nel passaggio precedente, la ex riga 3 che è ora salita alla seconda non viene esaminata ma verrà esaminata, ma verrà ora esaminata la ex riga 4 che, sempre per effetto della avvenuta cancellazione, è ora passata alla riga 3.

E questo si ripeterà fino alla fine del ciclo.

Per questo motivo il risultato finale sarà quello mostrato nella figura qui sopra con la tabella che presenta ancora le righe vuote.

Il trucco per far funzionare nel giusto modo la routine consiste nell'impostare il ciclo che esplora le righe al contrario, ossia, anzichè usare For R = 1 To Righe si userà For R = Righe To 1 Step -1.

In questo modo siamo sicuri che, nonostante le cancellazioni delle righe vuote, tutte saranno esaminate.

Sub elimina_righe_prova_2()
Dim Intervallo As Range
Dim Righe, R, Colonne, C, FL As Boolean
Sheets("Foglio2").Select
Set Intervallo = ActiveSheet.UsedRange
Righe = Intervallo.Rows.Count
Colonne = Intervallo.Columns.Count
For R = Righe To 1 Step -1 ' questo è il ciclo modificato
FL = False
For C = 1 To Colonne
If Intervallo(R, C) <> "" Then
FL = True
End If
Next
If FL = False Then
Intervallo(R, 1).EntireRow.Delete
End If
Next
End Sub

elimina righe vuote

Questo è il risultato che ci aspettavamo e questo lo abbiamo ottenuto grazie a questa piccola modifica al codice.

A questo punto avremmo finito, ma ... la routine può essere migliorata in leggibilità e prestazioni.

Infatti all'interno del ciclo creato per spazzolare le righe (For R = Righe To 1 Step -1) abbiamo un secondo ciclo per controllare le celle che sono sulla riga in esame (For C = 1 To Colonne).

In un piccolo elenco questo potrebbe anche andar bene, ma in un elenco dalle demensioni esageratamente grande, potrebbe causare una perdita di tempo.

Per far questo possiamo ricorrere alla proprietà EnableEvents e alla funzione CountA che è l'equivalente della funzione CONTA.VALORI di Excel.

Se la proprietà EnableEvents è impostata a False sono disattivati gli eventi facendo risparmiare tempo nell'elaborazione. Alla fine delle operazioni è però necessario riportare a True la proprietà EnableEvents per poter continuare a lavorare

La funzione CountA (CONTA.VALORI) conta il numero di celle contenenti dati in un intervallo.

Da queste considerazioni nasce la routine finale, molto più breve e veloce delle precedenti, per eliminare le righe vuote.

Sub elimina_righe()
Dim Intervallo As Range
Dim Righe, R
Set Intervallo = ActiveSheet.UsedRange
Righe = Intervallo.Rows.Count
Application.EnableEvents = False
For R = Righe To 1 Step -1
If WorksheetFunction.CountA(Rows(R)) = 0 Then
Intervallo(R, 1).EntireRow.Delete
End If
Next
Application.EnableEvents = True
End Sub

 

 

 

 

 

Bene. Anche questa volta ... Buon lavoro.