l capitolo 7 Controllo di Visual Basic
Transcript
l capitolo 7 Controllo di Visual Basic
7 Controllo di Visual Basic Al termine del capitolo, si sarà in grado di: ✔ ✔ ✔ ✔ ✔ Utilizzare istruzioni condizionali. Creare cicli utilizzando tre diversi blocchi. Recuperare i nomi dei file di una cartella. Creare punti di interruzione per eseguire il debug di cicli lunghi. Visualizzare lo stato di avanzamento mentre una macro esegue un ciclo. Il primo tunnel sottomarino mai costruito è quello sotto il Tamigi, i cui lavoro hanno avuto inizio nel 1825. A quel tempo, venne considerato un disastro finanziario, anche se viene utilizzato ancora oggi come tratta del sistema metropolitano londinese. Il genio che ideò il progetto era un uomo di nome Marc Brunel. Vent’anni prima di inaugurarlo, Brunel si era già fatto conoscere per aver inventato per conto dell’industria navale britannica un modo economico per produrre i paranchi differenziali necessari per costruire le navi. La tecnica di Brunel, definita successivamente come “catena di montaggio”, venne trasformata da Henry Ford in un metodo industriale, che gli consentì di produrre l’automobile Modello T per il mercato americano al costo di soli $3.500 odierni. Le ripetizioni possono avere effetti molto negativi sull’efficienza. I programmi informatici, comprese la macro scritte dall’utente, diventano più efficaci se viene introdotto un effetto moltiplicatore. Nel presente capitolo, si apprenderà come aggiungere dei cicli alle macro e, per renderli più efficienti, si imparerà a creare espressioni condizionali che consentano alla macro di prendere decisioni. Importante Prima di completare la lettura del presente capitolo, è necessario installare i file di esercitazione del CD allegato nei relativi percorsi predefiniti. Per maggiori informazioni, consultare la sezione “Utilizzo del CD allegato” a pagina xvii. 209 210 Capitolo 7 Controllo di Visual Basic UTILIZZARE la cartella di lavoro Flow.xlsx, il file di testo Flow.txtt e la cartella di lavoro Orders.xlsx. I file di esercitazione si trovano nella cartella Documenti\MSP\ExcelVBA07SBS. Il file di testo Flow contiene alcune macro iniziali da copiare nella propria cartella di lavoro e da modificare durante la lettura del capitolo. Le macro iniziali sono archiviate in un file di testo semplice, per garantire l’assenza di codice dannoso, prima di inserire il codice in un percorso attendibile. ASSICURARSI DI salvare la cartella di lavoro Flow.xlsxx come cartella di lavoro Chapter07.xlsm con attivazione macro nel percorso attendibile creato nel capitolo 1. APRIRE il file di testo Flow. w Quindi, aprire la cartella di lavoro Chapter07, 7 fare clic con il pulsante destro su una delle schede del foglio e selezionare Visualizza codice per aprire Microsoft Visual Basic Editor. Qui, nel menu Inserisci, fare clic su Modulo per creare un nuovo modulo per le macro, quindi salvare il file. Adattare le finestre di Microsoft Office Excel 2007 e Visual Basic Editor in modo che risultino affiancate. Utilizzo di espressioni condizionali Le macro registrate non sono molto accorte: sono in grado di ripetere ciò che è stato definito in fase di registrazione, ma se le circostanze sono diverse non sono capaci di modificare il loro comportamento e di prendere decisioni. L’unico modo per rendere le macro più “intelligenti” è quello di aggiungere una funzionalità che consenta loro di prendere decisioni autonome. Decisioni delle macro Il file di testo Flow contiene una macro chiamata MoveRight, uguale alla seguente: Sub MoveRight() ActiveCell.Offset(0, 1).Select End Sub Essa seleziona la cella a destra di quella attiva e funziona quasi sempre in modo corretto. 1. Copiare la macro MoveRight dal file di testo e incollarla in una modulo VBA nella cartella di lavoro Chapter07. 2. Con la cella A1 selezionata nella cartella, attivare Visual Basic Editor, fare clic sulla macro MoveRight e premere F5. Essa seleziona la cella B1 della cartella di lavoro. 3. In Excel, premere Ctrl+freccia DESTRA per selezionare la cella XFD1, l’ultima a destra nella prima riga. 4. In Visual Basic Editor, premere F5. Visual Basic visualizza un errore. Utilizzo di espressioni condizionali 211 Non è possibile selezionare la cella a destra della cella chi si trova all’estrema destra. Se la macro non riesce a spostarsi a destra, non può fare altro che visualizzare un messaggio di errore. 5. Nella finestra di messaggio, fare clic sul pulsante Debug per passare alla macro, quindi selezionare Ripristina per arrestarla. 6. Inserire l’istruzione if ActiveCell.Column < Columns.Count Then dopo l’istruzione Sub. Inserire un rientro per l’istruzione che modifica la selezione, quindi aggiungere l’istruzione End If prima della fine della macro. Accertarsi di fare rientrare tutte le istruzioni, in modo tale che sia chiaro quale istruzione dipende dall’istruzione if. Visual Basic non richiede un tipo di rientro specifico, tuttavia questa operazione è fondamentale per consentire all’utente che ha creato la macro (o chi lo seguirà) di interpretare la macro esattamente come Visual Basic. La macro rivista sarà simile alla seguente: Sub MoveRight() If ActiveCell.Column < Columns.Count Then ActiveCell.Offset(0, 1).Select End If End Sub Un’istruzione if (un’istruzione che inizia con la parola If) è sempre abbinata a un’istruzione End If. Il gruppo di istruzioni dalla If alla End If è definito blocco If. Visual Basic controlla l’espressione appena dopo la parola If e determina se valutarla True o False. L’espressione true o false è definita condizionale. In un semplice blocco If come quello illustrato nell’esempio, se il valore dell’espressione è Ture, Visual Basic esegue tutte le istruzioni comprese tra la If e la End If. Se è False, Visual Basic passa direttamente all’istruzione End If. È necessario inserire sempre la parola Then al termine dell’istruzione If. In questo caso, l’espressione condizionale verifica se il numero della colonna corrente è inferiore rispetto al numero totale di colonne del foglio di lavoro. È possibile anche fare un confronto con una costante, ad esempio 16384 o 2^14, tuttavia utilizzare le proprietà dell’oggetto consente alla macro di funzionare sia con versioni di Excel precedenti (con 256 colonne), che con Excel 2007 (16384 colonne). 212 Capitolo 7 7. Controllo di Visual Basic Tornare a Visual Basic, selezionare la cella XFA1, attivare Visual Basic e premere F5 per quattro o cinque volte. La macro sposta la cella attiva verso destra finché non raggiunge l’ultima cella. Dopodiché, non esegue alcuna altra operazione, proprio come indicato nelle istruzioni fornite. Il registratore macro non creerà mai un blocco If. Questa decisione può essere presa solo da Visual Basic, ma è necessario aggiungere un blocco If. Fortunamente, questa operazione è semplice. 1. Creare una domanda che richieda come risposta “sì” o “no”. Nell’esempio in questione, la domanda è “Il numero della colonna della cella attiva è inferiore a 256?” e può essere tramutata in espressione condizionale true-false di un’istruzione if. 2. Inserire la parola If prima dell’espressione condizione e la parola Then dopo la stessa. 3. Indicare quante istruzioni si desidera eseguire se l’espressione condizionale restituisce un valore True. 4. Inserire un’istruzione End If dopo l’ultima istruzione che deve essere controllata dal blocco If. Utilizzando i blocchi If, è possibile rendere le macro più intelligenti. Decisioni doppie delle macro A volte, ad esempio quando si intende evitare un errore, si desidera che la macro venga eseguita sono se l’espressione condizionale è True. Altre volte, si desidera che si comporti in un determinato modo se l’espressione è True e in un altro se è False. Ad esempio, si supponga che la macro debba spostare la cella attiva verso destra, ma solo nelle prime cinque colonne del foglio di lavoro. Quando la cella attiva arriva alla quinta colonna, si desidera che si sposti sulla prima cella della riga successiva. In questo caso, la macro dovrà eseguire una determinata azione se la colonna della cella è inferiore alla quinta (spostare la cella verso destra) e un’altra se supera la quinta (spostarsi alla prima cella della riga successiva). Perché la macro scelga tra due opzioni, è necessario aggiungere una seconda parte del blocco If. 1. Passare a Visual Basic Editor e copiare la macro MoveRight. Modificare il nome della nuova copia con FiveColumnWrap. 2. Quindi, nella stessa modificare l’espressione Columns.Count su 5 nell’istruzione if. Utilizzo di espressioni condizionali 3. Aggiungere l’istruzione Else prima dell’istruzione End If e premere Invio. 4. Premere Tab e aggiungere l’istruzione Cells(ActiveCell.Row + 1, 1).Select dopo l’istruzione Else. 213 La macro rivista sarà uguale alla seguente: Sub MoveRight() If ActiveCell.Column < 5 Then ActiveCell.Offset(0, 1).Select Else Cells(ActiveCell.Row + 1, 1).Select End If End Sub L’istruzione Else indica semplicemente a Visual Basic quale/i istruzione/i eseguire se l’espressione condizionale è False. Suggerimento Molte altre istruzioni diverse selezionerebbero la prima cella della riga successiva. Di seguito, vengono riportate alcune alternative: Rows(ActiveCell.Row + 1).Cells(1).Select ActiveCell.EntireRow.Cells(2, 1).Select ActiveCell.Offset(1, 0).EntireRow.Cells(1).Select. Tutte hanno lo stesso punto di partenza (ActiveCell) e la stessa destinazione. Quando si scrivono le macro, spesso sono disponibili varie alternative. È sufficiente scegliere la più semplice da capire. 5. Premere F5 più volte per eseguire la macro. Si visualizzerà la selezione spostarsi verso destra e poi tornare alla colonna A, come fa un elaboratore di testo quando va a capo. Un blocco If può contenere una sola parte che esegue le istruzioni se l’espressione condizionale è True, oppure due o più parti, che eseguono una serie di istruzioni quando l’espressione condizionale è True e altre quando è False. Suggerimento Nella maggior parte dei casi If e Else sono sufficienti. Esiste anche un modo per utilizzare un blocco If al fine di creare più condizioni, ovvero inserendo un’istruzione ElseIf. Per maggiori informazioni sui blocchi If, evidenziare la parola If nella macro e premere F1. 214 Capitolo 7 Controllo di Visual Basic Inserimento di una domanda Nel capitolo 2, “Esecuzione di attività complesse mediante una macro”, è stata creata una macro che richiedeva di inserire una data. Per eseguire l’operazione, è stata utilizzata la funzione InputBox di Visual Basic. Tale funzione è molto adatta per porre una domanda, ma bisogna fare particolare attenzione a ciò che avviene quando si seleziona il pulsante Cancella. Il file di testo Flow contiene una macro chiamata TestInput che richiede la data. Il codice di questa macro dovrebbe essere già noto. Sub TestInput() Dim myDate As String myDate = InputBox("Enter Month in MMM-YYYY format") MsgBox "Continue the macro" End Sub La macro richiede una data. Poi, visualizza una semplice finestra di messaggio indicante che il resto della macro è in esecuzione. 1. Copiare la macro TestInput dal file di testo e incollarla in un modulo della cartella di lavoro Chapter07 di Visual Basic Editor. 2. Selezionare la macro TestInput. Premere F5 per eseguire la macro, digitare Nov2007 come data e fare clic su OK. Viene visualizzata la finestra di messaggio che indica il proseguimento della macro. 3. Fare clic su OK per chiuderla. 4. Premere F5 per eseguire nuovamente la macro, ma questa volta selezionare Annulla quando viene richiesto di inserire la data. Viene visualizzata ancora la finestra di messaggio anche se, normalmente, selezionando Annulla si dovrebbe interrompere l’operazione avviata. 5. Fare clic su OK per chiuderla. Utilizzo di espressioni condizionali 215 Serve un’espressione condizionale nella quale True significa che si desidera proseguire l’esecuzione della macro. Dato che fare clic su Annulla è come lasciare la casella vuota, una domanda appropriata è: “L’utente ha inserito qualcosa nella finestra?” In entrambi i casi, la funzione InputBox restituisce una stringa vuota (uguale alle virgolette di apertura e chiusura vuote). L’operatore <> (un segno di inferiore seguito da un segno di maggiore) significa “non uguale”, ovvero il contrario del segno uguale. 6. Prima dell’istruzione MsgBox, digitare l’istruzione If myDate <> “” Then, e prima dell’istruzione End Sub, inserire End If. Aggiungere un rientro nell’istruzione contenuta nel blocco If. La macro rivista sarà simile alla seguente: Sub TestInput() Dim myDate As String myDate = InputBox("Enter Month in MMM-YYYY format") If myDate <> "" Then MsgBox "Continue the macro" End If End Sub 7. Premere F5 e provarla per accertarsi che gestisca correttamente un valore di input. Inserire una data e fare clic su OK. La macro “continua”. 8. Fare clic su OK per chiudere la finestra di messaggio. 9. Quindi, eseguire nuovamente la macro, questa volta selezionando Annulla quando viene richiesta una data. La macro si interrompe automaticamente. Ogni qualvolta si consente all’utente di inserire un input in una macro, è necessario verificare se ha cancellato l’intera macro. Verifica di inserimento di una voce valida La ricerca di una stringa vuota verifica se l’utente ha selezionato il pulsante Annulla, ma non serve a determinare se il valore inserito è valido. Per eseguire questo controllo, è necessario aggiungere una seconda prova. 1. Eseguire di nuovo la macro TestInput, questa volta digitando nella casella di input la parola “ippopotamo”, e fare clic su OK. La macro continua come se fosse stata inserita una data. 216 Capitolo 7 2. Controllo di Visual Basic Fare clic su OK per chiudere la finestra di messaggio. Questo comportamento potrebbe provocare dei problemi. Quindi, è necessario controllare se la finestra è vuota ma anche cercare una data valida. Visual Basic dispone di una funzione IsDate che indica se Visual Basic è in grado di interpretare un valore come data. Tuttavia, questa verifica va eseguita solo se l’utente non ha selezionato Annulla, e richiede blocchi If nidificati. 3. Modificare la macro come segue: Sub TestInput() Dim myDate As String myDate = InputBox(“Enter Month in MMM-YYYY format”) If myDate <> “” Then If IsDate(myDate) Then MsgBox “Continue the macro” Else MsgBox “You didn’t enter a date” End If End If End Sub Accertarsi di fare rientrare ogni istruzione in modo tale che sia chiaro quale istruzione dipende da quale istruzione If o Else. 4. Eseguire la macro almeno tre volte. Provarla con una data valida, con una non valida e selezionando Annulla. In caso di voci valide o non valide, verranno visualizzati i messaggi appropriati, invece se viene selezionato Annulla oppure se la finestra viene lasciata vuota, non verrà visualizzato alcun messaggio. Suggerimento Visual Basic è in grado di interpretare come date molti formati diversi. Provarne alcuni, come 11/07, per verificare quali vengono interpretati come date. L’utilizzo della funzione InputBox rappresenta un modo molto valido per poter utilizzare una macro in circostanze diverse. Tuttavia, è necessario controllare il risultato di InputBox prima di continuare la macro. Utilizzo di espressioni condizionali 217 Normalmente, le possibilità da verificare sono tre: input valido, input non valido e Annulla. Un blocco If, a volte un blocco If nidificato, sono sufficienti per rendere una macro abbastanza strutturata da soddisfare tutte le possibili opzioni. Domande tramite messaggi La funzione MsgBox di è utile per visualizzare messaggi semplici. Come indica il nome, questa funzione visualizza una finestra di messaggio, ma è in grado di eseguire molte altre operazioni. Può fare domande, ad esempio. Molte volte, quando una macro pone una domanda, è sufficiente rispondere “sì” o “no”, e la funzione MsgBox si presta perfettamente a questo tipo di domande. SI supponga di avere due macro: una chiamata PrintMonth lunga e lenta e un’altra chiamata ProcessMonth breve e rapida. A volte, per errore, viene eseguita quella lenta invece di quella rapida. Una soluzione possibile è quella di aggiungere una finestra di messaggio all’inizio della macro lenta che richiede una conferma di esecuzione. Il file di testo Flow comprende una macro chiamata CheckRun, che è possibile sviluppare affinché utilizzi una funzione MsgBox per porre una domanda. Prima di iniziare, la macro è come la seguente: Sub CheckRun() MsgBox “This takes a long time. Continue?” MsgBox “Continue with slow macro...” End Sub 1. Copiare la macro CheckRun dal file di testo in un modulo della cartella di lavoro Chapter07. 2. Fare clic nella macro CheckRun e premere F5 per eseguirla. Fare clic due volte su OK per chiudere tutte le finestre di messaggio. La prima finestra di messaggio viene visualizzata per porre una domanda ma presenta un solo pulsante. Per utilizzarla in questo modo, è necessario aggiungerne altri. 3. Spostare il cursore alla fine della prima istruzione MsgBox. Appena dopo le virgolette di chiusura, inserire una virgola. 218 Capitolo 7 Controllo di Visual Basic Non appena viene digitata la virgola, Visual Basic visualizza la finestra Informazioni rapide della funzione MsgBox. Il primo argomento è chiamato Prompt ed è quello nel quale viene inserito il messaggio da visualizzare. Il secondo è chiamato Buttons e corrisponde a un elenco enumerato di valori. Il valore predefinito di Buttons è vbOKOnly, ed è per questo che eseguendo la macro si visualizzava il solo pulsante OK. Oltre alla finestra Informazioni rapide, Visual Basic visualizza anche un elenco automatico di possibili valori dell’argomento Buttons. Esso deve porre una domanda che preveda sì o no come risposta. 4. Scorrere l’elenco quasi fino alla fine, selezionare vbYesNo, premere Tab e quindi F5 per eseguire la macro. Adesso, la prima finestra di messaggio visualizza due pulsanti 5. Fare clic su Sì per chiudere la prima e poi su OK per chiudere la seconda. La finestra di messaggio pone una domanda ma ignora completamente la risposta ricevuta. È necessario ottenere la risposta dalla funzione MsgBox e quindi utilizzarla per controllare l’esecuzione della macro. 6. Digitare l’istruzione Dim myCheck As VbMsgBoxResult all’inizio della macro. Se si è certi che una variabile conterrà solo il valore ottenuto da un elenco enumerato, sarà possibile utilizzare il nome dell’elenco nella dichiarazione della variabile. Dopodiché, quando si scrive un’istruzione per provare il valore della variabile, Visual Basic visualizzerà l’elenco dei valori possibili. 7. All’inizio della prima istruzione MsgBox, digitare myCheck = e racchiudere tra parentesi l’elenco di argomenti della funzione MsgBox. Utilizzo di espressioni condizionali 219 L’istruzione rivista sarà uguale alla seguente: myCheck = MsgBox(“This takes a long time. Continue?”, vbYesNo) Importante Quando si utilizza il valore restituito di una funzione come MsgBox, è necessario racchiudere l’elenco degli argomenti tra due parentesi. Quando, invece, non si utilizza il valore restituito, le parentesi non servono. 8. Prima della seconda istruzione MsgBox, inserire le tre istruzioni seguenti: If myCheck = vbNo Then Exit Sub End If Importante Quando si crea un’espressione condizionale utilizzando il risultato della funzione MsgBox, non cercare True o False. MsgBox può visualizzare molti tipi di pulsanti, quindi prevede molti tipi di risposte. Utilizzando vbYesNo nell’argomento Buttons, MsgBox restituirà sempre vbYes o vbNo. Nessuno di questi valori enumerati corrisponde a False, quindi confrontare il risultato con False è come selezionare sempre Sì. Quando si prova un valore ottenuto da un elenco enumerato, accertarsi sempre di utilizzare la costante di enumerazione appropriata. L’istruzione Exit Sub comporta l’interruzione immediata della macro corrente da parte di Visual Basic. Per evitare di complicare troppo le macro, utilizzare Exit Sub raramente. Questa istruzione è molto valida quando si annulla la parte iniziale della macro, come in questo caso. La macro completa sarà uguale alla seguente: Sub CheckRun() Dim myCheck As VbMsgBoxResult myCheck = MsgBox(“This takes a long time. Continue?”, vbYesNo) If myCheck = vbNo Then Exit Sub End If MsgBox “Continue with slow macro...” End Sub 9. Provare la macro. Eseguirla e fare clic su Sì, poi eseguirla e fare clic su No. Accertarsi che la parte restante della macro venga eseguita solo quando si seleziona Sì. Le finestre di messaggio rappresentano uno strumento efficace per porre domande semplici. La funzione MsgBox costituisce un esempio valido di come utilizzare le parentesi per racchiudere gli elenchi di argomenti: inserirle se si utilizza il valore restituito della funzione, altrimenti no. 220 Capitolo 7 Controllo di Visual Basic Creazione di cicli Molto prima di Henry Ford e perfino di Marc Brunel, l’economista Adam Smith affermò che in una giornata ogni operaio poteva produrre un solo spillo finito, ma che dieci operai che si suddividevano la varie mansioni ne potevano produrre 48.000, pari a una produttività 5.000 volte superiore. Allo stesso modo, è possibile ottenere notevoli aumenti produttivi convertendo una macro che viene eseguita una volta in una eseguita migliaia di volte tramite un ciclo. Ciclo di raccolta attraverso un’istruzione For Each Excel consente di proteggere un foglio di lavoro, in modo che l’utente possa modificare solo le celle sbloccate. Tuttavia, ogni foglio va protetto in modo individuale. Si supponga di avere una cartella di lavoro contenente budget relativi a dieci diversi reparti e che si desideri proteggere tutti i fogli di lavoro. Il file di testo Flow comprende una macro chiamata ProtectSheets, riportata di seguito: Sub ProtectSheets() Dim mySheet As Worksheet Set mySheet = Worksheets(1) mySheet.Select mySheet.Protect “Password”, True, True, True End Sub Questa macro assegna un riferimento al primo foglio di lavoro della variabile mySheet, lo seleziona e quindi lo protegge. (Selezionare il foglio non è realmente necessario, tuttavia semplifica la visualizzazione delle operazioni della macro.) Di seguito, viene illustrato come convertire la macro per proteggere tutti i fogli di lavoro della cartella. 1. Copiare la macro ProtectSheets dal file di testo e incollarla in un modulo VBA della cartella di lavoro Chapter07. 2. Fare clic nella macro ProtectSheets e premere più volte F8 per analizzarla. Accertarsi di aver compreso tutte le operazioni eseguite dalla macro originale. 3. Nella terza riga, sostituire Set con For Each, il segno uguale con In e rimuovere sia le parentesi che il numero in esse contenuto. 4. Inserire un rientro per le due istruzioni che iniziano con mySheet, aggiungere una nuova riga e digitare l’istruzione Next mySheet. La macro completa sarà uguale alla seguente: Sub ProtectSheets() Dim mySheet As Worksheet For Each mySheet In Worksheets mySheet.Select mySheet.Protect “Password”, True, True, True Creazione di cicli 221 Next mySheet End Sub L’istruzione For Each funziona come Set, ovvero assegna un riferimento dell’oggetto a una variabile. Ma invece di assegnarne uno solo, sceglie tutti gli elementi di una raccolta. Quindi, per ogni oggetto della raccolta, Visual Basic esegue tutte le istruzioni fino alla Next. (Tecnicamente, non è necessario inserire il nome della variabile dopo Next. Tuttavia, se lo si utilizza, Visual Basic richiede che corrisponda al nome della variabile dopo For Each. Utilizzare sempre la variabile del ciclo dopo Next in modo che Visual Basic possa contribuire a evitare bug nella macro.) Le istruzioni che hanno inizio con For Each e terminano con Next sono definite blocchi For Each o cicli For Each. 5. Premere F8 più volte per analizzare la macro, controllandone il funzionamento in ogni foglio di lavoro. 6. Passare a Excel e cercare di inserire un valore in una cella di uno dei fogli di lavoro. Dopodiché, chiudere la finestra del messaggio di errore aperta. 7. Creare una nuova macro chiamata UnprotectSheets che toglie la protezione a tutti i fogli di lavoro. Cercare di scrivere la macro senza controllare il codice finito che segue. Consiglio: è necessario utilizzare il metodo Unprotect dell’oggetto del foglio di lavoro con un solo argomento con password. Suggerimento Un ciclo For Each rappresenta un modo pratico per sfogliare gli insiemi della finestra Immediata. Tuttavia, ciò che viene inserito in questa finestra deve essere contenuto in una singola riga. Quindi, per digitare più istruzioni, utilizzare i due punti per separarle. Ad esempio, di seguito viene illustrato cosa scrivere nella finestra Immediata per visualizzare i nomi di tutti i fogli di lavoro della cartella attiva: For Each x In Worksheets: ?x.Name: Next x. (Nella finestra Immediata, è consigliabile utilizzare nomi brevi e semplici.) La macro UnprotectSheets ottenuta sarà la seguente: Sub UnprotectSheets() Dim mySheet As Worksheet For Each mySheet In Worksheets mySheet.Select ‘ This statement is optional. mySheet.Unprotect “Password” Next mySheet End Sub 222 Capitolo 7 8. Controllo di Visual Basic Salvare la cartella di lavoro, premere F5 per eseguire la macro UnprotectSheets e quindi provarla modificando un valore in un foglio di lavoro. La protezione di un insieme è semplice quanto l’assegnazione di un singolo oggetto a una variabile. L’unica differenza è che si utilizza For Each invece di Set, si specifica l’esecuzione di un ciclo di raccolta e si aggiunge un’istruzione Next al termine del ciclo stesso. Esecuzione di un ciclo con un contatore mediante una struttura For Loop A volte si desidera eseguire alcune operazioni più volte ma non è possibile utilizzare un ciclo For Each. Ad esempio, un ciclo di questo tipo funziona unicamente in un solo insieme. Quindi, se si desidera confrontare due insiemi paralleli, come due intervalli, non è possibile utilizzarlo. In questa situazione, Visual Basic fornisce un altro modo più generalizzato per eseguire un ciclo: un ciclo For. Il foglio di lavoro Compare della cartella di lavoro Chapter07 contiene due intervalli nominati. Uno a sinistra chiamato Old e uno a destra chiamato New. Essi vanno considerati, il primo come previsione originale e il secondo come previsione rivista. Le celle dell’intervallo Old contengono i valori, mentre le celle dell’intervallo New contengono una formula che calcola un numero casuale ogni volta che si preme F9 per ricalcolare la cartella di lavoro. (La formula di queste celle è =ROUND(RAND()*50+100,0), che indica a Excel di calcolare un numero casuale tra 0 e 1, moltiplicarlo per 50, aggiungervi 100 e arrotondarlo al numero intero più prossimo. Dato che i numeri dell’intervallo New vengono generati a caso, quelli visualizzati potrebbero essere diversi da quelli illustrati nell’immagine.) Il file di testo Flow contiene una macro chiamata CompareCells, uguale alla seguente: Sub CompareCells() Dim i As Integer Calculate If Range(“New”).Cells(i) > Range(“Old”).Cells(i) Then Range(“New”).Cells(i).Interior.Color = rgbLightGreen Else Range(“New”).Cells(i).Interior.Color = rgbLightSteelBlue End If End Sub Creazione di cicli 223 Prima la macro esegue il metodo Calcolate, che calcola i nuovi valori di tutte le celle dell’intervallo New, poi confronta solo l’ultima cella dell’intervallo New con l’ultima dell’intervallo Old. Se il valore New della cella in questione è più alto del valore Old, la cella diventa verde chiaro; altrimenti diventa azzurra. La macro assegna la proprietà Count delle celle contenute nell’intervallo alla variabile i, che rappresenta un valore integer semplice. Vedere anche Se non si conoscono in modo approfondito i blocchi If, rivedere la prima metà del presente capitolo. Per maggiori informazioni sul colore delle celle, consultare la sezione “Formattazione della parte interna di un intervallo” del capitolo 4 “Esplorazione degli oggetti Range”. A questo punto convertire la macro per utilizzare un ciclo al fine di confrontare e colorare tutte le celle dell’intervallo New. 1. Copiare la macro CompareCells dal file di testo e incollarla in un modulo VBA della cartella di lavoro Chapter07. 2. Fare clic nella macro CompareCells e premere F8 più volte per analizzare la macro. Accertarsi di aver compreso il comportamento della macro originale. 3. Nell’istruzione che assegna Count alla variabile, inserire la parola For prima della variabile, quindi inserire 1 To dopo il segno uguale. 4. Digitare Next i prima dell’istruzione End Sub e inserire un rientro per tutte le istruzioni tra For e Next. La macro completa sarà uguale alla seguente: Sub CompareCells() Dim i As Integer Calculate For i = 1 To Range(“New”).Cells.Count If Range(“New”).Cells(i) > Range(“Old”).Cells(i) Then Range(“New”).Cells(i).Interior.Color = rgbLightGreen Else Range(“New”).Cells(i).Interior.Color = rgbLightSteelBlue End If Next i End Sub 224 Capitolo 7 Controllo di Visual Basic La parola chiave For funziona come una semplice istruzione di assegnazione, ovvero assegna un numero a una variabile. (L’istruzione For assegna un numero a una variabile integer, mentre l’istruzione For Each assegna un riferimento a una variabile di oggetto.) La variabile che contiene il numero è chiamata contatore di ciclo. Si specifica il valore iniziale del contatore di ciclo (in questo caso, 1) e il valore finale (in questo caso, il numero totale di celle nell’intervallo). Il ciclo For assegna il valore iniziale al contatore di ciclo, esegue tutte le istruzioni dopo l’istruzione Next, aggiunge 1 al contatore e lo controlla rispetto al valore finale. Se il contatore di ciclo è superiore al valore finale, il ciclo For salta l’istruzione Next. Se invece è inferiore o uguale al valore finale, il ciclo For ripete l’operazione. 5. Premere F8 più volte per visualizzare il funzionamento della macro. Analizzare almeno due o tre cicli, quindi premere F5 per concludere la macro. In molti casi, utilizzare un ciclo For Each è più utile che utilizzare un ciclo For. Tuttavia, For rimane uno strumento più generico: per riprodurre il comportamento di un ciclo For Each, è sempre possibile utilizzare un ciclo For. Ad esempio, di seguito viene illustrato come scrivere la macro ProtectSheets senza utilizzare For Each: Sub ForProtectSheets() Dim mySheet As Worksheet Dim i As Integer For i = 1 to Worksheets.Count Set mySheet = Worksheets(i) mySheet.Select mySheet.Protect "Password", True, True, True Next i End Sub Risoluzione dei problemi Se si esegue una macro che contiene un ciclo infinito, arrestare la macro premendo Ctrl+Interr. Il ciclo For è leggermente più rischioso di un ciclo For Each, perché è necessario accertarsi di ottenere i valori iniziale e finale corretti. Se si ha un valore finale inferiore a quello iniziale, il ciclo continuerà all’infinito, una condizione nota come ciclo infinito. Con un ciclo For Each, non è possibile creare un ciclo infinito. Creazione di cicli 225 Esecuzione di un ciclo indefinito mediante una struttura Do Un ciclo For Each agisce in un insieme, mentre For esegue un ciclo da un punto iniziale a uno finale. Tuttavia, in alcune situazioni, nessuna delle due opzioni funziona. Ad esempio, si supponga di voler recuperare i nomi di tutte le cartelle di lavoro Excel della cartella corrente. Visual Basic fornisce una funzione che indica i nomi dei file di una cartella (o directory). Essa è chiamata Dir, per ricordare il comando del sistema operativo MS-DOS che portava lo stesso nome. La prima volta che si utilizza Dir, è necessario forrnire un argomento che indichi quale tipo di file visualizzare. Per recuperare il nome della prima cartella di lavoro di Excel della directory corrente, utilizzare l’istruzione myFile = Dir(“*.xlsx”). Per ottenere il file successivo che corrisponde allo stesso modello, utilizzare nuovamente Dir ma senza argomento. Dir va eseguito ripetutamente perché restituisce un solo nome di file per volta. Se Visual Basic non è in grado di trovare file corrispondenti, la funzione Dir restituisce una stringa vuota. Quindi, come creare una macro che recuperi i nomi di tutti i file Excel della cartella corrente? L’elenco dei file non costituisce un insieme, pertanto non è possibile utilizzare un ciclo For Each. Non si può utilizzare neppure un ciclo For perché non si conosce il numero dei file che verranno recuperati prima del completamento dell’operazione. Fortunatamente, Visual Basic fornisce un altro modo per controllare un ciclo, ovvero Do. La macro ListFiles del file di testo Flow recupera i primi due file di Excel dalla directory corrente e ne inserisce i nomi nelle prime due celle della prima colonna del foglio di lavoro attivo. La macro originale è la seguente: Sub ListFiles() Dim myRow As Integer Dim myFile As String myRow = 1 myFile = Dir(“*.xls”) Cells(myRow, 1) = myFile myRow = myRow + 1 myFile = Dir Cells(myRow, 1) = myFile End Sub A parte le istruzioni di dichiarazione delle variabili, questa macro è costituita da due gruppi di tre istruzioni ognuno. In ogni gruppo, la macro assegna un numero di riga a myRow, recupera un nome di file utilizzando la funzione Dir e poi lo inserisce nella cella appropriata. La prima volta che la macro utilizza Dir, specifica il modello con il quale trovare corrispondenza. La volta successiva, la macro utilizza Dir senza argomento al fine di recuperare il successivo file corrispondente. 226 Capitolo 7 Controllo di Visual Basic Di seguito, viene illustrato come convertire questa macro per eseguire il ciclo finché non trova tutti i file della cartella. 1. Copiare la macro ListFiles dal file di testo e incollarla in un modulo VBA della cartella di lavoro Chapter07. 2. Nella cartella Chapter07, attivare il foglio di lavoro Files. 3. Accertarsi che la cartella corrente sia quella contenente i file di esercitazione del libro. (Fare clic sul pulsante Office, selezionare Apri, modificare il percorso con quello della cartella corrente e fare clic su Annulla.) 4. In Visual Basic Editor, fare clic sulla macro ListFiles e premere più volte F8 per analizzarla. (I nomi dei file recuperati dalla macro potrebbero essere diversi da quelli mostrati nell’immagine.) Accertarsi di aver compreso la macro originale. Suggerimento Durante l’analisi della macro, spostare il puntatore del mouse sul nome di una variabile per visualizzare il valore corrente in essa contenuto. 5. Dopo la prima istruzione che contiene una funzione Dir, inserire una nuova riga e digitare Do Until myFile = “” (senza spazio tra le virgolette.) Questa istruzione avvia il ciclo. Esso ha inizio dopo la prima funzione Dir perché Dir viene utilizzato con un argomento solo una volta. 6. Al termine della seconda istruzione contenente una funzione Dir, inserire una nuova riga e digitare Loop. Questa istruzione arresta il ciclo e indica a Visual Basic di tornare all’inizio del ciclo e verificare se è possibile chiudere la macro. 7. Eliminare la seconda istruzione Cells(myRow, 1) = myFile. Essa non serve perché il ciclo ripete l’istruzione di assegnazione tutte le volte necessarie. 8. Appena prima dell’istruzione myRow = 1, inserire una riga e l’istruzione Cells.Clear. Questa operazione garantisce che il foglio di lavoro sia vuoto nel caso la macro venga eseguita più volte e alcuni elenchi siano più brevi di altri. Suggerimento Quando si utilizza una macro per scrivere un elenco in un foglio di lavoro, accertarsi che nel foglio non siano rimasti elenchi utilizzati in precedenza. Utilizzare Cells.Clear per cancellare il foglio o Worksheets.Add per crearne uno nuovo. Creazione di cicli 9. 227 Inserire un rientro per le tre istruzioni collocate tra le istruzioni Do e Loop. La macro rivista sarà uguale alla seguente: Sub ListFiles() Dim myRow As Integer Dim myFile As String Cells.Clear myRow = 1 myFile = Dir(“*.xlsx”) Do Until myFile = “” Cells(myRow, 1) = myFile myRow = myRow + 1 myFile = Dir Loop End Sub L’espressione myFile = “” al termine dell’istruzione Do Until rappresenta un’espressione condizionale, uguale a quella utilizzata con un’istruzione If. L’espressione condizionale deve essere una parte interpretabile da Visual Basic come True o False. Il programma si limita a ripetere il ciclo finché l’espressione è True. Si noti che la condizione non deve realizzarsi, altrimenti il ciclo non verrà mai eseguito. Ad esempio se non ci sono file .xlsx nella cartella, la condizione di arresto si realizzerà già la prima volta che verrà eseguito. Se si desidera incrementare un numero durante il ciclo, è necessario inserire un’istruzione che esegua tale operazione. Inoltre, è necessario fare in modo che durante il ciclo si verifichi una situazione che ne consenta l’arresto. In questo caso, viene recuperato un nuovo nome di file dalla funzione Dir. 10. Premere più volte F8 per visualizzare il funzionamento della macro. Analizzare almeno due o tre cicli e quindi premere F5 per concludere la macro. Risoluzione dei problemi Se si esegue una macro che contiene un ciclo infinito, arrestarla premendo Ctrl+Interr. 228 Capitolo 7 Controllo di Visual Basic Il ciclo Do è il più flessibile. Tutte le operazioni eseguite con un ciclo For o For Each sono possibili anche con Do. Se si naufragasse su un’isola deserta con una sola struttura di ciclo, Do sarebbe senza dubbio lo strumento migliore. Ad esempio, di seguito viene illustrato come scrivere la macro ProtectSheets utilizzando un ciclo Do. Sub ProtectSheets() Dim mySheet As Worksheet Dim i As Integer i = 1 Do Until i > Worksheets.Count Set mySheet = Worksheets(i) mySheet.Select mySheet.Protect “Password”, True, True, True i = i + 1 Loop End Sub A causa delle caratteristiche di flessibilità, il ciclo Do risulta leggermente più complicato rispetto agli altri perché è necessario creare e incrementare la variabile del ciclo e fornire la condizione necessaria perchè si arresti. Ciò lo rende particolarmente vulnerabile al rischio di diventare un ciclo infinito. Ad esempio, se non è stata inserita l’istruzione per recuperare il nome di un nuovo file o se nel ciclo è stato incluso l’argomento per la funzione Dir (causando la restituzione continua del nome del primo file da parte di Dir), il ciclo sarà infinito. Suggerimento I cicli Do presentano diverse variazioni utili. È possibile eseguire il ciclo finché l’espressione condizionale è True, oppure mentre l’espressione è True. Inoltre, è possibile inserire l’espressione condizione all’inizio del ciclo (nell’istruzione Do) oppure alla fine (nell’istruzione Loop). Per maggiori informazioni sulle strutture di ciclo Do, selezionare la parola Do nella macro e premere F1. Gestione di cicli lunghi Un ciclo eseguito due o tre volte non è molto diverso da un programma senza ciclo. È rapido e semplice da visualizzare per analizzare il funzionamento delle singole istruzioni. Tuttavia, quando un ciclo viene ripetuto centinaia o migliaia di volte, servono alcune tecniche supplementari per garantire che la macro funzioni esattamente come previsto. Gestione di cicli lunghi 229 Impostazione di un punto di interruzione Il file di testo Flow comprende una macro chiamata PrintOrders. Essa può essere considerata come la macro scritta da un collega poco prima di lasciare l’azienda, oppure la macro creata tre mesi prima. Qualunque sia il caso, si tratta di una macro non compresa fino in fondo e non funzionante in modo corretto. Lo scopo della macro PrintOrders è quello di stampare una copia di tutta la cartella di lavoro Orders, in modo specifico se ordinata per Category. Si consegna al responsabile di ogni Category la sezione del report riportante gli ordini della propria categoria, pertanto servirà una nuova pagina ogni volta che una Category cambia. Sfortunatamente ma macro non esegue le operazioni previste, quindi è necessario identificare e risolvere il problema. Di seguito viene riportata la macro originale: Sub PrintOrders() Dim myRow As Long Dim myStop As Long Workbooks.Open FileName:=”orders.xls” Columns(“E:E”).Cut Columns(“A:A”).Insert Shift:=xlToRight Range(“A1”).CurrentRegion.Sort Key1:=”Category”, _ Order1:=xlAscending, Header:=xlYes myStop = Range(“A1”).CurrentRegion.Rows.Count For myRow = 3 To myStop If Cells(myRow, 1) <> Cells(myRow + 1, 1) Then Cells(myRow, 1).Select ActiveCell.PageBreak = xlPageBreakManual End If Next myRow Cells(myRow, 1).Select ActiveSheet.PageSetup.PrintTitleRows = “$1:$1” ActiveSheet.PrintPreview ActiveWorkbook.Close SaveChanges:=False End Sub L’approccio migliore è probabilmente quello di analizzare la macro. 1. Copiare la macro PrintOrders dal file di testo e incollarla in un modulo VBA della cartella di lavoro Chapter07. 2. Accertarsi che la cartella corrente sia quella contenente i file di esercitazione del libro. (Fare clic sul pulsante Office, selezionare Apri, modificare la cartella corrente e fare clic su Annulla.) 230 Capitolo 7 Controllo di Visual Basic 3. In Visual Basic Editor, fare clic sulla macro PrintOrders e premere F8 tre volte per ignorare le dichiarazioni delle variabili e aprire la cartella di lavoro Orders. 4. Premere F8 tre volte. Queste istruzioni spostano il campo Category nella colonna A e poi ordinano la lista in base a Category. 5. Premere F8 due volte per assegnare un numero a myStop e per avviare il ciclo. Tenere il puntatore del mouse su myStop e quindi su myRow per visualizzare i valori assegnati. Il valore di myStop è 3266 mentre quello di myRow è 3 e sembrano essere corretti. Il ciclo verrà eseguito dalla riga 3 alla 3266. 6. Premere F8 più volte. Visual Basic continua a verificare se la riga corrente corrisponde alla cella sottostante. Quante righe ci sono nella categoria Art? Premere F8 finché la macro trova l’ultima riga della categoria potrebbe richiedere del tempo. Tuttavia, se si preme soltanto F5 per eseguire il resto della macro, non è possibile verificare cosa accade quando la condizione dell’istruzione If è True. Purtroppo, non esiste un modo per ignorare tutte le istruzioni finché la macro arriva al blocco If. 7. Fare clic sull’area grigia a sinistra dell’istruzione che inizia con ActiveCell. Nel margine viene visualizzato un cerchio rosso scuro e anche lo sfondo dell’istruzione cambia nello stesso colore. Si tratta di un punto di interruzione. Quando se ne imposta uno, la macro viene arrestata quando raggiunge l’istruzione che lo contiene. Gestione di cicli lunghi 8. 231 Premere F5 per continuare l’esecuzione della macro. Essa viene arrestata al punto di interruzione. Quando la macro raggiunge tale punto, la cella attiva risulta essere la prima che l’istruzione If ha identificato come diversa da quella sopra. 9. Premere F8 per eseguire l’istruzione che assegna un’interruzione di pagina manuale. Tale interruzione viene visualizzata sopra la riga, non sotto, il che rappresenta un problema, perché la macro non dovrebbe impostare un punto di interruzione nell’ultima cella di una Category, bensì nella prima. L’istruzione If dovrebbe verificare se la cella è diversa da quella esattamente sopra. 10. Modificare il segno più (+) dell’istruzione If con un segno meno (–). L’istruzione rivista sarà uguale alla quella sottoriportata: If Cells(myRow, 1) <> Cells(myRow - 1, 1) Then 11. Fare clic sul pulsante Ripristina, premere F5 e riaprire il file Orders. Quindi, premere F8 per visualizzare il delicato funzionamento dell’istruzione nel momento esatto in cui assegna l’interruzione di pagina dopo la categoria Art. 12. Fare clic sul cerchio rosso nel margine per disattivare il punto di interruzione. Impostare un punto di interruzione rappresenta uno strumento molto prezioso per identificare eventuali problemi in un ciclo lungo. Nella sezione seguente, verrà illustrato un modo semplice per impostare un punto di interruzione temporaneo, nel caso in cui vada utilizzato una sola volta. 232 Capitolo 7 Controllo di Visual Basic Impostazione di un punto di interruzione temporaneo Un punto di interruzione interrompe la macro ogni volta che raggiunge l’istruzione in cui è stato collocato e resta attivo finché non viene rimosso. Cosa succede quando si crea un punto di interruzione temporaneo da usare una sola volta? Ad esempio, si supponga di trovarsi in fase di analisi della macro PrintOrders. Il codice che assegna un’interruzione di pagina sembra funzionare correttamente. Tuttavia, nella parte finale della macro ci sono ancora alcune istruzioni che si desidera analizzare. 1. Se non si sta già analizzando la macro, premere F8 per avviare l’operazione. 2. Fare clic in un punto qualunque dell’istruzione Cells(myRow, 1).Select al termine del ciclo per collocare un punto di inserimento. Si intende stabilirne uno, da utilizzare solo una volta. 3. Nel menu Debug, fare clic su Esegui fino al cursore. La macro viene eseguita in tutte le pagine del report e si interrompe una volta arrivata all’istruzione con il cursore. 4. Premere F8 tre volte per scorrere l’elenco fino alla fine, impostare i titoli di stampa e visualizzare un’anteprima del report. Quando la macro viene interrotta in un’istruzione, è possibile continuare l’analisi da quel punto. 5. Rivedere il report. Fare clic più volte su Pagina successiva per arrivare alla pagina 10 e visualizzare la parte finale della categoria Art. Risoluzione dei problemi Se a pagina 10 non viene vsualizzata l’ultima parte della categoria Art, è sufficiente fare clic su Pagina successiva o Pagina precedente per trovare la pagina corretta . Il driver corrente della stampante potrebbe aver collocato la fine della categoria in una pagina diversa. Gestione di cicli lunghi 6. Chiudere Anteprima di stampa e premere F8 due volte per concludere la macro. 7. Salvare la cartella di lavoro Chapter07. 233 Disattivare un punto di interruzione è semplice quanto attivarlo: è sufficiente fare clic nel margine sinistro della finestra di Visual Basic Editor. Se attivare e disattivare un punto di interruzione comporta troppe operazioni, è possibile crearne uno temporaneo eseguendo la macro fino alla posizione del cursore. Visualizzazione dello stato di avanzamento di un ciclo Anche se il ciclo funziona perfettamente, la macro può risultare lenta perché evidenzia qualche errore. Il modo migliore per controllare l’esecuzione di un ciclo lento (soprattutto se ci si chiede perché si ha il tempo di fare una pausa caffè) è quello di visualizzarne lo stato di avanzamento. Questa operazione può essere eseguita per tutti i tipi di ciclo. Tuttavia, il ciclo For si presta particolarmente a questa procedura perché in qualsiasi punto dello stesso, è possibile determinare sia il valore corrente del contatore di ciclo sia quello finale presunto. 1. Nella macro PrintOrders, appena dopo l’istruzione For, inserire l’istruzione seguente: Application.StatusBar = “Processing row “ & myRow & “ of “ & myStop La barra di stato visualizzata nella parte inferiore della finestra di Excel indica “Pronto.” La proprietà StatusBar dell’oggetto Applciation consente di ottenere dalla barra di stato tutte le informazioni desiderate. Il messaggio più appropriato è quello che indica lo stato di avanzamento, consentendo all’utente di calcolare i tempi di esecuzione necessari. 234 Capitolo 7 Controllo di Visual Basic Quando avvia il ciclo la prima volta, L’istruzione aggiunta crea questo messaggio: “Elaborazione riga 3 di 3300.” Utilizzando una e commerciale (&) per unire il testo del messaggio ai numeri delle variabili myRow e myStop, è possibile generare un messaggio utile. Ricordarsi, però, di includere uno spazio in più prima e dopo i numeri. 2. Premere F5 per eseguire la macro. Controllare la barra di stato per visualizzarne lo stato di avanzamento. 3. Chiudere l’Anteprima di stampa per consentire la conclusione della macro. La barra di stato indica che la macro è ancora in esecuzione, perché non si reimposta automaticamente al termine della stessa. Per restituire a Excel il controllo della barra, è necessario assegnare un valore di False. 4. Dopo l’istruzione Next, inserire l’istruzione seguente: Application.StatusBar = False 5. Eseguire di nuovo la macro, chiudere l’Anteprima di stampa al momento giusto e poi controllare la barra di stato. È tornata allo stato normale. 6. Salvare la cartella di lavoro Chapter07. Visual Basic fornisce strumenti estermamente efficaci per ripetere le istruzioni in un ciclo. Insieme all’utilizzo di blocchi If, tali strumenti consentono di creare macro valide e molto potenti. CHIUDERE la cartella di lavoro Chapter07.xlsm. Concetti fondamentali 235 Concetti fondamentali ● Utilizzare una struttura If per consentire a una macro di prendere decisioni. Aggiungere una clausola Else se è necessario che le condizioni True e False eseguano azioni diverse. ● Quandi si utilizza l’istruzione MsgBox, aggiungere l’argomento Buttons per generare scelte esplicite. Quando si controlla il risultato di una MsgBox, accertarsi di confrontarlo alla costante adeguata. ● Quando si utilizza una InputBox, ricordarsi di considerare tutti i tipi di input possibili – valido, non valido, inesistente. Creare una struttura If per gestire tutte le condizioni possibili. ● Quando si deve eseguire un ciclo di raccolta, For Each rappresenta l’opzione più semplice. ● Quando serve un contatore per semplificare l’utilizzo di un ciclo, ad esempio per tenere sincronizzati due oggetti, utilizzare un ciclo For. ● Quando si deve eseguire un ciclo temporaneo o eseguire un ciclo finché una condizione è True, utilizzare un ciclo Do risulta estrememente flessibile. Tuttavia, fare attenzione a non creare un ciclo infinito. ● Utilizzare punti di interruzione permanenti o temporanei, per risolvere i problemi di macro e cicli lunghi.