Skip Navigation LinksHome : Articoli : Creare Add-in per VBE in Microsoft Access

Creare Add-in per VBE in Microsoft Access

di Gionata Aladino Canova (VBJ n° 68)

Uilizzare strumenti che svolgono per noi i compiti ripetitivi, permette di concentrarsi sui concetti della programmazione e di essere più produttivi.

Nell'articolo "Creare Add-in per Microsoft Access" abbiamo visto come realizzare una barra di strumenti che si integra nell'ambiente di Access, per automatizzare certe operazioni. In questo articolo vedremo come aggiungere al menu dell'editor di VBA (VBE Visual Basic Editor) dei comandi personalizzati che ci aiutino nella stesura del codice.

Analizzeremo poi un add-in che utilizzo comunemente per sviluppare, visibile in Figura 1.


Figura 1
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.

Le complessità nascoste

La programmazione in un ambiente visuale è un problema complesso. Chi ha visto cosa ci voleva in C per creare una finestra in Windows, sa a cosa mi riferisco. Tanti sistemi moderni, Access compreso, consentono di fare molte cose in modo semplice, nascondendo le complessità sottostanti. Creare un add-in in Access è sicuramente più facile che creare un add-in per il VBE, poiché quest'ultimo nasconde un po' meno cose. Ad esempio, personalizzare i menu di VBE è più complicato che personalizzare i menu di Access. Questo perché VBE è basato sul modello di Visual Studio e non su quello di Office.

Progettare un add-in

La prima operazione da fare per progettare un add-in è analizzare quali operazioni desideriamo implementare. Da questa lista otterremo una serie di funzioni che potranno logicamente essere raggruppate. Ad esempio, le funzioni che trattano la generazione di codice per la gestione di recordset potranno essere organizzate tutte in un'unica form. Creata la lista delle form e delle eventuali funzioni da chiamare direttamente, sarà facile progettare l'interfaccia utente dell'add-in, ossia stabilire quali menu o barre degli strumenti vadano create o quali siano gli eventi da intercettare. Nel wizard di esempio vedremo la creazione di un menu e l'intercettazione dell'evento di compilazione. La parte finale della progettazione sarà il suddividere quali funzioni vadano create in quali moduli. La creazione dell'add-in si svilupperà nella stesura del codice che realizza le funzioni e nella parte che crea l'interfaccia con l'utente.

Costruire lo scheletro dell'add-in

Iniziamo aprendo Access, cliccando sulla caption e spostandoci nell'editor VBE (tasto rapido ALT+F11). La finestra è desolantemente vuota. Se la finestra Progetto non è visualizzata, dal menu Visualizza selezioniamo Gestione Progetti (CTRL+R). Dal menu File, selezioniamo l'opzione Nuovo Progetto e poi Progetto Aggiunta. Nella finestra che compare, compiliamo le voci Nome aggiunta visualizzato inserendo VBJ Wizard e Descrizione aggiunta con un commento a piacere, poi impostiamo la voce Applicazione a Visual Basic for Application IDE. In futuro, per far ricomparire questa finestra, dalla finestra Gestione Progetti, andremo nella sezione Finestre di progettazione e faremo doppio click sulla voce che, di default, si chiama AddInDesigner1. Salviamo il file con il nome VBJAddIn.

Nei riferimenti (Strumenti – Riferimenti) dovremo aggiungere:

  • Microsoft Access 10.0 Object Library (per l'oggetto VBE)
  • Microsoft Office 10.0 Object Library (per la gestione delle barre degli strumenti, es. CommandBarButton)
  • Microsoft Visual Basic For Applications Extensibility 5.3 (per intercettare gli eventi delle Barre di VBE)

Aggiungiamo il modulo che conterrà le operazioni da implementare. Inseriamo il codice seguente:

Option Explicit

Public oHostApplication As Object
Public oAddIn As Object
Public conNomeApp As String
Public Const conVersione = "1.0 del 12-02-2006"
Public Const conTitoloApp = "VBJ Wizard"

Function wizCompila()
    MsgBox "Stai compilando!", vbInformation, "VBJAddIn"
End Function

Sub wizInfo()
    MsgBox "VBJ Wizard ver." & conVersione, vbInformation, _
           "VBJAddIn"
End Sub

Sub wizNumeroCasuale()
    MsgBox "Il primo numero che mi viene in mente è: " _
           & Int(Rnd() * 1000)
End Sub

 La funzione wizCompila ci avviserà che l'utente sta compilando. In un progetto reale potrebbe incrementare un numero di build (funzione mai gestita in Access!). La funzione wizInfo fornisce informazioni sul wizard, mentre wizNumeroCasuale visualizza una message-box che stampa un numero a caso. Dal riquadro Proprietà, impostiamo il nome del modulo a modMioCodice. Dobbiamo adesso costruire l'interfaccia con l'utente. Facciamo un click destro su AddInDesigner1 e selezioniamo Visualizza codice.

Inseriamo il codice contenuto nel Listato 2. Se proviamo a compilare, non dovremmo ottenere errori.

Option Explicit

Private WithEvents mnuItem1 As Office.CommandBarButton
Private WithEvents mnuItem2 As Office.CommandBarButton

Private WithEvents cCompila As CommandBarEvents

Private Sub AddinInstance_OnConnection _
    (ByVal Application As Object, _
     ByVal ConnectMode As AddInDesignerObjects.ext_ConnectMode, _
     ByVal AddInInst As Object, custom() As Variant)
    'Memorizzo le referenze all'avvio
    Set oHostApplication = Application
    Set oAddIn = AddInInst
    
    conNomeApp = AddInInst.ProgId
    
    'Crea le opzioni aggiuntive nel menu di VBE
    CreaMenu (AddInInst.ProgId)
    
    ' Intercetta l'evento di compilazione (Debug / Compila)
    Dim c As CommandBarControl
    Set c = VBE.CommandBars(1).Controls(5).Controls(1)
    Set cCompila = VBE.Events.CommandBarEvents(c)
End Sub

Private Sub AddinInstance_OnDisconnection _
        (ByVal RemoveMode As _
         AddInDesignerObjects.ext_DisconnectMode, _
         custom() As Variant)
    'Rimuove le opzioni dal menu
    RimuoviMenu
    Set oAddIn = Nothing
    Set oHostApplication = Nothing
End Sub

Sub CreaMenu(strProgID As String)
    ' Crea un elemento nel menu e lo collega all'addin.
    Dim cbrMenu As Office.CommandBar
    Dim ctlBtnAddIn As Office.CommandBarButton
    Dim strKey As String
    
    ' Stabilisce un riferimento al menu Add-Ins
    Set cbrMenu = VBE.CommandBars("Add-Ins")
    
    ' Prova a cercare il pulsante "VBJ - Numero casuale"
    strKey = "VBJWizNumCasuale"
    Set mnuItem1 = cbrMenu.FindControl(Tag:=strKey)
    
    If mnuItem1 Is Nothing Then
        ' Aggiunge il pulsante
        Set mnuItem1 = cbrMenu.Controls.Add(msoControlButton _
            , , strKey, , True)
    
        With mnuItem1
            .Caption = "VBJ - Numero casuale"
            .Tag = strKey
            .Style = msoButtonCaption
            .FaceId = 634
            .OnAction = "!<" & strProgID & ">"
            .BeginGroup = True
        End With
    End If

    ' Prova a cercare il pulsante "Informazioni su..."
    strKey = "VBJWizInfo"
    Set mnuItem2 = cbrMenu.FindControl(Tag:=strKey)
    
    If mnuItem2 Is Nothing Then
        ' Aggiunge il pulsante
        Set mnuItem2 = cbrMenu.Controls.Add(msoControlButton _
            , , strKey, , True)
    
        With mnuItem2
            .Caption = "Informazioni su VBJ Developer Wizard"
            .Tag = strKey
            .Style = msoButtonCaption
            .FaceId = 634
            .OnAction = "!<" & strProgID & ">"
            .BeginGroup = True
        End With
    End If

End Sub

Sub RimuoviMenu()
    On Error Resume Next
    VBE.CommandBars("Add-Ins").Controls _
        ("VBJ - Numero casuale").Delete
    VBE.CommandBars("Add-Ins").Controls _
        ("Informazioni su VBJ Developer Wizard").Delete
End Sub


' Qui inizia la sezione che gestisce gli eventi
Private Sub mnuItem1_Click(ByVal Ctrl As Office.CommandBarButton, _ 
                           CancelDefault As Boolean)
    wizNumeroCasuale
End Sub

Private Sub mnuItem2_Click(ByVal Ctrl As Office.CommandBarButton, _
                           CancelDefault As Boolean)
    wizInfo
End Sub

Private Sub cCompila_Click(ByVal CommandBarControl As Object, _
                           Handled As Boolean, _
                           CancelDefault As Boolean)
    ' Viene gestito l'evento di compilazione
    wizCompila
End Sub
Prima di analizzarlo, collaudiamo l'add-in.

Collaudare l'add-in

Dopo essere riusciti a compilare senza errori, la sequenza per collaudare l'add-in è:

  • Esegui/Esegui Progetto (c'è anche il corrispondente pulsante sulla barra Standard.
  • Aggiunte/Gestione Aggiunte. Fare doppio click sul nostro add-in (nell'esempio, VBJ Wizard), per caricarlo, poi premere Ok.
  • Nel menu Aggiunte troveremo le due opzioni da noi create. Per provarle è sufficiente selezionarle. Per provare la compilazione, apriamo un database vuoto, aggiungiamo un modulo ed una routine anch’essa vuota. Selezioniamo poi Debug/Compila. Se tutto funziona, una message-box ci avviserà che stiamo compilando.
  • Finito il test, ritorniamo in Aggiunte/Gestione Aggiunte e facciamo doppio click sul nostro add-in (nell'esempio, VBJ Wizard), per scaricarlo. Questa operazione è necessaria per ripulire i menu di VBE dalle voci che vi abbiamo aggiunto. Interrompendo semplicemente il progetto, non viene eseguita la routine di pulizia.
  • Selezioniamo Esegui/Interrompi progetto

Se saltiamo lo scaricamento dell'Add-in, oppure abbiamo commesso errori nel codice, il menu potrebbe rimanere sporco. Per rimediare, se non abbiamo altre personalizzazioni manuali, è sufficiente andare in modifica delle barre dei menu, selezionare la Barra dei menu e selezionare la funzione Reimposta.

Come funziona l'add-in

Vediamo adesso in dettaglio il funzionamento dell'add-in. Le operazioni che esso compie sono volutamente banali, per potersi concentrare solo sul codice di base necessario per costruire l'add-in.

Le dichiarazioni

Private WithEvents mnuItem1 As Office.CommandBarButton
Private WithEvents mnuItem2 As Office.CommandBarButton

impostano due riferimenti per le due voci di menu che andremo a creare nella routine CreaMenu. La parola chiave WithEvents indica al compilatore che, di quei due oggetti, vogliamo gestirne gli eventi. Il modo per gestire gli eventi è dichiarare una routine, come Access fa in maniera automatica quando gli chiediamo di gestire un evento di un oggetto, con la sintassi

Private Sub <nomeVariabile>_<NomeEvento>()[parametri])

come si vede nell'esempio seguente, dove viene gestito l'evento Click dell'oggetto mnuItem1.

Private Sub mnuItem1_Click(ByVal Ctrl As Office.CommandBarButton, _
            CancelDefault
As Boolean)

Queste routine devono stare nel modulo di codice associato all'AddInDesigner e, ovviamente, possono contenere chiamate a routine contenute in moduli esterni, come succede in quella appena vista.

La dichiarazione

Private WithEvents cCompila As CommandBarEvents

ci permette invece di gestire l'evento legato all'opzione già esistente Compila. L'associazione tra la variabile cCompila ed il pulsante di compilazione viene effettuata all'interno della routine AddinInstance_OnConnection, dalle righe

' Intercetta l'evento di compilazione (Debug / Compila)
Dim c As CommandBarControl
Set c = VBE.CommandBars(1).Controls(5).Controls(1)
Set cCompila = VBE.Events.CommandBarEvents(c)

All'avvio dell'add-in, viene eseguita la routine AddinInstance_OnConnection, nella quale creiamo i menu ed impostiamo l'intercettazione dell'evento di compilazione, come visto sopra. Alla chiusura dell'add-in, tramite la routine AddinInstance_OnDisconnection provvediamo all'eliminazione delle voci di menu.

La routine CreaMenu è abbastanza semplice, se si ha un'idea di come sia il modello ad oggetti delle barre di menu. Impostato il riferimento in cbrMenu, alla barra Add-Ins di VBE, per evitare duplicazioni di opzioni, proviamo a cercare se esiste già l'opzione che vorremmo creare, altrimenti la aggiungiamo. L'operazione viene ripetuta tante volte quante sono le voci da inserire nel menu. La routine RimuoviMenu è molto semplice, limitandosi solo a tentare di cancellare le voci create in precedenza.

In pratica, avendo la lista delle opzioni che vogliamo creare, è necessario dichiarare n variabili come mnuItemX all'inizio della routine, inserire la creazione e la distruzione delle opzioni in CreaMenu e RimuoviMenu ed infine creare le corrispondenti routine di intercettazione degli eventi.

Il codice del Listato 1 non ha bisogno di commenti, essendo un esempio ridotto all'osso.

Un Add-in reale

Nel codice allegato trovate anche un add-in completo, che uso per sviluppare. Il file si chiama AladinoDevWizard.vba e contiene, oltre a tutta l'infrastruttura vista fino ad ora, una form per generare recordset, visibile in Figura 2.


Figura 2

Analizzando la sub wizGeneraRecordSet troviamo del codice la cui analisi esula da questo articolo, ma che merita di essere studiato. La routine, come primo compito, controlla di essere stata chiamata con il cursore puntato in VBE all'interno di una definizione di sub o di function. Poi, dopo aver visualizzato la form e letto i relativi dati, costruisce una stringa che contiene il codice generato. La stringa viene inserita nella posizione in cui si trova il cursore, dalla riga

VBE.ActiveCodePane.CodeModule.InsertLines lngStartLine, strCode

Utilizzando come base questo codice, possiamo costruire una form che ci chieda l'input che vogliamo, generare il codice corrispondente ed inserirlo nel progetto corrente. Per chi non ha mai lavorato con il modello ad oggetti di VBE, consiglio di cercare esempi in rete e di leggere [1] e [2]. Esistono metodi per aggiungere sub e function, spostarsi all'interno del codice e fare altre operazioni in maniera molto semplice.

Nell'add-in è inclusa una UserForm. A differenza di Word ed Excel, pare che in Access non ci sia un modo immediato per aggiungerla. Probabilmente perché si pensa di utilizzare le form di Access. Per aggirare il problema, ci sono due modi. Possiamo personalizzare la barra dei menu aggiungendo il comando UserForm, nel menu Inserisci. Oppure possiamo inserire in un modulo il codice seguente che, richiamato dalla finestra di debug, crea una UserForm.

Sub Add_Form1()
' Declare a variable to hold the UserForm.
Dim x As Object
    ' Create a new UserForm. You can use this new 
    ' VBComponent object to manipulate the User Form.
    Set x = Application.VBE.ActiveVBProject _
       .VBComponents.Add(vbext_ct_MSForm)
End Sub

Il risultato è visibile in Figura 3.


Figura 3

Installazione e distribuzione

Per distribuire il nostro add-in, dovremo prima creare la DLL tramite l'opzione File/CreaVBJAddIn.DLL, poi selezioniamo Aggiunte/Creazione guidata pacchetti (disponibile con la versione Developer di Office). Seguendo le istruzioni, verrà creato un pacchetto che consentirà la distribuzione della nostra DLL, tramite un normale programma di setup.

Conclusioni

La stesura di un Add-in per VBE è un'operazione non banale, ma fattibile tranquillamente da chi programma tutti i giorni. È importante, nel lavoro quotidiano, capire se scriviamo spesso parti di codice ripetitive, perché in questo caso si può trarre parecchio beneficio creando un add-in personalizzato. Per funzioni standard tipo conteggio di righe, ordinamento di procedure o simili, conviene invece fare ricerche in rete, poiché si trovano add-in già pronti e collaudati, spesso gratuiti, veramente potenti. Un esempio è VBA MZ-Tools 3.0 [3].

Riferimenti

[1] Programming the Microsoft Office Visual Basic Editor

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnofftalk/html/office07042002.asp

[2] Before You Create a VB Add-In, Learn the IDE's Object Model

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dninvb00/html/IDEObjectModel.asp

[3] MZ-Tools 3.0 for Visual Basic 6.0, 5.0 and VBA