Docsity
Docsity

Prepara i tuoi esami
Prepara i tuoi esami

Studia grazie alle numerose risorse presenti su Docsity


Ottieni i punti per scaricare
Ottieni i punti per scaricare

Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium


Guide e consigli
Guide e consigli


Introduzione al Visual Basic per applicazioni, Appunti di Informatica

Significato del Visual Basic per applicazioni (VBA)

Tipologia: Appunti

2020/2021

Caricato il 02/02/2023

tennyx
tennyx 🇮🇹

1 documento

1 / 36

Toggle sidebar

Questa pagina non è visibile nell’anteprima

Non perderti parti importanti!

bg1
Introduzione al Visual Basic per applicazioni:
il caso Excel
di Gianni Giaccaglini
Significato del Visual Basic per applicazioni (VBA)
Fin dalla versione 5.0 di Excel la Microsoft ha introdotto il Visual Basic for
Application in sigla, VBA - inaugurando una strategia unificante, all'insegna del
linguaggio di programmazione Visual Basic. Il Visual Basic peculiare di Excel ha
soppiantato il precedente sistema di macrofunzioni (rimaste tuttora in vita, per
compatibilità) e, successivamente è stato esteso agli altri membri della famiglia MS
Office (Word, Access ecc.).
Ma che cos'è un Visual Basic per applicazioni? Esiste una certa confusione al
riguardo, persino fra i programmatori di professione, per cui vanno subito fatte due
puntualizzioni:
a) non si tratta di un'estensione del linguaggio "padre", il Visual Basic standard, bensì
di un'evoluzione del sistema di macro tradizionalmente associata ai fogli elettronici;
b) di conseguenza, pur aderendo da vicino alla sintassi Visual Basic stadard, una
routine VBA si esegue soprattutto, anche se non esclusivamente, nell'ambiente del
package Excel (dalla versione 5.0 in avanti);
c) grazie ad un avanzato "protocollo" Microsoft, l'OLE Automation, si danno però
interessanti possibilità di cooperazione, in una logica Client/Server fra i vari
membri del mondo Visual Basic.
Le opzioni avanzate offerte dall'OLE Automation implicano la possibilità di
richiamare funzionalità di un pacchetto da parte di un programma scritto sia in Visual
Basic standard sia in uno qualunque degli altri "dialetti" VBA. Per fare due esempi
concreti, con OLE automation è possibile:
in un programma Visual Basic 5.0 o 6.0 sfruttare la libreria di funzioni finanziarie
di Excel sia direttamente che tramite fogli elettronici (creati anche
estemporaneamente);
da una macro Excel gestire documenti Word (o presentazioni PowerPoint).
In queste note introduttive al vasto mondo VBA non arriveremo a parlare di tali
prospettive avanzate, tuttavia l'averne accennato è importante, se non altro per mettere
in evidenza l'importanza del VBA:
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24

Anteprima parziale del testo

Scarica Introduzione al Visual Basic per applicazioni e più Appunti in PDF di Informatica solo su Docsity!

Introduzione al Visual Basic per applicazioni:

il caso Excel

di Gianni Giaccaglini

Significato del Visual Basic per applicazioni (VBA)

Fin dalla versione 5.0 di Excel la Microsoft ha introdotto il Visual Basic for Application – in sigla, VBA - inaugurando una strategia unificante, all'insegna del linguaggio di programmazione Visual Basic. Il Visual Basic peculiare di Excel ha soppiantato il precedente sistema di macrofunzioni (rimaste tuttora in vita, per compatibilità) e, successivamente è stato esteso agli altri membri della famiglia MS Office (Word, Access ecc.).

Ma che cos'è un Visual Basic per applicazioni? Esiste una certa confusione al riguardo, persino fra i programmatori di professione, per cui vanno subito fatte due puntualizzioni:

a ) non si tratta di un'estensione del linguaggio "padre", il Visual Basic standard, bensì di un'evoluzione del sistema di macro tradizionalmente associata ai fogli elettronici;

b ) di conseguenza, pur aderendo da vicino alla sintassi Visual Basic stadard, una routine VBA si esegue soprattutto, anche se non esclusivamente, nell'ambiente del package Excel (dalla versione 5.0 in avanti);

c ) grazie ad un avanzato "protocollo" Microsoft, l' OLE Automation , si danno però interessanti possibilità di cooperazione, in una logica Client/Server fra i vari membri del mondo Visual Basic. Le opzioni avanzate offerte dall'OLE Automation implicano la possibilità di richiamare funzionalità di un pacchetto da parte di un programma scritto sia in Visual Basic standard sia in uno qualunque degli altri "dialetti" VBA. Per fare due esempi concreti, con OLE automation è possibile:

 in un programma Visual Basic 5.0 o 6.0 sfruttare la libreria di funzioni finanziarie di Excel sia direttamente che tramite fogli elettronici (creati anche estemporaneamente);

 da una macro Excel gestire documenti Word (o presentazioni PowerPoint).

In queste note introduttive al vasto mondo VBA non arriveremo a parlare di tali prospettive avanzate, tuttavia l'averne accennato è importante, se non altro per mettere in evidenza l'importanza del VBA:

Il Visual Basic per applicazioni è lo strumento principe per la creazione di veri e propri applicativi di OFFICE AUTOMATION, sulla base della più diffusa famiglia di pacchetti specifici, Microsoft Office.

Il discorso interessa in misura crescente i programmatori professionisti, mentre le difficoltà concettuali del VBA tagliano fuori molti fra gli utenti, salvo una élite di esperti.

NOTA - Queste dispense si occupano, per brevità, del VBA di Excel, se non il più importante, sicuramente il più ricco dialetto VBA.

Modelli Excel e ruolo delle macro

Una conoscenza non superficiale del foglio elettronico in generale e di Excel in particolare è un prerequisito per seguire questa trattazione, tuttavia non nuoce a nessuno la lettura di questo paragrafo, volto alla definizione concreta del significato di modello Excel , inteso come una particolare applicazione sviluppata direttamente dall'utilizzatore di spreadsheet, fin dai tempi del progenitore VisiCalc, facendo a meno - per forza di cose, a quei tempi - di macro o altri mezzi strettamente informatici. Si trattò di una programmazione "senza accorgersene" grazie anche a funzioni speciali come quelle di ricerca tabellare ed a funzioni decisorie come la =SE().

Per far capire la cosa nel modo meno pedante possibile il ruolo - distinto ma cooperante – svolto dalle formule e dalle macro VBA facciamo un esempio semplice ma significativo. Si abbia una cartella di lavoro Excel il cui unico foglio di lavoro contiene diverse formule che danno adito a risultati relative alla "Analisi ABC" di uno stocki di magazzino. Con la manovra Alt+F11 passiamo all'ambiente Editor Visual Basic di Excel, del tutto simile a quello del VB5 o VB6 (Visual Basic 5.0 o 6.0) e creaiamo un modulo Visual Basic Modulo.

NOTA - I moduli speciali Foglio1 Foglio2 ecc. e ThisWorksheet non verranno svolti in queste note introduttive, per brevità, ma anche perché esse hanno come scopo la trattazione degli aspetti più peculiari del VBA di Excel: soprattutto l'oggetto Range e relativi proprietà/ metodi.

Il modulo Visual Basic serve a contenere le procedure che automatizzano parzialmente il modello. Il foglio di lavoro in questione corrisponde a uno schema tabellare che riporta, a partire dalla colonna B, le voci seguenti:

PRODOTTO (nomi degli articoli di un magazzino) GIACENZA (valore della) VALORE% VALORECOM% CLASSE (A, B o C) In altri termini, la situazione corrisponde al layout seguente:

i prodotti in questione siano disposti in ordine decrescente per quanto riguarda l'incidenza percentuale (sempre la colonna VALORE%). Altrimenti il modello dà i numeri.

Nella sua estrema semplicità l'esempio è dunque interessante, per almeno due motivi:

a ) si può pensare che la parte statica dell'applicativo sia stata creata da un normale utilizzatore, digiuno di informatica e VBA;

b ) in casi come quello in esame l'esigenza di aggiungere routine per l'ulteriore automatizzazione dell'applicativo scaturisce non solo da esigenze di interfaccia, bensì anche, se non ancor più, dalla natura dinamica di modelli del genere. Spieghiamoci meglio. Il foglio elettronico viene tuttora ritenuto adatto quasi solo per analisi di bilancio ed altre pur utili ma tristi e grigie applicazioni contabili. Nelle quali le voci in gioco e, di conseguenza, il layout risulta rigido. Nulla di scandaloso in sé, ma muovendo da tali casi più semplici e comuni anche gli esperti di spreadsheet hanno finito per confinare l'impiego delle macro nella creazione di menu personalizzati (con o senza corredo di finestre di dialogo) destinati a compiti di assoluta routine come la stampa o la visualizzazione di un grafico. Va da sé che simili cose, ad una fredda analisi talora non si rivelano neanche troppo pratiche, visto che chi usa un package evoluto come Excel se la cava benissimo da sé, coi comandi che l'ambiente gli mette a disposizione.

NOTA – Non ci si fraintenda: un'interfaccia gradevole è utile anche in un modello Excel, ma va da sé che i programmatori in Visual Basic se la cavano benissimo con i controlli offerti dal VBA di Excel, gli stessi (anche se in numero inferiore). Pertanto, in queste note non staremo a ripetere cose già note a chi mastica il VB standard.

Excel consente non solo di migliorare l'interfaccia ma offre anche la possibilità di rendere chiuso al massimo grado un modello (fra l'altro occultando formule del foglio e rendendo naccessibile il codice VBA), comunque l'automazione su cui focalizzeremo l'attenzione è di altra natura.

Tornando al precedente modellino, il suo carattere dinamico deriva da due fattori (riscontrabili anche altrove): la necessità di copiare formule (quelle contenute nelle celle delle colonne D, E ed F) ogni volta che si aggiunge una voce (il cui numero può non essere noto a priori) e la già citata esigenza di ordinare le voci. Ora entrambe queste operazioni possono essere compiute manualmente però anche l'utente più esperto perde tempo e rischia di imbrogliarsi. Ed ecco allora che anche un menu costituito magari da pochi pulsanti incollati sul foglio di lavoro, a ciascuno dei quali è associata una macro viene incontro alla bisogna: AGGIUNGI_VOCE e RIORDINA, ad esempio.

Le macro Visual Basic

Che cosa sono le macro? Come anche i programmatori dovrebbero sapere, le macro, altrove dette anche script, originariamente rispecchiavano le azioni dell'utente per lo più registrate automaticamente per essere poi rilanciate riproducendo così una sequenza ripetitiva di comandi (non a caso venivano chiamate macro "di tastiera"). L'evoluzione

verso un vero e proprio linguaggio di alto livello come il VBA ha visto come tappe intermedie l'inserimento di istruzioni di controllo del flusso e l'abbandono, per lo più, del rispecchiamento delle manovre dell'utente. Si esamini ad esempio il seguente listato:

Sub Macro1() Range("B3:E6").Select Selection.Copy Range("D9").Select ActiveSheet.Paste Application.CutCopyMode = False End Sub

Sub Macro2() With Selection.Font .Name = "Arial" .FontStyle = "Grassetto" .Size = 10 .Strikethrough = False .Superscript = False .Subscript = False .OutlineFont = False .Shadow = False .Underline = xlUnderlineStyleNone .ColorIndex = xlAutomatic End With End Sub

Macro1 e Macro2 sono due routine ottenute mediante il registratore di macro VBA. Il significato del codice è ragionevolmente leggibile, basta tener presente che la sintassi object oriented fa sì che l'oggetto precede la proprietà o il metodo. Di conseguenza Range("B3:E6").Select equivale a "seleziona l'intervallo (alias zona) B3:E6". Come è facile comprendere, la prima macro riproduce pedissequamente le azioni seguenti: 1) selezione dell'intervallo appena detto; 2) comando Modifica Copia ; 3) selezione della cella D9 di destinazione; 4) comando Modifica Incolla ; 5) chiusura delle operazioni Copia-taglia-incolla (tramite Esc o Invio).

La seconda macro è stata invece ottenuta, sempre per registrazione, applicando il grassetto ai caratteri della selezione corrente mediante il comando Formato Celle... (o la sua scorciatoia Ctrl+1 ). Stavolta il registratore si sforza di rivelarsi "intelligente", provvedendo a inserire le proprietà definite nella finestra di dialogo in questione entro il contrutto With ... End With , che risparmia di ripetere Selection.Font per tutti gli attributi. Semmai l'eccesso di zelo del registratore produce ridondanze relative ad attributi default che non abbiamo inteso toccare, per cui ci converrà eliminarle come mostrato nella seguente Macro3 (o ancora più drasticamente):

Sub Macro3() 'Semplificazione della Macro With Selection.Character .Name = "Arial" .FontStyle = "Grassetto" .Size = 10 End With End Sub

L'importante è verificare che sia che si lanci la Macro2 sia che si lanci la Macro non si assiste minimamente alla comparsa delle finestre di dialogo dell'azione manuale.

 l'oggetto Workbook che è la cartella di lavoro (una di quelle attualmente aperte)

 l'oggetto Worksheet , foglio di lavoro

 L'oggetto Range , intervallo di calle.

Lo schema verrà ripreso e approfondito in seguito, per ora diamo alcune anticipazioni sintattiche:

  1. ciascun oggetto fa parte di una famiglia o classe (di suoi simili) e l'accesso al singolo membro di ciascuna classe si effettua attraverso metodi, diciamo così, "pluralistici", ai quali corrispondono insiemi (collection) di oggetti omogenei: Workbooks , Worksheet, Range (un'apparente eccezione, vedremo perché), Cells ;

  2. esattamente come accade in altri lidi informatici (incluso il rude DOS) i membri più elevati di una catena gerarchica si possono omettere, nel qual caso è sottinteso il soggetto attualmente attivo.

  3. l'istruzione Set serve a fissare un oggetto in una variabile.

Spieghiamoci un po' meglio. Sul primo punto, ci si accontenti di esempi: Workbooks("BILAN.XLS") e Worksheets("Foglio1") individuano rispettivamente la cartella e il foglio di lavoro virgolettati entro parentesi, mentre Workbooks(2) e Worksheets(3) si riferiscono al secondo, rispettivamente al terzo fiore dei rispettivi... mazzi.

Quanto al secondo punto, la terrificante espressione genealogica (completa) seguente:

Application.Workbooks(1).Worksheets(2).Range("A1:B12")

può essere ridotta semplicemente a Range("A1:B12") se è attivo il secondo foglio della prima cartella. E il più delle volte si lavora con una data cartella, inoltre Application si può quasi sempre omettere, visto che si sta lavorando con Excel (ma vi sono casi particolari in cui, ciononostante, non se ne può fare a meno).

Esemplifichiamo infine la comoda istruzione Set :

Set MioInterv = Worksheets(2).Range("A1:B12")

Grazie ad essa, si potrà in qualunque momento successivo riferirsi a tale intervallo, poniamo il caso per grassettarne il contenuto, con:

MioInterv.Font.FontStyle = "grassetto"

NOTA - E c'è un altro grosso vantaggio: l'istruzione agisce anche se il caro MioInterv non è attualmente attivo!

Concludiamo questi antipasti offrendo nel listato che segue una macro VBA da sperimentare.

Sub AggiungiFormule() Set I = Range("inivoci") Set F = Range("iniform") NrVoci = Range(I, I.End(xlDown)).Count Range(F, F.Offset(NrVoci - 1, 2)).Select Selection.FillDown 'Ricopia in basso

EnD Sub

Del metodo FillDown , peraltro di significato intuitivo, si parlerà meglio in seguito, qui diciamo solo che la routine AggiungiFormule provvede con una tecnica un po’ particolare alla copia dinamica delle formule del modellino seguente ogni volta che l'utente aggiunge una o più voci in fondo alle colonne B e C:

Osiamo poi asserire che persino esperti di Visual Basic standard, che tendenziualmente identificano gli oggetti con i tipici controlli dell'interattività potrebbero trarre giovamenti concettuali dallo studio di Excel VBA, per approfondire la comprensione concettuale del mondo OOP.

Libreria degli oggetti tipici di Excel

Riprendiamo in esame la tassonomia relativa alla libreria di oggetti tipici di Excel. In testa a tale piramide si trova l'oggetto Application , nella fattispecie Excel. Limitandoci agli oggetti tipici abbiamo una struttura gerarchica o a scatole cinesi o, se si preferisce, una genealogica - sotto al capostipite - così suddivisa:

WorkBooks (Cartelle di lavoro), genitrici e contenitrici di

Sheets (fogli) di diversi tipi, come Charts (fogli per grafici) e, principalmente WorkSheets (Fogli di lavoro), questi ultimi comprendenti, a loro volta,

 insiemi Range (Intervalli), ovvero raggruppamenti di Cells (celle).

Si faccia attenzione. Nell'elenco appena fatto si è fatto direttamente ricorso alla proprietà VBA che danno accesso ai diversi oggetti, rispettandone la sintassi (che prevede maiuscole intermedie, peraltro facoltative). Si tratta di una sintassi di tipo, "pluralistico" (con l'eccezione - apparente, come si vedrà - della proprietà Range ) che si riscontra, in VBA, in tutti i casi in cui si punta ad insiemi di oggetti, detti anche gruppi o collection. Altri esempi di collection Excel: Shapes (Oggetti grafici come quelli creati con la barra strumenti Disegno) e OLEObjects (oggetti OLE incorporati)..

Un particolare elemento di un dato insieme viene individuato tramite indice. Questo può essere, a scelta, il numero d'ordine o il nome fra virgolette. Così le proprietà Workbooks(2) e Workbooks("MIACART.XLS") puntano entrambe alla stessa MIACART.XLS sempreché questa sia la seconda fra quelle che al momento sono aperte sulla scrivania di Excel. Dovrebbero fin d'ora essere chiari i pro e contro dei due sistemi d'indicizzazione: il primo è prezioso per spazzolare un insieme con cicli quali For ... Next.

Con oggetti gerarchicamente strutturati - In perfetta analogia con il path di un file, in DOS - un elemento di basso livello può essere individuato in modo completo, indicandone l'intero percorso genealogico. L'esempio che segue, nella sua prolissità, lo considero autoeloquente:

Application.Workbooks("MIA.XLS") _ .Worksheets("Foglio1").Range("A2:B5")

Si noti che, come sa chi già mastica il Visual Basic, il separatore dei vari componenti è il punto (.), carattere perciò vietatissimo negli identificatori adottabili dal programmatore (contrariamente a quanto accade con funzioni e macrofunzioni Excel).

Proprio come nel DOS, se si omettono papà o nonni sono sottintesi quelli attualmente attivi. Ragion per cui, restando nel caso precedente, se è aperta la cartella MIA.XLS, sono consentite più stringate notazioni:

Worksheets("Foglio1").Range("A2:B5")

se poi è attivo il foglio Foglio1 di una data cartella possiamo scrivere solamente:

Range("A2:B5")

Per l'esattezza va anzi ribadito che le due ultime notazioni puntano, la prima, a qualunque intervallo A2:B5 del Foglio1 di qualsiasi cartella attuale o a qualunque Intervallo A2:B5 di qualsiasi cartella o foglio di lavoro attuali (d'altronde proprio come nei due banali esempi DOS seguenti: Dir MIADIR\PIPPO.MIO e Dir PIPPO.MIO).

Quanto ad Application , è quasi sempre facoltativo (visto che ci troviamo in Excel) salvo in casi speciali di omonimia col Visual Basic standard, che in parte avremo modo di vedere.

Osservazione sintattica sottile ma pratica. Con le proprietà "insiemistiche" nei primi tempi è facile scordarsi del plurale, scrivendo Workbook("TALE:XLS") anziché Workbooks ("TALE:XLS") oppure Worksheet("Bilancio") invece di Worksheets ("Bilancio").

NOTA - Nella terminologia VBA i vocaboli (keyword, parole chiavi) Workbook , Worksheet ecc. esistono, però di fatto sono usati solo per definire o identificare il tipo di oggetto. Li si userà, di fatto, in una Dim (e da nessun'altra parte), esempio: Dim MioFoglio As Worksheet Quando si desidera una certa concreta cartella o un certo concreto foglio occorre invocare la proprietà giusta e questa, nel caso di collection, ha sintassi plurale.

Tutto chiaro? Di sicuro sì per chi già conosce il Visual Basic, comunque gli esempi e l'esercizio rafforzeranno questo basilare concetto della programmazione a oggetti.

Le Windows (finestre), oggetti secondari ma inevitabili

Prima di procedere è opportuno, ancorché tedioso, parlare di un oggetto particolare per semplicità non incluso nella tassonomia accennata nel paragrafo precedente. Si tratta dell'oggetto Window che, per così dire, costituisce un terzo incomodo rispetto alle cartelle e ai fogli. Ci conviene liquidarlo subito, così non se ne parla più e, al tempo stesso, ci servirà come oggetto propedeutico ad altri, più interessanti oggetti.

Per individuere una finestra occorre la proprietà "insiemistica" Windows appartenente sia all'oggetto Application che all'oggetto Wordkook. Il motivo di questa duplice appartenenza probabilmente è l'ereditarietà, ma più prosaicamente deriva dal fatto che una cartella può comprendere più finestre, a seguito del comando Nuova Finestra del menu Finestra. Per fissare le idee supponiamo che siano aperte le due cartelle GRAF.XLS e BILAN.XLS. Ebbene con successive applicazioni del comando appena detto possiamo pervenire a una situazione di sei finestre, di cui due appartenenti alla cartella GRAF.XLS e quattro a BILAN.XLS.

La proprietà Windows permette di impostare sia una particolare finestra che tutte le finestre, nel loro insieme, mediante l'una o l'altra delle forme sintattiche seguenti:

oggetto. Windows(indice) oggetto. Windows

Nell'ultimo come in altri casi, la differenza fra metodi e proprietà appare sottile, l'importante è comprendere pragmaticamente il ruolo di questa o di quello. Ad ogni buon conto non guasta precisare che:

 un metodo esegue una certa azione;

 una proprietà restituisce un valore ma, a volte, anche un oggetto (come nel caso di ActiveWindow o, analogamente, ActiveWordkook , ActiveSheet ) A volte poi l'assegnazione di una proprietà si confonde con un'azione. Esempio:

ActiveWindow.Height = 200

in cui l'assegnazione ha un preciso effetto: l'altezza della finestra cambia (e, naturalmente, si vede).

Chiudiamo queste tediose (ma inevitabili) note sintattiche richiamando un principio ignoto ai neofiti del mondo OOP: un metodo o una proprietà si aggancia, tramite il connettore ". ", ad un trenino genealogico come un ulteriore vagoncino, magari generando a sua volta un oggetto oppure restituendo o modificando il valore di una proprietà (in senso stretto). Vediamo, al riguardo, un esempio concreto:

Wordkooks(2).ActiveSheet.Range("B2").Value = 1234

Seguiamo i passaggi esecutivi. La proprietà Workbooks(2) imposta la seconda cartella (poniamo MIACART.XLS) quindi la proprietà ActiveSheet restituisce il foglio attivo di MIACART.XLS (potrebbe essere il Foglio3), poi la palla passa alla proprietà Range("B2") che restituisce un ben preciso oggetto Range e, infine alla proprietà Value di tale oggetto Range. L'istruzione culmina con l'assegnazione del valore 1234 ad una cella ben precisa.

Ma adesso commentiamo le procedure del listato seguente, miranti fra l'altro a marcare certi distinguo. In particolare la seconda delle due routine in questione evidenzia l'esatta appartenenza delle varie finestre: all'oggetto Application oppure a singole cartelle di lavoro.

Sub EsploraFinestreInBlocco() 'Esamina, indiscriminatamente, TUTTE le 'finestre aperte sulla scrivania Excel For Each finest In Application.Windows MsgBox finest.Caption & " " & finest.Parent.Name Next End Sub

Sub EsploraFinestre() 'Esamina le finestre, definendone in dettaglio 'la cartella di appartenenza Constant Messiniz = "La cartella n. " Dim i As Integer, j As Integer, Mess As Stringa Dim NumCart As Integer, NumFines As Integer NumFines = Windows.Count NumCart = Wordkooks.Count MsgBox "Finestre Totali: " & NumFines MsgBox "Cartelle di lavoro Totali: " & NumCart For i = 1 To NumCart With Wordkooks(i) Mess = Messiniz & i

NumFines = .Windows.Count If NumFines = 1 Then MsgBox Mess & " ha una sola finestra" Else MsgBox Mess & " ha le seguenti " _ & NumFines & " finestre..." For j = 1 To NumFines MsgBox .Windows(j).Caption Next End If End With Next End Sub

Il ciclo For Each... Next e il costrutto With... End With

Dando per nota la funzione MsgBox dal corso VB5 parliamo del ciclo seguente:

For Each In istruzioni Next

Dovrebbe essere già noto a chi ha pratica di VB5 o VB6, comunque ha una particolare importanza in Excel VBA (ove sono presenti molti tipi di oggetti). Si applica a qualunque gruppo di oggetti, come pure a vettori e matrici, restituendone ad uno ad uno gli elementi nella variabile NomeElem , senza obbligo di gestire un indice.

La prima semplice routinetta del listato precedente sfrutta tale comodo costrutto e le proprietà Caption e Parent per elencarci a video tutte, indistintamente, le finestre presenti sulla scrivania Excel nonché il padre, in senso oggettual-genealogico, di ciascuna. Si provino a questo punto, assieme o separatamente, le istruzione seguenti:

Babbo = ActiveWorkbook.Parent MsgBox "Il papà della Cartella attiva è " & Babbo Avo = ActiveSheet.Parent.Parent.Name MsgBox "Il nonno del foglio attivo è " & Avo (l'operatore & di concatenamento stringhe dovrebbe essere noto sia agli utenti Excel che a quelli di Visual Basic.)

Scopriamo così che il capostipite di tutti gli Oggetti Excel VBA si chiama "Microsoft Excel", come ci attendevamo. Però tornando alla routine EsploraFinestreInBlocco , c'è da scommettere che alcuni saranno sorpresi nell'apprendere che non tutte le finestre hanno come padri la cartella di appartenenza e non Excel.

Passiamo alla seconda routine del listato precedente, sorvolando sulla dichiarazione iniziale di variabili, che sovente si ometteranno (il tipo implicito o default è l'onnicomprensivo Variant ). Per comprendere la routine EsploraFinestre occorre introdurre, per chi non la ricordi o la sfrutti poco, un'importante struttura del Visual Basic:

With ... End With

grazie alla quale, una volta precisato , non occorre ripeterlo e se ne possono invocare proprietà e metodi - entro i "terminatori" With ed End With - preceduti dal carattere "." (punto). Esempio:

Next

L' esempio mostra come il ciclo For Each... Next si possa tranquillamente applicare a un intervallo (cosa di cui molti manuali non parlano. L'effetto, come è chiaro o perlomeno intuibile, è la riduzione del 5% di tutti gli sconti contenuti nell'intervallo denominato appunto "Sconti".

Infine il listato che chiude questo paragrafo oltre a riproporre la routine di copia dinamica intravista all'inizio ne aggiunge un'altra quasi altrettanto inesplicata (ma non inesplicabile) ed affidata momentaneamente all'apprendimento autonomo:

Sub AggiungiFormule() Set I = Range("inivoci") Set F = Range("iniform") NrVoci = Range(I, I.End(xlDown)).Count Range(F, F.Offset(NrVoci - 1, 2)).Select Selection.FillDown End Sub

Sub CopiaRel() 'Copia dinamica in basso di una riga di formule, 'già battezzata "Rigaform", mediante la tecnica '(ingegnosa ma rudimentale) del nome temporaneo Application.Goto Reference:="Rigaform" ActiveCell.Offset(0, -1).Select Selection.End(xlDown).Select ActiveCell.Offset(0, 3).Select ActiveWorkbook.Names.Add Name:="ultimacella", _ RefersToR1C1:=ActiveCell Range("Rigaform").Select Selection.Copy Range("Rigaform:ultimacella").Select ActiveSheet.Paste Application.CutCopyMode = False ActiveWordkook.Names("ultimacella").Delete End Sub

Diciamo solo che la routine CopiaRel va applicata a un foglio in cui sia stato battezzato come "Rigaform" un intervallo di formule orizzontale (diciamo, ma solo per fissare le idee, E7:G7), sempre in modo dinamico ossia adeguandosi al numero (variabile) di voci nella prima colonna D di etichette.

Cartelle, fogli di lavoro, celle e intervalli

Continuando a dare per intuitiva la proprietà Valore [inglese Value ], tipica di un oggetto Range, riproponiamo la routine vista poc'anzi:

For Each Sconto in Range("Sconti") Sconto.Value = Sconto.Value * 0, Next

Essa dimostra che Range("Sconti") altro non è che l'insieme delle celle che lo compongono. Forse pochi ci penserebbero, ma da qui deriva la possibilità di applicare anche a un oggetto Range la proprietà Count e i volgari indici numerici:

Set ZonaMia = Range("A1:C10") NumCelle = ZonaMia.Count For i = 1 To NumCelle If ZonaMia(i).Font.Bold = True Then

ZonaMia(i).Font.Italic = True 'Aggiunge il corsivo solo alle celle grassettate End If Next Si è già accennato all'istruzione Set. Si contrappone a Let , storica istruzione BASIC facoltativa che nessuno adopera (tutti scrivono sempre x = ... anziché Let x =...). Set , che invece è obbligatorio, fissa un oggetto in una variabile di tipo Object (oggetto generico) o, quantomeno, di tipo Variant. Da quel momento tale variabile diventa, per così dire, un alter ego dell'oggetto. L'istruzione Set può essere, banalmente, usata per non dover ripetere la denominazione di oggetti, specie se lunga e verbosa. Così nel caso appena visto (in cui, si fa notare, non si poteva ricorrere a With... End With ). Ma dal momento che una variabile "impostata" a un oggetto ne racchiude tutti i riferimenti identificativi, si intuiscono usi più raffinati che vedremo presto.

Per liberare memoria sarebbe opportuno, una volta che tale variabile ha assolto il suo scopo, il codice seguente:

Set ZonaMia = Nothing

NOTA - Ma sovente se ne può fare a meno; soprattutto istruzioni del genere, a parere di chi scrive, sono superflue se poste al termine di un programma che ritorna all’ambiente Excel, visto che in tal caso la liberazione di memoria avviene automaticamente.

Il secondo esempio che stiamo per dare introduce la proprietà Rows propria, come la sua parente stretta, la proprietà Columns , di un oggetto Range come pure dell'oggetto Application (che può omettersi). Così Application.Columns(3) o, semplicemente Columns(3) ci dà l'intera terza colonna, ossia la C (del foglio corrente). Applicando Rows e Columns a un Range si ha l'insieme delle righe o colonne dell'intervallo, talché Rows.Count ce ne dà il numero mentre Rows(3) ci dà le celle della terza riga. Idem, mutatis mutandis, per Columns.

Ma ecco l'esempietto:

Sub Asterix() Set Z = Range("A1:J10") Nr = Z.Rows.Count For i = 1 To Nr Z(i, i).Value = "*" Z(i, i).HorizontalAlignement = xlFill Next End Sub

La routine Asterix immette asterischi nelle celle diagonali della zona (quadrata) A1:J10 formattandole in modalità Riempi (per cui si ha il pieno di asterischi, indipendentemente dalla larghezza della colonna).

NOTA - A proposito delle proprietà Rows e Columns : i più svegli e audaci sostituiscano Z(i, i) con Z.Rows(i).Columns(i). Vedranno che i due codici si equivalgono e... capiranno perché.

L’oggetto Application: cenni a proprietà e metodi

I neofiti qui si chiederanno che cosa sia mai quel tal xlNormal. È un esempio della miriade di costanti incorporate , rappresentate in modo mnemonico anziché con il loro valore (in altri termini, nella fattispecie, xlNormal equivale per l'interprete VBA al valore – 4143, davvero ostico da tenere a mente!).

Variabili incorporate ne abbiamo già introdotte, in modo surrettizio e affidandosi all'intuizione dell'allievo, nelle routine precedenti (es. xlFillDown , xlAutomatic ecc.). Se ne danno di due tipi:

a) precedute da " vb " - es. VbYes e vbNo – e in tal caso appartengono al Visual Basic standard

b) precedute da " xl ", prefisso che le distingue come peculiari di Excel VBA.

Altre proprietà di Application corrispondono al fissaggio di opzioni relative all'intero ambiente. Ecco due esempi interessanti, che corrispondono ad attributi che si possono impostare nella finestra di dialogo Opzioni , scheda Modifica :

Application.FixedDecimal = True 'imposta il formato numerico con DECIMALI FISSI Application.FixedDecimalPlaces = 4 'imposta 4 decimali (dopo la virgola)

Accenniamo poi a un'istruzione abbastanza utile, di cui si parlerà in seguito: Application.Goto. Qui l'anteposizione di "Application." è obbligatoria, per non confondere con GoTo , istruzione di salto incondizionato. Application.Goto traduce il comando Excel Modifica Vai a... , alias tasto F.

Parlimo ora di StatusBar , proprietà di lettura/scrittura utile per depositare un messaggio, per l'appunto, nella barra di stato. Anche qui l'oggetto Application è d'obbligo, inoltre occorre che la barra di stato sia visibile: provvede alla bisogna la proprietà VisuallzzaBarraDiStato , che può essere impostata ai valori logici True e False. Ed ecco un esempio generico d'impiego:

With Application BarraStatoVisib = .DisplayStatusBar 'registra True o False .DisplayStatusBar = True 'Forza la visibilità della barra di stato .StatusBar = "Attendere, prego..."

'... (omissis) ... .StatusBar = False .DisplayStatusBar = BarraStatoVisib 'Ripristina la vecchia situazione End With

Altre note su Sheets , Workbooks e Windows

A questo punto, prima di passare ai sospirati intervalli (oggetti Range) diciamo le cose essenziali sugli Sheets e Worksheets, aggiungendo alcuni distinguo, a mo' di flashback, sulle Workbooks (Cartelle di lavoro) e sulle Windows (Finestre). Il numero di metodi e proprietà specifici è talmente vasto da esigere uno sforzo di trattazione sistematica, fuori luogo su una dispensa introduttiva.

Per le proprietà che riguardano fogli ci limitiamo a dire che alla tipologia più usuale espressa dall'insieme Worksheets se ne affiancano altri come Charts (Grafici o, meglio, fogli per Grafici), inoltre Sheets punta a fogli di qualsiasi tipo. Il seguente listato comprende tre semplici procedure esplorative.

Sub EsploraTuttiFogli() 'Esamina indiscriminatamente i fogli d'ogni tipo 'della cartella corrente, indicandone via via il nome For Each fog In ActiveWorkbook.Sheets MsgBox fog.Name Next End Sub

Sub MostraTuttiFogliLav() 'Rende via via attivi i fogli di lavoro 'della cartella corrente (qui sottintesa). For i = 1 To Worksheets.Count With Worksheets(i) .Activate MsgBox .Name End With Next End Sub

Sub AttivaTuttiFogli() indAtt = ActiveSheet.Index nflav = Sheets.Count For i = indAtt To nflav With Sheets(i) .Activate MsgBox .Name End With Next For i = 1 To indAtt - 1 With Sheets(i) .Activate MsgBox .Name End With Next Sheets(indAtt).Activate End Sub

La prima delle tre precedenti routine, EsploraTuttiFogli , esamina indiscriminatamente tutti i fogli della cartella di lavoro attuale segnalandone il nome. La seconda routine, MostraTuttiFogliLav() , è simile alla MostraTutteFinestre vista nel paragrafo precedente, volta ad esibire all'utente le varie finestre presenti. Dal confronto emerge subito una differenza: non si ha più ActivateNext , che è un metodo esclusivo dell'oggetto Window. In sua vece si è fatto ricorso al metodo Activate , di chiara semantica.

NOTA - Il metodo Activate appartiene alla maggioranza degli oggetti, incluso Window! Provere per credere una variante di MostraTutteFinestre che usa Attivate anziché ActivateNext (esperimento lasciato per esercizio).