Il VBA e la gestione degli  ERRORI

 

Istruzione On Error e Err.Number

Chiunque abbia iniziato a lavorare con il Vba, realizzando macro o routines, sicuramente è incappato in qualche "Errore" di programmazione. Queste note non vogliono essere un'analisi dei vari errori, ma più semplicemente una breve spiegazione di come poterli "addomesticare".

Gli "Errori" di cui ci occuperemo, non sono gli errori che vengono intercettati "mentre" si scrive del codice (una macro), e che ci vengono immediatamente segnalati dal "compilatore", e che riguardano esclusivamente errori di sintassi, (scrivendo male un istruzione, se omettiamo un carattere, oppure una parentesi, o ancora il segno di uguale, ecc.), ma di quelli errori  che ci vengono segnalati quando, tutti soddisfatti lanciamo la nostra routine dal foglio di lavoro, e improvvisamente ci appare un messaggio con su scritto : "Errore di Run-Time n° xy", bloccando l'esecuzione delle istruzioni (in alcuni casi anche il S.O.), e che ci lasciano frustrati e sgomenti. E' opportuno precisare che in Excel esistono due tipi di intercettazione errori: uno è gestito direttamente da Excel sul foglio di lavoro, attraverso i purtroppo famosi messaggi nelle celle, tipo #N/D, opp. #DIV, ecc. ecc. (trovate una esauriente spiegazione di questi errori nella sezione "Primi passi"), l'altro invece viene gestito dal Vba, e intercetta gli errori di istruzioni inserite nel codice.

Intanto vediamo chi è che ci avvisa, è il Debugger, uno strumento di controllo delle istruzioni da eseguire, presente in tutti i Programmi di compilazione, che ha il compito, appunto, di intercettare e bloccare l'esecuzione di codice errato, segnalandoci il tipo di errore e l'eventuale numero di identificazione. Esiste appunto una tabella, nella guida in linea, dove sono riportate le spiegazioni relative ai numeri di errore. Qua sotto vi indico come arrivare alla tabella dei codici errore attraverso la Guida in linea richiamabile dall'Editor di Visual Basic: nella cartellina "Indice", digitate la parola "errori",  premete "Cerca", e nella finestra "Selezione argomento" selezionate "Errori intercettabili",  e nella pagina a lato sulla destra appare l'elenco degli Errori Intercettabili, dove, per ogni errore, viene fornita una spiegazione cliccando sul "messaggio".

 

 

Quando appare la finestra messaggio che ci avvisa dell'errore, troviamo due pulsanti : uno ci consente di uscire dal blocco che si è verificato a causa dell'errore stesso, l'altro, importante, dove c'è scritto "Debug", ci porta nella zona codice e ci viene evidenziata in giallo la riga dell'istruzione che sta generando l'errore; questo ci consente di identificare l'istruzione incriminata, senza scervellarsi a controllare tutte le istruzioni riga per riga. Potremo quindi (speriamo) capire cosa e come correggere, evitando l'insorgere dell'errore.

Esiste la maniera di poter gestire il verificarsi di un errore, attraverso un'istruzione appropriata, che è  On Error. Si possono usare tre tipi di istruzioni basate su On Error, io vi segnalo quella, secondo me, più "universale", e che consente di evitare il blocco causato da un errore, con il vantaggio che le istruzioni successive a quella che contiene l'errore, verranno comunque eseguite. ( è ovvio che se l'errore si verifica su un'istruzione che deve essere utilizzata dalle istruzioni successive, anche se le successive verranno eseguite, il risultato voluto mancherà, per l'assenza di un dato). L'istruzione On Error si compone di due righe, la prima andrà scritta così   On Error Resume Next   e va posizionata subito sotto l'inizio routine (che comincia sempre con il nome della macro o dell'oggetto il cui evento attiverà le istruzioni); la seconda riga invece è :   Resume   e va posizionata a fine istruzioni, immediatamente prima di End Sub. Tenere presente che la "visibilità" di queste istruzioni rimane di pertinenza della routine che le incorpora. Per ogni routine andranno ripetute se vorremo un controllo errori su tutte. Facciamo il classico esempio:

Sub Latua()   'nome macro o routine

On Error Resume Next

seguono tutte le righe di istruzioni

Resume

End Sub

Suggerirei di preparare le istruzioni On Error nella nostra/nostre macro, ma di tenerle disattivate (con un apice ( ' ) ad inizio riga) durante la fase di compilazione del codice, perchè dovendo provare se tutto funziona bene, dovremo approfittare del Debugger perchè ci segnali eventuali errori, cosa che non avverrebbe se lasciamo operative le istruzioni On Error. Toglieremo poi l'apice una volta che avremo verificato la correttezza della routine.

Abbiamo detto che l'uso di On Error ci consente di evitare il blocco delle istruzioni e l'uscita dal programma. Esistono degli errori che si possono verificare DOPO che abbiamo controllato e trovato esatte le nostre istruzioni, errori causati nella gestione del programma da noi fatto. L'istruzione On Error, anche in questo caso interverrebbe per evitare il blocco, ma colui che sta lavorando e aspetta il risultato di un operazione, non vede soddisfatta la sua richiesta, e non capisce il motivo. Imputa subito la responsabilità al programma,senza pensare a cosa di sbagliato può avere fatto lui. Vediamo di fare un esempio : supponiamo di avere, in una UserForm, delle textbox nelle quali inseriremo dei valori da moltiplicare, e in un'altra textbox, vogliamo il risultato. Useremo l'evento Click di un commandbutton per attivare l'esecuzione del codice, queste le istruzioni:

Private Sub CommandButton1_Click

TextBox3 =  (TextBox1)  *  (TextBox2)

End Sub

Apriamo la nostra Userform, scriviamo nella textbox1 un valore (18O) (ho scritto il numero 18 seguito dalla o maiuscola, al posto dello zero), nella textbox2 un'altro valore (12)

Appena lanciamo l'esecuzione, apparirà però un messaggio di errore: Errore di run-time 13; Tipo non corrispondente.

Clicchiamo sul pulsante Debug, e ci ritroviamo nell'editor di visual basic, dove ci viene evidenziata la riga dell'istruzione che ha causato l'errore :

L'errore in questo caso, è causato dal valore inserito nella textbox1, che non è un numero, ma, per una distrazione che accade spesso, una parte è un numero (18) e parte è una lettera dell'alfabeto (O). Excel non può eseguire una moltiplicazione se i valori non sono solo numeri. Questo, ovviamente è un esempio, ma che evidenzia la necessità di proteggere le nostre applicazioni non solo da errori di compilazione di codice, ma da quegli errori che si possono verificare nell'uso del programma. Inserendo quindi l'istruzione On Error nella nostra routine, avremmo evitato l'intervento del Debugger con conseguente chiusura della form (premendo il pulsante "Fine"), o vederci catapultati nell'editor con la sottolineatura della riga che ha generato l'errore (premendo il pulsante "Debug"). In tutti e due i casi perderemmo eventuali dati già scritti sulla form. Una modifica all'esempio precedente, con l'inserimento di On Error, quindi sarebbe questa :

Private Sub CommandButton1_Click
On Error Resume Next
TextBox3 = (TextBox1) * (TextBox2)
Resume
End Sub

e otterremo di non far comparire la finestra del Debugger con la segnalazione dell'errore, e la conseguente uscita dalla form.

Non avremmo però neppure ottenuto il risultato della moltiplicazione nella textbox3, perchè si sarebbe interrotta l'esecuzione del codice (grazie all'istruzione On Error.).  E' evidente che un errore di scrittura come quello esemplificato, può lasciare perplessi e il "povero pellegrino", rimane lì a fissare non individuando subito il perchè non viene il risultato. E' qui che possiamo "gestire" il verificarsi di un errore, sfruttando l'istruzione  Err.Number  . (Premesso che un errore del genere può essere intercettato prima che si verifichi, usando la funzione IsNumeric con il ciclo If...Then) ma stiamo vedendo come usare una gestione di errori, e quindi proseguendo con l'esempio sopra, potrebbe essere questa una giusta compilazione che preveda l'uso della funzione Err.Number :

 

Private Sub CommandButton1_Click
On Error Resume Next
TextBox3 = (TextBox1)  *  (TextBox2)
If Err.Number = 13 Then
MsgBox "Il valore inserito non è un numero"
End If
Resume
End Sub

Cosa succede quando il "pellegrino" lancia l'istruzione dopo aver scritto in una delle due textbox un valore errato? Parte l'esecuzione delle istruzioni, viene trovato che uno dei due dati non è un numero, si genera l'errore n. 13, l'esecuzione continua fino alla riga If Err.Number = 13 Then che significa : SE il numero dell'errore è uguale a 13 ecc., mostra il messaggio che l'avvisa di correggere un valore, e poi termina l'esecuzione fino a End Sub, senza bloccare niente nè uscire dalla Form, avvisando inoltre che qualcosa è scritto male.

Un consiglio, quando si lavora usando valori numerici, sarebbe opportuno far conoscere al codice, che tipi di numeri si stanno trattando, assegnando che "TIPO" di dati (numeri) una TextBox conterrà.

Questo lo si può fare dimensionando delle variabili con dichiarazione del "tipo" di variabile, esempio:

Dim X, Y, Z As Long 
X = TextBox1
Y = TextBox2
Z = TextBox3
Z = X * Y

Oppure, (e scriveremo di meno) sarà sufficiente anteporre alla definizione dell'oggetto (textbox) una definizione del tipo di dati numerici, per esempio: Integer, Long, Currency, Decimal, Single, Double  ed altri, usando le Funzioni di conversione relative. Esemplificando 

CInt(TextBox1)        -    per numeri interi

CDbl(TextBox1)      -    per numeri decimali

Val(TextBox1)         -    riconosce numeri all'interno di stringhe

CCur(TextBox1)      -    Per formato valuta (e quindi anche con decimali)       

Usate la Guida in Linea per prendere confidenza con questi concetti e leggere le caratteristiche di ognuna. Nell'indice della Guida, scrivete "funzione", premete il pulsante "Cerca", e nella finestra "Selezionare un argomento", cercate "Funzioni di conversione del tipo", selezionate questa voce, e sulla destra appariranno le spiegazioni. Ricordo che la Guida è diversa se si chiama dall'editor di visual basic o dal foglio di lavoro. A voi in questo caso, serve quella dell'editor.