prog_Subito2liv.jpg (18041 byte)

Questo mese il corso dedicato a Visual Basic è ancora dedicato ai database. Oggetto di studio 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

capoletteraI.jpg (5705 byte) database sono insiemi di dati organizzati secondo strutture ben definite, aventi lo scopo di rendere agevole la gestione e la ricerca delle informazioni. Lo studio delle modalità con cui è possibile localizzare dei record all’interno di un archivio costituisce lo scopo di questa lezione, che ha come protagonista 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 soluzione dell’esercizio proposto nella scorsa lezione.
L’applicazione rappresenta una semplice rubrica telefonica, in grado di consentire l’inserimento di nuove voci e la cancellazione di quelle eventualmente esistenti. La sua realizzazione prevede dapprima la creazione di un database per mezzo di un apposito strumento (ad esempio Microsoft Access) e l’inserimento in esso di una tabella, a cui si dà il nome Rubrica, caratterizzata dal possedere 7 campi di tipo alfanumerico, denominati Cognome, Nome, Indirizzo, Comune, Telefono, Fax, eMail. Il passo successivo prevede la creazione di un form, su cui va inserito un oggetto di tipo Data, a cui è assegnato il nome dbArchivio. 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 della proprietà RecordSource. Il form deve poi essere completato con le caselle di testo destinate ad accogliere le 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 il campo contenente le informazioni da visualizzare. L’applicazione è completata con l’inserimento nel form dei pulsanti che permettono l’aggiunta di un nuovo record, la memorizzazione dei dati in esso inseriti e la cancellazione 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 procedure associate ai pulsanti btnNuovo, btnCancella e btnAggiorna sono pertanto le seguenti:

Private Sub btnNuovo_Click()
dbArchivio.Recordset.AddNew
End Sub
Private Sub btnCancella_Click()
dbArchivio.Recordset.Delete
End Sub
Private 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. In questi casi occorre inserire nel form dei pulsanti che consentano la selezione degli elementi posti in archivio.
Per mezzo del metodo MoveFirst dell’oggetto Recordset, è possibile fare in modo che il primo elemento presente in archivio diventi il record corrente. In pratica, il suddetto metodo provoca un effetto analogo a quello della pressione del pulsante posto all’estrema sinistra dell’oggetto Data. Volendo quindi inserire nel form il pulsante btnPrimo, in grado di selezionare il primo record presente in archivio, occorre digitare il seguente codice:

Private Sub btnPrimo_Click()
dbArchivio.Recordset.MoveFirst
End Sub

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

Private Sub btnUltimo_Click()
dbArchivio.Recordset.MoveLast
End Sub

Il passaggio al record successivo o precedente

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

Private Sub btnPrecedente_Click()
If not dbArchivio.Recordset.BOF Then
dbArchivio.Recordset.MovePrevious
End If
End Sub
Private Sub btnSeguente_Click()
If not dbArchivio.Recordset.EOF Then
dbArchivio.Recordset.MoveNext
End If
End 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 al successivo. 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, si aggiunge al form il pulsante btnCerca, a cui è associato il seguente codice:

Private Sub btnCerca_Click()
Dim Ripeti As Boolean
Dim Trovato As Boolean
Dim DaCercare As String
DaCercare = InputBox("Stringa da cercare:")
dbArchivio.Recordset.MoveFirst
Do
Trovato = (txtCognome.Text = DaCercare)
Ripeti = Not (dbArchivio.EOF Or Trovato)
If Ripeti Then
dbArchivio.Recordset.MoveNext
End If
Loop While Ripeti
If Not Trovato Then
MsgBox "Stringa non trovata"
End If
End Sub

La stringa da cercare, richiesta per mezzo della funzione InputBox, è confrontata con il contenuto del campo Cognome, associato all’elemento txtCognome. La ricerca avviene in modo sequenziale a partire dal primo record. La soluzione presentata permette di ricercare il primo record caratterizzato dall’uguaglianza del contenuto del campo Cognome rispetto alla stringa inserita dall’utente. Tuttavia, il numero delle righe di codice necessarie per la sua realizzazione è elevato. Ciò è in contrasto con una della caratteristiche che fanno dei database delle strutture pressoché onnipresenti in tutte le applicazioni gestionali, ovvero la possibilità 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 ricerche va ben oltre quanto illustrato fino ad ora. Per la localizzazione di elementi fra quelli posti in archivio, 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 ricercare rispettivamente il primo e l’ultimo elemento in grado di soddisfare il criterio specificato. FindNext e FindPrevious permettono invece rispettivamente la localizzazione del record successivo e del precedente fra quelli in grado di soddisfare una data condizione. La sintassi è pressoché identica per tutti e 4 i metodi e 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 il valore da ricercare. Si noti che ai comuni operatori di confronto (=, >, <, <>, >=, <=) ne è stato aggiunto un altro, denominato LIKE. Quest’ultimo permette di confrontare due stringhe in modo meno rigido rispetto al normale operatore di uguaglianza. In sostanza, fa sì che la verifica abbia esito positivo non solo se due stringhe sono identiche, bensì anche quando una costituisce solo l’inizio dell’altra. Per comprendere questo concetto, si consideri l’esempio che segue.
Si supponga di disporre di un database in cui sono presenti dei record aventi fra gli altri un campo denominato 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 del metodo

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". Si noti 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 di gestione del database riconosce infatti la sequenza "Viva l". I caratteri mancanti, non essendo riconosciuti come parte della stringa, causano la generazione di un messaggio di errore. Per ovviare a questo inconveniente, è opportuno l’utilizzo delle virgolette (") per delimitare le stringhe da cercare. Per consentire che siano interpretate da Visual Basic correttamente, essendo esse utilizzate anche per racchiudere la stringa 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 se l’ultima ricerca effettuata è andata a buon fine. Dopo aver eseguito una ricerca per mezzo di uno fra i metodi 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. In quest’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 è il seguente:

Private Sub btnCerca_Click()
Dim DaCercare As String
Dim Criterio As String
DaCercare = InputBox("Stringa da cercare:")
Criterio = "Nome = """ & DaCercare & """"
dbArchivio.Recordset.FindFirst
If dbArchivio.Recordset.NoMatch Then
MsgBox "Stringa non trovata"
End If
End Sub

Com’è possibile notare, il numero delle righe di codice è diminuito. La nuova procedura si limita a chiedere la stringa da cercare ed a comporre il parametro da passare al metodo FindFirst. Una successiva verifica della proprietà NoMatch permette di stabilire l’opportunità della visualizzazione di un messaggio di errore indicante 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 che costituisce l’applicazione modificata è visibile nel listato 1 ed è disponibile su Internet per il download all’indirizzo http://www.infomedia.it. Com’è possibile osservare in figura, sono stati aggiunti al form una casella di testo, denominata txtCerca, un pulsante (btnCerca) e 4 option button. La textbox ha lo scopo di contenere 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. Si tratta di pulsanti caratterizzati dall’annullarsi a vicenda. Questo tipo di componenti prende spesso il nome radio button, in quanto ricorda i comandi che permettono di cambiare la banda di frequenze nelle radio. Per mezzo degli option button, l’utente può selezionare una sola modalità di ricerca fra quelle disponibili. Esse corrispondono ai metodi FindFirst, FindLast, FindNext, FindPrevious. La ricerca è avviata dalla pressione del pulsante btnCerca. Il codice ad esso associato si limita a comporre la stringa che costituisce il criterio di selezione 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 la proprietà NoMatch dell’oggetto Recordset assume il valore logico true, è visualizzato un messaggio di errore.

Conclusioni

La potenza e la flessibilità dei database permettono di gestire grandi quantità di informazioni. Grazie ai metodi di ricerca, diventa estremamente semplice provvedere alla localizzazione all’interno degli archivi delle informazioni desiderate. In attesa di approfondire ulteriormente l’argomento database nel prossimo numero, si provi ad aggiungere alla rubrica telefonica descritta in precedenza la capacità di richiedere una stringa e di contare i record presenti in archivio che contengono nel campo Cognome la sequenza alfanumerica 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ò essere contattato tramite Internet all’indirizzo mcrespi@infomedia.it.

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) e VBScript. 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, a VB-IT è sufficiente inviare un messaggio a
majordomo@infomedia.it e nel body inserire la stringa: subscribe vb-it Una volta iscritto, esponi i tuoi problemi a vb-it@infomedia.it e aiuta gli altri a risolvere i propri. Sarà anche un modo per instaurare nuovi rapporti di lavoro, collaborazione ed amicizia!