Access-Add-In per Knopfdruck erstellen

Immer, wenn ich ein neues Add-In für eine Automatisierung meiner Access-Entwicklung erstelle, führe ich die gleichen Schritte durch: Anlegen einer neuen Datenbank, Speichern als .accda, Erstellen der Tabelle USysRegInfo, Hinzufügen der Daten für die Registry, Einstellen der Datenbankinformationen, sodass diese im Add-In-Manager angezeigt werden und Programmieren der Funktion, die beim Start des Add-Ins aufgerufen werden soll. Und erst danach fängt der eigentliche Spaß an, nämlich die Programmierung der Funktion, die ich gern mit dem Add-In erledigen möchte. Weil ich das oft genug gemacht habe, baue ich im Rahmen dieses Beitrags ein Tool, mit dem ich solche Add-Ins per Mausklick erstellen kann – beziehungsweise ein Add-In, mit dem ich die aktuelle Datenbank in ein Add-In umwandeln kann.

Wenn ich schon regelmäßig Access-Add-Ins programmiere, um damit lästige, immer wieder auftretende Aufgaben zu vereinfachen – warum sollte ich dann nicht das Zusammenstellen der wichtigsten Elemente dieses Add-Ins auch automatisieren?

Ich habe erst überlegt, mir eine Vorlage zu erstellen, die ich dann kopiere und anpasse. Aber letztlich sind doch einige Schritte zu erledigen.

Selbst wenn die Tabelle USysRegInfo in einer solchen Vorlage bereits vorhanden ist, muss ich die dortigen Daten noch einstellen, und auch die Informationen der Access-Datenbank selbst, die später im Add-In-Manager angezeigt werden, müssen immer wieder angepasst werden.

Davon abgesehen schaffe ich es regelmäßig, die Daten in der Tabelle USysRegInfo nicht korrekt einzugeben, und selbst der kleinste Fehler führt dazu, dass die Registrierung nicht durchgeführt wird oder das Access-Add-In anschließend dennoch nicht gestartet werden kann.

Viel einfacher wäre es doch, wenn es ein Formular gäbe, das die wichtigsten Einstellungen vor dem Erstellen des Access-Add-Ins abfragt und diese automatisch anlegt.

Neues Access-Add-In oder aktuell geöffnete Datenbank umrüsten?

Nun stellt sich die Frage, wie wir das Erstellen eines neuen Access-Add-Ins gestalten wollen. Wir könnten beispielsweise eine herkömmliche Access-Datenbank erstellen, die ein Formular enthält, welches die Parameter für das Access-Add-In abfragt und diese dann auf die gleiche Datenbank anwendet.

In dieser Datenbank könnten wir die Tabelle USysRegInfo dann bereits vorbereiten und brauchen diese nur noch auf Basis der in das Formular eingegebenen Daten anzupassen – das gilt auch für die Datenbankinformationen.

Die Alternative wäre, wiederum ein Access-Add-In zu programmieren, das der aktuell geöffneten Datenbank die notwendigen Elemente hinzufügt. Das Access-Add-In müsste dann die notwendigen Informationen abfragen, die Tabelle USysRegInfo anlegen und mit den Daten für die Registrierung füllen, die Datenbankinformationen eintragen und das Modul mit der Funktion zum Starten des Access-Add-Ins anlegen.

Mein Weg zu Access-Add-Ins

Ich gehe an dieser Stelle einmal von meiner eigenen Vorgehensweise beim Erstellen eines Access-Add-Ins aus. Diese sieht so aus, dass ich zu Beginn meist gar kein Access-Add-In plane, sondern einfach nur in irgendeiner Datenbankanwendung, die ich gerade programmiere, eine VBA-Prozedur hinzufüge, mit der ich eine Aufgabe automatisiere.

Diese setze ich dann ein, stelle fest, dass sie gut funktioniert, und füge dann gegebenenfalls ein Formular hinzu, von dem ich die Prozedur aufrufe.

Wenig später stelle ich dann fest, dass ich diese Funktion auch noch in weiteren Projekten nutzen könnte. Meistens kopiere ich diese dann zuerst in das betroffene Projekt und nutze es dort. Irgendwann kommt mir dann die Idee, dass ich ja auch ein Access-Add-In aus der Funktion machen könnte – und dann beginnen die Schritte, die ich bereits eingangs erwähnt habe.

Ich starte also eher mit einer Datenbankanwendung, in der bereits die Funktionen des zukünftigen Access-Add-Ins enthalten sind und wandle diese dann in ein Add-In um. Dementsprechend legen wir die Lösung dieses Beitrags auch als Access-Add-In an – um damit über das Add-In-Menü die aktuell geöffnete Datenbank in ein Add-In umwandeln zu können.

Formular zum Erfassen der Add-In-Daten

Bevor wir loslegen, benötigen wir ein Formular, mit dem der Benutzer die Daten eingeben kann, die für das Umrüsten des Add-Ins benötigt werden. Dieses Formular sieht in der Entwurfsansicht wie in Bild 1 aus. Wir verwenden hier die folgenden Textfelder:

Entwurf des Formulars zur Eingabe der Add-In-Daten

Bild 1: Entwurf des Formulars zur Eingabe der Add-In-Daten

  • txtAddInName: Diese Bezeichnung wird in der Liste der Add-Ins im Ribbon verwendet sowie als Schlüssel in der Registry.
  • txtBeschreibung: Die Beschreibung wird in die Eigenschaft Kommentare der Datenbank geschrieben. Sie wird im Add-In-Manager angezeigt, wenn das Add-In darin markiert wurde.
  • txtHersteller: Der Hersteller wird in die Eigenschaft Firma der Add-In-Datenbank geschrieben. Auch diese Information landet im Add-In-Manager.
  • txtStartfunktion: Name der VBA-Funktion, die beim Starten des Add-Ins aufgerufen werden soll.
  • txtAddInDatei: Aktueller Dateiname, bei dem gegebenenfalls noch die Dateiendung .accdb durch .accda ersetzt wird. Der tatsächliche Dateiname muss dem hier angegebenen Dateinamen entsprechen.

Damit gleich beim Öffnen des Formulars einige Beispieldaten erscheinen, füllen wir die Textfelder beim Laden des Formulars mit der folgenden Ereignisprozedur:

Private Sub Form_Load()
     Me!txtAddInName = "Add-In-Name"
     Me!txtBeschreibung = _
         "Dies ist die Beschreibung des Add-Ins."
     Me!txtHersteller = "Hersteller"
     Me!txtStartfunktion = "Autostart"
     Me!txtAddInDatei = _
         Replace(CurrentProject.Name, ".accdb", ".accda")
End Sub

Dadurch sieht das Formular nach dem Öffnen wie in Bild 2 aus.

Das Formular zur Eingabe der Add-In-Daten in der Formularansicht

Bild 2: Das Formular zur Eingabe der Add-In-Daten in der Formularansicht

Umwandeln der Access-Datenbank in ein Access-Add-In

Damit wir die Access-Datenbank als Access-Add-In nutzen können, sind einige Schritte nötig, die im Code der Prozedur, die durch die Schaltfläche cmdZumAddInUmruesten bereits skizziert sind (siehe Listing 1).

Private Sub cmdZumAddInUmruesten_Click()
     Dim db As dao.Database
     Dim dbc As dao.Database
     Set db = CurrentDb
     Set dbc = CodeDb
     If Not CreateUSysRegInfo(db) Then
         MsgBox "Offensichtlich ist bereits eine Tabelle namens ''USysRegInfo'' vorhanden." & vbCrLf _
             & "Prüfen Sie die aktuelle Datenbank." & vbCrLf & vbCrLf _
             & "Der Vorgang wird abgebrochen.", vbOKOnly + vbExclamation
         Exit Sub
     End If
     AddRegistryEntries db, dbc, Me!txtAddInName, 1, Me!txtStartfunktion, Me!txtBeschreibung, Me!txtAddInDatei
     ChangeProperties db, Me!txtAddInName, Me!txtBeschreibung, Me!txtHersteller
     AddStartfunction db, Me!txtStartfunktion
     If Not Right(CurrentProject.Name, 6) = ".accda" Then
         MsgBox "Die Dateiendung muss noch in .accda geändert werden.", vbOKOnly + vbExclamation, "Dateiendung anpassen"
     End If
End Sub

Listing 1: Code zum Umwandeln der aktuell geöffneten Datenbank in ein Access-Add-In

Die Prozedur deklariert und füllt zwei Database-Variablen: Die erste heißt db und referenziert die aktuell geöffnete Datenbank (mit CurrentDb), die zweite heißt dbc und bezieht sich auf die Add-In-Datenbank (mit CodeDb).

Bedenken Sie: Die Datenbank, die wir gerade programmieren, wird ja selbst ein Access-Add-In, mit dem wir die dann geladene Datenbank in ein Access-Add-In umwandeln wollen.

Die Prozedur ruft danach weitere Routinen auf. Die erste heißt CreateUSysRegInfo und wird mit dem Verweis auf die aktuell geöffnete Datenbank als Parameter aufgerufen. Sie hat die Aufgabe, die Tabelle USysRegInfo zu erstellen, welche die Informationen aufnimmt, die beim Installieren des Access-Add-Ins in die Registry geschrieben werden sollen, damit Access beim Öffnen auslesen kann, welche Access-Add-Ins verfügbar sind.

Diese Funktion prüft auch, ob die Tabelle USysRegInfo bereits vorhanden ist – falls ja, wird der Vorgang abgebrochen.

Der Aufruf der Prozedur AddRegistryEntries übergibt Verweise auf die aktuelle Datenbank, das aktuelle Access-Add-In, den Namen des zu erstellenden Add-Ins, den Wert 1 als Parameter für den zu erstellenden Add-In-Typ (aktuell gibt es nur den einen), den Namen der beim Start aufzurufenden Funktion, die Beschreibung und den Dateinamen der zukünftigen Add-In-Datenbank. Sie soll die benötigten Daten in die Tabelle USysRegInfo schreiben.

[

Die Prozedur ChangeProperties soll die Eigenschaften der Datenbankdatei ändern, die später im Add-In-Manager angezeigt werden. Dazu erhält sie als Parameter den Verweis auf die zu ändernde Datenbank, den Namen des Add-Ins, die Beschreibung und den Hersteller.

Schließlich folgt noch die Prozedur AddStartfunction, der wir den Verweis auf die Datenbank übergeben, welche um ein Modul mit dieser Funktion erweitert werden soll – und den Namen der anzulegenden Funktion.

Schließlich prüft die Prozedur noch, ob die Zieldatenbank bereits die Dateiendung .accda hat und weist den Benutzer darauf hin, diesen gegebenenfalls anzupassen.

Erstellen der Tabelle USysRegInfo

Die erste Funktion namens CreateUSysRegInfo erwartet einen Verweis auf die in ein Access-Add-In umzuwandelnde Datenbank als Parameter (siehe Listing 2). Sie versucht zunächst, eine bereits bestehende Tabelle namens USysRegInfo zu referenzieren. Gelingt dies, wird die Funktion mit dem Ergebnis False abgebrochen, damit keine eventuell bereits angelegten Elemente überschrieben werden.

Public Function CreateUSysRegInfo(dbAddIn As dao.Database) As Boolean
     Dim tdf As dao.TableDef
     Dim fld As dao.Field
     On Error Resume Next
     Set tdf = dbAddIn.TableDefs("USysRegInfo")
     If Not tdf Is Nothing Then
         Exit Function
     End If
     On Error GoTo 0
     Set tdf = dbAddIn.CreateTableDef("USysRegInfo")
     With tdf
         Set fld = .CreateField("Subkey", dbText, 255)
         tdf.Fields.Append fld
         Set fld = .CreateField("Type", dbInteger)
         tdf.Fields.Append fld
         Set fld = .CreateField("ValName", dbText, 255)
         tdf.Fields.Append fld
         Set fld = .CreateField("Value", dbText, 255)
         fld.AllowZeroLength = True
         tdf.Fields.Append fld
         dbAddIn.TableDefs.Append tdf
     End With
     CreateUSysRegInfo = True
End Function

Listing 2: Code zum Erstellen der Tabelle USysRegInfo

Ist die Tabelle jedoch noch nicht vorhanden, legt die Prozedur diese mit der Methode CreateTableDef des Database-Objekts an und legt dabei direkt den Namen USysRegInfo fest. Danach fügt sie durch mehrfaches Aufrufen der CreateField-Methode des zuvor erstellten TableDef-Objekts die Felder Subkey, Type, ValName und Value mit den entsprechenden Datentypen hinzu. Das Feld Type wird dabei als Zahlenfeld definiert und alle anderen als Textfelder mit einer Länge von 255 Zeichen.

Jedes neue Field-Objekt wird nach dem Erstellen mit der Append-Methode an die Fields-Auflistung des TableDef-Objekts angehängt. Für das Feld Value wird außerdem die Eigenschaft AllowZeroLength auf True eingestellt.

Schließlich hängt die Prozedur auch das neue TableDef-Objekt an die TableDefs-Auflistung des Database-Objekts der aktuellen Datenbank an.

Anlegen der Tabelleneinträge für die Registrierung

Die nächste Funktion namens AddRegistryEntries übernimmt eine sehr wichtige Aufgabe, denn beim Anlegen der Einträge der Tabelle USysRegInfo treten die meisten Fehler beim Erstellen von Access-Add-Ins auf (siehe Listing 3).

Public Function AddRegistryEntries(dbAddIn As dao.Database, dbTemplate As dao.Database, strAddInName As String, _
         lngTemplateID As Long, strExpression As String, strDescription As String, strFilename As String)
     Dim rstTemplate As dao.Recordset
     Dim rstAddIn As dao.Recordset
     Dim strValue As String
     Set rstAddIn = dbAddIn.OpenRecordset("USysRegInfo", dbOpenDynaset)
     Set rstTemplate = dbTemplate.OpenRecordset("SELECT * FROM tblRegistryEntries WHERE TemplateID = " _
         & lngTemplateID, dbOpenDynaset)
     Do While Not rstTemplate.EOF
         strValue = Nz(rstTemplate!RegistryValue)
         strValue = Replace(strValue, "[Expression]", strExpression)
         strValue = Replace(strValue, "[Description]", strDescription)
         strValue = Replace(strValue, "[Filename]", strFilename)
         rstAddIn.AddNew
         rstAddIn!Subkey = rstTemplate!RegistrySubkey & strAddInName
         rstAddIn!Type = rstTemplate!RegistryEntryType
         rstAddIn!ValName = rstTemplate!RegistryValname
         rstAddIn!Value = strValue
         rstAddIn.Update
         rstTemplate.MoveNext
     Loop
End Function

Listing 3: Code zum Füllen der Tabelle USysRegInfo

Sie erwartet als Parameter neben den Verweisen auf das aktuelle und das zukünftige Add-In den Namen des Add-Ins, die ID des zu verwendenden Templates (hier gibt es aktuell nur den Wert 1 für das Menü-Add-In), die aufzurufende Funktion, die Beschreibung und den Dateinamen (mit der Dateiendung .accda).

Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...

den kompletten Artikel im PDF-Format mit Beispieldatenbank

diesen und alle anderen Artikel mit dem Jahresabo

Schreibe einen Kommentar