Accedi per seguire   
Seguaci 0
Alexsandra

Vba : I Cicli

1 messaggio in questa discussione

VBA : I Cicli

Ora che sappiamo come scegliere diverse azioni basandosi su delle condizioni predeterminate, siamo pronti a vedere come ripetere delle azioni un numero predeterminato di volte se si verifica, o non si verifica una particolare condizione nella nostra procedura. Uno degli svantaggi delle macro è la loro incapacità di ripetere le azioni a meno che le azioni desiderate non vengano registrate ripetutamente, VBA fornisce diverse strutture potenti e versatili per permetterci di ripetere facilmente le azioni e per controllare il modo in cui VBA effettua queste ripetizioni.

Le strutture del programma che ripetono l'esecuzione di una o più istruzioni sono chiamate Cicli, alcune strutture per i cicli sono costruite in modo da venire eseguite un numero impostato di volte, e vengono chiamate cicli ad interazione fissa, mentre altri tipi di strutture per i cicli vengono impostate un numero variabile di volte sulla base di alcune condizioni impostate, proprio perchè il numero di ripetizioni di queste strutture non è definito questi cicli vengono chiamati cicli ad interazione indefinita.

Sia nelle strutture ad interazione fissa che nelle strutture ad interazione indefinita, ci sono alcune espressioni che determinano quante volte il ciclo viene ripetuto, questa espressione viene chiamata determinante del ciclo, questa espressione in un ciclo ad interazione fissa è quasi sempre una espressione numerica, mentre per i cicli a interazione indefinita la determinante del ciclo è solitamente un'espressione logica che descrive la condizione sotto la quale il ciclo può continuare o interrompere la sua esecuzione, praticamente vengono usate delle espressioni logiche per la determinante dei cicli allo stesso modo in cui sono state usate per prendere delle decisioni in VBA che abbiamo visto nella lezione precedente.

Ci sarebbero altri aspetti da spiegare su quanto esposto, ma li ritengo puramente teorici, pertanto possiamo andare avanti con l'esposizione delle parole chiave usate e con qualche esempio, nel proseguo della lezione ritorneremo su questo argomento di costruzione dei cicli e risulterà più facile capirne la logica di operare dopo averne visto qualche esempio.

Ciclo For Next

La più semplice struttura per i cicli è quella ad interazione fissa, VBA ne fornisce due diverse tipologie che vengono espresse così For ...Next e For ...Each ... Next entrambi i cicli vengono chiamati ciclo For perchè vengono eseguiti per uno specifico numero di volte. Il ciclo For ... Next ha la seguente sintassi

For contatore = inizio To fine

istruzioni

Next contatore

contatore viene rappresentato da una qualsiasi variabile numerica, inizio è anch'esso rappresentato da una variabile numerica e specifica il valore iniziale per la variabile contatore, fine è una espressione numerica che rappresenta il valore finale per la variabile contatore. Per default VBA incrementa la variabile contatore di 1 unità ogni volta che esegue le istruzioni di un ciclo, mentre la parola chiave Next indica a VBA che è stata raggiunta la fine del ciclo, inoltre la variabile contatore deve essere la stessa che abbiamo messo appena dopo l'enunciato For. Possiamo però anche specificare un valore diverso per l'incremento del contatore includendo la parola chiave Step [opzionale], in questo caso dobbiamo specificare l'incremento della variabile contatore, e la sintassi diventa così:

For contatore = inizio To fine Step passo

istruzioni

Next contatore

In questo caso l'espressione passo viene rappresentata da una espressione numerica e indica la quantità per incrementare la variabile contatore, vediamo qualche esempio

Sub for_semplice()
For I = 1 To 10
MsgBox (I)
Next I
End Sub

L'esecuzione di questo codice ci porta a video la finestra di messaggio (MsgBox) per 10 volte con il valore della variabile I (contatore) e ci appare così

%25235old_01.png Fig. 1

Se invece vogliamo usare la parola chiave Step e far apparire solo le espressioni dispari possiamo modificare il listato in questo modo

Sub for_step()
For I = 1 To 10 Step 2
MsgBox (I)
Next I
End Sub

Vedremmo comparire il messaggio di avviso con i soli valori dispari della variabile

%25235old_02.png Fig. 2

Cosa abbiamo fatto con Step, abbiamo modificato l'incremento della variabile da 1 unità (di default) a 2 unità, in pratica alla prima esecuzione del ciclo I vale 1 ma quando incontra la parola chiave Step viene incrementata di 2. Al primo ciclo viene stampato il valore 1, questo perchè I quando incontra la parola chiave Step vale ancora 1, per cambiare valore deve arrivare alla parola chiave Next (che abbiamo detto essere quella che avvisa di essere arrivati alla fine del ciclo e che incrementa la variabile).

In ultima analisi l'enunciato For viene interpretato così : For I [Per I] = 1 To 10 [che và da 1 a 10] Step 2 [incrementa di 2], Esegui le istruzioni , Next I [incrementa il valore di I], Il ciclo For ..Next ha la flessibilità di poter incrementare e decrementare la variabile, possiamo modificare il listato da For I = 1 To 10 Step 2 a For I = 100 To 1 Step -2 pertanto le possibilità di impiego sono abbastanza vaste, possiamo eseguire somme, incrementare e decrementare il valore delle variabili, utilizzare la ciclicità per ogni bisogno che richieda il nostro programma fermo restando i principi di impiego esposti all'inizio. Esiste anche un'altra forma di ciclo ed è il ciclo For Each ..Next adesso è prematuro affrontare l'argomento, più avanti quando avremmo visto le matrici ed altri elementi ritorneremo sull'argomento comunque si esprime in questa forma

For Each elemento In gruppo

Istruzioni

Next [elemento]

molto brevemente possiamo descrivere così l'enunciato: elemento è una variabile usata per interare il ciclo (allo stesso modo che abbiamo visto sopra), gruppo è una collezione di oggetti o un vettore (matrice), questa tipo di ciclo ha meno opzioni del ciclo For Next, l'incremento del contatore non è rilevante in questo ciclo, perchè viene sempre eseguito tante volte quanti sono gli elementi presenti nel gruppo specificato, per il momento tralasciamolo e vediamo un altro metodo molto più versatile : il ciclo Do Loop

Ciclo Do Loop

Abbiamo parlato all'inizio di due tipi di cicli, quelli ad interazione fissa e quelli ad interazione indefinita, il ciclo Do Loop appartiene ai cicli ad interazione indefinita, VBA ci fornisce questa istruzione estremamente potente per costruire strutture cicliche indefinite nelle nostre funzioni o procedure. Essenzialmente è costituito da una singola istruzione: Do. Questa istruzione ha molte opzioni ed è talmente flessibile che ci fornisce quattro diverse possibilità per costruire dei cicli raggruppati in due diverse categorie di base, che sono i cicli controllati da un contatore e i cicli controllati da eventi, quale è la differenza?

In un ciclo controllato da un contatore, le istruzioni del corpo del ciclo vengono eseguite finchè il valore è inferiore o superiore al limite specificato, in sostanza non varia molto dal ciclo For ..Next, eccetto che il programmatore è direttamente responsabile per l'inizializzazione della variabile contatore e per l'incrementazione o decrementazione del contatore. Potremmo usare il ciclo Do se il passo del contatore non è regolare, o se non c'è modo di determinare il limite finale se non dopo che il ciclo ha iniziato la sua esecuzione. Per esempio se vogliamo spostarci attraverso 15 righe di un foglio, alcune volte avanzando di una sola riga e altre volte avanzando di due righe, poichè il numero di righe da avanzare (cioè il passo del contatore) cambia, non possiamo usare il ciclo For ..Next ma dobbiamo usare il ciclo Do

Per i cicli controllati da eventi, le istruzioni vengono eseguite quando la determinante del ciclo diventa vera o falsa sulla base di alcuni eventi che si verificano all'interno del corpo del ciclo. Per esempio potremmo scrivere un ciclo che viene eseguito indefinitamente fino a quando l'utente non inserisce un particolare valore in una finestra di dialogo input, e l'inserimento di questo particolare valore è l'evento che termina il ciclo, oppure possiamo eseguire delle operazioni sulle celle di un foglio fino a quando non si raggiunge la cella vuota di una colonna, anche in questo caso il raggiungimento della cella vuota è l'evento che termina il ciclo. Per ora abbiamo chiarito le due categorie di cicli, abbiamo capito che esistono cicli controllati da un contatore e cicli controllati da eventi, vediamo ora la sintassi

Do

istruzioni

Loop Until condizione

E qualche esempio.

Sub ciclo1()
Dim a As Integer
[color=darkred]Do[/color]
a = a + 1
MsgBox (a)
[color=darkred]Loop Until a = 10[/color]
End Sub

Questo è un ciclo controllato da un contatore, noterete che c'è poca differenza dal ciclo For ..Next , infatti otteniamo lo stesso effetto, cioè portiamo a video un messaggio col valore della variabile finchè non arriva a 10, ma abbiamo visto poco sopra che abbiamo quattro diverse possibilità di costruire cicli divisi in due categorie, ora le categorie le abbiamo viste ( cicli controllati da un contatore e i cicli controllati da eventi) vediamo ora i quattro modi di costruire un ciclo, il listato sopra esposto è un metodo, vediamo ora gli altri e dopo li commentiamo assieme

Sub ciclo2()
Dim a As Integer
[color=darkred]Do Until a = 10 [/color]
a = a + 1
MsgBox (a)
[color=darkred]Loop [/color]
End Sub

Sub ciclo3()
Dim a As Integer
[color=darkred]Do [/color]
a = a + 1
MsgBox (a)
[color=darkred]Loop While a <> 10[/color]
End Sub

Sub ciclo4()
Dim a As Integer
[color=darkred]Do While a <> 10[/color]
a = a + 1
MsgBox (a)
[color=darkred]Loop[/color]
End Sub

Come potete vedere la differenza sta nell'enunciato in rosso, il risultato non cambia ma le parole chiave e la loro collocazione si, vediamo come viene interpretato l'enunciato : Do Until a = 10 [Ripeti finchè a = 10], oppure Do While a <> 10 [Ripeti finchè a è diverso da 10], in questi 2 casi la differenza fondamentale è che viene verificata la condizione determinante prima che venga eseguito il ciclo, infatti se a fosse = a 20 il ciclo non verrebbe eseguito, gli altri 2 metodi

Do ......Loop While a <> 10 e Do ...... Loop Until a = 10 vengono interpretati come spiegato sopra, ma la determinate del ciclo viene verificata alla fine del ciclo.

In pratica la forma Do Loop While e Do Loop Until prima vengono eseguite le istruzioni presenti nel ciclo e poi quando raggiunge la parola chiave Loop viene verificata la condizione (vedi sintassi) se condizione è False (nel caso si usi Until VBA ritorna all'inizio del ciclo ed esegue nuovamente le istruzioni del ciclo, se invece usiamo la forma While la condizione da verificare deve essere True, mentre nelle altre 2 forme espresse Do Until ...Loop e Do While ...Loop la condizione invece viene verificata subito. Vediamo un esempio che semplifica e chiarifica quanto esposto. Supponiamo di far comparire a video un Inputbox per chiedere informazioni all'utente, e poi verificare se i dati immessi siano validi, in questo caso inseriamo nel nostro ciclo dobbiamo eseguire le istruzioni (far comparire il messaggio di Input) e all'inserimento dei dati da parte dell'utente verifichiamo la condizione, il listato si presenta così

Sub esempio1()
Dim pass As String
Do
pass = InputBox(prompt:="Inserisci password di accesso per Proseguire: ", Title:="Controllo accessi")
Loop Until pass = "Alex"
MsgBox "Password esatta : Accesso consentito", vbInformation + vbYes, "Verifica Password"
End Sub

Se proviamo questo codice vedremmo che il ciclo continua a ripetere le istruzioni finchè non viene digitata la password esatta, però se vogliamo uscire perchè non ricordiamo la password?, anche premendo sul tasto "Annulla" dell'Inputbox le istruzioni continuano ad essere ripetute lo stesso, allora è sempre meglio porre una condizione per evitare di proseguire, ma al tempo stesso controllare che l'esecuzione del ciclo avvenga correttamente, in pratica mettiamo l'utente in grado di uscire da un ciclo senza però che eviti di inserire la password richiesta. Per ovviare a questo modifichiamo il listato in questo modo.

Sub esempio2()
Dim pass As String
Do
pass = InputBox(prompt:="Inserisci password di accesso per Proseguire: ", Title:="Controllo accessi")
[color=darkred]If pass <> "Alex" Then Exit Sub[/color]
Loop Until pass = "Alex"
MsgBox "Password esatta: Accesso consentito", vbInformation + vbYes, "Verifica Password"
End Sub

Inserendo la riga di codice in rosso, abbiamo posto una condizione, cioè Se pass è diverso da "Alex" esci dalla sub, attenzione, che esci dalla sub non vuol dire proseguire, ma semplicemente abbandoniamo questa routine che in ogni caso per poter proseguire dobbiamo inserire la password giusta, questa semplice metodica viene chiamata Uscita forzata dal ciclo. Anche con l'altro metodo cioè Do Until ...Loop e Do While ...Loop il risultato non cambia, pertanto non c'è una regola ben precisa su quale forma sia meglio usare, possiamo dire che a disposizione VBA ci mette queste forme, sta a noi usare quella che ci pare più logica o intuitiva per esprimere quello che vogliamo esegua il nostro codice. Se vi ricordate nella lezione precedente avevamo parlato della nidificazione del ciclo IF, anche nei cicli For ... Next e Do ...Loop è possibile eseguirla, visto che l'argomento lo abbiamo già toccato in questo contesto facciamo subito un esempio e dopo lo commenteremo assieme

Sub scrivi_col_for()
For riga = 12 To 35
For colonna = 7 To 18
Cells(riga, colonna).Value = riga
Next colonna
Next riga
End Sub

Cosa abbiamo fatto? se provate ad eseguire la macro vedrete che nell'area di lavoro abbiamo riempito tutte le celle con il numero della riga corrispondente. Vediamo il codice For riga = 12 To 35 il contatore del ciclo è rappresentato dalla variabile riga e gli diciamo [Per riga che và da 12 a 35] e subito dopo invece di far eseguire le istruzioni gli mettiamo un'altro enunciato For colonna = 7 To 18 in questo caso il contatore del ciclo è rappresentato dalla variabile colonna e lo interpretiamo così [Per colonna che và da 7 a 18], a questo punto abbiamo posto due condizioni una sotto l'altra e subito dopo abbiamo posto le istruzioni Cells(riga, colonna).Value = riga in questo enunciato la parola chiave Cells (che vedremmo nella prossima lezione) sta ad indicare una determinata cella del nostro foglio localizzata dai valori delle variabili riga e colonna, l'altra parola chiave Value indica il valore da inserire nelle coordinate rappresentate, tale valore lo abbiamo identificato con riga.

Seguendo l'esecuzione del ciclo, prima viene eseguito il ciclo interno, e cominciamo dalla cella che si trova all'intersezione tra la colonna n° 7 e la riga n° 12 che sul nostro foglio è rappresentata da G12, al cui interno scriviamo il valore di riga (per cui 12), poi incontriamo la parola chiave Next colonna, a questo punto però non abbiamo ancora raggiunto la determinante del ciclo (rappresentato dal valore [18]) e VBA incrementa il contatore di 1 e ripete le istruzioni, così facendo andiamo a scorrere tutte le colonne e scriviamo al loro interno il valore della variabile riga.

Una volta raggiunta la determinante del ciclo usciamo dal ciclo interno ma troviamo la parola chiave Next riga, per cui il contatore del ciclo esterno viene incrementato, passiamo alla riga successiva (la 13) e ripetiamo il ciclo interno come abbiamo descritto sopra. Il nostro listato ha fine quando viene raggiunta la determinate del ciclo esterno e a questo punto troveremo la nostra area di lavoro riempita con il valore della variabile riga estesa sulle colonne di ciascuna riga. Ora che abbiamo riempito l'area con il valore della riga tramite un ciclo For Next nidificato potremmo vedere un listato Do Loop per fare il contrario, cioè riempire l'area col valore della colonna.

Sub scrivi_col_dolop()
riga = 12: colonna = 7
Do Until riga = 35
Do While colonna <> 19
Cells(riga, colonna).Value = colonna
colonna = colonna + 1
Loop
riga = riga + 1: colonna = 7
Loop
End Sub

Notiamo subito una netta differenza tra i due cicli, infatti abbiamo dovuto dichiarare i valori iniziali delle variabili riga e colonna prima dell'inizio del ciclo (riga = 12: colonna = 7) in questa tipologia ciclica il VBA non riesce a determinare da dove deve iniziare, in quanto la sintassi di espressione è diversa, una volta indicati i valori di partenza troviamo la prima parola chiave Do Until riga = 35 [ripeti finchè il valore di riga non è uguale a 35] e subito dopo abbiamo posto l'altra condizione che costituisce il ciclo interno Do While colonna <> 19 facciamo attenzione a questo enunciato, abbiamo usato la parola chiave While e il codice viene interpretato così[ripeti mentre colonna è diversa da 19] ma perchè 19 dato che l'ultima colonna che dobbiamo riempire è la n° [18]?.

Lo comprendiamo subito andando avanti con l'analisi del ciclo, possiamo saltare la spiegazione delle istruzioni Cells(riga, colonna).Value = colonna in quanto la loro funzione è uguale a quanto spiegato sopra per il ciclo For con la sola differenza che riempiamo le celle col valore della variabile colonna, mentre la soluzione al quesito posto sta nella riga sotto colonna = colonna + 1 questo è il nostro contatore, il metodo che usa Do ... Loop per incrementarlo e continuare nella sua esecuzione, infatti alla prima esecuzione colonna vale 7 e viene incrementata sempre di 1, poi quando trova la parola chiave Loop ritorna all'altra parola chiave Do (dove ha iniziato il ciclo) ed esegue ancora le istruzioni, ma nella determinante del ciclo abbiamo messo 19 (un valore in più di [18]) semplicemente perchè quando incrementiamo il valore della variabile colonna con la dicitura colonna = colonna + 1 alla parola chiave Loop la determinate del ciclo sarebbe soddisfatta se mettessimo [18] e di conseguenza la nostra area verrebbe riempita fino alla colonna 17

Provate a modificare il valore nell'esempio allegato e comprenderete come agisce il ciclo, inoltre quando si lavora con i cicli e per un motivo qualsiasi ci viene rimandato un errore oppure non viene eseguito quello che volevamo, possiamo usare un piccolo espediente per vedere come agisce il ciclo e quale valore attribuisce alle variabili usate, infatti basta usare la parola chiave Msgbox e possiamo vedere a video il valore della variabile e correggere l'errore. Ecco un esempio di utilizzo

Sub scrivi_col_dolop()
riga = 12: colonna = 7
[color=darkred]MsgBox riga[/color]
Do Until riga = 35
Do While colonna <> 19
[color=darkred]MsgBox colonna[/color]
Cells(riga, colonna).Value = colonna
colonna = colonna + 1
Loop
riga = riga + 1: colonna = 7
Loop
End Sub

Ovviamente il codice in rosso è solo un aiuto molto semplice per trovare un errore, esistono altri metodi da poter utilizzare direttamente nell'editor di VBA, ma questo fa comprendere meglio come "gira" il nostro programma.

Modificato da Alexsandra

Condividi questo messaggio


Link di questo messaggio
Condividi su altri siti
Accedi per seguire   
Seguaci 0