Paolo Guccini
© Apogeo - IF - Idee editoriali Feltrinelli s.r.l.
Socio Unico Giangiacomo Feltrinelli Editore s.r.l.
Il presente file può essere usato esclusivamente per finalità di carattere personale. Tutti i contenuti
sono protetti dalla Legge sul diritto d'autore.
Nomi e marchi citati nel testo sono generalmente depositati o registrati dalle rispettive case
produttrici.
Finalità
Questo libro ha un taglio pratico e ha l’obiettivo di indicare con semplicità le tecniche da
adottare nell’ultilizzo delle macro, per ottenere rapidamente i risultati desiderati. L’aspetto più
importante è comprendere che le immense potenzialità delle macro possono essere sfruttate
iniziando con la creazione di quelle più semplici, per aumentarne progressivamente la complessità
fino a realizzare macro (anche dette funzioni o routine) molto articolate, in grado di aprire un
documento, cercare un’informazione, chiedere all’utente cosa fare e agire di conseguenza.
NOTA Nella versione 2010, la procedura è analoga, mentre per la versione 2007 si agisce attraverso il pulsante
Office, ovvero quel pulsante tondo posto in altro a sinistra che ha sostituito il menu File, si accede a un menu in cui
è presente il pulsante Opzioni di Excel, che apre una finestra in cui occorre selezionare, dall’elenco di sinistra, la
voce Centro protezione. Il pulsante Impostazioni Centro protezione consente di accedere alla finestra successiva,
all’interno della quale si può definire il livello di sicurezza.
Figura 1.2 Un clic sul pulsante Opzioni di Excel visualizza la finestra che consente di gestire varie configurazioni.
Figura 1.3 In questa finestra è possibile definire il comportamento che Excel terrà quando viene aperta una cartella
contenente macro.
La finestra Centro protezione ha un elenco a sinistra in cui sono presenti diverse voci (Figura
1.3) che consentono di configurare altrettanti insiemi di parametri relativi alla sicurezza e alla
privacy: quella riguardante il livello di sicurezza è Impostazioni macro, che consente di scegliere
quattro diversi livelli, elencati di seguito.
Disattiva tutte le macro senza notifica: è il massimo livello di sicurezza, in cui ogni macro
viene disattivata senza avvisare l’utente. In questo modo nessuna macro funzionerà, riducendo
drasticamente ogni rischio di infezione da virus basati sulle macro.
Disattiva tutte le macro con notifica: ogni volta che viene aperto un documento Excel
contenente macro, sarà visualizzato un messaggio per chiedere se si preferisce attivare o
disattivare le macro contenute. Questa scelta rappresenta un eccellente compromesso tra
sicurezza e la possibilità di utilizzare macro, dal momento che viene mantenuto il controllo
sull’apertura di documenti contenenti macro: è l’utente stesso che decide quale documento
può godere del privilegio di avere le macro attivate. Occorre notare che la scelta non è
permanente: ogni volta che lo stesso documento viene aperto, l’utente riceverà la medesima
richiesta di conferma.
Disattiva tutte le macro tranne quelle con firma digitale: le macro possono contenere una
firma digitale, una sorta di identificativo univoco di colui che le ha create. Questa scelta non
è attualmente una delle più convenienti poiché le macro non hanno quasi mai questa firma e
quindi vengono immediatamente disattivate.
Attiva tutte le macro: questa selezione è utilizzabile solo su un computer che non è esposto a
rischi di virus, in quanto ogni documento che viene aperto gode della facoltà di eseguire
automaticamente le macro contenute al suo interno; quindi se esso contiene un virus che il
software antivirus non ha rilevato, il computer ne verrà infettato.
Per chi vuole realizzare e utilizzare macro, la scelta più conveniente è Disattiva tutte le macro
con notifica. Dopo avere fatto clic su OK ed essere tornati al foglio di Excel, è possibile
occuparsi della realizzazione della prima macro.
Avviare il registratore
Il registratore di macro si avvia mediante la voce Visualizza della barra multifunzione (la
versione 2007 utilizzava il menu Sviluppo/Registra), che, come ultimo elemento, ha il gruppo
Macro nel quale appare un pulsante composto da due parti: il pulsante vero e proprio con la sua
icona e, immediatamente sotto, la scritta Macro: essa è in realtà un secondo pulsante che attiva un
menu (Figura 1.4) nel quale va selezionata la voce Registra Macro.
Figura 1.4 Il menu attivabile con la parte inferiore del pulsante Macro, accessibile dalla voce Visualizza della barra
multifunzione.
Verrà visualizzata una finestra (Figura 1.5), che contiene le opzioni illustrate di seguito.
La casella Nome macro: consente di assegnare un nome che renda la macro facilmente
individuabile e aiuti a comprenderne lo scopo.
La casella Tasto di scelta rapida: se la macro che si sta per memorizzare verrà utilizzata di
frequente, allora può essere utile associare a essa una combinazione di tasti basata su
Ctrl+lettera oppure Ctrl+Maiusc+lettera; questa opzione consentirà di eseguirla velocemente
senza utilizzare la finestra di avvio delle macro.
La lista Memorizza macro in: consente di indicare la cartella nella quale la macro sarà
memorizzata. Esistono tre possibilità: la cartella corrente, una nuova che viene
automaticamente creata e quella personale; quest’ultima è la cartella che Excel apre
automaticamente a ogni esecuzione, per cui ogni macro memorizzata al suo interno sarà
sempre visibile e disponibile per essere eseguita su tutti i documenti di Excel.
La casella Descrizione: consente di inserire una nota descrittiva della macro; verrà
visualizzata sulla parte inferiore della finestra utilizzata per richiamare le macro per
l’esecuzione.
Dopo aver fatto clic sul pulsante OK il registratore di macro è attivo e si può iniziare a eseguire
le operazioni che si desidera memorizzare.
Probabilmente può risultare poco o per nulla comprensibile, ma già dai prossimi capitoli
diventerà più chiaro e interpretabile.
Se avete fretta, però, un veloce sguardo può fornire qualche informazione:
la prima riga contiene l’istruzione Sub che indica l’inizio della macro e il nome, ovvero
FormattaAllineaCentroGrassetto12punti;
le successive sono commenti, in quanto il primo carattere è un apice (lo stesso carattere
utilizzato normalmente anche come accento);
With è un’istruzione molto comoda, poiché permette di semplificare la scrittura e lettura dei
programmi, infatti indica che le istruzioni successive fino a End With fanno riferimento alla
stessa entità, in questo caso a Selection, ovvero alla cella o alle celle correntemente
selezionate;
il carattere punto anteposto alle istruzioni indica che l’istruzione è relativa all’entità
precedentemente indicata in With. La riga
.HorizontalAlignment = xlCenter
In questo esempio, l’impiego dell’istruzione With e del carattere punto consente di non dover
ripetere in ogni istruzione il nome Selection.
Il significato è relativamente semplice: l’oggetto Selection ha una proprietà di nome
HorizontalAlignment al quale si deve assegnare il valore xlCenter, ovvero la selezione dovrà avere
In questo capitolo verranno analizzati diversi aspetti, compreso il più semplice e veloce sistema
per realizzare le macro attraverso il registratore, nonché l’utilizzo dell’ambiente di sviluppo di
VBA (Visual Basic for Application) di Excel.
Prima di continuare, è utile indicare alcuni termini che nel corso della trattazione diverranno
familiari.
Istruzione: riga di testo scritta nel linguaggio di programmazione, che consente al
programmatore di definire un’azione, un calcolo o un’operazione che deve essere svolta dal
computer.
Routine: è un’insieme di istruzioni Visual Basic strutturate per ottenere un determinato
risultato o elaborazione; è il termine più corretto per identificare una macro.
Subroutine: sinonimo di routine che veniva un tempo utilizzato per indicare parti di
programma richiamate dalla routine principale; attualmente, non vi è più una distinzione
linguistica tra i due termini. Per chiarezza espositiva, nel seguito della trattazione con il
termine subroutine si farà riferimento a quelle routine che prevedono parametri e di
conseguenza non appaiono tra le macro richiamabili dalla finestra macro.
Funzione: simile alla routine, riceve generalmente valori che elabora per restituire un
risultato. Per esempio, le funzioni trigonometriche quali sen() e cosen() sono funzioni. Si
differenzia dalla routine per il fatto che può essere utilizzata all’interno di un’espressione e
restituisce sempre un valore.
Chiamata: indica l’istruzione che esegue una routine o una funzione.
Programma: è un insieme strutturato di istruzioni abitualmente raggruppate in diverse
subroutine e funzioni, che svolge un compito ben preciso. In ambiente Excel è anche un
termine utilizzato in sostituzione della parola macro.
Modulo: concettualmente simile a un documento, al cui interno si inseriscono i programmi o
una loro parte. La suddivisione di un programma in vari moduli, spesso, è dovuta alla volontà
del programmatore di suddividere in più parti il programma in base a concetti di omogeneità;
per esempio, si può avere un modulo con tutte le funzioni create per eseguire calcoli
finanziari, o con le routine che gestiscono l’accesso ai database, uno con le funzioni a uso
generale, come quelle che eseguono particolari elaborazioni sul testo, e un altro ancora
contenente le routine principali del programma che richiamano quelle contenute negli altri
moduli.
Classe: è un programma che nasce per interagire con altre classi, o programmi, attraverso una
serie di comportamenti, detti metodi, al fine di mettere a loro disposizione funzionalità
collaudate che il linguaggio di programmazione non possiede. È anche dotato di proprietà,
ovvero caratteristiche. Esempi di metodo possono essere la richiesta di stampare i dati che la
classe gestisce, oppure di ordinarli alfabeticamente, mentre esempi di proprietà possono
essere il tipo di carattere o il colore che la classe utilizza per visualizzare i dati.
Metodo: è un’azione che la classe può eseguire; ogni classe è dotata di metodi definiti dal
programmatore, che si dividono in pubblici, ovvero richiamabili dalla classe stessa, da altre
o da altri programmi, e privati, richiamabili solo dalla classe stessa. Il metodo è un insieme
di istruzioni racchiuse tra Sub ed End Sub.
Proprietà: caratteristica di una classe che può essere impostata o acquisita. Essa viene
realizzata utilizzando un insieme di istruzioni racchiuse tra Function ed End Function.
Codice: spesso viene utilizzato come sinonimo d’insieme di istruzioni, funzioni (Function) e
routine (Sub) costituenti il programma. È frequente leggere la frase equivalente: codice
sorgente.
Form: termine per indicare le finestre che vengono costruite dal programmatore utilizzando
gli strumenti messi a disposizione nell’ambiente di Visual Basic Editor.
Controllo: relativamente ai form, i controlli sono gli oggetti che possono essere collocati
all’interno di una finestra, come pulsanti, caselle di testo, caselle di spunta ed elenchi a
discesa.
Debug: attività del programmatore atta a individuare ed eliminare le anomalie che
abitualmente i programmi presentano durante la fase di sviluppo e nel periodo di collaudo; è
la parte più delicata e stressante in quanto, talvolta, gli errori sono difficili da individuare,
soprattutto se il loro presentarsi sembra non seguire regole ma appare casuale e inspiegabile.
IDE (Integrated Developement Environment): acronimo dell’espressione inglese che
definisce, in questo caso, l’ambiente di sviluppo di Microsoft Visual Basic for Excel.
Finestra ancorabile: tipo di finestra i cui trascinamenti producono proposte automatiche di
allineamento ai bordi della finestra che la contiene, o il suo inserimento in particolari
contenitori rappresentati da un bordo più spesso di una normale finestra.
Esecuzione passo passo: è una modalità di debug del programma che viene eseguito non
interamente bensì per ogni singola istruzione; il programmatore deve premere il tasto F8
affinché l’elaborazione proceda. È una tecnica utilizzata per capire in quale sequenza sono
eseguite le varie istruzioni, quando si è in presenza di condizioni o cicli che non si
comportano come atteso.
Punto d’interruzione: istruzione alla quale è stata associata una segnalazione, che appare
graficamente come un pallino rosso alla sua sinistra, e viene interpretata da Visual Basic
Editor come un ordine di sospendere l’esecuzione del programma. Molto spesso i
programmatori vi fanno riferimento con il termine inglese breakpoint.
Ciclo: serie di istruzioni che viene continuamente ripetuta. L’equivalente termine inglese, che
gli sviluppatori di software usano spesso, è loop.
Indentazione: rientranza dal margine sinistro che si utilizza, in quasi tutti i linguaggi, per
identificare visivamente una serie di istruzioni come appartenente a un gruppo particolare
quale, per esempio, un ciclo. Il suo utilizzo non influisce minimamente sul programma e la sua
esecuzione, ma aiuta sensibilmente la lettura e comprensione del programma stesso.
Default: valore predefinito, che viene assegnato automaticamente in mancanza di altre
assegnazioni esplicite. Per esempio, il grigio è il colore di default dello sfondo delle finestre.
NOTA Per indentare rapidamente un intero gruppo di istruzioni è sufficiente selezionarle e premere il tasto Tab; per
ridurre l’indentazione, ovvero per spostare il testo verso sinistra, si utilizza lo stesso tasto tenendo premuto il tasto
Caps lock, cioè quello che raffigura un lucchetto.
La finestra Progetto
La finestra Progetto (Figura 2.1) contiene un elenco in cui sono visibili tutti gli oggetti aperti in
Excel e i loro componenti. Normalmente sono presenti gli oggetti elencati di seguito.
VBAProject (Cartel1): identifica un progetto di VBA, ovvero un insieme di oggetti, e il nome tra
parentesi è quello della cartella in cui esso è memorizzato, in questo caso Cartel1.
Foglio1 (Foglio1): identifica un oggetto di tipo foglio di lavoro contenuto nella cartella il cui
nome appare tra parentesi. Tutti i fogli di lavoro appaiono identificati dalla parola “Foglio”
seguita da un numero, ma è importante non confondere questo con il nome che appare sulla
linguetta nella finestra di Excel e che nella finestra Progetto si trova tra parentesi; per ogni
foglio di lavoro della cartella sono presenti altrettante voci.
Questa_cartella_di_lavoro: indica la cartella Excel, ovvero il file. Nelle precedenti versioni
di Excel era chiamata ThisWorkbook.
NOTA Se le finestre Progetto e Proprietà vengono spostate e diventano autonome dalle altre, acquisiranno la
caratteristica di rimanere sempre in primo piano, ovvero non verranno mai coperte da altre finestre di Visual Basic
Editor.
Figura 2.1 La finestra Progetto. Il numero di oggetti “Fogliox” varia in relazione al numero di fogli contenuti nella cartella.
È importante capire la struttura di questi dati: essi hanno una forma quasi gerarchica; la finestra
Progetto contiene gli oggetti di Excel, come la cartella Cartel2 al cui interno si trovano gli oggetti
Foglio1, Foglio2, Foglio3. Questa struttura è evidenziata dalla rappresentazione grafica:
dall’icona di VBAProject (Cartel2) parte una linea verticale alla quale sono legate le icone dei
fogli.
Se si trattasse di una struttura rigidamente gerarchica, l’oggetto Questa_cartella_di_ lavoro
(ThisWorkbook) non dovrebbe essere allo stesso livello dei fogli di lavoro che contiene, come invece
accade. Questa caratteristica non rappresenta comunque un problema nella creazione delle macro.
Si osservi l’icona a forma di quadrato al cui interno può esserci un più o un meno; facendovi
clic sopra è possibile ampliare o ridurre la lunghezza dell’elenco poiché tali segni aprono o
chiudono la categoria, alla stregua del comportamento adottato dal programma Gestione risorse di
Windows.
Questa finestra è utile per muoversi tra gli oggetti e i moduli presenti nelle cartelle, mentre le
altre finestre visualizzano le informazioni dell’oggetto che viene selezionato in questa.
La finestra Proprietà
La finestra Proprietà visualizza le cosiddette proprietà dell’oggetto che è selezionato, per
esempio l’elemento nella finestra Progetto o un altro oggetto. Per chi non ha esperienza di
programmazione a oggetti è utile anticipare che si tratta di una tecnica che assegna agli oggetti i
comportamenti descritti con le macro; per esempio, per l’oggetto pulsante, alla proprietà Caption
può essere associata la scritta che appare su di esso, oppure la proprietà BackColor, il colore che
esso deve avere.
La finestra Proprietà (Figura 2.2) appare costituita da una griglia composta da due colonne e un
numero di righe e di contenuto che varia in relazione al tipo di oggetto selezionato nella finestra
Progetto. Per esempio, l’oggetto VBAProject ha una sola proprietà mentre Foglio e
Questa_cartella_di_lavoro (ThisWorkbook) ne hanno molte di più.
La finestra è organizzata nel modo seguente:
nella colonna di sinistra appare il nome della proprietà;
nella colonna di destra è visibile il valore assegnato alla proprietà.
Nella parte superiore sono visibili due linguette che servono a modificare il modo di elencare le
proprietà nella griglia:
Alfabetico. Le proprietà appaiono rispettando l’ordine alfabetico;
Per categoria. Le proprietà sono raggruppate per categorie funzionali e, al loro interno,
alfabeticamente. Quando si sceglie questa forma di elencazione, alla griglia viene aggiunta a
sinistra una nuova colonna, che contiene un’icona per gestire il collasso delle proprietà
appartenenti a tale categoria.
Non cambia molto, ma la possibilità di avere le proprietà raggruppate in base al loro scopo si
rivela estremamente utile quando si utilizzano oggetti che ne possiedono molte.
NOTA Il numero di proprietà di un oggetto è stabilito dal suo creatore e si possono incontrare oggetti dotati anche
di centinaia di proprietà.
Nella barra dei pulsanti nel riquadro Progetto (evidenziati in Figura 2.2) sono presenti tre
pulsanti, illustrati di seguito.
Visualizza codice: attiva la finestra Codice dell’oggetto selezionato.
Visualizza oggetto: visualizza l’oggetto selezionato; nel caso di un foglio di lavoro il
controllo passa a Excel, che visualizzerà il foglio di lavoro selezionato.
Espandi/Comprimi cartelle: cambia la modalità di visualizzazione degli oggetti, passando da
una forma strutturata per tipologie a una più lineare, in cui sotto l’oggetto di tipo VBAProject
appaiono gli altri oggetti non raggruppati in base al loro tipo.
La finestra Codice
Solitamente, quando viene creata una macro attraverso il registratore, Excel provvede a
memorizzarla all’interno della cartella che è stata selezionata nell’elenco Memorizza macro in.
Più precisamente, all’interno della cartella viene creato un modulo, ovvero un particolare
documento, che la finestra Codice consente di vedere.
Ogni modulo può contenere una o più macro (oppure nessuna) e il suo contenuto è accessibile e
leggibile attraverso Visual Basic Editor, in quanto le macro sono memorizzate con il linguaggio
VBA. La parte centrale della finestra è costituita da un’area simile al programma Appunti o
Wordpad di Windows, ove è possibile scrivere le macro.
Ogni macro appare separata dalle altre da una linea orizzontale, la quale non possiede alcuna
utilità o valenza se non per il programmatore che, in questo modo, è facilitato e meno distratto nel
suo lavoro.
È anche possibile visualizzare solamente una macro per volta anziché averle tutte visibili e
separate dalla linea. Infatti, utilizzando il pulsante Visualizza routine si impone a Visual Basic
Editor di limitare la visualizzazione alla sola macro al cui interno si trova il cursore; tale pulsante
si trova a sinistra della barra di scorrimento orizzontale della finestra Codice.
La visualizzazione delle altre macro avviene selezionandole dall’elenco posto nella parte
superiore destra della finestra. Per tornare alla modalità di visualizzazione di tutto il modulo, è
sufficiente fare clic sul pulsante Visualizza modulo intero, che è ugualmente collocato nella parte
inferiore sinistra della finestra.
Figura 2.3 Visual Basic Editor con la finestra Codice aperta nella parte sinistra. Si noti il nome corrente della finestra.
NOTA Ogni istanza di Visual Basic Editor di Excel opera solamente sugli oggetti aperti nell’istanza di Excel
utilizzata per lanciarla. In altre parole, se Excel viene eseguito due volte contemporaneamente, si ottengono due
diverse istanze, quindi sarà possibile richiamare Visual Basic Editor da entrambe creandone così due nuove,
ciascuna delle quali potrà accedere e gestire solo gli oggetti dell’istanza di Excel da cui è stata eseguita, salvo che
le macro non vengano memorizzate nella cartella macro personale come indicato nel capitoletto ”Avviare il
registratore”.
Sfruttando questa peculiarità e per non annoiare i lettori che hanno già conseguito un ottimo
livello di conoscenza, verranno presentati di seguito i vari menu e sottomenu che sono specifici di
Visual Basic Editor.
Il menu File
Salva (nome). Consente di salvare le modifiche apportate alle macro.
Importa file. Apre un finestra di dialogo nella quale è possibile indicare un file macro, form o
classi che verranno aggiunti al progetto corrente. Può risultare utile per importare all’interno
di una cartella il lavoro memorizzato in altre cartelle e precedentemente copiato al suo
esterno mediante il menu File/Esporta file.
Esporta file. Consente di estrarre dalla cartella un oggetto di Visual Basic; questa operazione
non elimina l’oggetto contenuto nella cartella, ma ne esegue una copia. Si tratta di una
funzione utile per archiviarlo separatamente, farlo pervenire ad altre persone senza inviare
l’intera cartella e copiarlo all’interno di altre cartelle in modo tale che possano avvalersene
senza che la cartella originaria sia aperta.
Rimuovi (nome). Provvede a eliminare dalla cartella l’oggetto selezionato; si tratta di una
funzione che va impiegata con attenzione in quanto non è possibile annullarla. Comunque,
prima di eseguire la cancellazione, il programma provvede ad aprire una finestra di dialogo
che richiede se si desidera salvarlo in un file separato. Se la risposta è sì, verrà presentata
l’usuale finestra Esporta file analogamente a quanto accade con File/Esporta file.
Stampa. Permette di stampare un form o il programma.
Il menu Modifica
Il menu Modifica è un altro dei menu obbligatori per le applicazioni Windows. Da notare che
molti comandi di questo menu sono attivi solo se la finestra Codice è attiva.
Aumenta rientro. Permette di spostare a destra di quattro spazi le istruzioni evidenziate o la
riga sulla quale è presente il cursore; questo comando risulta particolarmente utile quando si
deve racchiudere un blocco di istruzioni all’interno di altre, quali If oppure With.
NOTA Il numero di caratteri d’indentazione utilizzati dai comandi File/Aumenta rientro e File/Riduci rientro è
personalizzabile attraverso il percorso Strumenti/Opzioni, che apre una finestra nella quale è presente la casella
Rientro tabulazione contenente tale valore.
L’utilizzo della combinazione di tasti Ctrl+J rende estremamente semplice il suo utilizzo,
sostituendo l’uso poco pratico di questo comando. È da notare che l’elenco viene automaticamente
attivato quando si digita un carattere che sintatticamente prevede la successiva presenza di una
proprietà o un metodo, come nel caso del carattere punto.
Elenca costanti. Apre un elenco contenente i valori ammissibili per assegnare un valore
all’oggetto posto a sinistra dell’uguale che precede il cursore.
Informazioni rapide. Apre un riquadro nel quale sono presenti informazioni sulla funzione o
subroutine selezionata nella finestra Codice, riepilogandone le caratteristiche (Figura 2.5).
Informazioni parametri. Apre un riquadro nel quale sono presenti informazioni sulla funzione
o subroutine selezionata nella finestra Codice.
Completa parola. Per sveltire la digitazione delle istruzioni è disponibile questo comando,
che si comporta in maniera analoga al comando Modifica/Elenca proprietà/metodi.
Segnalibri. Permette di marcare una linea in modo da poter tornare celermente a essa. Non è
possibile associare nomi ai vari segnalibri per identificarli e li si può scorrere solamente in
sequenza, avanti e indietro. Essi vengono graficamente rappresentati da un rettangolo azzurro
che appare sul bordo sinistro della finestra Codice. Operativamente, per creare un segnalibro
per una determinata istruzione, si deve portare il cursore su di essa e selezionare Modifica/
Segnalibri/Imposta/rimuovi segnalibro; per rimuoverlo si utilizza la medesima procedura. La
navigazione avviene mediante Modifica/Segnalibri/Segnalibro Successivo e
Modifica/Segnalibri/Segnalibro Precedente. Il percorso Modifica/Segnalibri/Rimuovi
Segnalibri provvede a eliminare tutti i segnalibri esistenti, mentre il testo presente sulle
rispettive linee non viene modificato.
Il menu Visualizza
Il menu Visualizza contiene, tra gli altri, i comandi necessari per aprire alcune finestre utili nella
fase di debug del codice, nonché per fare riapparire le finestre di Visual Basic Editor qualora
siano state chiuse.
Codice. Apre la finestra Codice relativa all’oggetto selezionato nella finestra Progetto.
Oggetto. Visualizza l’oggetto selezionato nella finestra Progetto. Per esempio, se nella finestra
Progetto è selezionato un oggetto di tipo UserForm, questo comando lo visualizzerà.
Definizione. Consente di individuare la posizione ove una variabile è stata definita. Per
utilizzarlo è necessario fare clic sulla variabile e richiamare questo comando, che
visualizzerà l’area ricercata. Questo comando è attivo se lo è anche la finestra Codice.
Ultima posizione. Si comporta come il comando Definizione, ma per ricercare la successiva
posizione nel codice ove la variabile appare rispetto alla posizione attuale.
Visualizzatore oggetti. Apre una finestra nella quale sono elencati tutti gli oggetti e le relative
caratteristiche, in particolare le proprietà, le subroutine, gli eventi. Una caratteristica molto
utile è la possibilità di eseguire ricerche. Per esempio, inserendo la parola color nella casella
posta a sinistra del pulsante raffigurante un binocolo e facendo clic su di esso, il
Visualizzatore oggetti elencherà tutti gli oggetti che contengono un riferimento a tale parola.
Finestra Immediata. Apre una finestra, con le caratteristiche di ancorabilità già viste per
Progetto e Proprietà, che è utilizzata durante il debug di un programma. In particolare, quando
l’elaborazione viene temporaneamente sospesa, è possibile digitare al suo interno comandi
per analizzare i valori delle variabili o delle espressioni, ma anche modificarli attraverso
normali istruzioni in linguaggio Visual Basic (Figura 2.6). Per esempio, sono legittime le
istruzioni:
Print Now()
? Now()
che sono tra loro equivalenti e richiamano la funzione now() che restituisce la data e l’ora del
computer, mentre l’istruzione:
Longitudine = 2
Finestra Variabili locali. Apre la finestra ancorabile Variabili locali nella quale appaiono
tutte le variabili definite o visibili dalla funzione o subroutine attiva.
Finestra Espressioni di controllo. Apre una finestra ancorabile al cui interno è possibile
inserire espressioni che verranno continuamente analizzate, mostrandone il risultato.
Stack di chiamate. Visualizza la finestra ancorabile Stack di chiamate, che contiene un elenco
nel quale appaiono le funzioni e le subroutine che in un dato momento sono attive, ovvero in
esecuzione.
NOTA Questa finestra è fondamentale durante le operazioni di debug: quando il programma raggiunge un punto di
interruzione, infatti, attraverso di essa è possibile comprendere la catena di chiamate in successione delle routine
e funzioni. In tal modo, si può ricostruire il motivo per cui il programma è giunto su questa istruzione e analizzare i
valori delle variabili nelle varie routine e funzioni chiamanti.
Gestione progetti. Apre l’omonima finestra ancorabile, descritta all’inizio di questo capitolo,
che mostra tutti gli oggetti aperti da Excel.
Finestra Proprietà. Apre l’omonima finestra ancorabile, descritta all’inizio di questo capitolo;
il suo scopo consiste nel visualizzare le proprietà dell’oggetto selezionato.
Casella degli strumenti. Apre una barra degli strumenti contenente gli oggetti che possono
essere collocati in un form, come le caselle di testo o i pulsanti.
Ordine di tabulazione. Apre una finestra al cui interno appare un elenco che mostra l’ordine
con cui gli oggetti saranno resi attivi, in sequenza, dal tasto Tab quando la finestra che li
contiene verrà aperta dal programma in esecuzione. L’ordine è normalmente definito
rispettando la cronologia dell’inserimento degli oggetti sulla finestra, ma spesso occorre
intervenire manualmente per modificarlo in base alla logica con cui l’utente vuole avvalersi
dei componenti.
Barre degli strumenti. Contiene un sottomenu attraverso il quale è possibile definire quali
barre degli strumenti si desidera siano presenti all’interno della finestra di Visual Basic
Editor. Più rapidamente, è possibile ottenere lo stesso risultato facendo clic con il tasto
destro sulla barra dei menu o la barra degli strumenti.
Microsoft Excel. Passa al programma Excel senza chiudere o salvare i dati in Visual Basic
Editor. In alternativa a questo comando è possibile utilizzare la combinazione di tasti Alt+F11
oppure fare clic sul pulsante di Excel nella barra delle applicazioni di Windows.
Il menu Inserisci
Il menu Inserisci consente di creare nuovi oggetti all’interno di VBAProject corrente, oppure si
limita a introdurre le parti testuali di apertura e chiusura richieste dalle regole sintattiche. È dotato
di vari comandi.
Routine. Apre una finestra al cui interno è possibile indicarne il tipo; Visual Basic Editor
provvederà a inserire le parole chiave necessarie sostituendosi al programmatore, che ne
beneficia in termini di tempo e contro il rischio di dimenticarne delle parti. Generalmente, i
programmatori esperti preferiscono un approccio più diretto e provvedono a scrivere tutte le
parti a mano.
User Form. Crea un nuovo form senza controlli: il programmatore li inserirà selezionandoli
dalla Casella degli strumenti (Figura 2.7).
Figura 2.7 Dopo averla creata tramite Inserisci/UserForm, il nuovo UserForm appare privo di controlli.
Modulo. Crea un nuovo modulo vuoto al cui interno potranno essere inserite routine e
funzioni.
Modulo di classe. Crea un nuovo modulo vuoto al cui interno potranno essere creati i metodi
e le proprietà della nuova classe.
File. Apre una finestra di dialogo che permette di inserire in VBAProject corrente un file
contenente programmi in Visual Basic.
Il menu Formato
Il menu Formato fornisce gli strumenti necessari a gestire il posizionamento e l’allineamento
degli oggetti nei form tramite alcuni comandi.
Allinea. Dispone di un sottomenu nel quale sono presenti tre comandi per l’allineamento
orizzontale, tre per quello verticale e un altro per allineare lo spigolo superiore sinistro
dell’oggetto selezionato al più vicino punto della griglia.
Rendi uguale. Permette di uniformare le dimensioni dei controlli presenti su un form agendo
sulle loro dimensioni: altezza, larghezza o entrambe. L’impiego è semplice: si selezionano i
controlli di cui si desidera modificare le dimensioni e, come ultimo, l’oggetto a cui fare
riferimento per impostare le dimensioni dei precedenti; essi vengono distinti dal colore delle
maniglie: nere per gli oggetti che saranno ridimensionati, bianche per quelli di riferimento.
Adatta. Modifica le dimensioni di tutti i controlli selezionati affinché la superficie che
occupano nella finestra sia proporzionata al testo che contengono.
Adatta alla griglia. Modifica le dimensioni di tutti i controlli selezionati affinché gli spigoli
coincidano con i punti della griglia a essi più vicini. Per questi scopi si può anche agire
direttamente sulle rispettive proprietà, individuabili nel gruppo Posizione della scheda Per
categoria della finestra Proprietà.
Spaziatura orizzontale. Mette a disposizione un sottomenu che consente di modificare la
distanza orizzontale tra due controlli.
Spaziatura verticale. Mette a disposizione un sottomenu che consente di modificare la
distanza verticale.
Centra nel form. Attraverso i suoi sottomenu, permette di spostare i controlli selezionati in
una posizione centrale del form rispetto al suo asse orizzontale o verticale.
Disponi pulsanti. Questo comando è utile per spostare in modo automatico più pulsanti sul
lato destro oppure inferiore del form, al fine di creare un’omogeneità visiva.
Raggruppa. Permette di definire più controlli come facenti parte di un gruppo, ottenendo il
vantaggio di poter agire su tutti contemporaneamente senza doverli selezionare
individualmente ogni volta (Figura 2.8). Per disattivare il raggruppamento si seleziona
Formato/Annulla raggruppamento.
Annulla raggruppamento. Elimina la definizione di raggruppamento assegnata a più controlli
di un form attraverso Formato/Raggruppa.
Ordina. Serve per definire i piani di visualizzazione degli oggetti quando essi occupano la
stessa area della finestra sovrapponendosi. I controlli in primo piano sono quelli che
appaiono sopra agli altri, coprendo i sottostanti. I sottocomandi Porta Avanti e Porta Indietro
sono utili quando vi sono più controlli nella stessa area, in quanto permettono di agire sul
controllo selezionato spostandolo a un livello superiore o inferiore rispetto a quello
occupato.
Il menu Debug
Il menu Debug è probabilmente quello più utilizzato dagli sviluppatori che si avvalgono di
Visual Basic Editor, in quanto mette a disposizione gli strumenti per analizzare e modificare il
codice al fine di risolvere tutti quei piccoli e grandi problemi che si incontrano durante la
realizzazione di nuovi programmi, o anche semplicemente arricchendo quelli già esistenti di nuove
funzionalità. Esso si compone di vari comandi.
Compila VBAProject. Corrisponde alla richiesta di compilare il progetto corrente, ovvero di
analizzare tutto il programma e i suoi componenti per verificarne la correttezza nel suo
complesso.
Esegui istruzione. Durante l’esecuzione passo passo, questo comando ordina a Visual Basic
Editor di elaborare la prossima istruzione. Nel caso corrisponda a una chiamata a un’altra
routine o funzione, l’esecuzione passo passo viene applicata anche a essa; se invece si
desidera che venga elaborata interamente senza questa modalità, che però deve essere
riapplicata quando termina la routine chiamata ritornando dall’istruzione successiva a quella
corrente, allora si utilizza il comando Esegui istruzione/routine. Normalmente, invece di
selezionare questo menu, si preferisce premere il tasto F8.
Esegui istruzione/routine. Nell’elaborazione passo passo, permette di evitare che essa sia
applicata alle routine o funzioni richiamate da quella corrente. Si utilizza questo comando in
sostituzione di Esegui istruzione quando la routine che sta per essere chiamata è già stata
testata, o si è sicuri che essa non sia la causa del problema in questione. Per esempio, se
viene richiamata una routine già collaudata da lungo tempo è inutile applicarle l’esecuzione
passo passo; infatti, la probabilità che l’origine dell’errore ricercato vi sia contenuto è molto
scarsa, per cui è meglio concentrarsi sulle parti di codice più recenti.
Esci da istruzione/routine. Disattiva temporaneamente l’esecuzione passo passo fino a quando
non termina l’elaborazione dell’attuale routine o funzione; a quel punto viene ripristinata la
modalità passo passo. Questo sistema è utile quando si è entrati per errore, per esempio con
il tasto F8, in una routine che non si desidera analizzare oppure si è già visto ciò che si
voleva controllare e si preferisce tornare al punto in cui essa è stata richiamata, riprendendo
l’elaborazione passo passo.
Esegui fino al cursore. Disattiva temporaneamente l’esecuzione passo passo, permettendo a
Visual Basic di eseguire tutte le istruzioni che incontra fino a quando non raggiunge
l’istruzione sulla quale è stato dato questo comando, che è simile alla creazione di un punto di
interruzione temporaneo. Da notare che, se durante l’elaborazione vengono incontrate
istruzioni con punti di interruzione, essa verrà interrotta anche se non è stata ancora raggiunta
l’istruzione marcata con questo comando. Si riscontra la sua utilità quando, per esempio, si
stanno analizzando porzioni di codice che contengono cicli e non si desidera premere il tasto
F8 per tutta la loro durata; infatti, Esegui fino al cursore sospende la modalità passo passo
fino a quando non viene raggiunta l’istruzione desiderata.
Aggiungi espressione di controllo. Permette di impostare un’espressione o una condizione che
Visual Basic Editor analizza e della quale mostra il risultato nella finestra Espressioni di
controllo. È estremamente comoda per verificare il risultato di determinate variabili o
espressioni durante l’esecuzione del programma in modalità passo passo (Figura 2.9). Per
esempio, se vi sono variabili la cui somma deve sempre risultare 100 e il programma
presenta come difetto il non rispetto di questa regola, allora si può inserire l’espressione di
somma di tutte le variabili nella finestra Espressioni di controllo, in modo da poter
controllare costantemente se il risultato è sempre quello atteso ed eventualmente quando è
cambiato.
Figura 2.9 La finestra Aggiungi espressione di controllo.
Modifica espressione di controllo. Può capitare di voler modificare quanto inserito nella
finestra Espressioni di controllo: in tal caso si può utilizzare questo comando dopo aver
selezionato la voce da modificare.
Controllo immediato. Serve ad analizzare estemporaneamente il valore di una variabile, di
un’espressione o di una condizione evitando di creare un’espressione di controllo
nell’apposita finestra. Questo comando utilizza il testo selezionato nella finestra.
Imposta/rimuovi punto di interruzione. Serve per assegnare un punto d’interruzione
all’istruzione sulla quale è presente il cursore. Quando Visual Basic la incontrerà durante
l’esecuzione del programma, si fermerà evidenziandola. I programmatori utilizzano questo
sistema per iniziare l’analisi passo passo del programma quando esso raggiunge determinati
punti. L’istruzione alla quale è associato un punto d’interruzione appare con lo sfondo rosso
ed è contrassegnata da un punto rosso alla sua sinistra. Per eliminarlo si utilizza questo stesso
comando.
Rimuovi punti di interruzione. Provvede a eliminare tutti i punti d’interruzione presenti nel
modulo.
Imposta istruzione successiva. Può accadere che durante l’esecuzione passo passo si
individui un errore, ma potrebbe essere preferibile continuare l’esecuzione in quanto frutto di
un lungo periodo di debug che non si vuole perdere. A questo punto si potrebbe alterare la
normale sequenza logica delle istruzioni imponendo a Visual Basic Editor di proseguire
l’elaborazione da un punto diverso da quello attuale: ciò si ottiene facendo clic su tale
istruzione ed eseguendo il comando Debug/Imposta istruzione successiva.
Mostra istruzione successiva. Visualizza qual è l’istruzione successiva che verrà eseguita.
Il menu Esegui
Il menu Esegui è completamente replicato sulla barra degli strumenti Standard in quanto i suoi
comandi sono utilizzati con la massima frequenza.
Esegui Sub/UsersForm oppure Esegui Macro, in funzione del tipo di oggetto selezionato.
Esegue la routine attiva o avvia il form selezionato, altrimenti può aprire la finestra Macro al
fine di consentire al programmatore di indicare quella che desidera sia eseguita.
Interrompi. Permette d’interrompere temporaneamente l’esecuzione della routine. Si rivela
utile nei casi in cui il programma entri in cicli lunghi e si desideri vedere che cosa stia
accadendo.
Ripristina. Interrompe definitivamente l’esecuzione cancellando dalla memoria tutti i valori
associati alle variabili.
Modalità progettazione oppure Esci da modalità progettazione. Permette di attivare e
disattivare la modalità di progettazione.
Quando essa è attiva, non vengono elaborati gli eventi associati ai controlli né eseguito alcun
codice del progetto.
Il menu Strumenti
Il menu Strumenti mette a disposizione alcune opzioni utili per i progetti che devono essere
condivisi con altre persone o comunque distribuiti, in cui si desidera mantenere il segreto sulle
tecniche di programmazione o, comunque, rendere inaccessibile il codice. Dispone di alcuni
comandi.
Riferimenti. È una finestra contenente un elenco nel quale sono visibili tutti i software
installati sul computer e che possono essere utilizzati come risorse in un programma Visual
Basic. Per renderli disponibili è necessario attivare la casella di spunta che precede il nome
dell’elemento (Figura 2.10). Le loro caratteristiche potranno essere analizzate con il
Visualizzatore oggetti, che si attiva mediante Visualizza/Visualizzatore oggetti, mentre per
poterli inserire nei form è necessario inserirli nella Casella degli strumenti, che si apre
selezionando Visualizza/Casella degli strumenti attraverso Strumenti/Controlli aggiuntivi.
Controlli aggiuntivi. Apre una finestra al cui interno sono elencati tutti i componenti aggiuntivi
relativi a quanto selezionato mediante Strumenti/Riferimenti. Per renderli disponibili nella
Casella degli strumenti si deve attivare la casella di spunta che precede le voci desiderate:
essi prenderanno posto nella scheda attiva al momento in cui questo comando viene eseguito
(Figura 2.11).
Figura 2.10 La finestra Riferimenti. Se presenti voci che iniziano con “MANCA”: indicano dei riferimenti che sono stati
selezionati per essere utilizzati nel progetto corrente, ma essi non sono più disponibili. Questo può accadere quando il
progetto è stato realizzato su un computer diverso da quello attualmente utilizzato oppure se determinati programmi sono
stati disinstallati.
Opzioni. Questo comando apre una finestra nella quale è possibile personalizzare il
comportamento di Visual Basic Editor e alcune sue caratteristiche. Si compone di quattro
diverse schede. La scheda Editor tratta alcune caratteristiche come la gestione del rientro e la
sua dimensione, la visualizzazione separata delle varie routine e il controllo automatico della
sintassi delle istruzioni che vengono digitate nella finestra Codice.
NOTA Per creare nuove schede nella Casella degli strumenti, si deve fare clic con il tasto destro del mouse sopra
uno dei cavalierini in essa visibili e selezionare il comando Nuova pagina; in questo modo apparirà una nuova
scheda che, una volta resa attiva, potrà accogliere i nuovi componenti.
Figura 2.12 Le finestre per l’assegnazione della firma digitale e l’elenco dei certificati ottenuti e utilizzabili per firmare il
programma.
Il menu Aggiunte
Il menu Aggiunte è molto semplice in quanto contiene una sola voce che permette di indicare le
risorse aggiuntive che si desidera siano disponibili in Excel.
Gestione aggiunte. Apre la finestra omonima, nella quale appaiono elencate le aggiunte
disponibili sul computer e se e come devono essere caricate, ovvero rese disponibili a Excel.
Le aggiunte sono identificabili attraverso la loro estensione che può essere .XLAM, XLA,
oppure .XLL. Per una gestione decisamente più comoda e funzionale, è meglio agire
attraverso la barra multifunzione File/Opzioni/Componenti aggiuntivi.
Il menu Finestra
Il menu Finestra si divide in tre parti: la prima contiene gli strumenti per la divisione della
finestra attualmente attiva, la seconda gli strumenti per modificare la visualizzazione di tutte le
finestre aperte, la terza l’elenco delle finestre aperte.
Il menu ?
Il menu ? contiene vari comandi per attivare sistemi di supporto per il programmatore. Alcuni di
essi sono già familiari agli utenti dei programmi Microsoft.
NOTA In genere, le estensioni non appaiono quando si sfogliano le cartelle con Gestione risorse o Risorse del
computer; questo perché l’impostazione di default di Windows prevede che esse siano nascoste all’utente per vari
motivi. Per cambiare tale impostazione si deve fare doppio clic sull’icona Risorse del computer e usare il comando
Visualizza/Opzioni per aprire la finestra Opzioni: al suo interno è presente la scheda Visualizza in cui va disattivata
la casella di spunta Non visualizzare le estensioni per i file registrati.
Figura 2.13 La finestra Opzioni di Excel con parametri di Personalizzazione della barra multifunzione attraverso la quale è
possibile visualizzare il gruppo Sviluppo.
Figura 2.14 La barra multifunzione con il gruppo Sviluppo attivato.
Capitolo 3
Macro e subroutine
Quando si termina la registrazione di una nuova macro, essa è immediatamente pronta per essere
utilizzata. Ma dove viene memorizzata e come può essere modificata? In questo capitolo saranno
analizzati i vari aspetti di contorno della memorizzazione delle macro.
NOTA Le vocali minuscole accentate sono ammesse ma è sconsigliabile impiegarle se si ipotizza che la macro
possa essere utilizzata su versioni internazionali di Excel.
Eliminare un modulo
Per eliminare un modulo si opera all’interno della finestra Progetto, facendo clic con il tasto
destro del mouse sul modulo da eliminare al fine di visualizzare il menu contestuale nel quale è
presente il comando Rimuovi: selezionandolo, si apre una finestra che domanda se si desidera
effettuare un’esportazione del contenuto di tale modulo prima di procedere alla sua cancellazione.
In caso affermativo viene richiesto il nome da assegnare al nuovo file, altrimenti il modulo verrà
eliminato.
Le routine
Ora è arrivato il momento di vedere come scrivere una routine senza il registratore.
End Sub
Tra le righe Sub ed End Sub vengono inserite le istruzioni che dovranno essere eseguite ogni volta
che la routine viene richiamata. Per esempio, la seguente routine apre una finestra di dialogo
utilizzando l’istruzione MsgBox (Figura 3.1), la quale conterrà l’orario acquisito dall’orologio di
Windows, poi, dopo aver fatto clic sul pulsante OK, comparirà un’altra finestra che visualizzerà la
frase “ Nella precedente finestra era visibile l’orario!” :
Sub EsempioConCorpo()
MsgBox Time
End Sub
Il linguaggio
Disporre dell’ambiente di sviluppo non significa automaticamente poter scrivere le routine, in
quanto è indispensabile conoscere anche il linguaggio di programmazione. Questo argomento sarà
oggetto dei prossimi capitoli.
Capitolo 4
Dati e informazioni possono essere suddivisi in categorie in base al loro tipo o natura, quali una
data, un orario, un numero, una parola o un’immagine.
Lo strumento per memorizzare permanentemente un dato è l’archivio, il file o il database, ma
spesso il programma necessita di gestire informazioni la cui vita non supera quella della durata del
programma stesso: per esempio, il pulsante premuto dall’utente in una finestra o se è stato scelto il
fax per stampare un documento. Per questo motivo vengono utilizzate le variabili.
Le categorie a disposizione del programmatore possono essere limitate o numerose in base al
tipo di linguaggio che si utilizza. Di seguito si vedrà, dunque, come VBA identifichi i vari tipi,
ovvero quali parole chiave utilizzare secondo le necessità.
Tipi di variabile
La Tabella 4.1 elenca i tipi di variabile numerica più comuni e le loro caratteristiche.
Tabella 4.1 Caratteristiche dei tipi di variabile numerica più comuni
Numero di
Parola Tipo di
Intervallo cifre
chiave informazione
decimali
Numeri interi
Byte Da zero a 255 Nessuno
positivi
Integer Numeri interi Da –32.768 a +32.767 Nessuno
Long Numeri interi Da –2.147.483.648 a +2.147.483.647 Nessuno
Currency Importo monetario Da –922.337.203.685.477,5808 a +922.337.203.685.477,5807 4
Numeri con
Valori negativi: da –3,402823E38 a –1,401298E-45; valori positivi: da
Single decimali in singola 6
+1,401298E-45 a +3,402823E38
precisione
Numeri con Valori negativi: da –1,79769313486231E308 a –4,94065645841247E-
Double decimali in doppia 324; valori positivi: da 4,94065645841247E-324 a 14
precisione 1,797693134862325E308
Variabili numeriche
Il Visual Basic fornisce varie possibilità per la gestione dei valori numerici, che vanno scelte di
volta in volta in accordo con il genere di informazione da memorizzare. A prima vista, potrebbe
apparire più comodo impiegare tipi generici che vadano bene per qualunque occasione come il
Double, ma in realtà questo è sconsigliabile per vari motivi; per esempio, i tipi che supportano la
parte decimale vengono elaborati a una velocità inferiore di quelli che non la gestiscono, quali
Integer o Byte, oppure, proprio in virtù della loro parte decimale, possono contenere valori che
NOTA Il Visual Basic supporta anche il tipo Decimal che attualmente può essere utilizzato solo in modo indiretto
mediante il tipo Variant; il valore massimo che è in grado di memorizzare è +/–
79.228.162.514.264.337.593.543.950.335, ovvero con 28 cifre significative. È altresì possibile memorizzare valori
decimali con precisione fino alla 27a cifra decimale.
NOTA Il termine “stringa” è utilizzato per indicare informazioni testuali. Per memorizzare un testo all’interno di una
variabile di tipo stringa, occorre racchiuderlo tra virgolette doppie; ovviamente le virgolette non saranno copiate
all’interno della variabile. Per esempio, “questa è una frase” è una stringa correttamente delimitata che può essere
assegnata a una variabile di tipo String o Variant.
Date e orari
Per memorizzare una data o un orario in una variabile è necessario definirla di tipo Date.
Gestire le date
Per assegnare un valore a una variabile di tipo Date mediante un’istruzione, si deve ricorrere a
una sintassi particolare che prevede di racchiudere la data tra una coppia di caratteri #. Per
esempio, il 31 dicembre 1999 può essere rappresentato nel modo seguente:
Dim UltimoDellAnno As Date
UltimoDellAnno = #12/31/1999# ‘ #mese/giorno/anno#
Come si può notare, il formato prevede l’inserimento invertito del mese e del giorno rispetto
alle abituali convenzioni italiane. Per agevolare la digitazione delle date è previsto un sistema
alternativo che verrà immediatamente convertito da Visual Basic Editor nel formato standard. È
possibile digitare le seguenti istruzioni che sono tra loro equivalenti:
Dim dt As Date
dt = #21/03/1980#
dt = #21 March 1980#
dt = #12 march,1980#
Il seguente esempio mostra come viene calcolata la differenza tra due date, la prima contenuta
nella variabile Nascita e impostata con il valore del 21 marzo 1980, la seconda ottenuta dalla
funzione Date() che restituisce la data corrente:
Sub GiorniVissutiFinoAdOggi()
Dim Nascita As Date
Dim GiorniVissuti As Integer
Nascita = #21/03/1980#
GiorniVissuti = Date() – Nascita
MsgBox “Hai già vissuto” & GiorniVissuti & “giorni!”
End Sub
NOTA È importante non utilizzare la funzione Date() come variabile assegnandole un valore, altrimenti verrà
aggiornato l’orologio di sistema in accordo a tale assegnazione: Date() è lo strumento per acquisire e impostare
tale orologio.
OraAttuale = Time()
TempoTrascorso = OraAttuale - #12:00:00 AM# ‘mezzanotte
OreTrascorse = Int(TempoTrascorso * 24)
MinutiTrascorsi = Int((TempoTrascorso * 24 – _
Int(TempoTrascorso * 24)) * 60)
SecondiTrascorsi = (TempoTrascorso * 24 * 60 – _
Int(TempoTrascorso * 24 * 60)) * 60
MsgBox “Tempotrascorso: Ore=” & OreTrascorse & “, _
Minuti=” & MinutiTrascorsi & “, Secondi=” & _
SecondiTrascorsi
End Sub
NOTA La mezzanotte viene indicata con l’orario #12:00:00 AM# che quindi corrisponde alle ore 00:00:00.
Variabili Variant
Variant può memorizzare tutti i tipi di valori ammessi da Visual Basic, infatti il linguaggio si fa
carico di eseguire tutte le operazioni di conversione necessarie.
Per esempio, le assegnazioni di valori di diverso tipo alla stessa variabile sono corrette come
appare nel seguente listato:
Sub EsempioVariabileVariant()
Dim V As Variant
V = “adesso V contiene una stringa”
V = True ‘ ora contiene un valore booleano
V = 123 ‘ in questo modo contiene un intero
V = #12/31/1999# ‘ ora contiene una data
V = “ora contiene nuovamente una stringa”
End Sub
Questi benefici hanno un costo per il programmatore, che perde il supporto del compilatore per
eventuali segnalazioni di errori nell’assegnazione di valori diversi da quelli previsti. Per esempio,
è possibile creare una variabile per memorizzare il risultato di una somma e assegnarle una stringa
per errore.
Sub EsempioDiAssegnazioniIndesiderate()
Dim V As Variant
V = 1 + 2 + 3
V = “stringa”
If V <> 6 Then
MsgBox “la variabile V non contiene il valore 6”
End If
End Sub
Overflow
L’overflow è un termine che in ambito informatico indica una situazione in cui un valore, che si
sta cercando di assegnare, eccede le capacità dell’oggetto di destinazione. Tipicamente, è la
situazione in cui si cerca di dare un valore più grande di quello che la variabile è in grado di
contenere. Per esempio, una variabile di tipo Integer non può contenere il valore 1.000.000 e il
tentativo di assegnazione fallirà:
Sub ErroreDiOverflow()
Dim VarA As Integer
VarA = 1000000
End Sub
NOTA L’errore di overflow viene segnalato esclusivamente durante l’esecuzione del programma (Figura 4.1). In
questo caso è necessario provvedere a dichiarare la variabile utilizzando un diverso tipo, come in questo esempio
i l Long. Per le variabili di tipo stringa a lunghezza costante, l’overflow non è segnalato e i caratteri in eccesso
vengono automaticamente troncati.
Variabili
Il concetto di variabile è presente in tutti i linguaggi di programmazione, che lo implementano
con modalità estremamente simili, per cui la sua comprensione è utile anche per altri linguaggi.
La variabile può essere considerata come una sorta di scatola o contenitore di un’informazione
di un certo tipo, al quale si assegna un nome convenzionale attraverso cui si potrà accedere
all’informazione o sostituirla con un’altra.
In sintesi, una variabile è composta da:
un nome che deve iniziare con una lettera;
la definizione del tipo di informazione da memorizzare;
l’informazione.
Il nome e il tipo sono definiti attraverso l’istruzione Dim, mentre l’informazione viene inserita o
acquisita dalla variabile utilizzando il suo nome convenzionale. Nel listato seguente è mostrato un
esempio di routine che definisce una variabile di nome Var di tipo Integer, alla quale è assegnato il
valore 1; subito dopo l’istruzione If analizza il valore contenuto dalla variabile: se è uguale a 1, si
apre una finestra, tramite l’istruzione MsgBox, che riporta il suo valore:
Sub DefinisceVariabileDiTipoInteger()
Dim Var As Integer
Var = 1
If Var = 1 Then
MsgBox “La variabile di nome ‘Var’ vale 1”
End If
End Sub
Nomi di variabile
Il nome che si assegna alla variabile è soggetto ad alcune regole formali identiche a quelle che
regolano i nomi delle macro, ma a differenza di quest’ultime è possibile assegnare fino a 255
caratteri. Le lettere maiuscole e minuscole sono equivalenti, quindi i nomi EsitoControllo,
Esitocontrollo, ESITOCONTROLLO, esitocontrollo ed EsiToConTrOllo fanno riferimento alla stessa variabile.
una copia del valore di VarStr seguita dalla stringa “! e anche ”, più un’literiore copia della
stringa VarStr; vale a dire “questa e’ una stringa! e anche questa e’ una stringa”.
dove nomevariabile rappresenta il nome da assegnare alla variabile mentre tipo corrisponde a una
delle parole chiave che identificano il tipo di dati che essa dovrà contenere. All’inizio di questo
capitolo sono stati riportati alcuni esempi per illustrare come si dichiarano le variabili dei vari
tipi.
Generalmente le istruzioni Dim costituiscono le prime istruzioni di ogni routine.
Call SecondaRoutine
A = 2
End Sub
Sub SecondaRoutine()
Dim B As Integer
B = 1
A = 1 ‘ errato: A non è visibile in questa routine
End Sub
Per fare in modo che la variabile A sia visibile a entrambe le routine, va dichiarata all’esterno di
queste, facendola divenire una variabile di modulo:
Option Explicit
Sub SecondaRoutine()
Dim B As Integer
B = 1
A = 1 ‘ ok
End Sub
Per fare in modo che una variabile sia accessibile anche dalle routine contenute in moduli
diversi da quello in cui è dichiarata, si utilizzano le variabili pubbliche; per rendere la variabile A
di tipo pubblico, la si deve dichiarare tale all’inizio di un modulo, utilizzando la parola chiave
Public:
Option Explicit
Public A As Integer ‘ accessibile da qualunque routine del _
progetto
Sub RoutineDue()
Dim VarA As Integer
VarA = 2
Call RoutineTre
End Sub
Sub RoutineTre()
Dim VarA As Integer
Var A = 3
End Sub
Type Persona
Cognome As String
Nome As String
DataNascita As Date
End Type
Sub EsempioTipoPersona()
Dim Presidente As Persona
Presidente.Cognome = “Rossi”
Presidente.Nome = “Luca”
Presidente.DataNascita = #12/31/1965#
End Sub
Si può vedere che la routine EsempioTipoPersona crea la variabile Presidente di tipo Persona e assegna
valori alle tre variabili membro, applicando la sintassi obbligatoria per questi casi. Nel seguente
esempio sono definiti i tipi Persona e CoppiaSposata, mentre la routine EsempioTipiDefinitiDalProgrammatore
crea una variabile di tipo CoppiaSposata e assegna valori alle variabili membro Marito e Moglie. Poiché
le variabili membro sono di tipo Persona, che è costituito da altre variabili membro, l’assegnazione
della stringa “Rossi” alla variabile Cognome della variabile Marito della variabile Prossimi-
InLunaDiMiele richiede che siano tutte indicate separandole con un punto:
Option Explicit ‘ inizio del modulo
Type Persona
Cognome As String
Nome As String
DataNascita As Date
End Type
Type CoppiaSposata
Marito As Persona
Moglie As Persona
End Type
Sub EsempioTipiDefinitiDalProgrammatore()
Dim ProssimiInLunaDiMiele As CoppiaSposata
ProssimiInLunaDiMiele.Marito.Cognome = “Rossi”
ProssimiInLunaDiMiele.Marito.Nome = “Luca”
ProssimiInLunaDiMiele.Marito.DataNascita = #12/31/1965#
ProssimiInLunaDiMiele.Moglie.Cognome = “Bianchi”
ProssimiInLunaDiMiele.Moglie.Nome = “Gabriella”
ProssimiInLunaDiMiele.Moglie.DataNascita = #1/1/1970#
End Sub
Sub EsempioConWith()
Dim ProssimiInLunaDiMiele As CoppiaSposata
With ProssimiInLunaDiMiele
.Marito.Cognome = “Rossi”
.Marito.Nome = “Luca”
.Marito.DataNascita = #12/31/1965#
.Moglie.Cognome = “Bianchi”
.Moglie.Nome = “Gabriella”
.Moglie.DataNascita = #1/1/1970#
End With
End Sub
Inoltre è possibile annidare istruzioni With all’interno di altre With, come nel listato seguente che
è equivalente a quello visto in precedenza:
Sub EsempioConDoppioWith()
Dim ProssimiInLunaDiMiele As CoppiaSposata
With ProssimiInLunaDiMiele
With .Marito
.Cognome = “Rossi”
.Nome = “Luca”
.DataNascita = #12/31/1965#
End With
With .Moglie
.Cognome = “Bianchi”
.Nome = “Gabriella”
.DataNascita = #1/1/1970#
End With
End With
End Sub
NOTA Un errore ricorrente nell’utilizzo delle variabili basate sui tipi definiti dal programmatore consiste
nell’impiegare il nome del tipo al posto di quello della variabile (Figura 4.2). Per esempio, l’istruzione:
CoppiaSposata.Marito.Cognome = “Rossi”
NOTA è errata perché CoppiaSposata è un tipo (creato con l’istruzione Type) e non una variabile (creata con
l’istruzione Dim). Similmente, la seguente istruzione risulta errata perché si fa uso del tipo Persona al posto della
variabile Marito (Figura 4.3).
ProssimiInLunaDiMiele.Persona.Cognome = “Rossi”
Figura 4.3 Persona è un tipo e non una variabile membro di ProssimiInLunaDiMiele, quindi viene segnalato un errore.
Matrici o array
Le matrici o array sono strumenti che affiancano le variabili e si rivelano estremamente utili in
molteplici situazioni. Possono essere considerati come variabili in grado di memorizzare un
determinato numero di valori dello stesso tipo. Alle matrici si affianca il concetto di indice,
ovvero un numero o un’espressione numerica che consente di identificare ogni elemento della
matrice. Nella sintassi di Visual Basic, l’indice figura va racchiuso tra parentesi tonde,
immediatamente dopo il nome della matrice.
Le seguenti istruzioni rappresentano esempi sintatticamente corretti dell’uso degli indici relativi
alla matrice di stringhe Colori:
Dim Colori (10 * 4 + 1) As String
Dim i As Integer
Colori(1) = “Azzurro”
Colori(1) = Colori(1) & “!”
Colori(1+1) = “Rosso!”
i = 2
Colori(i + 1) = Colori(i)
NOTA Il valore utilizzato come indice nell’istruzione Dim per creare le matrici non è esattamente corrispondente al
numero complessivo di elementi che la matrice può contenere, in quanto dipende dalle impostazioni definite
attraverso l’istruzione Option Base; in questo caso, si potrebbe parlare con maggiore esattezza dell’indice
definendolo come l’ultimo elemento ammissibile per la matrice, ma sotto il profilo didattico ciò risulta fuorviante.
Facendo un parallelo con le cartelle di Excel, se un foglio di lavoro può essere facilmente
considerato come una matrice bidimensionale, la loro successione può essere considerata come
un’ulteriore dimensione, ottenendo una matrice a tre dimensioni: foglio, colonna e riga. La
dichiarazione di una matrice di 2 × 3 × 4 elementi viene dichiarata mediante la seguente istruzione:
Dim Matrice(2, 3, 4) As Integer
Figura 4.4 Il numero di indici utilizzati per indicare un elemento è diverso dalle dimensioni della matrice.
Nel caso nella routine venisse utilizzata la matrice Matrice impiegando un numero di indici
diverso da quello utilizzato nella sua creazione, Visual Basic lo segnalerebbe con un’apposita
finestra (Figura 4.4).
La Figura 4.5 mostra la finestra Immediata che stampa i valori restituiti dalla matrice.
Le costanti
Le costanti sono valori inseriti nel programma che non devono essere modificati e sono
utilizzate con un nome convenzionale definito dal programmatore all’atto della loro dichiarazione.
Il rapporto tra le variabili e le costanti è stretto solo in apparenza, ma può aiutare a costruire un
parallelo: la differenza sostanziale risiede nel fatto che il valore assegnato a una variabile è
modificabile durante l’esecuzione del programma (rispettando sempre le regole di vita e
visibilità), invece il valore assegnato a una costante non può essere modificato nel corso
dell’esecuzione del programma, per cui rimane costante.
Per esempio, si potrebbe creare una variabile di nome PiGreco e assegnarle il valore
3,1415926535897932, ma potrebbe accadere di scrivere erroneamente un’istruzione che ne
modifica il valore e, una volta eseguita, altererebbe tutti i calcoli che utilizzassero tale variabile
all’interno di quel programma. Invece, se venisse definita una costante con lo stesso nome e lo
stesso valore, ogni istruzione che tentasse di modificarla causerebbe una segnalazione di errore
(Figura 4.6).
Figura 4.6 Il programma ha tentato di modificare il valore di una costante.
Può anche accadere di incontrare forme più sintetiche di dichiarazione nelle quali non viene
indicato il tipo, quindi sarà il compilatore a decidere quale sia più corretto utilizzare in base al
valore indicato; la seguente istruzione creerà una costante il cui tipo sarà Double:
Const PiGreco = 3.14159265358979
Di seguito sono mostrati alcuni esempi di definizione di costanti, il cui contenuto è mostrato
nella Figura 4.7:
Option Explicit
Const TitoloApplicazione = “Questo e’ il mio programma”
Const VersioneProgramma = “3.11 Beta”
Const TitoloFinestaPrincipale = TitoloApplicazione & “_
“ & VersioneProgramma
Const DataDiScadenza = #12/31/2009#
Const OrarioFissatoComeInizio = #8:00:00 AM#
Figura 4.7 La finestra Variabili locali mostra il contenuto delle costanti di una routine durante la fase di di debug.
È interessante osservare che le costanti possono essere definite tramite l’impiego combinato di
altre costanti, come mostrato nell’esempio precedente.
Per vedere quali siano le costanti disponibili si può ricorrere al visualizzatore di oggetti tramite
Visualizza/Visualizzatore di oggetti e, digitando la parola constants nella casella Testo da cercare,
si ottiene un elenco di tutte le costanti disponibili.
NOTA Il prefisso xl oppure vb identifica l’ambito d’impiego della costante: xl indica costanti di oggetti di Excel
mentre vb è relativo a costanti del linguaggio. Ne consegue che qualunque programma che utilizzi le costanti con
prefisso xl è orientato a gestire Excel.
Capitolo 5
Gli operatori
Ogni linguaggio di programmazione utilizza alcuni caratteri per indicare i vari operatori che è in
grado di gestire.
Operatori matematici
Gli operatori matematici sono quelli che indicano le operazioni matematiche e sono:
+: addizione;
–: sottrazione;
*: moltiplicazione;
/: divisione;
\: divisione con restituzione della sola parte intera;
^: elevazione a potenza.
NOTA Non sono disponibili le parentesi quadre e graffe per definire i livelli multipli di priorità nei calcoli, ma si
ricorre all’uso ricorsivo di parentesi tonde, per esempio 1 * (2 / (3 + 4)).
Somma e sottrazione
La somma avviene rispettando le usuali regole matematiche di precedenza degli operatori
prioritari quali la moltiplicazione e la divisione. Un esempio di utilizzo dell’operatore di somma è
il seguente:
a = b + c + 1
È utile riportare un’osservazione sulle somme tra addendi di tipo diverso: se il primo addendo è
di tipo Single e il secondo di tipo Long, il risultato sarà di tipo Double. Se il risultato dovrà essere
memorizzato in una variabile di tipo Variant, essa assumerà internamente il tipo Double , altrimenti il
risultato sarà convertito per accordarsi al tipo della variabile e, se essa non potrà contenerlo,
verrà generato un errore di overflow. (L’operatore + è utilizzato anche per concatenare le
stringhe.)
Moltiplicazione e divisione
La moltiplicazione non presenta particolarità, mentre la divisione si presta a una
considerazione, in quanto il Visual Basic fornisce tre strumenti:
l’operatore di divisione /;
l’operatore di divisione con restituzione della parte intera che tralascia la parte decimale \;
l’operatore Mod che restituisce la sola parte decimale della divisione.
Per evidenziare la differenza, nella Tabella 5.1 sono riportati alcuni esempi dell’utilizzo di tali
operatori.
Tabella 5.1 I vari tipi di divisione a confronto
Dividendo Operatore Divisore Quoziente
11 / 4 2,75
11 \ 4 2
11 Mod 4 3
Operatore di assegnazione =
L’operatore di assegnazione permette di assegnare un valore a una variabile o a una proprietà di
un oggetto.
Il seguente frammento di codice contiene due esempi di assegnazione: il primo assegna il testo
“Questo è il testo che compare sul pulsante” a una stringa, il secondo assegna il valore di tale stringa
alla proprietà .Caption di un pulsante di nome CommandButton1, presente nell’UserForm a cui appartiene
questo frammento:
Dim Str As String
Str = “Questo è il testo che compare sul pulsante”
CommandButton1.Caption = Str
NOTA L’operatore di assegnazione coincide graficamente con quello di confronto di uguaglianza. Ciò non causa
generalmente nessuna confusione nel programmatore che si abitua con una certa rapidità a riconoscerli e
distinguerli nel loro significato. L’unico aspetto che lascia momentaneamente confuso chi non ha mai avuto
esperienze di sviluppo software è proprio il carattere uguale come operatore di assegnazione, in quanto si tende a
considerare l’uguale (=) un’asserzione di eguaglianza tra il valore posto alla sua destra e quello alla sua sinistra: si
tratta di una normale perplessità originata da quanto appreso sui banchi di scuola.
Operatori di confronto
Gli operatori di confronto vengono utilizzati per verificare condizioni e sono riportati nella
Tabella 5.2.
Tabella 5.2 Operatori di confronto
Operatore Simbolo Esempio
Minore < a<b
Minore o uguale <= a <= b
Uguale = a=b
Diverso <> a <> b
Maggiore > a>b
Maggiore o uguale >= a >= b
L’operatore Is
L’operatore Is viene utilizzato per verificare se due variabili di tipo Object indicano lo stesso
oggetto. Il seguente listato contiene una routine che utilizza due variabili di nome o1 e o2 : alla
prima viene assegnato un riferimento all’oggetto di nome ThisWorkbook e la successiva istruzione
MsgBox consente di osservare il risultato del test Is applicato a queste variabili.
Successivamente, anche la variabile o2 viene impostata con il riferimento dello stesso oggetto di
o1 , quindi dal test o1 Like o2 si otterrà il risultato True:
Sub EsempioOperatoreIs()
Dim o1 As Object
Dim o2 As Object
Set o1 = ThisWorkbook
MsgBox o1 Is o2 ‘ l’op. “Is” restituisce False
Set o2 = ThisWorkbook
MsgBox o1 Is o2 ‘ l’op. “Is” restituisce True
End Sub
Operatori logici
Se gli operatori di confronto permettono di mettere in relazione due valori tra loro; gli operatori
logici, descritti di seguito, vengono utilizzati per costruire test complessi basati su più relazioni.
And. Restituisce il valore True se il risultato della valutazione delle condizioni, poste alla sua
destra e alla sua sinistra, è per entrambe True, altrimenti restituisce il valore False.
Or. Restituisce il valore True, se il risultato della valutazione di almeno una delle condizioni
A differenza della precedente condizione, essa sarà considerata vera se il valore di a è minore
di b oppure se il valore di c è maggiore di d: non importa che entrambe siano vere, però se
entrambe sono false allora il risultato che si otterrà è False. L’operatore Not permette di invertire il
risultato booleano che si ottiene da una condizione. Per esempio, l’istruzione:
If Not RigaCorrente = 65536 Then
è composta da un test che verifica se il valore della variabile RigaCorrente è uguale al numero
65536; il risultato viene invertito dall’operatore Not. Per esempio, se la variabile contiene il valore
1 allora la condizione risulterà vera. L’impiego dell’operatore Not viene generalmente evitato dai
programmatori alle prime armi in quanto può essere causa di problemi nello scrivere i test, ma in
talune situazioni si rivela utile per rendere il codice più leggibile; la seguente istruzione valuta il
valore della variabile booleana RaggiuntaFineDelFoglio e risulta decisamente comprensibile a una
prima occhiata:
If Not RaggiuntaFineDelFoglio Then
And e Or in sequenza
Attraverso gli operatori And e Or si possono verificare condizioni molto complesse:
If Mese >= 1 And Mese <= 12 And Giorno >= 1 And Giorno <= _<
31 Then
Poiché è stato utilizzato il solo operatore And non vi sono problemi, mentre l’impiego congiunto
di operatori Not, And e Or richiederebbe una maggiore attenzione in quanto essi vengono valutati
gestendo un ordine di priorità, come avviene con gli operatori matematici.
Per evitare problemi di priorità è possibile ricorrere alle parentesi, le quali possono contribuire
a rendere più chiara la condizione che, comunque, può essere spezzata su più righe:
If (Mese >= 1 And Mese <= 12) And (Giorno >= 1 And Giorno <= 31) Then
oppure
If (Mese >= 1 And Mese <= 12) And _
(Giorno >= 1 And Giorno <= 31) Then
NOTA Le istruzioni che vengono spezzate su più righe impongono di inserire alla fine di ognuna di esse uno spazio
e il carattere underscore, fatta eccezione per l’ultima.
Confronto con operatori logici
La Tabella 5.3 riporta i valori di verità che si ottengono dagli operatori in base alle varie
combinazioni possibili.
Tabella 5.3 Risultati ottenibili dalla combinazione di valori booleani
Sinistra Operatore Destra Risultato
True And True True
False And False False
True And False False
False And True False
True Or True True
False Or False False
True Or False True
Concatenazione di stringhe
È estremamente usuale per i programmatori prendere il valore di due o più stringhe per crearne
una nuova, composta dal loro valore. Allo scopo è disponibile l’operatore &. Un esempio di come
concatenare alcune stringhe, per assegnare il risultato a una variabile di tipo String, può essere
fornito dalla seguente istruzione:
Str = “Questa è una “ & “stringa concatenata”
Str = Str1 & Str2
Str = “Il Signor “ & Cognome & “ ha questo nome di _
battesimo:” & Nome
L’operatore di concatenazione +
Si segnala che l’operatore + può venire utilizzato per concatenare le stringhe in sostituzione
dell’operatore &. Essi non sono perfettamente equivalenti anche se la sintassi è identica; infatti,
l’operatore & richiede esplicitamente di gestire i valori come stringhe e concatenarli, mentre
l’operatore + assume il significato di somma o di concatenazione in relazione al tipo di oggetti su
cui opera, ma non sempre il compilatore è in grado di stabilirne con esattezza il significato
desiderato dal programmatore, per esempio se gli oggetti sono di tipo Variant.
L’utilizzo di Excel porta a una naturale familiarità con le funzioni in quanto esse rappresentano
uno dei punti di forza dei fogli elettronici. Nella programmazione di Excel sono presenti numerose
funzioni, alcune proprie del Visual Basic, altre specifiche del foglio di lavoro. In Visual Basic, la
funzione è un potentissimo strumento per ottenere un’informazione o una conversione ed è
possibile crearne di nuove utilizzando questo stesso linguaggio.
NOTA Nel corso del capitolo, così come nel gergo dei programmatori, l’aggettivo chiamante fa riferimento a una
routine oppure a una funzione che, durante la propria esecuzione, viene temporaneamente sospesa per avviare
un’altra routine o funzione. Quest’ultima viene detta routine o funzione richiamata.
NOTA Prima di utilizzare la parola chiave ByRef è fondamentale comprenderne il significato, che sarà illustrato in
questo stesso capitolo.
È ancora possibile utilizzare l’istruzione Call, gestendo una funzione esattamente come una
subroutine, ma in tal modo si perde il risultato che la funzione restituisce. Nelle seguenti due righe
di codice viene richiamata la funzione Unisci(), ma il suo risultato non viene utilizzato:
Call Unisci(Cognome, Nome)
Unisci(Cognome, Nome)
Do While Right(str, 1) = “ “
str = Mid(str, 1, Len(str) - 1)
Loop
End Function
può essere richiamata dalla seguente routine mediante Call (Figura 6.1) ottenendo un
cambiamento del valore della variabile Testo, in cui la funzione EliminaSpaziSuperflui() avrà eliminato
gli spazi iniziali e finali:
Sub EliminazioneSpazi()
Dim Testo As String
Testo = “ ABC “
MsgBox “1: {“ & Testo & “}”
Call EliminaSpaziSuperflui(Testo)
MsgBox “2: {“ & Testo & “}”
End Sub
Oppure la stessa routine può essere modificata nella riga che chiama la funzione
EliminaSpaziSuperflui() senza ottenere il cambiamento del valore di Testo (Figura 6.2):
Sub EliminazioneSpazi()
Dim Testo As String
Testo = “ ABC “
MsgBox “1: {“ & Testo & “}”
EliminaSpaziSuperflui(Testo)
MsgBox “2: {“ & Testo & “}”
End Sub
Figura 6.2 Richiamare funzioni con ByRef non utilizzando l’istruzione Call comporta un difetto.
As String, posto alla fine della riga, indica che la funzione restituirà un valore di tipo stringa.
Nel corpo della funzione è presente solo un’istruzione che assegna un valore concatenato a una
variabile che:
non è mai stata allocata attraverso l’istruzione Dim, né è stato dichiarato il suo tipo;
ha il nome uguale a quello della funzione che la contiene;
non è, anche se non determinabile con sicurezza leggendo solo il codice riportato, una
variabile pubblica definita in altri moduli.
In altre parole non si tratta di una normale variabile perché:
viene automaticamente allocata al momento in cui la funzione incomincia l’elaborazione;
il suo tipo viene definito mediante l’indicazione collocata dopo la parentesi tonda chiusa
dell’istruzione Function e, se tale informazione viene omessa dal programmatore, il Visual
Basic utilizzerà implicitamente il tipo Variant;
la sua vita e la visibilità sono limitate alla funzione stessa;
il valore in essa contenuto verrà restituito al chiamante al termine dell’elaborazione della
funzione.
Le ultime considerazioni sono:
il corpo della funzione è costituito da normali istruzioni in linguaggio Visual Basic e quindi
anche richiami di altre funzioni o routine;
la parola chiave End Function indica la fine del corpo.
Parametri o argomenti
I parametri sono valori che la funzione riceve per la propria elaborazione e sono indicati tra
parentesi tonde nella riga di dichiarazione della funzione. La sintassi è identica a quella
dell’istruzione Dim, ma senza tale parola chiave, e ogni parametro viene separato dal successivo
con una virgola. Per esempio, la seguente funzione Montante(), che calcola il valore di un importo
comprensivo di interessi dopo un determinato periodo, utilizza tre parametri:
Capitale. Di tipo Currency;
Anni. Di tipo Integer;
Tasso. Di tipo Single.
Restituisce un valore di tipo Currency:
Function Montante(Capitale As Currency, Anni As Integer, _
Tasso As Single) As Currency
Montante = Capitale * (1 + Tasso / 100) ^ Anni
End Function
Nella seconda istruzione MsgBox() è presente la funzione Trim(), che visualizza il valore di Str
privato degli spazi iniziali e finali superflui, ma il valore di tale variabile è rimasto immutato. Ne
è la riprova la successiva MsgBox() in cui apparirà il valore di Str con tutti i suoi spazi.
ByRef
I parametri sono copie dei valori originari utilizzati nella chiamata della funzione o della
subroutine e ciò permette di scrivere istruzioni che possano modificare liberamente i parametri
senza preoccuparsi delle conseguenze: si tratta di copie a perdere. In taluni casi, però, può
risultare utile disporre del dato originale e non della sua copia. Per tali scopi è disponibile la
parola chiave ByRef, che richiede al compilatore di rendere disponibile e accessibile la fonte
originale dell’informazione.
Tecnicamente si dice che la variabile viene passata alla funzione o sub-routine per riferimento e
non per valore; infatti ByRef è l’abbreviazione del termine inglese By Reference (per riferimento).
La seguente funzione opera la conversione di tutte le lettere contenute in una stringa nel loro
corrispondente maiuscolo ed è simile alla funzione nativa UCase(), ma si differenzia per il fatto
che agisce direttamente sul parametro che riceve, modificandolo, in quanto esso viene indicato
nella dichiarazione di funzione come ByRef:
Function TuttoMaiuscolo(ByRef Txt As String)
Dim x As Integer
For x = 1 To Len(Txt)
If Mid(Txt, x, 1) >= “a” And Mid(Txt, x, 1) <= “z” Then
Mid(Txt, x, 1) = Chr$(Asc(Mid(Txt, x, 1)) –
Asc(“a”) + Asc(“A”))
End If
Next x
End Function
Un esempio di utilizzo è costituito dalla seguente routine, che assegna a una variabile un valore
e lo visualizza attraverso l’istruzione MsgBox str; successivamente viene eseguita la funzione
TuttoMaiuscolo(), passandole come parametro la precedente variabile e, immediatamente dopo,
viene nuovamente visualizzato il valore della variabile, che risulterà modificato (Figura 6.5):
Sub RichiamaTuttoMaiuscolo()
Dim str As String
str = “AbCdefg”
MsgBox str
Call TuttoMaiuscolo(str)
MsgBox str
End Sub
NOTA Quando vengono richiamate funzioni o subroutine i cui parametri sono identificati dalla parola chiave ByRef,
diventa fondamentale il ricorso alla parola chiave Call. Per approfondimenti, vedere più indietro in questo capitolo il
paragrafo “Il problema del ByRef”, relativo alle chiamate di funzioni e subroutine.
Figura 6.5 La funzione TuttoMaiuscolo() ha modificato la variabile della routine chiamante.
NOTA Quando si scrivono le prime funzioni può capitare che il ricorso alla parola chiave ByRef sia corretto. Prima
di utilizzarla è però bene considerare se la funzione può essere usata come parametro di altre funzioni oppure se è
possibile che il suo parametro debba essere modificato: in tali circostanze ByRef è sconsigliabile ed è invece
meglio impiegare il normale sistema di restituzione del valore attraverso la variabile con lo stesso nome della
funzione. Per chiarire il concetto, se la funzione Trim() fosse stata scritta indicando il parametro con ByRef, non
sarebbe possibile il suo impiego come invece avviene in numerosi programmi.
Matrici o array
Anche se nella pratica quotidiana è difficile incontrare funzioni che richiedano parametri di
matrice, ciò può avvenire semplicemente definendo il parametro come array.
Ovviamente, per rendere la funzione utilizzabile in una pluralità di situazioni, essa deve poter
operare con matrici di qualunque grandezza, purché coerenti con il numero di dimensioni.
Per questo motivo la dichiarazione di un parametro di matrice non riporta alcun indice:
Function SommaParametriInMatrice(Mtx() As Integer) As Long
In questo esempio è stata dichiarata una funzione che restituisce un valore di tipo Long e opera
su una matrice di tipo Integer di nome Mtx. In questo modo, essa può operare su array
monodimensionali aventi qualunque numero di elementi.
Il seguente listato riporta un esempio di una funzione operante sulle matrici, la quale viene
richiamata dalla routine Sommatoria, al cui interno sono create due matrici di nome ValA e ValB di
diverse dimensioni: la funzione SommaParametriInMatrice() calcolerà la somma dei vari elementi,
che verrà memorizzata rispettivamente nelle variabili TotaleA e TotaleB; al termine, tali risultati
saranno visualizzati mediante una finestra (Figura 6.6):
Sub Sommatoria()
Dim ValA(3) As Integer
Dim ValB(5) As Integer
Dim TotaleA As Long
Dim TotaleB As Long
ValA(1) = 2
ValA(2) = 3
ValA(3) = 4
ValB(1) = 10
ValB(2) = 20
ValB(3) = 30
ValB(4) = 40
ValB(5) = 50
TotaleA = SommaParametriInMatrice(ValA)
TotaleB = SommaParametriInMatrice(ValB)
Figura 6.6 I risultati dei calcoli effettuati dalla funzione che gestisce le matrici.
Set IntervalloCelle = _
ActiveWorkbook.Worksheets(“Foglio1”).Range(“A1:A5”)
Totale = _
Application.WorksheetFunction.Sum(IntervalloCelle)
MsgBox Totale
End Sub
Le funzioni del foglio di lavoro
La guida di Excel include un elenco di tutte le funzioni disponibili per il foglio di lavoro
ordinate alfabeticamente. Per accedervi si deve:
aprire la guida in linea del Visual Basic mediante il tasto F1;
selezionare la scheda Indice;
digitare la parola Funzione nella casella 1.Digitare le parole chiave;
selezionare la voce Funzione nell’elenco 2.Oppure selezionarle dall’elenco;
fare clic sulla voce Funzioni relative al foglio di lavoro elencate in base alla categoria
visibile nell a casella 3.Selezionare un argomento.
Un tipo di dato composto, creato con l’istruzione Type, con cui si indicherà il tipo restituito
dalla funzione:
‘ Esempio di Type per restituire più valori al chiamante
Type Persona
Cognome As String
Nome As String
End Type
Sub AcquisisceAutore()
Dim Autore As Persona
Autore = RestituisceAutore
MsgBox “Libroscrittoda “ & Autore.Nome & “ “ & _
Autore.Cognome
End Sub
Variabili pubbliche:
Public Cognome As String
Public Nome As String
Sub AcquisisceAutore()
RestituisceAutore
MsgBox “Libro scritto da “ & Nome & “ “ & Cognome
End Sub
Function RestituisceAutore()
Cognome = “Guccini”
Nome = “Paolo”
End Function
Più funzioni, ciascuna delle quali deputata a restituire un valore alla volta:
Sub AcquisisceAutore()
Dim Cognome As String
Dim Nome As String
Cognome = RestituisceAutoreCognome()
Nome = RestituisceAutoreNome()
MsgBox “Libro scritto da “ & Nome & “ “ & Cognome
End Sub
Le funzioni native
In questo capitolo vengono elencate le funzioni native del Visual Basic, ovvero le funzioni che il
linguaggio mette a disposizione del programmatore per svolgere compiti semplici e ripetitivi
oppure che non potrebbero essere effettuati senza di esse. Prima di continuare è opportuno
soffermarsi su alcuni termini che verranno utilizzati nel corso del capitolo.
Tabella Ascii. È una tabella contenente 256 simboli, tra i quali trovano spazio le lettere, i
numeri, i caratteri di interpunzione e altro.
Funzione nativa. Viene messa a disposizione direttamente dal soft-ware e si contrappone alle
funzioni create dal programmatore.
Espressione. Formula che può comprendere anche funzioni, costanti e variabili.
Espressione numerica. Il suo risultato è di tipo numerico.
Espressione testuale. Il suo risultato è di tipo String.
Algoritmo. Sequenza logica di operazioni che devono essere eseguite per ottenere un
determinato risultato.
Personalizzazione. Attività del programmatore atta a ottenere dal software un risultato diverso
da quello standard, al fine di soddisfare meglio determinate esigenze.
Matematiche
La Tabella 7.1 contiene una serie di funzioni matematiche native di VBA.
Tabella 7.1 Le funzione matematiche di VBA
Funzione Valore restituito
Abs(n) Valore assoluto
Atn(n) Arcotangente
Cos(n) Coseno
Exp(n) Elevazione alla n-esima potenza del logaritmo naturale ‘e’
Fix(n)
Parte intera del numero positivo senza arrotondamento, oppure arrotondamento per difetto dei numeri
negativi, ed equivale all’espressione Int (Abs numero) * Sgn (numero)
Int(n)
Parte intera del numero positivo senza arrotondamento oppure parte intera arrotondata per eccesso dei
numeri negativi
Log(n) Logaritmo naturale di base n
Rnd(n)
Numero frazionario casuale maggiore di 0 e minore di 1 che viene generato da un particolare algoritmo
matematico il cui punto di inizio può essere modificato utilizzando l’istruzione Randomize()
Round(n,d) Arrotondamento di n alla d-esima cifra decimale
Sgn(n) –1 oppure +1 se n è negativo o positivo
Sin(n) Funzione trigonometrica del seno
Sqr(n) Radice quadrata di n
Tan(n) Tangente di n
Conversione
La Tabella 7.2 contiene una serie di funzioni native di VBA per effettuare conversioni di tipi.
Tabella 7.2 Le funzioni di conversione di VBA
Funzione Valore restituito
Asc(Str) Codice Ascii del primo carattere della stringa Str ed è la funzione reciproca di Chr()
Chr(n) Carattere corrispondente all’n-esimo codice Ascii ed è il reciproco di Asc()
Hex(n) Stringa con il codice esadecimale di n
Oct(n) Stringa con il codice ottale di n
Str(n) Stringa con il valore del numero n e reciproca di Val(s) e si consiglia di valutare anche l’uso di CStr()
Val(s) Conversione del valore della stringa s nel suo equivalente numerico ed è reciproco di Str(n)
CBool(Esp) Restituisce il valore di tipo Boolean del risultato dell’espressione Esp
CCur(Esp) Restituisce il valore di tipo Currency del risultato dell’espressione Esp
CDate(Esp) Restituisce il valore di tipo Date del risultato dell’espressione Esp
CDbl(Esp) Restituisce il valore di tipo Double del risultato dell’espressione Esp
CDec(Esp) Restituisce il valore di tipo Decimal del risultato dell’espressione Esp
CInt(Esp) Restituisce il valore di tipo Integer del risultato dell’espressione Esp
CLng(Esp) Restituisce il valore di tipo Long del risultato dell’espressione Esp
CSng(Esp) Restituisce il valore di tipo Single del risultato dell’espressione Esp
CStr(Esp) Restituisce il valore di tipo String del risultato dell’espressione Esp
CVar(Esp) Restituisce il valore di tipo Variant del risultato dell’espressione Esp
In relazione al fatto che Visual Basic provvede in modo automatico a gestire le operazioni di
assegnazione dei valori, rispettando opportunamente i tipi, verrebbe da chiedersi il motivo di tante
funzioni di conversione.
Quasi sempre, Visual Basic effettua la corretta conversione semplicemente basandosi sul tipo
della variabile di destinazione, ma ciò non è possibile tutte le volte, quindi può accadere di dover
gestire manualmente la corretta conversione.
In più, c’è da considerare che vi sono situazioni in cui il programmatore può desiderare di
indicare esplicitamente il tipo che dovrà essere utilizzato, per esempio si potrebbe volere che
Visual Basic tratti tutti i calcoli di una determinata espressione matematica in formato Double. Per
esempio, la seguente formula rispetta le normali regole che il linguaggio adotta:
r = (a / b) * ((1 / c) * (d / (((e + 1.5) / 2))))
In questo modo si è certi che la precisione utilizzata sia quella corrispondente al tipo Double e
non vi saranno errori negli arrotondamenti, anche se ciò rappresenta una discreta perdita di tempo.
Double è il tipo preferito da VBA nei calcoli, quindi il risultato finale delle due espressioni è
identico.
Weekday(d)
Giorno della settimana relativo alla data d, espresso con un numero sequenziale Integer
che definisce 1 come domenica, 2 per il lunedì e così via
Hour(t) Ora dell’orario t Integer
DateSerial(a,m, g)
Valore rappresentante una data seriale creata attraverso l’indicazione di anno,
mese e giorno nei rispettivi tre parametri
DoubleTimeSerial(h,M, Valore rappresentante un orario seriale creato attraverso l’indicazione di ora, Double
S) minuti e secondi nei rispettivi tre parametri
DateValue(Esp) Il valore dell’espressione esp Date
Mid(S, p, n) Sottostringa della stringa S dal suo p-esimo carattere e lunga n caratteri String
StrReverse(S) Stringa composta dai caratteri contenuti nella stringa S, ma riportati in ordine inverso String
Trim(S) Stringa contenente il valore di S privato degli spazi iniziali e finali superflui String
Abs(n)
Restituisce il valore assoluto del numero o dell’espressione numerica. Il seguente frammento
richiama una funzione chiamata Calcola-Media() che restituisce un valore che viene testato per
segnalare se esso è compreso tra –2 e +2:
If CalcolaMedia() > –2 And CalcolaMedia() < 2 Then
MsgBox “La media è troppo vicina allo zero”
End If
Int(n)
Relativamente al valore o espressione numerica che riceve come parametro, restituisce la parte
intera del numero positivo senza arrotondamento oppure la parte intera arrotondata per eccesso dei
numeri negativi:
If Int(x) = x Then
MsgBox “numero privo di parte decimale”
Else
MsgBox “il numero ha un valore decimale”
End If
Round(n, d)
Per consentire di gestire l’arrotondamento con semplicità, è stata introdotta la funzione Round()
che arrotonda il valore del parametro n a un numero di cifre decimali impostate attraverso il
parametro d. La seguente routine permette di visualizzare una sequenza di finestre:
Sub EsempioRound()
Dim n As Double
Dim x As Integer
n = 123.987654321098
For x = 0 To11
MsgBox Prompt:=Round(n, x)_
, Title:=”Valore “ & n & “ arrotondato alla “ & x _
& “ cifra decimale”
Next x
End Sub
Sgn(n)
Restituisce il segno matematico dell’espressione numerica che riceve come parametro attribuito
il valore 1. Quindi, se il valore del parametro è:
negativo ovvero minore di 0: Sgn() restituisce il valore –1;
uguale a zero: Sgn() restituisce 0;
positivo ovvero maggiore di 0: Sgn() restituisce il valore +1.
Chr(n)
Restituisce una stringa lunga un carattere, il cui valore è dato dalla conversione del codice Ascii
che la funzione riceve come parametro nel corrispondente carattere. Per esempio, si veda la
funzione Asc().
Str(n)
La funzione Str() è stata una delle più utilizzate prima dell’avvento del tipo Variant e dei
linguaggi che gestivano automaticamente le conversioni del valore in base alle esigenze del tipo.
In particolare, Str() restituisce una stringa che contiene il valore di n convertito in tale tipo, ma
considera sempre il carattere punto come il separatore decimale. In contesti internazionali è
consigliabile ricorrere abitualmente alla funzione CStr() che, basandosi sulle impostazioni della
voce orologio, lingua e opzioni internazionali del Pannello di controllo (Figura 7.1), ricorre
all’opportuno separatore scegliendo tra la virgola o il punto.
Figura 7.1 Il Pannello di controllo e la scheda Formati delle Opzioni internazionali e della lingua in Windows 8.
Val(s)
La funzione Val() provvede ad analizzare la stringa che riceve come parametro, per restituirne il
valore numerico di tipo Double ove possibile, altrimenti restituisce 0. In particolare, la stringa viene
analizzata da sinistra verso destra fino a quando vi sono caratteri validi, poi la funzione restituisce
il valore numerico di quanto trovato. Per esempio:
Val(“12345.6”): restituisce il valore 12345.6;
Val(“12345.6A”): restituisce il valore 12345.6 ignorando il carattere “A” e tutti quelli che
eventualmente seguono;
Val(“123A45.6”): restituisce 123 ignorando tutti i caratteri dalla A in poi;
Funzioni di conversione
Le funzioni di conversione che permettono di evitare che VBA esegua conversioni automatiche
verso tipi indesiderati sono molto utili. Il parametro Esp indica che le funzioni richiedono un
parametro tra le parentesi.
CBool(Esp): restituisce la conversione in tipo Boolean del valore dell’espressione matematica che
riceve come parametro. In particolare, il valore sarà sempre True tranne se il valore di Esp è uguale
a zero: in tal caso CBool() restituirà il valore False.
CCur(Esp): restituisce la conversione in tipo Currency del valore che riceve come parametro. La
seguente istruzione assegna alla variabile Importo il valore contenuto nella variabile Somma di tipo
Double:
Importo = CCur(Somma)
: restituisce la conversione in tipo Date del valore numerico che riceve come parametro
CDate(Esp)
: restituisce la conversione in tipo Double del valore numerico che riceve come
CDbl(Esp)
parametro.
CDec(Esp): restituisce la conversione in tipo Decimal del valore numerico che riceve come
parametro. È interessante notare che nell’attuale versione di Visual Basic non è possibile creare
variabili di tipo Decimal e solo quelle di tipo Variant possono assumere tale configurazione.
CInt(Esp): restituisce la conversione in tipo Integer del valore numerico che riceve come
parametro. Questa funzione è da preferire alla sua versione più antica Int(), anche se ciò implica lo
scrivere programmi che potranno essere correttamente gestiti solo da compilatori Microsoft Visual
Basic, rendendo quindi molto difficile utilizzare un listato con un altro compilatore. Però, in questo
caso, è anche importante osservare che il Visual Basic per Excel serve per scrivere programmi che
interagiscano con Excel e, conseguentemente, questo problema non è molto significativo.
CLng(Esp): restituisce la conversione in tipo Long del valore numerico che riceve come parametro.
CSng(Esp): restituisce la conversione in tipo Single del valore numerico che riceve come
parametro.
CStr(Esp): restituisce la conversione in tipo String del valore numerico che riceve come
parametro.
Date
La parola chiave Date viene utilizzata in due contesti diversi con due significati differenti:
per un tipo di dato che è deputato a contenere date, orari o entrambi;
per una funzione e, in questo caso, non richiede le parentesi dopo il nome.
Tra le funzioni per la gestione di date e orari, Date permette di interrogare il calendario del
computer per conoscere la data del giorno corrente, che viene restituita in formato Date. La seguente
routine interroga l’orologio interno e visualizza il giorno della settimana:
Sub VisualizzaGiornoDellaSettimanaDiOggi()
Dim d As Date
d = Date
MsgBox Prompt:=Format(d, “dddd”), _
Title:=”Giorno della settima per la data del “ & d
End Sub
Time
Interroga l’orologio del computer e restituisce un valore di tipo Date con l’orario corrente:
Sub VisualizzaDifferenzaOrari()
Dim d1, d2 As Date
d1 = Time
Dim x As Long
For x = 1 To 100000000#
Sqr (Sqr(Sqr(Rnd() * 100000)))
Next x
d2 = Time
Dim TempoImpiegato As String
TempoImpiegato = Format(d2 - d1, “hh:mm:ss”)
MsgBox “il ciclo e’ stato eseguito nel tempo di “ & _
TempoImpiegato
End Sub
NOTA Si utilizza la funzione Now() per ottenere contemporaneamente sia la data sia l’ora.
Now
La funzione Now() è l’equivalente delle funzioni Date() e Time() eseguite contemporaneamente e,
per chi deve lavorare sia con le date sia con gli orari, rappresenta una soluzione ottimale. Quando,
per esempio, si acquisiscono in sequenza, ma separatamente, la data e l’orario dall’orologio del
computer mediante le funzioni Date() e Time() può accadere che, nella frazione di secondo che
intercorre tra l’elaborazione delle due istruzioni, scatti la mezzanotte; in questa circostanza si
avrebbe la data del giorno prima e l’orario del giorno corrente:
Sub EsempioNow()
Dim Adesso As Date
Adesso = Now
MsgBox Adesso
End Sub
Weekday(d)
La funzione Weekday() permette di ottenere il numero di tipo Integer che indica il giorno della
settimana relativo alla data che riceve come parametro. I giorni vengono rappresentati secondo il
valore della tabella riportata di seguito, dove sono indicate le relative costanti.
Giorno Costante VBA
Domenica vbSunday
Lunedì vbMonday
Martedì vbTuesday
Mercoledì vbWednesday
Giovedì vbThursday
Venerdì vbFriday
Sabato vbSaturday
GiornoSettimana = Weekday(Date)
DateSerial(a, m, g)
Le date vengono memorizzate in una variabile di tipo Date che è equivalente al tipo Double, per cui
si può impostare una specifica data in una variabile di tipo Date con relativa semplicità, come
spiegato nei capitoli precedenti relativamente al modo in cui vengono memorizzati questi valori.
Impostare direttamente il valore di una variabile Date è invece sconsigliabile perché:
è facile scrivere la formula errata;
non è garantita in alcun modo la compatibilità con le versioni future di VBA o di Excel;
il tempo di elaborazione che si risparmia è minimo anche nel caso l’operazione venga
eseguita centinaia di migliaia di volte.
Per impostare il valore di una variabile di tipo Date conoscendo giorno, mese e anno espressi in
formato Integer esiste la funzione DateSerial(), atta a tale scopo, che richiede, nell’ordine, tre
parametri:
un numero che rappresenti l’anno;
un numero che rappresenti il mese;
un numero che rappresenti il giorno.
La routine EsempioDateSerial costituisce un semplice esempio d’impiego di questa funzione per
costruire una data il cui giorno, mese e anno sono estratti dalla variabile Oggi; la routine si chiude
con un test che verifica se le variabili Oggi e Riconvertito sono equivalenti, come è lecito attendersi:
Sub EsempioDateSerial()
Dim g, m, a As Integer
Dim Oggi As Date
Dim Riconvertito As Date
Oggi = Date
g = Day(Oggi)
m = Month(Oggi)
a = Year(Oggi)
Riconvertito = DateSerial(a, m, g)
If Riconvertito <> Oggi Then
MsgBox “Con la data “ & Oggi & “ la funzione _
DateSerial ha un bug”
End If
End Sub
TimeSerial(h, m, s)
In maniera simile alla funzione DateSerial(), la funzione TimeSerial() opera restituendo un valore
che si può utilizzare per una variabile di tipo Date; essa richiede tre parametri per indicare:
l’ora (il valore deve essere compreso tra 0 e 23);
i minuti (il valore deve essere compreso tra 0 e 59);
i secondi (il valore deve essere compreso tra 0 e 59).
DateValue(Esp)
Questa funzione riceve come parametro una stringa contenente una data e restituisce un valore di
tipo Variant che può essere utilizzato per assegnare tale data a una variabile di tipo Date (Figura
7.4):
Sub EsempioDateValue()
Dim d As Date
d = Date
If d <> DateValue(“31 dicembre 2002”) Then
Fineanno = DateValue(“31 dicembre 2002”)
MsgBox “a capodanno mancano”_
& Fineanno - d & “ giorni”
Else
MsgBox “Auguri per un felice anno nuovo!”
End If
End Sub
Il seguente esempio fa un uso coordinato della funzione Format() per ottenere una stringa,
opportunamente formattata, che possa essere utilizzata dalla funzione DateValue(); in particolare, la
variabile d contiene la data corrente che viene convertita in stringa e memorizzata in str;
quest’ultima diventa il parametro per la funzione DateValue() che provvede a restituire l’equivalente
valore, in formato Date, che viene assegnato alla variabile Riconvertito. Siccome si tratta sempre
della stessa data che ha subito alcune conversioni, ovviamente la data finale sarà ancora uguale a
quella iniziale:
Sub EsempioDateValueFormat()
Dim d As Date
Dim str As String
Dim Riconvertito As Date
d = Date
str = Format(d, “dd mmmm yyyy”)
Riconvertito = DateValue(str)
MsgBox “LafunzioneFormat()” _
& vbCr & “con i seguenti parametri: “ _
& Date & “,””dd mmmm yyyy””” _
& vbCr & “produce: “ & str _
& vbCr & “che utilizzata come parametro in” _
& vbCr & “DateValue(“”” & str & “””)” _
& vbCr & “permette di ottenere la data iniziale del” _
& Riconvertito
End Sub
TimeValue(Esp)
Similmente a quanto accade per la funzione DateValue(), questa funzione restituisce un valore in
formato Date estraendolo dalla stringa che riceve come parametro:
Sub EsempioTimeValue()
Dim diff As Date
diff = TimeValue(“23:59:59”) - Time
MsgBox “Alla mezzanotte mancano” & _
vbCr & Hour(diff) & “ ore, “ & Minute(diff) & _
“ minuti e “ & Second(diff) & “ secondi”
End Sub
LCase(S)
LCase() restituisce una copia della stringa che riceve come parametro dopo aver convertito tutte
le lettere nell’equivalente minuscolo: la lettera L iniziale è l’abbreviazione del termine inglese
Lower: minore. UCase è la funzione speculare che restituisce la stringa convertita in maiuscolo.
Queste funzioni trovano applicazione pratica per verificare i valori introdotti dall’utente, evitando
di costruire test doppi; per esempio, il test che controlla che il carattere digitato dall’utente sia una
vocale deve verificare dieci possibilità, ovvero cinque vocali minuscole e cinque maiuscole:
Sub EsempioSenzaLower()
Dim s As String
Mid(S,p,l) restituisce una stringa lunga l caratteri copiati da S iniziando dalla posizione p.
La funzione Left() permette di ottenere una copia della stringa che riceve come parametro,
limitandone la lunghezza ai primi n caratteri.
La seguente istruzione copia il primo carattere della variabile Sorg in Dest:
Dest = Left(Sorg,1)
La seguente istruzione copia il valore della variabile Sorg in Dest, escluso l’ultimo carattere,
calcolandone la lunghezza mediante la funzione Len():
Dest = Left(Sorg,Len(Sorg)-1)
Len(S)
La funzione Len() restituisce un valore di tipo Long indicante il numero di caratteri contenuti nella
stringa che riceve come parametro, in altre parole la sua lunghezza.
Il seguente frammento di codice verifica se la stringa immessa dall’utente è più lunga di un
carattere e, in tal caso, invia una segnalazione di errore:
S = InputBox(“Inserisci una vocale”)
If Len(S) > 1 Then
MsgBox “solo un carattere!”
End If
sinistra).
RTrim(s) elimina gli spazi posti alla fine della stringa (R è l’abbreviazione di Right ovvero
destra).
MsgBox
, senza parentesi tonde per racchiudere i parametri, viene abitualmente considerata
MsgBox
un’istruzione anche se, in realtà, è una chiamata a funzione. È possibile omettere sia le parentesi,
per comodità del programmatore, sia l’istruzione Call, infatti le seguenti righe di codice sono
equivalenti per quanto riguarda il risultato:
Sub EsempioCallMsgBox()
Call MsgBox(“Questo e’ il test”)
MsgBox (“Questo e’ il test”)
MsgBox “Questo e’ il test”
End Sub
L’istruzione Call è abitualmente tralasciata, mentre l’uso delle parentesi è indispensabile per
conoscere quale pulsante è stato selezionato dall’utente per chiudere la finestra. I parametri che
tale funzione accetta e per i quali viene anche indicato il relativo nome sono riportati di seguito.
Prompt. Stringa contenente il testo che deve essere visualizzato all’interno della finestra.
Buttons. Codici dei pulsanti che dovranno essere visualizzati nella finestra e permetteranno di
HelpFile. Stringa contenente il nome del file di help nel quale sono contenute le informazioni
associate a tale finestra; di default viene aperto l’help di Excel attraverso l’assistente.
Context. Nel caso sia stato indicato un file di help, questo parametro consente di specificare
esattamente quale sua porzione sia efferente alla finestra, permettendo in tal modo di
visualizzare il testo di aiuto associato a essa.
Per comprendere che cosa si può ottenere agendo sui parametri Buttons, di seguito vengono
elencate alcune possibilità:
MsgBox _
prompt:=”Esempi delle possibili combinazioni di pulsanti” _
, Buttons:=vbYesNo_
, Title:=”Nome della costante: vbYesNo “
Per poter conoscere quale pulsante è stato utilizzato dall’utente per chiudere la finestra è
necessario utilizzare la forma MsgBox(), ovvero racchiudere i parametri tra parentesi.
MsgBox()
La funzione MsgBox() è in tutto equivalente a MsgBox, ma vi aggiunge la possibilità di conoscere
quale pulsante sia stato selezionato dall’utente attraverso il valore che essa restituisce; nella
seguente tabella sono riportati i valori restituiti da ogni pulsante.
Pulsante Nome della costante Valore equivalente
OK vbOK 1
Annulla vbCancel 2
Termina vbAbort 3
Riprova vbRetry 4
Ignora vbIgnore 5
Sì vbYes 6
No vbNo 7
Il seguente listato mostra come utilizzare il valore restituito dalla funzione MsgBox():
Sub EsempioMsgBoxConRestituzione()
Dim Btn As Integer
Btn = MsgBox(“Fai un clic su un pulsante”, _
vbExclamation + vbYesNo)
Select Case Btn
Case vbYes
MsgBox “E’ stato fatto clic su Yes”
Case vbNo
MsgBox “E’ stato fatto clic su No”
End Select
End Sub
InputBox()
La funzione InputBox() permette di aprire una finestra similmente a quanto avviene con la funzione
MsgBox(), ma anzichè restituire il codice del pulsante sul quale è stato fatto clic, restituisce la stringa
che l’utente ha digitato all’interno della relativa casella. I parametri che richiede sono diversi.
Prompt. Stringa contenente il testo che deve essere visualizzato all’interno della finestra.
Title. Stringa contenente il titolo della finestra; il valore di default è “Microsoft Excel”.
XPos. Posizione orizzontale della finestra calcolata come distanza dal lato sinistro dello
associate a tale finestra; di default viene aperto l’help di Excel attraverso l’assistente.
Context. Nel caso sia stato indicato un file di help, questo parametro consente di specificare
esattamente quale sua porzione sia afferente alla finestra permettendo in tal modo di
visualizzare il testo di aiuto associato a essa.
La funzione InputBox() può essere utilizzata per richiedere all’utente di digitare un valore
numerico e ripetere la domanda fino a quando non viene introdotto un valore corretto.
NOTA Il valore dei parametri XPos e YPos sono espressi con una particolare unità di misura detta twip. Se essi sono
omessi, la posizione di default della finestra viene automaticamente calcolata per apparire centrata rispetto allo
schermo.
Capitolo 8
Nei precedenti capitoli si è fatto uso del linguaggio Visual Basic per creare alcune semplici
routine esemplificative senza specificare esattamente il senso di ogni istruzione, ma cercando di
fornire una chiara via interpretativa che consentisse di comprenderne il significato anche a chi non
ha dimestichezza con la programmazione. è giunto il momento di affrontare direttamente il tema del
linguaggio e dei suoi costrutti.
NOTA Nel corso di questo capitolo si farà spesso ricorso al termine manutenzione: la manutenzione è l’attività di
modifica di un programma per adattarlo a nuove circostanze o esigenze dell’utente.
Il flusso logico
Il flusso logico è la sequenza con cui il computer elabora il programma.Esso non è lineare in
quanto esistono istruzioni:
atte a ripetere ciclicamente un insieme di altre istruzioni, come nel caso dell’analisi del
contenuto di più celle del foglio di lavoro;
atte a scegliere tra due o più gruppi di istruzioni sulla base del test di una condizione.
Questi strumenti sono disponibili in ogni linguaggio di programmazione e sono irrinunciabili.
NOTA In questo caso, quando si fa riferimento a un gruppo di istruzioni, si intendono anche le routine, subroutine e
funzioni che possono farne parte.
La sequenza
La successione delle istruzioni che vengono eseguite, detta flusso del programma è, in linea di
principio, sequenziale, ovvero dalla prima istruzione che segue la riga Sub fino a quella che
contiene l’End Sub. Vanno tenute presenti le seguenti segnalazioni di normali casi che alterano tale
sequenza:
quando viene incontrata l’istruzione Call, o un’equivalente sistema di chiamata, la routine
corrente viene temporaneamente sospesa per eseguire quella richiamata e, al suo termine,
riprenderà l’elaborazione della routine chiamante;
quando viene richiamata una funzione, la routine corrente viene momentaneamente sospesa
per eseguire la funzione e, al termine di questa, l’elaborazione riprenderà, eseguendo
un’immaginaria sostituzione del valore restituito al nome della funzione e ai suoi parametri e
continuando a elaborare l’eventuale succedersi di operazioni nella formula.
In cima all’elenco della finestra Visualizza/Stack di chiamate appare visibile la routine attiva e,
al di sotto di essa, tutte le chiamanti nell’ordine inverso a quello in cui si sono succedute. In
pratica, la prima è la routine correntemente in esecuzione che, quando terminerà, verrà eliminata
dalla finestra; il controllo passerà a quella sottostante, che acquisirà il primo posto, mentre le altre
scaleranno di una posizione (Figura 8.2).
Il seguente listato può aiutare a comprendere meglio che cosa accade a una routine che viene
sospesa dalla chiamata a un’altra routine; infatti, ognuna di esse crea una variabile di nome Testo
nella quale inserisce una stringa che indica il nome della routine in cui è contenuta e il richiamo a
un’altra funzione in cui avvengono le stesse operazioni. A questo punto, può sorgere spontanea una
domanda: che cosa accade alla variabile Testo, dato che ogni routine la crea e vi inserisce un
valore?
Option Explicit
Sub Prima()
Dim Testo As String
Testo = “Prima”
Call Seconda
MsgBox Testo, , “Questa finestra è stata aperta dalla _
routine Prima”
End Sub
Sub Seconda()
Dim Testo As String
Testo = “Seconda”
Call Terza
MsgBox Testo, , “Questa finestra è stata aperta dalla _
routine Seconda”
End Sub
Sub Terza()
Dim Testo As String
Testo = “Terza”
Call Quarta
MsgBox Testo, , “Questa finestra è stata aperta dalla _
routine Terza”
End Sub
Sub Quarta()
Dim Testo As String
Testo = “Quarta”
Call Quinta
MsgBox Testo, , “Questa finestra è stata aperta dalla _
routine Quarta”
End Sub
Sub Quinta()
Dim Testo As String
Testo = “Quinta”
MsgBox Testo, , “Questa finestra è stata aperta dalla _
routine Quinta”
End Sub
NOTA Se si desidera collaudare questo listato, al momento di eseguirlo è necessario fare attenzione a come si
avvia l’esecuzione in quanto, se si utilizza il pulsante o il comando Esegui Sub/UserForm, si rischia che essa non
abbia inizio dalla routine Prima perché l’esecuzione inizia dalla routine che contiene il cursore. Per evitare questo
inconveniente, si deve preventivamente posizionare il cursore in una delle istruzioni della routine Prima oppure
utilizzare Strumenti/Macro di Visual Basic Editor.
Ogni routine alloca una variabile di nome Testo che, essendo dichiarata all’interno delle
istruzioni Sub/End Sub, è di tipo locale, ovvero visibile solo da tale routine; ne consegue che tutte le
routine creano tante variabili, ognuna assolutamente indipendente dalle altre. Infatti, la sequenza
delle finestre che vengono aperte dalle varie routine incomincia dall’ultima e, ognuna di esse,
mostra il valore corretto delle singole variabili Testo (Figura 8.3). Per approfondimenti in tema di
variabili si legga il Capitolo 4, in particolare il paragrafo “Vita e visibilità delle variabili”.
NOTA In realtà, il programma subisce continuamente interruzioni causate dai cosiddetti Interrupt, generati da altri
programmi, che richiedono al sistema operativo di essere elaborati. Inoltre, lo stesso sistema operativo gestisce in
frazioni di secondo i programmi in esecuzione affinché si alternino nell’utilizzo del processore, dando la sensazione
che tutti i programmi siano eseguiti, contemporaneamente. Può aiutare a comprendere il concetto immaginare i
programmi come persone assetate sedute in cerchio, in attesa che la persona con la borraccia (il sistema
operativo) permetta loro di bere un solo sorso (il tempo di elaborazione del processore): per placare la sete
bevendo altri sorsi (completare l’esecuzione di tutte le istruzioni), sarà necessario attendere che la borraccia
compia altri giri di tutti i presenti.
Figura 8.3 Le finestre prodotte dalle routine Quinta, Quarta, Terza, Seconda e Prima.
La fine dell’esecuzione
Il termine dell’esecuzione di una routine o funzione può portare a due differenti risultati, se l’una
o l’altra erano in esecuzione.
Da un’altra routine: quest’ultima riprenderà la sua esecuzione, ciò significa che non si è
raggiunta la fine del programma che continuerà l’esecuzione.
Da un oggetto di un UserForm: lo UserForm sarà nuovamente visualizzato in attesa di altre
interazioni con l’utente, a meno che tra le istruzioni compaia l’istruzione UnLoad Me che causa la
chiusura della finestra stessa.
Le condizioni
All’interno di un programma è possibile definire test mediante i quali decidere le istruzioni che
il programma deve eseguire. Nella Tabella 8.1 è riportato un paragone tra l’azione di preanalisi,
che può svolgere una persona addetta all’ufficio rilascio patenti, e la versione informatica di tale
operazione, considerando i dati del richiedente inseriti in una variabile di tipo definito dal
programmatore (attraverso l’istruzione Type).
Il Visual Basic dispone di diverse istruzioni con alcune varianti per la gestione dei test, che
sono:
If
Select Case
la pratica può essere passata al competente ufficio per tutti gli espletamenti e InviaPraticaUfficioRilascioPatenti(Richi
gli ulteriori accertamenti del caso
altrimenti Else
segnalare che egli deve pazientare ancora un po’ MsgBox “Sii paziente!”
For Each/Next;
While/Wend;
Do/Loop.
Ognuna delle precedenti istruzioni, con le sue varianti, verrà discussa nei prossimi paragrafi.
If
L’istruzione If è la più nota, viene utilizzata da coloro che sviluppano software ed è presente in
ogni linguaggio di programmazione.
È composta dalle seguenti parti:
il test, che deve poter essere ricondotto a un risultato esprimibile con un valore di tipo
booleano oppure numerico;
la parola chiave Then, sempre presente al termine della condizione;
le istruzioni da eseguire nel caso il test risulti positivo;
eventualmente le istruzioni da eseguire nel caso il test risulti negativo, precedute da una riga
contenente la parola chiave Else;
la parola chiave End if.
Più specificatamente, si considera che il risultato del test sia:
vero (il test ha restituito un valore numerico diverso da zero oppure un tipo booleano il cui
valore è True);
falso (il test ha restituito un valore numerico uguale a zero oppure un tipo booleano il cui
valore è False).
Nei prossimi paragrafi verranno analizzate le diverse forme che può assumere l’istruzione If.
If…Then/End If
La forma If/End If è la più semplice e permette di indicare un blocco di istruzioni che verrà
eseguito se il test contenuto nell’istruzione risultasse vero.
Nel seguente esempio, la condizione è costituita da un’identità matematica, ovvero
dall’asserzione che il valore 1 è uguale al valore 1; il risultato è quindi alquanto scontato:
Sub EsempioIfSemplice1()
If 1 = 1 Then
MsgBox “Il test ha dato ‘True’ come risultato”
End If
End Sub
Questa forma viene utilizzata nei casi in cui si debbano intraprendere una o più azioni se la
condizione è vera, mentre se essa risulta False il flusso deve proseguire ignorandola e passando
alla prima istruzione successiva alla End If corrispondente alla If appena analizzata.
Nel seguente esempio viene verificato se i valori di default, utilizzati dall’applicazione, sono
già stati letti da un ipotetico file; in tal caso l’applicazione provvede a caricarli per proseguire
l’elaborazione:
If Not ParametriDefaultGiaCaricati Then
Call AperturaFileParametriDefault
End If
In questo caso, la necessità del programmatore è assicurarsi che i parametri di default siano già
stati caricati per poter proseguire il normale flusso; la If rappresenta un’azione da eseguire prima
di continuare l’esecuzione del programma con le istruzioni a essa successive.
NOTA Si noti la presenza dell’operatore Not, il quale inverte il valore booleano dell’espressione che lo segue. Il test
verifica se il contrario della variabile ParametriDefaultGiaCaricati è True, ovvero se non sono già stati caricati i
dati.
If…Then/Else/End If
La forma If…Then/Else/End If è molto comune in quanto permette di scegliere tra due blocchi di
istruzioni, basandosi sul risultato di un’espressione inserita sulla riga If. Il concetto da sottolineare
è che solo uno dei due blocchi di istruzioni sarà eseguito in base all’esito del test: i programmatori
che si cimentano le prime volte con questa forma di If tendono a confondere l’uso della If…Then/End
If, ma si tratta di un problema che si risolve quasi subito.
Nel seguente esempio viene richiesto all’utente di introdurre un valore numerico; il test verifica
attraverso la funzione IsNumeric() se quanto digitato è effettivamente numerico e, in base al risultato
di tale controllo, visualizza un messaggio differente:
Sub EsempioIfElse1()
Dim str As String
str = InputBox(“Inserisci un numero”)
If IsNumeric(str) Then
MsgBox “Il test ha dato ‘True’ come risultato”
Else
MsgBox “Il test ha dato ‘False’ come risultato”
End If
End Sub
If annidate
Le If annidate non costituiscono un tipo diverso, ma semplicemente sono istruzioni che
contengono altre If come nel seguente esempio:
Sub EsempioIfannidate1()
Dim Velocita As Single
Velocita = 70
Normalmente, nei programmi, si ricorre alle If annidate anche se talvolta possono rendere meno
immediata la comprensione del programma stesso, come nell’esempio precedente. In realtà è raro
costruire If così complesse basate sul test della stessa variabile in quanto, per tali situazioni,
esistono strumenti più sofisticati, quali l’istruzione Select Case o If/ElseIf.
È invece più comune trovare If annidate le cui varie condizioni sono basate su parametri che
non si ripetono e risultano più leggibili.
If…Then/ElseIf/Endif
Nell’esempio del paragrafo delle If annidate è stata presentata una routine che poteva essere
scritta in modo diverso e più leggibile ricorrendo alla forma If...Then/ElseIf/Endif:
Sub EsempioIfElseIf()
Dim Velocita As Single
Velocita = 70
If Velocita < 50 Then
MsgBox “Sei in città o fermo?”
Else If Velocita < 90 Then
MsgBox “Velocità fra 50 e 90”
ElseIf Velocita < 130 Then
MsgBox “Stai viaggiando in autostrada?”
Else
MsgBox “Amante della velocità a rischio autovelox”
End If
End Sub
Come si può osservare, la parola chiave ElseIf si comporta analogamente alla Else a cui viene
aggiunta una condizione, in pratica si tratta dello stesso comportamento che si ottiene dalla Else
seguita da una If/ElseIf.
If con condizioni molto lunghe
Le variabili e le funzioni con il nome molto lungo hanno il grande vantaggio di essere
autoesplicative del contenuto o della funzionalità del relativo oggetto, ma anche lo svantaggio di
richiedere molto spazio.
Le condizioni possono diventare anche particolarmente lunghe, estendendosi al di là del margine
destro della finestra e diventando così illeggibili, perciò si perde la possibilità di comprenderne il
significato a colpo d’occhio. Per aggirare questo problema è stato introdotto il carattere
underscore (_) il quale indica che l’istruzione al termine della riga su cui si trova prosegue nella
successiva. Esso deve essere collocato in una posizione che sintatticamente potrebbe accettare uno
spazio ed essere digitato facendolo precedere da uno spazio.
Inoltre, con questo sistema, è possibile utilizzare più di una riga per una singola istruzione. Nel
seguente frammento, l’istruzione If presenta la condizione su più righe, si tratta di un esempio per
mostrare varie possibilità di interruzione:
If Valore1 > Valore2 _
And Valore3 = Valore4 And _
Valore5 _
< _
Valore6 _
Then
Valore0 = 1
End If
Il carattere underscore non è utilizzabile per spezzare il valore di una stringa, ma si può
ricorrere a esso creando due stringhe concatenate, ciascuna su una riga, tramite l’apposito
operatore (Figura 8.4):
Sub EsempioACapo2()
Dim str As String
str = “abcd” _
& “efgh”
MsgBox str
End Sub
NOTA è importante non dimenticare che sono necessari uno spazio, il carattere underscore e il ritorno a capo per
suddividere correttamente un’istruzione su più righe.
Select Case
L’istruzione Select Case è utile nella maggioranza dei casi in cui si dovrebbe costruire una serie
di If nelle quali il test si basa sulla valutazione del risultato della stessa espressione.
Essa si compone di:
parole chiave Select Case seguite da un’espressione;
parola chiave Case, con il valore o l’insieme di valori che gestisce, seguita da una o più righe
che costituiscono le istruzioni eseguite nel caso il valore dell’espressione presente in Select
Case dia un risultato tra quelli indicati nell’istruzione Case;
NOTA Si osservi che non esiste l’istruzione End Case ma solo la End Select.
Un esempio è indubbiamente il miglior modo per chiarire questi concetti, prendendo come
riferimento una funzione che debba restituire il nome del mese corrispondente al numero che
riceve come parametro; tale funzione potrebbe venir scritta nel seguente modo:
Function EsempioSelectCase2(N As Integer) As String
If N = 1 Then EsempioSelectCase2 = “gen”
If N = 2 Then EsempioSelectCase2 = “feb”
If N = 3 Then EsempioSelectCase2 = “mar”
If N = 4 Then EsempioSelectCase2 = “apr”
If N = 5 Then EsempioSelectCase2 = “mag”
If N = 6 Then EsempioSelectCase2 = “giu”
If N = 7 Then EsempioSelectCase2 = “lug”
If N = 8 Then EsempioSelectCase2 = “ago”
If N = 9 Then EsempioSelectCase2 = “set”
If N = 10 Then EsempioSelectCase2 = “ott”
If N = 11 Then EsempioSelectCase2 = “nov”
If N = 12 Then EsempioSelectCase2 = “dic”
If N < 1 Or N > 12 Then EsempioSelectCase2 = “Numero _
sbagliato”
End Function
NOTA Tra tutti i gruppi di istruzioni inclusi nella Select Case, solo uno sarà eseguito: il primo la cui Case indica un
valore o criterio uguale al valore del test presente nella Select Case.
Il primo inciso riguarda la compattezza della prima forma basata sulla If…Then che, con 12 righe,
gestisce altrettante condizioni, mentre l’istruzione Select Case ne richiede addirittura 26, più del
doppio. Ciò è fuorviante, in quanto la flessibilità di questa istruzione è molto ampia e va valutata
nell’ottica che ci può essere più di una singola istruzione da eseguire per ogni possibilità. Oltre a
rendere il listato più elegante e leggibile, in quanto esiste una sola espressione che il
programmatore deve leggere mentre sono presenti tante righe Case con i valori possibili da gestire,
questa istruzione dispone di caratteristiche che la rendono estremamente interessante:
si può indicare un singolo valore: la seguente istruzione è un esempio di Case che gestisce il
valore 1:
Case 1
è possibile ricorrere a un confronto semplice per indicare i valori che la Case deve gestire:
Case Is > 300
si possono anche combinare tali possibilità, come deducibile dai seguenti esempi di
istruzione Case:
Case 10 To 19, 50 To 59
I cicli o loop
Tra gli strumenti classici a disposizione del programmatore, che tutti i linguaggi forniscono, vi è
la possibilità di costruire cicli, ovvero una o più operazioni da ripetere varie volte. Ecco alcuni
esempi di cicli:
scorrere tutte le celle contenute in una colonna di un foglio di lavoro per contare quante
presentano un determinato valore;
scorrere tutti i fogli di lavoro per verificare se ne esiste uno con un determinato nome;
scorrere tutti i caratteri di una stringa per sostituire quelli che contengono una lettera
minuscola con l’equivalente maiuscolo;
scorrere tutti gli elementi di una matrice per porre il loro valore uguale a zero;
scorrere tutti gli oggetti di tipo Casella di testo di una finestra per cancellarne l’eventuale
contenuto.
Il ciclo viene continuamente eseguito fino a quando non è stata raggiunta la condizione di fine
che può essere identificata da:
una condizione il cui risultato è il valore booleano False, oppure numerico uguale a 0, eccetto
il ciclo Do Until/Loop;
il numero di cicli predefiniti che è stato eseguito;
una specifica istruzione che ne determina la fine, indipendentemente dal valore della
condizione o dal numero di cicli già compiuti.
Un ciclo può contenere al proprio interno uno o più cicli, facendo attenzione che il ciclo interno
sia completamente contenuto in quello più esterno, come nel classico gioco delle bambole russe o
scatole cinesi. In pratica è vietato utilizzare le istruzioni nel seguente ordine:
dichiarare il punto di inizio di un ciclo;
dichiarare il punto di inizio di un altro ciclo;
dichiarare il punto di fine del primo ciclo;
dichiarare il punto di fine del secondo ciclo.
Ciò è errato, in quanto i due cicli si intersecano. La forma corretta è la seguente:
dichiarare il punto di inizio di un ciclo;
dichiarare il punto di inizio di un altro ciclo;
dichiarare il punto di fine del secondo ciclo;
dichiarare il punto di fine del primo ciclo.
For/Next
Il ciclo For/Next è il più semplice da apprendere e utilizzare e serve a eseguire il ciclo un numero
predeterminato di volte. L’istruzione For richiede:
L’aspetto più interessante è però il fatto che la variabile di controllo del ciclo può essere
utilizzata al suo interno; la seguente routine mostra, come la precedente, un messaggio sul monitor,
ma aggiunge anche il numero ottenuto da tale variabile:
Sub EsempioForNext4()
Dim x As Long
La variabile di controllo può essere utilizzata per inserire un determinato valore all’interno di
una matrice, per esempio lo 0:
Sub EsempioForNext3()
Dim x As Integer
Dim Valore(30) As Integer
For x = 1 To 30
Valore(x) = 0
Next x
End Sub
La variabile di controllo, inoltre, è spesso utilizzata come indice per accedere alle singole celle
di un foglio di lavoro. La seguente routine inserisce la data e l’ora corrente all’interno di tutte le
celle della seconda colonna del foglio di lavoro attivo, impiegando alcune decine di secondi
(Figura 8.5):
Sub EsempioForNext4()
Dim x As Long
For x = 1 To 65536
Sheets(1).Cells(x, 2) = Now
Next x
End Sub
Il limite inferiore del ciclo non deve necessariamente essere impostato a 1: qualunque valore è
possibile, l’importante è rispettare la congruenza tra il valore massimo supportato dal tipo della
variabile di controllo e i limiti del ciclo stesso.
In altre parole, non è possibile eseguire un ciclo che inizi o superi il valore 40.000, se la
variabile è di tipo Integer e accetta solo valori inclusi tra –32.768 e +32.767. In caso contrario si
verifica un errore.
NOTA Se il ciclo deve lavorare su una matrice, è possibile utilizzare le funzioni LBound() e UBound() per indicare i
valori iniziale e finale del ciclo nei casi in cui la sua dimensione non sia nota a priori: per esempio nel caso delle
matrici dimensionate con le istruzioni Dim e Redim in modo variabile di esecuzione in esecuzione.
Un esempio di ciclo For/Next inserito in altri cicli For/Next è la seguente routine, che verifica le
celle nell’area composta dalle prime 4 colonne e 20 righe analizzandone il valore e ricercando
quelle il cui valore sia uguale a zero, con lo scopo di mostrare le coordinate all’utente:
Sub EsempioForNext5()
Dim Riga As Long
Dim Colonna As Long
Dim V As Variant
For Colonna = 1 To 4
For Riga = 1 To 20
V = Sheets(“Foglio2”).Cells(Riga, Colonna).Value
If Not IsEmpty(V) Then
If V = 0 Then
Sheets(“Foglio2”).Cells(Riga, Colonna).
Select
Sheets(“Foglio2”).Cells(Riga, Colonna).
Value = “ZERO”
MsgBox “Coordinate: “ & Riga & “,” &
Colonna & “, sostituito valore =” & V & “
con ZERO”
End If
End If
Next Riga
Next Colonna
End Sub
For…Step/Next
Il ciclo For…Step/Next non è altro che l’estensione del precedente, al quale viene aggiunta la
clausola Step per indicare un incremento o un decremento diverso da quello di default: +1. Step è
utile per eseguire:
cicli il cui limite iniziale è maggiore di quello terminale, impostando Step con un valore
negativo;
cicli in cui l’incremento della variabile sia definito da uno specifico valore come 2, 3, 5
oppure decimale: 1,2, e 3,77 (Figura 8.6).
Sub EsempioForStepNext1()
Dim x As Long
For x = 1 To 30 Step 2
Sheets(1).Cells(x, 1).Value = “esempio”
Next
End Sub
For Each/Next
Visual Basic dispone di un’istruzione per definire un ciclo operante su un insieme di oggetti,
evitando al programmatore di impostare il limite di partenza e quello di arrivo, in quanto
automaticamente gestiti. Si tratta di For Each/Next che richiede:
la parola chiave For Each;
il nome di una variabile di tipo Variant;
la parola chiave In;
il nome dell’insieme per il quale ogni singolo elemento sarà oggetto di un’elaborazione del
ciclo.
Il seguente esempio dichiara una matrice di tipo stringa composta da tre elementi ai quali
assegna un valore. Il ciclo viene eseguito sulla matrice allo scopo di concatenare il valore di ogni
singolo elemento nella variabile Str (Figura 8.7):
Sub EsempioForEach1()
Dim Mtx(3) As String
Dim Str As String
Dim x As Variant
Mtx(1) = “ABC”
Mtx(2) = “DEF”
Mtx(3) = “GHI”
MsgBox Str
End Sub
Per utilizzare il ciclo For Each/Next con le matrici è indispensabile tenere a mente come è
impostata l’Option Base.
Un ottimo esempio pratico è costituito dalla seguente routine che visualizza la media dei valori
contenuti nella matrice Valori (Figura 8.8 e Figura 8.9):
Sub EsempioForEach2()
Dim Valori(3) As Long
Dim Totale As Long
Dim Num As Integer
Dim x As Variant
Valori(1) = 10
Valori(2) = 20
Valori(3) = 30
Infatti, senza agire su tale impostazione del linguaggio, la matrice risulterà composta anche
dall’elemento Valori(0) che, pur avendo un valore uguale a zero, fa sì che la somma di tutti gli
elementi che corrisponde a 60 sia divisa per 4 anziché per 3, come apparentemente è lecito
attendersi.
Figura 8.8 La finestra aperta da EsempioForEach2, se Option Base è stata impostata con il valore zero.
Figura 8.9 La finestra aperta da EsempioForEach2, se Option Base è stata impostata con il valore uno.
NOTA Il ciclo For Each/Next non può essere utilizzato direttamente con i tipi di dati definiti dal programmatore,
perché il compilatore non saprebbe quale valore assegnare alla variabile di controllo tra quelli delle variabili
membro.
L’istruzione For Each/Next può essere utilizzata con successo sugli insiemi di oggetti che Excel
gestisce. Il seguente esempio mostra come creare una funzione che può essere richiamata
all’interno di una cella come una qualunque funzione di Excel quale SOMMA().
Oltre all’impiego dell’istruzione For Each/Next, essa è utile anche per vedere come si può gestire
un parametro del tipo A1:A20.
Function Sommatoria(r As Range) As Double
Dim SingolaCella As Object
For Each SingolaCella In r
Sommatoria = Sommatoria + SingolaCella.Value
Next SingolaCella
End Function
Do While/Loop
Il ciclo Do While/Loop viene utilizzato per indicare un blocco di istruzioni la cui esecuzione inizia
ed è ripetuta fino a quando la condizione indicata nell’istruzione Do While è vera.
Questo tipo di istruzioni viene utilizzato per eseguire un ciclo:
per un numero di volte non predefinibile che può anche essere zero;
quando la condizione di uscita è il risultato di un’azione che non può essere riassunta in
un’espressione, ma è il frutto dell’elaborazione stessa del ciclo; in questi casi si opta per
un’espressione composta da una sola variabile il cui valore segnala all’istruzione Do While se
il ciclo deve essere ripetuto o interrotto.
Nel seguente esempio, il ciclo viene ripetuto fino a quando l’utente non immette un valore
numerico nella finestra:
Sub EsempioWhileWend1()
Dim str As String
L’equivalente esempio che utilizza una variabile per definire se il loop deve terminare è il
seguente:
Sub EsempioWhileWend2()
Dim str As String
Dim f As Boolean
f = True
Do While f
str = InputBox(“digita un numero”)
If IsNumeric(str) Then
F = False
End If
Loop
End Sub
NOTA All’inizio della propria esperienza di programmatore, la creazione delle condizioni del loop appaiono
complesse. Si può ricorrere a un piccolo trucco, ovvero utilizzare un ciclo con la condizione sempre vera, come ad
esempio Do While true e inserire all’interno del ciclo una o più istruzioni if che ne gestiscono l’interruzione (come
spiegato nel relativo capitoletto sull’uscita anticipata). Unica attenzione di ricordarsi di inserire questa if, altrimenti il
ciclo diventa infinito.
È da segnalare che esiste anche la forma While/Wend. Essa proviene dai linguaggi Basic degli anni
’80, ma è sempre meno utilizzata.
Con essa è possibile determinare se il blocco delle istruzioni deve essere eseguito o meno in
relazione al test che viene valutato prima di iniziare a elaborarle. Do/While/Loop e Do Until/Loop
introducono un’istruzione (Exit Do) che consente l’uscita dal ciclo in cui è contenuta, senza
ricorrere all’istruzione GoTo considerata in modo negativo per quanto ne riguarda l’utilizzo. I cicli
Do/Loop While e Do Loop/Until elaborano almeno una volta il blocco delle istruzioni che contengono.
La prosecuzione nella ripetizione del ciclo è invece sancita dal risultato del test. Nella Tabella
8.2 sono messi a confronto i comportamenti dei vari tipi di loop per evidenziare quali prevedono
che le istruzioni del ciclo siano sempre eseguite almeno una volta, indipendentemente dall’esito
del test.
Tabella 8.2 Il test della condizione di un ciclo a volte avviene dopo l’esecuzione delle istruzioni
Le istruzioni del ciclo vengono eseguite con esito
Tipo di ciclo
del primo test dei successivi test
True False True False
While/Wend Sì No Sì No
Do/Loop While Sì Sì Sì No
Do Loop/Until Sì Sì No Sì
Do While/Loop Sì No Sì No
Do Until/Loop No Sì No Sì
For/Next Sì No Sì No
NOTA L’indicazione relativa al ciclo For/Next è da interpretare come la situazione in cui il valore del limite di arrivo è
già stato superato, per esempio con l’istruzione For x = 3 to 1.
Do/Loop While
Il ciclo Do/Loop While consente di definire un insieme di istruzioni che verranno ripetute fino a
quando risulta vera la condizione che appare dopo la parola chiave While. Il seguente esempio
ripropone il ciclo presentato per While/Wend, al fine di comprendere le differenze d’impiego dei due
sistemi:
Sub EsempioDoLoopWhile1()
Dim str As String
Do
Do/Loop Until
Il ciclo Do/Loop Until consente di definire un insieme di istruzioni che saranno ripetute fino a
quando risulti vera la condizione che appare dopo la parola chiave Until. Il seguente esempio
ripropone ancora quello precedente opportunamente modificato:
Sub EsempioDoLoopUntil1()
Dim str As String
Do
str = InputBox(“digita un numero”)
Loop Until IsNumeric(str)
End Sub
Come si può vedere, la routine è identica tranne che per l’istruzione Loop Until, nella quale la
condizione non contiene più l’operatore Not.
GoTo
Le situazioni in cui si rende necessario l’impiego dell’istruzione GoTo sono molto rare, comunque
è utile conoscerla poiché la sua sintassi è veramente semplice, mentre il compito a cui assolve
consiste nel permettere al programmatore di spostare l’esecuzione del programma dal punto in cui
essa viene inserita a una linea individuata da un’etichetta o label.
Nel seguente esempio, la riga con la prima funzione MsgBox non verrà mai eseguita, poiché
l’istruzione GoTo fa in modo che il programma prosegua l’elaborazione con la riga successiva alla
label:
Sub EsempioGoto1()
GoTo SaltaAQuestaPosizione
MsgBox “Questa riga non verra’ mai elaborata”
SaltaAQuestaPosizione:
MsgBox “EsempioGoto1”
End Sub
L’istruzione GoTo vuole il nome della label dalla quale proseguire l’elaborazione: essa va
posizionata alla colonna 1, deve iniziare con una lettera e terminare con il carattere due punti. I
caratteri ammessi sono gli stessi utilizzabili per definire il nome di una funzione.
Per farsi un’idea della struttura che poteva avere un programma scritto con le vecchie versioni
del Basic, si può osservare il listato EsempioGoto2, che è utile soprattutto come autoverifica, per
vedere se si riesce a seguire la logica dei salti. La sequenza delle finestre che aprono la routine è
mostrata nella Figura 8.10.
Sub EsempioGoto2()
MsgBox “Passo 1”
GoTo Pos2
Pos3:
MsgBox “Passo 3”
GoTo Pos4
Pos2:
MsgBox “Passo 2”
GoTo Pos3
Pos4:
MsgBox “Passo 4”
End Sub
L’unica limitazione che l’istruzione GoTo presenta risiede nel fatto che non è possibile saltare
all’esterno della routine o funzione in cui essa è contenuta. Il seguente esempio genererà un errore:
Sub EsempioGotoErratoA()
GoTo Punto
End Sub
Sub EsempioGotoErratoB()
Punto:
End Sub
t1 = Now
While 1
If (Now - t1 > 1 / 24 / 60 / 60) Then
GoTo PuntoUscita
End If
Wend
PuntoUscita:
MsgBox “Ciclo terminato”
End Sub
In alternativa, si può utilizzare una variabile che viene impostata con il valore True, prima che il
ciclo abbia inizio, e al suo interno viene impostata a False, quando è giunto il momento di uscire da
essa:
Sub EsempioWhileInterrotto2()
Dim t1 As Date
Dim Continuare As Boolean
t1 = Now
Continuare = True
While Continuare
If (Now - t1 > 1 / 24 / 60 / 60 Then
Continuare = False
End If
Wend
PuntoUscita:
MsgBox “Ciclo terminato”
End Sub
Do
a = a + 1
If a > 32000 Then
MsgBox “Si rischia che ci metta troppo!”
Exit Do
End If
Loop While 1
End Sub
Capitolo 9
Insiemi di oggetti
Il concetto di oggetto ha più di quindici anni ed è quindi relativamente vecchio rispetto ai tempi
dell’informatica; infatti ha cominciato a essere discusso verso la metà degli anni ‘80.
L’idea sostanziale del tipo di programmazione e dei compilatori che si fondano su tale tecnica si
basa sull’interazione del programma verso componenti software dotati di proprie caratteristiche. Il
programma richiede a essi di svolgere una determinata azione che deve ricadere tra gli obiettivi
dell’oggetto.
Un altro dettaglio molto importante è dato dal fatto che un oggetto può essere composto da altri
oggetti, ereditandone le caratteristiche e le funzionalità più altre routine o funzioni che li
coordinano, ampliando così le possibilità dell’oggetto finale che si deve ottenere.
Finestra di input.
Figura 9.1 Esempio di come sarebbe un oggetto base, che permette di ricavarne altri.
L’oggetto Finestra di visualizzazione sarà arricchito con gli oggetti che seguono (Figura 9.2):
un’area in cui inserire il testo;
un oggetto del tipo Casella di testo all’interno del quale l’utente può inserire alcuni valori;
una gamma di pulsanti che saranno visualizzati nella parte inferiore della finestra in base alle
impostazioni che di volta in volta riceverà;
un sistema per comunicare quale pulsante è stato utilizzato dall’utente per chiuderlo.
Al contrario, l’oggetto Finestra di input sarà arricchito con gli elementi che seguono (Figura
9.3):
un’area in cui inserire il testo;
un oggetto del tipo Casella di testo in cui l’utente può inserire valori;
due pulsanti per consentire all’utente di confermare o annullare;
un sistema per comunicare il contenuto della casella di testo.
A loro volta, questi oggetti potrebbero essere presi come base per altri, per esempio si potrebbe
creare un oggetto di nome Finestra di visualizzazione con icona basato sull’oggetto Finestra di
visualizzazione, al quale venga aggiunta la possibilità di selezionare un’icona che appaia nella
parte sinistra della finestra. Quest’ultima può servire per rafforzare visivamente il tipo
d’informazione che essa fornisce, di volta in volta, all’utente. Questa possibilità, garantita dai
compilatori per la programmazione a oggetti, si chiama ereditarietà.
Il testo che visualizzano le finestre, sia nel titolo sia al loro interno, deve necessariamente poter
essere impostato a seconda delle necessità del programma. Esso viene memorizzato in una
variabile di nome Caption la quale, appartenendo a un oggetto ed essendo accessibile dall’esterno
dell’oggetto stesso, non viene chiamata variabile bensì proprietà. Le proprietà possono essere di
due tipi:
normale (il valore può essere acquisito o impostato);
di sola lettura (il valore può essere solo acquisito, ma non impostato).
Le eventuali funzioni che fanno parte dell’oggetto e possono essere richiamate dall’esterno di
esso vengono denominate metodi.
Alle proprietà e ai metodi di un oggetto si aggiungono gli eventi. Con questo termine si indica un
accadimento, o evento, che l’oggetto è in grado di gestire, eseguendo una specifica routine che il
programmatore ha creato per tali situazioni, assegnando a essa un nome composto dagli elementi
seguenti:
nome dell’oggetto;
carattere underscore;
nome dell’evento.
Gli esempi di nomi di routine che seguono sono relativi ad alcuni eventi per una finestra di
nome UserForm:
UserForm_Activate
UserForm_DblClick
UserForm_KeyPress
UserForm_MouseDown
Il Visual Basic utilizza il carattere punto per indicare l’appartenenza di una proprietà o di un
metodo a un oggetto. Per esempio, la seguente istruzione permette al programma di indicare il
valore della proprietà .Caption per l’oggetto CommandButton1:
CommandButton1.Caption = “Testo sul pulsante”
L’unico problema del programmatore consiste, quindi, nell’individuare il nome della proprietà
che gli può essere utile: gli è d’aiuto la finestra Proprietà che le elenca tutte (si ricorda che essa si
apre selezionando Visualizza/Finestra Proprietà).
NOTA Per evidenziare che si tratta di metodi o proprietà, saranno riportati con il nome preceduto dal punto. È
tuttavia importante sapere che quelli appartenenti all’oggetto Application possono apparire nel programma senza
l’indicazione di tale oggetto e senza il carattere punto.
Application
Application è un oggetto particolare, in quanto potrebbe essere paragonato all’Excel stesso e
contiene al suo interno altri oggetti fondamentali quali le cartelle, che a loro volta contengono i
fogli di lavoro. Esso fornisce al programmatore un numero considerevole di proprietà, metodi ed
eventi. Quelli più importanti sono elencati di seguito.
: insieme di tutte le cartelle aperte, compresa la cartella Personal.xls.
Workbooks
AddIns: insieme di tutti gli AddIn installati sul computer, indipendentemente dal fatto che
siano stati caricati o meno.
NOTA Gli AddIn sono cartelle con estensione .XLA che mettono a disposizione funzionalità aggiuntive e vengono
rese disponibili quando l’AddIn è caricato mediante il percorso Strumenti/Componenti aggiuntivi; per esempio,
Eurotool.xlaè un AddIn che contiene le funzioni per le conversioni delle valute.
Debug : mette a disposizione del programmatore il metodo .Print, che consente di stampare
qualcosa all’interno della finestra Immediata di Visual Basic Editor, e il metodo .Assert, per
definire una condizione che, se non risulta vera, permette di arrestare l’esecuzione del
programma.
Dialogs: insieme contenente tutte le finestre di dialogo di Excel. Esso viene richiamato
mediante il metodo .Item() che necessita di un numero per il tipo di finestra richiesta e può
essere sostituito dall’equivalente costante.
CommandBars: insieme di tutte le barre degli strumenti e dei menu di Excel.
Names: insieme di tutti i nomi che sono stati creati all’interno di una cartella con il comando
una delle funzioni disponibili sul foglio di lavoro, per esempio SOMMA().
RecentFiles: insieme di oggetti contenenti il nome delle cartelle aperte di recente che sono
criteri di ricerca.
VBE: fornisce uno strumento per acquisire informazioni, attraverso diverse proprietà, relative a
NOTA È possibile utilizzare le proprietà e i metodi di Application ricorrendo al riferimento implicito, che consente di
scrivere molto velocemente istruzioni più compatte: eliminando l’oggetto e il carattere punto, Visual Basic tenterà di
individuare l’oggetto che dispone di tale proprietà o metodo attraverso alcune regole di ricerca.
.SheetsInNewWorkbook
La proprietà .SheetsInNewWorkbook consente di conoscere il numero di fogli che conterrà ogni
nuova cartella, in base a quanto è stato impostato dall’utente nella casella Fogli nella nuova
cartella, contenuta nella scheda Generale della finestra Opzioni di Excel. Essa permette altresì di
impostare tale valore. Il seguente esempio verifica che ogni nuova cartella contenga almeno cinque
fogli di lavoro:
If Application.SheetsInNewWorkbook < 5 Then
Application.SheetsInNewWorkbook = 5
End If
FileSearch
L’oggetto .FileSearch consente di creare una matrice contenente tutti i file il cui nome
corrisponde a un criterio di ricerca, specificato attraverso le proprietà elencate di seguito.
.LookIn: accetta una stringa con il percorso in cui fare la ricerca.
.FileName: consente di indicare il criterio o il nome del file da ricercare. Si accettano le
combinazioni di caratteri quali ? e *, analogamente a quanto si utilizzava nel comando Dir del
Dos.
.FileType: costituisce un’alternativa a .FileName e permette di indicare il tipo di file che
deve essere ricercato attraverso alcune costanti che sono in grado di gestire tutte le relative
estensioni.
.SearchSubFolders: viene indicato, attraverso il valore booleano True o False, se la ricerca
dovrà avvenire solo nella cartella indicata in .LookIn o essere estesa alle eventuali cartelle
che essa contiene.
.Execute: avvia la ricerca in base a quanto specificato attraverso le precedenti proprietà.
Genera una matrice di nomi di file, completi del percorso, contenuta nella proprietà
.FoundFiles.Item, mentre la proprietà .FoundFiles.Count permette di conoscerne il numero.
L’esempio seguente effettua una ricerca nella cartella “c:\Archivi”, e nelle eventuali
sottocartelle, di tutti i file con estensione .XLS, per visualizzarne il nome in gruppi di quindici
mediante la MsgBox:
Sub RicercaTuttiIFileExcel()
Dim f As Long
Dim str As String
Dim Pagina As Long
Application.FileSearch.LookIn = “C:\Archivi\”
Application.FileSearch.Filename = “*.xls”
Application.FileSearch.FileType = _
msoFileTypeExcelWorkbooks
Application.FileSearch.SearchSubFolders = True
Application.FileSearch.Execute
For f = 1 To Application.FileSearch.FoundFiles.Count
str = str & Application.FileSearch.FoundFiles(f) & _
vbCr
If (f Mod 15 = 0) Then
Pagina = Pagina + 1
MsgBox str, , “Pagina numero “ & Pagina
str = Empty
End If
Next f
MsgBox str
End Sub
.GetOpenFilename
Il metodo .GetOpenFilename rappresenta un interessante sistema per i programmatori che
desiderano gestire il dialogo con l’utente, per la selezione dei file da aprire, avvalendosi della
finestra Apri di Windows, ma evitando che venga aperto automaticamente e rimandando tale
operazione a un momento successivo:
Sub FinestraDialogoApriConAperturaGestitaDalVBA()
Dim Nome As String
Nome = Application.GetOpenFilename
If Len(Nome) > 0 And Nome <> “Falso” Then
MsgBox “Il programma aprirà” & Nome
Application.Workbooks.Open (Nome)
End If
End Sub
.Evaluate
Il metodo .Evaluate consente di ottenere il valore contenuto nella cella con il nome indicato
come parametro. La Figura 9.4 mostra un esempio. La seguente istruzione visualizza il valore della
cella alla quale è stato assegnato il nome CostoLitroBenzina attraverso il percorso Formule/Definisci
nome:
MsgBox Application.Evaluate(“CostoLitroBenzina”)
Figura 9.4 Esempio di applicazione del metodo Evaluate per visualizzare il valore di una cella.
Windows
L’insieme di oggetti Windows contiene vari oggetti di tipo Window e consente di utilizzare le
funzioni disponibili nel menu Windows di Excel, attraverso alcuni metodi e proprietà. Alcuni
esempi si trovano nell’elenco riportato di seguito:
Attivare la finestra contenente la cartella Cartel1:
Application.Windows(“Cartel1.xls”).Activate
Rendere visibile a tutto schermo la prima finestra riportata nell’elenco delle finestre aperte,
la quale coincide con la cartella correntemente attiva:
Windows.Item(1).WindowState = xlMaximized
Creare una nuova finestra che visualizza una cartella già aperta e ottenere il numero che la
identifica come non univoca per quella cartella:
ActiveWindow.NewWindow
win = ActiveWindow.WindowNumber
Workbooks
L’oggetto Workbooks è contenuto nell’oggetto Application e rappresenta l’insieme delle cartelle di
Excel correntemente aperte (Figura 9.5). Gli oggetti più interessanti che contiene sono i seguenti:
Worksheets , l’insieme dei fogli di lavoro appartenenti alla cartella;
BuiltinDocumentProperties, insieme dei valori inseriti o visibili nella finestra Proprietà di Excel;
.Item()
Ogni foglio di lavoro contenuto nella cartella è accessibile attraverso la proprietà .Item() che
richiede un indice per selezionare quello desiderato. L’istruzione seguente visualizza il nome del
primo foglio di lavoro contenuto nella prima cartella:
MsgBox Workbooks.Item(1).Worksheets.Item(1).Name
Cartella corrente
La cartella corrente viene individuata attraverso la proprietà .Active Workbook di Application che
restituisce un oggetto di tipo Workbook:
Sub EsempioActiveWorkbook()
Dim n As Long
n = ActiveWorkbook.Sheets.Count
MsgBox “La cartella attiva e’ composta da “ & n & “ _
fogli”
End Sub
Debug
Il metodo Debug è utile durante le fasi di sviluppo e verifica dei programmi, in quanto permette di
inserire righe che, quando vengono eseguite, possono inviare un messaggio nella finestra
Immediata di Visual Basic Editor. Il programmatore può servirsene per vari scopi: verificare se
l’esecuzione del programma è transitata per un determinato punto oppure conoscere il valore di
una variabile in un determinato momento. In tali casi si utilizza il suo metodo .Print.
La routine EsempioDebugPrint esegue un ciclo su tutti i fogli di tutte le cartelle e, quando trova la
cella A1 che contiene qualcosa, provvede a segnalarlo al programmatore (Figura 9.6).
L’oggetto Debug dispone di un altro metodo che all’apparenza può sembrare strano o pericoloso,
mentre ha una propria utilità. Si tratta di .Assert, il cui compito consiste nelle operazioni seguenti:
arrestare temporaneamente l’esecuzione del programma nel caso in cui una condizione risulti
False;
Figura 9.6 Eseguendo EsempioDebugPrint, nella finestra Immediata di Visual Basic Editor appare il nome del foglio che
contiene un valore in A1 seguito dal valore stesso.
In questo modo il programmatore può applicare le operazioni che ritiene più opportune. La
routine EsempioDebugAssert analizza tutti i fogli di lavoro e interrompe l’esecuzione nel caso ne
trovi uno in cui la cella A1 contenga il valore “Questo e’ il valore della cella A1”:
Sub EsempioDebugAssert()
Dim wb As Variant
Dim ws As Variant
Ora il programmatore potrebbe avvalersi della finestra Immediata per verificare il valore delle
proprietà degli oggetti ws e wb, o altri valori che ritiene importanti, per comprendere lo stato del
programma e i motivi che hanno condotto alla situazione corrente.
Dialogs
L’oggetto Dialogs contiene tutte le finestre di dialogo disponibili in Excel che possono essere
utilizzate dal programmatore, evitando di dover costruire propri UserForm che svolgono lo stesso
lavoro di quelli standard come, per esempio, la finestra Apri oppure Salva con nome.
Ogni finestra è contenuta in un apposito oggetto di tipo Dialog, al quale si accede mediante la
proprietà .Item() che richiede un indice che identifica la finestra richiesta. Le finestre sono oltre
duecento e molte non vengono utilizzate dalla maggior parte dei programmatori; di seguito viene
fornita una routine che permette di visualizzarle tutte in sequenza:
Sub EsempioDialogs()
Dim dlg As Variant
Dim r As Integer
Worksheets(1).Activate
For dlg = 1 To Application.Dialogs.Count
r = r + 1
Cells(r, 1) = Application.Dialogs.Item(dlg).Show
Next dlg
End Sub
NOTA L’indice può essere inserito ricorrendo alle costanti messe a disposizione da Visual Basic Editor per le
finestre di dialogo; in linea di principio il loro nome è composto dal prefisso xlDialog seguito dal nome inglese della
finestra: per esempio, la costante della finestra Apri si chiama xlDialogOpen.
CommandBars
L’insieme CommandBars è utilissimo per i programmatori che vogliono creare nuove barre
degli strumenti oppure inserire, in quelle esistenti, nuovi oggetti quali pulsanti, liste, caselle di
testo ecc.
Nell’esempio della routine EsempioCommandBars2 viene illustrato come visualizzare le barre
di comando Pattern, Chart, WordArt e Web:
Sub EsempioCommandBars2()
Application.CommandBars.Item(“Pattern”).Visible = True
Application.CommandBars.Item(“Chart”).Visible = True
Application.CommandBars.Item(“WordArt”).Visible = True
Application.CommandBars.Item(“Web”).Visible = True
End Sub
Windows
L’insieme Windows contiene tanti oggetti quante sono le finestre correnti aperte in Excel, più
vari metodi per selezionarle o sistemarle analogamente alle funzionalità messe a disposizione dal
menu Finestra. La routine EsempioWindows1 esegue un ciclo per un numero di volte pari al
numero di oggetti contenuti nell’insieme Windows, al fine di attivare ogni finestra e accodare il
suo titolo in una variabile di tipo String, il cui contenuto verrà visualizzato a esecuzione terminata:
Sub EsempioWindows1()
Dim w As Integer
Dim str As String
For w = 1 To Windows.Count
str = str & Windows.Item(w).Caption & vbCr
Windows.Item(w).Activate
Next w
WorksheetFunction
L’insieme WorksheetFunction arricchisce le funzioni native di VBA rendendo disponibili quelle
di Excel. La seguente istruzione esemplifica come utilizzare la funzione .Power() di Excel
passandole come parametri i valori 8 e 2:
v = WorksheetFunction.Power(8, 2)
Worksheets
L’insieme Worksheets contiene tutti i fogli di una cartella di lavoro, più specificatamente la
cartella a cui esso appartiene; inoltre, a ogni foglio di lavoro corrisponde un oggetto di tipo
Worksheet.
Per accedere ai vari fogli si utilizza la proprietà .Item(). La subroutine che segue applica un
ciclo basato su tutte le cartelle aperte e contiene un altro ciclo basato su tutti i fogli della cartella
presa in esame dal ciclo esterno; lo scopo del ciclo è acquisire il nome di ogni foglio e riportarlo,
corredato dal nome della cartella a cui appartiene, nel primo foglio della cartella:
Sub EsempioLoopSuTuttiFogliDiTutteCartelle()
Dim nwb As Integer
Dim nws As Integer
Dim r As Integer
Dim wbNome As String
Dim wsNome As String
La subroutine è molto interessante perché illustra diversi aspetti importanti, quali i seguenti:
come accedere a tutte le cartelle che vengono individuate dalla proprietà .Item();
come acquisire il numero di cartelle aperte includendo quelle nascoste, quale Personal.xls;
come acquisire il numero di fogli di lavoro di cui dispone una determinata cartella.
L’istruzione seguente:
For nwb = 1 To Workbooks.Count
avvia un ciclo che verrà ripetuto tante volte quante sono le cartelle aperte, informazione resa
disponibile dalla proprietà .Count applicata all’oggetto Workbooks, mentre l’istruzione:
For nws = 1 To Workbooks.Item(nwb).Worksheets.Count
avvia un altro ciclo che sarà ripetuto tante volte quanti sono gli oggetti Worksheets contenuti
nella mesima cartella.
Applicando a tali oggetti la proprietà .Name, diventa possibile acquisire i nomi dei singoli
oggetti che potranno essere memorizzati all’interno del primo foglio, appartenente alla seconda
cartella aperta.
Più precisamente l’istruzione:
Workbooks.Item(2).Sheets(1).Cells(r, 1) = wbNome
memorizza, nella prima colonna e alla riga individuata dalla variabile r, il nome dell’oggetto
Workbook che è stato copiato nella variabile wbNome. Analogamente si comporta l’istruzione
seguente:
Workbooks.Item(2).Sheets(1).Cells(r, 2) = wsNome
Come si può vedere, il codice risulta molto più compatto e, quando si avrà un poco di
confidenza con gli oggetti e gli insiemi di oggetti, anche molto più leggibile. Comunque seguono
alcune annotazioni per renderlo più chiaro.
Le variabili di controllo wb e ws del ciclo non sono più utilizzate come indici nelle proprietà
.Item() e il loro tipo è stato modificato in Variant in accordo con quanto richiesto dal ciclo For
Each/Next.
Il primo ciclo opera su tutti gli oggetti contenuti all’interno dell’oggetto Workbooks che è
implicitamente contenuto in Application.
Il secondo ciclo è particolarmente interessante e analizza tutti gli oggetti contenuti nell’insieme
Worksheets che appartiene al Workbook attualmente in analisi, identificato attraverso la variabile
di controllo del ciclo esterno.
L’impiego della proprietà .Name risulta molto più immediato.
Un altro sistema per accedere agli oggetti Workbooks e Worksheets, che può essere impiegato
praticamente su qualunque oggetto, si basa sull’impiego di variabili di tipo Object. La routine
seguente assegna alla variabile wb l’indirizzo del secondo elemento dell’insieme Workbooks e lo
utilizza per visualizzare il valore della sua proprietà .Name:
Sub EsempioVariabileObjectPerWorkbook()
Dim wb As Object
Set wb = Workbooks.Item(2)
MsgBox wb.Name
End Sub
Set ws = Workbooks.Item(2).Worksheets.Item(1)
MsgBox ws.Name
Figura 9.8 La macro visibile nella finestra elenca, all’interno del primo foglio della prima cartella, tutte le cartelle aperte e i
nomi dei fogli che esse contengono.
End Sub
NOTA Quando si utilizzano le variabili di tipo Object è indispensabile ricordarsi di ricorrere all’istruzione Set per
assegnare loro un valore, altrimenti Visual Basic Editor visualizzerà un messaggio di errore.
Font
L’oggetto Font ricorre praticamente in ogni oggetto che visualizzi il testo, come le celle del
foglio di lavoro e le finestre create dal programmatore, e dispone delle proprietà riportate nella
Tabella 9.1.
NOTA Quando si sta indicando che è necessario fare ricorso alla funzione RGB() per ottenere il codice colore,
significa che è necessario indicare il colore come risultato della combinazione di rosso, verde e blu, ciascuno
misurato su una scala da 0 a 255; i valori sono poi da convertire nel codice colore corrispondente, richiamando la
funzione RGB() e passandole i tre valori. Essa, in questo modo, restituisce un codice numerico di tipo Long
corrispondente alla combinazione di colori indicata.
Creare le finestre
Oggi, creare un programma che utilizzi una finestra per dialogare con l’utente è diventato più
semplice rispetto allo sforzo richiesto alcuni anni fa. Queste finestre sono create con una tecnica
chiamata visuale, che si basa su un oggetto detto, appunto, finestra al quale sono aggiunti altri
oggetti quali caselle di testo, pulsanti e liste a discesa.
Terminologia
UserForm: è utilizzato per indicare le finestre create dal programmatore.
Focus: è un sostantivo che indica il componente della finestra attivo in un determinato
momento.
I preliminari
Il primo passo per costruire una finestra consiste nell’avere ben chiare le idee riguardo il suo
scopo e gli strumenti di cui si dovrà disporre per raggiungerlo. Il programma non è più l’elemento
fondamentale, che invece diventa la finestra: a essa dovranno essere associate routine che saranno
eseguite in risposta a determinati eventi, quali il clic del mouse o un inserimento di dati in una
casella da parte dell’utente.
Nel corso di questo capitolo saranno fornite le indicazioni necessarie per affrontare questo tipo
di lavoro, anche se non potranno essere esaustive; per esempio, non verranno riportate e illustrate
tutte le proprietà degli oggetti, poiché numerose e non indispensabili, evitando quindi di
confondere il lettore o di non consentire una rapida focalizzazione. Il Visualizzatore oggetti
contiene tuttavia tutte le informazioni per soddisfare le eventuali curiosità in proposito.
NOTA Durante la fase di test delle finestre può capitare di incontrare situazioni apparentemente senza senso
riconducibili a Visual Basic Editor quali:
NOTA Queste e altre anomalie sono spesso dovute ai seguenti problemi di Excel:
NOTA La prima cosa da fare, quando si riscontrano anomalie, consiste nel tornare in Excel per controllarne lo
stato.
Ricordare questo dettaglio significa non perdere tempo a cercare di visualizzare tale finestra e a
capire come comportarsi se scompare facendo doppio clic o eseguendo altre operazioni. A questo
riguardo, il menu Finestra è indubbiamente di aiuto, in quanto permette di vedere:
la voce relativa al nuovo UserForm;
la voce del codice relativa allo UserForm, se è già stata creata involontariamente (Figura
10.2).
Figura 10.2 Il menu Finestra dopo la creazione di una nuova finestra e del suo codice.
NOTA Si tenga presente che la finestra Proprietà visualizza informazioni relative all’oggetto correntemente
selezionato, il cui nome viene riportato per comodità immediatamente sotto l’intestazione.
NOTA Il primo oggetto a essere selezionato avrà le maniglie di colore bianco, a differenza degli altri che le avranno
nere.
Per deselezionare un oggetto che è stato erroneamente selezionato è sufficiente fare clic sopra di
esso, tenendo premuto il tasto Ctrl.
NOTA Una finestra modale non impedisce all’utente di passare a un altro software, ma solo a quello a cui essa
appartiene, in questo caso Excel.
Indubbiamente le finestre non modali sono quelle più apprezzate dall’utente, che può
sospendere l’interazione con essa, magari per spostarsi su un foglio in cerca di informazioni
richieste dalla finestra; per il programmatore, le finestre modali sono quelle che richiedono un
numero inferiore di attenzioni, in quanto tutto quello che avviene è limitato all’interazione
dell’utente con la finestra, per cui è relativamente facile prevedere tutte le condizioni che possono
verificarsi.
Per i programmi destinati a essere elaborati in Excel, la scelta tra i due tipi è abbastanza
scontata ed è orientata verso il tipo modale, anche in virtù del fatto che l’utente è abituato a esso,
anche se il tipo non modale potrebbe essere ugualmente apprezzato.
Nell’ipotetico caso esistesse la necessità di modificare l’allineamento verticale di celle non
contigue, l’utente dovrebbe:
selezionare la cella;
richiamare la finestra che gestisce l’allineamento verticale e selezionare quello di volta in
volta più opportuno;
chiudere la finestra.
Occorre quindi ripetere queste operazioni per tutte le celle da riformattare.
La finestra Formato celle è di tipo modale, ovvero l’utente la richiama, imposta i parametri
secondo le proprie necessità e la chiude indicando al programma che deve applicare le
impostazioni alla cella attiva o a quelle selezionate (Figura 10.4). Diversamente, se tale finestra
fosse di tipo non modale, essa rimarrebbe sempre aperta evitando all’utente di riaprirla
continuamente.
Figura 10.4 La finestra di Excel da utilizzare per applicare la formattazione relativa all’allineamento verticale. Essa viene
aperta con la modalità ShowModal.
Già da questo esempio si potrebbero trarre numerose riflessioni sulla scelta tra il tipo modale o
non modale: in alcuni casi la programmazione sembra essere un’arte e cosa sia meglio o più utile
porta a lunghe disquisizioni accademiche.
Il suggerimento che si può dare in questi casi è utilizzare le finestre modali, in quanto non
causano alcun tipo di complicazione, come la nessessità di aggiungere al programma controlli per
evitare errori (per esempio, per verificare se la cartella sulla quale la finestra deve agire non è
stata chiusa nel frattempo, oppure se l’utente ha avviato lo stesso programma più volte).
Il punto cruciale che impone il ricorso alla finestra di tipo modale può essere riassunto in una
domanda: le informazioni che vengono introdotte nella finestra sono necessarie o indispensabili
per la prosecuzione? Se la riposta è affermativa non vi sono dubbi di sorta.
Se si è deciso per creare una finestra non modale, allora si deve impostare la proprietà ShowModal
con il valore False: tale proprietà non è accessibile ai programmi, quindi non è possibile
impostarla dall’interno di una routine, ma può comunque essere successivamente variata attraverso
Visual Basic Editor.
NOTA Un programma che utilizza una finestra modale può comunque aprire altre finestre.
Quello che è invece necessario conoscere sono le caratteristiche dei controlli, che vengono qui
elencati rispettando l’ordine in cui appaiono nella Casella degli strumenti:
Etichetta o Label
Casella di testo
Casella combinata
Casella di riepilogo
Casella di controllo
Pulsante di opzione
Pulsante interruttore
Cornice
Pulsante di comando
Schede
Pagine
Barra di scorrimento
Pulsante di selezione
Immagine
RefEdit
Il componente Etichetta, o label (Figura 10.6), consente di creare un oggetto sulla finestra il cui
scopo è visualizzare un testo che viene digitato:
nella proprietà .Caption:
Label1.Caption = “Testo dell’Etichetta”
direttamente all’interno del controllo dopo averlo selezionato con due clic del mouse,
facendo attenzione a non farli troppo ravvicinati per evitare che siano interpretati come un
doppio clic (in questo caso verrebbe aperta la finestra relativa al codice e si dovrebbe
utilizzare il menu Finestra per tornare alla finestra dello UserForm).
Figura 10.6 Come appare un controllo Etichetta in fase di progettazione della finestra.
Le caratteristiche del testo che viene visualizzato all’interno del componente Etichetta possono
essere specificate attraverso le sue proprietà, in particolare Font che consente di agire su tutti gli
attributi del carattere (Figura 10.7). Essi possono essere anche impostati attraverso il programma
utilizzando l’oggetto Font; per esempio, la seguente istruzione modifica l’oggetto di nome Label1
attivando l’attributo Grassetto per il testo che visualizza:
Label1.Font.Bold = True
Figura 10.7 La finestra Tipo di carattere che si apre facendo clic sul pulsante ... presente nella voce Font della finestra
Proprietà.
Altre proprietà dell’oggetto Etichetta che possono risultare utili sono riportate nella tabella
seguente (Figura 10.8).
Nome della
Scopo
proprietà
ControlTipText
Definisce una stringa che viene visualizzata sotto il puntatore del cursore quando l’utente
indugia sopra di esso.
AutoSize
La dimensione del controllo viene automaticamente modificata per adattarsi alla dimensione del
testo che contiene.
TextAlign Definisce l’allineamento del testo optando tra sinistra (default), centrato e destra.
WordWrap
Consente all’etichetta di mandare a capo il testo se la lunghezza complessiva supera quella del
controllo.
Figura 10.8 Le proprietà del componente Label (etichetta).
Figura 10.9 Come appare il controllo Casella di testo in fase di progettazione della finestra.
Casella combinata o ComboBox
Il componente Casella combinata (Figura 10.10) consente all’utente di inserire un valore
attraverso due sistemi:
a digitazione;
la scelta di una voce presente nella lista che si apre facendo clic sul pulsante posto alla fine
della casella.
Figura 10.10 Come appare il controllo Casella combinata in fase di progettazione della finestra.
Il valore digitato può essere acquisito mediante la proprietà Value. Il seguente listato è una
routine, associata a un controllo di nome CommandButton1, che provvede a copiare il valore della
casella combinata di nome MezziDiTrasportoUtilizzabili in TextBox1:
Private Sub CommandButton1_Click()
TextBox1.Text = MezziDiTrasportoUtilizzabili.Value
End Sub
La stessa proprietà consente di impostare il valore che tale controllo deve visualizzare, magari
come opzione da proporre all’utente:
MezziDiTrasportoUtilizzabili.Value = “Automobile”
Per inserire i valori all’interno della lista si può ricorrere al metodo Add-Item; il seguente
esempio carica alcuni valori in un componente ComboBox di nome MezziDiTrasportoUtilizzabili:
MezziDiTrasportoUtilizzabili.AddItem (“Motocicletta”)
MezziDiTrasportoUtilizzabili.AddItem (“Bicicletta”)
MezziDiTrasportoUtilizzabili.AddItem (“Autobus”)
MezziDiTrasportoUtilizzabili.AddItem (“Taxi”)
MezziDiTrasportoUtilizzabili.AddItem (“Aereo di linea”)
MezziDiTrasportoUtilizzabili.AddItem (“Aereo noleggiato”)
Per la loro capacità di interagire direttamente con il foglio di lavoro, risultano interessanti le
proprietà illustrate di seguito.
Row Source: è possibile assegnarle un riferimento stile Excel dal quale prenderà i valori che
verranno visualizzati all’utente; per esempio, si può assegnare A1:A8 mediante Proprietà
oppure “A1:A8” se si utilizza una macro.
Control Source: contiene il riferimento alla cella nella quale verrà copiato il valore che
l’utente introdurrà nel controllo.
uno o più di uno, tra loro contigui, se la proprietà Multiselect è impostata a uno ovvero con la
costante fmMultiSelectMulti;
uno o più di uno, anche se non sono tra loro contigui, se la proprietà Multiselect è impostata a
uno ovvero con la costante fmMultiSelectExtended.
Figura 10.11 Come appare il controllo Casella di riepilogo in fase di progettazione della finestra.
Per controllare quali voci siano state selezionate dall’utente, si può ricorrere a un ciclo che
verifica ogni elemento per determinare se è selezionato o meno. La seguente routine è un esempio
di come deve essere costruito il loop: in questo caso, il suo scopo è visualizzare una finestra che
riepiloga tali voci:
Private Sub CommandButton1_Click()
Dim n As Integer
Dim Selezionato As Boolean
Dim s As String
For n = 0 To MezziDiTrasportoUtilizzati.ListCount - 1
Selezionato = MezziDiTrasportoUtilizzati.Selected(n)
If Selezionato Then
s = s & MezziDiTrasportoUtilizzati.List(n)
s = s & vbCr
End If
Next n
MsgBox s
End Sub
NOTA Gli elementi del componente Casella di riepilogo sono numerati da zero indipendentemente dalle
impostazioni di Option Base; per questo motivo, il loop viene eseguito da zero fino al numero di elementi in esso
contenuti decrementato di un’unita: per esempio, se esistono tre elementi la proprietà Count restituisce il valore 3
(comunque essi sono numerati da zero a due).
Casella di controllo o CheckBox
Le caselle di controllo sono un altro componente presente molto spesso nelle finestre (Figura
10.12); il loro compito consiste nel fornire all’utente la possibilità di contrassegnare una scelta
facendo clic con il mouse per visualizzare il tipico segno di spunta. Il testo descrittivo viene
inserito attraverso la proprietà Caption, disponibile sia al programma sia, più comodamente, nella
finestra Proprietà di Visual Basic Editor. Per sapere se l’utente ha attivato o disattivato la casella,
si ricorre alla proprietà Value. Il seguente codice di esempio controlla se l’utente ha attivato una
casella di nome StampareBusta:
If StampareBusta.Value = True Then
Call EsegueStampaDellaBusta
End If
Figura 10.12 Come appare il controllo Casella di controllo in fase di progettazione della finestra.
Figura 10.13 Come appare il controllo Pulsante di opzione in fase di progettazione della finestra.
Per poter gestire più insiemi di pulsanti di opzione si deve ricorrere a una sorta di contenitore
che consenta allo UserForm di sapere quali devono interagire tra loro e quali no (Figura 10.14): la
Cornice o Frame.
È utile ritornare al concetto di oggetto che ne può contenere altri: la finestra è un oggetto che può
contenere più pulsanti di opzione dei quali solo uno può essere selezionato. Se essa contiene un
oggetto Cornice il quale, a sua volta contiene altri oggetti Pulsante di opzione, essi costituiranno
un gruppo separato all’interno del quale vi sarà un solo Pulsante di opzione selezionato. In questo
modo si contano già due pulsanti di opzione attivi: uno contenuto nell’oggetto UserForm e un altro
nell’oggetto Cornice dentro UserForm. Applicando questo concetto si potranno avere più cornici
per creare gruppi indipendenti di
Figura 10.14 Come appare uno UserForm con una serie di gruppi di pulsanti di opzione raggruppati in quattro insiemi.
Quelli numerati da 1 a 4 appartengono all’insieme degli UserForm.
pulsanti di opzione, arrivando a inserire in una cornice altre cornici, ognuna delle quali
potrebbe avere gruppi di pulsanti di opzione tra loro indipendenti.
Il controllo per determinare se un Pulsante di opzione è stato selezionato o meno può essere
effettuato analizzando la proprietà Value, che restituisce il valore booleano True o False a seconda
dei casi.
Cornice o Frame
Il componente Cornice viene impiegato per creare un insieme di componenti che abbiano tra
loro una relazione, per cui può risultare utile raggrupparli (Figura 10.15).
Per fini estetici e di immediatezza: per esempio, in una finestra in cui devono essere inseriti
dati relativi a una coppia spostata, questi possono essere raggruppati in due Cornici distinte;
Per motivi tecnici: i pulsanti di opzione contenuti in una cornice opereranno come un gruppo,
per cui attivare uno di essi significa disattivare tutti quelli appartenenti allo stesso gruppo; in
tal modo è possibile avere più gruppi di pulsanti di opzione che non interferiscano
reciprocamente.
Figura 10.15 Come appare un controllo Cornice in fase di progettazione della finestra.
Ogni cornice può avere una scritta che appare nella parte superiore; può esservi indicato il
contenuto della cornice (Figura 10.16) in modo da guidare l’utente a una migliore lettura della
finestra. Questo testo viene inserito mediante la proprietà Caption.
Figura 10.16 Esempio di utilizzo delle Cornici per migliorare la leggibilità della finestra.
Scheda o TabStrip
Il componente Scheda serve per avere più controlli raggruppati su diverse schede ed è analogo
al controllo Pagina che, però, è più immediato, per cui si suggerisce di utilizzare quest’ultimo.
Pagina o Page
Se una finestra visualizza troppe informazioni, generalmente diventa poco leggibile e tende a
confondere l’utente.
In queste situazioni, il controllo Pagina si rivela utile in quanto consente di creare un’area
concettualmente suddivisa in più livelli, ciascuno dei quali è un insieme di oggetti che saranno
visualizzati a turno (Figura 10.18).
L’ordine di visualizzazione si basa sulla scheda che l’utente decide di vedere agendo sulla
linguetta posta nella parte superiore del controllo Pagina.
Figura 10.18 Come appare il controllo Pagina in fase di progettazione della finestra.
Anche nei casi in cui non vi sia un reale sovraffollamento di informazioni ma, più
semplicemente, siano presenti informazioni utilizzate più raramente, è possibile conferire alla
finestra una migliore leggibilità utilizzando due o più schede in cui inserire i dati meno utili che
siano comunque immediatamente disponibili per l’utente, qualora desiderasse consultarli o
modificarli.
Di seguito è descritto come utilizzare questo controllo.
Per prima cosa si crea il controllo Pagina sulla finestra.
Si assegna il testo descrittivo alla scheda agendo sulla sua proprietà Caption.
Si inseriscono i controlli appartenenti alla prima scheda.
Si assegna il nome alla scheda, sostituendo quello di default con un altro più descrittivo e
utilizzando il menu contestuale.
Una volta completata una scheda, si passa a quella successiva facendo clic sulla sua linguetta;
possono essere create schede con il menu contestuale, se non ve ne sono altre disponibili.
Le Figure 10.19 e 10.20 mostrano alcuni esempi.
NOTA Il menu contestuale del controllo Pagina verrà descritto nel prossimo paragrafo.
Immagine o Image
Il componente Immagine riserva un’area nella quale potrà essere caricata un’immagine che sarà
visualizzata nella finestra. L’immagine viene indicata:
all’interno di Visual Basic Editor attraverso la proprietà Picture;
dal programma, mediante la proprietà Picture alla quale viene assegnato il risultato della
funzione LoadPicture() che riceve come parametro, il nome dell’immagine da caricare (Figura
10.21).
Figura 10.21 Come appare un controllo Immagine dopo aver specificato l’immagine attraverso la proprietà Picture.
rispettando le proporzioni;
fmPictureSizeModeClip per rispettare le dimensioni originarie.
RefEdit
Il controllo RefEdit è uno strumento molto interessante per i programmatori in Visual Basic per
Excel, infatti permette all’utente di inserire un riferimento a una o più celle mediante il mouse, in
modo simile a quanto può fare con altre funzionalità di Excel come Ricerca obiettivo (Figura
10.23).
Figura 10.23 La finestra Ricerca obiettivo che si apre da Dati/Analisi di Simulazione/Ricerca obiettivo di Excel: la prima e
l’ultima casella sono componenti RefEdit.
Tutta la gestione è a carico di Visual Basic; quando l’utente preme il pulsante alla destra del
componente RefEdit la finestra viene nascosta e ne appare un’altra, che consente di accedere al
foglio di lavoro e selezionare una cella o un’insieme di celle (Figura 10.24): i riferimenti di tale
selezione vengono copiati nella nuova finestra. Al termine di questa operazione l’utente deve fare
un altro clic sul pulsante della casella, la finestra si richiuderà e quella originaria tornerà visibile,
mentre all’interno del controllo RefEdit su cui si era fatto clic compariranno i riferimenti
selezionati dall’utente.
Figura 10.24 Il risultato che si ottiene facendo clic sul pulsante collocato a destra di una casella RefEdit; la finestra
originaria si nasconde e viene sostituita.
Il programmatore non deve fare altro che acquisire, nel momento in cui gli servono, i riferimenti
selezionati o digitati, ricorrendo alla proprietà Text. La seguente routine visualizza i riferimenti
inseriti nel componente RefEdit quando viene fatto clic su un pulsante di nome CommandButton1:
Private Sub CommandButton1_Click()
Dim str As String
str = RefEdit1.Text
MsgBox “Il riferimento e’ : “ & str
End Sub
NOTA Se il componente RefEdit non è visibile sulla Casella degli strumenti, significa che esso non è configurato.
Per risolvere, fare clic con il tasto destro del mouse nella parte più interna della Casella degli
strumenti per aprire il menu contestuale in cui andrà selezionata la voce Controlli Aggiuntivi
(Figura 10.25). per aprire l’omonima finestra: nell’elenco Controlli disponibili, cercare la voce
RefEdit.Ctrl e selezionarla (Figura 10.26).
Alla chiusura della finestra, nella Casella degli strumenti sarà disponibile l’icona del controllo
RefEdit.
NOTA La dichiarazione delle routine di uno UserForm è preceduta dalla parola chiave Private per rendere tali
routine inaccessibili agli altri moduli o UserForm. Se si desidera condividere una routine con altre finestre,
conviene realizzare una routine separata (non di tipo Private) che possa essere richiamata dalle varie routine degli
UserForm.
Capitolo 11
Terminologia
Di seguito sono elencati alcuni termini informatici, tanto per chiarire qualche concetto.
Ambiente. Insieme di fattori disgiunti o concomitanti, con cui il programma deve rapportarsi:
versione del software, spazio libero su disco fisso, esecuzione contemporanea di altri
programmi e lingua.
Compilazione. Fase in cui Visual Basic Editor converte le istruzioni in un formato interno,
eseguibile come programma.
Sintassi. Insieme di regole formali che indicano come un’istruzione può essere costruita.
Errori sintattici
Quello sintattico è il primo tipo di errore con cui il programmatore moderno deve confrontarsi.
È causato da un’istruzione scritta con errori formali come, per esempio, i seguenti:
omettere il nome identificativo nell’istruzione Sub o Function;
una parola chiave digitata erroneamente;
una parola chiave digitata ma omessa;
mancanza di una parentesi, una virgola oppure uno o più parametri obbligatori nella chiamata
di funzioni o subroutine;
suddividere un’istruzione su più linee senza utilizzare correttamente i caratteri spazio e
underscore;
concatenare stringhe e variabili, utilizzando l’operatore & senza lasciare gli spazi tra i vari
componenti;
creare espressioni nelle quali non è presente una corrispondenza corretta tra le parentesi
aperte e chiuse;
accedere a un elemento di una matrice senza utilizzare l’indice;
cercare di assegnare un valore a una proprietà non modificabile di un oggetto.
Questo genere di errori viene individuato da Visual Basic Editor nel momento stesso in cui si
preme il tasto Invio, oppure si sposta il cursore all’esterno della o delle righe che contengono
l’istruzione: ciò rende possibile analizzarla immediatamente per cercare di comprendere l’errore e
correggerlo. Il tipo di segnalazione è duplice e si presenta come nell’elenco che segue.
I caratteri dell’istruzione appena introdotta o modificata, nella quale viene riscontrato un
errore, assumono il colore rosso.
Appare una finestra in cui un’indicazione comunica la presenza di un errore di compilazione e
la tipologia del problema.
Arrivati a questo punto, esiste la possibilità di premere il pulsante ? per cercare di avere
spiegazioni più esaurienti riguardanti l’errore. Premendo il pulsante OK il cursore torna
sull’istruzione errata.
NOTA Visual Basic Editor definisce come errori di compilazione le analisi sintattiche delle istruzioni. La
compilazione avviene nel momento in cui il programma è eseguito.
Individuare la causa dell’errore può essere semplice o difficile, in relazione alla stessa
istruzione. È consigliabile, in proposito, suddividere le istruzioni troppo complesse in modo che
gli eventuali errori possano essere circoscritti con maggiore semplicità. Per esempio, utilizzare
un’istruzione che assegna a una proprietà un valore derivante da una funzione che richiede tre
parametri, ognuno dei quali composto da una lunga espressione, significa complicarsi la vita. È
più facile controllare la stessa istruzione suddividendola in cinque parti come di seguito.
Tre destinate ad assegnare ad altrettante variabili i valori che restituiscono le tre espressioni.
Una per assegnare a un’altra variabile il risultato della funzione richiamata utilizzando le tre
precedenti variabili.
Una per assegnare alla proprietà il valore dell’ultima variabile.
In caso si debba procedere al debug del programma, questa tecnica permette di avere
rapidamente sotto controllo gli elementi che seguono:
il valore di ogni singolo parametro utilizzato nella funzione;
il valore restituito dalla funzione.
Diventerà così molto più semplice capire se il problema è presente in essi o se una delle
espressioni è stata scritta omettendo una coppia di parentesi o un’operazione (dalla Figura 11.1
alla Figura 11.6).
Un esempio concreto di quanto detto può essere costituito dall’istruzione seguente:
Sub EsempioDivisione1()
MsgBox InputBox(“Digitare il divisore”)/ _
InputBox(“Digitare il dividendo”)
End Sub
Essa risulta sintatticamente perfetta; quando viene eseguita apre in successione due finestre
InputBox per richiedere all’utente di introdurre altrettanti numeri per poi visualizzare, con la
funzione MsgBox, il risultato della loro divisione. Il suddividerla in più istruzioni porta alla routine
seguente:
Sub EsempioDivisione1()
Dim divisore, dividendo As Double
MsgBox dividendo & “/” & divisore & “=” & dividendo / _
divisore
End Sub
NOTA La funzione InputBox restituisce un valore di tipo String che Visual Basic provvede a convertire
automaticamente nel tipo della variabile a cui deve essere assegnato il valore digitato dall’utente.
NOTA Il compilatore, a differenza delle precedenti versioni, non ammette più che una variabile abbia lo stesso
nome di una funzione e lo segnala immediatamente. Ciò riduce la possibilità di scrivere errori: per esempio poteva
capitare di creare la variabile di nome Len che ha un’omonima funzione.
Figura 11.1 Errore causato dall’omissione del nome della routine nell’istruzione Sub.
Figura 11.3 Errore causato dalla mancanza di una parola chiave nell’istruzione If.
Figura 11.6 Errore causato dall’assenza del carattere spazio prima di underscore per suddividere un’istruzione su più
righe.
Errori di compilazione
Quando si introduce un’istruzione, essa può essere sintatticamente corretta, ma nel contesto
generale potrebbe risultare incoerente. Per esempio, si è visto che i cicli possono contenere al loro
interno altri cicli. In questo modo, la routine che segue non presenta errori per l’interprete ma, al
momento della compilazione, viene segnalato (Figura 11.7):
‘ ---Attenzione: ciclo errato!
Sub EsempioConCicloErrato()
Dim a, b As Integer
Dim c As Long
For a = 1 To 5
For b = a To a + 1
c = b ^ 2
Next a
Next b
End Sub
Figura 11.7 Esempio di errore di compilazione nel ciclo For / Next.
Questi errori sono decisamente più difficili da individuare e risolvere degli errori sintattici ed è
quindi necessaria un’analisi che non si limiti alla singola istruzione, ma abbracci in successione
gli elementi seguenti:
tutta la routine;
tutto il modulo;
tutto il progetto (VBAProject).
Quasi mai è necessario spingersi a verificare l’intero progetto, in quanto il problema è quasi
sempre posto all’interno della routine o funzione che viene indicata da Visual Basic Editor. Vi
sono anche casi, però, decisamente più rari, in cui il problema va risolto a livello di modulo, per
esempio quando ci sono routine con lo stesso nome.
Gli errori di compilazione, per i programmatori che non hanno ancora avuto il tempo di
acquisire una sufficiente esperienza con il linguaggio, rappresentano una difficoltà che può metterli
alla prova, ma generalmente vengono risolti in breve tempo. Esistono casi in cui, tuttavia, per vari
motivi la routine errata sembra non contenere nessun errore. In queste situazioni potrebbe essere
utile suddividerla, se possibile, in due o più subroutine, ognuna delle quali specializzata a
svolgere una parte del lavoro della routine originaria; per non dover andare a modificare i
programmi che eventualmente la richiamano, la tecnica da utilizzare consiste nel mantenerla come
contenitore delle chiamate alle altre subroutine.
La routine che segue è un esempio di due differenti e ipotetici cicli: il primo scorre tutto il
foglio Disponibilità per conteggiare le righe aventi uno specifico requisito, al fine di verificare se
tale numero è maggiore di dieci, per eseguire sullo stesso foglio un aggiornamento. I cicli
appaiono sostituiti da una chiamata a una funzione e una chiamata a una subroutine nelle quali
apparirà il codice dei due cicli:
SubA ggiornaDisponibilitaSeNecessario()
r = ContaRigheOveQuantitaUgualeAZero(“Disponibilita”)
if (r > 10 Then)
Call AggiornaMagazzino(“Disponibilita”)
End If
End Sub
Meglio ancora, si può utilizzare il nome stesso della routine principale seguito da una
descrizione estremamente sintetica del lavoro che svolgono:
Sub AggiornaDisponibilitaSeNecessario()
r = _
AggiornaDisponibilitaSeNecessario_ContaRighe(“Disponibilita”)
if (r > 10 Then)
Call _
AggiornaDisponibilitaSeNecessario_Aggiorna(“Disponibilita”)
End If
End Sub
Per evitare l’eccessiva proliferazione di nomi di routine e funzioni che possono inutilmente
invadere la finestra Macro o Funzioni di Excel, oppure rendere difficile comprendere quali sono
direttamente richiamabili e quali invece esistono solo come supporto per altre, si consiglia
vivamente di ricorrere alla parola chiave Private, che precederà Sub o Function, rendendole così
visibili solo all’interno del modulo in cui sono contenute e, quindi, non nelle finestre.
Else
MsgBox “impossibile eseguire divisioni per zero”
End If
End Sub
Esiste ancora la possibilità che si verifichi un problema se non viene introdotto un valore
numerico, allora l’assegnazione di quanto digitato dall’utente a una variabile di tipo numerico
genererà un messaggio di errore (Figura 11.8).
Figura 11.8 Viene generato un errore, se InputBox riceve un valore testuale da assegnare a una variabile di tipo numerico.
MsgBox dividendo & “/” & divisore & “=” & dividendo / _
divisore
Fine:
Exit Sub
ErroreTipoNonNumerico:
MsgBox “Non è stato immesso un numero”
GoTo Fine:
ErroreDivisoreUgualeAZero:
MsgBox “Impossibile eseguire divisioni per zero”
GoTo Fine:
End Sub
contiene alcuni aspetti, già illustrati nei capitoli precedenti, che meritano di
EsempioDivisione3
NOTA Quando il flusso del programma incontra un’etichetta non accade nulla, perché essa è solamente il punto di
riferimento a cui andare per le istruzioni GoTo.
Degne di particolare nota sono le ultime istruzioni, che vengono eseguite solo nei casi in cui il
programma abbia aggirato una situazione che avrebbe causato un errore:
ErroreTipoNonNumerico:
MsgBox “Non è stato immesso un numero”
GoTo Fine:
ErroreDivisoreUgualeAZero:
MsgBox “impossibile eseguire divisioni per zero”
GoTo Fine:
Esse provvedono a visualizzare una descrizione del problema mediante la funzione InputBox e,
anziché terminare l’esecuzione della routine mediante l’istruzione Exit Sub, la fanno continuare
dall’etichetta Fine. Tecnicamente si poteva procedere anche nel modo seguente:
sostituire la prima istruzione GoTo Fine con una Exit Sub;
eliminare la seconda istruzione GoTo Fine.
Si ottiene così, anche se è sconsigliabile scegliere questa soluzione, un risultato perfettamente
identico a quello ottenuto con EsempioDivisione3:
ErroreTipoNonNumerico:
MsgBox “Non è stato immesso un numero”
Exit Sub
ErroreDivisoreUgualeAZero:
MsgBox “impossibile eseguire divisioni per zero”
End Sub
Se alla fine delle istruzioni deputate a essere eseguite, quando vengono scoperte potenziali
situazioni di errore, viene inserito sempre un GoTo verso un punto terminale della routine, si
possono ottenere i vantaggi elencati di seguito.
Diventa sempre possibile eseguire operazioni alla fine della routine come, per esempio,
chiudere una cartella che era stata aperta per le operazioni da compiere.
Si riduce il rischio di dimenticare di introdurre un GoTo quando vengono inserite nuove
istruzioni prima della End Sub, per la gestione di altre situazioni di rischio; in caso contrario,
quando viene eseguito il penultimo gruppo di istruzioni, verrà eseguito anche l’ultimo.
Dalla routine EsempioDivisione3 vengono riprese le ultime istruzioni, opportunamente modificate
per mostrare la forma in cui l’errore può presentarsi. Esso è abbastanza visibile dato l’esiguo
numero di istruzioni presenti:
ErroreTipoNonNumerico:
MsgBox “Non è stato immesso un numero”
ErroreDivisoreUgualeAZero:
MsgBox “impossibile eseguire divisioni per zero”
GoTo Fine:
End Sub
IsNumeric(Nome)
il valore della variabile è di tipo numerico o può essere anche convertito in tipo numerico senza
errori.
IsObject(Nome) la variabile è di tipo Object.
Alcune di queste funzioni ricorrono al concetto di vuoto, o assenza di valore, che viene indicato
mediante le costanti descritte di seguito:
Empty, alla variabile non è ancora stato assegnato nessun valore;
Null, la variabile non contiene un valore ma lo ha avuto.
I test IsEmpty() e IsNull() sono significativi solo in presenza di variabili di tipo Variant.
NOTA L’utilizzo del valore Null può essere fonte di sorprese apparentemente incomprensibili, perché ogni test su
di esso restituisce False in quanto la sua presenza rende l’intero test nullo, quindi non vero.
Il debugging
Il debugging è la fase in cui il programma può essere compilato ed eseguito per verificarne il
comportamento, eliminando difetti o errori.
Generalmente, il tempo che richiede è di difficile stima, dato che giocano diversi fattori come
quelli descritti di seguito:
l’efficienza e la flessibilità degli strumenti utilizzati;
l’esperienza del programmatore con il linguaggio;
l’esperienza del programmatore e le tematiche con cui opererà il software;
la dimensione del programma in termini di moduli e numero di linee;
la facilità e velocità nel disporre i dati che devono essere utilizzati per il test.
Visual Basic Editor contiene diversi strumenti per il debugging, i quali gravitano principalmente
intorno al principio del punto di interruzione.
Prima di tutto, però, è utile conoscere due informazioni fondamentali.
Se il pulsante Microsoft Visual Basic scompare dalla barra delle applicazioni di Windows è
possibile che un programma VBA abbia aperto una finestra di dialogo, visibile in Excel, che
non è stata chiusa.
Se Visual Basic Editor non permette di interagire con il programma, emettendo un beep ogni
qualvolta si fa clic sulla finestra, oppure quando viene premuto un tasto, bisogna controllare
se Excel è nella modalità Pronto, il che è determinabile osservando la barra che appare sul
bordo inferiore della finestra.
Questi piccoli suggerimenti possono semplificare la vita per chi inizia a cimentarsi con Visual
Basic Editor e il debugger.
Il punto di interruzione
Il punto di interruzione (break point) è un’istruzione che viene contrassegnata affinché il
programma sospenda la propria esecuzione quando la incontra. Permette di compiere varie
operazioni tra le quali:
verificare il contenuto delle variabili;
analizzare quali routine o funzioni si sono succedute nelle chiamate fino a giungere a quella
corrente;
analizzare il contenuto delle proprietà di oggetti.
Inoltre, permette di eseguire attività quali:
modificare il valore di una variabile;
modificare il contenuto delle proprietà di oggetti;
impostare un’istruzione dalla quale riprendere l’esecuzione.
Figura 11.9 Come appare un punto d’interruzione impostato su un’istruzione che occupa più righe.
NOTA Per accelerare la definizione dei punti di interruzione si può fare clic sulla barra laterale grigia in
corrispondenza dell’istruzione. Quando il programma raggiunge un’istruzione contrassegnata con un punto di
interruzione, l’esecuzione si arresta prima di eseguirla, in modo da permettere al programmatore di verificare ciò
che ritiene importante. L’istruzione che sarà eseguita appare contraddistinta, oltre che dal pallino rosso, anche da
una freccia gialla e il suo sfondo sarà giallo e rosso.
While True
a = 123456
Wend
End Sub
NOTA Se si cerca di visualizzare il valore di una variabile inesistente mediante il metodo Print, VBA non segnalerà
errore; per questo motivo è utile fare attenzione a come si è digitato il nome se il risultato è una riga vuota. In
alternativa, è utile ricorrere al completamento automatico del nome utilizzando i tasti Ctrl premuti
contemporaneamente alla barra spaziatrice.
Il quarto sistema utilizza la finestra Variabili locali nella quale si può inserire il nome di una
variabile o di un’espressione per visualizzarne il valore (Figura 11.12).
Figura 11.12 La finestra Variabili locali mostra le variabili dichiarate nella routine corrente. Si noti il pulsate posto a destra e
in altro raffigurante tre punti: esso permette di selezionare le routine chiamanti.
In tutto il libro sono stati portati esempi nei quali si è cercato di fare uso degli oggetti più
importanti e specifici di Visual Basic per Excel, ovvero celle, fogli di lavoro e cartelle di lavoro:
essi dovrebbero risultare sufficientemente semplici per poter comprendere il loro funzionamento,
anche se non ne è stata data una spiegazione tecnica approfondita, ma per padroneggiarli bene è
necessaria una maggiore conoscenza.
Prima una precisazione: ogni proprietà o metodo riferito a uno di questi oggetti fa
automaticamente riferimento all’entità attiva. Per esempio:
agire su una cella indicandone solo le coordinate significa che essa appartiene al foglio di
lavoro corrente;
non definire a quale cartella appartiene il foglio cui si fa riferimento significa che esso si
trova nella cartella corrente.
Questi aspetti sono importanti per comprendere come operano i vari metodi in assenza di
indicazioni specifiche.
Terminologia
Di seguito si riportano i termini più usati nel corso della trattazione di questo argomento.
Coordinata: informazione relativa alla posizione di riga o di colonna di una cella. Per
individuare una cella è necessario l’uso congiunto di entrambe, ottenendo un Riferimento.
Riferimento: sistema attraverso il quale viene individuata la posizione di una cella nel foglio
di lavoro, oppure indicazione di un oggetto ottenuta attraverso una variabile di tipo Object (in
altri linguaggi prende il nome di puntatore).
Riferimento A1: sistema di riferimento, normalmente utilizzato da Excel, in cui ogni cella
viene indicata attraverso una lettera che ne identifica la colonna e un numero che ne identifica
la riga di posizionamento entro il foglio di lavoro.
Riferimento R1C1: sistema di riferimento alternativo in cui ogni cella viene indicata con una
coppia di numeri che ne identifica il numero di colonna e di riga rispettivamente, preceduti
dalle lettere R e C, iniziali di Riga e Colonna.
Intervallo: insieme di celle che occupa sul foglio un’area di forma rettangolare; viene
indicato riportando il riferimento di una coppia di celle poste sugli spigoli opposti, per
esempio A1:H5.
L’istruzione With
Un’istruzione molto utile quanto si parla di oggetti che possono richiedere l’applicazione
sequenziale di più proprietà e metodi è With/End With: tutte le istruzioni comprese all’interno del
suo blocco fanno implicitamente riferimento all’oggetto indicato in With. Per esempio:
With ActiveCell
.Borders.LineStyle = xlDouble
.Value = “Nuovo valore”
.Orientation = xlVertical
End With
.Borders.LineStyle = xlDouble
.Value = “Nuovo valore”
.Orientation = xlVertical
End With
End Sub
NOTA La proprietà Orientation determina come il testo deve apparire all’interno della cella, similmente a quanto
viene definito dalla scheda Allineamento della finestra Celle, e accetta un valore di tipo Long; le principali costanti
per formattare la cella sono: xlDownward, xlHorizontal, xlUpward, xlVertical.
La cella
La cella è il componente base del foglio elettronico. Programma e utente devono poter agire su
essa liberamente, altrimenti vi sarebbero operazioni realizzabili solo manualmente. Per accedere
alla cella si utilizzano i seguenti due metodi:
Cells
Range
.Formula assegna alla cella una formula indicata attraverso l’abituale sistema di riferimento
Excel A1:
Cells(1, 1).Formula = “=A2+A3”;
.FormulaR1C1 assegna alla cella una formula indicata attraverso il sistema di riferimento
basato sul numero di riga e colonna, che verrà tramutato nel sistema A1 utilizzando i
riferimenti assoluti; la seguente istruzione inserisce nella cella A4 la formula =B1+C1:
Cells(4, 1). FormulaR1C1 = “=R1C2+R1C3”;
.Text restituisce una stringa con il valore contenuto nella cella rispettando la sua
formattazione, cioè la sua visualizzazione all’interno del foglio di lavoro; più precisamente,
Text differisce da Value perché non restituisce un valore di tipo Variant.
Il metodo Cells
Il metodo Cells permette di accedere a una cella utilizzando i suoi indici di riga e di colonna ed è
utile quando il programma deve agire su più celle mediante un ciclo: bastano due variabili di
controllo, una per ciascuna coordinata che individua la cella.
Il seguente esempio mostra come inserire il valore zero nelle celle poste nell’intervallo A1:H5:
Sub EsempioCells1A()
Dim r, c As Long
For r = 1 To 5
For c = 1 To 8
Cells(r, c).Value = 0
Next c
Next r
End Sub
Il metodo Range
Cells permette di accedere a una cella utilizzando due indici che indicano il suo numero di riga e
colonna.
Anche il metodo Range è molto utile quando il programma deve agire su più celle mediante un
ciclo, ma in questo caso è sufficiente una variabile di controllo per identificarle.
Il seguente esempio mostra come inserire il valore zero nelle celle poste nell’intervallo A1:H5,
analogamente a quanto svolto dalla routine EsempioCells1A:
Sub EsempioRange1A()
Dim cella
For Each cella In Range(“A1:H5”)
cella.Value = 1
Next cella
End Sub
In alternativa, sfruttando il concetto che la proprietà Range si può riferire a un insieme di celle,
si può concentrare tutto in un’unica istruzione, con enormi vantaggi di comprensibilità e poco
rischio di errori di scrittura rispetto alla forma proposta in EsempioRange1A:
Sub EsempioRange1B()
Range(“A1:H5”).Value = 0
End Sub
NOTA Range può essere utilizzato come tipo per una variabile, ricorrendo all’istruzione Dim.
Discorso analogo per la proprietà Row, che restituisce la coordinata della riga:
NumRiga = Range(“F5”).Row
NOTA La funzione ConvRifR1C1RifA1 è complessa, ma interessante per studiare come si possa lavorare sulle
lettere utilizzando numeri per selezionare quelle desiderate dalla tabella Ascii.
Come si può osservare, al metodo Range vengono forniti due parametri, il cui valore viene
restituito da altrettante chiamate ai metodi Cells aventi gli stessi riferimenti.
Per esempio, se le variabili r e c contenessero rispettivamente i valori 2 e 3, Range otterrebbe il
seguente riferimento: “C2:C2”.
In queste situazioni è comunque consigliabile l’utilizzo del metodo Cells, che rende il loop
molto più chiaro.
Per spaziare gli intervalli è sufficiente l’inserimento del carattere punto e virgola.
Ricorrendo poi agli spazi per separare gli intervalli tra loro, il risultato visivo diventa
decisamente migliore:
Range(“A1:G1 ; A3:G3 ; A5:G5 ; A7:G7”).Value = 12345678
NOTA È indispensabile porre la massima attenzione nell’inserire gli spazi all’interno delle stringhe in quanto
possono alterarne il significato; per esempio, non è ammessa la loro presenza tra le coordinate di un riferimento.
xlToRight
xlUp
xlDown
La seguente istruzione ottiene lo stesso spostamento della cella attiva che si potrebbe ottenere
sul foglio mediante la pressione dei tasti Ctrl+destra:
ActiveCell.End(xlToRight).Select
RendiMaiuscolo = True
‘ per tutta la lunghezza del valore della cella c...
For p = 1 To Len(c.Value)
‘se il p-esimo carattere e’ spazio...
If c.Characters(p,1).Text = “ “ Then
‘ non modificarlo, ma la prossima lettera va in
maiuscolo
‘perche’ e’ l’iniziale
RendiMaiuscolo = True
Else
‘ se deve rendere maiuscola questa lettera
If RendiMaiuscolo Then
‘ copia carattere maiuscolo
c.Characters(p, 1).Text = _
UCase(c.Characters(p,1).Text)
‘ la prossima non va più in maiuscolo
RendiMaiuscolo = False
Else
‘ copia carattere minuscolo
c.Characters(p, 1).Text = _
LCase(c.Characters(p, 1).Text)
End If
End If
Next p
Next c
End Sub
NOTA Nella routine SoloInizialiMaiuscole si può sostituire l’uso della proprietà Characters, ricorrendo a una
variabile di tipo String, e la proprietà Value, per acquisire il valore della cella e modificarlo a fine elaborazione.
La colonna e la riga
Le colonne e le righe di un foglio di lavoro possono venire utilizzate come oggetti all’interno di
Visual Basic, anche se le loro situazioni d’impiego sono poche.
La routine EsempioColumns esegue un ciclo per tutte le colonne del foglio di lavoro attivo e
modifica la larghezza di tutte le colonne, dimezzandola con la proprietà ColumnWidth:
Sub EsempioColumns()
Dim Cln
La routine EsempioRows si comporta in maniera analoga alla precedente, agendo sulle righe
mediante la proprietà RowHeight:
Sub EsempioRows()
Dim Rw
Per operare su un’intera colonna, o un’intera riga, indicando unicamente una cella appartenente
a essa, si possono utilizzare le seguenti proprietà.
EntireColumn, che applicata a una cella restituisce un oggetto di tipo Range nel cui intervallo
è compresa un’intera colonna. La seguente istruzione, per esempio, seleziona l’intera colonna
in cui si trova la cella attiva:
ActiveCell.EntireColumn.Select;
EntireRow, che applicata a una cella restituisce un oggetto di tipo Range nel cui intervallo è
compresa un’intera riga. La seguente istruzione, per esempio, seleziona l’intera riga nella
quale si trova la cella attiva:
ActiveCell.EntireRow.Select.
NOTA La prima istruzione utilizza l’indice 2, in quanto il primo foglio è sempre Personal.xls, a meno che non sia
stato chiuso, e viene supposto che non ve ne siano altri aperti.
Come si può osservare, nell’istruzione di assegnazione di un valore alla variabile obj non viene
utilizzata anche la proprietà Name, che invece era presente nell’esempio delle quattro istruzioni
MsgBox: questo è dovuto al fatto che le variabili di tipo Object sono riferimenti agli oggetti,
mentre la proprietà Name avrebbe restituito una stringa con il nome dell’oggetto.
oppure:
ActiveWorkbook.Worksheets.Add after:= Worksheets(“Foglio01”)
Di default, il nuovo foglio viene creato in una posizione precedente a quello corrente.
Per collocare il nuovo foglio in fondo alla cartella si ricorre alla proprietà Count, per calcolare
l’indice dell’ultimo foglio e creare il riferimento da passare nel parametro after, come qui di
seguito:
ActiveWorkbook.Worksheets.Add after:= Sheets(Sheets.Count)
NOTA Add supporta il parametro di nome Count, che è numerico e può servire a indicare il numero di fogli da
creare.
Eliminare un foglio
È possibile eliminare un foglio da una cartella ricorrendo al metodo Delete, che viene applicato
a un oggetto Sheet come nei seguenti esempi (Figura 12.1):
ActiveWorkbook.Worksheets(“Foglio01”).Delete
ActiveWorkbook.Sheets(“Foglio01”).Delete
Workbooks(“Esempio12.xls”). Sheets(“Foglio01”).Delete
Figura 12.1 Il metodo Delete apre una finestra che richiede conferma.
Il metodo Add applicato alle cartelle non accetta i parametri After e Before, come accade con i
fogli di lavoro: ogni nuova cartella viene semplicemente creata e le viene attribuito il nome di
default, costituito dalla parola Cartel seguita da un numero.
Ovviamente, per non perdere le informazioni inserite nella nuova cartella, è necessario salvarla
con il metodo SaveAs che può accettare diversi parametri, i più comuni e interessanti dei quali
vengono riportati di seguito:
FileName, nome con il quale la cartella verrà salvata;
Password, consente di indicare una password per limitare l’accesso alla cartella;
CreateBackup, a ogni successivo salvataggio Excel farà una copia di backup della cartella,
aggiornata al precedente salvataggio.
Sub EsempioCreaNuovaCartella()
Dim wb As Workbook
Set wb = Workbooks.Add
MsgBox “Creata nuova cartella di nome “ & wb.Name
wb.SaveAs Filename:=”EsempioDiCartellaCreataDaVBA”
End Sub
La selezione di celle
La selezione di celle può essere composta da una o più celle, raggruppate in uno o più intervalli
anche non contigui.
Per Visual Basic la selezione è un oggetto di tipo Range, che contiene i riferimenti agli intervalli
selezionati nei fogli di lavoro.
È importante dare risalto ai seguenti concetti:
la cella attiva è quella in cui è presente il cursore, quindi è pronta a ricevere l’input
dell’utente (è unica in ogni sessione di Excel ed esi-ste sempre);
la selezione esiste solo quando più celle vengono selezionate e comprende sempre la cella
attiva.
La selezione può essere utilizzata per agire su ogni singola cella; per esempio, il seguente ciclo
provvede a trasformare il contenuto di ogni cella da formula a valore:
Sub TrasformaFormulaInValore()
Dim c
Indubbiamente, a prima vista, questo ciclo apparirà alquanto strano, poiché l’istruzione al suo
interno sembra decisamente superflua, invece ottiene il risultato desiderato.
La spiegazione è relativamente semplice: la variabile c rappresenterà una cella diversa per ogni
ciclo e a essa verrà assegnato il valore ottenuto applicando la proprietà Value alla variabile c
stessa, che abbiamo detto essere una formula.
In pratica la variabile c assumerà il valore del risultato della formula in essa contenuta.
Se si fosse utilizzata l’istruzione:
c.Value = c.Formula
le celle contenenti formule sarebbero rimaste immodificate, in quanto sarebbe stata assegnata
loro la formula stessa, non il suo risultato.
NOTA Se non esiste nessuna selezione, Selection restituirà il valore Nothing.
Indice
Introduzione
Finalità
Convenzioni utilizzate nel libro
Capitolo 1 - Macro: un modo per dire “programma”
VBA: come iniziare con facilità
Prima di iniziare: impostare il livello di sicurezza
Avviare il registratore
Registrare la prima macro
Capitolo 2 - L’ambiente di Visual Basic Editor
Visual Basic Editor
I menu di Visual Basic Editor
Capitolo 3 - Macro e subroutine
Le macro create con il registratore
Le routine
Capitolo 4 - Tipi, variabili, matrici e costanti
Tipi di variabile
Variabili
Matrici o array
Le costanti
Capitolo 5 - Gli operatori
Operatori matematici
Operatore di assegnazione =
Operatori di confronto
Operatori logici
Concatenazione di stringhe
Priorità nell’ordine di valutazione
Capitolo 6 - Funzioni, routine e subroutine
Differenza tra funzione, routine e subroutine
Richiamare routine, subroutine e funzioni
Creare una nuova funzione
Parametri o argomenti
Le funzioni del foglio di lavoro
Restituire uno o più valori
Creare funzioni utilizzabili nel foglio di lavoro
Excel: le finestre Macro e Inserisci funzione
Capitolo 7 - Le funzioni native
Le funzioni del Visual Basic
Applicazione delle funzioni native di conversione
Applicazione delle funzioni native per date, orari e calendario
Applicazione delle funzioni native per le stringhe
Funzioni native per l’interazione con l’utente
Capitolo 8 - Esecuzione condizionale e ciclica delle istruzioni
Il flusso logico
Le condizioni
I cicli o loop
Uscire anticipatamente da Function, Sub o cicli
Capitolo 9 - Insiemi di oggetti
Proprietà, metodi, eventi ed ereditarietà: concetti
Gli oggetti di Excel
Font
Un esempio di iterazione con l’oggetto Selection
Capitolo 10 - Creare le finestre
Terminologia
I preliminari
L’aggiunta dei componenti
Navigare tra i componenti
Associare le routine ai componenti
Capitolo 11 - Gestione degli errori
Terminologia
Errori di compilazione e di esecuzione
Il debugging
Capitolo 12 - Come interagire con celle, fogli e cartelle
Terminologia
L’istruzione With
La cella
La colonna e la riga
Il foglio di lavoro e la cartella
La selezione di celle