Creare add-in per Microsoft Access
di Gionata Aladino Canova (VBJ n° 62)
Automatizzare i compiti ripetitivi riduce la possibilità di commettere errori, migliora
l’efficienza e rende il programmatore più sorridente.
Il programmatore è un animale particolare, generalmente pigro ma dotato di molta
inventiva. Chi ha letto "Gli uomini vengono da Marte e le donne da Venere",
capisce facilmente che, per le sue caratteristiche, il programmatore è quasi sempre
maschio. Date un problema ad un programmatore ed esso ve lo risolverà. Affidate
allo stesso individuo un compito ripetitivo: dopo poche iterazioni vi svilupperà
un sistema che faccia il lavoro al posto suo; questo succede anche se, in termini
di lavoro complessivo, la seconda soluzione dovesse essere più onerosa! Tralasciando
le considerazioni filosofiche, tutte le volte che si automatizza un processo ripetitivo,
si produce più in fretta e si riduce la possibilità di commettere errori. In questo
articolo vedremo come sviluppare uno strumento atto allo scopo, che funziona dal
lato Access, mentre in un prossimo appuntamento vedremo come sviluppare una ulteriore
aggiunta per l’editor VBE. Tale strumento è
liberamente scaricabile ed il suo utilizzo è gratuito; è fornito completo
di sorgenti che possono essere modificati e ridistribuiti a condizione di non rimuovere
le indicazioni sull'autore. Per la comprensione dell’articolo serve una
discreta padronanza dell’ambiente di Access e la conoscenza del VBA; i concetti
esposti sono validi da Microsoft Access 2000 in poi.
Motivi per estendere le funzionalità di Microsoft Access
Microsoft Access ha avuto un buon successo poiché unisce la potenza di un database
relazionale alla facilità di utilizzo tipica dei prodotti Microsoft. Sono fornite
di base autocomposizioni che creano piccole applicazioni già funzionanti; esistono
poi una vasta gamma di wizard che aiutano l’utente nei compiti più disparati.
Il limite di questi strumenti sta nell’essere stati creati per accontentare
il massimo numero di utenti possibile, si tratta cioè di strumenti orizzontali.
Quando, nel creare le nostre applicazioni, ci troviamo di fronte ad un compito ripetitivo
per cui non esiste nessun strumento in Access, probabilmente abbiamo un’esigenza
verticale. Il primo passo per creare la nostra cassetta di lavori sarà un’attenta
analisi di quello di cui avremo veramente bisogno. Appena scoperto cosa si può fare
con una semplice toolbar, è facile cadere nella tentazione di aggiungerci tutto
quello che ci viene in mente. Selezioniamo invece ciò che ci è realmente utile e
sviluppiamolo al meglio.
Tipi di aggiunte
Le funzionalità di Microsoft Access possono essere estese in diversi modi. Per lavorare
con Microsoft Access è necessario avere un database aperto. Per i nostri scopi,
consideriamo di avere aperto il database VBJ.mdb. Possiamo scrivere una routine
VBA che colori tutte le maschere del database con un colore specifico, salvarla
dentro VBJ.mdb stesso e richiamarla dalla finestra di debug. Oppure possiamo salvare
la routine in un database di libreria ed agganciarlo dall’editor VBE tramite
l’opzione Strumenti, Riferimenti. Lo svantaggio di questi approcci è che le
routine sono incluse nell’applicazione e che serve una certa conoscenza per
utilizzarle. Il primo limite si avverte particolarmente quando le applicazioni gestite
sono molte, mentre il dover conoscere bene uno strumento per poterlo utilizzare
è controproducente nell'ambito di un gruppo, in quanto potrebbe portare alcune
persone a non servirsene. Gli wizard, oltre a velocizzare il lavoro, aiutano a mantenere
determinati standard, sia di interfaccia grafica che di codifica.
Le aggiunte vere e proprie, o add-in, si classificano in
- Menu componenti aggiuntivi: forniscono pulsanti o menu per funzionalità aggiuntive
e si trovano sotto Strumenti, Componenti aggiuntivi
- Creazioni guidate: vengono lanciate creando degli oggetti, come le maschere
- Creazioni guidate di controlli: sono gli aiuti lanciati automaticamente alla creazione
di un nuovo controllo
- Generatori: vengono lanciati dal pulsante genera presente sul foglio delle proprietà
di un oggetto ed aiutano ad impostare la proprietà a cui appartengono
Inoltre si possono utilizzare aggiunte anche per l’editor VBE. Vediamo adesso
come costruire una barra degli strumenti come menu componente aggiuntivo. Per maggiori
dettagli e per gli altri tipi di aggiunte, si veda [1].
Creare ed utilizzare un add-in
Il processo per creare un menu componente aggiuntivo è poco più complicato di quello
che serve per generare un’applicazione. Creiamo il database VBJWiz.mdb. Tramite
il menu File/Proprietà scriviamo nei campi
- Titolo: Il nostro primo add-in
- Società: VBJ
- Commenti: Versione 1.0 rilasciata il 1 marzo 2005
Impostiamo una tabella con i campi revisione di tipo testo e descrizione di tipo
memo. Salviamola con il nome tblHistory e lasciamo che Microsoft Access imposti
per noi un campo contatore. Adesso creiamo su questa tabella, tramite l’autocomposizione,
una maschera standard. Salviamola con il nome frmHistory. Creiamo un modulo in cui
inseriamo il codice
Option Compare Database
Option Explicit
Function VBJWizStart()
DoCmd.OpenForm "frmHistory"
MsgBox "Il Wizard è partito!", vbInformation, "VBJ Wizard"
End Function
Function VBJWizMiaFunzione()
Dim str As String
Select Case Application.CurrentProject.ProjectType
Case acADP
str = "Il wizard sta lavorando per un file .adp."
Case acMDB
str = "Il wizard sta lavorando per un file .mdb."
Case Else
str "Impossibile determinare il tipo di progetto."
End Select
MsgBox str & vbCrLf & "Oggi è il " & Date, _
vbInformation, "VBJ Wizard"
End Function
Salviamo il modulo con il nome modStart. Tramite Strumenti, Proprietà di Access<numero
versione>, impostiamo il nome del progetto a VBJWizard. Creiamo una toolbar chiamandola
VBJToolbar. Aggiungiamo dalla sezione Comandi, Categorie, Struttura Maschera/Report
il pulsante Allinea a sinistra. Duplichiamo il pulsante e impostiamo sul duplicato,
tramite tasto destro, Proprietà:
- Didascalia: Visualizza la data
- Azione: =VBJWizMiaFunzione()
Volendo, possiamo cambiarne l’icona. Chiudiamo il database e rinominiamo il
file in VBJWiz.mda, che è l’estensione standard per le aggiunte.
Adesso dobbiamo creare una tabella che consenta ad Access di recuperare le informazioni
di installazione della nostra aggiunta. Tramite il menu Strumenti, Opzioni, Visualizzazione,
abilitare l’opzione Oggetti di sistema che consente la visualizzazione degli
oggetti di sistema.
Creiamo una tabella con i seguenti campi:
- Subkey (testo -255 caratteri)
- Type (Intero lungo)
- ValName (testo -255 caratteri)
- Value (testo -255 caratteri)
Salviamo la tabella con il nome USysRegInfo ed aggiungiamo quattro record con le
informazioni riportate in Tabella 1.
Tabella1: Informazioni da inserire nella tabella USysRegInfo
Subkey
|
Type
|
ValName
|
Value
|
HKEY_LOCAL_MACHINE\Software\Microsoft\Office\11.0\Access\Menu Add-Ins\&VBJ
Toolbar
|
0
|
|
|
HKEY_LOCAL_MACHINE\Software\Microsoft\Office\11.0\Access\Menu Add-Ins\&
VBJ Toolbar
|
1
|
Expression
|
=VBJWizStart()
|
HKEY_LOCAL_MACHINE\Software\Microsoft\Office\11.0\Access\Menu Add-Ins\&
VBJ Toolbar
|
1
|
Library
|
|ACCDIR\VBJWiz.mda
|
HKEY_LOCAL_MACHINE\Software\Microsoft\Office\11.0\Access\Menu Add-Ins\&
VBJ Toolbar
|
4
|
Version
|
3
|
Il campo SubKey è uguale per tutti e quattro i record; se utilizzate Access 2003
il valore giusto è 11.0, per Access XP è 10.0 e per Access 2000 è 9.0. Nel campo
value del secondo recorde 9.0 per Access 20000eomandi –iciente considerare
che gli wizard di Access sono realizzati in Access! teca delle maschere, dei
è riportata la funzione che verrà lanciata al caricamento dell’aggiunta e
nel terzo record il nome del file contenente la nostra aggiunta. Come si nota, l’aggiunta
potrebbe essere memorizzata in qualsiasi cartella, sarebbe sufficiente sostituire
la keyword ACCDIR con il percorso completo. Il quarto record è in realtà
opzionale: se non viene aggiunto, l’add-in sarà disponibile solo per i database
(file .mdb). Se il valore del campo value è impostato a 1, l’add-in sarà disponibile
solo per i database (file .mdb); 2 per rendere disponibile l’add-in per i
file di progetto (file .adp); 3 rende disponibile l’add-in per entrambi i
tipi di file. In realtà la tabella USysRegInfo consente molte altre possibilità:
per maggiori dettagli vedere [2].
Copiamo il file VBJWiz.mda in C:\Documents and Settings\<nome utente>\Dati
applicazioni\Microsoft\AddIns. È ovviamente possibile creare il database già nella
cartella di destinazione, ma conviene copiarvi solo le versioni dell’add-in
già collaudate e lasciare quelle in sviluppo in una cartella separata.
Creiamo ora un database che si chiama VBJ.mdb. Tramite il menu Strumenti, Componenti
aggiuntivi, Gestione Componenti aggiuntivi, troverete tra le altre eventuali aggiunte,
quella appena creata. Fatevi un doppio click. Se non succede nulla, allora è tutto
a posto :-). Aprite nuovamente Strumenti, Componenti aggiuntivi e selezionate la
nuova opzione VBJ Toolbar. Ecco il vostro Wizard che vi saluta.
Aggiungendo alla funzione VBJWizStart come prima riga
Function VBJWizStart()
CommandBars("VBJToolbar").Visible = True
MsgBox "Il Wizard è partito!", vbInformation, "VBJ Wizard"
End Function
e riavviando il wizard dal database VBJ.mdb, noterete che compare la toolbar creata
nell’add-in: lavorando su una qualsiasi form, adesso avrete a portata di mano
un pulsante per allineare i controlli, interamente gestito da Access ed uno per
vedere l’ora, alla cui pressione viene lanciato il vostro codice.
Accedere agli oggetti da modificare
Un add-in è un database utilizzato da un altro database. Entrambi hanno, ad esempio,
l’insieme delle maschere. Per far riferimento agli oggetti del database in
sviluppo, utilizzeremo CurrentProject, mentre con CodeProject accederemo a quello
dell’add-in. Apriamo VBJ.mdb e lanciamo il nostro add-in: dalla finestra di
debug possiamo scrivere
?codeproject.AllForms(0).Name
ed otterremo frmHistory, che è il nome della sola maschera contenuta nel
file VBJWiz.mda.
L’add-in può lavorare sulla maschera selezionata tramite le istruzioni
Screen.ActiveForm.SetFocus
Set frm = Screen.ActiveForm
Ovviamente, una volta che si è impostato il riferimento alla maschera, si può iterare
sull’insieme dei controlli o navigarne il modello a oggetti.
E se volessimo aggiungere del codice che gestisce un evento? Il modello ad oggetti
di Access ci aiuta: il seguente codice aggiunge l'evento Click alla form selezionata
in quel momento.
Function VBJWizAggiungiEvento()
Dim frm As Form
Dim ctl As Control
Dim mdl As Module
Dim lng As Long
Dim strCode As String
Screen.ActiveForm.SetFocus
Set frm = Screen.ActiveForm
Set mdl = frm.Module
' Aggiunge la procedura evento.
lng = mdl.CreateEventProc("Click", Replace("Corpo", " ", "_"))
' Cancella una riga vuota
mdl.DeleteLines lng + 1, 1
strCode = vbTab & "' Evento aggiunto dal Wizard" & vbNewLine _
& vbTab & "MsgBox ""Evento On_Click"", VbInformation"
' Inserisce il corpo della procedura.
mdl.InsertLines lng + 1, strCode
End Function
Un particolare degno di nota è il metodo CreateEventProc, che crea automaticamente
la dichiarazione della funzione con i parametri necessari e la posiziona al giusto
posto nel modulo associato alla maschera.
In pratica, una volta creato il riferimento al modulo associato alla maschera, è
sufficiente dichiarare l’evento da creare e poi inserirvi le righe di codice
volute.
Progettare un add-in
L’esempio appena visto consente di capire che si possono costruire tabelle,
form e codice che stanno in un database separato da quello su cui si lavora; come
si può intuire, le potenzialità sono enormi. Per avere un'idea di cosa è possibile
fare, è sufficiente considerare che gli wizard di Access sono realizzati in Access
e VBA!
Per progettare un add-in, è bene considerare i seguenti passi:
- Identificare quali sono le funzioni desiderate
- Dividere le funzioni già fornite da Access da quelle da creare; ad esempio, allineare
a destra i controlli è una funzione già inclusa
- Realizzare le funzioni non incluse nel database dell’add-in e collaudarle
- Realizzare nell’add-in una toolbar o un menu che richiami tutte le funzioni
volute
- Pubblicare l’add-in
Una menzione speciale merita la denominazione degli oggetti. Conviene cercare un
prefisso inusuale sia per gli oggetti di database che per le funzioni. Access è
abbastanza intelligente da tenere separati gli spazi dei nomi, infatti, creando
nel database VBJ.mdb una funzione che si chiama VBJWizMiaFunzione, ossia uguale
a quella presente nell’add-in, il pulsante della toolbar continuerà a richiamare
quella giusta. Comunque, esplorando il progetto può essere utile riconoscere al
volo dove una certa funzione sia stata implementata, grazie al suo nome.
Per distribuire un add-in senza fornire l'accesso ai sorgenti, oltre a proteggere
il progetto dalla visualizzazione tramite una password, è possibile convertire il
database in formato .MDE. Il file generato impedisce l'accesso ai sorgenti,
che sono stati fisicamente rimossi, ed anche alla struttura della maggior parte
degli oggetti. Gli wizard di Access sono (purtroppo) generati proprio con questa
tecnica. In alcuni casi, con le versioni per sviluppatori di Access, essi sono stati
rilasciati anche in formato sorgente e, per chi vuole studiare determinati meccanismi,
si tratta di una vera manna.
Un caso reale
Per stuzzicare l’appetito, ho corredato quest’articolo dell’add-in
che utilizzo per programmare, visibile in
figura 1.
Figura 1
Sia perché ci sono delle funzioni a mio parere utili, sia perché è possibile trovare
più materiale da analizzare che in un esempio didattico.
Partiamo dalla password per visualizzare il progetto che è VBJ (maiuscolo!).
La password è utile per evitare che, lavorando sul database di applicazione, ci
si trovi aperta ed espansa nell’albero del progetto anche la sezione relativa
all’add-in.
Nella tabella nascosta USysRegInfo, i record sono 12 invece che 4, per permettere
all’add-in di essere utilizzato sotto Access 2000/2002/2003.
I moduli sono divisi per funzionalità. In modInizializza ci sono le funzioni
di inizializzazione e di richiamo delle maschere. Il modulo modAggiungiAMenu
contiene il codice per realizzare il menu a tendina che compare premendo il pulsante
Dim della toolbar, mentre in modAladinoWizard si trovano le routine di automazione.
L’ultimo modulo, modAPI, contiene il codice basato su API per ridimensionare
la finestra di Access.
Lo wizard è utilizzabile a fini didattici o per lo sviluppo di applicazioni. Le
migliorie possibili sono molte. Per esempio, il wizard non lavora correttamente,
in alcuni casi, selezionando una sottomaschera. Oppure, talvolta, richiede che sia
abilitata la visualizzazione dell’intestazione e del pié di pagina maschera.
Le funzioni
In figura 2
Figura 2
è rappresentata la toolbar dell’Aladino Wizard con dei numeri per identificare
ogni pulsante.
I numeri 1,2,4,5,6,7,8,9,10 sono le comuni funzioni di formattazione di Access,
riportate nella barra per praticità. Il pulsante 3 risolve il problema di centrare
più controlli tra loro.
Tramite il pulsante 11, si imposta l’ordine di tabulazione dei soli controlli
selezionati. Ad esempio, se si sta realizzando una maschera con due colonne, si
seleziona la prima colonna di controlli e si preme il pulsante. Al termine, viene
comunque visualizzata la finestra standard per l’ordine di tabulazione di
Access. Le opzioni 12, 13 e 14 sono utili nel realizzare maschere tabulari. Per
vederle in azione, creare una maschera standard a colonne, poi premere 13: il wizard
sposterà tutte le etichette nell’intestazione. Dopo aver impostato i campi
alla larghezza voluta, premere 12: il wizard formatterà la maschera per voi. Selezionando
un campo e premendo 14 verrà creato, nel pié di pagina, un campo con origine =Somma(<nomecampo>).
La differenza rispetto a quelle create da Access sta nel poter modificare la larghezza
di un singolo campo e riformattare correttamente tutta la maschera premendo un solo
tasto.
Il 15 serve nelle maschere continue o in quelle visualizzate in modalità a foglio
dati. Introduce del codice che intercetta la pressione della freccia in basso ed
in alto e le trasforma in un movimento in avanti o indietro di un record. Il codice
associato a questo pulsante dimostra come sia facile inserire del codice associato
ad un controllo nel nostro progetto.
Il tasto 16 associa a tutti i campi percentuale una routine che, se il valore inserito
è maggiore o uguale di 1, lo divide per 100. pratica, scrivendo 20 nel campo, la
routine lo trasformerà in 0,20, che Access vede come 20%.
Il tasto 17 apre una maschera che permette di creare del codice basato sui campi
di una tabella del database locale, come si vede nella
figura 3.
Figura 3
Il tasto 18 aggiunge una routine che visualizza un calendario, utile sui campi di
tipo data. Se la provate, non funzionerà, semplicemente perché il codice
app.SelezionaData Screen.ActiveControl, Me.hwnd ' Apre il calendario
fa riferimento ad una routine di una mia libreria. Ho ritenuto opportuno includerla
perché mostra come si possa automatizzare lo sviluppo di applicazioni definendo
alcune routine all’interno di una libreria ed applicandole facendo uso di
uno wizard.
Le opzioni 19 e 20 colorano un campo con il colore predefinito per il collegamento.
Nello standard che ho adottato, ogni campo dove funziona il doppio click è colorato
con un giallo chiaro.
Con il tasto 21 viene generato il codice che apre una maschera con determinati criteri.
Ad esempio, in un ordine ho l’IDAnagrafica: volendo aprire la maschera frmAnagrafica
selezionando l’IDAnagrafica che ho nel codice, lo wizard scrive il codice
giusto.
Il tasto 22 offre una funzione carina. Permette infatti di scegliere tra le migliaia
di icone fornite con Access. Ogni icona ha un ID: una volta saputo l’ID, con
poche righe di codice, la si può impostare. Tutte le icone della toolbar sono state
scelte in questo modo. Un esempio è la
figura 4.
Figura 4
Nella maschera è riportato anche lo schema di codice utile per raggiungere il controllo
di cui cambiare l’icona.
L’opzione 23 consente di dimensionare la finestra di Access in formati standard.
Si rivela utile per collaudare un’applicazione all’effettiva risoluzione
alla quale verrà utilizzata, per evitare che maschere sviluppate magari a 1280x1024
non entrino nello schermo dell’utente che – sic – lavora ancora
a 800x600. Per creare il menu a discesa nella barra degli strumenti viene utilizzata
la routine seguente, che dimostra ancora una volta la versatilità delle toolbar
e la maneggevolezza delle stesse, fornita dal modello ad oggetti.
Public Sub InsertDropDownx()
Dim ctlCombo As CommandBarComboBox
Set ctlCombo = CommandBars("Aladino Developer Wizard Toolbar")_
.Controls.Add(msoControlDropdown)
With ctlCombo
.BeginGroup = True
.AddItem ("640x480")
.AddItem ("800x600")
.AddItem ("1024x768")
.AddItem ("1280x1024")
.AddItem ("Massimizza")
.BeginGroup = True
.AddItem ("Dimensione massima")
.Caption = "Dimensione finestra di Access"
.Tag = "DimensioneFinestraAccess"
.Width = 120
End With
End Sub
L’opzione 24 disattiva la clessidra, rimasta attiva dopo un blocco del programma.
Infine le opzioni 25 e 26 visualizzano rispettivamente le opzioni e le informazioni
sullo wizard.
Trucchi e problemi
La parte più complessa nella realizzazione di uno wizard, consiste nel prevedere
tutti i possibili ambienti in cui esso verrà impiegato. Una differenza rilevante
è il lavorare su un database (file .mdb) o su un progetto (file .adp); potrebbe
essere necessario, ad esempio, generare codice SQL diverso nei due casi, anche solo
variando i caratteri jolly che sono l’asterisco per l’mdb e la percentuale
per l’adp.
Possiamo dotare il wizard della capacità di discernere su quale tipo di file sta
lavorando. Nella funzione VBJWizMiaFunzione viene stampato un messaggio che evidenzia
il tipo di file correntemente aperto, grazie alla proprietà Application.CurrentProject.ProjectType.
Se si effettua un ciclo sull'insieme dei controlli, è necessario assicurarsi
di trattare correttamente i diversi tipi di oggetti. Ad esempio, nel mio wizard,
se in una maschera aggiungete una riga e provate la funzione 12, otterrete l'errore
di "Proprietà o metodo non supportati dall'oggetto". Ovviamente non
ho mai la necessità di formattare maschere con righe nel mezzo, ma se volessi commercializzare
il wizard, dovrei eliminare anomalie simili.
Quando si lavora su maschere, è necessario discernere se il controllo selezionato
dall'utente si trovi su una maschera o su una sottomaschera, impostando correttamente
i riferimenti.
La gestione degli errori riveste una parte fondamentale; intercettare correttamente
un errore e identificare la routine dove si è verificato è fondamentale per motivi
diversi sia in fase di sviluppo che in produzione. Durante il collaudo dell’add-in,
è importante identificare la parte di codice che produce l’errore, poiché
può essere già complesso riprodurre la situazione in cui esso si verifica. Si consideri
un ambiguo messaggio tipo "Impossibile trovare il nome di funzione immesso
nell'espressione". Senza altre indicazioni, può trattarsi del fatto che
Access non riesce a richiamare la funzione specificata nel pulsante, oppure può
trattarsi di un errore generato nella funzione richiamata. In produzione, il gestire
un errore, consente probabilmente di proseguire il lavoro senza problemi. Se l'errore
non è gestito, l'utente potrebbe interrompere l'esecuzione del codice distruggendo
così eventuali variabili globali. A quel punto, il wizard dovrebbe essere rilanciato.
Conclusioni
Se sviluppate spesso applicazioni in Access e non avete mai creato un add-in, è
il momento buono per farlo. Create il minimo indispensabile ed usatelo: in breve
comincerete ad arricchirlo di funzioni. L'add-in allegato è un buon punto di
partenza. Inoltre, se sviluppate in un gruppo, l'adozione di un add-in comune
a tutti i programmatori aiuta a mantenere degli standard di programmazione. Invito
chiunque abbia qualche buona idea da sviluppare a contattare me o la redazione.
Riferimenti
[1] Ken Getz, Paul Litwin, Mike Gilbert - "Access 2000 Manuale di programmazione",
Jackson Libri, 2000
[2] "
Creating the USysRegInfo Table for a Microsoft Access 2000
Add-In ",
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnacc2k/html/usysregacc2k.asp