Triplo Ciclo For .. Next
I cicli
For
... Next sono legati al concetto di insiemi.
Questi insiemi possono essere
oggetti di vario tipo : controlli, barre di
comando, celle del foglio di lavoro, fogli di lavoro, ma anche matrici,
valori, ecc. ecc. Quando si deve eseguire una verifica o una ricerca su
ogni componente di un insieme, come per esempio
cercare un valore in una serie di celle (Range), allora e utile ricorrere
proprio alla struttura di un ciclo For ... Next.
Sono due tra le strutture cicliche di controllo (ne esistono altre) :
Per ogni cella (C)<elemento>
nell'<insieme> Range("A1:A20"). In questo
caso viene assegnato un indice implicito
rappresentato dal numero di celle presenti nel Range A1:A20, indice
che identifica numericamente le 20 celle. L'istruzione
Next, posta alla fine del ciclo, non fa
altro che passare all'indice successivo, ripetendo le istruzioni, fino
a che non ha raggiunto l'indice 20, dopodichè esce dal ciclo.
For Each C in Range("A1:A20")
...istruzioni
Next |
-
oppure un ciclo,
posto un valore iniziale ed un valore finale, che si baserà su un
contatore (indice non implicito) che si
incrementerà di una unità ad ogni Next fino a
raggiungere il valore finale, usando la forma For
I <I è il contatore>= 1 To
20 ... Next <passa
al valore successivo rappresentato da I>. Un esempio
Questa forma consente di "spazzolare" un
intervallo di <elementi> di un <insieme>,
dichiarando noi l'indice per quanti <elementi>
(1 To 20 ) dovrà essere ripetuto il ciclo (20 volte) ed identificando
l'<elemento> con il
contatore (o indice). Rifacendoci all'esempio sopra, dove si
scorre la colonna A fino alla cella 20, identificate come <insieme>
dall'oggetto Range, in questo caso
useremo Cells come <elemento>
dell'oggetto Foglio (in questo caso l'<insieme>).
Visto che per identificare le celle del foglio di lavoro, usiamo due
indici, il primo è sempre l'indice di riga, il secondo è sempre
l'indice di colonna (es.: Cells(1, 3) = C1), useremo al posto
dell'indice di riga il numero rappresentato dal
contatore ( I ) per
scorrere tutte le righe fino alla 20.
For I = 1 To 20
Cells(I, 1) seguono
istruzioni
Next
I è una
variabile che può essere identificata con qualsiasi lettera o nome, N
oppure X o ancora Cont, o quel che vi pare, l'importante che poi
usiate quello che avrete scelto come contatore al posto dell'indice
riga, oppure assegnare il tipo di variabile con Dim, es.:
Dim Cont as Integer
For Cont = 1 To 20
Cells(Cont, 1) seguono
istruzioni
Next |
Fatte queste premesse, passo ad illustrare un esempio scaturito da una
richiesta, strettamente legato a cicli For.. Next, e lo propongo in due
varianti.
Vediamo il problema:
In una tabella, formata da 10 colonne e da 10 righe, si trovano dei numeri,
da 1 a 100. Si voleva che, cancellando uno qualsiasi dei numeri rimasti, i
numeri successivi a quello cancellato, scalassero di una cella, e si
ripristinasse la progressione dei i numeri rimasti, lasciando quindi vuota
l'ultima cella. Vediamo le tabelle: nella prima è stato eliminato il valore
nella cella evidenziata in giallo; come si nota, manca il numero 64
Si vuole quindi
che a partire dal 65, si scali di una cella, ricreando la naturale
progressione, e questo sarà il risultato finale, in cui i numeri sono in
progressione ed è l'ultima cella a restare vuota.:
Vediamo come
procedere:
abbiamo
bisogno di un ciclo che controlli tutte le celle di una stessa riga della
tabella, e quindi lavori avanzando colonna dopo colonna.
abbiamo
bisogno di un secondo ciclo, che una volta completato il ciclo per le
colonne della prima riga, passi alla riga successiva dell'elenco per
ripetere il ciclo sulle colonne, e che questo ciclo scorra fino alla fine
tutte le righe.
Visto che stiamo
cercando se una cella sarà vuota, inseriremo un controllo
If .. Then. Se troveremo una cella vuota, e quì
ho scelto la soluzione più veloce, cancello l'intera tabella, assegno alla
prima cella (A1) il valore 1, e rigenero l'intera sequenza dei numeri
fermandomi a 99, con un terzo ciclo For.. Next,
dopodichè esco da tutti i cicli con Exit For
(ripetuto due volte perchè due sono i cicli "esterni"
inizializzati.). Se invece non verrà trovata nessuna cella vuota, il terzo
ciclo (interno) non si verifica e si uscirà
dalla routine quando tutte le celle sono state controllate. Questa la
routine:
Sub Riordina()
'istruzione necessaria per
non vedere lo scorrere dei cicli
Application.ScreenUpdating = False
'assegnazione alla
variabile "zona" del range su cui operare
Set zona = Range("A1:J10")
'inizio del primo ciclo
esterno, che inizializza l'indice riga (rwIndex); cioè a partire dalla
'riga 1 (e poi fino alla riga 10)
For rwIndex = 1 To 10
'inizia il secondo ciclo,
che nella riga ora selezionata (la 1) scorre tutte le colonne, 'dall'indice
colonna 1 fino alla 10 (colIndex)
For colIndex = 1 To 10
'con l'<insieme> Foglio1,
per l'<elemento> Cella (indice riga, indicecolonna)(questi indici
'rappresentati ora da rwIndex e da colIndex)
With Worksheets("Foglio1").Cells(rwIndex, colIndex)
'se la cella è vuota,
allora
If .Value = "" Then
'cancelliamo tutta l'area
assegnata a "zona"
zona.ClearContents
'assegnamo alla prima cella
dell'area "zona" (A1) il valore 1
zona.Cells(1) = 1
'inizio del terzo ciclo,
partendo dalla cella 2 (la cella uno è già stata inizializzata con 1)
e 'fino al valore rappresentato dal numero di celle (zona.Cells.Count=
100) - 1 perchè 'dovrà mancare una cella, l'ultima
For I = 2 To
zona.Cells.Count - 1
'I ora è un contatore, e determina su
quale cella della "zona" si interviene, sommando al 'valore della
cella precedente (la I -1) la cella attuale, una unità (1)
zona.Cells(I) = zona.Cells(I - 1) + 1
Next I
'finito con Next I il terzo
ciclo che ha poste nelle celle la progressione dei numeri fino a 99,
si esce dai due cicli precedenti aperti, e si salta a End Sub
Exit For: Exit For
End If
End With
Next colIndex
Next rwIndex
End Sub |
Ho preparato anche
la routine per riempire tutta la tabella con numeri da 1 a 100,
ripristinando la tabella completa: Questa la routine, inutili mi pare, i
commenti:
Sub Riempi()
Application.ScreenUpdating = False
Set zona = Range("A1:J10")
zona.ClearContents
For I = 2 To zona.Cells.Count
zona.Cells(1) = 1
zona.Cells(I) = zona.Cells(I - 1) + 1
Next
End Sub |
Questa invece la
seconda variante, promessa all'inizio. Presupponendo che si voglia il
comportamento relativo al problema (quello di scalare celle e ripristino
della progressione) MA il tutto su una tabella dove il numero di celle vuote
sia superiore ad 1, e dove quindi è necessario "contare" quante celle vuote
si trovano per determinare quante celle vuote lasciare alla fine.
Come procedere:
dovremo
usare i due cicli For..Next per scorrere tutte le righe e tutte le
colonne, per cercare quante celle vuote sono presenti.
ci
affideremo ad un contatore (cont) che
memorizzi quante celle vuote sono presenti con
If .Value = "" Then
cont = cont + 1
End If
Alla fine
dei due cicli di ricerca, controlleremo se il valore del contatore è
maggiore di 0 (zero), in caso sia maggiore, iniziamo il ciclo di
azzeramento tabella, riassegnazione alla prima cella del valore 1, ed
incremento delle altre celle di una unità in progressione, ottenendo dove
fermarci dal valore ottenuto dal conteggio di quante celle ci sono nella
tabella, meno il valore rappresentato dal contatore.
Sub Riordina()
Application.ScreenUpdating = False
Set zona = Range("A1:J10")
For rwIndex = 1 To 10
For colIndex = 1 To 10
With Worksheets("Foglio1").Cells(rwIndex, colIndex)
If .Value = "" Then
cont = cont + 1
End If
End With
Next colIndex
Next rwIndex
If cont > 0 Then
zona.ClearContents
For I = 2 To zona.Cells.Count - cont
zona.Cells(1) = 1
zona.Cells(I) = zona.Cells(I - 1) + 1
Next
End If
End Sub
|
Buon lavoro.
prelevato sul sito http://ennius.interfree.it |