Zur Hauptseite ... Zum Onlinearchiv ... Zum Abonnement ... Zum Newsletter ... Zu den Tools ... Zum Impressum ... Zum Login ...

Achtung: Dies ist nicht der vollständige Artikel, sondern nur ein paar Seiten davon. Wenn Sie hier nicht erfahren, was Sie wissen möchten, finden Sie am Ende Informationen darüber, wie Sie den ganzen Artikel lesen können.

Kompletten Artikel lesen?

Einfach für den Newsletter anmelden, dann lesen Sie schon in einer Minute den kompletten Artikel und erhalten die Beispieldatenbanken.

E-Mail:

Gedrucktes Heft

Diesen Beitrag finden Sie in Ausgabe 1/2013.

Unser Angebot für Sie!

Lesen Sie diesen Beitrag und 500 andere sofort im Onlinearchiv, und erhalten Sie alle zwei Monate brandheißes Access-Know-how auf 72 gedruckten Seiten! Plus attraktive Präsente, zum Beispiel das bald erscheinende Buch 'Access 2010 - Das Grundlagenbuch für Entwickler'!

Diesen Beitrag twittern

Zusammenfassung

Erstellen Sie komplette Klassen zum Aufnehmen der Daten aus Tabellen mit dem in diesem Beitrag beschriebenen Add-In.

Techniken

Add-Ins, Klassenprogrammierung, VBA

Voraussetzungen

Access 2000 und höher

Beispieldateien

Klassengenerator.mda

Shortlink

www.access-im-unternehmen.de/871

Klassengenerator

André Minhorst, Duisburg

Gelegentlich ist es sinnvoll, Daten eines Datensatzes aus einer Tabelle in einem Objekt auf Basis einer Klasse abzulegen - vor allem dann, wenn Sie nur auf einen kompakten Satz von Daten zugreifen möchten und diese nicht ändern wollen. Leider ist der nötige Code je nach Anzahl der Felder der Datenherkunft und somit der Eigenschaften recht umfangreich und die Erstellung eine mühselige Arbeit. Mit dem in diesem Beitrag vorgestellten Add-In soll dies ganz schnell von der Hand gehen.

Die Beispieldatenbank ist ein fertiges Add-In. Zur Installation starten Sie den Add-In-Manager und wählen die Datei Klassengenerator.mda aus. Anschließend finden Sie im Add-In-Menü den Eintrag aiuKlassengenerator. Es erscheint der Dialog aus Abb. 1. Hier lesen Sie entweder die Daten aller Tabellen neu ein (was beim ersten Öffnen in einer Datenbank automatisch geschieht) und wählen per Kombinationsfeld die Tabelle oder Abfrage aus, zu der Sie eine Klasse erstellen möchten. Das Unterformular zeigt dann alle Felder dieser Datenherkunft. Legen Sie dort fest, welche Felder als Eigenschaften der Klasse berücksichtigt werden sollen, und passen Sie gegebenenfalls von den Feldnamen abweichende Eigenschaftsnamen an. Klicken Sie dann auf Erzeugen, um die komplette Klasse auf Basis der Datenherkunft in Sekundenbruchteilen zu erstellen. Nach Wunsch fügen Sie dem Code auch gleich eine Prozedur hinzu, die eine Routine zum Erstellen und Füllen einer Instanz dieser Klasse erstellt. Die erzeugten Quelltexte müssen Sie nur noch in die Zielmodule kopieren.

pic015.png

Abb. 1: Der Klassengenerator in Aktion

Datenmodell

Das Add-In soll die Auswahl einer Tabelle oder Abfrage ermöglichen, für deren Felder eine Klasse angelegt werden soll. Für diese Tabelle soll das Add-In alle Felder anzeigen. Der Benutzer legt fest, welche Felder berücksichtigt werden sollen und wie die entsprechenden Eigenschaften in der Klasse heißen sollen.

Das Add-In soll die Namen der Tabellen und Abfragen in der Datenbank, von der aus das Add-In gestartet wurde, in einem Kombinationsfeld zur Auswahl anbieten. Der direkte Zugriff von einem Kombinationsfeld innerhalb eines Add-Ins auf die Daten der Host-Datenbank ist nicht möglich, also schreiben wir die notwendigen Daten zuvor in eine Tabelle innerhalb der Add-In-Datenbank.

Diese Tabelle enthält die Felder TabelleAbfrageID (Primärschlüsselfeld, Autowert), TabelleAbfrage, Datenbank, Klassenname, Primaerschluesselfeld und Objekttyp. TabelleAbfrage nimmt die Namen der in der Datenbank enthaltenen Tabellen und Abfragen auf (s. Abb. 2). Datenbank speichert den Namen der Zieldatenbank, damit einmal definierte Schemata zur Erzeugung von Klassen erneut verwendet werden können. Das Feld Klassenname nimmt den Namen auf, unter dem die Klasse für diese Tabelle oder Abfrage erzeugt werden soll - also beispielsweise clsPerson. Primaerschluesselfeld enthält den Namen des entsprechenden Feldes der Tabelle. Bei Tabellen wird dieser später automatisch ermittelt, bei Abfragen muss er manuell eingetragen werden. Objekttyp nimmt den Zahlenwert des Feldes Type der Tabelle MSysObjects auf - dazu später mehr.

pic001.png

Abb. 2: Diese Tabelle speichert die Namen der Tabellen und Abfragen der Zieldatenbank.

Die zweite Tabelle heißt tblFelder (s. Abb. 3). Sie enthält neben dem Primärschlüsselfeld FeldID folgende Felder:

pic003.png

Abb. 4: Beziehung der beiden Tabellen des Add-Ins

  • Feldname: Name des Feldes in der Tabelle
  • Eigenschaftsname: Name der Eigenschaft für das Feld in der Klasse
  • Erzeugen: Gibt an, ob das Feld beim Erzeugen des Klassencodes berücksichtigt werden soll
  • TabelleAbfrageID: Fremdschlüsselfeld zur Tabelle tblTabellenAbfragen
  • Datentyp: Nummer des Datentyps des Feldes

Die Beziehung zwischen den beiden Tabellen ist mit referentieller Integrität definiert und Löschweitergabe. Wenn also ein Datensatz aus der Tabelle tblTabellenAbfragen gelöscht wird, entfernt Access auch die mit dem entsprechenden Datensatz verknüpften Datensätze der Tabelle tblFelder (s. Abb. 4).

pic004.png

Abb. 3: Die Tabelle tblFelder speichert die Felder und ihre Einstellungen.

Formular des Add-Ins

Damit der Benutzer die Tabelle/Abfrage für die Generierung der Klasse auswählen und die Felder festlegen kann, die das Add-In dabei berücksichtigen soll, zeigt das Add-In eine entsprechende Benutzeroberfläche in Form eines Formulars an. Dieses heißt frmKlassengenerator und bietet zunächst ein Kombinationsfeld zur Auswahl der zu verwendenden Tabelle oder Abfrage an. Außerdem soll das Hauptformular jeweils einen Datensatz der Tabelle tblTabelleAbfrage anzeigen - und zwar denjenigen, der vom Benutzer mit dem im Anschluss beschriebenen Kombinationsfeld ausgewählt wurde. Dazu stellen Sie für das Formular die Eigenschaft Datenherkunft auf die Tabelle tblTabelleAbfrage ein. Ziehen Sie außerdem die beiden Felder Datenbank und Klassenname aus der Feldliste in den Entwurf des Formulars. Lassen Sie darüber noch ein wenig Platz für ein Kombinationsfeld zur Auswahl der Tabelle/Abfrage (s. Abb. 5). Wir schauen uns zunächst das Kombinationsfeld an und den Mechanismus, der die Datensatzherkunft des Kombinationsfeldes füllt und filtert.

pic005.png

Abb. 6: Kombinationsfeld zur Auswahl der Tabellen und Abfragen der Zieldatenbank

Das Kombinationsfeld soll alle Tabellen der aktuellen Datenbank wie in Abb. 6 anzeigen. Damit dieses überhaupt Daten anzeigt, weisen Sie diesem zunächst eine entsprechende Datenherkunft zu - und zwar die Tabelle tblTabellenAbfragen. Damit das Kombinationsfeld das Primärschlüsselfeld der Tabelle ausblendet und nur die Namen der Tabellen und Abfragen anzeigt, stellen Sie die beiden Eigenschaften Spaltenanzahl und Spaltenbreiten auf die Werte 2 und 0cm ein. Nachdem Sie in der Formularansicht geprüft haben, dass das Kombinationsfeld die Werte wie gewünscht anzeigt, können Sie die Eigenschaft Datensatzherkunft wieder leeren - wir füllen diese später zur Laufzeit. Immerhin soll das Kombinationsfeld ja nur die Tabellen und Abfragen der aktuellen Datenbank anzeigen. Die Tabelle tblTabellenAbfragen soll jedoch nach der Verwendung des Add-Ins in verschiedenen Anwendungen auch die entsprechenden Daten zu den jeweiligen Anwendungen enthalten.

pic002.png

Abb. 5: Entwurfsansicht des aktuellen Stands des Formulars frmKlassengenerator

Deshalb löst das Formular beim Öffnen das Ereignis Beim Laden aus und somit die Ereignisprozedur aus Listing 1. Diese Prozedur speichert zunächst den Namen der Zieldatenbank in der Variablen strDatenbank (beim Erstellen und Testen des Add-Ins öffnen Sie dieses direkt und nicht von einer anderen Anwendung aus, daher enthält strDatenbank hier den Namen der Add-In-Datenbank selbst).

Listing 1: Füllen des Kombinationsfeldes beim Öffnen des Formulars

Private Sub Form_Load()

    Dim strDatenbank As String

    strDatenbank = CurrentProject.Name

    If IsNull(FLookup("TabelleAbfrageID", "tblTabellenAbfragen", "Datenbank = '" & strDatenbank _

        & "'")) Then

    TabellenAbfragenEinlesen

End If

Me!cboTabelleAbfrage.RowSource = "SELECT * FROM tblTabellenAbfragen WHERE Datenbank = '" _

    & strDatenbank & "'"

End Sub

Ein Aufruf der Funktion FLookup mit den entsprechenden Parametern prüft, ob es in der Tabelle tblTabellenAbfragen bereits mindestens einen Datensatz gibt, dessen Feld Datenbank den Namen der aktuellen Datenbank enthält. Falls ja, wird die Prozedur TabellenAbfragenEinlesen aufgerufen, welche die Tabelle tblTabellenAbfragen mit den Namen der Tabellen und Abfragen der Zieltabelle füllt. Anschließend stellt die Prozedur die Datensatzherkunft des Kombinationsfeldes cboTabelleAbfrage auf eine SQL-Abfrage ein, die alle Datensätze der Tabelle tblTabellenAbfragen liefert, deren Feld Datenbank den Namen der aktuellen Zieldatenbank enthält (beziehungsweise im Standalone-Modus den Namen der Add-In-Datenbank).

Warum nutzen wir hier eine Funktion namens FLookup - heißt diese nicht üblicherweise DLookup? Das ist richtig. FLookup ist ein Nachbau der DLookup-Funktion, die allerdings auf eine Datensatzgruppe zugreift, die sich in der mit CodeDB referenzierten Datenbank befindet. DLookup greift, auch von einem Add-In aus, immer auf die Tabellen oder Abfragen der Datenbank zu, die das Add-In geöffnet hat.

Tabellen und Abfragen einlesen

Nun sind beim ersten Start des Formulars noch keine Tabellen oder Abfragen in der Tabelle tblTabellenAbfragen gespeichert. Also ruft die Prozedur Form_Load auf jeden Fall die Prozedur TabellenAbfragenEinlesen auf (s. Listing 2). Diese Prozedur deklariert gleich zwei Database-Objekte. Das erste heißt dbHost und wird mit der Funktion CurrentDb gefüllt. Dies liefert einen Verweis auf die aktuell in Access geöffnete Datenbank. Wenn Sie das Add-In von einer anderen Datenbank aus geöffnet haben, handelt es sich um die öffnende Datenbank, wenn Sie das Add-In direkt geöffnet haben, wird hier die Add-In-Datenbank selbst referenziert. Die zweite Variable namens dbAddIn erhält ihren Verweis auf das Database-Objekt über die Funktion CodeDB. Dieses liefert immer einen Verweis auf die Datenbank, in welcher sich der ausführende Code befindet.

Listing 2: Füllen der Tabelle tblTabellenAbfragen

Private Sub TabellenAbfragenEinlesen()

    Dim dbHost As DAO.Database

    Dim dbAddIn As DAO.Database

    Dim rst As DAO.Recordset

    Dim strKlassenname As String

    Set dbHost = CurrentDb

    Set dbAddIn = CodeDb

    Set rst = dbHost.OpenRecordset("SELECT Name, Type FROM MSysObjects WHERE Type IN (1,4,5,6) " _

        & "AND Name NOT LIKE '~*' ORDER BY Name", dbOpenDynaset)

    Do While Not rst.EOF

        strKlassenname = KlassennameErmitteln(rst!Name)

        dbAddIn.Execute "INSERT INTO tblTabellenAbfragen(TabelleAbfrageName, Datenbank, Klassenname) " _

            & "VALUES('" & rst!Name & "', '" & CurrentProject.Name & "', '" & strKlassenname & "')", _

        dbFailOnError

        rst.MoveNext

    Loop

    Me.Requery

    Me!cboTabelleAbfrage.Requery

    Set dbHost = Nothing

    Set dbAddIn = Nothing

End Sub

Mit diesen beiden Verweisen ausgestattet öffnet die Prozedur eine Datensatzgruppe auf Basis der Tabelle MSysObjects der Zieldatenbank. Die Datensatzgruppe liefert das Feld Name aller Datensätze zurück, deren Feld Type den Wert 1, 4, 5 oder 6 enthält und deren Name nicht mit ~ beginnt (dies sind Abfragen, die als Wert der Eigenschaften Datenherkunft beziehungsweise Datensatzherkunft gespeichert, aber nicht im Datenbankfenster oder Navigationsbereich angezeigt werden). Der Wert 1 für das Feld Type gibt an, dass es sich um eine eingebaute Tabelle handelt. 4 kennzeichnet eine per ODBC verknüpfte Tabelle, 5 eine Abfrage und 6 eine per Jet verknüpfte Tabelle - also beispielsweise eine externe Excel- oder Access-Tabelle oder Textdatei.

In einer Do While-Schleife über diese Datensätze trägt die Prozedur für jede Tabelle oder Abfrage einen Datensatz in die Tabelle tblTabellenAbfragen ein. Dazu ermittelt diese mit der Funktion KlassennameErmitteln den Namen der zu erzeugenden Klasse - mehr dazu weiter unten. Eine INSERT INTO-Anweisung füllt die Felder TabelleAbfrageName, Datenbank und Klassenname mit den ermittelten Werten. Anschließend aktualisiert die Prozedur die Datenherkunft des Formulars und des Kombinationsfeldes.

Felder der gewählten Datenherkunft anzeigen

Ein Unterformular namens sfmKlassengenerator liefert die Daten zu den in der Tabelle/Abfrage enthaltenen Feldern. Nach der Anzeige der Tabellen und Abfragen der aktuellen Datenbank und der Auswahl eines der Objekte durch den Benutzer soll das Unterformular alle Felder dieser Datenherkunft in der Datenblattansicht anzeigen. Dazu erstellen Sie zunächst ein Unterformular namens sfmKlassengenerator. Weisen Sie seiner Eigenschaft Datenherkunft die Tabelle tblFelder zu. Ziehen Sie die drei Felder Feldname, Eigenschaftsname und Erzeugen in den Detailbereich des Formularentwurfs und stellen Sie die Eigenschaft Standardansicht des Formulars auf Datenblatt ein (s. Abb. 7).

pic006.png

Abb. 7: Unterformular zur Anzeige der Felder der Tabelle oder Abfrage

Speichern Sie das Formular, öffnen Sie das Hauptformular frmKlassengenerator in der Entwurfsansicht und ziehen Sie das Unterformular sfmKlassengenerator aus dem Datenbankfenster beziehungsweise dem Navigationsbereich in den Detailbereich des Hauptformulars. Das Ergebnis sieht nun etwa wie in Abb. 8 aus. Nun sorgen Sie dafür, dass nach der Auswahl einer Tabelle oder Abfrage durch den Benutzer die entsprechenden Felder im Unterformular angezeigt werden. Dazu müssen diese zunächst einmal in die Tabelle tblFelder eingetragen werden - dies ist bislang noch nicht geschehen.

pic007.png

Abb. 8: Hauptformular mit integriertem Unterformular in der Entwurfsansicht

Dazu fügen Sie für das Kombinationsfeld cboTabelleAbfrage eine neue Ereignisprozedur für das Ereignis Nach Aktualisierung hinzu (s. Listing 3). Diese Prozedur verwendet wiederum zwei Objektvariablen des Typs Database - eines für die Add-In-Datenbank und eines für die aufrufende Datenbank. Die Prozedur prüft zunächst, ob der Benutzer überhaupt einen Eintrag im Kombinationsfeld cboTabelleAbfrage ausgewählt hat.

Listing 3: Füllen der Tabelle tblFelder

Private Sub cboTabelleAbfrage_AfterUpdate()

    Dim dbHost As DAO.Database

    Dim dbAddIn As DAO.Database

    Dim rst As DAO.Recordset

    Dim fld As DAO.Field

    Dim bolEinlesen As Boolean

    If Not IsNull(Me!cboTabelleAbfrage) Then

        bolEinlesen = True

        If Not IsNull(FLookup("FeldID", "tblFelder", "TabelleAbfrageID = " & Me!cboTabelleAbfrage)) Then

            bolEinlesen = _

                MsgBox("Felder neu einlesen und vorhandene Daten überschreiben?", vbYesNo) = vbYes

        End If

        If bolEinlesen Then

            Set dbHost = CurrentDb

            Set dbAddIn = CodeDb

            dbAddIn.Execute "DELETE FROM tblFelder WHERE TabelleAbfrageID = " _

                & Me!cboTabelleAbfrage, dbFailOnError

            Set rst = dbHost.OpenRecordset("SELECT * FROM " & Me!cboTabelleAbfrage.Column(1) _

                & " WHERE 1=2", dbOpenDynaset)

            For Each fld In rst.Fields

                dbAddIn.Execute "INSERT INTO tblFelder(Feldname, Eigenschaftsname, " _

Sie haben das Ende des frei verfügbaren Teils des Artikels erreicht. Lesen Sie weiter, um zu erfahren, wie Sie den vollständigen Artikel lesen und auf viele hundert weitere Artikel zugreifen können.

Sind Sie Abonnent?Jetzt einloggen ...
 

Kompletten Artikel lesen?

Einfach für den Newsletter anmelden, dann lesen Sie schon in einer Minute den kompletten Artikel und erhalten die Beispieldatenbanken.

E-Mail:

© 2003-2015 André Minhorst Alle Rechte vorbehalten.