Come
prima cosa esaminiamo due metodi applicabili all'oggetto
DbEngine e che eseguono operazioni del Menù Access
Strumenti / Utilità Database, e precisamente la Compattazione
di un Database (ovvero l'eliminazione fisica dei record
cancellati) ed il Ripristino di un Database danneggiato.
Come in Access il Database non deve essere già aperto.
La sintassi è la seguente:
DbEngine.CompactDatabase
databasedacompattare, nuovodatabase
DbEngine.RepairDatabase database |
Ovviamente
l'utilizzo in una applicazione deve prevedere copie di sicurezza
e, nel primo caso, che il nuovo database sostituisca l'originario
se l'operazione ha esito positivo; pertanto avremo un codice
come il seguente:
(CompactDatabase):
Screen.MousePointer
= 11
DBEngine.CompactDatabase App.Path + "\Rubrica.mdb",
App.Path + "\RubricaNew.mdb"
If Len(Dir(App.Path + "\Rubrica.bak"))
> 0 Then
Kill App.Path + "\Rubrica.bak"
End If
Name App.Path + "\Rubrica.mdb" As App.Path +
"\Rubrica.bak"
Name App.Path + "\RubricaNew.mdb" As App.Path
+ "\Rubrica.mdb"
Screen.MousePointer = 0
RCode = MsgBox("Il Database originario è sato
salvato come Rubrica.bak", _ vbOKOnly, "ATTENZIONE")
|
(RepairDatabase):
Screen.MousePointer
= 11
RCode = MsgBox("Il Database originario viene salvato
come Rubrica.bak", _ vbOKOnly, "ATTENZIONE")
FileCopy App.Path + "\Rubrica.mdb", App.Path
+ "\Rubrica.bak"
DBEngine.RepairDatabase App.Path + "\Rubrica.mdb"
Screen.MousePointer = 0
|
Tra
le proprietà di DbEngine esaminiamo DefaultType;
può assumere i valori dbUseJet o dbUseODBC
e ci permette di specificare di che tipo saranno gli oggetti
Workspace creati, se per MS Jet o per fonti esterne ODBC.
Per quanto riguarda i metodi, oltre ai due precedenti, è
fondamentale CreateWorkspace: l'oggetto Workspace infatti
definisce una sessione per un utente e contiene le collection
Connections, Databases, Groups e Users; tuttavia per semplici
applicazioni che non coinvolgano gruppi di lavoro o utenti
con diversi livelli di accesso useremo tale metodo in una
forma più semplice, ovvero quella che crea il Workspace
di default di MS Jet:
Set
oggettoworkspace = DBEngine.Workspaces(0) |
Anzichè
trattare sistematicamente la creazione degli oggetti esamineremo
un esempio pratico, ovvero la creazione a programma di un
Database con Table e Query.
Partiamo
da un problema concreto: abbiamo scritto una Applicazione
di Gestione dati per un cliente ed è già in
funzione (ovvero il Db non è vuoto).
Si
presenta l'esigenza di modificarlo aggiungendo un campo nuovo
e non possiamo eseguire l'operazione con Access presso il
cliente; facciamo allora un programma che effettua tale operazione.
Per motivi ovvii di sicurezza non operiamo direttamente sul
Db originario ma ne creiamo uno nuovo e poi lo aggiorniamo
con i dati dell'originario.
Se tutto è andato bene facciamo 2 rename e l'operazione
è completata.
Come esempio (banale) vogliamo aggiungere a Rubrica.mdb l'indirizzo
del sito Web e, visto che lo modifichiamo, anche la Query
di selezione per anagrafico (Cognome+Nome).
Nelle
dichiarazioni:
Dim
wksPredef As Workspace
Dim dbsRubrica As
Database
Dim tdfRubrica As
TableDef
Dim qdfRubrica As
QueryDef
Dim rsRubrica As
Recordset
Dim dbsRubricaOld As
Database
Dim rsRubricaOld As
Recordset
Dim Campo As
Field |
Nel
corpo del programma: creiamo il Database
'
se esiste già lo cancella perché altrimenti
' il metodo CreateDatabase darebbe errore
If Len(Dir(App.Path &
"\Rubrica1.mdb")) > 0 Then
Kill App.Path & "\Rubrica1.mdb"
End If
'
apre il Workspace default di MS Jet
Set wksPredef = DBEngine.Workspaces(0)
'
Crea un nuovo oggetto Database, lo salva su disco e
lo apre come Database 'corrente
Set dbsRubrica = wksPredef.CreateDatabase(App.Path
& "\Rubrica1.mdb", _ dbLangGeneral)
|
Abbiamo
creato Rubrica1.mdb ma è un database vuoto; adesso
dobbiamo creare la Table "Rubrica".
'
Crea un nuovo oggetto TableDef.
Set tdfRubrica = dbsRubrica.CreateTableDef("Rubrica")
'
Crea i campi e li accoda al nuovo oggetto TableDef.
' Questa operazione deve essere eseguita prima di accodare
l'oggetto TableDef
' all'insieme TableDefs di Rubrica1.mdb.
With tdfRubrica
Set Campo = .CreateField("Cognome",
dbText, 30)
Campo.Required = True 'il
default è NO
.Fields.Append Campo
Set Campo = .CreateField("Nome",
dbText, 20)
Campo.AllowZeroLength = True
'il default è NO
.Fields.Append Campo
Set Campo = .CreateField("Indirizzo",
dbText, 30)
Campo.AllowZeroLength = True
.Fields.Append Campo
Set Campo = .CreateField("CAP",
dbText, 5)
Campo.AllowZeroLength = True
.Fields.Append Campo
Set Campo = .CreateField("Città",
dbText, 30)
Campo.AllowZeroLength = True
.Fields.Append Campo
Set Campo = .CreateField("Prov",
dbText, 3)
Campo.AllowZeroLength = True
.Fields.Append Campo
Set Campo = .CreateField("TelefonoC",
dbText, 12)
Campo.AllowZeroLength = True
.Fields.Append Campo
Set Campo = .CreateField("TelefonoU",
dbText, 15)
Campo.AllowZeroLength = True
.Fields.Append Campo
Set Campo = .CreateField("Telefonino",
dbText, 12)
Campo.AllowZeroLength = True
.Fields.Append Campo
Set Campo = .CreateField("Fax",
dbText, 15)
Campo.AllowZeroLength = True
.Fields.Append Campo
Set Campo = .CreateField("EMail",
dbText, 30)
Campo.AllowZeroLength = True
.Fields.Append Campo
Set Campo = .CreateField("Web",
dbText, 30)
Campo.AllowZeroLength = True
.Fields.Append Campo
End With
'
accoda il nuovo oggetto all'insieme TableDefs
dbsRubrica.TableDefs.Append tdfRubrica
Label1.Caption = "Creazione di Rubrica1.mdb effettuata"
Label1.Visible = True
'
chiude il Database
dbsRubrica.Close
|
Alcuni
commenti: innanzitutto le note sulla creazione di un oggetto
TableDef ed il suo successivo accodamento all'insieme
TableDefs; non è automatico come la creazione
di un oggetto Database ed il suo accodamento all'insieme Databases.
Inoltre per poterlo accodare deve essere già stato
definito l'insieme base Fields, necessario per l'esistenza
stessa dell'oggetto Table.
L'istruzione di creazione/accodamento degli oggetti Field
avrebbe potuto essere scritta:
.Fields.Append
.CreateField("nomecampo", tipocampo, lunghezza) |
ma
in tal caso le proprietà del campo sarebbero state
quelle di default ed in particolare Richiesto = No e Consenti
lunghezza zero = NO.
Un metodo più sofisticato (e da seguire) sarebbe stato
quello di aprire il database Rubrica.mdb e quindi la Table
Rubrica ed utilizzare un loop For sugli oggetti Field di Rubrica
creando un oggetto Field della table Rubrica di Rubrica1.mdb
per ogni oggetto Field della table Rubrica di Rubrica.mdb
con lo stesso Name, Type, Size, Required ed AllowZeroLength
con un codice del tipo seguente (rsRubricaOld è la
Table Rubrica di Rubrica.mdb) nel blocco With:
For I = 0 To
rsRubricaOld.Fields.Count - 1
Set Campo = .CreateField(rsRubricaOld.Fields(I).Name,
_
rsRubricaOld.Fields(I).Type, rsRubricaOld.Fields(I).Size)
Campo.Required = rsRubricaOld.Fields(I).Required
Campo.AllowZeroLength = rsRubricaOld.Fields(I).AllowZeroLength
.Fields.Append Campo
Next I
Set Campo = .CreateField("Web",
dbText, 30)
Campo.AllowZeroLength = True
.Fields.Append Campo |
La
ragione per cui non lo abbiamo utilizzato è la minore
immediatezza, ma è più sicuro (non possiamo
sbagliare le proprietà dei campi) e quindi da usare
sempre.
La creazione di una Query è invece molto più
semplice: il metodo .CreateQueryDef accoda automaticamente
la query all'insieme QueryDefs del database se il nome della
query non è una stringa nulla:
'
Crea un nuovo oggetto QueryDef.
Set qdfRubrica = dbsRubrica.CreateQueryDef("Alfabetico",
MySQL) |
dove
in MySQL abbiamo precedentemente messo la stringa SQL voluta
non perché era necessario ma per una migliore leggibilità
del programma; possiamo infatti scrivere anche:
Set
qdfRubrica = dbsRubrica.CreateQueryDef("Alfabetico",
"SELECT Cognome, Nome, _ Telefono, TelefonoU, Cognome
& " & Chr$(34) & " " &
Chr$(34) & " & Nome AS _ Anagraf FROM Rubrica
ORDER BY Anagraf") |
ma poi potremmo anche non capirci più nulla.
A questo punto non ci rimane che vedere come si crea un Indice
ed abbiamo visto tutto quello che ci serve per creare un database
od aggiungere nuovi oggetti ad un database esistente, perché
il metodo è lo stesso; l'unica avvertenza è
che i metodi di creazione degli oggetti DAO danno un errore
di run-time se l'oggetto che si vuole creare esiste già.
Set dbsRubrica = OpenDatabase(App.Path
& "\Rubrica1.mdb")
Set tdfRubrica = dbsRubrica!Rubrica
With
tdfRubrica
' Crea il primo oggetto Index, crea
e accoda gli oggetti Field all'oggetto Index ' e accoda
l'oggetto Index all'insieme Indexes dell'oggetto TableDef.
Set idxNome = .CreateIndex
With idxNome
.Name = "Rubrica"
.Fields.Append .CreateField("Cognome")
.Fields.Append .CreateField("Nome")
End With
.Indexes.Append idxNome
.Indexes.Refresh
End With
dbsRubrica.Close
|
Non
ci resta altro che aprire entrambi i database ed entrambe
le Table Rubrica ed inserire in una i records presenti nell'altra,
ma ormai siete diventati bravi e la parte del programma relativa
la capite da soli senza bisogno di commentarla.
Ovviamente daremo una struttura logica al programma, con bottoni
di comando da abilitare in cascata e Label che segnalano il
compimento delle varie fasi; il programma completo si chiama
CreaDAO e tutti i files di progetto sono contenuti in CreaDAO.zip
(Download - 3Kb); non è stata inclusa la parte relativa
al rename di Rubrica.mdb->Rubrica.bak e Rubrica1.mdb->Rubrica.mdb
perché si presuppone che prima di farlo un programmatore
voglia controllare che il programma sia andato bene ! (altrimenti
è meglio che si metta a vendere bruciate: guadagnerà
di più e combinerà meno casini).
» "DAO
Object Model: The Definitive Reference" di Helen
Feddema capitolo 2: "DBEngine
Object"
» "Data
Access Object Reference" introduzione al "DBEngine
Object"
|