Formular-Importer

Lies diesen Artikel und viele weitere mit einem kostenlosen, einwöchigen Testzugang.

Beim Fertigstellen einer jeden Ausgabe von Access im Unternehmen sind auch einige Beispieldatenbanken anzupassen. Manchmal sind einige Schritte nötig, um diese rund zu machen, mindestens aber muss das Startformular mit dem Hinweis auf die Herkunft der Datenbank hinzugefügt werden. Und jedes Mal nehmen die notwendigen Schritte einige Zeit in Anspruch. Zeit, ein Access-Add-In zu entwickeln, das einem diese Arbeit abnimmt. Dieser Beitrag zeigt, wie Sie solche Aufgaben viel einfacher erledigen.

Ziel des Add-Ins

Was genau soll der Formular-Importer erledigen In dem Fall, der zum Erstellen dieses Add-Ins führte, sollen einige Beispieldatenbanken immer mit dem gleichen Startformular ausgestattet werden, die sich lediglich durch einige Kleinigkeiten unterscheiden – beispielsweise den Titeltext, die Ausgabe oder das Objekt, das nach dem Schließen des Formulars aufgerufen werden soll. Dabei kann es sich um ein Formular oder einen Bericht handeln, aber auch um ein VBA-Modul, eine Tabelle, eine Abfrage oder gar das Beziehungsfenster.

Außerdem soll das Formular beim Start der Anwendung angezeigt werden. Dazu müssen Sie normalerweise einen manuellen Eintrag in den Access-Optionen beziehungsweise in den Start-Optionen (Access 2003 und älter) durchführen.

Das Add-In soll als Menü-Add-In implementiert werden. Bei Auswahl des Add-Ins soll dieses eine kleine Benutzeroberfläche anbieten, mit der die variablen Anteile des Formulars geändert werden. Außerdem soll es eine Option geben, mit der Sie festlegen können, ob das Formular als Startformular angezeigt werden soll.

Bislang habe ich immer ein Startformular von Anwendung zu Anwendung vererbt, indem ich es von der aktuell bearbeiteten Access-Datenbank aus importiert, angepasst und als Startformular festgelegt habe. Kein Problem, wenn man das nur einmal durchführt, aber wenn diese Aufgabe acht- bis zehnmal hintereinander erledigt werden muss …

Wohin soll es gehen

Die Grundanforderungen sind definiert. Die Frage ist: Gibt es weitere Anwendungsfälle für das Formular Sollte man es beispielsweise als globalen Formular-Container verwenden, mit dem man nicht nur eines, sondern gleich alle möglichen Formulare verwaltet, die man vielleicht mal in mehr als einer Anwendung benötigt Nein. In diesem Fall halten wir die Lösung möglichst klein und arbeiten auf das Ziel hin. Dabei werden wir einige interessante Techniken entdecken, die Grundlagen für eine größere Lösung sein können.

Technische Hintergründe

Ein Formular soll gespeichert und nach Bedarf in die aktuell geöffnete Anwendung importiert werden. Wie kommt die Formularvorlage in das Add-In Wo speichern wir es Und wie bekommen wir es am einfachsten in die Zielanwendung Diese Fragen klären wir, bevor wir mit der Entwicklung beginnen. Vielleicht kennen Sie bereits die beiden Befehle SaveAsText und LoadFromText, mit denen Sie Access-Objekte (mit Ausnahme von Tabellen) als Textdatei speichern und wieder einlesen können. Diese können die Arbeit beim Einlesen und Wiederherstellen von Formularen erheblich erleichtern. Theoretisch ist es natürlich auch möglich, das Formular auf Basis der Vorlage komplett neu anzulegen und Steuerelement für Steuerelement, Eigenschaft für Eigenschaft aufzubauen. Theoretisch sollte sich dies sogar innerhalb einiger Schleifen über Steuerelemente und Eigenschaft realisieren lassen, aber die Methode mit der Textdatei als Zwischenstation ist doch etwas leichtgängiger.

Wir starten mit dem Import, der logischerweise bei geöffneter Quelldatei erfolgt. Hier soll das Formular, ausgestattet mit entsprechenden Platzhaltern, die durch eckige Klammern markiert werden, in das Add-In eingelesen werden. Dazu wird das Formular per SaveAsText als Textdatei gespeichert und mit den herkömmlichen Anweisungen zum Einlesen von Textdateien in eine Tabelle der Add-In-Datenbank geschrieben.

Wenn Platzhalter verwendet werden sollen, müssen diese vor dem Importieren in die Add-In-Datenbank eingebaut werden. Dies gilt sowohl für Eigenschaften von Steuerelementen als auch für Codezeilen – mehr dazu später.

Nach dem Öffnen der Zieldatei wird diese Vorlage nach Eingabe der Texte für die Platzhalter aus der Tabelle ins Dateisystem gespeichert und mit der Methode LoadFromText in die Zieldatenbank importiert.

Add-In vorbereiten

Als Add-In-Datenbank verwenden wir eine herkömmliche Datenbankdatei, die wir um einige Elemente erweitern. Vergeben Sie für die Add-In-Datenbank die Dateiendung .mda beziehungsweise .accda, damit der Add-In-Manager diese Datenbanken gleich als Add-In-Datenbanken erkennt.

Legen Sie dann eine Tabelle namens USysRegInfo an, die beim Installieren des Add-Ins mit dem Add-In-Manager einige Einträge zur die Registry hinzufügt. Dadurch wird die Datenbank beim Start von Access in die Liste der verfügbaren Add-Ins aufgenommen und gemeinsam mit den übrigen Menü-Add-Ins angezeigt. Die Tabelle sieht wie in Bild 1 aus.

pic002.png

Bild 1: Die Tabelle USysRegInfo enthält Informationen, die beim Installieren des Add-Ins in die Registry eingetragen werden.

Fügen Sie außerdem ein Standardmodul namens mdlAddIn zur Datenbank hinzu (Sie können diesem auch einen anderen Namen geben). Tragen Sie dort die folgende Funktion ein:

Public Function Autostart()
    DoCmd.OpenForm "frmFormularImporter", WindowMode:=acDialog
End Function

Diese öffnet beim Auswählen des Menü-Add-Ins das angegebene Formular. Dieses müssen Sie natürlich auch noch anlegen. Für den Anfang möchten wir einfach nur Formulardefinitionen in einer Tabelle der Add-In-Datenbank speichern, wozu ein Kombinationsfeld und eine OK-Schaltfläche ausreichen.

Formular im Add-In speichern

Die Formulardefinitionen sollen in einer Tabelle namens frmFormulare gespeichert werden. Diese Tabelle ist wie in Bild 2 aufgebaut. Sie enthält zwei Felder zum Speichern des Formularnamens und des Formularcodes.

pic003.png

Bild 2: Tabelle zum Speichern der Formulardefinitionen

Wie aber gelangen die Formulardefinitionen in diese Tabelle Dazu benutzen wir die bereits erwähnten beiden Steuerelemente im Formular frmFormularImporter (s. Bild 3). Das Kombinationsfeld frmFormulare soll alle Formulare der Datenbank anzeigen, von der aus Sie das Add-In geöffnet haben. Dazu können wir nicht einfach eine Abfrage auf Basis der Tabelle MSysObjects als Datenherkunft verwenden, die ja auch alle Formulare enthält – Sie würden dann auf die Tabelle MSysObjects der Add-In-Datenbank zugreifen und deren Formulare anzeigen. Also definieren wir eine Tabelle namens tblFormulareTemp, die nur ein Feld namens Formular enthält, und füllen diese in einer Schleife über alle Elemente der Auflistung AllForms der Host-Datenbank mit den jeweiligen Formularnamen.

pic001.png

Bild 3: Formular mit den ersten Steuerelementen zum Importieren der Formulardefinitionen

Diese Tabelle wird anschließend, sortiert nach den Formularnamen, als Datensatzherkunft des Kombinationsfeldes festgelegt. Wie aber unterscheiden wir zwischen der Host- und der Add-In-Datenbank Dies gelingt mithilfe der Varianten zweier Funktionen, die den Zugriff auf die beiden Instanzen erlauben. Mit CodeDB und CodeProject greifen Sie auf die Add-In-Datenbank zu, mit CurrentDB und CurrentProject auf die Host-Datenbank. Deshalb greifen wir mit CurrentProject auf die AllForms-Auflistung zu und schreiben diese dann über das mit der Funktion CodeDB gewonnene Database-Objekt in die entsprechende Tabelle der Add-In-Datenbank (s. Listing 1).

Listing 1: Anzeigen aller Formulare der Host-Tabelle im Kombinationsfeld

Private Sub Form_Load()
    Dim db As dao.Database
    Dim rst As dao.Recordset
    Dim i As Integer
    Set db = CodeDb
    db.Execute "DELETE FROM tblFormulareTemp", dbFailOnError
    Set rst = db.OpenRecordset("tblFormulareTemp", dbOpenDynaset)
    For i = 0 To CurrentProject.AllForms.Count - 1
        rst.AddNew
        rst!Formular = CurrentProject.AllForms(i).Name
        rst.Update
    Next i
    Me!cboFormulare.RowSource = "SELECT * FROM tblFormulareTemp ORDER BY Formular"
End Sub

Damit kann der Benutzer nun zumindest schon einmal die in der Host-Datenbank enthaltenen Formulare anzeigen und das zu importierende Formular auswählen.

Formulardefinition einlesen

Nach der Auswahl soll ein Klick auf die Speichern-Taste die Formular-Definition in die Tabelle tblFormulare schreiben. Die entsprechende Ereignisprozedur speichert die Formulardefinition zunächst mit der SaveAsText-Methode in eine Textdatei namens frmXXX.txt, und zwar im gleichen Verzeichnis wie die Add-In-Datei (s. Listing 2). Dann verwendet sie die Open-, Input$– und Close-Methode, um den Inhalt der Textdatei in eine String-Variable zu schreiben. Der Formularcode wird dann per AddNew, Zuweisen der Feldwerte und Update in ein Recordset auf Basis der Tabelle tblFormulare geschrieben – das aber nur, wenn noch kein gleichnamiges Formular gespeichert wurde. Falls doch, kann der Benutzer einen alternativen Namen angeben oder das vorhandene Formular überschreiben. Gibt der Benutzer keinen neuen Namen ein, wird der vorhandene Datensatz gelöscht. Danach ermittelt die Prozedur den Wert des Primärschlüsselfeldes des soeben neu angelegten Datensatzes. Mit diesem ruft sie die Prozedur PlatzhalterSpeichern auf – dazu später mehr.

Listing 2: Einlesen einer Formulardefinition in die Add-In-Datenbank

Private Sub cmdSpeichern_Click()
    Dim strForm As String
    Dim strFormname As String
    Dim dbc As dao.Database
    Dim rst As dao.Recordset
    Dim lngFormularID As Long
    Set dbc = CodeDb
    SaveAsText acForm, Me!cboFormulare, CodeProject.Path & "\frmXXX.txt"
    Open CodeProject.Path & "\frmXXX.txt" For Input As #1
    strForm = Input$(LOF(1), #1)
    strFormname = Me!cboFormulare
    If Not dbc.OpenRecordset("SELECT * FROM tblFormulare WHERE Formularname = ''" & strFormname & "''").EOF Then
        strFormname = InputBox("Es ist bereits ein Formular namens ''" & strFormname _
            & "'' vorhanden. Geben Sie einen anderen Namen ein, anderenfalls wird das vorhandene " _
            & "Formular gelöscht.", "Formular schon vorhanden", strFormname)
    End If
    dbc.Execute "DELETE FROM tblFormulare WHERE Formularname = ''" & strFormname & "''", dbFailOnError
    Set rst = dbc.OpenRecordset("SELECT * FROM tblFormulare WHERE 1=2", dbOpenDynaset)
    rst.AddNew
    rst!Formularname = strFormname
    rst!Formularcode = strForm
    lngFormularID = rst!FormularID
    rst.Update
    PlatzhalterSpeichern strForm, lngFormularID
    Close #1
    Kill CodeProject.Path & "\frmXXX.txt"
    Me!lstFormulare.Requery
    Me!lstFormulare = lngFormularID
    PlatzhalterAktualisieren
End Sub

Schließlich löscht die Kill-Methode die temporär gespeicherte Textdatei wieder und weitere Steuerelemente werden aktualisiert – auch auf diese kommen wir später zurück. Der erste Teil wäre somit geschafft – Sie können den Code kompletter Formulare in eine Tabelle der Add-In-Datenbank schreiben.

Platzhalter verwalten

Wie bereits erwähnt, wollen wir einen gewissen flexiben Anteil beim Erstellen eines neuen Formulars auf Basis eines im Add-In gespeicherten Formulars erhalten. Deshalb können Sie in den Eigenschaften und im Code des zu speichernden Formulars Platzhalter unterbringen, die in eckigen Klammern eingefasst sein müssen. Diese werden gleich beim Einlesen des Formulars in eine weitere Tabelle namens tblPlatzhalter geschrieben (s. Bild 4).

pic004.png

Bild 4: Diese Tabelle speichert Platzhalter und ihre Standardwerte.

Diese Aufgabe führt die Prozedur PlatzhalterSpeichern aus Listing 3 durch. Sie erwartet den Code des Formulars sowie die ID des Datensatzes in der Tabelle tblFormulare als Parameter. Die Prozedur ermittelt mit der InStr-Funktion zunächst die Position der ersten öffnenden eckigen Klammer ([). Liefert dies einen Wert größer 0, sucht die Prozedur auch noch nach der passenden schließenden Klammer. Der Ausdruck dazwischen könnte ein Platzhalter sein, aber auch die Zuweisung des Wertes [Event Procedure] zu einer Ereigniseigenschaft des Formulars. Diese sollen natürlich nicht als Platzhalter erkannt werden, daher übergeht die Prozedur diese. In allen anderen Fällen schreibt die Prozedur den Namen des Platzhalters in die Tabelle tblPlatzhalter. Dieser Vorgang wird so lange wiederholt, bis keine öffnende Klammer mehr gefunden wird.

Listing 3: Speichern der in einem Formular enthaltenen Platzhalter

Private Sub PlatzhalterSpeichern(strForm As String, lngFormularID As Long)
    Dim dbc As dao.Database
    Dim lngStart As Long
    Dim lngStop As Long
    Dim strPlatzhalter As String
    Set dbc = CodeDb
    lngStart = InStr(1, strForm, "[")
    Do While lngStart > 0
        lngStop = InStr(lngStart + 1, strForm, "]")
        strPlatzhalter = Mid(strForm, lngStart + 1, lngStop - lngStart - 1)
        Select Case strPlatzhalter
            Case "Event Procedure"
            Case Else
                dbc.Execute "INSERT INTO tblPlatzhalter(Platzhalter, FormularID) VALUES(''" _
                    & strPlatzhalter & "'', " & lngFormularID & ")", dbFailOnError
        End Select
        lngStart = InStr(lngStop + 1, strForm, "[")
    Loop
End Sub

Unterformular zur Anzeige der Platzhalter

Die Platzhalter werden in einem Unterformular namens sfmPlatzhalter verwaltet. Dieses verwendet die Tabelle tblPlatzhalter als Basis-Datenherkunft. Diese wird jedoch gelegentlich aktualisiert – beispielsweise, wenn soeben ein neues Formular samt Platzhalter-Datensätzen eingelesen wurde.

Dies führt die folgende Prozedur durch:

Private Sub PlatzhalterAktualisieren()
    If Me!lstFormulare.ListCount > 0 Then
        Me!sfmPlatzhalter.Form.RecordSource = "SELECT * FROM tblPlatzhalter WHERE " _
            & "FormularID = " & Me!lstFormulare
    Else
        Me!sfmPlatzhalter.Form.RecordSource = "SELET * FROM tblPlatzhalter"
    End If
End Sub

Wie dieses Formular in das Hauptformular frmFormularimporter eingefügt wird, beschreiben wir weiter unten.

Gespeicherte Formulare anzeigen

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

Testzugang

eine Woche kostenlosen Zugriff auf diesen und mehr als 1.000 weitere Artikel

diesen und alle anderen Artikel mit dem Jahresabo

Schreibe einen Kommentar