Utilizzando
il controllo Data è possibile eseguire le operazioni
più comuni scrivendo solo poche righe di codice (al
limite nessuna).
Vediamo un esempio pratico: nella finestra di progettazione
creiamo un nuovo progetto, chiamiamo il Form Esempio1, scegliamo
come font Arial 9 (per schermo 800x600), inseriamo un Frame
a cui diamo come Caption "record corrente" (questo
è solo per scopi estetici) e inseriamo nel Frame un
controllo Data.
Gli diamo come Caption "Rubrica" (è più
estetico di Data1), in Databasename scegliamo il file Rubrica.mdb,
modifichiamo Exclusive in True (per abituarci a pensare che
potremmo non essere l'unico utente che accede al Db), modifichiamo
il tipo da Dynaset a Table e scegliamo la tabella Rubrica.
Aggiungiamo, sempre nel Frame, un controllo Text e gli assegnamo
come DataSource Data1, poi scegliamo come DataField il primo,
Cognome.
Copiamo poi Text1, confermando che vogliamo creare una matrice
di controlli, tante volte quanto è necessario modificando
ogni volta il DataField, la lunghezza della casella e la proprietà
MaxLength per i vari campi.
Oltre che più comodo creare istanze multiple di un
controllo è anche una buona abitudine di programmazione,
in quanto in questo modo si utilizzano meno risorse del Sistema.
Aggiungiamo poi delle Label per dire che campi sono ed il
nostro programma è pronto; consente di scorrere la
tabella Rubrica e modificare il contenuto dei records presenti:
infatti se modifichiamo il contenuto di uno o più dei
campi Text automaticamente modificheremo il Database.
Ma se modificheremo un record e poi terminiamo il programma
senza spostarci di record tramite il controllo Data vedremo
la volta dopo che le ultime modifiche si sono perse: infatti
le modifiche vengono scritte sul Db quando ci si sposta ad
un altro record.
Dovremo quindi rimediare aggiungendo del codice: clicchiamo
Form, scegliamo Unload ed aggiungiamo:
Private
Sub
Form_Unload(Cancel As Integer)
Data1.Recordset.MoveLast
End Sub |
Così
il primo problema è risolto.
Ma ne abbiamo un altro: in Databasename del controllo Data
c'è un indirizzo assoluto (nel mio caso "D:\Programmi\Vb98\Esempi\Database\Rubrica.mdb"),
mentre normalmente si vuole che Db e Programma stiano nella
stessa Cartella; inoltre Rubrica ha un indice per Cognome,
Nome chiamato Rubrica e vogliamo che i record compaiano in
ordine. Aggiungiamo altro codice, questa volta in Form_Laod:
Private
Sub
Form_Load()
Data1.DatabaseName = App.Path & "\Rubrica.mdb"
Data1.RecordSource = "Rubrica"
Data1.Refresh
' Impostiamo l'indice da usare (Cognome,
Nome)
Data1.Recordset.Index = "Rubrica"
End Sub |
Visto
che è necessario anche inserire nuovi record (la prima
volta il Db è vuoto ed il programma non servirebbe
a nulla) ed è utile potere anche cancellare inseriamo
due Bottoni ed aggiungiamo una Label per avvertire se non
ci sono record; il Form avrà questo aspetto:
Naturalmente
Label1.Visible = False e Command1(0).Enabled = False.
Dovremo preoccuparci di vedere se ci sono o meno records e
decidere a programma come settarli; inoltre dovremo scrivere
il codice per gestire DELETE (Command1(0)) ed INSERT (Command1(1))
e tenere presente che queste operazioni possono rendere Rubrica
vuota o meno.
Il nostro programma sarà quindi scritto così:
Private
Sub
Command1_Click(Index As Integer)
If Index = 0 Then
'
Cancella record corrente
Data1.Recordset.Delete: Data1.Recordset.MoveNext
If Data1.Recordset.RecordCount
= 0 Then '
non ci sono più record
Label2.Visible = True: Command1(0).Enabled
= False
End If
Exit Sub
End If
If Index = 1 Then
' Inserisci un record vuoto
Data1.Recordset.AddNew
Data1.Recordset("Cognome") = " "
Data1.Recordset.Update
' fa divenire record corrente quello
aggiunto
Data1.Recordset.Bookmark = Data1.Recordset.LastModified
' abilita tasto DELETE perché
c'è almeno 1 record
Command1(0).Enabled = True:
Label2.Visible = False
' seleziona il blank del Cognome
Text1(0).SelStart = 0: Text1(0).SelLength = Len(Text1(0).Text):
Text1(0).SetFocus
Exit Sub
End If
End Sub
Private
Sub
Form_Load()
Data1.DatabaseName = App.Path & "\Rubrica.mdb"
Data1.RecordSource = "Rubrica"
Data1.Refresh
' Impostiamo l'indice da usare (Cognome,
Nome)
Data1.Recordset.Index = "Rubrica"
If Data1.Recordset.RecordCount
> 0 Then
Data1.Recordset.MoveFirst ' altrimenti
se Rubrica è vuoto da un errore
Command1(0).Enabled = True
'
abilita tasto DELETE
Else
Label2.Visible = True
End If
End Sub
Private
Sub
Form_Unload(Cancel As Integer)
If Data1.Recordset.RecordCount
> 0 Then
' se non si sposta il puntatore di
record dopo avere variato i campi 'l'aggiornamento non
viene effettuato
Data1.Recordset.MoveLast
End If
End Sub |
Il
nostro programmino comincia ad essere abbastanza a posto;
lo proviamo, funziona tutto, etc. Ma l'appetito vien mangiando
e lo vogliamo rendere più completo: farebbe comodo
vedere in una lista tutti i records e poter scegliere quello
voluto e posizionarlo come record corrente.
Per fare questo ci serve un nuovo controllo, il DbList, che
non è tra quelli di default.
Per aggiungerlo clicchiamo Progetto, Componenti, cerchiamo
nella lista Microsoft Data bound List Control, lo spuntiamo
e clicchiamo OK.
Questo controllo si presenta come un List Box ma tra le sue
proprietà ci sono quelle collegate ai dati; ci interessano
RowSource e ListField: la prima è il
controllo Data collegato, la seconda il campo che verrà
listato.
Però abbiamo un problema: se usiamo il campo Cognome
come facciamo se abbiano 2 record con lo stesso cognome e
nomi diversi?
Facciamo attenzione a questo punto perché la soluzione
potrà servirci anche in futuro!
Creiamo un altro controllo Data (Data2), lo assegnamo allo
stesso Database di Data1, ma come RecordsetType lasciamo 1
- Dynaset e come RecordSource usiamo una SQL:
SELECT
Cognome, Nome, Cognome & ' ' & Nome AS Anagraf
FROM Rubrica ORDER BY Cognome, Nome |
C'è
una novità! Infatti nell'elenco campi della SQL non
compare un campo o una funzione di aggregazione, ma una espressione
campi (Cognome & ' ' & Nome) seguita da AS Anagraf
(tecnicamente detto Alias): abbiamo creato un nuovo campo
e gli abbiamo dato come "Header di Colonna" Anagraf;
l'espressione campi può essere qualsiasi, ad esempio
Importo * 1,2 AS ConIva, od anche più complicata e
questo ci potrà essere utile in futuro.
Impostiamo a Data2 ReadOnly = True (non si sa mai) e Visible
= False (non serve per scorrere i records) e mettiamo al nostro
DbList RowSource = Data2 e ListField = Anagraf.
il Form avrà questo aspetto:
Aggiungiamo
al programma il codice necessario:
Oltre a ricordarsi di mettere in Form_Load Data2.DatabaseName
= Data1.DatabaseName, per gestire il posizionamento sul record
scelto bisogna aggiungere:
Private
Sub
DBList1_Click()
' posiziona Data2 su quello selezionato
Data2.Recordset.Bookmark = DBList1.SelectedItem
' Ricerca per chiave su Data1
Data1.Recordset.Seek "=", Data2.Recordset("Cognome"),
Data2.Recordset("Nome")
End Sub |
Il
controllo DbList non viene aggiornato automaticamente se variamo,
aggiungiamo o cancelliamo records da Data1, per cui dobbiamo
aggiungere:
Private
Sub
Data1_Reposition()
Data2.Refresh
DBList1.ReFill
End Sub |
Il
nostro programma è terminato: i files di progetto Vb6
e Rubrica.mdb sono contenuti in Esempio1.zip
(Download
- 11kb)
Se
dobbiamo realizzare una applicazione per terzi lo schema seguito
necessita di alcuni miglioramenti. Infatti non possiamo aggiornare
in diretta il Database, ma dobbiamo farlo solo dopo avere
controllato i dati immessi e dopo che l'utente abbia confermato
l'operazione.
Pertanto dovremo operare nel modo seguente:
1 - Utilizzare nel Frame esistente label al posto di Text1
per la sola visualizzazione;
2 - Aggiungere un altro pulsante: EDIT;
3 - Creare un altro frame come quello attuale e nella stessa
posizione ma con i campi Text non collegati a Data1 e con
2 pulsanti OK e Cancel e porre il frame con Visible = False;
4 - Al click di EDIT riempire i Text del 2° frame con
le Caption delle label, renderlo visibile e mettere DbList1.Enabled
= False;
5 - Al click di INSERT mettere a "" i Text del 2°
frame, renderlo visibile e mettere:
6
- Effettuare Data1.Recordset.Edit o Data1.Recordset.AddNew,
mettere nei campi di Data1 il contenuto dei Text ed eseguire
Data1.Recordset.Update quando viene cliccato OK e solo dopo
avere controllato la congruità dei dati immessi (segnalando
gli errori se ci sono), quindi rendere di nuovo invisibile
il frame e riabilitare DbList1;
7 - Se viene cliccato Cancel rendere invisibile il frame e
riabiltare DbList1.
Disabilitare DbList1 è necessario, perché se
viene cliccato sposta il record corrente mentre stiamo aggiornando!
Non sarà più necessario spostare il puntatore
dopo un aggiornamento in quanto il metodo Update provvede
a rendere effettiva la modifica.
Il programma così modificato si chiama Esempio2 ed
i files Vb6 relativi sono contenuti in Esempio2.zip (Download
- 5kb). Oltre che utilizzarlo come vi pare potete stampare
Esempio1 ed Esempio2 e confrontarli.
Inoltre potrebbe essere utile aggiungere la possibilità
di ricercare i record per Chiave parziale: possiamo
aggiungere una casella Textn ed all'evento Keypress eseguire:
Data1.Recordset.Seek
">=", Textn.Text
|
Teniamo
però presente che la chiave è "case sensitive"
(Mal, mal e MAL non sono la stessa cosa), per cui nel caso
del nostro esempio dovremo porre maiuscola (UCase$)
la 1a lettera del Text e minuscole (LCase$) le successive
prima di eseguire la Seek.
In
questo modo abbiamo anche visto il trattamento di un Database
tramite oggetti DAO, anche se si tratta di oggetti impliciti
ovvero creati automaticamente dal sistema: Data1.Recordset
è un oggetto a tutti gli effetti e supporta tutti i
Metodi e le Proprietà degli oggetti Recordset.
Nella Lezione 6 tratteremo oggetti espliciti, ovvero creati
da noi tramite codice, e vedremo come trattarli.
» "ADO:
Methods, Properties, Events, Collection" dal sito
DevGuru
|