corso visual basic

178

Upload: pischiutta-alberto

Post on 23-Mar-2016

242 views

Category:

Documents


6 download

DESCRIPTION

Semplice corso di visual Basic con esempi.

TRANSCRIPT

Page 1: Corso Visual Basic
Page 2: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte I)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb01/index.htm[23/09/2010 4:38:12]

Corso di Visual Basic(Parte I)

La creazione di un form

Gli eventi

I metodi

Le variabili

Conclusioni

Figure

Figura 1

Figura 2

Figura 3

Figura 4

(c) 1997, Edizioni Infomedia srl

Corso di Visual Basic

(Parte I)

Come muovere i primi passi con Microsoft Visual Basic, lo strumento damolti considerato ideale per la realizzazione di applicazioni di piccola e

media entità in ambiente Windows.

di Maurizio Crespi

La nascita di Microsoft Visual Basic ha comportato una rivoluzione nelmondo degli strumenti di sviluppo per Windows, lanciando un nuovomodo di programmare, che vede per la prima volta prevalere l'uso delmouse nei confronti di quello della tastiera.

Tale approccio, detto visuale, si basa sull'uso di oggetti, ovvero dielementi attivi selezionabili su una barra degli strumenti (toolbox),caratterizzati dall'essere descritti da un insieme di valori, detti proprietàed in grado di eseguire dei metodi, ovvero delle azioni che ne possonoinfluenzare lo stato.

Un'ulteriore particolarità degli oggetti consiste nella capacità di generaredegli eventi, a cui il programmatore può associare come risposta degliinsiemi di istruzioni, detti procedure (ad esempio quando viene premutoun bottone il programmatore può associare la chiusura di una finestra).

Il linguaggio con cui esse sono scritte si basa sulle regole sintattichepreviste dal BASIC, di cui mantiene la semplicità.

La creazione di un form

Un'applicazione Visual Basic è costituita da una o più finestre, dette form,sulle quali si trovano gli oggetti che formano l'interfaccia fral'applicazione e l'utente.

Su un form è possibile inserire pressoché qualsiasi elemento, sia che sitratti di un'immagine, di un box di testo, di una lista o di un pulsante.

Il form principale dell'applicazione è generato automaticamente ognivolta che si agisce sul menu File per creare un nuovo progetto ed èvisualizzato all'avvio dell'applicazione, di cui, in genere, rappresenta laschermata principale.

La sua chiusura determina la fine dell'esecuzione del programma.

Si supponga di voler realizzare un'applicazione che, alla pressione di unpulsante, faccia apparire in un punto preciso della finestra la scritta"Benvenuto in Visual Basic". Il primo passo consiste nel posizionare sulform gli elementi grafici necessari.

Si deve dapprima inserire un contenitore per il testo da visualizzare.

Visual Basic prevede due tipi di elementi adatti a questo scopo: si trattadelle label e delle textbox.

Page 3: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte I)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb01/index.htm[23/09/2010 4:38:12]

Le prime, come indica il nome, sono dedicate alla visualizzazione di"etichette", ovvero di porzioni di testo non modificabili dall'utente. Leseconde, invece, consentono la digitazione di un testo al proprio internoe si rivelano pertanto adatte all'acquisizione di dati.

Nel caso dell'esempio, dovendo visualizzare un testo modificabile solo dalprogramma, è conveniente optare per una label, che può essere inseritasul form rendendo visibile la barra degli strumenti di disegno, operazioneeffettuabile agendo sulla voce Toolbox del menu View, selezionando su diessa l'elemento contraddistinto dalla lettera "A" e tracciando con ilmouse un rettangolo sull'area destinata ad ospitare l'etichetta.

Al rilascio del pulsante sinistro del mouse appare l'elemento desiderato,contenente la scritta "Label1".

Con questa operazione si crea il primo oggetto. Per adeguarlo alleproprie esigenze, è necessario variarne le proprietà. Ciò è possibilefacendo clic su di esso con il mouse e visualizzando la finestra delleproprietà agendo sulla voce Properties Window del menu View.

Appare così una tabella, in cui la colonna di sinistra contiene i nomi ditutte le proprietà che descrivono l'elemento e la colonna di destra neindica i rispettivi valori. Nel caso dell'etichetta testuale appena creata, sinota che due sue proprietà contengono il testo "Label1".

Esse sono denominate, rispettivamente, Name e Caption. Come è facileimmaginare, esse definiscono rispettivamente il nome dell'oggetto,ovvero l'identificatore da usare ogniqualvolta si desideri fare riferimentoad esso e il testo visualizzato nell'etichetta.

Si noti che Visual Basic provvede ad assegnare a queste proprietà unvalore predefinito. Spesso, però, è necessario fare in modo che la labelvisualizzi un dato diverso.

Nell'esempio, l'etichetta deve visualizzare del testo solo dopo lapressione del pulsante. È pertanto necessario che all'avvio delprogramma il suo contenuto sia nullo. Affinché ciò avvenga, si deve fareclic con il mouse sulla colonna di destra in corrispondenza della proprietàCaption e si deve sostituirne il contenuto con uno spazio.

Sebbene sia possibile mantenere per gli oggetti i nomi predefiniti, èconsigliabile, al fine di rendere più facilmente leggibile il programma,assegnare ad essi degli identificatori che permettano ad un altroprogrammatore, o allo stesso autore dopo che sia trascorso unconsiderevole lasso di tempo, di poterne facilmente comprendere lafunzione. Ciò rende più semplice ogni eventuale modifica successiva.

Nel caso dell'esempio, è pertanto conveniente assegnare all'etichetta ilnome lblMessaggio. Si noti l'uso del prefisso "lbl", abbreviazione di"label". Il ricorso a un prefisso è assolutamente facoltativo, ma si rivelaestremamente utile nel caso di applicazioni complesse per fare sì che acolpo d'occhio sia possibile comprendere il tipo di componente a cui sista facendo riferimento.

La modifica del nome dell'oggetto avviene digitando il nuovoidentificatore nella colonna di destra della finestra Properties, incorrispondenza della riga denominata Name.

Page 4: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte I)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb01/index.htm[23/09/2010 4:38:12]

In modo analogo a quanto visto per la label, è possibile inserire ilpulsante all'interno del form selezionando sulla toolbox l'apposita icona etracciando un rettangolo avente le dimensioni dell'oggetto da creare.

Queste ultime possono essere modificate in qualsiasi momentotrascinando i bordi dell'elemento con il mouse. Sempre con l'ausilio diquesto strumento, è possibile spostare qualsiasi oggetto in una diversaposizione. Agendo sulla finestra delle proprietà, è possibile denominarel'oggetto btScrivi (ove "bt" rappresenta l'abbreviazione di bottone) eassociare alla proprietà Caption, che contiene il testo che deve appariresul pulsante, il valore "Scrivi".

Gli eventi

Il form appare come visualizzato in Figura 1. A questo punto ènecessario rendere "attivo" il bottone, ovvero fare in modo che alverificarsi dell'evento costituito dalla sua pressione sia eseguito delcodice che provveda a modificare il contenuto della label. A tal fine,occorre selezionare il pulsante e fare su di esso un doppio clic con ilmouse.

Si provoca così l'apertura di una finestra caratterizzata da una barranella parte superiore, in cui è possibile osservare due liste a scomparsa.

Quella posta a sinistra contiene il nome dell'oggetto, mentre in quella didestra sono elencati tutti i possibili eventi che esso può generare.

Volendo fare in modo che la risposta avvenga in occasione dellapressione del pulsante, occorre selezionare nella lista l'evento Click. Siprovoca così la creazione della procedura btScrivi_Click, di cui èautomaticamente visualizzata l'intestazione nella parte inferiore dellafinestra, seguita dalla frase End Sub, che indica la fine del blocco dicodice.

Le istruzioni che devono essere eseguite in risposta all'evento vannoinserite nello spazio compreso fra le righe generate automaticamente,avendo l'accortezza di indicare un solo comando per linea. Per fare inmodo che il programma visualizzi per mezzo della label lblMessaggio iltesto "Benvenuto in Visual Basic", è necessario variare la proprietàCaption di quest'ultima. La procedura da associare al pulsante è quindi laseguente:

Sub btScrivi_Click ()

lblMessaggio.Caption = "Benvenuto in Visual Basic"

End Sub

Si noti che il nome della proprietà segue quello dell'oggetto, da cui èseparato per mezzo di un punto.

Per verificare il funzionamento dell'applicazione, è necessario selezionarela voce Start del menu Run, oppure premere il tasto F5.

È così possibile osservare che, pur digitando una sola riga di codice, èstato creato un vero programma operante in ambiente Windows conun'interfaccia grafica.

Page 5: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte I)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb01/index.htm[23/09/2010 4:38:12]

I metodi

Come si è già accennato, ogni oggetto è in grado di ricevere dei comandiche possono provocare la variazione di alcune proprietà o la generazionedi eventi.

Si tratta dei metodi. L'invocazione di un metodo avviene secondo lasintassi:

<oggetto>.<metodo> [<parametro>, ... ,<parametro>]

Al nome dell'oggetto è necessario far seguire, separato da un punto,quello del metodo e gli eventuali parametri.

Ad esempio, l'aggiunta della riga

lblMessaggio.Move 0,0

nella procedura vista in precedenza, provoca l'esecuzione del metodoMove da parte dall'oggetto lblMessaggio. La coppia 0, 0 rappresental'insieme dei parametri.

L'effetto che si ottiene consiste nello spostamento dell'etichetta testualenell'angolo superiore sinistro del form, ovvero nel punto di cui iparametri rappresentano le coordinate.

Le variabili

Anche Visual Basic, come tutti i linguaggi di programmazione, prevedel'uso delle variabili, mediante le quali è possibile memorizzare dei valoritestuali o numerici in strutture a cui il programma può accedere grazie aun nome assegnato loro in fase di creazione.

Una variabile è detta locale quando è definita all'interno di unaprocedura; la sua creazione avviene quando si fa riferimento ad essa perla prima volta, oppure quando è eseguita l'istruzione Dim, che presentala seguente sintassi:

Dim <nome> [As <tipo>]

in cui <nome> rappresenta il nome da assegnare alla variabile.

Esso non si sottrae alla regola valida per tutti gli identificatori, ivicompresi i nomi degli oggetti, che impone loro di essere costituiti dadelle sequenze di caratteri alfabetici o numerici prive di spazi ed aventiper iniziali delle lettere dell'alfabeto.

È inoltre possibile, anche se non indispensabile (come sottolineato dallapresenza delle parentesi quadre), aggiungere all'istruzione Dimun'indicazione del tipo di dato da creare. Visual Basic prevede numerositipi standard. I più utilizzati sono integer, usato per rappresentare i datinumerici interi compresi fra -32,768 a 32,767, string, che può conteneredelle sequenze (stringhe) alfanumeriche composte al massimo da circa65500 caratteri, long, in grado di ospitare numeri interi compresi fra -2,147,483,648 e 2,147,483,647, single e double, con cui è possibilememorizzare numeri reali anche di notevole entità.

Se invece è omessa la dichiarazione del tipo, la variabile è definitavariant. Questo formato non è previsto dalla maggior parte dei linguaggi

Page 6: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte I)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb01/index.htm[23/09/2010 4:38:12]

di programmazione tradizionali. La sua caratteristica fondamentale èl'universalità. Una variabile variant, infatti, può contenere dei dati aventiqualsiasi formato.

È buona norma, tuttavia, non fare largo uso di strutture di questo tipo,in quanto la loro gestione da parte dell'interprete è poco efficiente.

Una variabile locale può anche non essere dichiarata. In questo caso, lasua creazione avviene la prima volta in cui si fa riferimento ad essa.

In assenza di dichiarazione, è necessario aggiungere al nome unidentificatore di tipo, costituito da un carattere. In caso di sua omissione,la variabile è creata di tipo Variant. I principali identificatori di tipo sono iseguenti: $ (String), % (Integer), & (Long), ! (Single), # (Double).

Ad esempio, è possibile creare una variabile di tipo numerico intero edassegnarle il valore 5 sia scrivendo

Dim A as Integer

A = 5

sia con la riga

A% = 5

Dopo l'esecuzione dell'ultima istruzione presente nella procedura in cuisono state create, le variabili locali sono automaticamente distrutte.

Per fare in modo che il loro valore sia conservato anche in occasionedelle chiamate successive, è necessario dichiarare le variabili sostituendoStatic alla parola chiave Dim.

In alcuni casi, si rivela necessario fare in modo che una variabile non siamai distrutta e sia accessibile anche dalle altre procedure presenti in unform.

In questo caso, è necessario selezionare la sezione General nella lista adiscesa posta nella parte superiore sinistra della finestra contenente ilcodice associato al form, la voce Declarations nella lista di destra edichiarare la variabile per mezzo dell'istruzione Dim.

Quando invece si presenta la necessità di fare in modo che una strutturasia accessibile da tutte le procedure presenti nell'applicazione,indipendentemente dal form in cui esse si trovano, è necessario utilizzareper la dichiarazione la parola chiave Global.

Una variabile dichiarata in questo modo è detta globale. La suadichiarazione è impossibile all'interno di un form. Essa deve essereeffettuata in un modulo, ovvero in un file di testo caratterizzatodall'estensione .BAS, che è aggiunto al progetto selezionando la voce AddModule del menu Project. La riga di codice rappresenta un esempio didichiarazione di una variabile globale:

Global NomeCognome as String

Un esempio di utilizzo di una variabile

Si consideri l'applicazione precedentemente realizzata. Si desidera

Page 7: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte I)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb01/index.htm[23/09/2010 4:38:12]

modificarla per creare un semplice strumento in grado di visualizzare iltempo trascorso dall'ultima pressione del pulsante btScrivi.

Per fare ciò, è necessario aggiungere al form un timer. Si tratta di unoggetto in grado di generare un evento ad intervalli regolari, la cuifrequenza è decisa dal programmatore.

Per inserire tale elemento, occorre selezionare sulla toolbox l'icona aforma di cronografo e disegnare un rettangolo sul form. Si provvede poia selezionare il nuovo oggetto, a visualizzare la finestra Properties e adassegnare il valore 1000 alla proprietà Interval.

In tal modo si definisce il periodo (in millisecondi) che intercorre fra dueeventi. L'impostazione effettuata provoca la generazione di un eventoogni secondo.

Anche in questo caso, è possibile associare al verificarsi di questi eventiun insieme di istruzioni da eseguire. Ciò è possibile facendo doppio clicsull'oggetto.

Si provoca così l'apertura della finestra del codice sorgente e la creazionedella procedura Timer1_Timer, in cui è possibile scrivere:

Sub Timer1_Timer ()

NumSecondi = NumSecondi + 1

lblMessaggio.Caption = Str$(NumSecondi)

End Sub

Essa ha lo scopo di incrementare di un'unità il valore della variabileNumSecondi, usata per conteggiare i secondi e di visualizzare tale valoreall'interno della label. A tal fine, il risultato del conteggio è convertito intesto tramite la funzione Str$ ed è assegnato alla proprietà Captiondell'oggetto che provvede a visualizzarlo sullo schermo.

Per consentire l'azzeramento del contasecondi in seguito alla pressionedel pulsante btScrivi, è necessario modificare la procedura associata atale evento.

Ciò è possibile facendo doppio clic sul bottone e sostituendo le istruzioniprecedentemente inserite con le seguenti:

Sub btScrivi_Click ()

NumSecondi = 0

End Sub

Affinché la variabile NumSecondi possa essere utilizzata da entrambe leprocedure, è necessario che sia accessibile in tutto il form. Come visto inprecedenza, perché ciò sia possibile, si deve digitare nella sezioneGlobal/Declarations la riga

Dim NumSecondi as Long

Conclusioni

Come dimostrato dagli esempi sopra descritti, si può realizzare

Page 8: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte I)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb01/index.htm[23/09/2010 4:38:12]

un'applicazione funzionante in ambiente Windows in un batter d'occhio,semplicemente facendo uso del mouse e scrivendo un numero davveroridotto di righe di codice.

È proprio grazie alla notevole facilità d'uso, oltre che all'affidabilitàdell'interprete di cui è dotato, che Visual Basic è da molti considerato lostrumento ideale per la realizzazione di programmi di piccola e mediaentità.

(c) 1998 Edizioni Infomedia srl

Page 9: Corso Visual Basic

La dichiarazione di una variabile accessibile da tutte le procedure presenti nel form

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb01/fig4.htm[23/09/2010 4:39:19]

Figura 4La dichiarazione di una variabile accessibile da tutte le procedure presenti nel form

Page 10: Corso Visual Basic

L'ambiente di sviluppo di Visual Basic 5

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb01/fig1.htm[23/09/2010 4:42:19]

Figura 1L'ambiente di sviluppo di Visual Basic 5

Page 11: Corso Visual Basic

La toolbox e la finestra "Properties"

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb01/fig2.htm[23/09/2010 4:42:54]

Figura 2La toolbox e la finestra "Properties"

Page 12: Corso Visual Basic

L'applicazione di esempio in esecuzione

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb01/fig3.htm[23/09/2010 4:43:04]

Figura 3L'applicazione di esempio in esecuzione

Page 13: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 2)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb02/index.htm[26/09/2010 12:37:56]

Corso di Visual Basic(Parte 2)

Le soluzioni degli esercizi proposti nellaprima parte

La struttura If

La funzione Val

Le strutture If nidificate

Conclusioni

Figure

Figura 1

Figura 2

Figura 3

Figura 4

(c) 1997, Edizioni Infomedia srl

Corso di

Visual Basic

(Parte 2)

di Maurizio Crespi

La seconda parte del corso introduttivo alla programmazione in Visual Basic si pone come scopo di insegnare l'uso della struttura dicontrollo If e delle proprie varianti.

Dopo aver studiato come si creano delle semplici applicazioni ed averpreso confidenza con i tipi di dati fondamentali, è ora giunto ilmomento di occuparsi delle strutture di controllo, mediante le quali sipossono scrivere dei programmi in grado di comportarsi in mododiverso a seconda dei valori assunti dai dati da elaborare.

Le soluzioni degli esercizi proposti nella prima parte

Prima di affrontare nuovi argomenti, è bene rivedere ciò che è statooggetto di studio nella scorsa puntata. Lo spunto è offerto dallacorrezione degli esercizi in essa proposti.

Il primo esercizio

Il primo esercizio prevede la creazione di un programma in grado disimulare il funzionamento di un interruttore mediante due pulsanti,riportanti rispettivamente le scritte "ON" e "OFF" e un'etichetta ditesto, nella quale devono essere visualizzate in alternativa leindicazioni "Acceso" e "Spento".

La prima fase consiste nel creare un nuovo progetto e nell'inserireall'interno del form principale i tre elementi grafici. Si provvede poi,per mezzo dell'apposita finestra, ad assegnare ad essi i valori dellaproprietà Caption, affinché sui pulsanti appaiano le scritte "ON" e"OFF". L'interfaccia appare come nella Figura 1.

È buona norma assegnare anche dei nomi agli oggetti. Ciò comportal'impostazione per ognuno di essi della proprietà Name. Si suppongadi utilizzare i nomi btnON, btnOFF, per i pulsanti e lblValore perl'etichetta testuale.

L'ultimo passo consiste nello scrivere il codice da associare allapressione dei bottoni. Essi devono semplicemente variare il testovisualizzato dalla label, ovvero modificare la sua proprietà Caption.Dopo aver premuto due volte il tasto sinistro del mouse sul pulsantebtnON ed aver quindi aperto la finestra che ospita il codice di rispostaall'evento Click, è necessario scrivere quanto segue:

Private Sub btnON_Click()

Page 14: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 2)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb02/index.htm[26/09/2010 12:37:56]

lblValore.Caption = "Acceso"

End Sub

Si noti che l'indicazione Private, il cui significato sarà analizzato in unodei prossimi numeri, deve essere omessa sulle versioni di Visual Basicprecedenti la 4.0. In modo perfettamente analogo si può completarel'applicazione associando al pulsante btnOFF la procedura:

Private Sub btnOFF_Click()

lblValore.Caption = "Spento"

End Sub

Il secondo esercizio

Nel secondo esercizio è richiesta la modifica del funzionamento di unprogramma che simula un cronografo. L'interfaccia si compone di unpulsante di azzeramento e di una label che visualizza il numero deisecondi trascorsi. Si desidera fare in modo che l'indicazione del temposia rappresentata nel formato HH:MM:SS.

Il conteggio avviene per mezzo di un timer regolato, mediantel'impostazione della proprietà Interval al valore 1000, in modo dagenerare un evento ogni secondo. La procedura da modificare èpertanto quella che gestisce gli eventi Timer da esso prodotti. Devonoessere eseguite delle divisioni successive per determinare il numerodelle ore, dei minuti e dei secondi. Il codice diventa pertanto ilseguente:

Private Sub Timer1_Timer()

Dim Ore, Minuti, Secondi, Resto As Integer

Dim StringaOre, StringaMinuti, StringaSecondi,

Tempo As String

NumSecondi = NumSecondi + 1

Ore = Int(NumSecondi / 3600)

Resto = NumSecondi - (Ore * 3600)

Minuti = Int(Resto / 60)

Secondi = Resto - (Minuti * 60)

StringaOre = Str$(Ore)

StringaMinuti = Str$(Minuti)

StringaSecondi = Str$(Secondi)

Tempo = StringaOre + ":"

Tempo = Tempo + StringaMinuti + ":"

Tempo = Tempo + StringaSecondi

lblMessaggio.Caption = Tempo

End Sub

Si noti che, per estrarre la parte intera del risultato di ogni divisione,si è fatto ripetutamente uso della funzione Int.

Il numero delle ore è calcolato dividendo per 3600 il totale deisecondi, contenuto nella variabile globale NumSecondi. Il resto è poidiviso per 60 al fine di quantificare i minuti. Questa operazione generaun nuovo resto, che rappresenta il numero di secondi. I valori ottenutisono successivamente trasformati in sequenze alfanumeriche e copiatinella variabile Tempo, anch'essa di tipo String, avendo cura diinterporre fra di loro il carattere ":". Si noti che, per concatenare lestringhe, si fa uso dell'operatore di addizione "+". Il valore della

Page 15: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 2)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb02/index.htm[26/09/2010 12:37:56]

variabile Tempo è infine visualizzato per mezzo della label.

La struttura If

Avviando l'applicazione sopra descritta, è possibile osservare che ilcontenuto dell'etichetta non è esattamente espresso nel formatoHH:MM:SS. Infatti, l'indicazione appare come in Figura 2, ossia ivalori indicanti il numero di ore, minuti e secondi non sonoobbligatoriamente composti da due cifre. Si supponga di volermodificare il programma affinché provveda ad anteporre uno zero nonsignificativo al contenuto delle variabili StringaOre, StringaMinuti eStringaSecondi ogniqualvolta esse risultino composte da una solacifra. L'applicazione, in questo caso, deve essere in grado diriconoscere una condizione, nella fattispecie la presenza di un valoreinferiore a dieci e di intervenire anteponendo uno zero solo quandoessa è verificata. A differenza degli esempi fino ad ora esaminati, ilflusso delle istruzioni all'interno della procedura non è più rigidamentedefinito, ma può variare in base al verificarsi di alcune condizioni. Ilprogramma deve pertanto essere in grado di prendere delle decisioni.Come la quasi totalità dei linguaggi di programmazione, Visual Basicprevede a tal fine la struttura If, caratterizzata dalla seguentesintassi:

If <condizione> Then

<istruzioni da eseguire se la condizione è vera>

[Else

<istruzioni da eseguire se la condizione è falsa>]

End If

La condizione può essere rappresentata da pressoché qualsiasiespressione booleana. Si ricorda che un'espressione è così detta sepuò assumere solo due valori distinti, cioè vero o falso. Se essa èverificata, l'interprete esegue il blocco di istruzioni indicato fra leparole chiave Then e Else. In caso contrario, è eseguito il secondogruppo di comandi. Si noti che quest'ultimo può anche essere assente.In tal caso, la parola chiave Else non va utilizzata e non è eseguitoalcun codice in caso di mancata verifica della condizione.

La frase End If delimita la struttura. Tutte le istruzioni che la seguonosono eseguite in modo indipendente dal valore dell'espressionebooleana. La procedura da associare all'evento Timer può esserepertanto modificata come indicato:

Private Sub Timer1_Timer()

Dim Ore, Minuti, Secondi, Resto As Integer

Dim StringaOre, StringaMinuti, StringaSecondi,

Tempo As String

NumSecondi = NumSecondi + 1

Ore = Int(NumSecondi / 3600)

Resto = NumSecondi - (Ore * 60)

Minuti = Int(Resto / 60)

Secondi = Resto - (Minuti * 60)

If Ore < 10 Then

StringaOre = "0" & Ore

Page 16: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 2)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb02/index.htm[26/09/2010 12:37:56]

Else

StringaOre = Str$(Ore)

End If

If Minuti < 10 Then

StringaMinuti = "0" & Minuti

Else

StringaMinuti = Str$(Minuti)

End If

If Secondi < 10 Then

StringaSecondi = "0" & Secondi

Else

StringaSecondi = Str$(Secondi)

End If

Tempo = StringaOre + ":"

Tempo = Tempo + StringaMinuti + ":"

Tempo = Tempo + StringaSecondi

lblMessaggio.Caption = Tempo

End Sub

Essa si differenzia dalla precedente per l'introduzione di tre strutturedi controllo pressoché analoghe. Si osservi ad esempio la prima; lacondizione è vera se la variabile Ore contiene un numero inferiore adieci. In questo caso, alla variabile StringaOre è associato un testocomposto dal carattere "0" e dal valore contenuto nella variabile Ore.Si noti che in questo caso non si è fatto uso della funzione Str$.Quando un dato numerico è assegnato ad una variabile di tipo stringa,infatti, la conversione di formato è eseguita automaticamente, acondizione che il codice utilizzato non possa generare delle ambiguità.È per questo motivo che la concatenazione delle stringhe è stataeffettuata mediante il simbolo "&", anziché con l'operatore diaddizione che, essendo applicabile anche ai valori numerici, avrebbereso l'interprete incapace di dedurre le reali intenzioni delprogrammatore. Il carattere "&" può essere utilizzato esclusivamenteper unire due stringhe alfanumeriche e quindi pone al riparo da ognidubbio.

La funzione Val

Nel seguito di questa trattazione si farà uso delle caselle di testo(textbox). Esse risultano estremamente simili alle label, ma sidifferenziano da esse in quanto rendono possibile la modifica delproprio contenuto all'utente finale. Sono pertanto utilizzateogniqualvolta si presenti la necessità di richiedere un datoalfanumerico all'utilizzatore del programma. Per verificare o modificareil loro contenuto è necessario accedere alla proprietà Text, che èsempre di tipo String. La sua conversione in una valore numerico,quando possibile, può essere effettuata per mezzo della funzione Val,la cui sintassi è:

<var1> = Val(<var2>)

dove var1 è di tipo numerico e var2 rappresenta una stringa. Occorrenotare che la funzione esegue una scansione del testo fornitole comeparametro a partire dal carattere posto all'estrema sinistra. Il controllo

Page 17: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 2)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb02/index.htm[26/09/2010 12:37:56]

termina quando è incontrato un elemento non numerico. Pertanto, lacondizione

Val("1234") = Val("1234abc")

è verificata. Inoltre, è vera anche la condizione:

Val("abcde") = 0

Facendo tesoro di ciò che è stato appena appreso, si provi a realizzareuna semplice applicazione in grado di visualizzare in una label il valoreassoluto di un numero posto in una casella di testo, senza far usodella funzione Abs. Il calcolo può essere eseguito in corrispondenzadella pressione di un pulsante.

Le strutture If nidificate

Si supponga di voler realizzare un programma in grado di calcolare ilvalore massimo fra due numeri forniti in ingresso mediante dellecaselle di testo e di visualizzare il risultato in una label. L'interfaccia èrappresentata nella Figura 3. Si supponga di assegnare i nomitxtPrimoValore e txtSecondoValore alle textbox. La procedura daassociare come risposta alla pressione del pulsante di calcolo è laseguente:

Private Sub btCalcola_Click()

Dim Valore1, Valore2 As Double

Dim Risultato As String

Valore1 = Val(txtPrimoValore.Text)

Valore2 = Val(txtSecondoValore.Text)

If Valore1 > Valore2 Then

Risultato = "Valore massimo: " & Valore1

Else

If Valore1 < Valore2 Then

Risultato = "Valore massimo: " & Valore2

Else

Risultato = "I valori sono uguali"

End If

End If

lblMessaggio.Caption = Risultato

End Sub

Dopo aver copiato i dati in ingresso in variabili numeriche,l'applicazione procede al confronto fra i valori. Dapprima il programmaverifica se prevale il contenuto della variabile Valore1 rispetto a quellodi Valore2. Se la condizione è verificata, il massimo è copiato nellavariabile Risultato, che costituisce il testo da visualizzare per mezzodella label lblMessaggio. Altrimenti, è eseguito l'altro blocco dellastruttura If, ovvero è verificata la prevalenza del secondo valorerispetto al primo. In caso negativo, è segnalata l'uguaglianza dei datiin ingresso. È possibile osservare che è stata posta una struttura Ifall'interno di un'altra. L'annidamento di più blocchi di programma èuna pratica molto comune quando si fa uso di linguaggi moderni comeVisual Basic. Si noti che se fosse stato necessario eseguire il confrontofra un numero più elevato di valori, l'uso di strutture nidificate

Page 18: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 2)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb02/index.htm[26/09/2010 12:37:56]

avrebbe influenzato negativamente la leggibilità del programma. Perridurre tali effetti negativi è possibile utilizzare la parola chiave ElseIf,che permette di mantenere un'organizzazione a due livelli anche inpresenza di un numero elevato di confronti. Ecco come si presenta laprocedura modificata:

Private Sub btCalcola_Click()

Dim Valore1, Valore2 As Double

Dim Risultato As String

Valore1 = Val(txtPrimoValore.Text)

Valore2 = Val(txtSecondoValore.Text)

If Valore1 > Valore2 Then

Risultato = "Valore massimo: " & Valore1

ElseIf Valore1 < Valore2 Then

Risultato = "Valore massimo: " & Valore2

Else

Risultato = "I valori sono uguali"

End If

lblMessaggio.Caption = Risultato

End Sub

L'uso delle parole riservate ElseIf permette di aumentare a piacimentoil numero di condizioni da controllare all'interno della stessa struttura.Se nessuna di esse risulta verificata, allora è eseguito il codicespecificato dopo la parola chiave Else. Per verificarne l'utilità, si provia realizzare un'applicazione in grado di visualizzare un messaggioindicante se il dato inserito in una textbox rappresenta il nome di unodei giorni della settimana.

Conclusioni

Le strutture di controllo, oggetto di questa trattazione, danno alleapplicazioni la flessibilità necessaria per svolgere operazioni nonbanali. Per questo motivo, la loro conoscenza è di importanzafondamentale. Al lettore è pertanto rivolto l'invito ad esercitarsinell'uso di tali costrutti. Buon lavoro, dunque!

(c) 1998 Edizioni Infomedia srl

Page 19: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 2)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb02/index.htm[26/09/2010 12:37:56]

Page 20: Corso Visual Basic

L'applicazione di esempio

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb02/FIG3.HTM[26/09/2010 12:48:06]

Figura 3L'applicazione di esempio

Page 21: Corso Visual Basic

La soluzione del secondo esercizio

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb02/FIG2.HTM[26/09/2010 12:47:40]

Figura 2La soluzione del secondo esercizio

Page 22: Corso Visual Basic

La soluzione del primo esercizio

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb02/FIG1.HTM[26/09/2010 12:47:09]

Figura 1La soluzione del primo esercizio

Page 23: Corso Visual Basic

La procedura che risponde alla pressione del pulsante btCalcola

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb02/FIG4.HTM[26/09/2010 12:48:48]

Figura 4La procedura che risponde alla pressione del pulsante btCalcola

Page 24: Corso Visual Basic

La soluzione del primo esercizio

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb02/fig1.htm[26/09/2010 12:52:10]

Figura 1La soluzione del primo esercizio

Page 25: Corso Visual Basic

La soluzione del secondo esercizio

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb02/fig2.htm[26/09/2010 12:52:55]

Figura 2La soluzione del secondo esercizio

Page 26: Corso Visual Basic

L'applicazione di esempio

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb02/fig3.htm[26/09/2010 12:53:16]

Figura 3L'applicazione di esempio

Page 27: Corso Visual Basic

La procedura che risponde alla pressione del pulsante btCalcola

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb02/fig4.htm[26/09/2010 12:53:26]

Figura 4La procedura che risponde alla pressione del pulsante btCalcola

Page 28: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 3)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb03/index.htm[26/09/2010 12:58:05]

Corso di Visual Basic(Parte 3)

Le soluzioni agli esercizi della scorsapuntata

La struttura Select Case

Quando utilizzare la struttura SelectCase

Confronti Multipli

Gli operatori logici elementari

L'operatore And

L'operatore Or

L'operatore Not

Conclusioni

Figure

Figura 1

Figura 2

Figura 3

Figura 4

(c) 1997, Edizioni Infomedia srl

Corso di

Visual Basic

(Parte 3)

di Maurizio Crespi

Il corso dedicato alla programmazione con Microsoft Visual Basic continua con l'analisi della struttura di controllo Select Case e deglioperatori logici fondamentali

Spesso si rivela necessario sviluppare dei programmi caratterizzatidalla capacità di eseguire istruzioni diverse in base al valore assuntoda una o più variabili. A tal fine, Visual Basic prevede la struttura diselezione multipla Select Case, al centro dell'attenzione in questa terzaparte del corso dedicato alla programmazione con il noto strumentoMicrosoft. Continua pertanto lo studio delle strutture di controllo, dellequali difficilmente un'applicazione può fare a meno.

Le soluzioni agli esercizi della scorsa puntata

Prima di affrontare lo studio di nuovi argomenti, è opportuno rivederequanto esposto nello scorso numero. Come di consueto, lo spunto èofferto dalla correzione degli esercizi in esso proposti.

Primo esercizio

Il primo esercizio prevede la realizzazione di un programma in gradodi leggere un numero mediante una textbox e di visualizzarne il valoreassoluto. A tal fine, dopo aver creato un nuovo progetto, occorreaggiungere al form principale la casella di testo, a cui è possibileassegnare il nome txtNumero, nonché il pulsante btnCalcola, a cui èaffidata la funzione di provocare l'aggiornamento del contenuto dellalabel lblRisultato con il frutto dell'elaborazione. Ciò è ottenuto permezzo della seguente procedura:

Private Sub btnCalcola_Click()

Dim StringaNumero As String

Dim Numero As Integer

StringaNumero = txtNumero.Text

Numero = Val(StringaNumero)

If Numero > 0 Then

lblRisultato.Caption = "Valore assoluto: " & Numero

Else

lblRisultato.Caption = "Valore assoluto: " & Str(-1 *

Numero)

End If

End Sub

Page 29: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 3)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb03/index.htm[26/09/2010 12:58:05]

Il contenuto della textbox è posto nella variabile StringaNumero, cheè convertita in un dato numerico per mezzo della funzione Val. Perfare in modo che il valore sia mantenuto invariato qualora risultipositivo, o ne sia calcolato l'opposto altrimenti, si impone il ricorso aduna struttura If, associata alla condizione

Numero > 0

Quando essa è verificata, il valore numerico fornito in ingresso èvisualizzato senza subire modifiche. In caso contrario, la proceduraprovvede ad effettuare l'inversione di segno e ad assegnare ilrisultato, opportunamente trasformato in una stringa, alla label.

Secondo esercizio

Anche il secondo esercizio prevede la creazione di un programma ingrado di ricevere un valore in ingresso per mezzo di una textbox e divisualizzare un risultato mediante una label. L'applicazione dasviluppare deve controllare che il dato inserito dall'utente rappresentiuno dei nomi dei giorni della settimana. Si desidera fare in modo chela verifica sia svolta automaticamente ogniqualvolta il contenuto dellacasella di testo subisca una variazione. Questa condizione è segnalatadall'oggetto, a cui si suppone di aver assegnato il nometxtTestoDigitato, con la generazione dell'evento Change. Per associaread esso del codice, è sufficiente fare doppio clic con il mouse sullatextbox. In tal modo si crea la procedura txtTestoDigitato_Change, diseguito descritta.

Private Sub txtTestoDigitato_Change()

Dim Testo As String

Dim GiornoSettimana As Integer

Testo = UCase(txtTestoDigitato.Text)

If Testo = "LUNEDI" Then

GiornoSettimana = True

ElseIf Testo = "MARTEDI" Then

GiornoSettimana = True

ElseIf Testo = "MERCOLEDI" Then

GiornoSettimana = True

ElseIf Testo = "GIOVEDI" Then

GiornoSettimana = True

ElseIf Testo = "VENERDI" Then

GiornoSettimana = True

ElseIf Testo = "SABATO" Then

GiornoSettimana = True

ElseIf Testo = "DOMENICA" Then

GiornoSettimana = True

Else

GiornoSettimana = False

End If

If GiornoSettimana Then

lblRisultato.Caption = "E' un giorno della settimana"

Else

lblRisultato.Caption = "Non è un giorno della settimana"

End If

End Sub

Page 30: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 3)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb03/index.htm[26/09/2010 12:58:05]

Si noti l'uso della funzione UCase, che provvede a restituire la stringaderivante dalla conversione in lettere maiuscole del dato in ingresso.Ciò permette di verificare la corrispondenza del testo digitatodall'utente al nome di un giorno della settimana in modo indipendentedall'uso che è stato effettuato durante la sua scrittura delle letteremaiuscole. Il numero dei confronti, in questo caso, risulta elevato. Siricorre pertanto all'uso della parola chiave ElseIf, al fine disemplificare la struttura di controllo, che in tal modo risultaorganizzata in un unico livello. Essa provvede alla modifica dellavariabile intera GiornoSettimana, che può assumere solamente duevalori. Il primo, corrispondente al valore logico True, è assegnato nelcaso in cui il confronto con uno dei nomi dei giorni della settimanaabbia fornito un esito positivo. In caso contrario, la variabile prende ilvalore False. Tale dato è oggetto di valutazione nella secondastruttura If che visualizza, facendo uso di una label a cui è statoassegnato il nome lblRisultato, un messaggio indicante l'esito dellaverifica. Si noti che la condizione è rappresentata dalla sola variabileGiornoSettimana, a cui non è associato alcun operatore di confronto.Ciò a prima vista può lasciare sconcertati. In realtà, è perfettamentelecito, in quanto è noto che la condizione che regola una struttura Ifdeve essere di tipo booleano, ovvero deve poter assumereesclusivamente i valori True o False. Proprio come la variabileGiornoSettimana.

La struttura Select Case

L'esercizio precedente rappresenta un esempio di come una strutturaIf possa assumere dimensioni notevoli. In questi casi, la leggibilità delprogramma rischia di essere gravemente intaccata. Per evitare chequesto accada, è possibile ricorrere ad una diversa struttura dicontrollo denominata Select Case, la cui sintassi è la seguente:

Select Case <variabile>

Case <valore 1>:

<blocco istruzioni 1>

[Case <valore 2>:

<blocco istruzioni 2>]

.

.

.

[Case <valore n>:

<blocco istruzioni n>]

[Case Else:

<istruzioni da eseguire se tutti i confronti falliscono>]

End Select

La struttura Select Case è adatta ad essere utilizzata ogniqualvolta sidesideri variare il flusso del programma in base al risultato delconfronto fra il valore di una variabile e uno o più dati costanti.Ognuno di essi deve essere preceduto dalla parola chiave Case eseguito dai due punti, nonché dal gruppo di istruzioni da eseguirequando il confronto ha esisto positivo. Inoltre, è possibile utilizzare laclausola Case Else, che va obbligatoriamente posta alla fine dellastruttura, per definire un gruppo di istruzioni che deve essere eseguito

Page 31: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 3)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb03/index.htm[26/09/2010 12:58:05]

solo se tutti i confronti hanno ottenuto un esito negativo. Laprocedura che costituisce la soluzione del secondo esercizio può quindiessere riscritta nel modo seguente:

Private Sub txtTestoDigitato_Change()

Dim Testo as string

Dim GiornoSettimana as integer

Testo = Ucase(txtTestoDigitato.text)

Select Case Testo

Case "LUNEDI":

GiornoSettimana = True

Case "MARTEDI":

GiornoSettimana = True

Case "MERCOLEDI":

GiornoSettimana = True

Case "GIOVEDI":

GiornoSettimana = True

Case "VENERDI":

GiornoSettimana = True

Case "SABATO":

GiornoSettimana = True

Case "DOMENICA":

GiornoSettimana = True

Case Else

GiornoSettimana = False

End Select

If GiornoSettimana Then

lblRisultato.caption = "E' un giorno della settimana"

Else

lblRisultato.caption = "Non è un giorno della settimana"

End If

End Sub

Il codice risulta in questo caso più leggibile. Tuttavia, c'è spazio perun ulteriore miglioramento, grazie alla possibilità di utilizzare la virgolaper separare i valori a cui devono essere fatte corrispondere sequenzeanaloghe di istruzioni. La struttura Select Case può quindi esserenuovamente riscritta in modo estremamente più sintetico:

Select Case Testo

Case "LUNEDI", "MARTEDI", "MERCOLEDI", "GIOVEDI",

"VENERDI", "SABATO", "DOMENICA":

GiornoSettimana = True

Case Else

GiornoSettimana = False

End Select

È possibile pertanto notare come talvolta l'impiego della strutturaCase possa agevolare notevolmente il compito del programmatore. Alfine di verificare ciò, si provi a realizzare un'applicazione che, ricevutoin ingresso un numero composto da una sola cifra, restituisca unastringa contenente l'indicazione dello stesso valore indicato in lettere.

Quando utilizzare la struttura Select Case

Page 32: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 3)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb03/index.htm[26/09/2010 12:58:05]

La struttura Select Case, potendo agire su una sola variabile pervolta, presenta alcune limitazioni rispetto alla struttura If, in quantonon rende possibile l'esecuzione di valutazioni complesse. Si osservi ilseguente esempio:

If (valore1 = 2) Then

Risultato = 5

ElseIf (valore2 = 3) Then

Risulato = 7

End if

Non è possibile eseguire le stesse operazioni mediante una solastruttura Case. Ne sono necessarie due nidificate, come illustrato diseguito:

Select Case Valore1

Case 2:

Risultato = 5

Case Else:

Select Case Valore2

Case 3:

Risultato = 7

End Select

End Select

La leggibilità del codice è in questo caso peggiorata. Inoltre, il numerodelle righe digitate è aumentato. Da ciò appare evidente che l'usodella struttura Case non è sempre consigliabile. La sua opportunitàdeve essere valutata attentamente in fase di progettazione.

Confronti Multipli

Fino ad ora si è fatto uso della struttura di selezione multipla perconfrontare il valore della variabile di controllo con alcuni dati costanti.In realtà, ci sono altre potenzialità nell'uso del costrutto Case cheandiamo ora ad esplorare.

L'uso della struttura Case per valutare l'appartenenza a degli intervallidi valori.

Per mezzo della struttura Case diventa estremamente semplicevalutare l'appartenenza del contenuto di una variabile a un intervallodi valori. Si supponga ad esempio di disporre di un form,caratterizzato anche questa volta dalla presenza di una label,denominata lblRisultato, di una casella di testo, a cui è assegnato ilnome txtValore e di un pulsante avente la funzione di avviarel'elaborazione. Si ipotizzi di voler avvisare mediante la label quando ilvalore indicato nella textbox, presunto numerico, risulta compreso fra1 e 10, oppure se appartiene all'intervallo avente per estremi 11 e100. Supponendo che il pulsante sia denominato btnVerifica, èpossibile digitare la procedura:

Private Sub btnVerifica_Click()

Dim Testo As String

Dim Valore As Integer

If IsNumeric(txtValore.Text) Then

Valore = Val(txtValore.Text)

Page 33: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 3)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb03/index.htm[26/09/2010 12:58:05]

Select Case Valore

Case 1 To 10:

Testo = "E' compreso fra 1 e 10"

Case 11 To 100:

Testo = "E' compreso fra 11 e 100"

Case Else:

Testo = "Non appartiene agli intervalli"

End Select

Else

Testo = "Non è un valore numerico"

End If

lblRisultato.Caption = Testo

End Sub

Si noti l'uso della funzione IsNumeric atta a controllare che la stringacontenuta nella textbox, contenga effettivamente un numero(convertibile successivamente in un valore numerico per mezzo dellafunzione Val). Infatti, solo in questo caso sono effettuati i confronti.Altrimenti, si provvede a visualizzare nella label un opportunomessaggio di avviso. Questa volta, la struttura Select Case non fariferimento a dei valori costanti, bensì a degli intervalli, ognuno deiquali è specificato per mezzo dei propri estremi, inframmezzati dallaparola chiave To.

L'uso della struttura Case per valutare se un valore è superiore ad unadata soglia.

Si supponga di voler modificare l'esempio precedente per valutare se ilvalore inserito è superiore a 100. La struttura case deve esseremodificata come segue:

Select Case Valore

Case 1 To 10:

Testo = "E' compreso fra 1 e 10"

Case 11 To 100:

Testo = "E' compreso fra 11 e 100"

Case Is > 100:

Testo = "E' maggiore di 100"

Case Else:

Testo = "Non appartiene agli intervalli"

End Select

Si noti l'introduzione della parola chiave Is, seguita da un'espressionedi confronto. Se quest'ultima ha esito positivo, è eseguita l'istruzioneassociata.

Gli operatori logici elementari

Si ipotizzi di voler scrivere una struttura If per verificare se il valore diuna variabile numerica intera, denominata Numero, appartieneall'intervallo compreso fra 10 e 100. È necessario valutarecontemporaneamente due condizioni:

il numero deve essere maggiore di 10

il numero deve essere inferiore a 100

Page 34: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 3)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb03/index.htm[26/09/2010 12:58:05]

Per far sì che sia prodotta una stringa indicante l'esito del confronto,occorre digitare il seguente codice:

If Numero > 10 then

If Numero < 100 then

Testo = "Il numero è compreso fra 10 e 100"

Else

Testo = "Il numero non appartiene all'intervallo"

End if

End if

Si noti che l'uso della struttura Case avrebbe consentito la creazione diun listato più semplice e leggibile. È però possibile operare unasemplificazione combinando i due confronti, ovvero creando un'unicaespressione booleana in grado di stabilire l'appartenenza all'intervallospecificato. A tal fine, è necessario ricorrere agli operatori logici.

L'operatore And

Spesso si rivela necessario valutare la contemporanea validità di due opiù condizioni.

È il caso dell'esempio precedente, in cui si desidera verificare se lavariabile Numero contiene un valore maggiore di 10 e nel contempominore di 100.

L'operatore And assolve questo compito, restituendo il valore logicoTrue solo se le condizioni a cui è applicato sono contemporaneamenteverificate. Il codice può pertanto essere riscritto come segue:

If (Numero > 10) And (Numero < 100) Then

Testo = "Il numero è compreso fra 10 e 100"

Else

Testo = "Il numero non appartiene all'intervallo"

End if

Come è possibile notare, la struttura risulta più semplice, in quantocomposta da un solo livello.

L'operatore Or

A differenza del precedente, l'operatore Or restituisce il valore logicoTrue se almeno una delle condizioni specificate è vera. Ad esempio, lacondizione

(Numero = 5) Or (Numero > 11)

è verificata quando la variabile Numero assume un valore maggiore di11 o uguale a 5.

L'operatore Not

Un altro utile operatore logico è quello di negazione (Not). Come èfacile dedurre, esso restituisce il valore True se la condizione a cui è

Page 35: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 3)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb03/index.htm[26/09/2010 12:58:05]

applicato non è verificata, mentre restituisce False in caso contrario. Atitolo di esempio, si supponga di voler realizzare una struttura If ingrado di generare una stringa indicate se il valore della variabileNumero risulta contemporaneamente diverso da 5 e da 10. Il codiceda digitare è il seguente:

If Not ((Numero = 5) Or (Numero = 10)) Then

Testo = "Il numero è diverso da 5 e da 10"

End if

Si osservi la condizione. Essa risulta dalla combinazione di dueconfronti. Si tratta di

Numero = 5

e

Numero = 10

L'uso dell'operatore OR permette di verificare se almeno uno di essi haesito positivo. In tal caso, non deve essere fornita alcuna indicazione.La stringa deve essere creata, infatti, solo quando entrambi i confrontihanno esito negativo, ovvero quando l'espressione

(Numero = 5) Or (Numero = 10)

restituisce il valore False, ovvero quando è verificata la condizione:

Not ((Numero = 5) Or (Numero = 10))

Come esercizio, si provi a realizzare un programma che riceva iningresso una stringa contenente il nome di un mese e restituisca ilnumero dei giorni di cui esso si compone. Si preveda la possibilità dispecificare l'anno a cui fare riferimento, al fine di offrire una correttaindicazione della lunghezza del mese di febbraio anche negli annibisestili.

Conclusioni

Lo studio della struttura Select Case ha completato la panoramicasulle strutture di controllo iniziata nello scorso numero. Tali istruzioniricoprono un ruolo fondamentale nella quasi totalità delle applicazioni.La loro conoscenza è inoltre indispensabile per la comprensione degliargomenti che verranno trattati nelle prossime puntate di questocorso. Al lettore va pertanto l'invito ad esercitarsi sui concetti illustratie a non trascurare gli esercizi proposti.

(c) 1998 Edizioni Infomedia srl

Page 36: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 3)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb03/index.htm[26/09/2010 12:58:05]

Page 37: Corso Visual Basic

La soluzione del primo esercizio

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb03/fig1.htm[26/09/2010 12:59:13]

Figura 1La soluzione del primo esercizio

Page 38: Corso Visual Basic

La soluzione del secondo esercizio

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb03/fig2.htm[26/09/2010 12:59:35]

Figura 2La soluzione del secondo esercizio

Page 39: Corso Visual Basic

Il programma per determinare l'appartenenza di un numero a degli intervalli

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb03/fig3.htm[26/09/2010 12:59:43]

Figura 3Il programma per determinare l'appartenenza di un numero a degli intervalli

Page 40: Corso Visual Basic

L'ambiente di sviluppo di Visual Basic 5

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb03/fig4.htm[26/09/2010 12:59:52]

Figura 4L'ambiente di sviluppo di Visual Basic 5

Page 41: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 4)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb04/index.htm[26/09/2010 1:02:21]

Corso di Visual Basic(Parte 4)

Le soluzioni degli esercizi dello scorsonumero

Il ciclo For

Cicli nidificati

Le funzioni Len e Mid$

Cicli con decremento

Conclusioni

Figure

Figura 1

Figura 2

Figura 3

Figura 4

(c) 1997, Edizioni Infomedia srl

Corso di

Visual Basic

(Parte 4)

di Maurizio Crespi

Oggetto di studio della quarta puntata del corso dedicato allaprogrammazione in Visual Basic sono i cicli e in particolare la strutturaFor, mediante la quale è possibile far eseguire al calcolatore delleoperazioni ripetitive

Uno dei punti di forza dei calcolatori è rappresentato dalla possibilitàdi eseguire in modo estremamente veloce delle operazioni ripetitive. Atal fine, i linguaggi di programmazione mettono a disposizione dellestrutture che prendono il nome di cicli. Naturalmente, Visual Basic nonsi sottrae a questa regola. La prima struttura ad essere presa inesame è rappresentata dal ciclo For, a cui è dedicata questa lezione.

Le soluzioni degli esercizi dello scorso numero

Come sempre, prima di procedere allo studio dei nuovi argomenti,saranno illustrate le soluzioni degli esercizi proposti nello scorsonumero.

Primo esercizio

Il primo esercizio prevede la realizzazione di un programma in gradodi leggere un numero composto da una sola cifra e di offrire comerisultato la sua indicazione in lettere. Si tratta di una tipicaapplicazione della struttura Select Case, che opera una scelta fra diecivalori. Come interfaccia utente si fa uso di un form costituito da unatextbox, denominata txtCifra, a cui è affidata la ricezione dei dati iningresso. Il risultato è restituito per mezzo della label lblMessaggio,che deve essere aggiornata ogniqualvolta la cifra in ingresso subiscauna variazione, ovvero in corrispondenza del verificarsi dell'eventochange sulla textbox. La gestione di quest'ultimo è possibile permezzo della seguente procedura:

Private Sub txtCifra_Change()

Dim Cifra As Integer

Dim DatoIngresso As String

DatoIngresso = txtCifra.Text

If IsNumeric(DatoIngresso) Then

Cifra = Val(DatoIngresso)

Select Case Cifra

Case 0

Page 42: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 4)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb04/index.htm[26/09/2010 1:02:21]

lblMessaggio.Caption = "ZERO"

Case 1

lblMessaggio.Caption = "UNO"

Case 2

lblMessaggio.Caption = "DUE"

Case 3

lblMessaggio.Caption = "TRE"

Case 4

lblMessaggio.Caption = "QUATTRO"

Case 5

lblMessaggio.Caption = "CINQUE"

Case 6

lblMessaggio.Caption = "SEI"

Case 7

lblMessaggio.Caption = "SETTE"

Case 8

lblMessaggio.Caption = "OTTO"

Case 9

lblMessaggio.Caption = "NOVE"

Case Else

lblMessaggio.Caption = "Il numero non è composto

da una sola cifra"

End Select

Else

lblMessaggio.Caption = "Dato non numerico"

End If

End Sub

La prima operazione effettuata consiste nella lettura del dato iningresso attraverso la textbox. Se esso risulta convertibile in unnumero, ovvero se la funzione IsNumeric restituisce il valore logicoTrue, il dato è copiato nella variabile intera Cifra ed è utilizzato percontrollare la struttura Select Case, che provvede ad effettuare iconfronti necessari per verificare l'uguaglianza con i numeri compresifra 0 e 9 ed a visualizzare la stringa corretta mediante la label.

Secondo esercizio

Il secondo esercizio prevede la creazione di un programma che,ricevendo in ingresso il nome di un mese, sia in grado di indicarne ilnumero dei giorni in un anno specificato. La soluzione comportanuovamente l'uso della struttura Select Case. Per l'acquisizione deidati si provvede, come di consueto, ad utilizzare delle caselle di testo,denominate txtMese e txtAnno. Il risultato è visualizzato in seguitoalla pressione di un pulsante per mezzo della label lblMessaggio. Dopoaver creato un form ed aver posto su di essi gli oggetti grafici, èpossibile implementare la procedura destinata al calcolo. Supponendoche al tasto sia assegnato il nome btnCalcola, si può scrivere:

Private Sub btnCalcola_Click()

Dim Anno As Integer

Dim Giorni As Integer

Dim Mese As String

Anno = Val(txtAnno.Text)

Mese = UCase(txtMese.Text)

Select Case Mese

Page 43: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 4)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb04/index.htm[26/09/2010 1:02:21]

Case "GENNAIO", "MARZO", "MAGGIO", "LUGLIO", "AGOSTO",

"OTTOBRE", "DICEMBRE":

Giorni = 31

Case "APRILE", "GIUGNO", "SETTEMBRE", "NOVEMBRE":

Giorni = 30

Case "FEBBRAIO":

If ((Anno Mod 4) = 0) And ((Anno Mod 100) <> 0) Then

Giorni = 29

Else

Giorni = 28

End If

Case Else

Giorni = 0

End Select

If Giorni > 0 Then

lblMessaggio.Caption = "Numero giorni :" & Giorni

Else

lblMessaggio.Caption = "Mese non corretto"

End If

End Sub

La struttura di selezione è controllata dalla variabile Mese, il cuicontenuto è opportunamente convertito in maiuscolo per mezzo dellafunzione UCase e confrontato con i nomi dei mesi, anch'essi compostisolo da lettere maiuscole. Ciò fa sì che il confronto non sia casesensitive. Si noti, che nel caso in cui il mese selezionato sia febbraio,è eseguito un ulteriore controllo per verificare se l'anno è bisestile.Tale verifica è effettuata testando la contemporanea validità di duecondizioni, ovvero la divisibilità dell'anno per quattro e la nondivisibilità per cento. La condizione risulta vera se entrambi i restidelle divisioni, calcolati per mezzo della funzione Mod, sono nulli. Siricorre pertanto all'operatore logico And, in grado di restituire il valoreTrue solo in caso di contemporanea verifica delle condizioni che necostituiscono gli operandi.

Il ciclo For

Si supponga di voler realizzare un programma in grado di calcolare ilfattoriale di un numero, ovvero il prodotto di tutti i valori interi positiviminori o uguali ad esso. Gli strumenti illustrati nelle puntateprecedenti di questo corso non si rivelano sufficienti a tal fine, inquanto è necessaria la capacità di ripetere per un numero variabile divolte l'operazione di moltiplicazione. Si impone pertanto il ricorso allestrutture di iterazione. Nel caso dell'esempio, occorre applicare lamoltiplicazione a tutti i numeri naturali minori o uguali a quello di cuisi desidera calcolare il fattoriale. Appare così evidente la necessità didisporre di una struttura in grado di permettere la ripetizione di unaporzione di codice per un numero finito di volte; si tratta della classicastruttura For, che nel caso di Visual Basic è caratterizzata dallaseguente sintassi:

For <contatore> = <valore iniziale> To <valore finale>

[Step <passo>]

<istruzione 1>

Page 44: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 4)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb04/index.htm[26/09/2010 1:02:21]

...

<istruzione n>

Next [<contatore>]

Dopo la parola chiave For è necessario far seguire una variabile intera,che funge da contatore. Il suo valore è incrementato ad ogniripetizione di un numero di unità pari a quello specificato dopo laparola chiave Step, fino al raggiungimento del valore finale; questacondizione determina la fine delle iterazioni e il passaggio all'istruzioneseguente la parola riservata Next. Volendo quindi realizzareun'applicazione in grado di calcolare il fattoriale di un numero, occorrecreare un form ed inserire su di esso una textbox, usata per leggere ildato in ingresso, una label, destinata ad accogliere il risultato e unpulsante, a cui è affidato il compito di avviare il calcolo. Alla pressionedi quest'ultimo deve essere associata la seguente procedura:

Private Sub btnCalcola_Click()

Dim Contatore As Integer

Dim Fattoriale As Integer

Dim Numero As Integer

If IsNumeric(txtNumero.Text) Then

Numero = Val(txtNumero.Text)

If Numero >= 0 Then

Fattoriale = 1

For Contatore = 1 To Numero

Fattoriale = Fattoriale * Contatore

Next Contatore

lblRisultato.Caption = Fattoriale

Else

lblRisultato.Caption = "Errore: valore negativo"

End If

Else

lblRisultato.Caption = "Errore: dato non numerico"

End If

End Sub

Essa dapprima verifica che nella textbox txtNumero sia presente undato numerico. In tal caso, quest'ultimo è assegnato alla variabileNumero dopo la necessaria conversione per mezzo della funzione Val.Tale valore è quindi oggetto di un secondo controllo volto a verificarnela positività. La funzione fattoriale, infatti, non è definita per i numerinegativi e vale 1 se il dato in ingresso è nullo. Successivamente, laprocedura provvede ad effettuare le moltiplicazioni. A tal fine fa uso diun ciclo For, avente come valore iniziale 1 e come valore finale ilnumero di cui si desidera calcolare il fattoriale. Si noti che è stataomessa la parola chiave Step. In questo caso, il passo adottato èquello predefinito, cioè 1. All'interno della struttura è presente unasola riga di codice, che ha il fine di moltiplicare il contenuto dellavariabile Fattoriale per il valore assunto dal contatore. La suaripetizione per tutti i valori compresi fra 1 e il numero fornito iningresso fa sì che alla fine del ciclo la variabile Fattoriale contenga ilrisultato desiderato, che può essere visualizzato per mezzo della label.Si noti ciò che avviene se in ingresso è fornito il numero 0. Lavariabile Fattoriale è comunque inizializzata al valore 1. L'istruzioneall'interno del ciclo, invece, non è mai eseguita. Infatti, come si èdetto in precedenza, la ripetizione termina quando il contatore

Page 45: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 4)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb04/index.htm[26/09/2010 1:02:21]

raggiunge il valore finale. In questo caso, la condizione èimmediatamente soddisfatta, per cui non si verificano iterazioni.

Esercizio

Per esercitarsi sull'uso della struttura For, si provi a realizzare unprogramma che, dato in ingresso un numero intero, visualizzi lasomma di tutti i numeri naturali pari minori o uguali ad esso.

Cicli nidificati

Si supponga ora di voler modificare l'applicazione dell'esempioprecedente per fare in modo che fornisca all'utente la somma deifattoriali dei primi n numeri interi positivi, dove n rappresenta il datoin ingresso acquisito mediante la casella di testo txtNumero.

Per il calcolo del fattoriale è necessario ricorrere nuovamente a unciclo, che è sostanzialmente identico a quello visto in precedenza. Taleoperazione deve essere però ripetuta per tutti i numeri naturali minorio uguali al dato n fornito dall'utente, ovvero per tutti i valori intericompresi fra 1 e n.

Si impone pertanto l'uso di un ulteriore ciclo, che deve risultare piùesterno rispetto al precedente. Al pulsante btnCalcola si può quindiassociare la seguente procedura:

Private Sub btnCalcola_Click()

Dim Contatore As Integer

Dim Fattoriale As Integer

Dim n As Integer

Dim Risultato As Long

If IsNumeric(txtNumero.Text) Then

n = Val(txtNumero.Text)

If n > 0 Then

Risultato = 0

For Contatore1 = 1 To n

Fattoriale = 1

For Contatore2 = 1 To Contatore1

Fattoriale = Fattoriale * Contatore2

Next Contatore2

Risultato = Risultato + Fattoriale

Next Contatore1

lblRisultato.Caption = Risultato

Else

lblRisultato.Caption = "Errore: valore negativo o

nullo"

End If

Else

lblRisultato.Caption = "Errore: dato non numerico"

End If

End Sub

Anche questa volta è per prima cosa eseguito un controllo dellavalidità del dato digitato dall'utente. Se si tratta di un numero intero

Page 46: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 4)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb04/index.htm[26/09/2010 1:02:21]

positivo, la procedura provvede ad avviare il calcolo, dopo aver postoa zero il valore della variabile Risultato. Si noti che tale operazionenon è in realtà necessaria, in quanto Visual Basic provvedeautomaticamente ad azzerare le variabili intere in fase di creazione.La sua presenza, però, contribuisce a rendere leggibile il codice,soprattutto a coloro che sono abituati all'uso di altri linguaggi che nonpresentano questa caratteristica. Si osservino ora i due cicli nidificati.La variabile usata come contatore in quello più esterno funge davalore finale nel ciclo interno. Ad ogni iterazione è pertanto calcolato ilfattoriale del numero contenuto nella variabile Contatore1. Tale valoreva ad incrementare quello della variabile Risultato, che alla fine èvisualizzato mediante la label. Allo scopo di mantenere una buonaleggibilità del codice, è necessario fare in modo che alle istruzioni chesi trovano all'interno di un ciclo sia associato un rientro sinistromaggiore. In tal modo risulta semplice riconoscere l'inizio e la finedella struttura. Tale necessità è ancora più evidente allorquando visiano più cicli nidificati. Per lo stesso motivo, sebbene sia possibilefarne a meno, è preferibile far seguire ogni parola chiave Next dalnome della variabile di conteggio che caratterizza il ciclo. In caso diomissione, l'interprete comunque assume che la struttura dadelimitare sia quella posta nel blocco più interno.

Le funzioni Len e Mid$

Si supponga di voler scrivere un programma che sia in grado diinvertire una stringa fornita in ingresso. Per la sua realizzazioneoccorre far uso di due funzioni specifiche per il trattamento dei datialfanumerici. Si tratta della funzione Len, che restituisce la lunghezzadella stringa passatale come parametro e della più complessa funzioneMid$. Quest'ultima permette di estrarre da una stringa una sequenzacomposta da un dato numero di caratteri consecutivi. La sua sintassi èla seguente:

<risultato> = Mid$(<stringa>, <posizione>, [<numero

caratteri>])

I parametri rappresentano rispettivamente la stringa fornita iningresso, la posizione del primo carattere da estrarre e il numero deicaratteri oggetto dell'operazione. Si noti che quest'ultimo è facoltativo.In sua assenza, è restituita tutta la porzione della stringa compresafra la posizione indicata e il carattere posto all'estrema destra. Adesempio, la riga

A$ = Mid$("Developing Software Solutions", 12, 8)

Assegna alla variabile A$ la stringa "Software". Scrivendo invece

A$ = Mid$("Developing Software Solutions", 12)

si provoca l'assegnamento della sequenza alfanumerica "SoftwareSolutions".

Cicli con decremento

Ora si dispone dei mezzi necessari per la realizzazionedell'applicazione in grado di invertire una stringa. Supponendo di

Page 47: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 4)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb04/index.htm[26/09/2010 1:02:21]

utilizzare un form analogo a quello degli esempi precedenti,caratterizzato da una textbox destinata all'acquisizione dei dati iningresso, denominata txtStringa, dalla label lblRisultato, utilizzata pervisualizzare la stringa risultante e dal pulsante btnInverti, che ha loscopo di provocare l'inversione della sequenza, la procedura daassociare ad esso è la seguente:

Private Sub btnInverti_Click()

Dim i As Integer

Dim Lunghezza As Integer

Dim Risultato As String

Dim Carattere As String * 1

Lunghezza = Len(txtStringa.Text)

Risultato = ""

For i = Lunghezza To 1 Step -1

Carattere = Mid$(txtStringa.Text, i, 1)

Risultato = Risultato + Carattere

Next i

lblRisultato.Caption = Risultato

End Sub

Si fa uso della funzione Len per calcolare la lunghezza della stringadigitata dall'utente. Il valore restituito determina la posizione delprimo carattere che deve essere aggiunto alla variabile Risultato. Essorappresenta pertanto il valore di partenza in un ciclo For caratterizzatoda un decremento, ovvero da un passo di segno negativo. Questavolta, quindi, il valore iniziale risulta maggiore di quello finale e leiterazioni terminano quando è raggiunto il valore minimo, nellafattispecie 1. La funzione Mid$ è utilizzata per estrarre il carattereposto nella posizione indicata dal contatore. Si noti che la variabileatta a contenerlo è di tipo stringa ed è stata dichiarata di dimensionepari a un elemento per mezzo della riga

Dim Carattere As String*1

Visual Basic, infatti, a differenza di molti altri linguaggi diprogrammazione, non dispone di un tipo di dati idoneo allamemorizzazione dei singoli caratteri. Per ovviare a questoinconveniente, è necessario ricorrere ad una stringa di dimensione pariad un'unità, come in questo esempio. Per mezzo dell'operatore diconcatenazione (+), ogni carattere estratto è aggiunto in coda alcontenuto della variabile Risultato, che al termine delle iterazionicontiene la stringa invertita. Quest'ultima può essere quindi assegnataalla proprietà Caption della label lblRisultato per essere visualizzata.

Esercizio

Per esercitarsi sui concetti esposti, si provi a realizzare un programmache, ricevuto in ingresso un numero intero positivo, sia in grado direstituire il maggior numero naturale per cui esso è divisibile.

Conclusioni

Il ciclo For è estremamente usato in ogni applicazione. Esso nonrappresenta però l'unica struttura di iterazione. Ne esistono delle

Page 48: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 4)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb04/index.htm[26/09/2010 1:02:21]

altre, che saranno oggetto di studio nella prossima lezione. Percomprendere il loro funzionamento è necessario aver assimilatoquanto esposto in questa trattazione. Al lettore è pertanto rivolto ilconsueto invito ad esercitarsi nell'applicazione dei concetti illustrati.

(c) 1998 Edizioni Infomedia srl

Page 49: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 4)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb04/index.htm[26/09/2010 1:02:21]

Page 50: Corso Visual Basic

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb04/fig1.htm[26/09/2010 1:03:01]

Figura 1

Page 51: Corso Visual Basic

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb04/fig2.htm[26/09/2010 1:03:08]

Figura 2

Page 52: Corso Visual Basic

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb04/fig3.htm[26/09/2010 1:03:17]

Figura 3

Page 53: Corso Visual Basic

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb04/fig4.htm[26/09/2010 1:03:26]

Figura 4

Page 54: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte V)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb05/index.htm[26/09/2010 1:04:47]

Corso di Visual Basic(Parte V)

Le soluzioni degli esercizi dello scorsonumero

Come ormai consuetudine, la primaparte della lezione è dedicata allacorrezione degli esercizi proposti nelloscorso numero.

Primo esercizio

Il comando Exit For

Il ciclo While

Le parole chiave Do e Loop

Il ciclo Do Until

Ripetizione di un blocco di istruzioni peralmeno una volta

Conclusioni

Figure

Figura 1

Figura 2

Figura 3

(c) 1997, Edizioni Infomedia srl

Corso di Visual Basic

(Parte V)

di Maurizio Crespi

Oggetto di studio della quinta parte del corso dedicato allaprogrammazione in Visual Basic sono ancora i cicli. Questa volta

l'obbiettivo è puntato sull'uso delle strutture regolate da unacondizione booleana

La necessità di poter eseguire ripetitivamente un gruppo di istruzioniè sentita durante la stesura di pressoché qualsiasi applicazione nonbanale. Per questo motivo, tutti gli strumenti di sviluppo prevedono ilsupporto per le strutture di iterazione. Dopo aver soffermatol'attenzione sulla struttura For, si procederà ora a studiare l'uso deicicli basati sulla parola chiave Do, che permettono di legare il numerodelle ripetizioni non più al valore assunto da un contatore, bensì alverificarsi di una condizione logica.

Le soluzioni degli esercizi dello scorso numero

Come ormai consuetudine, la prima parte della lezione è dedicata allacorrezione degli esercizi proposti nello scorso numero.

Primo esercizio

Il primo esercizio prevede la realizzazione di un programma che, datoin ingresso un numero intero, visualizzi la somma di tutti i numerinaturali pari minori o uguali ad esso. Dopo aver disegnato un formdotato di una casella di testo, a cui può essere assegnato il nometxtNumero, di una label (lblRisultato) e di un pulsante (btnCalcola), èpossibile scrivere la procedura da associare alla pressione diquest'ultimo:

Private Sub btnCalcola_Click()

Dim Numero As Integer

Dim Contatore As Integer

Dim Somma As Long

Numero = Val(txtNumero.text)

If Numero > 0 Then

Somma = 0

For Contatore = 2 To Numero Step 2

Somma = Somma + Contatore

Next Contatore

Page 55: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte V)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb05/index.htm[26/09/2010 1:04:47]

lblRisultato.Caption = Somma

Else

lblRisultato.Caption = "Numero negativo o nullo"

End If

End Sub

Il suo scopo è di trasformare in un dato numerico la stringa postanella casella di testo e, se tale valore risulta positivo, di creare unciclo per calcolare tutti i numeri interi pari minori ad esso. A tal fine fauso di una struttura For avente come valore iniziale 2, ovvero il piùpiccolo numero pari, e come passo ancora 2. In tal modo, sono esclusidal conteggio i valori dispari, cioè non multipli di 2. Il limite massimoè rappresentato dal numero fornito dall'utente. Si noti che, nel caso incui quest'ultimo sia dispari, la struttura fa sì che il contatore assumain realtà un valore massimo inferiore di un'unità rispetto a quelloindicato. Tutti i valori assunti dal contatore sono aggiunti alla variabileSomma, che al termine delle iterazioni contiene il risultato desiderato.

Secondo esercizio

Il secondo esercizio richiede la creazione di un programma che, datoin ingresso un numero intero positivo, restituisca il più grande numeronaturale per cui esso è divisibile. Supponendo di riutilizzare il formdescritto in precedenza, è possibile associare al pulsante la seguenteprocedura:

Private Sub btnCalcola_click()

Dim Contatore As Integer

Dim Divisore As Integer

Dim Numero As Double

Numero = Val(txtNumero.Text)

If Numero > 0 Then

If Numero = Int(Numero) Then

Divisore = 1

For Contatore = 2 To (Numero - 1)

If (Numero Mod Contatore) = 0 Then

Divisore = Contatore

End If

Next Contatore

lblRisultato.Caption = Divisore

Else

lblRisultato.Caption = "Numero non intero"

End If

Page 56: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte V)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb05/index.htm[26/09/2010 1:04:47]

Else

lblRisultato.Caption = "Numero negativo o nullo"

End If

End Sub

Si fa ancora uso di un ciclo For in cui il contatore è inizializzato a 2 (èsuperfluo verificare la divisibilità per 1). Il valore finale è pari alnumero diminuito di un'unità. Al il programma accede solo se il datofornito dall'utente, memorizzato nella variabile Numero, risulta interopositivo. Ad ogni iterazione, si fa uso dell'operatore Mod per verificarese il numero fornito in ingresso è divisibile per il valore della variabileContatore. In caso affermativo, quest'ultimo è memorizzato nellavariabile Divisore che, completato il ciclo, contiene il risultatodesiderato.

Il comando Exit For

Si noti che, con la procedura sopra descritta, il numero delle ripetizioniaumenta all'aumentare del valore fornito in ingresso dall'utente.L'applicazione di tale algoritmo a un numero molto grande potrebbepertanto causare, almeno in linea di principio, dei problemi diprestazioni. E' possibile scrivere una procedura più efficienterealizzando un ciclo con decremento. In questo caso, la struttura Forha come valore iniziale il dato fornito in ingresso diminuito di un'unità.

Private Sub btnCalcola_click()

Dim Contatore As Integer

Dim Divisore As Integer

Dim Numero As Double

Numero = Val(txtNumero.Text)

If Numero > 0 Then

If Numero = Int(Numero) Then

Divisore = Numero

For Contatore = (Numero - 1) To 1 Step -1

If (Numero Mod Contatore) = 0 Then

Divisore = Contatore

Exit For

End If

Next Contatore

lblRisultato.Caption = Divisore

Else

lblRisultato.Caption = "Numero non intero"

Page 57: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte V)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb05/index.htm[26/09/2010 1:04:47]

End If

Else

lblRisultato.Caption = "Numero negativo o nullo"

End If

End Sub

Ad ogni iterazione è effettuato un controllo atto a stabilire se ilcontenuto della variabile Contatore è in grado di dividere il numerofornito dall'utente. Il primo valore di cui è rilevata la capacità disoddisfare questa condizione è sicuramente il maggior divisore. Unavolta trovatolo, è pertanto inutile proseguire con le iterazioni. Perprovocare l'uscita prematura dal ciclo, si fa uso del comando Exit For.In questo caso, il numero delle ripetizioni è quello strettamentenecessario. Il vantaggio in termini di efficienza può essere notevole. E'tuttavia importante non abusare dell'uso di questo comando, inquanto ha influenza negativa sulla leggibilità del codice.

Il ciclo While

Una soluzione più elegante prevede l'uso del ciclo While, che permettela ripetizione di un segmento di codice per tutto il tempo in cui unacondizione risulta vera. La sua sintassi è la seguente:

While <condizione>

<istruzione 1>

<istruzione 2>

...

<istruzione n>

Wend

Le istruzioni comprese fra le parole chiave While e Wend sono ripetuteper un numero di volte non stabilito rigidamente a priori, bensìdipendente dalle stesse istruzioni, che devono essere in grado di farein modo che la condizione ad un certo punto smetta di verificarsi. Incaso contrario, si incappa in un errore molto diffuso fra iprogrammatori alle prime armi, ovvero si crea ciò che è usualmentedetto ciclo infinito. Gli effetti di un'iterazione senza fine sono evidenti.Il programma di fatto si blocca e per terminarlo occorre far ricorso altask manager del sistema operativo.

La procedura che costituisce la soluzione del secondo esercizio puòessere riscritta utilizzando la struttura While nel modo seguente:

Private Sub btnCalcola_click()

Dim Contatore As Integer

Dim Divisore As Integer

Dim Numero As Double

Numero = Val(txtNumero.Text)

Page 58: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte V)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb05/index.htm[26/09/2010 1:04:47]

If Numero > 0 Then

If Numero = Int(Numero) Then

Contatore = Numero - 1

While (Numero Mod Contatore) <> 0

Contatore = Contatore - 1

Wend

lblRisultato.Caption = Contatore

Else

lblRisultato.Caption = "Numero non intero"

End If

Else

lblRisultato.Caption = "Numero negativo o nullo"

End If

End Sub

Il suo funzionamento è estremamente semplice: un contatore èinizializzato al massimo numero intero inferiore al dato fornito iningresso ed è decrementato all'interno del ciclo più volte per tutto iltempo che il resto della divisione per il contatore del numero digitatodall'utente si mantiene diverso da zero. Quando il resto si annulla,ovvero quando la variabile Contatore contiene il divisore desiderato, lacondizione

(Numero Mod Contatore)<>0

diventa falsa e le iterazioni terminano. Il risultato può quindi esserevisualizzato per mezzo dell'apposita label. Si noti che il ciclo non puòmai essere infinito. La condizione infatti assume sicuramente unvalore falso quando la variabile Contatore vale 1.

Le parole chiave Do e Loop

Il ciclo While può anche essere descritto in modo più elegante permezzo delle parole chiave Do e Loop. In questo caso la sintassidiventa:

Do While <condizione>

<istruzione 1>

<istruzione 2>

...

<istruzione n>

Loop

Il comportamento è analogo a quello visto in precedenza: le istruzioni

Page 59: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte V)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb05/index.htm[26/09/2010 1:04:47]

contenute all'interno della struttura sono ripetute fintanto che lacondizione indicata accanto alla parola While si verifica. La proceduradell'esempio precedente può quindi essere riscritta come segue:

Private Sub btnCalcola_click()

Dim Contatore As Integer

Dim Divisore As Integer

Dim Numero As Double

Numero = Val(txtNumero.Text)

If Numero > 0 Then

If Numero = Int(Numero) Then

Contatore = Numero - 1

Do While (Numero Mod Contatore) <> 0

Contatore = Contatore - 1

Loop

lblRisultato.Caption = Contatore

Else

lblRisultato.Caption = "Numero non intero"

End If

Else

lblRisultato.Caption = "Numero negativo o nullo"

End If

End Sub

Il ciclo Do Until

Pressoché analogo è il ciclo Do Until, caratterizzato dalla seguentesintassi:

Do Until <condizione>

<istruzione 1>

<istruzione 2>

...

<istruzione n>

Loop

In questo caso, le iterazioni avvengono quando la condizione è falsa eterminano quando essa si avvera. Il ciclo su cui si basa la soluzionedel secondo esercizio può essere riscritto utilizzando la struttura DoUntil nel modo seguente:

Page 60: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte V)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb05/index.htm[26/09/2010 1:04:47]

Do Until (Numero Mod Contatore) = 0

Contatore = Contatore - 1

Loop

Si noti che l'uso di questa struttura in alternativa alla precedente nonpresenta dei vantaggi significativi. La scelta può pertanto essereeffettuata caso per caso in base alla comprensibilità del codice e alleproprie preferenze personali.

Si consideri ora il seguente esempio. Si desidera realizzare unprogramma che, ricevendo in ingresso due stringhe, sia in grado diindicare la posizione in cui la seconda è eventualmente contenutanella prima. In pratica, si tratta di realizzare una procedura in gradodi simulare il comportamento della funzione Instr.

Per prima cosa si provvede a disegnare un form dotato di due caselledi testo, a cui è possibile dare i nomi txtStringa e txtDaCercare, e diun pulsante, a cui è dato il nome btnCerca. Ad esso è possibileassociare la procedura che effettua la ricerca di una stringa nell'altra.Il codice è il seguente:

Private Sub btnCerca_click()

Dim Stringa As String

Dim DaCercare As String

Dim LunghStringa As Integer

Dim LunghDaCercare As Integer

Dim Posizione As Integer

Dim Trovato As Boolean

Stringa = txtStringa.Text

DaCercare = txtDaCercare.Text

LunghStringa = Len(Stringa)

LunghDaCercare = Len(DaCercare)

Posizione = 0

Trovato = False

Do Until Trovato Or (Posizione + LunghDaCercare) >LunghStringa

Posizione = Posizione + 1

Trovato = (Mid$(Stringa, Posizione, LunghDaCercare) =DaCercare)

Loop

If Trovato Then

lblMessaggio.Caption = "Posizione = " & Str$(Posizione)

Page 61: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte V)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb05/index.htm[26/09/2010 1:04:47]

Else

lblMessaggio.Caption = "Stringa non trovata"

End If

End Sub

La procedura dapprima calcola la lunghezza della stringa da cercare,poi estrae tutte le possibili sequenze di tale dimensione dal testoposto nella casella txtStringa. Il processo termina quando è estrattauna sequenza uguale a quella oggetto di ricerca; in questo caso lavariabile Trovato, contenente il risultato del confronto, assume ilvalore logico True. La condizione

Trovato Or (Posizione + LunghDaCercare) > LunghStringa

pertanto si verifica e il ciclo si conclude. La variabile Posizione, usatacome contatore, contiene allora la posizione in cui la sequenza è statalocalizzata. L'informazione in essa contenuta rappresenta il dato che ilprogramma deve visualizzare per mezzo della label.

Come si può facilmente notare, le iterazioni possono terminare anchequando il numero dei caratteri presenti nella stringa a partire dallaposizione indicata dal contatore risulta inferiore alla lunghezza dellasequenza da cercare. In questo caso, il ciclo termina senza che siastata trovata alcuna occorrenza; tale eventualità provoca lavisualizzazione di un opportuno messaggio di avviso per mezzo dellalabel. Si noti che se la stringa da cercare ha lunghezza inferiore aquella entro cui deve essere effettuata la ricerca, le istruzioni posteall'interno del ciclo non sono mai eseguite.

Esercizio

Si provi a realizzare un'applicazione che, ricevuta in ingresso unastringa alfabetica, indichi la posizione in essa occupata dalla primalettera maiuscola, se presente.

Ripetizione di un blocco di istruzioni per almeno una volta

Spesso si rivela utile poter fare in modo che, indipendentemente dalverificarsi della condizione che regola il ciclo, il blocco di istruzioni inesso contenuto sia eseguito almeno una volta. Ad esempio, sisupponga di voler realizzare un'applicazione in grado di estrarre asorte dei numeri compresi fra 1 e 10 mentre la loro somma simantiene inferiore a 15. A tal fine si utilizza la funzione Rnd, cherestituisce un numero pseudocasuale (ovvero generato in modo dasembrare estratto a sorte) compreso fra 0 e 1. E' evidente che almenouna volta deve essere effettuata l'estrazione di un numero. Per fare inmodo che ciò avvenga, è possibile posizionare la condizione che regolail ciclo alla fine di esso anziché all'inizio. In questo caso la sintassidiventa:

Do

<istruzione 1>

<istruzione 2>

Page 62: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte V)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb05/index.htm[26/09/2010 1:04:47]

...

<istruzione n>

Loop Until <condizione>

Per consentire all'estrazione di avere inizio in seguito alla pressionedel pulsante btnEstrai e per far sì che i numeri generati sianovisualizzati in una textbox, denominata txtNumeri, è necessarioscrivere la seguente procedura:

Private Sub btnEstrai_Click()

Dim Somma As Integer

Dim Numero As Integer

Randomize

Somma = 0

txtNumeri.Text = ""

Do

Numero = Int(10 * Rnd) + 1

Somma = Somma + Numero

txtNumeri.Text = txtNumeri.Text + Str$(Numero) + "-"

Loop Until Somma > 15

End Sub

Il ciclo provvede a calcolare un numero casuale compreso fra 1 e 10per mezzo della funzione Rnd, moltiplicando il valore da essa restituitoper 10, estraendone la parte intera e sommando il valore 1. Siccome,come già accennato in precedenza, la funzione restituisce un numerodecimale maggiore o uguale a 0 e minore di 1, la parte intera delprodotto risulta compresa fra 0 e 9. Per fare in modo che alla variabileNumero sia assegnato un valore compreso fra 1 e 10 occorre pertantoaggiungere un'unità. Il valore ottenuto è aggiunto alla variabileSomma. I numeri sono visualizzati, separati da un trattino, nellatextbox txtNumeri. Le iterazioni terminano quando il valore dellavariabile Somma diventa maggiore di 15.

Si noti l'uso dell'istruzione Randomize all'inizio della procedura. Essoha lo scopo di inizializzare il generatore di numeri pseudocasuali. Inassenza di tale operazione, i valori generati sarebbero sempre glistessi ogni volta che è lanciato il programma.

Anche quando la condizione è posta alla fine del ciclo è possibilesostituire la parola chiave Until con While. In questo caso, le iterazioniavvengono fintanto che si verifica la condizione indicata.

Esercizio

Per valutare la propria comprensione degli argomenti trattati, sirealizzi un'applicazione che, ricevendo in ingresso una stringa per

Page 63: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte V)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb05/index.htm[26/09/2010 1:04:47]

mezzo di una textbox, restituisca la lunghezza della prima parola inessa contenuta.

Conclusioni

I calcolatori sono nati allo scopo di agevolare l'utente nellosvolgimento delle operazioni ripetitive. Per questo motivo, le struttureche permettono di eseguire delle iterazioni rivestono una notevoleimportanza, tale da rendere la loro conoscenza imprescindibile perqualsiasi programmatore. Ancora una volta, pertanto, è rivolto allettore l'invito ad esercitarsi per acquisire la necessaria dimestichezzacon i concetti esposti.

(c) 1998 Edizioni Infomedia srl

Page 64: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte V)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb05/index.htm[26/09/2010 1:04:47]

Page 65: Corso Visual Basic

La soluzione del primo esercizio

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb05/fig1.htm[26/09/2010 1:05:00]

Figura 1La soluzione del primo esercizio

Page 66: Corso Visual Basic

L'applicazione che ricerca una stringa in un'altra

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb05/fig2.htm[26/09/2010 1:05:07]

Figura 2L'applicazione che ricerca una stringa in un'altra

Page 67: Corso Visual Basic

L'applicazione che genera numeri pseudocasuali

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb05/fig3.htm[26/09/2010 1:05:13]

Figura 3L'applicazione che genera numeri pseudocasuali

Page 68: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 6)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb06/index.htm[26/09/2010 1:06:00]

Corso di Visual Basic(Parte 6)

Le soluzioni degli esercizi della lezioneprecedente

Perché servono i vettori

I vettori

L'ordinamento per selezione diretta

Due esercizi

Rinfreschiamoci la memoria...

Figure

Figura 1

Figura 2

Figura 3

(c) 1997, Edizioni Infomedia srl

Corso di Visual Basic (Parte 6)di Maurizio Crespi

Nella sesta parte, il corso dedicato alla programmazione in ambiente Microsoft VisualBasic punta il proprio obbiettivo su delle strutture dati di importanza fondamentale: ivettori.

La fortuna dei calcolatori si deve alla capacità di effettuare in breve tempo delleoperazioni ripetitive su una grande quantità di informazioni. Fino ad ora, in questo corso,i dati da elaborare sono sempre stati considerati contenuti all'interno di comuni variabili.Quando tuttavia il numero dei valori da gestire diventa elevato, esse si rivelanoinadeguate a soddisfare le esigenze del programmatore. Lo scopo della lezione consistenell'introdurre il concetto di vettore e di dimostrare quanto una struttura di questo tipopossa agevolare il compito dello sviluppatore in presenza di un'elevata mole di dati ditipo omogeneo. Prima di illustrare i nuovi concetti, è opportuno verificare lacomprensione degli argomenti esposti nella precedente lezione. Lo spunto è come semprerappresentato dalla discussione delle soluzioni degli esercizi in essa proposti.

Le soluzioni degli esercizi della lezione precedente

Nella scorsa lezione sono state descritte le strutture di iterazione basate sull'uso dellaparola chiave Do. Gli esercizi in essa proposti hanno perciò lo scopo di invitare il lettorea farne uso.

Primo esercizio

Il primo esercizio richiede la realizzazione di un programma che, ricevuta in ingresso unastringa alfabetica, indichi la posizione in essa occupata dalla prima lettera maiuscola, sepresente. È evidente la necessità di implementare un ciclo che effettui una scansionedella stringa, la cui lunghezza può variare indefinitamente e può anche essere nulla. Perquesto motivo, occorre utilizzare una struttura che sia in grado di evitare le iterazioniqualora non siano necessarie. La scelta ricade sul ciclo Do While. Dopo aver realizzatoun form dotato di una casella di testo, utilizzata per l'inserimento della stringa e di unalabel, mediante la quale è visualizzato il risultato dell'elaborazione, è possibileaggiungere un pulsante, avente lo scopo di avviare la ricerca. Esso deve pertanto esserein grado di rispondere all'evento Click con la seguente procedura:

Private Sub btnCalcola_Click()

Dim Stringa As String

Dim Carattere As String * 1

Dim i As Integer

Dim Lunghezza As Integer

Dim Fine As Boolean

Stringa = txtStringa.Text

Lunghezza = Len(Stringa)

Page 69: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 6)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb06/index.htm[26/09/2010 1:06:00]

i = 1

Fine = False

Do While Not (Fine) And (i <= Lunghezza)

Carattere = Mid$(Stringa, i, 1)

Select Case Carattere

Case "A" To "Z":

Fine = True

Case Else:

i = i + 1

End Select

Loop

If Fine Then

lblRisultato.Caption = "Posizione: " & i

Else

lblRisultato.Caption = "Nessuna lettera maiuscola"

End If

End Sub

Il contenuto della casella di testo costituisce la stringa nella quale deve essere effettuatala ricerca. Per mezzo della funzione Mid$ è estratto un carattere per volta. La suaposizione è definita dalla variabile i. Se il carattere risulta maiuscolo, la variabilebooleana Fine è posta al valore logico True e la ricerca termina. In caso contrario, èincrementato il contatore di un'unità ed è eseguita una nuova iterazione per verificare ilcarattere seguente. Si noti che se il contatore assume un valore superiore al numero deicaratteri di cui è composta la stringa, condizione immediatamente verificata se lalunghezza è nulla, il ciclo termina. Si noti altresì l'uso della struttura Select Case perverificare se il carattere estratto risulta maiuscolo. Permettendo di definire degliintervalli, infatti, essa rende estremamente agevole l'operazione di controllo, rendendoinoltre il codice molto semplice da comprendere.

Secondo esercizio

Anche il secondo esercizio richiede la scansione di una stringa fornita dall'utente. La suasoluzione consiste infatti nella realizzazione di un programma in grado di ricevere iningresso una stringa per mezzo di una textbox e di restituire la lunghezza della primaparola in essa contenuta. È possibile far uso di un form analogo a quello dell'esercizioprecedente. Anche in questo caso, l'elaborazione è avviata dalla pressione del pulsante. Ilcodice che la descrive è quindi ancora contenuto nella procedura btnCalcola_Click:

Private Sub btnCalcola_Click()

Dim Stringa As String

Dim Carattere As String * 1

Page 70: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 6)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb06/index.htm[26/09/2010 1:06:00]

Dim i As Integer

Dim Lunghezza As Integer

Dim PosInizio As Integer

Dim Fine As Boolean

Stringa = txtStringa.Text

Lunghezza = Len(Stringa)

If Lunghezza > 0 Then

i = 1

Fine = False

Rem Ricerca della posizione

Rem del primo carattere alfabetico

Do

Carattere = Mid$(Stringa, i, 1)

Select Case Carattere

Case "A" To "Z", "a" To "z":

Fine = True

Case Else:

i = i + 1

End Select

Loop Until Fine Or (i > Lunghezza)

If Fine Then

Fine = False

PosInizio = i

Rem Ricerca di uno spazio o di

Rem un carattere di punteggiatura

Rem che delimiti la parola

Do While Not (Fine) And (i <= Lunghezza)

Carattere = Mid$(Stringa, i, 1)

Select Case Carattere

Case " ", ",", ";", ".":

Page 71: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 6)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb06/index.htm[26/09/2010 1:06:00]

Fine = True

Case Else:

i = i + 1

End Select

Loop

lblRisultato.Caption = "Lunghezza prima parola:" &

(i - PosInizio)

Else

lblRisultato.Caption = "La stringa non contiene parole"

End If

Else

lblRisultato.Caption = "Nessuna lettera maiuscola"

End If

End Sub

Dopo l'avvio, la procedura provvede a copiare il contenuto della textbox nella variabiledenominata Stringa, di cui è calcolata la lunghezza per mezzo della funzione Len.Mediante un ciclo, è effettuata la ricerca del primo carattere alfabetico contenuto nellastringa. Se l'esito è positivo, ovvero se essa contiene almeno una parola, è utilizzato unulteriore ciclo per ricercare il carattere che ne determina la fine. La differenza fra laposizione di quest'ultimo e quella del primo carattere costituisce la lunghezza dellaparola. Il valore è visualizzato per mezzo dell'etichetta testuale lblRisultato.

Perché servono i vettori

Si supponga di voler realizzare una semplice applicazione in grado di ordinare in modocrescente tre valori numerici. Non si tratta di un compito gravoso. È infatti sufficientedisegnare un form e porre su di esso tre textbox, necessarie per l'acquisizione dei valori,nonché una label destinata ad ospitare l'elenco ordinato. Per avviare l'elaborazione, èpossibile ancora una volta utilizzare una procedura associata all'evento Click generatodalla pressione di un pulsante. Il codice è il seguente:

Private Sub btnOrdina_Click()

Dim Valore1 As Double

Dim Valore2 As Double

Dim Valore3 As Double

Dim temp As Double

Valore1 = Val(txtValore1.Text)

Page 72: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 6)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb06/index.htm[26/09/2010 1:06:00]

Valore2 = Val(txtValore2.Text)

Valore3 = Val(txtValore3.Text)

If Valore2 < Valore1 Then

temp = Valore2

Valore2 = Valore1

Valore1 = temp

End If

If Valore3 < Valore1 Then

temp = Valore3

Valore3 = Valore1

Valore1 = temp

End If

If Valore3 < Valore2 Then

temp = Valore3

Valore3 = Valore2

Valore2 = temp

End If

lblRisultato.Caption = Valore1 & " - " & Valore2 & " - "

& Valore3

End Sub

I dati forniti dall'utente, dopo essere stati convertiti in valori numerici, sono postiall'interno delle variabili Valore1, Valore2, Valore3. È successivamente effettuato unconfronto fra i dati contenuti nelle variabili Valore1 e Valore2. Se il numero contenutonella seconda è maggiore di quello memorizzato nella prima, i due valori sono scambiati.In modo analogo, è effettuato il confronto fra i numeri contenuti nelle variabili Valore2 eValore3 ed è effettuato un ulteriore scambio qualora esso si riveli necessario per fare inmodo che la variabile Valore3 contenga un dato maggiore di quello posto in Valore2. Unulteriore verifica è eseguita per fare in modo che il dato contenuto in Valore3 siamaggiore di quello memorizzato in Valore1. In seguito all'esecuzione delle tre struttureIf, si ottiene che:

il dato contenuto nella variabile Valore2 risulta maggiore o uguale a quello posto inValore1

il dato posto nella variabile Valore3 risulta maggiore o uguale a quelli posti in Valore2 eValore1

La sequenza Valore1, Valore2, Valore3, risulta pertanto ordinata in modo crescente. Ivalori possono allora essere visualizzati utilizzando il carattere "-" come separatore.Sarebbe sicuramente molto meno agevole la realizzazione di un'applicazione analoga in

Page 73: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 6)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb06/index.htm[26/09/2010 1:06:00]

grado di gestire 100 numeri. Ancor più ardua si rivelerebbe la creazione di un programmain grado di operare su 1000 o 10000 valori. È evidente che le comuni variabili nonpermettono di sviluppare in modo ragionevolmente semplice dei programmi in grado digestire un numero elevato di informazioni dello stesso tipo. Per queste realizzazioni, ènecessario far ricorso ai vettori.

I vettori

Fino ad ora, le variabili sono stare considerate come delle strutture in grado di associarea un nome simbolico un solo valore, secondo una relazione uno a uno. Saranno descritteora delle speciali variabili, in grado di associare ad un unico nome uno o più valori,secondo una relazione uno a molti. Esse prendono il nome di vettori, o Array. Un array sipresenta quindi come una variabile in grado di ospitare diversi valori in opportuni spazinumerati.

L'accesso ad un elemento contenuto in un vettore non può pertanto essere effettuatoindicando il solo nome della struttura, bensì richiede che sia specificato anche il numerocorrispondente alla posizione, che prende il nome di indice. Per meglio comprendere ilconcetto di vettore, si provi ad immaginare una variabile come una sorta di cassetto incui è possibile riporre un'informazione.

Si supponga di applicare su questo cassetto un'etichetta su cui è riportata la scritta"Valori". Nel linguaggio naturale, per indicare a una persona di prendere il contenuto delcassetto caratterizzato dall'etichetta "Valori" e di porlo in un altro denominato "Risultato"si usa la frase: "Prendi il contenuto del cassetto Valori e ponilo nel cassetto Risultato". InVisual Basic, ricordando che tali cassetti sono in realtà delle variabili, è possibilescrivere:

Risultato = Valori

Si supponga ora di disporre di un'intera cassettiera, in cui ogni singolo cassetto ènumerato in modo univoco e di spostare su di essa l'etichetta. In questo caso, peraccedere a un oggetto, occorre specificare il nome della cassettiera e il numero cheidentifica il cassetto che lo contiene. Ad esempio, è possibile dire "Prendi il contenutodel cassetto numero 3 della cassettiera Valori e ponilo nel cassetto di nome Risultato".Ciò in Visual Basic è tradotto con la riga:

Risultato = Valori(3)

Si noti che l'indice dell'elemento è posto fra parentesi tonde. Grazie ai vettori, è orapossibile realizzare in modo molto semplice un'applicazione in grado di richiedere 100numeri e di visualizzare in un'etichetta di testo l'elenco dei valori ordinato in modocrescente. Il codice può essere associato all'evento Load del form di avvio, affinché siaeseguito durante la fase di creazione.

Private Sub Form_Load()

Dim Stringa As String

Dim Valori(100) As Double

Dim Temp As Double

Dim i As Integer

Dim j As Integer

Page 74: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 6)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb06/index.htm[26/09/2010 1:06:00]

Rem Acquisizione dei dati

For i = 1 To 100

Stringa = InputBox("Inserire il numero")

Valori(i) = Val(Stringa)

Next i

Rem Ordinamento con algoritmo di selezione diretta.

For i = 1 To 99

For j = i + 1 To 100

If Valori(i) > Valori(j) Then

Temp = Valori(i)

Valori(i) = Valori(j)

Valori(j) = Temp

End If

Next j, i

Rem Inserimento dei risultati nella textbox

lblRisultato.Caption = ""

For i = 1 To 100

lblRisultato.Caption = lblRisultato.Caption &

Valori(i) & Chr$(10)

Next i

End Sub

Si noti che la dichiarazione del vettore Valori è eseguita per mezzo dell'istruzione Dim,in modo pressoché analogo a quanto previsto per una qualsiasi variabile. L'unicadifferenza è costituita dalla presenza delle parentesi contenenti un numero cherappresenta la dimensione, ovvero il massimo indice utilizzabile. Il valore minimo perl'indice è sempre 0, tranne quando si provvede ad indicare nella sezione destinata delledichiarazioni delle variabili globali la clausola

Option Base 1

In questo caso, l'indice minimo dei vettori è 1. Osservando la dichiarazione, si nota lapresenza di un unico identificatore di tipo. Ciò rende immediatamente intuibile lanecessità che tutti i dati presenti nel vettore siano omogenei. Nell'esempio, i valori sonoacquisiti per mezzo della funzione InputBox, la cui sintassi è la seguente:

<stringa>=InputBox(<Messaggio di richiesta>

[, <titolo della finestra>]

Page 75: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 6)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb06/index.htm[26/09/2010 1:06:00]

[, <valore di default>]

[, <posizione orizzontale>]

[, <posizione verticale>])

Essa visualizza una finestra di dialogo che invita l'utente a digitare una stringa. Come èpossibile notare, il programmatore deve specificare il messaggio di richiesta. Inoltre, eglipuò provvedere a un ulteriore personalizzazione indicando il titolo della finestra (in casodi omissione è utilizzato quello dell'applicazione), il valore di default, che è restituito sel'utente agisce sul pulsante Annulla e le coordinate orizzontale e verticale del punto diorigine. Si noti che il riempimento del vettore avviene per mezzo di un ciclo For, cheprovvede a richiedere il valore di ogni singolo elemento richiamando 100 volte lafunzione InputBox.

L'ordinamento per selezione diretta

Dopo l'acquisizione dei dati, è possibile provvedere al loro ordinamento. A tal fine, si fauso dell'algoritmo detto di selezione diretta. Non si tratta del metodo più efficiente, ma sipresta molto bene agli scopi didattici, in quanto è caratterizzato da un'estrema semplicità.Eccone una breve descrizione. Si supponga che i sia l'indice di un elemento del vettore.Affinché l'ordinamento sia crescente, è necessario che tutti gli oggetti caratterizzati dalpossedere un indice superiore a i abbiano un valore maggiore di quello dell'elemento diindice i. Per fare in modo che ciò avvenga, per ogni posizione j maggiore di i èeffettuato un confronto. Se l'elemento di indice j contiene un valore inferiore a quellodell'oggetto di posizione i, i dati sono scambiati. Al termine dell'iterazione, l'elemento diindice i contiene sicuramente un valore inferiore a tutti quelli che lo seguono. Laripetizione di questa operazione per tutti gli elementi del vettore ne provocal'ordinamento. L'implementazione è basata sull'uso di due cicli For nidificati. Il piùinterno effettua la scansione del vettore alla ricerca dei valori inferiori a quello contenutonell'elemento di indice i. Il più esterno varia i per fare in modo che tale scansione siaripetuta per tutti gli elementi del vettore, tranne l'ultimo, per il quale l'operazione sarebbeevidentemente inutile. La terza parte del programma è ancora una volta costituita da unciclo, la cui funzione è quella di copiare nella label i dati contenuti nel vettore ordinato,separandoli con il carattere caratterizzato dal codice ASCII 10, che corrisponde al ritornoa capo. In tal modo i valori sono visualizzati su righe separate. Si noti l'uso dellafunzione Chr$ per generare un carattere a partire dal suo codice ASCII. L'applicazionedescritta si caratterizza per la presenza di ben quattro cicli. Ciò non è casuale. I vettori,infatti, essendo costituiti da dati di tipo omogeneo, sui quali in genere devono essereeffettuate le stesse operazioni, si prestano molto bene ad essere utilizzati nelle procedurebasate sull'uso delle strutture di iterazione.

Due esercizi

Per verificare la comprensione degli argomenti esposti, si provi ad eseguire i seguentiesercizi:

Primo esercizio

Si modifichi l'applicazione dell'esempio affinché effettui l'ordinamento in mododecrescente.

Secondo esercizio

Page 76: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 6)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb06/index.htm[26/09/2010 1:06:00]

Si realizzi un'applicazione in grado di estrarre a sorte 30 numeri, di calcolarne la mediaaritmetica e di visualizzare all'interno di una textbox solo quelli che risultano inferiori adessa.

I vettori sono strutture di dati dall'importanza fondamentale, il cui uso si rivela spessoindispensabile per la realizzazione di programmi in grado di gestire grandi quantità didati di tipo omogeneo. Nel prossimo numero si parlerà ancora degli array e sarannoillustrati alcuni concetti più avanzati. Per la loro comprensione è quindi importanteesercitarsi su quanto appreso questo mese.

Rinfreschiamoci la memoria...

Questa lezione si chiude in un modo un po' diverso, con una serie di domande aventi loscopo di consentire un'autoverifica del livello di comprensione degli argomenti esposti inquesti sei mesi. Le risposte corrette sono elencate di seguito, in corsivo.

Qual è la differenza che intercorre fra una textbox e una label?

La label permette solo di visualizzare una stringa. La textbox permette anchel'inserimento del dato da parte dell'utente.

A quale evento occorre associare del codice per fare in modo che sia eseguito incorrispondenza della pressione di un pulsante?

L'evento generato dalla pressione di un pulsante è denominato Click.

Può una variaibile di tipo Integer contenere il dato 23.45?

No, perché le variabili di tipo Integer non possono contenere numeri con cifre decimali.

Quale istruzione permette di dichiarare una variabile?

La dichiarazione di una variabile è possibile per mezzo dell'istru- zione Dim.

È consentito utilizzare più strutture If nidificate?

Si, in Visual Basic non ci sono limiti al livello di nidificazione delle strutture If.

Quali istruzioni sono eseguite se la condizione che regola una struttura If è falsa?

Sono eseguite le istruzioni comprese fra le parole chiave Else e End If

A cosa serve la funzione Val?

La funzione Val converte una stringa in un valore numerico

Cosa restituisce l'operatore logico And applicato a due condizioni?

L'operatore logico And, se applicato a due condizioni, restituisce il valore True se e solose entrambe sono verificate.

A cosa serve l'operatore logico Not?

L'operatore logico Not serve per negare una condizione.

A cosa serve la parola chiave Next?

Page 77: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 6)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb06/index.htm[26/09/2010 1:06:00]

La parola chiave Next è utilizzata per delimitare il blocco di istruzioni contenuto in unciclo For.

A cosa serve la funzione Len?

La funzione Len restituisce la lunghezza della stringa fornitale come parametro

A cosa serve la parola chiave Step?

La parola chiave Step permette di specificare l'incremento della variabile di controllo adogni iterazione in un ciclo For. Se è omessa, l'incremento è di un'unità.

È possibile interrompere prematuramente un ciclo For?

Si, per mezzo dell'istruzione Exit For

Un ciclo While può ripetere un blocco di istruzioni per un qualsiasi numero di volte. Sela condizione non è verificata, può non eseguire alcuna iterazione.

Quando un ciclo Do Until ripete un blocco di istruzioni?

Un ciclo Do Until ripete un blocco di istruzioni fino a quando si verifica la condizionespecificata dopo la parola Until

La clausola Option Base 1 serve per fare in modo che l'indice minimo dei vettoriall'interno del progetto sia 1, anziché 0.

(c) 1998 Edizioni Infomedia srl

Page 78: Corso Visual Basic

Maurizio Crespi - Corso di Visual Basic (Parte 6)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb06/index.htm[26/09/2010 1:06:00]

Page 79: Corso Visual Basic

La soluzione del primo esercizio

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb06/fig1.htm[26/09/2010 1:06:18]

Figura 1La soluzione del primo esercizio

Page 80: Corso Visual Basic

L'applicazione che ordina 3 valori

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb06/fig2.htm[26/09/2010 1:06:25]

Figura 2L'applicazione che ordina 3 valori

Page 81: Corso Visual Basic

L'applicazione che ordina 100 valori

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb06/fig3.htm[26/09/2010 1:06:32]

Figura 3L'applicazione che ordina 100 valori

Page 82: Corso Visual Basic

Corso di Visual Basic (Parte 7)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb07/index.htm[26/09/2010 1:08:29]

Corso diVisual Basic(Parte 7)Le soluzioni degli eserciziproposti nella precedentelezione

Vettori con indiceminimo diverso da 0 o 1

I vettori a dimensionevariabile

La clausola Preserve

Vettori a due indici

I vettori di controlli

Conclusioni

Listati

Listato 1 - La soluzionedel secondo eserciziodello scorso numero

Listato 2 - Una primaversione della procedurache calcola la media frale temperature di piùgiorni

Listato 3 - La procedurache calcola la media frale temperature di piùgiorni modificata perl'uso di array dinamici

Listato 4 - La procedurache calcola la media frale temperature di piùgiorni modificata perl'uso di array adimensione variabile

Listato 5 - La proceduramodificata per gestire letemperature minima emassima

Listato 6 - La procedurache gestisce le

Corso di

Visual Basic

(Parte 7)di Maurizio Crespi

Continua lo studio dei vettori; questo mese sono protagonisti quelli a più dimensioni, lestrutture caratterizzate dal poter variare dinamicamente il numero degli elementi che lecompongono e gli array di controlli

Nella scorsa lezione è stata introdotta la nozione di vettore, o array. Per mezzo di questastruttura di dati, è possibile associare un unico nome a un insieme di posizioni di memoriadello stesso tipo, ognuna delle quali può contenere un dato diverso. In questa settima puntatadel corso dedicato alla programmazione in Visual Basic sarà esteso il concetto e ne sarannodescritte le evoluzioni, ovvero saranno studiati i vettori caratterizzati dal possedere più diuna dimensione e gli utilissimi array di controlli, che talvolta contribuiscono notevolmente asemplificare il compito del programmatore.

Le soluzioni degli esercizi proposti nella precedentelezione

Il primo passo, prima di procedere allo studio dei nuovi argomenti, prevede come sempre laverifica della comprensione di quelli esposti nel numero precedente, mediante la correzionedegli esercizi in esso proposti.

Primo esercizio

Il primo esercizio richiede la modifica dell'applicazione, descritta nello scorsa puntata, ingrado di leggere 100 numeri e di elencarli in ordine crescente all'interno di una casella ditesto. È infatti richiesto di far sì che effettui l'ordinamento in modo decrescente. Lasoluzione è banale, in quanto richiede semplicemente l'inversione dell'operatore di confrontoall'interno del ciclo che provvede all'ordinamento. Il codice necessario per ordinare unvettore contenente 100 valori numerici in modo decrescente per mezzo dell'algoritmo diselezione diretta è pertanto quello indicato di seguito:

For i = 1 To 99

For j = i + 1 To 100

If Valori(i) < Valori(j) Then

Temp = Valori(i)

Valori(i) = Valori(j)

Valori(j) = Temp

End If

Page 83: Corso Visual Basic

Corso di Visual Basic (Parte 7)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb07/index.htm[26/09/2010 1:08:29]

temperature minima emassima con un vettore a2 dimensioni

(c) 1997, EdizioniInfomedia srl

Next j, i

Secondo esercizio

Il secondo esercizio presenta una complessità leggermente superiore. Esso richiede infatti direalizzare un'applicazione in grado di estrarre a sorte 30 numeri, di calcolarne la mediaaritmetica e di visualizzare all'interno di una label solo quelli che risultano inferiori ad essa.Per la sua realizzazione, l'applicazione richiede la creazione di un form, in cui va postaun'etichetta testuale denominata lblRisultato. Il codice che provvede al suo riempimentodeve essere eseguito all'avvio. Può pertanto essere associato all'evento Load del form. Laprocedura, che è possibile osservare nel Listato 1, è costituita da 3 cicli. Il primo ha lo scopodi estrarre a sorte 30 valori interi compresi fra 1 e 100. Di essi è calcolata la media aritmeticaper mezzo della seconda struttura di iterazione. Tutti i valori che risultano inferiori a questonumero sono elencati, uno sotto l'altro, all'interno della casella di testo. Ciò avviene permezzo del terzo ciclo.

Vettori con indice minimo diverso da 0 o 1

Si noti che la dichiarazione del vettore risulta leggermente diversa da quelle viste nellascorsa lezione. In questo caso, infatti, è stato specificato anche l'indice minimo, secondo lasintassi

Dim <nome> (<indice_minimo> To <indice_massimo>) As <tipo>

Ciò consente di creare dei vettori in cui gli indici possono essere anche negativi, oppureappartenere a un campo di valori molto diverso da quello usuale. Ad esempio, supponendodi voler creare un array in grado di ospitare un dato numerico indicante il prodotto internolordo dello Stato italiano negli anni compresi fra il 1989 ad oggi, è possibile dichiarare lavariabile PIL come segue:

Dim PIL(1989 To 1998) As Double

Naturalmente, il vettore è del tutto equivalente a uno di 10 elementi dichiarato con il metodousuale, però l'uso di indici strettamente correlati alle informazioni contenute nella strutturaoffre il vantaggio di migliorare la leggibilità del codice.

I vettori a dimensione variabile

Si supponga di voler scrivere un'applicazione in grado di leggere un dato numericocorrispondente alla temperatura massima per ogni giorno di un mese, di calcolare la media ditutti i valori e di indicare in quali giorni la temperatura si è mantenuta al di sotto del valoremedio calcolato. In pratica, l'applicazione risulta estremamente simile a quella descritta inprecedenza. In questo caso, tuttavia, i valori non sono casuali, bensì inseriti dall'utente.Inoltre, il loro numero non è fisso, in quanto dipendente dal mese a cui si riferiscono i dati.Una possibile soluzione è quella indicata nel Listato 2.

ReDim [Preserve] <nome> (<dimensione>)

Il suo scopo è di variare la dimensione del vettore di cui è specificato il nome. L'istruzionepuò essere ripetuta all'interno del programma per un numero di volte teoricamente infinito.La procedura descritta nel Listato 2 può essere resa più efficiente mediante l'uso di unvettore dinamico, come indicato nel Listato 3. Si noti che è cambiata la dichiarazione delvettore, che nella nuova procedura costituita dalla riga

Page 84: Corso Visual Basic

Corso di Visual Basic (Parte 7)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb07/index.htm[26/09/2010 1:08:29]

Dim V() As Integer

La dimensione questa volta non è stata specificata; il compito di allocare la giusta quantità dimemoria per le informazioni è demandato alla riga

ReDim V(NumGiorni)

che provvede a dimensionare il vettore in modo che il massimo indice sia pari al valore dellavariabile intera NumGiorni, il cui valore è fornito dall'utente.

La clausola Preserve

Si supponga ora di voler modificare la procedura sopra descritta per fare in modo che nonrichieda all'avvio il numero dei valori da elaborare, bensì acquisisca ciclicamente dei datifino alla digitazione da parte dell'utente della stringa "Fine".

In questo caso, non è possibile conoscere la dimensione del vettore prima dell'inserimentodei dati. Esso quindi deve essere in grado di crescere continuamente. Il codice necessario persvolgere il compito richiesto è descritto nel Listato 4. Si noti la presenza di un ciclodelimitato dalle parole chiave Do e Loop. Esso risulta privo delle clausole While o Until.L'uscita è infatti causata dall'istruzione Exit For, che è eseguita quando l'utente digita laparola "Fine". Osservando il codice, è possibile constatare che la stringa inserita dall'utente èconvertita in maiuscolo per mezzo della funzione UCase ed è privata degli eventuali spaziiniziali e finali per mezzo della funzione Trim. In tal modo, il confronto risulta indipendentedall'uso delle lettere maiuscole.

L'istruzione ReDim è invocata ad ogni iterazione, al fine di incrementare la dimensione delvettore di un'unità per fare posto al dato appena letto. Dovendo intervenire su una strutturagià contenente dei dati e volendo fare in modo che essi non siano persi, occorre utilizzarel'istruzione ReDim con la clausola Preserve; in sua assenza, il ridimensionamento dell'arraycomporterebbe la cancellazione di tutti i valori contenuti. All'interno della procedura si èfatto uso anche della funzione UBound, che ha lo scopo di calcolare il massimo indiceprevisto dal vettore, ovvero la sua dimensione.

Esercizio

Si provi a realizzare un'applicazione in grado di simulare lo spoglio delle schede elettorali.Essa deve leggere per ogni scheda il numero del candidato votato. Alla fine, deve essere ingrado di indicare la classifica in ordine decrescente.

Vettori a due indici

Si supponga ora di voler modificare il programma per fare in modo che sia in grado dieffettuare le proprie valutazioni facendo riferimento sia alle temperature massime, sia alleminime e che indichi i giorni in cui almeno uno dei due valori è risultato al di sotto dellamedia.

In questo caso, quindi, per ogni giorno è necessario acquisire due valori. Una soluzioneconsiste nell'utilizzare due vettori, uno dedicato alle temperature massime e l'altro alleminime. Il codice è descritto nel Listato 5. Esso non costituisce un esempio di compattezzaed efficienza. Infatti, le istruzioni utilizzate per gestire le temperature minime sonopraticamente duplicate per gestire le massime. La lunghezza del codice può essere ridottafacendo ricorso a una matrice costituita da due colonne, di cui una è dedicata alletemperature minime e l'altra alle massime. La procedura così modificata è descritta nelListato 6. Il primo indice determina la colonna della matrice.

Page 85: Corso Visual Basic

Corso di Visual Basic (Parte 7)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb07/index.htm[26/09/2010 1:08:29]

Il valore 1 fa riferimento alle temperature minime, mentre il valore 2 si riferisce allemassime. Il secondo, ridimensionabile per mezzo dell'istruzione ReDim, è invece utilizzatoper far riferimento al giorno. Si osservi che l'uso dell'istruzione ReDim non è possibile sulprimo indice.

Infatti, solo l'indice posto più a destra nella dichiarazione di una matrice può essereridimensionato. L'introduzione di una seconda dimensione comporta una semplificazione delcodice.

Per operazioni più complesse, è possibile incrementare ulteriormente il numero delledimensioni di un vettore, purché rimanga inferiore a 60.

Nella procedura appena descritta, si è fatto nuovamente uso della funzione UBound, che inquesto caso richiede un ulteriore parametro indicante la posizione della dimensione di cui sidesidera conoscere la grandezza.

I vettori di controlli

Si supponga ora di voler modificare l'applicazione per fare in modo che sia in grado dirichiedere su un unico form i valori delle temperature minime e massime rilevate in tutti igiorni di una settimana. L'interfaccia deve prevedere l'acquisizione dei dati che avviene permezzo di caselle di testo. Si tratta di creare un form e di aggiungere le textbox necessarie,che si supporranno denominate LunediMin, LunediMax, MartediMin, MartediMax, ecc.Occorre poi modificare la procedura precedentemente descritta sostituendo la parte dedicataall'inserimento dei dati nella matrice con il seguente codice:

V(1,1)=Val(LunediMin.Text)

V(2,1)=Val(LunediMax.Text)

V(1,2)=Val(MartediMin.Text)

V(2,2)=Val(MartediMax.Text)

V(1,3)=Val(MercolediMin.Text)

V(2,3)=Val(MercolediMax.Text)

V(1,4)=Val(GiovediMin.Text)

V(2,4)=Val(GiovediMax.Text)

V(1,5)=Val(VenerdiMin.Text)

V(2,5)=Val(VenerdiMax.Text)

V(1,6)=Val(SabatoMin.Text)

V(2,6)=Val(SabatoMax.Text)

V(1,7)=Val(DomenicaMin.Text)

V(2,7)=Val(DomenicaMax.Text)

La sequenza di istruzioni presentata non rappresenta un esempio di semplicità. Nel caso incui le caselle di testo, anziché essere 14, fossero in un numero sensibilmente maggiore, ilprogramma potrebbe diventare poco leggibile. Si osservi che di fatto le righe sonoestremamente simili fra loro. Ciò che varia è il nome della textbox. Grazie alle caratteristichedi Visual Basic, è possibile operare una notevole semplificazione del codice utilizzando un

Page 86: Corso Visual Basic

Corso di Visual Basic (Parte 7)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb07/index.htm[26/09/2010 1:08:29]

vettore di controlli, nella fattispecie rappresentati da caselle di testo. Un array di questo tiponon richiede alcuna dichiarazione. È sufficiente far uso della proprietà Index dei controlli.Ad esempio, si supponga di voler realizzare il form in grado di acquisire tutte le temperaturerilevate nell'arco della settimana. Dopo aver agito sul menu Progetto ed aver selezionato lavoce Inserisci form, si provvede ad inserire sul modulo creato una casella di testo e adassegnarle il nome txtMinima. Ad essa possono successivamente essere assegnati i valoridesiderati delle proprietà che definiscono il carattere, il colore e la dimensione. Si crea cosìl'elemento campione, che può essere duplicato per mezzo di una normale operazione dicopia e incolla. Si noti che, nel momento in cui si incolla il primo elemento, appare unmessaggio che segnala la presenza sul form di un altro oggetto denominato txtMinima epresenta una finestra di dialogo che ha lo scopo di chiedere al programmatore se desideracreare un array. Rispondendo Si, si crea un vettore di caselle di testo denominato txtMinima,in cui gli elementi che lo compongono sono caratterizzati dal possedere un diverso valoredella variabile Index.

Quest'ultima costituisce l'indice che identifica in modo univoco l'elemento nel vettore. Ètuttavia possibile realizzare una matrice anche riunendo dei controlli aventi dei nomi diversi,purché siano dello stesso tipo. In questo caso, occorre inserire tutti gli elementi nel form esuccessivamente associare ad essi dei diversi valori della proprietà Index. Dopo aver fattociò, è possibile variare il contenuto delle proprietà Name ed assegnare a tutti la stessastringa. Tornando all'esempio, si supponga di creare 7 copie dell'oggetto txtMinima. Sisupponga altresì di agire in modo analogo con un'altra casella di testo, denominatatxtMassima. In tal modo, si creano 2 vettori, destinati a contenere rispettivamente letemperature minime e massime rilevate. Grazie ad essi, il codice necessario per riempire ilvettore V si riduce a poche righe:

For i=1 to 7

V(1,i)=val(txtMinima(i).Text)

V(2,i)=val(txtMassima(i).Text)

Next i

Si noti la notevole compattezza che lo caratterizza e la possibilità di adattarlo alla gestione diun numero maggiore di textbox semplicemente variando il valore massimo della variabile dicontrollo del ciclo. L'accesso alle proprietà e ai metodi di ogni elemento del vettore richiedeobbligatoriamente l'indicazione dell'indice fra parentesi tonde. Un'interessante caratteristicadei vettori di controlli consiste nell'utilizzo della stessa procedura per rispondere agli eventigenerati da ogni singolo elemento.

Ad esempio, si supponga di disporre di un form dotato di 3 pulsanti, etichettati Primo,Secondo, Terzo, che costituiscono un vettore denominato btnBottoni. Volendo generare unmessaggio alla pressione di un pulsante che indichi quale di essi è stato premuto, è possibilescrivere la seguente procedura:

Private Sub btnBottoni_Click(Index As Integer)

MsgBox btnBottoni(Index).Caption

End Sub

Essa è associata all'evento Click di tutti gli elementi del vettore. Si noti che fra parentesi èspecificata la variabile Index. Essa ha valore solo all'interno della procedura ed identifical'indice dell'elemento che ha generato l'evento.

Per mezzo della funzione MsgBox, in grado di far apparire sullo schermo una finestracontenente un messaggio, è possibile visualizzare l'etichetta testuale del pulsante premuto,facendo riferimento alla proprietà Caption dell'elemento di indice corrispondente al valoredella variabile Index.

Page 87: Corso Visual Basic

Corso di Visual Basic (Parte 7)

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb07/index.htm[26/09/2010 1:08:29]

La procedura descritta risulta adatta a gestire vettori di dimensione qualsiasi. Ancora unavolta appare evidente la caratteristica fondamentale degli array: lo stesso codice può gestireallo stesso modo e con la stessa facilità delle strutture sia di piccole, sia di grandidimensioni.

Esercizio

Si provi a realizzare un'applicazione che preveda una pulsantiera costituita da tasti numeratida 1 a 9. La pressione di uno di essi deve provocare l'incremento di un contatore numerico diun'entità pari all'indicazione presente sulla sua etichetta. Il valore del contatore deve esserevisualizzato per mezzo di una label.

Conclusioni

L'uso dei vettori permette di aumentare notevolmente la flessibilità e il livello di astrazionedel proprio codice.

Per mezzo di quelli a più dimensioni e agli array di controlli, diventa spesso possibile ridurrenotevolmente la quantità di codice necessaria per realizzare un'applicazione, a tuttovantaggio della leggibilità.

Data l'importanza degli argomenti proposti, l'invito rivolto al lettore è come sempre diesercitarsi su di essi, al fine di raggiungere un buon livello di comprensione.

(c) 1998 Edizioni Infomedia srl

Page 88: Corso Visual Basic

La soluzione del secondo esercizio dello scorso numero

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb07/lis1.htm[26/09/2010 1:08:39]

Private Sub Form_Load()

Dim i As Integer

Dim Somma As Integer

Dim Media As Double

Dim V(1 To 30) As Integer

Rem Estrazione valori

Randomize

For i = 1 To 30

V(i) = Int(Rnd() * 100)

Next i

Rem Calcolo della media

Somma = 0

For i = 1 To 30

Somma = Somma + V(i)

Next i

Media = Somma / 30

Rem Inserimento dei risultati nella label

lblRisultato.Caption = ""

For i = 1 To 30

If V(i) < Media Then

lblRisultato.Caption = lblRisultato.

Caption & V(i) & Chr$(10)

End If

Next i

End Sub

Listato 1La soluzione del secondo esercizio dello scorso numero

Page 89: Corso Visual Basic

Una prima versione della procedura che calcola la media fra le temperature di più giorni

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb07/lis2.htm[26/09/2010 1:08:49]

Private Sub Form_Load()

Dim V(1 To 31) As Integer

Dim i As Integer

Dim NumGiorni As Integer

Dim Stringa As String

Dim Messaggio As String

Dim Somma As Integer

Dim Media As Double

Rem Acquisizione valori

Stringa = InputBox("Numero dei giorni")

NumGiorni = Val(Stringa)

For i = 1 To NumGiorni

Messaggio = "Temperatura giorno" & Str$(i)

Stringa = InputBox(Messaggio)

V(i) = Int(Val(Stringa))

Next i

Rem Calcolo della media

Somma = 0

For i = 1 To NumGiorni

Somma = Somma + V(i)

Next i

Media = Somma / NumGiorni

Rem Generazione elenco valori

' al di sotto della media

lblRisultato.Caption = ""

For i = 1 To NumGiorni

If V(i) < Media Then

lblRisultato.Caption = lblRisultato.Caption & i

& Chr$(10)

End If

Next i

End Sub

Listato 2Una prima versione della procedura che calcola la media fra le temperature di più giorni

Page 90: Corso Visual Basic

Una prima versione della procedura che calcola la media fra le temperature di più giorni

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb07/lis2.htm[26/09/2010 1:08:49]

Page 91: Corso Visual Basic

La procedura che calcola la media fra le temperature di più giorni modificata per l'uso di array dinamici

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb07/lis3.htm[26/09/2010 1:08:58]

Private Sub Form_Load()

Dim V() As Integer

Dim i As Integer

Dim NumGiorni As Integer

Dim Stringa As String

Dim Messaggio As String

Dim Somma As Integer

Dim Media As Double

Rem Acquisizione valori

Stringa = InputBox("Numero dei giorni")

NumGiorni = Val(Stringa)

ReDim V(NumGiorni)

For i = 1 To NumGiorni

Messaggio = "Temperatura giorno" & Str$(i)

Stringa = InputBox(Messaggio)

V(i) = Int(Val(Stringa))

Next i

Rem Calcolo della media

Somma = 0

For i = 1 To NumGiorni

Somma = Somma + V(i)

Next i

Media = Somma / NumGiorni

Rem Generazione elenco valori

' al di sotto della media

lblRisultato.Caption = ""

For i = 1 To NumGiorni

If V(i) < Media Then

lblRisultato.Caption = lblRisultato.Caption & i

& Chr$(10)

End If

Next i

End Sub

Listato 3La procedura che calcola la media fra le temperature di più giorni modificata per l'uso di array dinamici

Page 92: Corso Visual Basic

La procedura che calcola la media fra le temperature di più giorni modificata per l'uso di array dinamici

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb07/lis3.htm[26/09/2010 1:08:58]

Page 93: Corso Visual Basic

La procedura che calcola la media fra le temperature di più giorni modificata per l'uso di array a dimensione variabile

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb07/lis4.htm[26/09/2010 1:10:14]

Private Sub Form_Load()

Dim V() As Integer

Dim i As Integer

Dim NumGiorni As Integer

Dim Stringa As String

Dim Messaggio As String

Dim Somma As Integer

Dim Media As Double

Rem Acquisizione valori

i = 0

Stringa = ""

Do

i = i + 1

Messaggio = "Temperatura giorno" & Str$(i)

Stringa = InputBox(Messaggio)

Stringa = UCase(Stringa)

Stringa = Trim(Stringa)

If Stringa = "FINE" Then

Exit Do

Else

ReDim Preserve V(i)

V(i) = Int(Val(Stringa))

End If

Loop

NumGiorni = UBound(V)

Rem Calcolo della media

Somma = 0

For i = 1 To NumGiorni

Somma = Somma + V(i)

Next i

Media = Somma / NumGiorni

Rem Generazione elenco valori

' al di sotto della media

lblRisultato.Caption = ""

For i = 1 To NumGiorni

If V(i) < Media Then

lblRisultato.Caption = lblRisultato.Caption & i

Page 94: Corso Visual Basic

La procedura che calcola la media fra le temperature di più giorni modificata per l'uso di array a dimensione variabile

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb07/lis4.htm[26/09/2010 1:10:14]

& Chr$(10)

End If

Next i

End Sub

Listato 4La procedura che calcola la media fra le temperature di più giorni modificata per l'uso di array a dimensionevariabile

Page 95: Corso Visual Basic

La procedura modificata per gestire le temperature minima e massima

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb07/lis5.htm[26/09/2010 1:10:30]

Private Sub Form_Load()

Dim Vmin() As Integer

Dim Vmax() As Integer

Dim i As Integer

Dim NumGiorni As Integer

Dim Stringa As String

Dim Messaggio As String

Dim Somma As Integer

Dim MediaMin As Double

Dim MediaMax As Double

Rem Acquisizione valori

i = 0

Stringa = ""

Do

i = i + 1

Messaggio = "Temperatura minima giorno" & Str$(i)

Stringa = InputBox(Messaggio)

Stringa = UCase(Stringa)

Stringa = Trim(Stringa)

If Stringa = "FINE" Then

Exit Do

Else

ReDim Preserve Vmin(i)

ReDim Preserve Vmax(i)

Vmin(i) = Int(Val(Stringa))

Messaggio = "Temperatura massima giorno" & Str$(i)

Stringa = InputBox(Messaggio)

Stringa = UCase(Stringa)

Stringa = Trim(Stringa)

Vmax(i) = Int(Val(Stringa))

End If

Loop

NumGiorni = UBound(Vmin)

Rem Calcolo della media delle

' temperature minime

Somma = 0

For i = 1 To NumGiorni

Somma = Somma + Vmin(i)

Page 96: Corso Visual Basic

La procedura modificata per gestire le temperature minima e massima

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb07/lis5.htm[26/09/2010 1:10:30]

Next i

MediaMin = Somma / NumGiorni

Rem Calcolo della media delle

' temperature massime

Somma = 0

For i = 1 To NumGiorni

Somma = Somma + Vmax(i)

Next i

MediaMax = Somma / NumGiorni

Rem Generazione elenco giorni con

Rem temperature al di sotto della media

lblRisultato.Caption = ""

For i = 1 To NumGiorni

If (Vmin(i) < MediaMin) Or (Vmax(i) < MediaMax) Then

lblRisultato.Caption = lblRisultato.Caption & i

& Chr$(10)

End If

Next i

End Sub

Listato 5La procedura modificata per gestire le temperature minima e massima

Page 97: Corso Visual Basic

La procedura che gestisce le temperature minima e massima con un vettore a 2 dimensioni

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb07/lis6.htm[26/09/2010 1:10:38]

Private Sub Form_Load()

Dim V() As Integer

Dim i As Integer

Dim j As Integer

Dim NumGiorni As Integer

Dim Stringa(2) As String

Dim Messaggio As String

Dim Somma As Integer

Dim MediaMin As Double

Dim MediaMax As Double

Rem Acquisizione valori

i = 0

Do

i = i + 1

For j = 1 To 2

Stringa(j) = ""

If j = 1 Then

Messaggio = "Temperatura minima giorno" & Str$(i)

Else

Messaggio = "Temperatura massima giorno" & Str$(i)

End If

Stringa(j) = InputBox(Messaggio)

Stringa(j) = UCase(Stringa(j))

Stringa(j) = Trim(Stringa(j))

Next j

If (Stringa(1) = "FINE") Or (Stringa(2) = "FINE") Then

Exit Do

Else

ReDim Preserve V(2, i)

V(2, i) = Int(Val(Stringa(1)))

V(1, i) = Int(Val(Stringa(2)))

End If

Loop

NumGiorni = UBound(V, 2)

Rem Calcolo della media delle

' delle temperature minime

Somma = 0

For i = 1 To NumGiorni

Page 98: Corso Visual Basic

La procedura che gestisce le temperature minima e massima con un vettore a 2 dimensioni

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb07/lis6.htm[26/09/2010 1:10:38]

Somma = Somma + V(1, i)

Next i

MediaMin = Somma / NumGiorni

Rem Calcolo della media delle

' temperature massime

Somma = 0

For i = 1 To NumGiorni

Somma = Somma + V(2, i)

Next i

MediaMax = Somma / NumGiorni

Rem Generazione elenco giorni con

Rem temperature al di sotto della media

lblRisultato.Caption = ""

For i = 1 To NumGiorni

If (V(1, i) < MediaMin) Or (V(2, i) < MediaMax) Then

lblRisultato.Caption = lblRisultato.Caption & i

& Chr$(10)

End If

Next i

End Sub

Listato 6La procedura che gestisce le temperature minima e massima con un vettore a 2 dimensioni

Page 99: Corso Visual Basic

○ ○ ○ ○ ○SETTEMBRE 1998 - PROGRAMMO SUBITO n.8 ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○86

Corso diVisual Basic

(Parte 8)

DI MAURIZIO CRESPI

Q uesto mese il corso di programmazione in Visual Basicfocalizza la propria attenzione sulle procedure, talvoltadette subroutine

L�oggetto dell�ottava puntata del corso dedicato alla programma-zione in ambiente Microsoft Visual Basic è rappresentato dalleprocedure definibili dal programmatore. Come si potrà osservarein seguito, si tratta di strutture di fondamentale importanza, inquanto il loro uso permette di rendere notevolmente più compattoe leggibile il codice di un�applicazione.

LE SOLUZIONI DEGLI ESERCIZI DELLA SCORSA LEZIONECome sempre, prima di affrontare i nuovi argomenti sarà fornito

al lettore uno spunto per rinfrescare la propria memoria su quantoappreso nella scorsa lezione. L�occasione è data dalla correzionedegli esercizi in essa proposti.

Primo esercizioIl primo esercizio richiede la realizzazione di un programma in

grado di simulare lo spoglio delle schede elettorali. Per ognischeda, l�applicazione deve leggere il numero del candidatovotato e redigere, a scrutinio terminato, una classifica in ordinedecrescente. Il compito può essere svolto dalla seguente proce-dura, che è eseguita nella fase di caricamento di un form conte-nente un�etichetta di testo (lblClassifica) destinata a contenere laclassifica finale.

Private Sub Form_load() Dim ElencoVoti() As Integer Dim Classifica() As Integer Dim Stringa As String Dim Candidato As Integer Dim NumeroCandidati As Integer Dim i As Integer Dim j As Integer Dim x As Integer Dim y As Integer

Stringa = InputBox(�Numero candidati�) NumeroCandidati = Int(Val(Stringa)) ReDim ElencoVoti(NumeroCandidati) ReDim Classifica(NumeroCandidati)

Rem Acquisizione dei dati Do Stringa = InputBox(�N. candidato votato

(0 per finire)�) Candidato = Int(Val(Stringa)) If Candidato > 0 Then

ElencoVoti(Candidato) = ElencoVoti(Candidato) + 1 End If Loop Until Candidato = 0

Rem Preparazione vettore classifica For i = 1 To NumeroCandidati Classifica(i) = i Next i For i = 1 To NumeroCandidati - 1

For j = i + 1 To NumeroCandidati x = Classifica(i) y = Classifica(j) If ElencoVoti(x) < ElencoVoti(y) Then Temp = Classifica(i) Classifica(i) = Classifica(j) Classifica(j) = Temp End If

Next j, i

Rem Visualizzazione classificalblClassifica.Caption = ��For i = 1 To NumeroCandidati

lblClassifica.Caption = lblClassifica.Caption &Classifica(i) & Chr$(10)

Next iEnd Sub

La lettura dei dati è, per semplicità, affidata a delle finestre diinput, realizzate per mezzo della funzione InputBox.

Sono previsti due vettori; il primo, denominato ElencoVoti,associa all�elemento di indice n il numero dei voti collezionati dalcandidato numero n. Ogni elemento contiene un numero che èincrementato ogniqualvolta è estratta una scheda sui cui è espressauna preferenza riferita al candidato corrispondente. Un secondovettore, denominato Classifica, ha lo scopo di memorizzare inumeri associati ai candidati in modo che leggendo sequenzial-mente la struttura si possa leggere la classifica in ordine decrescen-te di voti. Entrambi i vettori sono dimensionati all�avvio delprogramma per prevedere un elemento per ogni candidato.

La procedura provvede a leggere tutti i voti di preferenza,aggiornando volta per volta il vettore ad essi dedicato. Dopo averfatto ciò, è inizializzato il vettore Classifica con i numeri corrispon-denti a tutti i candidati; tali valori sono in seguito scambiati fra loroin modo tale per cui al termine del ciclo il vettore contenga laclassifica in ordine decrescente di preferenze. Si noti che pereffettuare ciò è applicata una variante all�algoritmo di ordinamentoper selezione diretta visto nella scorsa lezione, in cui l�ordinamentoè eseguito sull�array Classifica ma i confronti sono effettuati fra glielementi del vettore ElencoVoti. Si desidera infatti fare in modo

Page 100: Corso Visual Basic

PROGRAMMO SUBITO n.8 - SETTEMBRE 1998○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○○ ○ ○ ○ ○ 87

che, dati due elementi qualsiasi x e y del vettore Classifica, xpreceda y se ElencoVoti(x)>ElencoVoti(y).

Secondo esercizioIl secondo esercizio prevede la realizzazione di un programma

dotato di una pulsantiera costituita da tasti numerati da 1 a 9. Lapressione di uno di essi deve provocare l�incremento di un conta-tore numerico di un�entità pari all�indicazione presente sulla suaetichetta. Il valore del contatore deve essere visualizzato permezzo di una label. Se si fa uso di un vettore di controlli, lasoluzione diventa estremamente semplice, al punto da non neces-sitare di alcun commento. Si supponga di disegnare un form dotatodi nove pulsanti, che costituiscono gli elementi del vettore btnNu-meri. Alla pressione di uno di essi, ovvero al verificarsi dell�eventoClick su un elemento del vettore, può essere associata la seguenteprocedura:

Private Sub btnNumeri_click(index As Integer)Dim Contatore As IntegerDim Incremento As IntegerContatore = Val(lblContatore.Caption)Incremento = Val(btnNumeri(index).Caption)Contatore = Contatore + IncrementolblContatore.Caption = Contatore

End Sub

LE PROCEDURESi supponga di voler realizzare un�applicazione in grado di

calcolare la somma di due valori numerici inseriti dall�utente dopoaver verificato che siano positivi e, rispettivamente, inferiori a 10e 50. Una possibile implementazione è la seguente:

Private Sub Form_Load() Dim Stringa As String Dim n1 As Double Dim n2 As Double Dim Somma As Double Rem Primo valore Do Stringa = InputBox(�Primo valore:�) n1 = Val(Stringa) Loop Until (n1 > 0) And (n1 < 10) Rem Secondo valore Do Stringa = InputBox(�Secondo valore:�)

n2 = Val(Stringa) Loop Until (n2 > 0) And (n2 < 50) Somma = n1 + n2 MsgBox (�La somma è � & Somma)End Sub

L�acquisizione dei valori avviene per mezzo di due cicli. Il loroscopo consiste nel richiedere la digitazione di una stringa all�utentee nell�effettuare la conversione in un valore numerico per mezzo

della funzione Val. Tale dato è successivamente sottoposto averifica per determinarne la conformità alle condizioni richieste.Qualora essa non fosse riscontrata, la presenza del ciclo fa sì che siarichiesto nuovamente il dato all�utente. Si noti che le due strutturedi iterazione sono estremamente simili. Ciò che cambia è rappre-sentato solamente dalla variabile da acquisire e dal valore massimoconsentito. Se Visual Basic disponesse di un�istruzione in grado dirichiedere un dato e di verificarne l�appartenenza ad un intervallo,il codice sarebbe notevolmente più semplice e privo di ripetizioni.Una simile istruzione non è prevista nella libreria standard dellostrumento di sviluppo. Tuttavia, come tutti i linguaggi di program-mazione moderni, Visual Basic permette la creazione di procedure,o subroutine. Esse rappresentano gruppi di istruzioni racchiuse instrutture identificate univocamente dai propri nomi. Una sequenzadi questo tipo può essere eseguita più volte all�interno di unprogramma senza che sia necessario ripeterne il codice; bastainfatti richiamarla indicandone il nome.

La definizione di una procedura prevede la seguente sintassi:

[Public|Private] Sub <nome> [(<definizione_parametro_1>, ... <definizione_parametro_n>)]

[<dichiarazione_variabili_locali>]<istruzione_1>...<istruzione_n>

End Sub

Dopo la parola chiave Sub è necessario specificare un identifica-tore che costituisce il nome della struttura. Come tutti gli altriidentificatori, deve essere composto da lettere, numeri o dalcarattere di sottolineatura (undescore) e il primo carattere deveessere necessariamente costituito da una lettera dell�alfabeto. Sinoti che non è la prima volta che si usa la parola chiave Suball�interno di questo corso. Infatti, le porzioni di codice da associa-re come risposta agli eventi sono anch�esse delle procedure.Quando un controllo genera un evento, l�interprete provvedeautomaticamente a verificare l�esistenza di una procedura aventeun nome composto dall�identificatore del controllo seguito dalcarattere di sottolineatura e dal tipo di evento (ad esempiobtnPulsante_Click). Se tale struttura esiste, è eseguita. Le proce-dure oggetto di trattazione in questa lezione sono invece definitedall�utente con lo scopo di migliorare la leggibilità del programmae riciclare il codice già scritto, evitando la ripetizione di lineepressoché identiche. Le procedure, analogamente alle variabili,sono soggette alle regole di scope. Pertanto, se sono definiteall�interno di un form, risultano locali a quest�ultimo, quindi

L�inter faccia utentedella soluzione delsecondo esercizioproposto nel lascorsa lezione

FIGURA 1

Mediante l�uso delleprocedure è possibile

migliorare la leggibilità delcodice

Page 101: Corso Visual Basic

○ ○ ○ ○ ○SETTEMBRE 1998 - PROGRAMMO SUBITO n.8 ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○88

pressoché invisibili agli altri moduli. Qualora si desiderasse crearedelle procedure globali, da utilizzare indifferentemente in tutti iform come se si trattasse di comandi standard previsti dal linguag-gio di programmazione, è necessario creare un nuovo moduloglobale, agendo sul menu Progetto alla voce Inserisci modulo.L�uso dei moduli globali permette anche di creare delle librerie diprocedure che possono essere agevolmente riutilizzate per losviluppo di altre applicazioni, semplicemente includendo il fileall�interno dei progetti.

UNA FUNZIONE IN UN MODULOPer inserire una procedura in un modulo occorre selezionare il

file nella finestra Progetto e premere il pulsante di visualizzazionedel codice. A questo punto è possibile utilizzare la voce Inserisciroutine del menu Strumenti. Appare così una finestra che permettedi specificare il nome della procedura, unitamente ad altre opzioniche per ora non saranno descritte.

Agendo in questo modo sul form di avvio dell�applicazione de-scritta nell�esempio precedente, è possibile inserire in esso laprocedura LeggiValore, in grado di leggere un dato e di convertirloin un valore numerico.

La sua definizione è la seguente:

Sub LeggiValore() Dim Stringa As String Do

Stringa = InputBox(MessaggioRichiesta)n = Val(Stringa)

Loop Until (n > 0) And (n < Massimo)End Sub

Si noti la dichiarazione della variabile Stringa, che risulta localealla procedura, essendo stata definita al suo interno. Pertanto, ècreata quando il programma inizia ad eseguire la routine ed èdistrutta in corrispondenza dell�uscita dal blocco di codice. Risultaquindi evidente che il suo valore non può essere utilizzato al di fuoridella procedura. Inoltre, non è conservato nelle chiamate succes-sive, a meno che non si sostituisca la parola chiave Dim con Static.In questo caso, la variabile è detta statica.

Tornando alla procedura LeggiValore, si nota che essa fa riferi-mento anche alle variabili n, MessaggioRichiesta e Massimo, di cuituttavia non è specificata la definizione. Ciò è corretto se si trattadi due variabili globali, ovvero se sono definite all�interno dellasezione Generale del form o in un modulo globale facendo uso dellaparola chiave Global. Nel primo caso esse risultano visibili a tuttele procedure definite all�interno del form.

Nel secondo, possono essere utilizzate addirittura da tutte leroutine contenute nell�applicazione. Con l�introduzione della pro-cedura LeggiValore, il codice da associare all�evento Load del formprincipale, diventa il seguente:

Private Sub Form_Load()Dim Stringa As StringDim n1 As DoubleDim n2 As DoubleDim Somma As DoubleRem Primo valoreMessaggioRichiesta = �Primo valore:�Massimo = 10LeggiValoren1 = nRem Secondo valoreMessaggioRichiesta = �Secondo valore:�Massimo = 50LeggiValoren2 = n

Somma = n1 + n2MsgBox (�La somma è � & Somma)

End Sub

Si noti l�uso delle variabili globali per comunicare alla procedurail valore massimo accettabile, nonché il messaggio da visualizzare.Si noti altresì che la routine provvede ad utilizzare un�altra varia-bile globale (n) per restituire il valore letto. Questo primo esempiodi utilizzo di una procedura ha sortito un effetto pressoché delu-dente, in quanto non ha comportato una sensibile semplificazionedel codice. Ciò a causa della necessità di utilizzare delle variabiliglobali per scambiare le informazioni fra i due blocchi di istruzionie dalla conseguente presenza di numerose operazioni di assegna-mento. Al fine di ottenere un consistente miglioramento dellaleggibilità del codice, nonché una sua semplificazione, è necessariomodificare la procedura LeggiValore per fare in modo che sia ingrado di accettare dei parametri, ovvero che permetta di inizializ-zare le variabili MessaggioRichiesta e Massimo nel momento dellasua invocazione, senza che sia richiesto l�uso delle istruzioni diassegnamento.

I PARAMETRIIl metodo più semplice ed efficace per comunicare delle informa-

zioni a una procedura consiste nell�uso dei parametri, ognuno deiquali deve essere dichiarato secondo la sintassi:

[ByVal|ByRef] <nome> As <Tipo>

Un parametro, talvolta detto argomento, per il codice contenutoall�interno della routine equivale a una variabile. Da essa si differen-zia per il fatto che la sua inizializzazione non avviene all�internodella procedura, bensì quando essa è richiamata. Si supponga adesempio di definire la seguente subroutine:

Sub Prova(Param1 As String, Param2 As Integer) MsgBox(Param1 & �-� & Param2)End Sub

Se si digita la riga

Prova �Dev�, 1998

si richiama la procedura Prova e si inizializzano i parametriParam1 e Param2 rispettivamente con la stringa �Dev� e con ilnumero 1998. Il messaggio visualizzato è pertanto il seguente:

Dev-1998

Si noti che un parametro può essere di un qualsiasi tipo baseprevisto da Visual Basic. Come accade per le variabili, se il formatonon è dichiarato, il dato è considerato Variant.

La procedura LeggiValore può pertanto essere riscritta in mododa accettare come parametri il messaggio da visualizzare al mo-mento della richiesta del dato e il valore massimo consentito.

Sub LeggiValore(MessaggioRichiesta As String,Massimo As Integer)

Dim Stringa As String Do

Stringa = InputBox(MessaggioRichiesta)n = Val(Stringa)

Loop Until (n > 0) And (n < Massimo)End Sub

Per effetto di questa modifica, il codice da associare al caricamen-to del form principale si semplifica notevolmente:

Page 102: Corso Visual Basic

PROGRAMMO SUBITO n.8 - SETTEMBRE 1998○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○○ ○ ○ ○ ○ 89

Sub Form_Load()Dim n1 As DoubleDim n2 As DoubleDim Somma As DoubleLeggiValore �Primo valore:�, 10n1 = nLeggiValore �Secondo valore:�, 50n2 = nSomma = n1 + n2MsgBox (�La somma è � & Somma)

End Sub

Le modifiche apportate fanno sì che non sia più necessariodichiarare le variabili globali MessaggioRichiesta e Massimo.

Un�ulteriore semplificazione potrebbe essere introdotta renden-do la procedura in grado di aggiornare automaticamente le varia-bili n1 e n2. Ciò è possibile introducendo un terzo parametro. Laprocedura LeggiValore diventa pertanto la seguente:

Sub LeggiValore(MessaggioRichiesta As String,Massimo As Integer, n As Double)

Dim Stringa As String Do

Stringa = InputBox(MessaggioRichiesta)n = Val(Stringa)

Loop Until (n > 0) And (n < Massimo)End Sub

Il codice da eseguire in fase di caricamento del form diventa:

Sub Form_Load() Dim n1 As Double Dim n2 As Double Dim Somma As Double LeggiValore �Primo valore:�, 10, n1 LeggiValore �Secondo valore:�, 50, n2 Somma = n1 + n2 MsgBox (�La somma è � & Somma)End Sub

L�applicazione ora non necessità più di alcuna variabile globale.

LE MODALITÀ DI PASSAGGIO DEI PARAMETRII parametri possono essere passati a una procedura secondo due

diverse modalità: per valore e per riferimento; la scelta è effettuatautilizzando per ogni singolo parametro in alternativa le clausoleByVal o ByRef.

Passaggio dei parametri per riferimentoNell�esempio precedente, la variabile n è stata passata alla

procedura LeggiValore non per fornire ad essa un�informazio-ne, bensì per fare in modo che sia la routine a restituire un valoreal blocco di istruzioni chiamante. Infatti, nel momento in cui èeseguita la riga

LeggiValore �Primo valore:�, 10, n1

alla variabile n1 non è stato ancora assegnato un valore.Questo compito spetta alla procedura. Si dice allora che lavariabile n1 è stata passata per riferimento, ovverosia che èstato fornito alla procedura l�indirizzo della locazione di memo-ria in cui risiede n1 per fare in modo che il dato in essacontenuto sia modificato. Questo è metodo di passaggio delleinformazioni predefinito in Visual Basic. Quando alla dichiara-zione di un parametro non è anteposta la clausola ByVal, esso è

considerato dall�interprete come passato per riferimento. Èquindi evidente che la clausola ByRef risulta di fatto superflua,in quanto ha solo lo scopo di rendere il codice più rapidamentecomprensibile.

Passaggio dei parametri per valoreSe nella dichiarazione di un parametro si antepone la clausola

ByVal, si stabilisce che l�informazione è passata per valore. Ciòsignifica che la procedura riceve un valore ma non la facoltà divariarlo. In pratica il dato deve essere considerato dalla routinealla stregua di una costante.

In realtà, la procedura può effettuare delle modifiche al valoredel parametro, ma esse non hanno effetto nel blocco chiamante.Ad esempio, si supponga di dichiarare le seguenti procedure:

Sub Prova1(ByVal Testo As String) Testo = Testo & � 5.0� MsgBox TestoEnd Sub

Sub Prova2(ByRef Testo as String) Testo = Testo & � 5.0� MsgBox TestoEnd Sub

Si supponga altresì di dichiarare una variabile di tipo stringadenominata Messaggio e di inserirvi la frase �Visual Basic�. Lariga

Prova1 Messaggio

provoca pertanto la visualizzazione di una finestra in cuiappare la scritta �Visual Basic 5.0�. Il contenuto della variabileMessaggio, tuttavia, non varia, in quanto essa è stata passataper valore.

Al contrario, l�esecuzione della riga

Prova2 Messaggio

provoca la visualizzazione di una finestra perfettamente iden-tica a quella descritta in precedenza, ma comporta anche lamodifica del contenuto della variabile Messaggio.

DUE SEMPLICI ESERCIZIAl fine di verificare la comprensione degli argomenti esposti,

si provi a realizzare una procedura in grado di restituire ilvalore assoluto di un numero intero, usando a tal fine unparametro passato per riferimento. Si realizzi poi una secondaprocedura che richiami la prima per calcolare la somma deivalori assoluti di 3 numeri passati come parametri per valore.

CONCLUSIONIUn uso corretto delle procedure è di fondamentale importanza

per la scrittura di codice leggibile e di facile manutenzione.Inoltre, il loro raggruppamento in librerie permette di crearedei moduli che possono essere riutilizzati nella realizzazione diapplicazioni da parte di uno o più utenti come se si trattasse diestensioni del linguaggio di programmazione.

Maurizio CrespiMaurizio CrespiMaurizio CrespiMaurizio CrespiMaurizio Crespi si occupa principalmente di grafica e multimedia. Svolge lafunzione di responsabile tecnico presso Datanord Multimedia, società specializzatanella realizzazione di software orientato al marketing e all�editoria, per la qualeprogetta e sviluppa applicazioni in C++, Visual Basic, Delphi e Director. Può esserecontattato per e-mail come [email protected].

Page 103: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB09/index.htm[26/09/2010 1:14:19]

Corso di Visual Basic (Parte 9)

di Maurizio Crespi

La nona lezione del corso dedicato alla programmazione in Visual Basic si pone lo scopodi illustrare le funzioni definibili dall'utente e il concetto di ricorsione

Nella scorsa lezione sono state descritte le subroutine e sono stati evidenziati i beneficiche il loro uso dà al programmatore. Questo mese l'argomento sarà ulteriormenteapprofondito con l'introduzione delle funzioni, ovvero di procedure in grado di restituire unvalore senza l'ausilio di una variabile globale o di un parametro passato per riferimento,nonché con la descrizione dell'uso avanzato che è possibile fare di esse. Prima però èopportuno compiere un passo indietro per riportare alla mente i concetti esposti nellaprecedente puntata del corso. Come sempre, il fine è raggiunto mediante l'illustrazionedelle soluzioni degli esercizi in essa proposti.

Le soluzioni degli esercizi della scorsa lezioneSi tratta di due semplicissimi esercizi, il cui scopo è quello di aiutare il lettore ariconoscere la differenza fra la modalità di passaggio dei parametri per valore e quellaper riferimento.

Primo esercizio Il primo esercizio prevede la realizzazione di una procedura in grado di restituire il valoreassoluto di un numero intero per mezzo di un parametro passato per riferimento. Dai testi scolastici è noto che il valore assoluto di un numero è pari ad esso se è positivooppure, in caso contrario, al suo opposto. Volendo fare a meno di ricorrere alla funzioneAbs prevista dalla libreria standard, è possibile effettuare il calcolo per mezzo di unastruttura If. La soluzione dell'esercizio è pertanto la seguente:

Sub ValAssoluto(ByVal Numero As Double, ByRef Risultato AsDouble) If Numero > 0 Then Risultato = Numero Else Risultato = -1 * Numero End If End Sub

Si noti che il numero di cui deve essere calcolato il valore assoluto è fornito allaprocedura tramite un parametro passato per valore. Si supponga ora di voler eseguire la seguente porzione di codice:

r=0 n=45

Page 104: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB09/index.htm[26/09/2010 1:14:19]

ValAssoluto n, r MsgBox(Str$(r))

Un eventuale tentativo da parte della routine di modificare il dato fornitole come primoparametro non ha effetto sulla variabile n posta nel blocco di codice chiamante. Diverso èinvece il discorso per quanto riguarda la variabile r. Essa, infatti, è passata comeparametro per riferimento; la procedura può quindi intervenire direttamente sul suovalore. Ciò permette alla routine di restituire un dato senza far uso di variabili globali.

Secondo esercizio Il secondo esercizio richiede la realizzazione di una procedura in grado di richiamarequella appena illustrata per calcolare la somma dei valori assoluti di 3 numeri passaticome parametri per valore. La soluzione è banale ed è rappresentata dal codice riportatodi seguito:

Sub SommaVAssoluti(ByVal n1 As Double, ByVal n2 As Double, ByVal n3 As Double, ByRef Somma As Double) Dim r1 As Double Dim r2 As Double Dim r3 As Double ValAssoluto n1, r1 ValAssoluto n2, r2 ValAssoluto n3, r3 Somma = r1 + r2 + r3 End Sub

Anche in questo caso, il risultato è restituito al blocco di codice chiamante per mezzo diun parametro passato per riferimento.

Le funzioni Un sensibile miglioramento della leggibilità del codice e della comodità d'uso dellostrumento di sviluppo deriva dalla possibilità di restituire un valore evitando l'uso di unavariabile globale o di un parametro passato per riferimento. Ciò è possibile per mezzodelle funzioni. Il linguaggio prevede una quantità elevatissima di funzioni standard. Adesempio, per calcolare il valore assoluto di un numero, esiste la funzione Abs, che ricevein ingresso un dato numerico e ne restituisce il modulo. La riga

x = Abs(y)

fa sì che alla variabile x sia assegnato il valore assoluto del numero contenuto nellavariabile y. Come accade per le procedure, è possibile incrementare l'insieme dellefunzioni disponibili creandone ad hoc per soddisfare le proprie esigenze. A tal fine ènecessario racchiudere le istruzioni in strutture dichiarate per mezzo della parola chiaveFunction, secondo la sintassi di seguito riportata:

[Public|Private] Function <nome> [(<definizione_parametro_1>, ... <definizione_parametro_n>)] As <tipo> [<dichiarazione_variabili_locali>] <istruzione_1> ... <istruzione_n> <nome>=<valore> End Function

Com'è possibile notare, l'analogia con le procedure è notevole. A differenza di esse, ènecessario indicare un tipo di dati standard al termine della riga di dichiarazione. Essoidentifica il formato in cui deve essere restituito il risultato. È inoltre necessario fare inmodo che all'interno del blocco di codice sia presente una riga che prevedal'assegnamento di un valore a una variabile avente lo stesso nome della funzione. Taledato è quello restituito al blocco chiamante.

Page 105: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB09/index.htm[26/09/2010 1:14:19]

Si supponga di voler realizzare una semplice funzione in grado di moltiplicare un numerointero per 4. Il codice necessario è il seguente:

Function Quadruplo(Numero As Integer) Quadruplo = Numero * 4 End Function

Il valore assunto dal parametro Numero è moltiplicato per 4 e restituito dalla funzione. È possibile utilizzare la struttura appena creata in un'istruzione di assegnamentoscrivendo il suo nome seguito dai parametri posti fra parentesi tonde, come nell'esempioche segue, in cui il risultato della valutazione della funzione Quadruplo è assegnato allavariabile x.

x = Quadruplo(y)

Lo stesso scopo può essere ottenuto anche per mezzo di una procedura dotata di unparametro passato per riferimento. In questo caso il codice è il seguente:

Sub Quadruplo(Numero As Integer, Risultato As Integer) Risultato = Numero * 4 End Sub

In questo caso, volendo assegnare alla variabile x il risultato, è necessario scrivere:

Quadruplo(y,x)

Pur essendo le due soluzioni del tutto equivalenti, appare evidente la maggiore semplicitàdella prima. Si noti che una funzione può restituire un solo valore. Qualora si presentassela necessità di fornire al blocco chiamante più di un'informazione, è necessario ricorrereai parametri passati per riferimento.

Esercizio Si provi a realizzare una funzione in grado di ricevere come parametro una stringaalfanumerica e restituire il valore logico True se essa contiene il nome di un giorno dellasettimana.

La ricorsione Si supponga di voler realizzare una funzione in grado di calcolare il fattoriale di unnumero intero. Ricordando che il fattoriale è definito solo per valori numerici positivi onulli (in quest'ultimo caso giova ricordare che il fattoriale di 0 è 1), è possibile prevederela seguente implementazione:

Function Fattoriale(ByVal n As Integer) As Long Dim i As Integer Dim Risultato As Long If n >= 0 Then Risultato = 1 For i = 2 To n Risultato = Risultato * i Next i Else Risultato = 0 End If Fattoriale = Risultato End Function

Si tratta di una funzione in grado di ricevere come parametro (per valore) un dato di tiponumerico intero e di restituire un long. L'algoritmo prevede dapprima la verifica che ilnumero oggetto di elaborazione sia positivo o nullo; successivamente, esegue un cicloche provvede ad effettuare la serie di moltiplicazioni necessaria per il calcolo del risultato.

Page 106: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB09/index.htm[26/09/2010 1:14:19]

Tale valore è infine assegnato alla funzione per fare in modo che essa lo restituisca. Sinoti che se il dato fornito in ingresso è negativo, la funzione restituisce il valore 0. Ciò èaccettabile, non essendo possibile che il fattoriale di un numero sia nullo; si tratta quindidi un valido indicatore della presenza di un errore. L'algoritmo appena descritto non è l'unico in grado di effettuare il calcolo del fattoriale diun numero. Ad esempio, è possibile scrivere la seguente implementazione:

Function Fattoriale(ByVal n As Integer) As Long If n >= 0 Then If n = 0 Then Fattoriale = 1 Else Fattoriale = n * Fattoriale(n - 1) End If End If End Function

Il numero delle righe di codice si è ridotto, a vantaggio della leggibilità. Tuttavia, a primavista il lettore può rimanere sconcertato dall'uso della funzione Fattoriale all'interno dellapropria definizione. Ciò può apparire come un errore. In realtà, tale tecnica èperfettamente lecita e prende il nome di ricorsione.

Per rendersi conto del corretto funzionamento, si provi ad osservare ciò che avvienecalcolando il fattoriale di un numero qualsiasi, ad esempio 3.

Essendo n pari a 3, la funzione esegue il calcolo

Fattoriale(3)=3*Fattoriale(2)

Ma, analogamente

Fattoriale(2)=2*Fattoriale(1)

e

Fattoriale(1)=1*Fattoriale(0)

Per mezzo di una struttura If , è distinto il caso in cui n è nullo. In questa condizione lafunzione restituisce il valore 1. Quindi,

Fattoriale(3)=3*(2*(1*(1)))

Ciò concorda con la definizione matematica del fattoriale. L'uso della ricorsione permettein alcuni casi di semplificare notevolmente la scrittura di una funzione e di migliorarne altempo stesso la leggibilità. Tuttavia, presenta numerose insidie. Si provi a valutare ilrisultato prodotto dalla riga

Calcola(7)

dove la funzione Calcola è definita come segue:

Function Calcola(n As Integer) As Integer Calcola = n + Calcola(n - 1) End Function

Il risultato è costituito da un errore di sistema. Infatti, non essendo prevista alcunacondizione di uscita, ovvero non esistendo un valore del parametro per cui è restituito unrisultato non dipendente da una successiva chiamata della funzione, si genera unasuccessione di invocazioni di quest'ultima destinata a non avere fine, almeno sinoall'esaurimento dello spazio di memoria dedicato allo stack del sistema. Appare quindi

Page 107: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB09/index.htm[26/09/2010 1:14:19]

evidente una condizione fondamentale che deve essere soddisfatta da tutte le funzioniricorsive: deve sempre essere prevista una condizione di uscita. È bene tuttavia non abusare della ricorsione. Infatti, sebbene in alcuni casi semplifichinotevolmente il compito del programmatore, talvolta può comportare un sensibileaumento della richiesta di risorse da parte del sistema, data la necessità che esso ha dimantenere contemporaneamente attive più istanze della stessa funzione.

Esercizio Si provi a realizzare una funzione che, dato un parametro n intero positivo passato pervalore, sia in grado di restituire la somma dei primi n numeri naturali. A tal fine si facciauso della ricorsione.

La procedura Main Lo studio delle subroutine termina con una procedura un po' particolare, la cui importanzaè tutt'altro che trascurabile. Si tratta della procedura Main. Un'applicazione realizzata in Visual Basic è generalmente dotata di un'interfaccia utentegrafica, in cui l'interazione con gli elementi attivi determina il flusso del programma.Tuttavia, in alcuni casi, soprattutto per la realizzazione di semplici utility in grado dioperare in modo invisibile all'utente, è necessario sopprimere l'interfaccia grafica.Quando ciò avviene, il progetto risulta privo di form. Il codice deve pertanto essere postoaltrove, ovvero all'interno di moduli. Affinché una sequenza di istruzioni sia eseguitaall'avvio di un'applicazione è necessario inserirla all'interno di una procedura denominataMain. Occorre inoltre selezionare tale routine come oggetto di avvio nella finestra delleproprietà del progetto in luogo di un form. Una semplice procedura Main è la seguente:

Sub Main() If Date$ = "12-25-1998" Then MsgBox "Buon Natale" End If End Sub

Si tratta di una piccola applicazione che può essere eseguita automaticamente all'avvio diWindows e che normalmente non fornisce alcun feedback all'utente. Solo il giorno diNatale del 1998 essa ha un effetto visibile, in quanto provvede a visualizzare unmessaggio di auguri. Si noti l'uso della funzione standard Date$ che restituisce unastringa contenente la data corrente. Il ricorso alla procedura Main non è tuttavia riservatosolo alle applicazioni prive di form. A volte può essere utile fare in modo che unprogramma all'avvio sia in grado di valutare una condizione e in base ad essa sceglierefra i form che lo compongono quello che deve essere visualizzato. Si supponga didisporre di una funzione denominata SelezionaForm, di cui saranno trascurati i dettagliimplementativi, in grado di leggere il registro di sistema per determinare la linguautilizzata dalla versione in uso del sistema operativo e di restituire una stringa contenenteuna delle seguenti sequenze alfanumeriche: "Italiano", "Inglese", "Tedesco", "Francese".Si supponga altresì di aver realizzato un progetto caratterizzato dalla presenza di 4 form,differenti fra loro per la lingua in cui sono scritte le etichette che identificano i controlli e diaver dato ad essi rispettivamente i nomi Ita, Ing, Ted, Fra. È allora possibile scrivere unaprocedura Main in grado di avviare il form corrispondente alla lingua presente nelsistema. Il codice è il seguente:

Sub Main() Select Case SelezionaForm() Case "Italiano": Ita.Show vbModal Case "Inglese": Ing.Show vbModal Case "Tedesco": Ted.Show vbModal Case "Francese"

Page 108: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB09/index.htm[26/09/2010 1:14:19]

Fra.Show vbModal End Select End Sub

Si notino alcune particolarità; la funzione SelezionaForm, ad esempio, non prevedeparametri. Affinché sia utilizzabile correttamente, è comunque necessario richiamarlaspecificando le parentesi, sebbene fra esse non sia posto alcun dato o nome di variabile.Si noti inoltre l'uso del metodo Show, che permette di avviare il caricamento e lasuccessiva visualizzazione di un form. L'uso della costante predefinita vbModal accantoad esso stabilisce che la procedura in fase di esecuzione non può passare all'istruzionesuccessiva finché il form risulta visibile. Solo dopo la sua chiusura il flusso delle istruzionipuò riprendere e, non essendo presente altro codice, il programma può terminare.

Conclusioni Le procedure e le funzioni sono strumenti estremamente efficaci, in grado di fornire unnotevole aiuto al programmatore. I moderni linguaggi di programmazione orientati aglieventi, come Visual Basic, si fondano in modo pressoché totale sulla presenza di talistrutture. L'acquisizione della necessaria dimestichezza nel loro uso diventa pertanto un obbligoper colui che desidera sfruttare al meglio le potenzialità dello strumento. Per questomotivo, ancora una volta la lezione si chiude rivolgendo al lettore un invito ad esercitarsisugli argomenti trattati, servendosi a tal fine anche degli esercizi proposti.

Maurizio Crespi si occupa principalmente di grafica e multimedia. Svolge la funzione diresponsabile tecnico presso Datanord Multimedia, società specializzata nellarealizzazione di software orientato al marketing e all'editoria, per la quale progetta esviluppa applicazioni in C++, Visual Basic, Delphi e Director. Può essere contattato per e-

Page 109: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb10/index.htm[26/09/2010 5:12:01]

Figura1 Figura2

Listato1

Corso di Visual Basic

Questo mese il corso dedicato alla programmazione in Visual Basic ha come obbiettivo la gestione deifile di testo, ovvero del più semplice formato di memorizzazione permanente previsto dallo strumento

Microsoft

Corso di Visual Basic - parte X

di Maurizio Crespi

La maggior parte delle applicazioni deve essere in grado di memorizzare delle informazioni su unsupporto di memoria di massa, costituito in genere da un'unità a disco, in modo tale da renderle reperibilinelle sessioni successive. La struttura destinata ad accogliere questi dati, oggetto di studio in questalezione, prende il nome di file.

Le soluzioni degli esercizi proposti nella scorsa lezionePrima di avventurarsi nello studio dei file, è bene focalizzare come di consueto l'attenzione sugli eserciziproposti nello scorso numero. Eccone, in breve, le soluzioni.

Primo esercizioIl primo esercizio prevede lo sviluppo di una funzione booleana in grado di ricevere come parametro unastringa alfanumerica e di restituire True se essa contiene il nome di un giorno della settimana. In casocontrario, il valore ritornato deve essere False. La soluzione, pressoché banale, è la seguente:

Function Giorno(Stringa As String) As BooleanDim Risultato As BooleanSelect Case UCase(Stringa)Case "LUNEDI", "MARTEDI", "MERCOLEDI", "GIOVEDI", "VENERDI", "SABATO", "DOMENICA"Risultato = TrueCase ElseRisultato = FalseEnd SelectGiorno = RisultatoEnd Function

Il valore restituito corrisponde a quello della variabile Risultato, che è aggiornato da una semplicestruttura Select Case effettuata sulla stringa convertita in maiuscolo.

Secondo esercizioIl secondo esercizio prevede la realizzazione di una funzione ricorsiva che, dato un parametro n interopositivo passato per valore, sia in grado di restituire la somma dei primi n numeri naturali. La soluzione èrappresentata dalla funzione Calcola descritta di seguito.

Function Calcola(n As Integer)As LongDim Somma As LongIf n > 0 ThenSomma = n + Calcola(n - 1)End IfCalcola = SommaEnd Function

Se il parametro n ha un valore non nullo, è sommato al risultato dell'applicazione della funzione a n-1.Se invece n è uguale a zero, si verifica la condizione di uscita.

I fileUn file è un agglomerato di informazioni residente su un supporto di memorizzazione di massa, ovverosu un dispositivo caratterizzato dalla capacità di mantenere i dati anche dopo lo spegnimento e ilsuccessivo riavvio del sistema. Di solito si tratta di un'unità a disco fisso o rimovibile. Le informazionicontenute in un file non devono essere necessariamente di tipo omogeneo. Esiste infatti la possibilità dicreare dei file strutturati, in grado cioè di contenere elementi di pari caratteristiche, oppure composti dainformazioni di natura anche profondamente diversa. Visual Basic permette di creare 3 diversi tipi di file,con accesso sequenziale o casuale. In questa lezione sono oggetto di studio le strutture ad accessosequenziale.

Page 110: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb10/index.htm[26/09/2010 5:12:01]

I file ad accesso sequenzialeLe strutture più elementari sono i file ad accesso sequenziale, il cui uso è in genere riservato allamemorizzazione delle informazioni testuali. Si tratta di strutture organizzate in righe, da utilizzare quandosi desidera salvare dei documenti da stampare oppure per la memorizzazione di limitate quantità di dati(come ad esempio quelle riguardanti le impostazioni di un programma). Il vantaggio offerto dai file adaccesso sequenziale è rappresentato dalla semplicità con cui è possibile accedere al loro contenutomediante un qualsiasi editor di testo, come il Blocco Note di Windows. Sono di questo tipo, ad esempio,i file Win.ini e System.ini, contenenti le informazioni riguardanti la configurazione dell'ambiente Windowsa 16 bit. L'organizzazione dei dati, tuttavia, fa sì che le strutture di questo tipo non siano adatte acontenere una grande quantità di informazioni, a causa del dilatarsi dei tempi di accesso dovuto al fattoche la ricerca di un particolare dato può comportare la lettura dell'intero file.

L'apertura di un file sequenzialeUn file, di qualsiasi tipo esso sia, per poter essere utilizzato deve necessariamente essere aperto. Èpossibile effettuare ciò per mezzo del comando Open, la cui sintassi, per le strutture ad accessosequenziale, è la seguente:

Open <percorso_file>[For <modalità>]As [#]<numero_identificatore>[Len=<lunghezza_record>]

dove <percorso_file> è una stringa che identifica il percorso del file che si desidera creare o leggere. Sesi sta usando una versione a 32 bit dello strumento e quindi si sta realizzando un'applicazionefunzionante solo su Windows 95, 98 o NT, è possibile far uso dei nomi di file lunghi. Ciò non èconsentito invece alle applicazioni destinate ad essere compilate con una versione a 16 bit di VisualBasic. In questo caso, occorre adeguarsi al formato previsto da MS-DOS e dalla macchina virtuale a 16bit di Windows, che prevede un massimo di 8 caratteri per i nomi dei file e di 3 per le estensioni. Ilcarattere separatore è in tutti i casi costituito dalla barra retroversa "\".Dopo aver specificato il nome delfile da gestire, è necessario indicare la modalità con cui si desidera accedere ad esso. La scelta è fraInput, Output e Append. Nel primo caso, il file è aperto in lettura, ovvero è utilizzato esclusivamente perreperire delle informazioni senza effettuare su di esse alcuna modifica. È evidente che l'apertura di unfile in questa modalità richiede che esso sia stato in precedenza creato sul disco, altrimenti provoca lanotifica di un errore.Diversamente accade invece per i file aperti in output. In questo caso, infatti, siprovoca la generazione di una nuova struttura e la sovrascrittura del file eventualmente già presente suldisco con il nome specificato dopo la parola chiave Open. Com'è facile intuire, l'accesso in output ha ilfine di permettere la scrittura delle informazioni sui file. In alcuni casi, tuttavia, risulta necessario inserireall'interno di uno di essi dei nuovi dati senza distruggere quelli inseriti in una o più sessioni precedenti.La modalità da utilizzare per raggiungere tale scopo è denominata Append.

Il numero identificatoreDopo aver dichiarato l'uso che si desidera fare del file, è necessario assegnare ad esso un numero, chene costituisce un identificatore univoco. Tale valore deve essere un intero compreso fra 1 e 511 e vaspecificato dopo la parola chiave As. Per le strutture non destinate alla condivisione con altreapplicazioni, è opportuno utilizzare i numeri compresi fra 1 e 255, riservando i rimanenti ai file chedevono essere resi accessibili da più processi nello stesso momento. Si noti che, per compatibilità con illinguaggio BASIC classico, il numero di identificazione si può far precedere dal carattere #.

Il parametro LenL'ultimo parametro che resta da esaminare è quello che definisce la lunghezza di ogni blocco diinformazioni interessato dalle operazioni di lettura o scrittura. Esso è opzionale e rappresenta ladimensione dello spazio di memoria temporanea (denominato buffer) allocato dal sistema. Tale valorenon può essere superiore a 32767.

L'istruzione CloseSe il comando Open rende possibile accedere a un file e crea per esso un identificatore, l'effettocontrario, ovvero il rilascio della struttura e l'eliminazione del numero di riferimento, è sortitodall'istruzione Close. Si supponga di aver aperto un file e di aver assegnato ad esso l'identificatore 1. Lariga

Close #1

determina la fine dell'uso della struttura da parte del programma, pur rendendone possibile la successivariapertura. Il numero di riferimento ritorna così ad essere utilizzabile per la gestione di un altro file.

La lettura di un file di testo

Page 111: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb10/index.htm[26/09/2010 5:12:01]

Si supponga di voler realizzare un'applicazione in grado di visualizzare in una casella di testo ilcontenuto del file di sistema Win.ini. In primo luogo, è necessario disegnare un form analogo a quellorappresentato nella figura 1, in cui è presente una textbox, che si suppone denominata txtTesto. È poinecessario fare in modo che all'avvio del programma essa sia riempita con il testo contenuto nel file daleggere. A tal fine, si può associare il seguente codice all'evento Load del form:

Private Sub Form_Load()Dim Riga As StringtxtTesto.Text = ""Open "c:\windows\win.ini" For Input As #1Do Until EOF(1)Line Input #1, RigatxtTesto.Text = txtTesto.Text & Riga & Chr$(13) & Chr$(10)LoopClose #1End Sub

Dopo aver eliminato i caratteri eventualmente presenti nella textbox, la procedura provvede ad aprire ininput il file, che si suppone contenuto nella cartella "C:\Windows" e ad associargli il numero identificatore1. Tutte le operazioni che in seguito sono effettuate sul file sono prodotte da istruzioni riceventi talevalore come parametro.Il file da leggere è notoriamente composto da testo organizzato in righe. Loscopo dell'applicazione illustrata in questo esempio è di leggere tutte le righe e di copiarle, una diseguito all'altra, nella textbox. A tal fine è necessario creare un ciclo in grado di svolgere le operazioni dilettura. La condizione che deve causare il termine delle iterazioni è rappresentata dal raggiungimentodella fine del file. Ciò si verifica quando tutti i dati sono stati letti. Il file, tuttavia, potrebbe anche esserevuoto. È pertanto necessario fare in modo che il ciclo preveda il test all'ingresso, ovvero che lacondizione sia specificata accanto alla parola chiave Do, al fine di evitare le iterazioni quando essa risultivera già immediatamente dopo l'esecuzione del comando Open.

La funzione EOFUn file sequenziale può essere paragonato a un nastro magnetico. Per sapere se l'ipotetica testina dilettura ha raggiunto la posizione di fine, è necessario ricorrere alla funzione EOF (End Of File), allaquale, come di consueto, va passato come parametro il numero identificatore della struttura a cui sidesidera far riferimento. Il valore restituito è di tipo logico e vale True se è raggiunta la fine del file;ovviamente, in caso contrario, il risultato è False.

La funzione Line InputLa lettura di una riga di un file di testo è effettuata per mezzo dell'istruzione Line Input. Essa prevededue parametri; il primo è costituito ancora una volta dall'identificatore del file su cui è eseguital'operazione. Il secondo, invece, è rappresentato dalla variabile di tipo stringa destinata ad ospitare lariga di testo da leggere. Nell'esempio è stata utilizzata la variabile denominata Riga. In esso, il dato lettoè aggiunto al contenuto della casella testuale per mezzo dell'operatore di concatenazione di stringhe (&).Si noti che per passare alla riga successiva della textbox si fa uso di una sequenza composta dalcarattere di ritorno del carrello (Chr$(13)) e da quello di avanzamento di una riga (Chr$(10)).

La scrittura su un file di testoSi supponga ora di voler realizzare un programma in grado di effettuare l'esatto contrario del precedente,ovvero di trasferire su un file di testo il contenuto di una textbox. La sua implementazione risultaestremamente semplice. In pratica richiede esclusivamente l'uso di un'istruzione Print.Si consideri il formrappresentato in figura 2, caratterizzato dalla presenza di 3 pulsanti. Il primo è denominato btnCarica edha lo scopo di caricare nella textbox txtTesto il contenuto del file di cui è specificato il nome nella casellatxtNomeFile. Un secondo pulsante, denominato btnCancella, ha lo scopo di eliminare il contenuto dellatextbox, mentre il terzo serve per memorizzare in un file le informazioni presenti all'interno del controllotxtTesto. Il codice è riportato nel listato 1. Si noti che la procedura che si occupa del caricamento deidati è pressoché identica a quella dell'esempio precedente; si differenzia solo perché il nome del file daleggere è acquisito dal controllo txtNomeFile, anziché essere fisso. Il salvataggio del file sul disco èeseguito in modo estremamente semplice; in pratica il programma non deve far altro che aprire il lastruttura in output ed eseguire su di essa l'istruzione Print, la quale riceve come parametri,rispettivamente, il numero identificatore e la stringa da scrivere, nella fattispecie costituita dal contenutodel controllo txtTesto.

Un semplice esercizioPer esercitarsi sugli argomenti esposti, si provi a realizzare un'applicazione in grado di leggere, permezzo di opportune textbox, tre valori numerici interi e una stringa. Si preveda poi la possibilità disalvarli in un file in seguito alla pressione di un pulsante. Mediante un altro bottone, si faccia in modoche l'utente possa ripristinare all'interno delle caselle di testo i valori salvati sul disco.

Nella prossima lezione…

Page 112: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb10/index.htm[26/09/2010 5:12:01]

I file di testo sono solo un tipo di struttura di memorizzazione permanente su supporti di memoria dimassa. Visual Basic permette di gestire anche dei file strutturati in modo diverso, adatti per esigenzedifferenti e per realizzazioni più impegnative, quali ad esempio quelle che accedono a una grandequantità di informazioni in modo non conforme a uno schema rigidamente sequenziale come quellodescritto nei paragrafi precedenti. Per sapere com'è possibile fare ciò, occorre semplicemente attenderela prossima lezione.

BibliografiaVisual Basic 5- McGrawHill – ISBN 88-386-0436-3

Page 113: Corso Visual Basic

Figura 1 L

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb10/figura1.htm[26/09/2010 5:12:29]

Figura 1 L'applicazione che visualizza il contenuto del file Win.ini

Page 114: Corso Visual Basic

Figura 2 L

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb10/figura2.htm[26/09/2010 5:12:46]

Figura 2 L'applicazione in grado di eseguire delle operazioni di caricamento e salvataggio dei dati su un file di testo.

Page 115: Corso Visual Basic

Listato 1 Il listato dell

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb10/listato1.htm[26/09/2010 5:12:57]

Listato 1 Il listato dell'applicazione in grado di eseguire delle operazioni di caricamento e salvataggio dei dati su un file di testo.

Private Sub btnCarica_Click() Dim Riga As String Dim NomeFile As String txtTesto.Text = "" NomeFile = txtNomeFile.Text Open NomeFile For Input As #1 Do Until EOF(1) Line Input #1, Riga txtTesto.Text = txtTesto.Text & Riga & Chr$(13) & Chr$(10) Loop Close #1End Sub

Private Sub btnCancella_Click() txtTesto.Text = ""End Sub

Private Sub btnSalva_Click() Dim NomeFile As String

NomeFile = txtNomeFile.Text Open NomeFile For Output As #1 Print #1, txtTesto.Text Close #1End Sub

Page 116: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB11/index.htm[26/09/2010 5:15:21]

Figura1 Figura2

Listato1 Listato2

Corso di Visual Basic(Parte 11)

uesto mese il corso di Visual Basic focalizza l’attenzione sui file ad accesso casuale, che sidistinguono per essere dotati di una struttura rigida; ciò li rende in grado di offrire una maggiorevelocità di accesso alle informazioni

Nella scorsa lezione sono stati presi in considerazione i file di testo, in cui l’accesso alle informazioniavviene in modo sequenziale. Essi presentano un limite, ovvero la scarsa idoneità alla memorizzazione digrandi quantità di dati, a causa dei talvolta elevati tempi di ricerca. In queste condizioni sono spesso preferibili delle strutture più sofisticate, quali ad esempio i file ad accessocasuale, che sono oggetto di studio in questa puntata del corso.Come sempre, tuttavia, prima di affrontare i nuovi argomenti, è opportuno un ripasso dei concetti esposti inprecedenza; lo spunto è fornito dalla correzione dell’esercizio proposto nella scorsa lezione.

La soluzione dell’esercizio proposto nella scorsa lezione

L’esercizio proposto nello scorso numero prevede la realizzazione di un programma in grado di leggere, permezzo di opportune textbox, tre valori numerici interi e una stringa, nonché di offrire la possibilità di salvarequesti dati su richiesta dell’utente. La pressione di un pulsante deve provocare il ripristino all’interno dellecaselle di testo dei valori salvati. Il codice è contenuto nel Listato 1. L’applicazione è composta da dueprocedure; la prima, associata alla pressione del pulsante btnSalva, ha lo scopo di scrivere le informazionisul file Archivio.dat. Si noti che è copiata sul disco solo la parte intera dei numeri; l’eventuale parte decimale, non previstadall’esercizio, è troncata. I dati sono letti dalla procedura associata alla pressione del pulsante btnCarica,che fa uso dell’istruzione Line Input.

I file ad accesso casuale

I file ad accesso casuale sono caratterizzati dall’organizzazione molto rigida in strutture dette record. Un fileè quindi composto da un numero variabile di record accodati. Al fine di comprendere meglio il concetto, sipensi a uno schedario, quale ad esempio l’anagrafica dei clienti di un’azienda. L’archivio è composto daschede aventi tutte la stessa dimensione e contenenti lo stesso tipo di informazione. Ogni schedarappresenta un record.

I record

Per poter inserire in un file più informazioni, anche di tipo non omogeneo, raggruppate in "schede", ènecessario riunirle in un’unica struttura. Si deve quindi creare un nuovo tipo di dati. Tale operazione èeseguita per mezzo della struttura Type, la cui sintassi è:

Type <nome><nome_campo_1> As <tipo_1><nome_campo_2> As <tipo_2>…<nome_campo_n> As <tipo_n>End Type

All’interno della struttura devono essere dichiarati gli elementi che la compongono, che sono denominaticampi. Per ognuno di essi deve essere specificato il tipo di dati che lo caratterizza. I campi possono essereanche di tipo totalmente diverso. Si possono infatti definire dei record contenenti contemporaneamente delleinformazioni di tipo testuale, numerico e logico. Ad esempio, la seguente dichiarazione è corretta:

Type AutomobileMarca As String*50Modello As String*50

Page 117: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB11/index.htm[26/09/2010 5:15:21]

Cilindrata As IntegerDiesel As BooleanEnd Type

Si noti che sono stati dichiarati due campi di tipo alfanumerico, uno di tipo logico e uno numerico intero. Lastruttura è denominata Automobile. In questo modo si è provveduto ad aggiungere un nuovo tipo di dati aquelli standard previsti da Visual Basic. È quindi possibile dichiarare la variabile MiaVettura, di tipoAutomobile digitando:

Dim MiaVettura As Automobile

Riempimento dei campi di un record

Le variabili definite come record prevedono, data la propria conformazione, una modalità di assegnamentodei valori leggermente diversa rispetto a quella prevista dalle strutture convenzionali. In genere, si esegueun’operazione di assegnamento per ogni campo, secondo la sintassi:

<variabile>.<campo> = <valore>

Ad esempio, volendo assegnare il valore 2499 al campo Cilindrata della variabile MiaVettura, definita inprecedenza, occorre scrivere:

MiaVettura.Cilindrata = 2499

L’apertura di un file ad accesso casuale

Come per le strutture sequenziali, l’apertura di un file ad accesso casuale avviene per mezzo dell’istruzioneOpen che, in questo caso, assume la forma:

Open <percorso_file>For RandomAs [#]<identificatore>Len = <lunghezza_record>

dove percorso_file indica il percorso completo del file che si desidera aprire, mentre identificatore costituisceun numero utilizzato per contraddistinguere in modo univoco tale struttura e pertanto va fornito comeparametro a tutti i comandi che sono destinati a gestirla. Si noti che la modalità di accesso è indicata permezzo della parola chiave Random, che deve essere obbligatoriamente specificata, indipendentemente daltipo di operazione che si desidera effettuare sul file, sia essa di lettura o scrittura. Si noti altresì che anche ilparametro Len è obbligatorio. Esso deve contenere l’esatta dimensione del record che costituisce l’unità diinformazione memorizzata nel file. Qualora essa non sia nota, può essere determinata per mezzo dellafunzione Len. Ad esempio, volendo assegnare alla variabile DimRec la dimensione del record MiaVettura, ènecessario digitare:

DimRec = Len(MiaVettura)

Il contenuto della variabile DimRec costituisce il valore da passare come ultimo parametro all’istruzioneOpen per consentire la gestione di un file composto da elementi di tipo Automobile. Analogamente ai filesequenziali, anche le strutture ad accesso casuale devono essere chiuse dopo l’uso per mezzodell’istruzione Close.

La lettura di un record

La lettura di un record contenuto in un file ad accesso casuale avviene per mezzo dell’istruzione Get,caratterizzata dalla seguente sintassi:

Get [#]<identificatore>, <posizione>, <variabile>

dove <identificatore> rappresenta il numero che univocamente identifica il file oggetto dell’operazione dilettura e <variabile> è il nome della variabile in cui i dati letti devono essere posti. Il parametro <posizione>indica la posizione del record da leggere. Si tratta di un valore intero compreso fra 1 e il numero dei recordpresenti nel file. Ad esempio, si supponga di voler accedere al quarto record presente nel file diidentificatore 1 e di voler porre il suo contenuto nella variabile Dato. Ciò è possibile per mezzo della riga:

Get #1, 4, Dato

Solo in un caso il valore del parametro <posizione> può essere omesso; ciò si verifica in occasionedell’effettuazione di operazioni di lettura in sequenza; l’assenza del numero indicante la posizione provoca

Page 118: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB11/index.htm[26/09/2010 5:15:21]

infatti l’accesso al record successivo a quello corrente. Non possono tuttavia essere omesse le virgole diseparazione. Ad esempio, la sequenza

Get #1, 4, DatoGet #1,, Dato1

provoca la lettura del quarto e del quinto record del file identificato dal numero 1.

La scrittura di un record

Per scrivere il contenuto di un record in un file ad accesso casuale è possibile utilizzare l’istruzione Put, lacui sintassi è pressoché identica a quella del comando Get:

Put [#]<identificatore>, <posizione>, <variabile>

In questo caso, la variabile indicata come terzo parametro contiene il dato da scrivere. Ad esempio, la riga

Put #1, 5, Dato

scrive il contenuto della variabile Dato nel quinto elemento del file identificato dal numero 1. Il valoreassunto dal parametro <posizione> assume un’importanza fondamentale, in quanto determina se è aggiuntoun nuovo record all’archivio o se ne è sovrascritto uno già esistente. Quest’ultima evenienza si verificaquando è indicata una posizione già occupata da un elemento. Per aggiungere un nuovo record al file,invece, è necessario indicare un valore pari al numero totale dei record incrementato di un’unità.

La cancellazione logica di un record

Il metodo più semplice per cancellare un record consiste nel sovrascriverlo con un elemento vuoto. Inquesto modo, tuttavia, non è possibile recuperare lo spazio da esso occupato sul disco. Si tratta cioè di unacancellazione logica, non fisica, in quanto Visual Basic non dispone di un’istruzione in grado di rimuovereun record e di recuperare automaticamente lo spazio da esso occupato. È possibile sfruttare a propriovantaggio la possibilità di effettuare solo una cancellazione logica dei record contenuti in un file per fare inmodo che degli elementi eventualmente eliminati per sbaglio possano essere agevolmente recuperati. Ciò èpossibile aggiungendo un campo booleano alla struttura dei record e facendo in modo che il programmache accede all’archivio consideri cancellati tutti gli elementi caratterizzati dal contenere il valore logico Trueall’interno di questo campo. L’eliminazione di un record comporta quindi la semplice variazione del valore diun suo campo. Analogamente, è possibile recuperare un elemento cancellato per errore impostandonuovamente al valore False il campo booleano. La struttura Automobile può pertanto essere modificatacome segue:

Type Automobile1Marca As String*50Modello As String*50Cilindrata As IntegerDiesel As BooleanCancellato As BooleanEnd Type

La cancellazione fisica di un record

Quando la quantità di informazioni da gestire diventa elevata, la necessità di recuperare lo spazio occupatodai record cancellati diventa evidente, sia per evitare lo spreco di spazio sul disco, sia per non ridurredrasticamente i tempi di accesso alle informazioni costringendo il programma a leggere dei dati inutili.Come già osservato in precedenza, Visual Basic non dispone di un’istruzione in grado di provvedereautomaticamente alla cancellazione fisica di un record. Tuttavia, la scrittura di una simile procedura nonpresenta un livello di difficoltà elevato. Essa deve solo creare un nuovo file e copiare al suo interno tutti irecord non vuoti. Successivamente, deve eliminare il primo file ed assegnare il suo nome alla nuovastruttura. È ciò che fa la procedura di seguito descritta, che riceve come parametro il nome del file dacompattare, che si suppone composto da record di tipo Automobile1:

Sub CompattaFile(ByVal NomeFile As String)Dim ID_old As IntegerDim ID_new As IntegerDim Dato As Automobile1Dim Lunghezza As IntegerLunghezza = Len(Dato)ID_old = FreeFileOpen NomeFile For Random As ID_old Len = LunghezzaID_new = FreeFileOpen "Temp.dat" For Random As ID_new Len = Lunghezza

Page 119: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB11/index.htm[26/09/2010 5:15:21]

Do While Not EOF(ID_old)Get ID_old, , DatoIf Not Dato.Cancellato ThenPut ID_new, , DatoEnd IfLoopClose ID_old, ID_newKill NomeFileName "Temp.dat" As NomeFileEnd Sub

Si noti l’uso della funzione FreeFile, che restituisce un numero adatto ad essere utilizzato comeidentificatore di file ed evita così il rischio di utilizzare degli identificatori già in uso in altre parti delprogramma. La procedura provvede a leggere in modo sequenziale il file di cui è specificato il nome comeparametro e a copiare in un file denominato Temp.dat tutti i record per i quali il campo Cancellato assume ilvalore False. Si noti che le operazioni di lettura e scrittura sono eseguite sequenzialmente, in quanto èstato omesso il valore indicante la posizione nelle istruzioni Get e Put. Il ciclo di copiatura termina quandosono esauriti i record da leggere. Quando ciò avviene, la funzione EOF (End Of File), già descritta nellascorsa lezione, restituisce il valore True. Dopo aver copiato tutti i record non cancellati logicamente, laprocedura provvede a chiudere entrambi i file. Si noti che a tal fine utilizza un’unica istruzione Close, in cuigli identificatori dei file da chiudere sono separati da una virgola. Il passo successivo consiste nel sostituireil file originale con quello creato. Ciò comporta l’esecuzione di due operazioni: la cancellazione del file diorigine e la ridenominazione di quello generato dalla procedura. L’eliminazione avviene per mezzodell’istruzione Kill, la cui sintassi è

Kill <Nome_file>

Il file Temp.dat è quindi rinominato per mezzo dell’istruzione Name, che è caratterizzata dalla seguentesintassi:

Name <Vecchio_nome> As <Nuovo_nome>

Un esempio…

Il Listato 2 contiene il codice di un’applicazione in grado di archiviare i dati relativi a dei siti Internet. Perognuno di essi, è possibile indicare l’indirizzo e una breve descrizione. È possibile creare dei nuovi recordvuoti in grado di ospitare i dati relativi a nuovi siti, oppure modificare le informazioni riferite a quelliesistenti, nonché scorrere l’archivio nei due sensi.Il file è composto da record del tipo DatiURL, definito all’inizio. Si noti che la definizione è preceduta dallaparola chiave Private per indicare che il suo campo di validità è limitato al form che la contiene. I recordsono letti e scritti rispettivamente per mezzo delle procedure LeggiRecord e ScriviRecord. La variabileglobale Posizione stabilisce il numero del record da leggere o aggiornare. Si noti la presenza della funzioneContaRecord, che ha lo scopo di calcolare il numero dei record presenti in archivio come rapporto fra ladimensione del file, restituita dalla funzione LOF (Length Of File) e la lunghezza di un singoloelemento.L’apertura del file avviene in corrispondenza dell’avvio dell’applicazione, quindi al verificarsidell’evento Load. Analogamente, per assicurare la chiusura dell’archivio quando cessa l’uso del programma,l’istruzione Close è stata posta fra il codice associato all’evento Unload.

… e un esercizio

Per esercitarsi sui concetti esposti, si provi a modificare l’esempio sopra descritto aggiungendo la possibilitàdi cancellare logicamente e, su richiesta, fisicamente dei record.

Conclusioni

I file rivestono un’importanza fondamentale nella maggior parte delle applicazioni, in quanto consentono ditrattare una quantità di dati superiore a quella che può essere contenuta nella memoria dell’elaboratore.Inoltre, trattandosi di strutture permanenti, permettono di mantenere tali informazioni anche dopo lospegnimento o il riavvio del sistema. L’utilizzo di strutture ad accesso casuale rende ancora più evidenti ivantaggi offerti dai file, permettendo una maggiore flessibilità d’uso.

Maurizio Crespi si occupa principalmente di grafica e multimedia. Svolge la funzione di responsabiletecnico presso Datanord Multimedia, società specializzata nella realizzazione di software orientato almarketing e all’editoria, per la quale progetta e sviluppa applicazioni in C++, Visual Basic, Delphi e Director.Può essere contattato per e-mail come [email protected].

Page 120: Corso Visual Basic

FIGURA 1 L

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB11/figura1.htm[26/09/2010 5:15:28]

FIGURA 1 L'interfaccia della soluzione dell'esercizio proposto nello scorso numero

Page 121: Corso Visual Basic

FIGURA 2 L

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB11/figura2.htm[26/09/2010 5:15:39]

FIGURA 2 L'interfaccia dell'applicazione d'esempio

Page 122: Corso Visual Basic

LISTATO 1 La soluzione dell

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB11/listato1.htm[26/09/2010 5:15:47]

LISTATO 1 La soluzione dell'esercizio proposto nello scorso numero

Private Sub btnSalva_Click()

Dim Numero1 As Integer

Dim Numero2 As Integer

Dim Numero3 As Integer

Dim Stringa As String

Open "archivio.dat" For Output As #1

Numero1 = Int(Val(txtNum1.Text))

Numero2 = Int(Val(txtNum2.Text))

Numero3 = Int(Val(txtNum3.Text))

Stringa = txtStringa.Text

Print #1, Numero1

Print #1, Numero2

Print #1, Numero3

Print #1, Stringa

Close #1

End Sub

Private Sub btnCarica_Click()

Dim Numero1 As String

Dim Numero2 As String

Dim Numero3 As String

Dim Stringa As String

Open "archivio.dat" For Input As #1

If Not EOF(1) Then

Line Input #1, Numero1

Line Input #1, Numero2

Line Input #1, Numero3

Line Input #1, Stringa

txtNum1.Text = Numero1

txtNum2.Text = Numero2

txtNum3.Text = Numero3

Page 123: Corso Visual Basic

LISTATO 1 La soluzione dell

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB11/listato1.htm[26/09/2010 5:15:47]

txtStringa.Text = Stringa

End If

Close #1

End Sub

Page 124: Corso Visual Basic

LISTATO 2 L

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB11/Listato2.htm[26/09/2010 5:15:54]

LISTATO 2 L'applicazione di esempio

Private Type DatiURL

Indirizzo As String * 100

Descrizione As String * 100

End Type

Dim Posizione As Long

Dim LunghezzaRecord As Long

Sub LeggiRecord()

Dim Dato As DatiURL

Get #1, Posizione, Dato

txtURL.Text = Dato.Indirizzo

txtDescrizione.Text = Dato.Descrizione

End Sub

Sub ScriviRecord()

Dim Dato As DatiURL

Dato.Indirizzo = txtURL.Text

Dato.Descrizione = txtDescrizione.Text

Put #1, Posizione, Dato

End Sub

Function ContaRecord() As Long

ContaRecord = (LOF(1) / LunghezzaRecord)

End Function

Private Sub Form_Load()

Dim Dato As DatiURL

LunghezzaRecord = Len(Dato)

Open "archivio.dat" For Random As #1 Len = LunghezzaRecord

Posizione = 1

Page 125: Corso Visual Basic

LISTATO 2 L

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB11/Listato2.htm[26/09/2010 5:15:54]

LeggiRecord

End Sub

Private Sub btnNuovo_Click()

txtURL.Text = ""

txtDescrizione.Text = ""

Posizione = 1 + ContaRecord()

ScriviRecord

End Sub

Private Sub BtnSalva_Click()

ScriviRecord

End Sub

Private Sub btnPrecedente_Click()

If Posizione > 1 Then

Posizione = Posizione - 1

LeggiRecord

Else

Beep

End If

End Sub

Private Sub btnSuccessivo_Click()

If Posizione < ContaRecord() Then

Posizione = Posizione + 1

LeggiRecord

Else

Beep

End If

End Sub

Page 126: Corso Visual Basic

LISTATO 2 L

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB11/Listato2.htm[26/09/2010 5:15:54]

Private Sub Form_Unload(Cancel As Integer)

Close #1

End Sub

Page 127: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB12/index.htm[26/09/2010 5:18:08]

Listato

Corso di Visual Basic

VB-IT: per tutti gli sviluppatori VB o aspiranti taliVB-IT è la mailing list italiana interamente dedicata a Visual Basic, VBA (VisualBasic for Application) e VBScript. Se sei uno sviluppatore esperto oppure tiinteressa il mondo Visual Basic anche solo per diletto, troverai VB-IT utilissima!Consigli, suggerimenti, trucchi, soluzioni a problemi comuni e molto altro. Periscriversi, gratuitamente, a VB-IT è sufficiente inviare un messaggio [email protected] e nel body inserire la stringa: subscribe vb-it. Unavolta iscritto, esponi i tuoi problemi a [email protected] e aiuta gli altri arisolvere i propri. Sarà anche un modo per instaurare nuovi rapporti di lavoro,collaborazione ed amicizia!

uesto mese il corso dedicato a Visual Basic ha come tema lo sviluppo delleapplicazioni in grado di far uso dei database, ovvero di strutture in grado diospitare grandi quantità di dati in modo particolarmente efficiente.

Un database è una struttura residente su un’unità a disco che si caratterizza per la capacità di contenereingenti quantità di dati organizzati in record. Ciò che fa la differenza fra un database e un normale file adaccesso casuale è la presenza di un modulo, detto generalmente database engine, che permette dieffettuare ricerche e inserimenti all’interno dell’archivio in modo semplice e veloce. Esiste quindi uncomponente che si fa carico di tutta la gestione dei dati, lasciando al programmatore il solo compito didefinire i parametri in base ai quali effettuare le operazioni di ricerca. Visual Basic, fin dalle sue origini, hasempre annoverato fra i suoi punti di forza la capacità di agevolare al massimo lo sviluppo delleapplicazioni in grado di gestire dei database. Questa sua caratteristica è andata evolvendosi nel tempo alpunto che oggi è uno degli strumenti più utilizzati nel campo della realizzazione di applicazioni gestionaliche accedono ad archivi locali o posti su un sistema remoto.

Le soluzioni dell’esercizio proposto nella scorsa lezione

Prima di affrontare lo studio dei database, è opportuno come sempre effettuare un breve ripasso di ciò chesi è appreso nella scorsa lezione. Lo spunto è dato dalla correzione dell’esercizio in essa proposto, cheprevede la modifica del programma descritto come esempio, in grado di visualizzare un elenco di sitiInternet, per consentirgli di gestire la cancellazione logica e, su richiesta, fisica dei record. Questi ultimi sono del tipo DatiURL, di cui è di seguito riportata la definizione:

Private Type DatiURLIndirizzo As String * 100Descrizione As String * 100End Type

Per consentire la cancellazione degli elementi, è necessario modificare la struttura aggiungendole un campobooleano, che è utilizzato per contrassegnare i record logicamente rimossi. La definizione del tipo DatiURLdiventa pertanto la seguente:

Private Type DatiURLIndirizzo As String * 100Descrizione As String * 100Cancellato As BooleanEnd Type

Per consentire la cancellazione del record corrente è necessario modificare la procedura ScriviRecord inmodo da tenere conto del nuovo campo.

Sub ScriviRecord(Cancella As Boolean)Dim Dato As DatiURLDato.Indirizzo = txtURL.TextDato.Descrizione = txtDescrizione.TextDato.Cancellato = CancellaPut #1, Posizione, Dato

Page 128: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB12/index.htm[26/09/2010 5:18:08]

End Sub

Si noti che ora accetta un parametro booleano che stabilisce se il record che deve essere scritto sul discodeve essere cancellato logicamente. Il codice da associare alla pressione del pulsante btnCancella, èpertanto il seguente:

Private Sub btnCancella_Click()ScriviRecord TrueEnd Sub

È inoltre possibile inserire un pulsante in grado di recuperare tutti gli elementi cancellati. La sua pressionedeve semplicemente richiamare la procedura Ripristina, composta da un ciclo in grado di leggere tutti irecord presenti in archivio e di riscriverli dopo aver modificato il valore del campo Cancellato.

Private Sub Ripristina()Dim i As LongDim NumElementi As LongDim Dato As DatiURLNumElementi = ContaRecord()For i = 1 To NumElementiGet #1, i, DatoDato.Cancellato = FalsePut #1, i, DatoNext iEnd Sub

La rimozione fisica di tutti gli elementi cancellati può invece avvenire per mezzo della funzioneCompattaFile, che provvede a copiare in un nuovo file tutti i record caratterizzati dal contenere il valoreFalse all’interno del campo Cancellato. Dopo essere stato creato, il nuovo file sostituisce quello di partenza.

Private Sub CompattaFile()Dim Dato As DatiURLDim Lunghezza As LongDim NumElementi As LongDim i As LongNumElementi = ContaRecord()Open "temp.dat" For Random As #2 Len = LunghezzaRecordFor i = 1 To NumElementiGet #1, i, DatoIf Not Dato.Cancellato ThenPut #2, , DatoEnd IfNext iClose #1, #2Kill "archivio.dat"Name "temp.dat" As "archivio.dat"Open "archivio.dat" For Random As #1 Len = LunghezzaRecordEnd Sub

Il codice completo del programma sopra descritto è riportato nel Listato 1. La sua lunghezza si sarebbenotevolmente ridotta se fosse stato utilizzato un database in luogo del file ad accesso casuale. Nel seguitodi questa lezione si vedrà come è possibile fare ciò.

I tipi di database utilizzabili da Visual Basic

Esistono sul mercato molti sistemi di gestione dei database. Ognuno di essi è caratterizzato da un diversomodo di organizzare le informazioni sul disco. Per questo motivo, i file prodotti con tali strumenti presentanospesso dei formati molto diversi. I prodotti più noti sono Microsoft Access e FoxPro, nonché Borland DBasee Paradox. Visual Basic è in grado di gestire tutti questi formati, grazie a dei moduli supplementari denominati ISAM(Indexed Sequential Access Method) che possono essere utilizzati dal motore di gestione dei database surichiesta dell’applicazione. Oltre ai formati gestibili per mezzo dei moduli ISAM, Visual Basic è in grado dileggere e scrivere dei dati anche in strutture di diverso tipo, eventualmente poste su server remoti, grazie alsupporto per la tecnologia ODBC (Open Database Connectivity). Ciò estende notevolmente il campo diutilizzo dello strumento, facendo sì che esso sia in grado di utilizzare qualunque formato di database per ilquale esista un driver ODBC.

La struttura di un database

Le informazioni contenute all’interno di un database, essendo spesso in grande quantità, sono raggruppatein tabelle, al fine di minimizzare lo spreco di spazio sul disco e di agevolare le operazioni di ricerca. Adesempio, supponendo di voler gestire l’inventario di una libreria, sarà necessario conoscere per ciascunlibro almeno il titolo, l’autore, l’editore e lo scaffale che lo contiene. È tuttavia verosimile attendersi che moltieditori abbiano pubblicato più di un libro. Se ad ogni opera è dedicato un record e se in ognuno di essisono presenti anche i dati relativi all’editore, è evidente che le informazioni riguardanti gli editori che hannopubblicato più di un libro sono inutilmente duplicate. L’ingombro degli archivi non risulta pertanto ottimizzatoin relazione ai dati contenuti. Ciò si traduce in uno spreco di spazio sul disco e in una maggior quantità diinformazioni da leggere durante l’effettuazione delle operazioni di ricerca. Inoltre, la presenza di più copiedello stesso dato può portare a problemi di inconsistenza dovuti ad errori di inserimento o alla mancatasincronizzazione in caso di modifica. Per evitare ciò, è conveniente suddividere l’archivio in più strutture,dette tabelle, raggruppando fra loro le informazioni dello stesso tipo. Fra le tabelle è possibile stabilire dellerelazioni. Nel caso della libreria, ad esempio, è possibile inserire i dati relativi agli editori in una tabella a parte edassociare ad ognuno di essi un identificatore univoco. Le altre informazioni relative ai libri possono esserecontenute in una seconda tabella, costituita da record in cui in luogo dei dati relativi agli editori sonopresenti solo i loro identificatori. Ciò fa sì che un’eventuale modifica delle informazioni relative a una casaeditrice, dovute ad esempio ad un cambio di indirizzo o di ragione sociale, comporti la variazione delcontenuto di un solo record e non metta a repentaglio la consistenza dei dati.

L’oggetto data

La gestione dei database in Visual Basic è resa estremamente semplice da uno speciale controllo: l’oggetto

Page 129: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB12/index.htm[26/09/2010 5:18:08]

data. Si tratta di un componente che presenta il caratteristico aspetto illustrato nella Figura 1; come èpossibile osservare, è composto da 4 pulsanti, su cui sono presenti i simboli tipici dei registratori a nastro,posti alle estremità di un’etichetta testuale. Tutte le operazioni che devono essere effettuate sull’archivio devono far riferimento all’oggetto data ad essoassociato. Per poter utilizzare il suddetto componente, occorre assegnare dei valori ad alcune sue proprietà.In primo luogo è necessario specificare il tipo di database che si prevede di utilizzare. Ciò è possibileagendo, per mezzo dell’apposita finestra, sulla proprietà Connect. Il valore predefinito è Access. Infatti, il motore di gestione dei database utilizzato da Visual Basic, denominato Jet, prevede come formatonativo quello di Microsoft Access, che ha la caratteristica di incorporare tutte le informazioni all’interno di unfile di estensione mdb. Scorrendo la lista che appare nella finestra delle proprietà, è possibile osservarel’elenco degli altri formati supportati per mezzo dei driver ISAM. La lunghezza di questa lista è variabile inbase al numero dei moduli installati nel sistema. Si noti che la decisione di utilizzare un formato diverso da quello standard comporta l’aggiunta al disco didistribuzione del necessario modulo ISAM. Dopo averne definito il tipo, è possibile indicare il nome deldatabase. Ciò è possibile agendo sull’attributo DatabaseName. Si noti che, facendo doppio clic sulla vocenella casella delle proprietà, si provoca l’apertura di una finestra che invita a selezionare un file. Nel caso diarchivi contenuti interamente all’interno di un unico file, come quelli in formato Access, esso rappresenta ildatabase da utilizzare. In altri casi, quali ad esempio le strutture di tipo xBase (DBase o FoxPro), in cuiogni tabella è memorizzata sul disco in un file a sé stante caratterizzato dall’estensione dbf, il database ècostituito dalla directory che contiene i dati.Un’altra proprietà a cui è necessario assegnare un valore è denominata RecordSource. Essa devecontenere l’espressione che permette al motore di gestione degli archivi di scegliere la fonte dei dati davisualizzare. Il valore da indicare è il nome della tabella da cui si desidera prelevare le informazioni.

La realizzazione di un programma in grado di accedere a un database

Si supponga di voler realizzare un’applicazione analoga a quella dell’esercizio proposto nella scorsalezione, in grado di visualizzare le informazioni relative a un elenco di siti Internet. Questa volta, tuttavia, sidesidera far uso di un database. L’archivio può essere creato mediante un prodotto come Microsoft Access.Con questo strumento è possibile definire una tabella costituita da record aventi due campi di tipoalfanumerico, denominati Indirizzo e Descrizione. Si supponga di assegnarle il nome TabellaURL e disalvare il database nel file Web.mdb.Il passo successivo consiste nel creare un form, su cui occorre trascinare dalla casella degli strumenti unoggetto di tipo Data. Ad esso si suppone di assegnare il nome dbArchivio. Si procede poi a scegliere ilformato da utilizzare assegnando alla proprietà Connect il valore Access e ad assegnare il corretto valorealla proprietà DatabaseName. A tal fine si seleziona il file Web.mdb per mezzo dell’apposita opzione presente nella finestra delle proprietà.L’ultimo attributo da impostare riguarda la fonte dei dati. Essendo il database composto da una sola tabella, la scelta del valore della proprietà RecordSource èpressoché obbligata. La lista posta nella finestra delle proprietà è infatti composta dalla sola voceTabellaURL. Dopo aver assegnato i valori alle proprietà fondamentali dell’oggetto di tipo data, non resta cheinserire sul form le caselle testuali che permettono la visualizzazione e la modifica dei dati presenti inarchivio. Il loro collegamento al database può essere effettuato senza bisogno di scrivere del codice, inquanto avviene semplicemente impostando le proprietà DataSource e DataField.La proprietà DataSource permette di indicare l’oggetto di tipo data da cui una textbox deve attingere i valorida visualizzare. Nell’apposita finestra è possibile selezionare l’unico valore proposto, ovvero dbArchivio. Laproprietà DataField, invece, permette di indicare il nome del campo da visualizzare. Nel caso dell’esempio, ivalori possibili sono Indirizzo e Descrizione.Senza scrivere alcuna riga di codice, bensì semplicemente seguendo le istruzioni sopra riportate, èpossibile realizzare un’applicazione in grado di visualizzare un archivio di siti Internet, caratterizzata dallapossibilità di scorrere i record agendo sui pulsanti posti all’interno del controllo di tipo data.

Il metodo UpdateControls

L’applicazione creata consente anche la modifica dei dati presenti in archivio. Se il contenuto di almeno unadelle textbox subisce delle variazioni, la pressione di uno dei pulsanti di cui è dotato il controllo dbArchivioprovoca il salvataggio nel database delle informazioni modificate.Si supponga ora di voler aggiungere all’applicazione un pulsante, a cui si dà il nome btnRipristina, in gradodi annullare le eventuali modifiche effettuate accidentalmente. Si tratta in pratica di costringere l’oggettodbArchivio a rileggere il record corrente e a sovrascrivere le informazioni poste nelle textbox collegate. Ciòè possibile semplicemente invocando il metodo UpdateControls. Il codice da associare al pulsante è ilseguente:

Private Sub btnRipristina_Click()dbArchivio.UpdateControlsEnd Sub

La proprietà Recordset

L’insieme dei record presenti in archivio è identificato dalla proprietà Recordset. Si tratta in sintesi di unoggetto su cui è possibile invocare dei metodi per aggiungere, togliere o modificare gli elementi posti nellabase di dati.

L’aggiunta di un record all’archivio

L’aggiunta di un nuovo record all’archivio richiede l’invocazione del metodo AddNew dell’oggetto Recordset.Supponendo di voler inserire nel form il pulsante btnNuovoRecord, il codice da associare alla sua pressioneè il seguente:

Private Sub btnNuovoRecord_Click()dbArchivio.Recordset.AddNewEnd Sub

Dopo aver inserito nelle caselle di testo il contenuto del nuovo record, è necessario trasferirlo nel database.Per fare ciò, occorre eseguire il metodo Update dell’oggetto Recordset. Questa operazione può essere

Page 130: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB12/index.htm[26/09/2010 5:18:08]

effettuata come risposta alla pressione di un pulsante che si suppone denominato btnAggiorna.

Private Sub btnAggiorna_Click()dbArchivio.Recordset.UpdateEnd Sub

La cancellazione di un record

Anche per cancellare un record è sufficiente utilizzare un semplice metodo dell’oggetto Recordset. Si trattadel metodo Delete. Volendo inserire nel form un pulsante in grado di rimuovere il record corrente, ènecessario scrivere il seguente codice:

Private Sub btnCancella_Click()dbArchivio.Recordset.DeleteEnd Sub

Un semplice esercizio

Per esercitarsi sui concetti esposti, si provi a realizzare un programma in grado di gestire una semplicerubrica telefonica.

Conclusioni

L’uso di un database consente il trattamento di cospicue quantità di informazioni in modo molto semplice eveloce. Per questo motivo, la stragrande maggioranza delle applicazioni gestionali ne fa uso. A questo tipodi strutture, data l’importanza che le caratterizza, sarà dedicata anche la prossima lezione. Per agevolarnela comprensione, il lettore è quindi invitato ad esercitarsi sui concetti sopra esposti.

Bibliografia

"Visual Basic 5", McGrawHill, ISBN 88-386-0436-3.

Page 131: Corso Visual Basic

LISTATO 1 Il listato della soluzione dell

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB12/listato1.htm[26/09/2010 5:18:19]

LISTATO 1 Il listato della soluzione dell'esercizio proposto nella scorsa lezione

Private Type DatiURL

Indirizzo As String * 100

Descrizione As String * 100

Cancellato As Boolean

End Type

Dim Posizione As Long

Dim LunghezzaRecord As Long

Private Sub Form_Load()

Dim Dato As DatiURL

LunghezzaRecord = Len(Dato)

Open "archivio.dat" For Random As #1 Len = LunghezzaRecord

Posizione = 1

LeggiRecord

End Sub

Function LeggiRecord() As Boolean

Dim Dato As DatiURL

Get #1, Posizione, Dato

If Not Dato.Cancellato Then

txtURL.Text = Dato.Indirizzo

txtDescrizione.Text = Dato.Descrizione

End If

LeggiRecord = Not Dato.Cancellato

End Function

Sub ScriviRecord(Cancella As Boolean)

Dim Dato As DatiURL

Dato.Indirizzo = txtURL.Text

Dato.Descrizione = txtDescrizione.Text

Page 132: Corso Visual Basic

LISTATO 1 Il listato della soluzione dell

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB12/listato1.htm[26/09/2010 5:18:19]

Dato.Cancellato = Cancella

Put #1, Posizione, Dato

End Sub

Function ContaRecord() As Long

ContaRecord = (LOF(1) / LunghezzaRecord)

End Function

Private Sub Ripristina()

Dim i As Long

Dim NumElementi As Long

Dim Dato As DatiURL

NumElementi = ContaRecord()

For i = 1 To NumElementi

Get #1, i, Dato

Dato.Cancellato = False

Put #1, i, Dato

Next i

End Sub

Private Sub CompattaFile()

Dim Dato As DatiURL

Dim Lunghezza As Long

Dim NumElementi As Long

Dim i As Long

NumElementi = ContaRecord()

Open "temp.dat" For Random As #2 Len = LunghezzaRecord

For i = 1 To NumElementi

Get #1, i, Dato

If Not Dato.Cancellato Then

Put #2, , Dato

Page 133: Corso Visual Basic

LISTATO 1 Il listato della soluzione dell

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB12/listato1.htm[26/09/2010 5:18:19]

End If

Next i

Close #1, #2

Kill "archivio.dat"

Name "temp.dat" As "archivio.dat"

Open "archivio.dat" For Random As #1 Len = LunghezzaRecord

End Sub

Private Sub btnNuovo_Click()

txtURL.Text = ""

txtDescrizione.Text = ""

Posizione = 1 + ContaRecord()

ScriviRecord False

End Sub

Private Sub BtnSalva_Click()

ScriviRecord False

End Sub

Private Sub btnPrecedente_Click()

Dim Termina As Boolean

Do

If Posizione > 1 Then

Posizione = Posizione - 1

Termina = LeggiRecord()

Else

Termina = True

End If

Loop Until Termina

End Sub

Private Sub btnSuccessivo_Click()

Dim Termina As Boolean

Page 134: Corso Visual Basic

LISTATO 1 Il listato della soluzione dell

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB12/listato1.htm[26/09/2010 5:18:19]

Do

If Posizione < ContaRecord() Then

Posizione = Posizione + 1

Termina = LeggiRecord()

Else

Termina = True

End If

Loop Until Termina

End Sub

Private Sub btnCancella_Click()

ScriviRecord True

End Sub

Private Sub btnRipristina_Click()

Ripristina

End Sub

Private Sub btnCompatta_Click()

CompattaFile

End Sub

Private Sub Form_Unload(Cancel As Integer)

Close #1

End Sub

Page 135: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB13/index.htm[26/09/2010 5:21:23]

Figura1 Figura2 Figura3

Questo mese il corso dedicato a Visual Basic è ancora dedicato ai database. Oggetto distudio sono questa volta i metodi dell’oggetto Recordset che permettono di effettuare

delle ricerche all’interno degli archivi

Corso di Visual Basic (Parte 13)

di Maurizio Crespi

database sono insiemi di dati organizzati secondo strutture ben definite, aventi lo scopo di rendereagevole la gestione e la ricerca delle informazioni. Lo studio delle modalità con cui è possibilelocalizzare dei record all’interno di un archivio costituisce lo scopo di questa lezione, che ha comeprotagonista l’oggetto Recordset.

La soluzione dell’esercizio proposto nella scorsa lezione

Come sempre, prima dell’introduzione dei nuovi concetti, è offerta un’occasione di ripasso di quelli giàacquisiti in precedenza. Lo spunto è dato dalla descrizione del programma che costituisce la soluzionedell’esercizio proposto nella scorsa lezione.L’applicazione rappresenta una semplice rubrica telefonica, in grado di consentire l’inserimento di nuovevoci e la cancellazione di quelle eventualmente esistenti. La sua realizzazione prevede dapprima lacreazione di un database per mezzo di un apposito strumento (ad esempio Microsoft Access) el’inserimento in esso di una tabella, a cui si dà il nome Rubrica, caratterizzata dal possedere 7 campi di tipoalfanumerico, denominati Cognome, Nome, Indirizzo, Comune, Telefono, Fax, eMail. Il passo successivoprevede la creazione di un form, su cui va inserito un oggetto di tipo Data, a cui è assegnato il nomedbArchivio. Esso è collegato al database assegnando il nome del file alla proprietà DatabaseName. Inoltre,deve essere collegato alla tabella. Per fare ciò occorre impostare la stringa "Rubrica" come valore dellaproprietà RecordSource. Il form deve poi essere completato con le caselle di testo destinate ad accoglierele stringhe contenute nei campi dei record. Ad ogni textbox deve essere assegnata la stringa "dbArchivio"come valore della proprietà DataSource. Per mezzo dell’attributo DataField è inoltre possibile specificare ilcampo contenente le informazioni da visualizzare. L’applicazione è completata con l’inserimento nel formdei pulsanti che permettono l’aggiunta di un nuovo record, la memorizzazione dei dati in esso inseriti e lacancellazione di un elemento. Per consentire ciò, alla pressione dei tasti deve corrispondere l’invocazione,rispettivamente, dei metodi AddNew, Update e Delete dell’oggetto Recordset. Quest’ultimo, come si èosservato nella scorsa lezione, costituisce una proprietà del componente di tipo Data. Le procedureassociate ai pulsanti btnNuovo, btnCancella e btnAggiorna sono pertanto le seguenti:

Private Sub btnNuovo_Click()dbArchivio.Recordset.AddNewEnd Sub Private Sub btnCancella_Click()dbArchivio.Recordset.DeleteEnd SubPrivate Sub btnAggiorna_Click()dbArchivio.Recordset.Update

End Sub

Il passaggio al primo o all’ultimo record presente in archivio

A volte, per motivi di estetica, si sente la necessità di rendere invisibile all’utente l’oggetto di tipo Data. Inquesti casi occorre inserire nel form dei pulsanti che consentano la selezione degli elementi posti in

Page 136: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB13/index.htm[26/09/2010 5:21:23]

archivio. Per mezzo del metodo MoveFirst dell’oggetto Recordset, è possibile fare in modo che il primo elementopresente in archivio diventi il record corrente. In pratica, il suddetto metodo provoca un effetto analogo aquello della pressione del pulsante posto all’estrema sinistra dell’oggetto Data. Volendo quindi inserire nelform il pulsante btnPrimo, in grado di selezionare il primo record presente in archivio, occorre digitare ilseguente codice:

Private Sub btnPrimo_Click()dbArchivio.Recordset.MoveFirstEnd Sub

Un metodo analogo a quello appena descritto consente invece il posizionamento sull’ultimo record. Il suonome è MoveLast. La procedura da associare al pulsante btnUltimo, in grado di selezionare l’elementoposto in coda all’archivio, è la seguente:

Private Sub btnUltimo_Click()dbArchivio.Recordset.MoveLastEnd Sub

Il passaggio al record successivo o precedente

Anche per accedere ad un record adiacente è necessario utilizzare l’oggetto Recordset. Il metodoMoveNext, infatti, provvede a fare del record successivo il record corrente. Analogamente, il passaggioall’elemento precedente avviene invocando il metodo MovePrevious.Volendo inserire nel form i pulsanti btnPrecedente e btnSeguente, in grado di consentire lo scorrimento deldatabase in entrambi i sensi, occorre digitare il seguente codice:

Private Sub btnPrecedente_Click()If not dbArchivio.Recordset.BOF ThendbArchivio.Recordset.MovePreviousEnd IfEnd SubPrivate Sub btnSeguente_Click()If not dbArchivio.Recordset.EOF ThendbArchivio.Recordset.MoveNextEnd IfEnd Sub

Le proprietà BOF e EOF

Si noti che il frammento di codice sopra riportato provvede a verificare i valori delle proprietà BOF(Beginning Of File) e EOF (End Of File) prima di accedere rispettivamente al record precedente o alsuccessivo. Ciò ha il fine di evitare che siano effettuati dei tentativi di lettura di elementi inesistenti.

La ricerca delle informazioni

Si supponga di voler dotare la rubrica telefonica della possibilità di ricercare dei nominativi. A tal fine, siaggiunge al form il pulsante btnCerca, a cui è associato il seguente codice:

Private Sub btnCerca_Click()Dim Ripeti As BooleanDim Trovato As BooleanDim DaCercare As StringDaCercare = InputBox("Stringa da cercare:")dbArchivio.Recordset.MoveFirstDoTrovato = (txtCognome.Text = DaCercare)Ripeti = Not (dbArchivio.EOF Or Trovato)If Ripeti ThendbArchivio.Recordset.MoveNextEnd IfLoop While RipetiIf Not Trovato ThenMsgBox "Stringa non trovata"End IfEnd Sub

La stringa da cercare, richiesta per mezzo della funzione InputBox, è confrontata con il contenuto delcampo Cognome, associato all’elemento txtCognome. La ricerca avviene in modo sequenziale a partire dalprimo record. La soluzione presentata permette di ricercare il primo record caratterizzato dall’uguaglianzadel contenuto del campo Cognome rispetto alla stringa inserita dall’utente. Tuttavia, il numero delle righe dicodice necessarie per la sua realizzazione è elevato. Ciò è in contrasto con una della caratteristiche chefanno dei database delle strutture pressoché onnipresenti in tutte le applicazioni gestionali, ovvero lapossibilità di effettuare delle ricerche in modo semplice e veloce.In realtà, la capacità che il modulo di gestione dei database in dotazione a Visual Basic ha di effettuare

Page 137: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB13/index.htm[26/09/2010 5:21:23]

ricerche va ben oltre quanto illustrato fino ad ora. Per la localizzazione di elementi fra quelli posti inarchivio, infatti, prevede degli appositi metodi dell’oggetto Recordset, denominati FindFirst, FindLast,FindPrevious, FindNext. Com’è facile intuire dai nomi, FindFirst e FindLast hanno lo scopo di ricercarerispettivamente il primo e l’ultimo elemento in grado di soddisfare il criterio specificato. FindNext eFindPrevious permettono invece rispettivamente la localizzazione del record successivo e del precedentefra quelli in grado di soddisfare una data condizione. La sintassi è pressoché identica per tutti e 4 i metodie prevede un parametro costituito dall’espressione che descrive il criterio di ricerca, secondo lo schema:

<oggetto_data>.Recordset.<comando> "<espressione>"dove <espressione> ha la forma<confronto> [AND | OR <confronto>]. . . [AND | OR <confronto>]e ogni confronto è del tipo<nome_campo> = | <> | > | < | >= | <= LIKE <valore>

in cui <nome_campo> rappresenta il nome del campo da usare come oggetto di ricerca e <valore> indica ilvalore da ricercare. Si noti che ai comuni operatori di confronto (=, >, <, <>, >=, <=) ne è stato aggiunto unaltro, denominato LIKE. Quest’ultimo permette di confrontare due stringhe in modo meno rigido rispetto alnormale operatore di uguaglianza. In sostanza, fa sì che la verifica abbia esito positivo non solo se duestringhe sono identiche, bensì anche quando una costituisce solo l’inizio dell’altra. Per comprendere questoconcetto, si consideri l’esempio che segue.Si supponga di disporre di un database in cui sono presenti dei record aventi fra gli altri un campodenominato Nome. Si supponga che esista un elemento contenente nel campo Nome la stringa "Dev,Developing software solutions". Se l’archivio è accessibile per mezzo dell’oggetto Data1, l’esecuzione delmetodo

Data1.FindFirst "Nome = ’Dev’"

fornisce un esito negativo, in quanto nessun campo denominato Nome contiene esattamente la stringa"Dev". Invece, la riga

Data1.FindFirst "Nome LIKE ’Dev’"

ha esito positivo perché esiste un elemento che contiene una stringa che inizia con la sequenza "Dev". Sinoti che per delimitare le stringhe negli esempi si è fatto uso dell’apice (‘). L’uso di questo carattere puòtalvolta essere causa di problemi, in quanto è spesso utilizzato all’interno delle frasi scritte in lingua italiana.Ad esempio, si osservi la riga

Data1.FindFirst "Nome = ’Viva l’informatica’"

La presenza dell’apostrofo fa sì che la stringa da cercare sia interpretata in modo errato; il motore digestione del database riconosce infatti la sequenza "Viva l". I caratteri mancanti, non essendo riconosciuticome parte della stringa, causano la generazione di un messaggio di errore. Per ovviare a questoinconveniente, è opportuno l’utilizzo delle virgolette (") per delimitare le stringhe da cercare. Per consentireche siano interpretate da Visual Basic correttamente, essendo esse utilizzate anche per racchiudere lastringa che costituisce l’intero criterio di ricerca, occorre raddoppiarle. La riga

Data1.FindFirst "Nome = ""Viva l’informatica"""

ottiene l’effetto desiderato.

La proprietà NoMatch

L’oggetto Recordset è dotato della proprietà NoMatch, che assume un valore booleano che indica sel’ultima ricerca effettuata è andata a buon fine. Dopo aver eseguito una ricerca per mezzo di uno fra imetodi FindFirst, FindLast, FindNext e FindPrevious, è necessario verificare il valore assunto dalla proprietàNoMatch per sapere se il record desiderato è stato trovato oppure se la ricerca non ha avuto successo. Inquest’ultimo caso, la proprietà assume il valore logico True.Si supponga di voler modificare la procedura,descritta in precedenza, associata al pulsante Cerca in modo da far uso del metodo FindFirst. Il codice è ilseguente:

Private Sub btnCerca_Click()Dim DaCercare As StringDim Criterio As StringDaCercare = InputBox("Stringa da cercare:")Criterio = "Nome = """ & DaCercare & """"dbArchivio.Recordset.FindFirstIf dbArchivio.Recordset.NoMatch ThenMsgBox "Stringa non trovata"End IfEnd Sub

Com’è possibile notare, il numero delle righe di codice è diminuito. La nuova procedura si limita a chiedere

Page 138: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB13/index.htm[26/09/2010 5:21:23]

la stringa da cercare ed a comporre il parametro da passare al metodo FindFirst. Una successiva verificadella proprietà NoMatch permette di stabilire l’opportunità della visualizzazione di un messaggio di erroreindicante che la ricerca non ha avuto esito positivo.

Un esempio

Quanto appreso in questa lezione può essere applicato all’esercizio descritto all’inizio dell’articolo. Èpossibile dotare la rubrica telefonica di un completo insieme di opzioni di ricerca dei dati. Il codice checostituisce l’applicazione modificata è visibile nel listato 1 ed è disponibile su Internet per il downloadall’indirizzo http://www.infomedia.it. Com’è possibile osservare in figura, sono stati aggiunti al form unacasella di testo, denominata txtCerca, un pulsante (btnCerca) e 4 option button. La textbox ha lo scopo dicontenere la stringa da cercare nel campo Cognome. Si noti che, per esigenze di semplicità, la ricerca èstata limitata a un solo campo. La modalità di ricerca è richiesta all’utente per mezzo degli option button. Sitratta di pulsanti caratterizzati dall’annullarsi a vicenda. Questo tipo di componenti prende spesso il nomeradio button, in quanto ricorda i comandi che permettono di cambiare la banda di frequenze nelle radio. Permezzo degli option button, l’utente può selezionare una sola modalità di ricerca fra quelle disponibili. Essecorrispondono ai metodi FindFirst, FindLast, FindNext, FindPrevious. La ricerca è avviata dalla pressionedel pulsante btnCerca. Il codice ad esso associato si limita a comporre la stringa che costituisce il criterio diselezione dei record ed a passarla al corretto metodo in funzione dell’option button selezionato,riconosciuto controllando il valori della proprietà value. Se la ricerca non va a buon fine, ovvero se laproprietà NoMatch dell’oggetto Recordset assume il valore logico true, è visualizzato un messaggio dierrore.

Conclusioni

La potenza e la flessibilità dei database permettono di gestire grandi quantità di informazioni. Grazie aimetodi di ricerca, diventa estremamente semplice provvedere alla localizzazione all’interno degli archividelle informazioni desiderate. In attesa di approfondire ulteriormente l’argomento database nel prossimonumero, si provi ad aggiungere alla rubrica telefonica descritta in precedenza la capacità di richiedere unastringa e di contare i record presenti in archivio che contengono nel campo Cognome la sequenzaalfanumerica indicata.

Bibliografia

"Visual Basic 5", McGrawHill, ISBN 88-386-0436-3

Maurizio Crespi si occupa di grafica, multimedialità, amministrazione di reti locali e geografiche, nonchédella progettazione e dello sviluppo di applicazioni in C++, Visual Basic, Delphi e Director. Può esserecontattato tramite Internet all’indirizzo [email protected].

VB-IT: per tutti gli sviluppatori VB o aspiranti tali

VB-IT e' la mailing list italiana interamente dedicata a Visual Basic, VBA (Visual Basic for Application) eVBScript. Se sei uno sviluppatore esperto oppure ti interessa il mondo Visual Basic anche solo per diletto,

troverai VB-IT utilissima!Consigli, suggerimenti, trucchi, soluzioni a problemi comuni e molto altro. Per iscriversi, gratuitamente, aVB-IT è sufficiente inviare un messaggio a [email protected] e nel body inserire la

stringa: subscribe vb-it Una volta iscritto, esponi i tuoi problemi a [email protected] e aiuta gli altri

Page 139: Corso Visual Basic

Figura 1 La soluzione all

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB13/figura1.htm[26/09/2010 5:21:29]

Figura 1 La soluzione all’esercizio proposto nella scorsa lezione

Page 140: Corso Visual Basic

Figura 2 La rubrica telefonica in cui è stato nascosto l

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB13/figura2.htm[26/09/2010 5:21:39]

Figura 2 La rubrica telefonica in cui è stato nascosto l’oggetto di tipo Data

Page 141: Corso Visual Basic

Figura 3 La rubrica telefonica con l

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB13/figura3.htm[26/09/2010 5:21:49]

Figura 3 La rubrica telefonica con l’aggiunta della funzione di ricerca dei cognomi

Page 142: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB14/index.htm[26/09/2010 5:23:38]

Figura1

Listato1

PROGRAMMO SUBITO n.14 - Corso di Visual Basic

Questo mese il corso dedicato a Visual Basic da nuovamente spazio ai database. Oggetto di studio sonoinfatti le modalità che permettono di interrogare una struttura per mezzo del linguaggio SQL

Corso di Visual BasicCome interrogare i database

(Parte 14)

di Maurizio Crespi

Spesso si sente parlare dei database come di strutture che devono essere "interrogate", ovvero dioggetti pressoché attivi in grado di restituire delle informazioni a comando. In realtà ciò che è attivo nonè il database vero e proprio, bensì il motore che lo gestisce. In questa lezione saranno descritte lemodalità con cui è possibile richiedere al modulo responsabile della gestione degli archivi di effettuaredelle ricerche e di fornire dei dati organizzati secondo una struttura differente da quella con cui essi sonomemorizzati sul disco.

La soluzione dell'esercizio proposto nella scorsa lezione

Come sempre, prima di introdurre i nuovi argomenti, sarà presentata la soluzione dell'esercizio propostonella scorsa lezione. Nello numero precedente, è stato descritto un programma in grado di gestire unasemplice rubrica telefonica. L'esercizio ne prevede la modifica con l'aggiunta di un pulsante in grado dicontare gli elementi dell'archivio contenenti nel campo Cognome una sequenza di caratteri indicatadall'utente. Supponendo di assegnare al nuovo tasto il nome btnConta, il codice che deve essereassociato alla sua pressione è il seguente:

Private Sub btnConta_Click()Dim Criterio As StringDim Contatore As Integer

Contatore = 0Criterio = "Cognome LIKE ""*" & txtCerca.Text & "*"""dbArchivio.Recordset.FindFirst (Criterio)Do While Not dbArchivio.Recordset.NoMatchContatore = Contatore + 1dbArchivio.Recordset.FindNext (Criterio)LoopMsgBox "Sono stati trovati " & Contatore & " record"End Sub

Per leggere la stringa da cercare si fa uso della casella di testo txtCerca, già presente nell'applicazionein quanto usata dal codice associato alla pressione del tasto di ricerca (btnCerca). Si noti il criterio diselezione, basato sull'operatore LIKE. Per fare in modo che siano trovati tutti i record che contengano lascritta inserita dall'utente in una qualsiasi posizione, occorre introdurre prima e dopo la sequenza dacercare il carattere jolly *. La stringa che costituisce il criterio di ricerca, supponendo di aver digitato nellacasella txtCerca la sequenza "Dev", è la seguente:

Cognome LIKE "*Dev*"

L'asterisco è in grado di sostituire un numero variabile di caratteri. Ciò significa che sono consideraterispondenti al criterio tutte le stringhe costituite da una sequenza qualsiasi, eventualmente nulla, seguitadalla parola "Dev" e da un'altra sequenza qualsiasi, anch'essa eventualmente nulla.Per mezzo del metodo FindFirst dell'oggetto Recordset associato all'archivio, è ricercato il primo recordche soddisfa il criterio. Un ciclo, che si interrompe solo quando la proprietà NoMatch diventa positiva,ovvero quando non sono più trovati elementi corrispondenti ai parametri di ricerca indicati, fa sì che siapiù volte invocato il metodo FindNext, che provoca la lettura del successivo elemento soddisfacente i

Page 143: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB14/index.htm[26/09/2010 5:23:38]

criteri. Il codice dell'applicazione completa è riportato nel listato 1.

Cosa significa "interrogare un database"

Un'applicazione che fa uso di un database percepisce tale struttura come attiva, cioè in grado dirispondere a delle richieste. Il programmatore può infatti creare diverse viste dell'archivio, scegliendo soloi campi desiderati e ordinando i record secondo le proprie preferenze. La creazione di una vista noncambia la conformazione fisica del database, bensì comporta la generazione di una struttura logicapersonalizzata che permette all'applicazione che accede all'archivio di avere di esso una visioneadeguata alle proprie esigenze. Una struttura logica di questo tipo prende il nome di dynaset(abbreviazione di dynamic set, ovvero insieme dinamico) e l'operazione che porta alla sua creazione è ingenere detta interrogazione del database.

e query

Un termine che si usa spesso quando si parla di database è costituito dalla parola query. Una query nonè altro che un'interrogazione del database, ovvero l'estrazione da esso dell'insieme costituito dai dati ingrado di soddisfare delle condizioni specificate. Una query quindi rappresenta un'operazione effettuatasull'archivio secondo delle modalità ben precise, che sono descritte tipicamente per mezzo di una stringacontenente un testo composto da nomi di elementi del database correlati per mezzo di parole chiaveappartenenti ad un linguaggio particolare (esso è detto in genere linguaggio di interrogazione o, dagliamanti della lingua inglese, query language). Sulla scena esistono molti linguaggi di questo tipo. Inpassato, infatti, ogni motore di database tendeva a possedere un proprio linguaggio di interrogazioneproprietario. Col passare del tempo, tuttavia, l'esigenza di creare uno standard che permettesse dioperare con prodotti diversi riducendo al minimo i costosi corsi di formazione si è sempre più fattasentire. I moderni strumenti, quindi, sono andati via via adeguandosi alle richieste dell'utenza e oggi,sebbene sopravvivano ancora molti linguaggi proprietari, si può affermare che lo standard mondiale,almeno per alcune categorie di prodotti, sia costituito dallo Structured Query Language (linguaggiostrutturato di interrogazione), il cui nome è noto ai più sotto forma di sigla (SQL). I vantaggi principaliofferti da questo linguaggio sono rappresentati dalla semplicità, dalla notevole potenza e dalla portabilitàda uno strumento di gestione dei database a un altro. Quest'ultima caratteristica non è tuttavia valida al100%, in quanto spesso si possono osservare delle piccole variazioni fra i linguaggi previsti dai variprodotti.

Il linguaggio SQL

Il linguaggio SQL rappresenta uno standard per tutti i recenti prodotti Microsoft in grado di accedere adei database. Anche il motore di gestione degli archivi integrato in Visual Basic non si sottrae questaregola.Per mezzo di una stringa SQL è quindi possibile definire la struttura logica, i requisiti, nonchél'ordinamento dei record che devono essere utilizzati da un controllo di tipo data.L'istruzione SQL di più frequente utilizzo è denominata SELECT. La sua sintassi è la seguente:

SELECT <elenco_campi>;FROM <tabella>dove <elenco_campi> ha la sintassi:<campo_1>[,<campo_2>,…, <campo_n>]

Per mezzo dell'istruzione SELECT è possibile specificare un elenco di campi che costituisce la strutturalogica da attribuire ai record da prelevare dal database. La tabella in cui essi sono contenuti èspecificata dopo la clausola FROM.Ad esempio, si supponga di disporre di un database denominato VeicoliAziendali, in cui ciascun recordcontiene tutte le informazioni riguardati un veicolo aziendale. All'atto dell'acquisto di una nuovaautomobile, in archivio sono inserite tutte le informazioni atte a identificarla in modo preciso. Il databasedeve pertanto prevedere una tabella, che si supporrà denominata Automobili, in cui sono presenti deicampi in grado di ospitare la marca, il modello, la versione, il numero di telaio, la targa, il numero delcontratto di assicurazione, la data di immatricolazione, ecc.Si supponga di voler realizzare un'applicazione che consenta al responsabile della gestione del parcoveicoli di verificare quali autovetture hanno superato i 5 anni di età e necessitano quindi di esseresostituite. È evidente che un'applicazione di questo tipo necessita per ogni veicolo delle informazionirelative all'anno di immatricolazione, al numero identificativo attribuito dall'azienda e al nominativo dellapersona a cui è stato affidato. Sicuramente non risulta utile conoscere il colore del l'auto, né il numero ditelaio o la scadenza del contratto di assicurazione. Per fare in modo che sia caricata in memoria unaminore quantità di informazioni, rendendo meno gravoso il compito del sistema e agevolando leoperazioni di debug al programmatore, è possibile fare in modo che il controllo di tipo data preposto alla

Page 144: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB14/index.htm[26/09/2010 5:23:38]

lettura delle informazioni abbia una percezione dell'archivio diversa da quella reale, ovvero sia in gradodi leggere dei record composti dai soli campi necessari. Ciò è possibile provvedendo a fornire all'oggettola stringa SQL:

SELECT Anno, Numero, Utente; FROM Automobili

Tale sequenza fa sì che il modulo di accesso ai dati provveda a creare un recordset composto da recordcaratterizzati dalla presenza dei soli 3 campi Anno, Numero, Utente. I dati sono prelevati dalla tabellaAutomobili. L'applicazione può eseguire qualsiasi operazione sugli elementi del dynaset, ivi compresa lamodifica dei contenuti o la loro cancellazione. Naturalmente, le informazioni poste nella tabella diprovenienza sono costantemente mantenute sincronizzate con quelle presenti nel dynaset, per cui ognioperazione effettuata sulla struttura logica influenza l'archivio memorizzato fisicamente sul disco.Per poter rendere ancora più veloce l'applicazione e per semplificare ulteriormente il compito delprogrammatore, sarebbe senz'altro utile disporre di un archivio costituito esclusivamente dai record chedescrivono i veicoli che hanno almeno 5 anni. In tal modo, non sarebbero necessari altri controlli sui datie il programma dovrebbe semplicemente limitarsi a visualizzare sequenzialmente tutti gli elementi fornitidal motore di gestione del database. Per mezzo della clausola WHERE, da utilizzare in combinazionecon l'istruzione SELECT, è possibile fare in modo che il programma veda i dati relativi ai veicoli piùanziani come contenuti all'interno di una tabella ad hoc, sebbene in realtà siano posti nella stessastruttura che contiene le informazioni relative alle altre vetture. La sintassi è la seguente:

SELECT <elenco_campi>;FROM <tabella>;WHERE <condizione>

dove <condizione> rappresenta un'espressione di confronto valida, definita secondo lo schema

<confronto> [And|Or <confronto>… And|Or <confonto>]

<confronto> è definito come

<campo> =|<>|<|>|<=|>=|Like [<valore>|<campo>]

oppure

<campo> Between <valore> And <valore>

L'uso della clausola WHERE implica la presenza di un criterio di scelta, che è descritto da una o piùcondizioni combinate per mezzo dei canonici operatori logici. Si noti che oltre ai tipici operatori diconfronto è possibile utilizzare la parola Between per verificare l'appartenenza del contenuto di uncampo a un preciso intervallo di valori.Ad esempio, volendo estrarre dall'archivio delle vetture aziendali tutti i veicoli immatricolati prima del1995, è necessario effettuare una query descritta dalla stringa

SELECT Anno, Numero, Utente; FROM Automobili;WHERE Anno<1995

I campi indicati nei criteri di selezione non devono necessariamente essere menzionati anche dopo ilcomando SELECT. Nel caso della query

SELECT Anno, Numero, Utente; FROM Automobili;WHERE (Anno<1995) And (Tipo='Station Wagon')

non ha alcun senso prelevare il campo Tipo dall'archivio, in quanto la condizione indicata fa sì che possasolo essere costituito dalla stringa "Station Wagon".Osservando la frase SQL appena descritta, si puònotare che il criterio di scelta è costituito da due condizioni racchiuse fra parentesi e combinate permezzo dell'operatore logico And. L'uso delle parentesi, sebbene spesso non sia obbligatorio, risultaconsigliabile in presenza delle parole chiave And e Or al fine di favorire la leggibilità de codice. Inoltre, lastringa alfanumerica da confrontare con il contenuto del campo Tipo è racchiusa fra apici. In alcuni casi,ad esempio in presenza di frasi contenenti degli apostrofi, può rivelarsi necessario l'utilizzo di un diversodelimitatore per le stringhe. L'alternativa è costituita dall'uso delle virgolette (").

Page 145: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB14/index.htm[26/09/2010 5:23:38]

La selezione di tutti i campi

Talvolta si rivela necessario utilizzare una query per leggere tutti i record che soddisfano una condizionesenza che sia necessario variare la loro struttura logica, ovvero rendendo disponibili all'applicazione tutti icampi che li compongono. In questi casi, può risultare scomodo dover fornire l'elenco completo dei campidopo la parola SELECT, soprattutto se il loro numero è elevato. È allora possibile utilizzare il carattere *,che significa tutti i campi.

La stringaSELECT *; FROM Automobili;WHERE Anno<1995

crea pertanto una query che provvede a prelevare dal database tutti i campi di tutti i record presenti nellatabella Automobili che sono caratterizzati dal contenere un valore inferiore a 1995 nel campo Anno.

Un esempio…

Si supponga di voler realizzare un'applicazione in grado di estrarre da un archivio di auto aziendali,contenuto in una tabella denominata Automobili, l'elenco dei veicoli immatricolati nell'anno 1998. Sisupponga che nell'archivio esistano almeno i campi Anno, Targa, Modello, Sede, contenentirispettivamente le informazioni riguardanti l'anno di immatricolazione, la targa, il modello e la sede allaquale il veicolo è stato assegnato.Come sempre, il primo passo da compiere riguarda la creazione di un form, in cui è necessario inserireun oggetto di tipo data, utilizzato per leggere le informazioni contenute nel database e quattro etichette,destinate ad accogliere i dati contenuti nei campi. Come per tutte le altre applicazioni facenti uso deidatabase, occorre collegare l'oggetto di tipo data, a cui sarà dato il nome Query, all'archivio. Il passosuccessivo consiste nel collegare all'elemento Query le etichette testuali usate per visualizzare ilcontenuto dei campi Anno, Targa, Modello e Sede. Si agisce quindi come se si volesse realizzareun'applicazione in grado di leggere sequenzialmente tutti i record dell'archivio. La differenza rispetto a unprogramma di questo tipo consiste esclusivamente nel valore assunto dalle proprietà RecordsetType eRecordSource dell'oggetto di tipo Data. La prima deve essere impostata al valore Dynaset in luogo diTable (tabella), mentre la seconda, anziché contenere il nome della tabella da cui devono essereprelevati i dati, deve ospitare la stringa SQL che descrive la query da effettuare, ovvero:

SELECT Anno, Targa, Modello, Sede; FROM Automobili;WHERE Anno=1998

Conclusioni

La possibilità di eseguire su un archivio locale o remoto delle query descritte da stringhe in linguaggioSQL fa di Visual Basic uno strumento particolarmente indicato per gestire i database. Non è quindi uncaso che il prodotto Microsoft si stia sempre più affermando come uno degli strumenti standard per larealizzazione di software gestionale in ambiente Windows. Data l'importanza dell'argomento, anche laprossima lezione di questo corso sarà dedicata alla realizzazione e alla gestione delle query. Persaperne di più, al lettore non resta che attendere il prossimo numero…

Bibliografia

"Visual Basic 5", McGrawHill, ISBN 88-386-0436-3

Maurizio Crespi si occupa di grafica, multimedialità, amministrazione di reti locali e geografiche, nonchédella progettazione e dello sviluppo di applicazioni in C++, Visual Basic, Delphi e Director. Può esserecontattato tramite Internet all'indirizzo [email protected].

VB-IT: per tutti gli sviluppatori VB o aspiranti tali

VB-IT e' la mailing list italiana interamente dedicata a Visual Basic, VBA (Visual Basic for Application) eVBScript. Se sei uno sviluppatore esperto oppure ti interessa il mondo Visual Basic anche solo perdiletto, troverai VB-IT utilissima!Consigli, suggerimenti, trucchi, soluzioni a problemi comuni e molto altro. Per iscriversi, gratuitamente, aVB-IT è sufficiente inviare un messaggio a [email protected] e nel body inserire la stringa:subscribe vb-it

Page 146: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB14/index.htm[26/09/2010 5:23:38]

Una volta iscritto, esponi i tuoi problemi a [email protected] e aiuta gli altri a risolvere i propri. Sarà

Page 147: Corso Visual Basic

Figura 1 L

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB14/figura1.htm[26/09/2010 5:23:45]

Figura 1 L’interfaccia utente della soluzione all’esercizio proposto nella scorsa lezione

Page 148: Corso Visual Basic

LISTATO 1 Il listato del programma che gestisce una rubrica telefonica

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB14/listato1.htm[26/09/2010 5:23:52]

LISTATO 1 Il listato del programma che gestisce una rubrica telefonica, soluzione dell’esercizio proposto nella scorsa lezione

Private Sub btnAggiorna_Click() dbArchivio.Recordset.UpdateEnd Sub

Private Sub btnCancella_Click() dbArchivio.Recordset.DeleteEnd Sub

Private Sub btnCerca_Click() Dim Criterio As String Criterio = "Cognome LIKE """ & txtCerca.Text & "*""" If obPrecedente.Value Then dbArchivio.Recordset.FindPrevious Criterio ElseIf obProssimo.Value Then dbArchivio.Recordset.FindNext Criterio ElseIf obPrimo.Value Then dbArchivio.Recordset.FindFirst Criterio Else dbArchivio.Recordset.FindLast Criterio End If If dbArchivio.Recordset.NoMatch Then MsgBox "Elemento non trovato" End IfEnd Sub

Private Sub btnNuovo_Click() dbArchivio.Recordset.AddNewEnd Sub

Private Sub btnPrecedente_Click() If Not dbArchivio.Recordset.BOF Then dbArchivio.Recordset.MovePrevious End IfEnd Sub

Private Sub btnPrimo_Click() If Not dbArchivio.Recordset.BOF Then dbArchivio.Recordset.MoveFirst End IfEnd Sub

Private Sub btnSeguente_Click() If Not dbArchivio.Recordset.EOF Then dbArchivio.Recordset.MoveNext End IfEnd Sub

Private Sub btnUltimo_Click() If Not dbArchivio.Recordset.EOF Then dbArchivio.Recordset.MoveLast End IfEnd Sub

Private Sub btnConta_Click() Dim Criterio As String Dim Contatore As Integer Contatore = 0 Criterio = "Cognome LIKE ""*" & txtCerca.Text & "*""" dbArchivio.Recordset.FindFirst (Criterio)

Page 149: Corso Visual Basic

LISTATO 1 Il listato del programma che gestisce una rubrica telefonica

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB14/listato1.htm[26/09/2010 5:23:52]

Do While Not dbArchivio.Recordset.NoMatch Contatore = Contatore + 1 dbArchivio.Recordset.FindNext (Criterio) Loop MsgBox "Sono stati trovati " & Contatore & " record"End Sub

Page 150: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB15/index.htm[26/09/2010 5:25:26]

Figura1 Figura2

Listato1

Programmo Subito - 2 Livello - Corso di Visual Basic

Anche questo mese il corso dedicato a Visual Basic dà spazio ai database, con la trattazione di alcuneclausole previste dal comando SQL SELECT

Corso di Visual BasicLe query SQL

(parte XV)

di Maurizio Crespi

Continua la trattazione della gestione dei database in Visual Basic. Questo mese sono ancoraprotagoniste la query e in particolare alcune utili clausole previste dal comando SQL SELECT. Nonmancherà, inoltre, un’occasione per rivedere i concetti esposti nelle ultime 10 lezioni di questo corso.

L’ordinamento dei dati risultanti dall’esecuzione di una query

Spesso si rivela opportuno fare in modo che i dati risultanti dall’esecuzione di una query siano presentatisecondo un particolare ordine. Ad esempio, si supponga di disporre di un database contenente i datianagrafici di tutti gli abitanti di un piccolo comune e di voler creare un’applicazione che permetta diestrarre l’elenco degli abitanti che nel corso del 1999 hanno compiuto o compieranno il diciottesimo annodi età. Si supponga che l’archivio preveda una tabella denominata Anagrafica, composta da recordcontenenti i campi Nome, Cognome, Indirizzo, AnnoNascita. Per estrarre dall’archivio tutti i nati nell’anno1981 è necessaria una query descritta dalla seguente stringa SQL:

SELECT Nome, Cognome, IndirizzoFROM AnagraficaWHERE AnnoNascita=1981

Generalmente, quando si gestiscono delle anagrafiche, si tende ad agevolare l’utente presentando inominativi in ordine alfabetico. La query descritta dalla stringa sopra menzionata non garantisce che ciòavvenga, in quanto non impone alcuna condizione in merito all’ordinamento dei dati.Per fare in modo che essi siano presentati secondo un preciso ordine, è necessario introdurre unaclausola aggiuntiva. La sintassi del comando SELECT diventa pertanto la seguente:

SELECT <elenco_campi>FROM <nome_tabella>[WHERE <condizione>][ORDER BY <ordinamento>]

dove <ordinamento> è descritto da

<ordinamento> = <campo 1> [, <campo 2>, ..., <campo n>]

Il primo campo indicato dopo la clausola ORDER BY è quello secondo il quale è effettuato il primoordinamento dei dati. Qualora alcuni record prevedano valori analoghi all’interno dell’elementospecificato, essi sono ordinati fra loro in base al valore contenuto nel campo indicato dopo la virgola. Incaso di ulteriore analogia fra alcuni record, essi sono ordinati fra loro in base al valore dell’eventualeterzo campo, ecc. Si noti che è obbligatorio indicare un nome di un campo dopo la clausola ORDER BY,mentre i successivi elementi sono facoltativi.Per chiarire il concetto, si osservino gli esempi riportati di seguito. Si supponga di applicare la querydescritta dalla stringa

SELECT Nome, CognomeFROM AnagraficaWHERE AnnoNascita=1981

al database contenente tutti gli abitanti di un piccolo comune.

Un possibile risultato è il seguente:

Rossi MarcoBianchi LuciaRossi Alessandro

Page 151: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB15/index.htm[26/09/2010 5:25:26]

Verdi MarcoRossi DavideGialli Claudia

Come si può notare, i dati non sono ordinati in base al contenuto dei campi.Si supponga ora di applicareallo stesso archivio la query:

SELECT Nome, CognomeFROM AnagraficaWHERE AnnoNascita=1981ORDER BY Cognome

In questo caso, il risultato è il seguente:

Bianchi LuciaGialli ClaudiaRossi DavideRossi Marco Rossi AlessandroVerdi Marco

Ora i nominativi sono ordinati per cognome. Si noti però che è assente l’ordinamento per nome nel casodi individui caratterizzati dallo stesso cognome. Per sopperire a ciò è possibile applicare la seguentequery:

SELECT Nome, CognomeFROM AnagraficaWHERE AnnoNascita=1981ORDER BY Cognome, Nome

Questa volta, i dati sono presentati nel modo corretto:

Bianchi LuciaGialli ClaudiaRossi AlessandroRossi DavideRossi Marco Verdi Marco

Ordinamento decrescente.

In mancanza di indicazioni contrarie, l’ordinamento avviene in modo crescente in base ai valori assuntidai campi indicati dopo la clausola ORDER BY. Si supponga ora di voler effettuare una query analogaalla precedente ma tale da fare in modo che l’ordinamento rispetto al campo Cognome sia decrescente.In questo caso, al nome del campo deve essere fatta seguire la parola DESC. Ad esempio, la stringa

SELECT Nome, CognomeFROM AnagraficaWHERE AnnoNascita=1981ORDER BY Cognome DESC, Nome

fornisce il seguente risultato:

Verdi MarcoRossi AlessandroRossi DavideRossi Marco Gialli ClaudiaBianchi Lucia

Come si può notare, l’ordinamento è decrescente solo rispetto al campo dopo il cui nome è stataspecificata la parola DESC, abbreviazione di descending. Per fare in modo che l’ordinamento siadecrescente anche nei confronti del campo Nome, è necessario quindi scrivere la seguente stringa SQL:

SELECT Nome, CognomeFROM AnagraficaWHERE AnnoNascita=1981ORDER BY Cognome DESC, Nome DESC

Il risultato è costituito dalla sequenza:

Verdi MarcoRossi Marco Rossi DavideRossi AlessandroGialli ClaudiaBianchi Lucia

Page 152: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB15/index.htm[26/09/2010 5:25:26]

Query senza duplicati

Si supponga che per scopi statistici si debba produrre un elenco dei nomi di persona utilizzati nell’anno1981 per iscrivere i nuovi nati all’anagrafe.

Ciò è possibile eseguendo sull’archivio la query descritta dalla stringa

SELECT NomeFROM AnagrafeWHERE AnnoNascita=1981ORDER BY Nome

Il risultato è costituito dai seguenti valori:

AlessandroClaudiaDavideLuciaMarcoMarco

Si noti che il nome "Marco" è duplicato. Infatti, come si è visto in precedenza, vi sono due individuiomonimi. Nel caso dell’esempio, l’esistenza di un voce duplicata nel risultato rappresenta un fattoindesiderato. Per evitare che ciò avvenga, è possibile far uso della clausola DISTINCT. La sintassi delcomando SQL SELECT diventa:

SELECT [DISTINCT ] <elenco_campi>FROM <nome_tabella>[WHERE <condizione>][ORDER BY <ordinamento>]

La query da effettuare è quindi descritta dalla stringa:

SELECT DISTINCT NomeFROM AnagrafeWHERE AnnoNascita=1981ORDER BY Nome

e il risultato è il seguente:

AlessandroClaudiaDavideLuciaMarco

Un esempio

Il Listato 1 costituisce il codice sorgente di una semplice applicazione in grado di comporre ed eseguireuna query SQL sul database descritto negli esempi precedenti. I file sono scaricabili da Internetall’indirizzo ftp://ftp.infomedia.it/pub/DEV./Listati. Il programma permette di selezionare, per mezzo dicheckbox, i campi da visualizzare. Con l’ausilio di alcuni option button, inoltre, consente di stabilire icriteri di ricerca e di ordinamento. I risultati sono visualizzati in una listbox. Si noti che l’oggetto di tipo Data è utilizzato solo per l’interfacciamento al database, non per lanavigazione; lo stesso dicasi per le 3 label ad esso collegate. Per questo motivo, questi elementi sonostati resi invisibili.Per realizzare questa applicazione è necessario disegnare un form dotato di tutti gli elementi necessari.Si provvede poi a collegare l’oggetto di tipo Data all’archivio e a legare ad esso le etichette testuali. A talfine occorre inizializzare l’elemento di gestione del database utilizzando come proprietà RecordSource ilnome della tabella da cui devono essere estratti i dati. Successivamente, dopo avere composto la query,il programma può provvedere a sostituire il contenuto della proprietà con la stringa in linguaggio SQL. Sinoti che, dopo aver eseguito tale operazione, è necessario invocare il metodo Refresh per aggiornarel’oggetto di tipo Data e quindi per accedere al risultato dell’interrogazione. Si osservi altresì che, perverificare l’eventuale assenza di dati soddisfacenti le condizioni imposte, si fa uso della proprietàRecordCount, che indica il numero degli elementi presenti nel recordset (insieme di record) corrente.

Rinfreschiamoci la memoria…

Il corso dedicato a Visual Basic prosegue ormai da molto tempo e gli argomenti già trattati sononumerosi. Lo scopo di quest’ultima parte della lezione è di invitare il lettore a rivedere i temi discussinegli ultimi 10 numeri, sia per valutare il proprio livello di comprensione, sia per evitare che dei concetti

Page 153: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB15/index.htm[26/09/2010 5:25:26]

importanti siano dimenticati in seguito all’acquisizione di nuove informazioni. Di seguito saranno quindiformulate alcune domande, a cui il lettore è invitato a rispondere. Le soluzioni corrette sono indicate diseguito in corsivo.

A cosa serve l’istruzione ReDim?L’istruzione ReDim permette di ridefinire un vettore per aumentare o ridurre la sua dimensione.A quale fine a volte si specifica la clausola Preserve dopo l’istruzione ReDim?L’uso della clausola Preserve permette di aumentare la dimensione di un vettore senza perdere ivalori in esso già contenuti.L’indice iniziale di un vettore deve essere sempre 0?No, può essere qualsiasi valore intero.Quali sono i principali vantaggi derivanti dall’uso delle subroutine?Le subroutine (o procedure) permettono di assegnare un nome a delle porzioni di codice usate inpiù punti di un programma. Esse possono poi essere richiamate semplicemente indicandonel’identificatore. Ciò rende più leggibile il codice dell’applicazione ed evita inutili duplicati al suointerno.A cosa serve la parola chiave ByVal?La parola chiave ByVal permette di passare a una procedura un parametro per valore.Quanti parametri possono essere passati a una procedura?Non esiste un limite ai parametri passabili a una procedura, sebbene non sia opportunoesagerare, onde evitare di produrre del codice scarsamente leggibile.Che cosa differenzia un parametro passato per valore da uno passato per riferimento?Se si richiama una procedura passando come parametro una variabile, se esso è definito perriferimento si rende la procedura in grado di modificare il valore della variabile. Se invece ilparametro è definito per valore, la procedura acquisisce il valore della variabile ma non la facoltàdi modificarla.Qual è la differenza che intercorre fra una funzione e una procedura?Una funzione può restituire dei valori. Una procedura invece no, a meno di ricorrere a deiparametri passati per riferimento.Può una funzione restituire più di un valore?No, a meno che non si faccia uso di parametri passati per riferimento.Quali rischi comporta un uso errato della ricorsione?Un uso errato della ricorsione, ad esempio quando non è specificata una condizione di uscita, puòprovocare il superamento della capacità massima dello stack di sistema (stack overflow).Cos’è la procedura Main?La procedura Main, se presente, è la prima procedura eseguita all’avvio di un programma. Essadeve risiedere in un modulo (file di estensione BAS).Qual è la differenza principale fra i file sequenziali e i file ad accesso casuale?I file ad accesso casuale permettono la ricerca delle informazioni senza comportare la lettura ditutto il proprio contenuto.A cosa serve l’istruzione Open?Per mezzo dell’istruzione Open è possibile fare in modo che il programma assuma il controllo diun file per eseguire su di esso delle operazioni di lettura o scrittura.A cosa serve la funzione Line Input?L’istruzione Line Input ha lo scopo di effettuare la lettura di una riga in un file di testo.Cos’è un record?Un record è un agglomerato di informazioni di tipo non necessariamente omogeneo. Costituiscel’elemento fondamentale di cui sono composti i file ad acceso casuale.Quando si apre un file ad accesso casuale, è opportuno specificare il parametro Len?E’ obbligatorio, al fine di consentire al sistema la distinzione dei record all’interno del file.Qual è l’istruzione da utilizzare per leggere un record in un file ad accesso casuale?La lettura di un record in un file ad accesso casuale avviene per mezzo dell’istruzione Get.Qual è l’istruzione che permette di scrivere un record in un file ad accesso casuale?La scrittura di un record in un file ad accesso casuale avviene per mezzo dell’istruzione Put.Che vantaggi offre l’uso di un database in luogo di un file ad accesso casuale?L’uso di un database permette di gestire grandi quantità di dati in modo semplice, grazie all’uso diun "motore" in grado di eseguire autonomamente la maggior parte delle operazioni di ricerca eselezione.Quali formati di database possono essere gestiti da Visual Basic?Visual Basic è in grado di gestire pressoché tutti i formati di database per i quali sia previsto undriver ODBC.A cosa serve il metodo MoveFirst dell’oggetto Recordset?

Page 154: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB15/index.htm[26/09/2010 5:25:26]

Il metodo MoveFirst permette di accedere al primo record presente in archivio.Quando la proprietà EOF dell’oggetto Recordset assume il valore logico True?La proprietà EOF (End Of File) assume il valore True quando il programma giunge all’ultimorecrod presente in archivio.Qual è la proprietà dell’oggetto Recordset che indica che la ricerca effettuata non è andata a buonfine?La proprietà che assume il valore logico True se un’operazione di ricerca non va a buon fine èdenominata NoMatch.Che vantaggi offre l’uso delle query?Le query permettono di fare in modo che il programma abbia una visione personalizzatadell’archivio, ovvero che acceda solo delle informazioni utili. Ciò semplifica il compito delprogrammatore, che non deve occuparsi dei filtrare i dati non necessari.Qual è il linguaggio di definizione delle query supportato da Visual Basic?In Visual Basic le query sono descritte per mezzo del linguaggio SQL.A cosa serve la clausola WHERE in una query SQL?La clausola WHERE permette di specificare la condizione che deve essere soddisfatta dai recordche devono essere estratti dall’archivio.Qual è la clausola da utilizzare per fare in modo che i dati siano ordinati in base al valore assuntoda un campo?Per fare in modo che i dati siano ordinati in base al valore assunto da un campo è necessario faruso della clausola ORDER BY.Com’è possibile far sì che l’ordinamento in funzione del valore assunto da un campo avvenga inmodo decrescente?L’ordinamento avviene in modo decrescente se nella clausola ORDER BY accanto al nome delcampo appare la parola DESC.Com’è possibile fare in modo che l’esecuzione di una query su un archivio non produca recordduplicati?Per evitare la generazione di record duplicati, è sufficiente far seguire la parola SELECT dallaclausola DISTINCT.

Bibliografia

"Visual Basic 5", McGrawHill, ISBN 88-386-0436-3

Note Biografiche

Maurizio Crespi si occupa di grafica, multimedialità, amministrazione di reti locali e geografiche, nonchédella progettazione e dello sviluppo di applicazioni in C++, Visual Basic, Delphi e Director. Può esserecontattato tramite Internet all’indirizzo [email protected].

VB-IT: per tutti gli sviluppatori VB o aspiranti tali

VB-IT e' la mailing list italiana interamente dedicata a Visual Basic, VBA (Visual Basic for Application) eVBScript. Se sei uno sviluppatore esperto oppure ti interessa il mondo Visual Basic anche solo perdiletto, troverai VB-IT utilissima!Consigli, suggerimenti, trucchi, soluzioni a problemi comuni e molto altro. Per iscriversi, gratuitamente, aVB-IT è sufficiente inviare un messaggio a [email protected] e nel body inserire la stringa:subscribe vb-itUna volta iscritto, esponi i tuoi problemi a [email protected] e aiuta gli altri a risolvere i propri. Sarà

Page 155: Corso Visual Basic

Figura 1 Il form dell

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB15/figura1.htm[26/09/2010 5:25:33]

Figura 1 Il form dell’applicazione di esempio

Page 156: Corso Visual Basic

Figura 2 L

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB15/figura2.htm[26/09/2010 5:25:42]

Figura 2 L’applicazione di esempio in esecuzione

Page 157: Corso Visual Basic

LISTATO 1 Il listato del programma di esempio

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB15/listato1.htm[26/09/2010 5:25:48]

LISTATO 1 Il listato del programma di esempio

Rem Esempio query SQL

Private Sub Form_Load() dbArchivio.DatabaseName = "C:\Dev\Archivio.mdb" dbArchivio.Connect = "Access"End Sub

Private Sub btnCerca_Click() Dim StringaSQL As String Dim Campi As String Dim CampoRicerca As String Dim CampoOrdinamento As String Dim StringaDati As String

Rem Composizione elenco campi da estrarre Campi = "" If ckCognome.Value = 1 Then Campi = "Cognome" End If If ckNome.Value = 1 Then If Campi <> "" Then Campi = Campi & ", Nome" Else Campi = "Nome" End If End If If CkAnno.Value = 1 Then If Campi <> "" Then Campi = Campi & ", AnnoNascita" Else Campi = "AnnoNascita" End If End If

Rem Controllo del campo su cui effettuare la ricerca

If obCercaNome.Value Then CampoRicerca = "Nome" ElseIf obCercaCognome.Value Then CampoRicerca = "Cognome" Else CampoRicerca = "AnnoNascita" End If

Rem Controllo del campo su cui effettuare l'ordinamento

If obOrdinaNome.Value Then CampoOrdinamento = "Nome" ElseIf obOrdinaCognome.Value Then CampoOrdinamento = "Cognome" Else CampoOrdinamento = "AnnoNascita" End If

Rem Composizione stringa SQL

StringaSQL = "SELECT " + Campi + " FROM Anagrafica"

Page 158: Corso Visual Basic

LISTATO 1 Il listato del programma di esempio

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB15/listato1.htm[26/09/2010 5:25:48]

StringaSQL = StringaSQL + " WHERE " + CampoRicerca StringaSQL = StringaSQL + " = '" + txtDaCercare.Text + "'" StringaSQL = StringaSQL + " ORDER BY " + CampoOrdinamento Rem La stringa è visualizzata nella label lblStringaSQL.Caption = StringaSQL

Rem Esecuzione della query e collegamento al controllo di tipo Data delle 3 etichette Rem lblNome, lblCognome, lblAnnoNascita

dbArchivio.RecordSource = StringaSQL dbArchivio.Refresh

Rem Cancellazione listbox

lstRisultato.Clear

Rem Inserimento dei dati Rem nella listbox

If dbArchivio.Recordset.RecordCount > 0 Then dbArchivio.Recordset.MoveFirst Do While Not dbArchivio.Recordset.EOF StringaDati = lblNome.Caption + " " StringaDati = StringaDati + lblCognome.Caption + " " StringaDati = StringaDati + lblAnnoNascita.Caption + " " lstRisultato.AddItem StringaDati dbArchivio.Recordset.MoveNext Loop Else MsgBox "Nessun elemento trovato" End IfEnd Sub

Page 159: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB16/index.htm[26/09/2010 5:27:15]

Programmo Subito n. 16 - 2 Livello - Corso di Visual Basic

Il corso dedicato a Visual Basic darà spazio alla gestione della stampante. Sarà illustratocome sia possibile, agendo su alcune semplici proprietà, produrre stampe anche di alto

livello

Corso di Visual BasicLa gestione della stampante

(Parte 16)

di Maurizio Crespi

Ogni sistema, di qualunque tipo o dimensione, se usato per uso professionale, è corredato da unastampante. Questa periferica, infatti, è ormai diventata una componente imprescindibile di ogni ufficio.Per questo motivo, tutti i programmatori, almeno una volta nella vita, si trovano a dover scrivere delsoftware in grado di gestirla. In particolare, coloro che sviluppano applicazioni gestionali non possono ingenere esimersi dal prevedere la rappresentazione su carta delle informazioni elaborate o archiviate.Visual Basic nel tempo si è conquistato una posizione da leader nel campo degli strumenti di sviluppoper applicazioni gestionali. Ciò è dovuto anche alla semplicità e alla flessibilità con cui permette diprodurre dei tabulati.

L’oggetto Printer

In Visual Basic la stampante è rappresentata da un oggetto, denominato Printer. Tutte le operazionidevono pertanto essere eseguite su di esso. Lo scopo della lezione è di consentire al lettore di prendereconfidenza con le proprietà e i metodi fondamentali che l’oggetto prevede.

Il metodo Print

Le stampanti sono nate con lo scopo di permettere la trasposizione su carta dei testi prodotti dalcalcolatore. L’operazione elementare per questo tipo di periferiche è quindi rappresentata dalla scritturadi testo. L’oggetto Printer a tal fine mette a disposizione il metodo denominato Print. Il suo utilizzo ricordaquello della parola chiave omonima del linguaggio Basic. Per scrivere una frase è quindi sufficienteinvocare il metodo passandogli la stringa da stampare. Ad esempio, la riga

Printer.Print "Io leggo Dev"

provoca la scrittura della frase "Io leggo Dev" sulla stampante. Analogamente, le righe

Printer.Print "Io leggo Dev"Printer.Print "perché mi insegna a programmare"

provocano la scrittura delle frasi "Io leggo Dev" e "perché mi insegna a programmare". Esse sono postesu due righe differenti. Infatti, analogamente a ciò che avviene nel linguaggio Basic per il comando Print,alla fine della frase è generata automaticamente una sequenza costituita dai caratteri CR (CarriageReturn, ovvero ritorno del carrello di stampa nella posizione di inizio riga) e LF (Line Feed, ovveroavanzamento di una riga). Ciò, tuttavia, a volte può risultare fastidioso, soprattutto quando si desideracomporre delle frasi a partire da informazioni calcolate dal programma in punti diversi.

Per evitare che sia richiesto alla stampante di andare a capo, è necessario far seguire l’invocazione delmetodo Print dal punto e virgola. Le righe

Printer.Print "Io leggo Dev";Printer.Print "perché mi insegna a programmare"

provocano pertanto la scrittura della frase

Io leggo Devperché mi insegna a programmare

Si noti che in questo caso non sono stati inseriti automaticamente degli spazi fra le parole "Dev" e"perché". È infatti cura del programmatore l’introduzione al termine di una stringa degli spazi tali da

Page 160: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB16/index.htm[26/09/2010 5:27:15]

impedire che sia unita alla successiva quando ciò non è desiderato. Quindi, per scrivere la frasecorrettamente, è necessario aggiungere uno spazio al termine della prima stringa, come nelle righe cheseguono:

Printer.Print "Io leggo Dev ";Printer.Print "perché mi insegna a programmare"

In alcuni casi, invece, può verificarsi la necessità di inserire delle righe vuote. Per fare ciò, è sufficienterichiamare il metodo Print senza parametri. Ad esempio, la riga

Printer.Print

fa sì che la testina della stampante si posizioni sulla riga successiva a quella corrente.

L’incolonnamento dei dati

Spesso, quando si stampano dei dati, si rivela necessario il loro incolonnamento. È il caso, ad esempio,dei documenti per uso fiscale. In questi casi, l’uso delle tabulazioni può rivelarsi molto utile. Essepermettono di suddividere il foglio in colonne, ognuna larga 14 caratteri. Visual Basic permette di gestirele tabulazioni per mezzo dell’opzione Tab del comando Print. Ad esempio, le righe

Printer.Print Tab(2);Printer.Print "Dev"

provocano la stampa della stringa "Dev" nella seconda colonna del foglio. Si noti che il parametronumerico descrive sempre una posizione assoluta. Quindi, il numero della colonna in cui la stampaavviene è indipendente dalla posizione assunta dalla testina di stampa prima dell’esecuzionedell’istruzione.Per mezzo dell’opzione Tab non è possibile definire uno spostamento relativo, bensì solo uno assoluto.L’unica eccezione è costituita dal caso in cui il parametro numerico è omesso. La scrittura avviene alloranella colonna successiva a quella corrente o, se la testina si trova alla fine del foglio, nella riga seguente.

Pertanto, le righePrinter.Print Tab; Printer.Print "Dev"

fanno sì che nella colonna successiva a quella corrente sia scritta la parola "Dev".Si noti che le colonne iniziano ogni 14 caratteri. La loro lunghezza risulta allora dipendente dal tipo dicarattere utilizzato e non dalle dimensioni del foglio.

L’inserimento di spazi

Spesso, soprattutto quando si devono indicare degli importi in valuta, è opportuno allineare i testi adestra. L’incolonnamento per mezzo delle tabulazioni può in questi casi non rivelarsi una scelta corretta,dal momento che permette di allineare i testi a sinistra ma non agevola un granché l’allineamento adestra. Può allora rivelarsi utile l’uso dell’opzione Spc del metodo Print, che permette di stampare unasequenza di spazi in quantità pari al valore indicato come parametro. Calcolando opportunamente taledato, è quindi possibile ottenere il corretto allineamento a destra del testo. Si osservi la proceduraAllineaDestra di cui è riportato di seguito il codice sorgente:

Private Sub AllineaDestra(ByVal Stringa As String, ByVal LarghCol As Integer)Dim Lungh As IntegerDim Spazi As IntegerStringa = Trim(Stringa)Lungh = Len(Stringa)Spazi = LarghCol - LunghPrinter.Print Spc(Spazi);Printer.Print Stringa;End Sub

Essa provvede a stampare la stringa fornitale come parametro dopo averla fatta seguire da spazi la cuiquantità è espressa dalla variabile Spazi. Il suo valore è calcolato come differenza fra il numero dellacolonna in cui deve avvenire l’allineamento, fornito come parametro (LarghCol) e la lunghezza dellastringa da stampare. Si noti che tale procedura funziona correttamente solo se il carattere utilizzato è ditipo a spaziatura non proporzionale. In caso contrario, infatti, le larghezze dei caratteri, compresi glispazi, risultano diverse fra loro e rendono molto più complesso l’allineamento. Al fine di ridurre il rischiodi errore derivante da un cattivo allineamento delle informazioni e di rendere più semplice e veloce losviluppo delle applicazioni, è pertanto consigliabile l’uso di un carattere a larghezza non proporzionale(ad esempio il "Courier New") nei programmi che prevedono la stampa di tabelle o altri dati sumodulistica di tipo fiscale.

Page 161: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB16/index.htm[26/09/2010 5:27:15]

L’impostazione del carattere da utilizzare

Per selezionare un carattere diverso da quello predefinito, occorre intervenire sulla proprietà FontNamedell’oggetto Printer. Ad esempio, la riga

Printer.FontName = "Courier New"

fa sì che la stampa sia eseguita con il carattere "Courier New".

È inoltre possibile impostare la dimensione del font da utilizzare agendo sul valore della proprietàFontSize. L’insieme dei valori che essa può assumere è rappresentato dalle misure in punti che sonoaccettate dal sistema per il carattere selezionato. Per i font di tipo raster, i valori possibili sono pochi,mentre per i caratteri true type, che costituiscono la quasi totalità della dotazione di Windows, ledimensioni possono variare in un intervallo estremamente vasto. Pertanto, per impostare quello che itipografi chiamano corpo del carattere, ovvero la sua dimensione, al valore corrispondente a 10 punti,occorre scrivere

Printer.FontSize = 10

Anche lo stile del carattere può essere variato. Ciò avviene agendo su alcune proprietà in grado diassumere dei valori booleani. Ad esempio, la riga

Printer.FontBold = True

fa sì che il testo sia scritto in grassetto.

La riga

Printer.FontItalic = True

seleziona invece lo stile corsivo.

La sottolineatura è invece legata alla proprietà FontUnderline. Pertanto, può essere attivata mediante lariga

Printer.FontUnderline = True

Un’altra proprietà, in genere poco usata, è quella che permette di generare delle stampe in cui ilcarattere risulta barrato. Essa è denominata FontStrikethru.Le proprietà sopra elencate sono combinabili fra loro. Si osservi il seguente codice:

Printer.FontName = "Arial"Printer.FontSize = 20Printer.FontBold = TruePrinter.FontItalic = TruePrinter.FontStrikethru = FalsePrinter.Print = "Io leggo Dev"

provocano la stampa della frase "Io leggo Dev" in Arial grassetto corsivo di corpo 20.

L’utilizzo di più tipi di caratteri in un documento

Le impostazioni relative al carattere sono attive per tutti i testi stampati dopo l’assegnazione dei valorialle proprietà, fino a quando esse non subiscono variazioni. In altre parole, le impostazioni riguardanti ilfont non interessano l’intero documento, a meno che non siano state definite prima della sua stampa.Inoltre, possono essere variate a piacere al suo interno. È quindi possibile usare un numeroteoricamente infinito di caratteri diversi in un’unica stampa.

Si osservi l’esempio che segue:

Printer.FontName = "Arial"Printer.FontSize = 20Printer.FontBold = TruePrinter.FontItalic = FalsePrinter.FontStrikethru = FalsePrinter.Print = "Io leggo Dev"Printer.FontSize = 15Printer.Print = "perché mi insegna"Printer.FontSize = 10Printer.FontItalic = TruePrinter.Print = "a programmare!"

Page 162: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB16/index.htm[26/09/2010 5:27:15]

Il testo prodotto è composto da 3 righe aventi dimensioni diverse. L’ultima, inoltre, si differenza per lostile, essendo scritta in corsivo.

Il passaggio a una nuova pagina

Molto spesso, le stampe che un programma deve produrre superano la capienza di una pagina. In questicasi, occorre inserire uno o più salti di pagina. Ciò è possibile invocando il metodo NewPage, senzaargomenti, come illustrato di seguito:

Printer.NewPage

L’utilizzo di tale metodo provoca inoltre l’incremento di un’unità del valore della proprietà Page che, comeè facile intuire, contiene il numero della pagina corrente. Si osservi la seguente procedura

Private Sub PaginaSuccPrinter.NewPagePrinter.Print "Pagina ";Printer.Print Printer.PageEnd Sub

Essa ha lo scopo di provocare l’avanzamento alla pagina successiva e di inserire nella parte superioredel nuovo foglio il numero di pagina.

L’avvio della stampa

Coloro che leggendo questo articolo hanno già provato a scrivere del codice volto a produrre unastampa, potrebbero aver subìto una delusione. Infatti, con molta probabilità, la stampante non haprodotto alcun risultato. Ciò è dovuto al fatto che i documenti sono prima composti in memoria e solo inseguito inviati alla stampante. Ciò permette la massima flessibilità, nonché la possibilità di annullare unastampa già iniziata. L’invio di un documento alla stampante avviene quindi solo dopo la sua completadefinizione, ovvero quando si provvede a dichiararne il completamento per mezzo del metodo EndDoc,da richiamare senza l’ausilio di parametri, come indicato di seguito:

Printer.EndDoc

L’annullamento di una stampa

Come si è già accennato, è possibile annullare una stampa in corso di definizione. Per fare ciò, bastaricorrere al metodo KillDoc.

Ad esempio, la riga

Printer.KillDocprovvede alla cancellazione della stampa in corso.

Un semplice esempio…

La lezione termina con un piccolo esempio. Si tratta di un semplice programma in grado di stampare unatavola pitagorica. Il suo codice, riportato nel listato 1, è tutto contenuto nella procedura Main, in quantonon necessita di un’interfaccia grafica. Esso si compone di due cicli nidificati. Uno è utilizzato per gestirele righe, mentre l’altro mantiene traccia delle colonne. Il prodotto dei valori assunti dalle variabili dicontrollo dei cicli costituisce il dato da visualizzare nella tabella. Si noti che è calcolata la lunghezza delvalore da scrivere, per consentire l’anteposizione di un numero di spazi tale da ottenere l’allineamento adestra dei dati.

Bibliografia

"Visual Basic 5", McGrawHill, ISBN 88-386-0436-3

Maurizio Crespi si occupa di grafica, multimedialità, amministrazione di reti locali e geografiche, nonchédella progettazione e dello sviluppo di applicazioni in C++, Visual Basic, Delphi e Director. Può esserecontattato tramite Internet all’indirizzo [email protected].

VB-IT: per tutti gli sviluppatori VB o aspiranti tali

VB-IT è la mailing list italiana interamente dedicata a Visual Basic, VBA (Visual Basic for Application) e

Page 163: Corso Visual Basic

Scrivere qui l’occhiello dell’articolo (di 150 caratteri per Dev

file:///C:/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB16/articolo.htm[26/09/2010 5:39:04]

iniziata. L’invio di un documento alla stampante avviene quindi solo dopo la sua completa definizione,ovvero quando si provvede a dichiararne il completamento per mezzo del metodo EndDoc, da richiamaresenza l’ausilio di parametri, come indicato di seguito:

Printer.EndDoc

L’annullamento di una stampa

Come si è già accennato, è possibile annullare una stampa in corso di definizione. Per fare ciò, bastaricorrere al metodo KillDoc.

Ad esempio, la riga

Printer.KillDocprovvede alla cancellazione della stampa in corso.

Un semplice esempio…

La lezione termina con un piccolo esempio. Si tratta di un semplice programma in grado di stampare unatavola pitagorica. Il suo codice, riportato nel listato 1, è tutto contenuto nella procedura Main, in quantonon necessita di un’interfaccia grafica. Esso si compone di due cicli nidificati. Uno è utilizzato per gestirele righe, mentre l’altro mantiene traccia delle colonne. Il prodotto dei valori assunti dalle variabili dicontrollo dei cicli costituisce il dato da visualizzare nella tabella. Si noti che è calcolata la lunghezza delvalore da scrivere, per consentire l’anteposizione di un numero di spazi tale da ottenere l’allineamento adestra dei dati.

Bibliografia

"Visual Basic 5", McGrawHill, ISBN 88-386-0436-3

Maurizio Crespi si occupa di grafica, multimedialità, amministrazione di reti locali e geografiche, nonchédella progettazione e dello sviluppo di applicazioni in C++, Visual Basic, Delphi e Director. Può esserecontattato tramite Internet all’indirizzo [email protected].

VB-IT: per tutti gli sviluppatori VB o aspiranti tali

VB-IT è la mailing list italiana interamente dedicata a Visual Basic, VBA (Visual Basic for Application) eVBScript. Se sei uno sviluppatore esperto oppure ti interessa il mondo Visual Basic anche solo perdiletto, troverai VB-IT utilissima!

Consigli, suggerimenti, trucchi, soluzioni a problemi comuni e molto altro. Per iscriversi, gratuitamente, aVB-IT è sufficiente inviare un messaggio a [email protected] nel body inserire la stringa: subscribe vb-itUna volta iscritto, esponi i tuoi problemi a [email protected] e aiuta gli altri a risolvere i propri. Saràanche un modo per instaurare nuovi rapporti di lavoro, collaborazione ed amicizia!

Page 164: Corso Visual Basic

Sub Main() Dim i As Integer Dim j As Integer Dim Prodotto As String Dim Lungh As Byte Dim NumSpazi As Byte Printer.FontName = "Courier New" Printer.FontSize = 10 For i = 1 To 10 For j = 1 To 10 Prodotto = Str$(i * j) Lungh = Len(Prodotto) NumSpazi = 8 - Lungh Printer.Print Spc(NumSpazi); Printer.Print Prodotto; Next j Rem va a capo Printer.Print Next i Printer.EndDocEnd Sub

Page 165: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB17/index.htm[26/09/2010 5:31:33]

Riquadro1 Riquadro2

Programmo Subito n. 17 - Giugno 1999 - 2 Livello - Corso di Visual Basic

Il corso dedicato a Visual Basic da nuovamente spazio alla gestione della stampante. Questa volta sarannodescritti i metodi che permettono di creare dei tabulati di alta qualità

Corso di Visual BasicLa produzione di stampe di elevata qualità

(parte XVII)

di Maurizio Crespi

Nel corso degli anni, gli strumenti che permettono di stampare le informazioni su carta hanno subìto unanotevole evoluzione. Dalle prime stampanti a margherita si è passati a quelle ad aghi, in grado di produrreanche della grafica e di operare con diversi tipi di carattere, fino poi ad arrivare alle moderne stampanti atecnologia laser o a getto di inchiostro, che permettono di ottenere dei risultati di qualità un tempo diesclusiva competenza dei migliori tipografi. L’evolversi delle periferiche ha portato ad un aumento delleesigenze dei programmatori. Dalla semplice rappresentazione di testi si è passati a un uso sempre piùmassiccio delle grafica, anche per le applicazioni di tutti i giorni. Per questo motivo, lo sviluppatore modernonecessita di uno strumento che gli permetta di gestire le stampanti anche per effettuare le operazioni piùcomplesse. Ancora una volta Visual Basic non delude le aspettative, in quanto mette a disposizione unanutrita serie di metodi tali da rendere l’oggetto Printer, di cui si è già ampiamente parlato nella scorsalezione, in grado di accontentare anche l’utenza più esigente senza richiedere uno sforzo elevato alprogrammatore.

La proprietà ScaleMode

Per effettuare stampe di alta qualità, occorre dapprima essere in grado di posizionare i testi con estremaprecisione in qualsiasi punto del foglio. Il concetto di "colonna", visto nella precedente lezione a propositodell’opzione Tab del metodo Print, non consente un controllo preciso della posizione in cui avviene lastampa, in quanto risulta legata alla dimensione del carattere. Per un posizionamento preciso all’interno delfoglio è pertanto necessario disporre di uno strumento che permetta di esprimere delle coordinate in unità dimisura semplici da usare e indipendenti dal carattere selezionato, quali sono ad esempio i millimetri. È ciòche la proprietà ScaleMode permette di fare. I valori più utilizzati per questa proprietà sono elencati nelriquadro 1. Per poter definire le coordinate degli elementi da posizionare sul foglio in centimetri, è quindisufficiente inserire nel codice la riga

Printer.ScaleMode = 7

Nella trattazione che segue si supporrà di aver selezionato come unità di misura i centimetri.

La verifica delle dimensioni del foglio

Per ottenere le dimensioni dell’area di stampa espresse nella scala impostata, è possibile ricorrere alleproprietà ScaleWidth e ScaleHeight. La prima restituisce la larghezza del foglio, mentre la seconda,ovviamente, l’altezza. Esse si basano sulle impostazioni inserite nella finestra di configurazione dellastampante nel Pannello di Controllo di Windows.Le righe che seguono stampano un messaggio indicante ledimensioni del foglio in uso.

Printer.ScaleMode = 7Altezza=Printer.ScaleHeightLarghezza=Printer.ScaleWidth Printer.Print "Il foglio è largo cm";Printer.Print Larghezza;Printer.Print "e alto cm";Printer.Print AltezzaPrinter.EndDoc

Le proprietà CurrentX e CurrentY

Dopo aver definito una scala, è possibile stabilire la posizione in cui deve essere visualizzata la successivariga di testo sul foglio. A tal fine, si fa uso delle proprietà CurrentX e CurrentY, che permettono di

Page 166: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB17/index.htm[26/09/2010 5:31:33]

intervenire rispettivamente sulla coordinata orizzontale e su quella verticale. Ad esempio, si supponga divoler scrivere sul foglio a 4 centimetri dal bordo superiore e a 2,5 centimetri da quello laterale sinistro, lafrase "Io leggo Dev". Il codice necessario per fare ciò è il seguente

Printer.ScaleMode = 7Printer.CurrentX = 2.5Printer.CurrentY = 4Printer.Print "Io leggo Dev"Printer.EndDoc

Le proprietà CurrentX e CurrentY si incrementano automaticamente. I loro valori riflettono pertanto semprela posizione che è occupata dalla testina di stampa.Per mezzo delle suddette proprietà è anche possibiledefinire degli spostamenti relativi. Ad esempio, le righe seguenti spostano la testina di stampa a destra di 3centimetri e in basso di 2 millimetri rispetto alla posizione corrente.

Printer.CurrentX = Printer.CurrentX + 3Printer.CurrentY = Printer.CurrentY + .2

L’allineamento di un testo a destra

Si supponga di voler scrivere la frase "Io leggo Dev" a 2 centimetri dal bordo destro del foglio. Per fare ciòoccorre calcolare la posizione iniziale in cui deve essere effettuata la scrittura. Essa è pari alla differenzafra la larghezza del foglio, a cui sono sottratti i 2 centimetri di margine, meno la lunghezza del testo. Èquindi necessario disporre di uno strumento in grado di calcolare l’ingombro di una frase in base alcarattere e allo stile selezionati ed esprimerlo nell’unità di misura in uso. Il metodo TextWidth ha questoscopo. La sua sintassi è:

<lunghezza> = Printer.TextWidth (<stringa>)

Per scrivere la frase nella posizione desiderata occorre quindi digitare il seguente codice

Testo = "Io leggo Dev"LarghFoglio = Printer.ScaleWidthLarghTesto = Printer.TextWidth(Testo)Printer.CurrentX = LarghFoglio – LarghTesto - 2 Printer.Print Testo

La centratura di un testo

Analogamente, è possibile centrare un testo nella pagina. A tal fine si fa ancora uso del metodo TextWidth,nonché delle proprietà ScaleWidth e CurrentX. Questa volta è necessario calcolare lo spazio che rimanelibero nella riga, ovvero la differenza fra la larghezza del foglio e quella del testo da scrivere. Il valoreottenuto deve essere diviso per 2. È ciò che fa la procedura CentraTesto.

Private Sub CentraTesto(ByVal Testo As String)LarghFoglio = Printer.ScaleWidthLarghTesto = Printer.TextWidth(Testo)Printer.CurrentX = (LarghFoglio – LarghTesto) / 2Printer.Print TestoEnd Sub

La scrittura di note a fine pagina

In modo perfettamente analogo è possibile stabile l’allineamento di un testo rispetto ai margini superiore einferiore del foglio. In questo caso, è necessario tenere conto dell’altezza della stringa da stampare. Essa ècalcolata dal metodo TextHeight, la cui sintassi è la seguente

<altezza> = Printer.TextHeight (<stringa>)

Si supponga di voler scrivere una procedura in grado di visualizzare delle note di fondo pagina in uncarattere di corpo 8 a 2 centimetri dal margine inferiore del foglio. Il codice che la descrive è il seguente

Private Sub NoteFondo(ByVal Testo As String)Printer.FontSize = 8AltFoglio = Printer.ScaleHeightAltTesto = Printer.TextHeight(Testo)Printer.CurrentY = AltFoglio – AltTesto – 2Printer.Print TestoEnd Sub

La stampa in orizzontale o verticale

Ormai tutte le stampanti moderne permettono di impostare l’orientamento della stampa, ovvero di scegliere

Page 167: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB17/index.htm[26/09/2010 5:31:33]

se utilizzare il foglio in modalità portrait (in verticale) o landscape (in orizzontale). Visual Basic offre ilsupporto per sfruttare questa caratteristica per mezzo della proprietà Orientation dell’oggetto Printer. I valoriche essa può assumere sono due: il primo corrisponde alla costante vbPRORPortrait, che ha valore 1 eimposta la stampa in verticale, mentre il secondo, corrispondente alla costante vbPRORLandscape,permette di attivare la stampa in orizzontale.

Il tracciamento di linee

Sovente, al fine di delimitare delle tabelle o di dare un look più professionale ai propri documenti, sitracciano delle linee sul foglio. Visual Basic offre questa possibilità per mezzo del metodo Line, la cuisintassi è la seguente:

Printer.Line <coord_inizio> - <coord_fine>

dove le coordinate sono espresse da coppie di tipo (x,y), in cui x rappresenta la posizione orizzontaleespressa nella scala in uso (indicata dalla proprietà ScaleMode) e y si riferisce alla posizione verticale.

Pertanto, considerando sempre il valore della proprietà ScaleMode pari a 7, la riga

Printer.Line (2,3) – (19,3)

provoca il tracciamento di una linea a 3 centimetri dal bordo superiore del documento che, in un comunefoglio in formato A4 largo 21 centimetri, occupa l’intera larghezza dell’area stampabile mantenendo unmargine di 2 centimetri dai bordi. La prima delle coppie indicanti le coordinate può essere omessa. Inquesto caso è assunta come punto di partenza la posizione corrente della testina di stampa, ovvero lacoppia (Printer.CurrentX, Printer.CurrentY)

Ad esempio, la riga

Printer.Line – (19,3)

provoca il tracciamento di una linea a partire dalla posizione corrente del cursore fino alla posizione distante19 unità (centimetri, se la proprietà ScaleMode è impostata al valore 7) dal bordo sinistro del foglio e 3unità da quello superiore.

Lo spessore della linea dipende dal valore assegnato alla proprietà DrawWidth. Essa può assumere unvalore interno fra 1 e 32767, che esprime il numero di pixel (punti) corrispondente allo spessore desiderato.

Ad esempio, le righe

Printer.DrawWidth = 4

Printer.Line (2,3) – (19,3)

fanno sì che sia disegnata una linea di spessore pari a 4 pixel.

Un’altra proprietà, denominata DrawStyle, descrive il tipo di tratto della linea. I valori che essa puòassumere sono elencati nel riquadro 2. Quelli compresi fra 1 e 4 hanno effetto solo se la proprietàDrawWidth è impostata a 1. Altrimenti, producono una linea continua, esattamente come quella determinatadall’uso dell’impostazione predefinita, ovvero quella corrispondente alla costante vbSolid, che ha valorenullo.

Si osservi il seguente codice:

Printer.ScaleMode = 7

Page 168: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB17/index.htm[26/09/2010 5:31:33]

Printer.DrawWidth = 1

Printer.Drawstyle = 1

Printer.Line (2,3) – (19,3)

Esso provoca il tracciamento di una linea orizzontale tratteggiata a partire dalla posizione posta a 2centimetri dal bordo sinistro del foglio fino alla posizione distante da esso 19 centimetri.

La stampa di immagini

Tutte le stampanti presenti sul mercato sono ormai in grado di stampare anche delle immagini, spesso conuna risoluzione grafica elevata. Naturalmente, Visual Basic mette a disposizione dei programmatori unostrumento che permette di sfruttare questa capacità. Si tratta del metodo PaintPicture, la cui sintassi è laseguente:

Printer.PaintPicture <immagine>,

<x1>, <y1>,

[<larghezza>],

[<altezza>],

dove <immagine> rappresenta la sorgente dei dati da visualizzare, ovvero è la proprietà Picture di unaPictureBox (oggetto atto a contenere immagini). I valori x1 e y1 rappresentano invece le coordinate delpunto in cui deve essere posizionato l’angolo superiore sinistro dell’immagine.

Ad esempio, si supponga di disporre di una PictureBox, denominata pbImg, in cui è contenutaun’immagine. Per riportare quest’ultima su carta a partire dal punto di coordinate (2,3) è necessario scriverela riga

Printer.PaintPicture pbImg.Picture, 2, 3

L’immagine è così disegnata in modo che la sua dimensione non sia alterata. Molto spesso, tuttavia, sidesidera effettuare un ridimensionamento in fase di stampa. Ciò ha in genere il fine di sfruttare l’intera areadisponibile sul foglio, indipendentemente dalle dimensioni di quest’ultimo. Ad esempio, si potrebbe volerstampare l’immagine in modo da occupare tutto il foglio mantenendo un margine di 2 centimetri dai bordi.Ciò è possibile digitando il seguente codice:

Printer.ScaleMode = 7Larghezza = Printer.ScaleWidth - 4Altezza = Printer.ScaleHeight – 4Printer.PaintPicture pbImg.Picture, 2, 2, Larghezza, Altezza

Si noti che sono stati utilizzati due ulteriori parametri che descrivono, rispettivamente, la larghezza e

Page 169: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/VB17/index.htm[26/09/2010 5:31:33]

l’altezza dell’immagine da stampare. Si osservi altresì che ad essi sono stati assegnati dei valori pari alledimensioni del foglio diminuite di 4 centimetri, al fine di generare i margini.

La scelta fra la stampa a colori o in bianco e nero

Le stampanti a colori, dato il continuo ridursi dei prezzi, si stanno sempre più diffondendo. La stampa acolori comporta tuttavia un costo per pagina più elevato rispetto a quella monocromatica a toni di grigio. Perquesto motivo, spesso si rivela utile fare in modo che le applicazioni siano in grado di operare una sceltafra le due modalità di stampa. Ciò è possibile per mezzo della proprietà ColorMode, che può assumere ivalori 1 (corrispondente alla costante predefinita vbPRCMMonochrome) e 2. L’assegnamento diquest’ultimo valore, a cui si può far riferimento anche attraverso la costante vbPRCMColor, fa sì che lastampa avvenga a colori. In caso contrario è monocromatica. Tale proprietà è ignorata nel caso in cui lastampante in uso sia in grado di produrre solo dei tabulati monocromatici.

Conclusioni

La capacità di produrre un risultato di qualità non solo sul video ma anche sulla stampante è sempre piùrichiesta dall’utenza moderna, che sembra accettare sempre di meno i tabulati grezzi e spesso pocoleggibili che un tempo costituivano lo standard per le applicazioni gestionali. Oggi le esigenze sonocambiate e con esse le periferiche in grado di stampare le immagini. Oggi un programmatore deve esserein grado di creare delle applicazioni che visualizzino nel migliore dei modi i risultati delle proprieelaborazioni, ricorrendo a quanto di meglio la tecnologia mette a disposizione. Un moderno strumento disviluppo deve quindi tenere conto di queste esigenze. Visual Basic fin dalla nascita si è affermato come unodei prodotti più innovativi. Anche per quanto riguarda la gestione delle stampe è all’altezza della propriafama, rivelandosi in grado di soddisfare le richieste dell’utenza più esigente, pur mantenendo la consuetasemplicità d’uso che rappresenta il suo fiore all’occhiello.

Bibliografia

"Visual Basic 5", McGrawHill, ISBN 88-386-0436-3

Maurizio Crespi si occupa di grafica, multimedialità, amministrazione di reti locali e geografiche, nonchédella progettazione e dello sviluppo di applicazioni in C++, Visual Basic, Delphi e Director. Può esserecontattato tramite Internet all’indirizzo [email protected].

VB-IT: per tutti gli sviluppatori VB o aspiranti tali

VB-IT e' la mailing list italiana interamente dedicata a Visual Basic, VBA (Visual Basic for Application) eVBScript. Se sei uno sviluppatore esperto oppure ti interessa il mondo Visual Basic anche solo perdiletto, troverai VB-IT utilissima! Consigli, suggerimenti, trucchi, soluzioni a problemi comuni e moltoaltro. Per iscriversi, gratuitamente, a VB-IT è sufficiente inviare un messaggio [email protected] e nel body inserire la stringa:

subscribe vb-it

Una volta iscritto, esponi i tuoi problemi a [email protected] e aiuta gli altri a risolvere i propri. Sarà

Page 170: Corso Visual Basic

Riquadro 1 I principali valori assegnabili alla proprietà ScaleMode

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB17/riquadro1.htm[26/09/2010 5:31:40]

Riquadro 1 I principali valori assegnabili alla proprietà ScaleMode

I principali valori assegnabili alla proprietà ScaleMode

Costante Valore Descrizione

predefinita numerico sintetica

VbPoints 2 Settantaduesimi di pollice

VbPixels 3 Pixel (punti sullo schermo).

VbInches 5 Pollici.

VbMillimeters 6 Millimetri.

VbCentimeters 7 Centimetri.

Page 171: Corso Visual Basic

Riquadro 2 I principali valori assegnabili alla proprietà DrawStyle

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/VB17/riquadro2.htm[26/09/2010 5:31:48]

Riquadro 2 I principali valori assegnabili alla proprietà DrawStyle

Costante Valore Descrizione

predefinita numerico sintetica

vbSolid 0 Linea continua (valore predefinito)

vbDash 1 Tratteggio.

vbDot 2 Sequenza di punti.

vbDashDot 3 Sequenza alternata di linee e punti.

vbDashDotDot 4 Sequenze linea-punto-punto.

vbInvisible 5 Tratto trasparente.

vbInsideSolid 6 Tratto continuo interno.

Page 172: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb18/index.htm[26/09/2010 5:32:52]

Figura1 Figura2 Figura3

Corso di Visual Basic

Questo articolo spiega gli strumenti che il Visual Basic propone per visualizzare delle immagini grafiche. Nelprossimo numero approfondiremo questa prima parte, per spiegare invece come crearne di nuove.

Corso Visual BasicLa visualizzazione di immagini grafiche

Parte 18

di Andrea T.M. Frosini

Il Visual Basic è un ambiente di sviluppo che offre almeno una soluzione ad ogni tipico problema dellaprogrammazione quotidiana. Perciò se avete ricevuto una commessa per lo sviluppo di un sempliceprogramma orientato alla gestione di magazzino, potete accettare perché siete in grado di interagire conuna base dati e di eseguire delle stampe di qualità. Quanto vi manca è forse quel "qual cosa in più" rispettoa ciò che i vostri concorrenti sono disposti a promettere. Per esempio la visualizzazione della foto cheriguarda il generico articolo gestito dal vostro programma, oppure la visualizzazione di un catalogoelettronico.Ciò che vi occorre è quindi uno strumento adatto per visualizzare immagini. A tale scopo, e’possibile utilizzare:

un Formun controllo chiamato Pictureun secondo controllo (simile al precedente) chiamato Image.

Vediamo ora come vare.

Immagini contenute in un FormPer visualizzare un’immagine in un Form create un nuovo progetto partendo da zero. Posizionatevi quindisulla finestra principale del progetto (normalmente chiamata Form1), e cercate nella relativa palette delleproprietà la voce Picture. Accanto ad essa trovate un pulsante: premetelo, e vi si aprirà una finestra che vipermette di scegliere il file da visualizzare. Esso deve ovviamente essere di tipo grafico, ossia deve avereun’estensione appartenente al seguente elenco:

BMP, DIB, GIF, JPG, WMF, EMF, ICO, CUR.

Fra gli esempi allegati a questo articolo troverete anche alcune immagini in formato Bitmap, che poteteusare per eseguire i vostri esperimenti. Perciò selezionatene una a caso, e confermate la finestra di sceltafile su cui vi trovate.Potete inserire un’immagine anche importandola dalla ClipBoard di Windows, a patto di avercelaprecedentemente inserita con un editor di disegni. Se così non è allora lanciate, per esempio, il programmaPaint e scarabocchiate qualche cosa al suo interno. Selezionato tale immagine ed inviatela in ClipBoard.Poi tornate in VB, e premete il tasto destro del mouse sul Form. Si apre un menù di contesto: scegliete lavoce Paste (o Incolla) per copiare in automatico l’immagine dalla ClipBoard… al Form.La cancellazione di un’immagine dal Form è un’operazione altrettanto semplice: ritornate sulla palette delleproprietà del Form e riposizionatevi sulla voce Picture. Premete poi il tasto "Canc" assicurandovi che laposizione del cursore sia sul primo carattere della stringa che compare in Picture.Bene, adesso che sapete come inserire e cancellare un’immagine a design time (cioè in fase di creazione),preoccupiamoci di come fare le stesse cose a run time (durante l’esecuzione del programma).

Inserire immagini a Run timePer visualizzare un’immagine a run time, dobbiamo usare un funzione che fa parte della libreria standard diVisual Basic. Il suo nome è piuttosto facile da ricordare, poiché si chiama LoadPicture. Il suo uso èaltrettanto immediato, perché basta eseguire un codice come quello che segue.

Form1.Picture = LoadPicture("ciliegia.bmp")

Per cancellare l’immagine dal Form è sufficiente richiamare la LoadPicture con una stringa vuota:

Form1.Picture = LoadPicture("")

Page 173: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb18/index.htm[26/09/2010 5:32:52]

Oppure eseguire un assegnamento a Nothing:

Form1.Picture = Nothing

Un’altra funzione di fondamentale importanza è la SavePicture, tipicamente utile per salvare un’immaginesu disco. Il suo uso, almeno nella forma, è del tutto simile a quello approntato per la LoadPicture.

Ma attenzione a non perdere i vostri dati: la SavePicture è distruttiva nei confronti del file su cui la fareteoperare, perciò per evitare spiacevoli sovrascritture è bene accertarsi che l'utente sia d'accordo. Unesempio di codice utile per chiedere conferme è il seguente:

Dim bSi As Boolean

bSi = True

If Dir("pippo.bmp") <> "" Then

bSi = MsgBox(_

"Sei sicuro?", _

vbYesNo)

End If

If bSi = True Then

SavePicture _

Form1.Picture, _

"pippo.bmp"

End If

Ricordo che la funzione Dir usata, serve proprio per verificare l'esistenza di un file su disco.

Prima di richiamare la SavePicture dovete inoltre essere certi che all’interno del Form vi sia un’immagine dasalvare, e questo lo ottenete con il seguente codice:

If Form1.Picture <> 0 Then

. . .

End If

Se non farete così, otterrete dal VB un noioso e poco professionale messaggio di errore.

Per leggere un’immagine da ClipBoard, dovete usare il metodo GetData dell’oggetto Clipboard usando ilseguente codice:

Form1.Picture = Clipboard.GetData(vbCFBitmap)

Come avete visto la GetData è molto semplice da usare, perché è sufficiente passare come suo parametroil formato con il quale vogliamo importare l’immagine. I formati disponibili sono pochi, ma sufficienti percoprire la maggior parte delle esigenze:

vbCFBitmap , vbCFMetafile e vbCFDIB.

Ovviamente potrebbe non esserci nulla di interessante in ClipBoard, o per lo meno nulla che assomigli adun formato grafico (potrebbe ad esempio esserci del semplice testo proveniente da un editor). Perciò primadi richiamare la GetData, potete usare il metodo GetFormat per scoprire se ci sono immagini di prontoutilizzo. Per esempio con il seguente costrutto If, è possibile verificare se in ClipBoard esiste un immaginedi tipo Bitmap:

Page 174: Corso Visual Basic

.

file:///C|/Documents and Settings/alberto/Desktop/access/corsovb/Vb18/index.htm[26/09/2010 5:32:52]

If Clipboard. GetFormat( vbCFBitmap) ThenForm1.Picture = Clipboard.GetData( vbCFBitmap)End If

Per salvare un’immagine anche in ClipBoard dovete usare il metodo SetData dell’oggetto Clipoard. Eccocome fare:

Clipboard.SetData Form1.Picture, vbCFBitmap

Tutto ciò che sino ad ora avete appreso in via del tutto teorica, lo potete sperimentare dal vivo usandoFORM.VBP (reperibile sul sito ftp di Infomedia), che ho preparato utilizzando la versione 6 del VisualBasic.Ma adesso è tempo di occuparci di nuove cose, ossia del controllo Image che ci permette diperimetrare un’immagine…

Il controllo ImageA volte visualizzare un’immagine in un Form è sconveniente, perché non si può controllare né la suaposizione video, né la sua dimensione. Se queste esigenze sono (o saranno) anche le vostre, allora poteteusare il controllo Image, appositamente progettato per visualizzare immagini.Image è presente nella palettedei controlli tramite l’icona visibile in Figura 1.Il suo uso è piuttosto semplice: selezionatelo dalla palette, edinseritelo all’interno di un Form così come fate di solito per ogni altro classico componente VisualBasic.Dopodiché, con esso potrete fare le stesse cose previste per i Form, riciclando quindi lo stesso codiceVB. Ovviamente là dove compariva la scritta Form1, ora deve apparire la scritta Image1. È la stessa cosache ho fatto io per l’esempio IMAGE.VBP (reperibile presso il sito ftp di Infomedia) che è un’opportunacopia del precedente progetto FORM.VBP.La proprietà fondamentale di Image si chiama Stretch. Se essa èimpostata al valore True, allora il controllo Image stirerà in lungo e in largo l’immagine, sino a quando essanon coprirà l’intera superficie video perimetrata dal controllo stesso. Perciò la prima immediataconseguenza visuale dell’operazione di Strech, è la trasformazione dei cerchi in ellissi e dei quadrati inrettangoli.Se invece tale proprietà è impostata al valore False, allora l’immagine si estenderà oltre il perimetro delcontrollo Image, a partire però dal suo angolo superiore sinistro.

Il controllo PictureUn’apparente ridondanza del controllo Image è il controllo Picture. Sembrano simili, ma non lo sonoaffatto.Picture è un controllo abbastanza duttile nelle sue funzionalità, perché dotato di alcuni strumentinecessari per agire sull’immagine in esso visualizzata. Attenzione però: il controllo Picture non è unelaboratore di immagini come ad esempio lo è Paint Shop Pro, ma un semplice editor grafico non interativoche permette di tracciare figure geometriche fondamentali. Quindi segmenti, rettangoli ed archi di curva.Lasua icona è visibile in Figura 2, mentre il suo utilizzo lo dettaglierò nel prossimo numero di questo corso diprogrammazione Visual Basic.Dunque arrivederci al prossima puntata, e nel frattempo (a mo’ di esercizio),provate ad usare da soli il controllo Picture "aiutandovi" con il manuale in linea del VB. Potrete cosìconfrontare i vostri risultati, con le informazioni che leggerete sul prossimo numero di DEV.

Andrea T.M. Frosini lavora presso il laboratorio di Ricerca e Sviluppo della Top Software S.A di S.Marino,per la quale (negli scorsi dieci anni trascorsi all'interno del team del progetto Passepartout http://www.top-soft.com) si è occupato di programmazione di sistema, di porting, dello sviluppo di componenti per libreriedi base, di interpreti, di compilatori p-code e di tool di sviluppo multipiattaforma usando il linguaggio C/C++.Da diversi anni collabora stabilmente con la redazione di DEV. Può essere contattato tramite l’[email protected].

VB-IT: per tutti gli sviluppatori VB o aspiranti taliVB-IT è la mailing list italiana interamente dedicata a Visual Basic, VBA (Visual Basic for Application) eVBScript. Se sei uno sviluppatore esperto oppure ti interessa il mondo Visual Basic anche solo perdiletto, troverai VB-IT utilissima!Consigli, suggerimenti, trucchi, soluzioni a problemi comuni e molto altro. Per iscriversi, gratuitamente, aVB-IT è sufficiente inviare un messaggio a [email protected] e nel body inserire la stringa:

subscribe vb-it

Una volta iscritto, esponi i tuoi problemi a [email protected] e aiuta gli altri a risolvere i propri. Saràanche un modo per instaurare nuovi rapporti di lavoro, collaborazione ed amicizia!

Page 175: Corso Visual Basic

Figura 1 L

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb18/figura1.htm[26/09/2010 5:32:58]

Figura 1 L’icona del controllo Image.

Page 176: Corso Visual Basic

Figura 2 L

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb18/figura2.htm[26/09/2010 5:33:07]

Figura 2 L’icona del controllo Picture: attenzione a non confonderla con la precedente…

Page 177: Corso Visual Basic

Figura 3 Il programma FORM

file:///C|/Documents%20and%20Settings/alberto/Desktop/access/corsovb/Vb18/figura3.htm[26/09/2010 5:33:14]

Figura 3 Il programma FORM.VBP in azione.

Page 178: Corso Visual Basic