{"id":55000871,"date":"2013-02-01T00:00:00","date_gmt":"2020-05-22T21:34:15","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=871"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Klassengenerator","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Klassengenerator\/","title":{"rendered":"Klassengenerator"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg05.met.vgwort.de\/na\/fc20b5cf4a274becb4bb75ae4fd51aa9\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Gelegentlich ist es sinnvoll, Daten eines Datensatzes aus einer Tabelle in einem Objekt auf Basis einer Klasse abzulegen &#8211; vor allem dann, wenn Sie nur auf einen kompakten Satz von Daten zugreifen m&ouml;chten und diese nicht &auml;ndern wollen. Leider ist der n&ouml;tige Code je nach Anzahl der Felder der Datenherkunft und somit der Eigenschaften recht umfangreich und die Erstellung eine m&uuml;hselige Arbeit. Mit dem in diesem Beitrag vorgestellten Add-In soll dies ganz schnell von der Hand gehen.<\/b><\/p>\n<p>Die Beispieldatenbank ist ein fertiges Add-In. Zur Installation starten Sie den Add-In-Manager und w&auml;hlen die Datei <b>Klassengenerator.mda<\/b> aus. Anschlie&szlig;end finden Sie im Add-In-Men&uuml; den Eintrag <b>aiuKlassengenerator<\/b>. Es erscheint der Dialog aus Bild 1. Hier lesen Sie entweder die Daten aller Tabellen neu ein (was beim ersten &Ouml;ffnen in einer Datenbank automatisch geschieht) und w&auml;hlen per Kombinationsfeld die Tabelle oder Abfrage aus, zu der Sie eine Klasse erstellen m&ouml;chten. Das Unterformular zeigt dann alle Felder dieser Datenherkunft. Legen Sie dort fest, welche Felder als Eigenschaften der Klasse ber&uuml;cksichtigt werden sollen, und passen Sie gegebenenfalls von den Feldnamen abweichende Eigenschaftsnamen an. Klicken Sie dann auf <b>Erzeugen<\/b>, um die komplette Klasse auf Basis der Datenherkunft in Sekundenbruchteilen zu erstellen. Nach Wunsch f&uuml;gen Sie dem Code auch gleich eine Prozedur hinzu, die eine Routine zum Erstellen und F&uuml;llen einer Instanz dieser Klasse erstellt. Die erzeugten Quelltexte m&uuml;ssen Sie nur noch in die Zielmodule kopieren.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_01\/Klassengenerator-web-images\/pic015.png\" alt=\"pic015.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 1: Der Klassengenerator in Aktion<\/span><\/b><\/p>\n<p><b>Datenmodell<\/b><\/p>\n<p>Das Add-In soll die Auswahl einer Tabelle oder Abfrage erm&ouml;glichen, f&uuml;r deren Felder eine Klasse angelegt werden soll. F&uuml;r diese Tabelle soll das Add-In alle Felder anzeigen. Der Benutzer legt fest, welche Felder ber&uuml;cksichtigt werden sollen und wie die entsprechenden Eigenschaften in der Klasse hei&szlig;en sollen.<\/p>\n<p>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&ouml;glich, also schreiben wir die notwendigen Daten zuvor in eine Tabelle innerhalb der Add-In-Datenbank.<\/p>\n<p>Diese Tabelle enth&auml;lt die Felder <b>TabelleAbfrageID <\/b>(Prim&auml;rschl&uuml;sselfeld, Autowert), <b>TabelleAbfrage<\/b>, <b>Datenbank<\/b>, <b>Klassenname<\/b>, <b>Primaerschluesselfeld<\/b> und <b>Objekttyp<\/b>. <b>TabelleAbfrage<\/b> nimmt die Namen der in der Datenbank enthaltenen Tabellen und Abfragen auf (s. Bild 2). <b>Datenbank<\/b> speichert den Namen der Zieldatenbank, damit einmal definierte Schemata zur Erzeugung von Klassen erneut verwendet werden k&ouml;nnen. Das Feld <b>Klassenname <\/b>nimmt den Namen auf, unter dem die Klasse f&uuml;r diese Tabelle oder Abfrage erzeugt werden soll &#8211; also beispielsweise <b>clsPerson<\/b>. <b>Primaerschluesselfeld <\/b>enth&auml;lt den Namen des entsprechenden Feldes der Tabelle. Bei Tabellen wird dieser sp&auml;ter automatisch ermittelt, bei Abfragen muss er manuell eingetragen werden. <b>Objekttyp <\/b>nimmt den Zahlenwert des Feldes <b>Type <\/b>der Tabelle <b>MSysObjects <\/b>auf &#8211; dazu sp&auml;ter mehr.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_01\/Klassengenerator-web-images\/pic001.png\" alt=\"pic001.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 2: Diese Tabelle speichert die Namen der Tabellen und Abfragen der Zieldatenbank.<\/span><\/b><\/p>\n<p>Die zweite Tabelle hei&szlig;t <b>tblFelder <\/b>(s. Bild 3). Sie enth&auml;lt neben dem Prim&auml;rschl&uuml;sselfeld <b>FeldID <\/b>folgende Felder:<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_01\/Klassengenerator-web-images\/pic003.png\" alt=\"pic003.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 4: Beziehung der beiden Tabellen des Add-Ins<\/span><\/b><\/p>\n<ul>\n<li class=\"aufz-hlung\"><b>Feldname<\/b>: Name des Feldes in der Tabelle<\/li>\n<li class=\"aufz-hlung\"><b>Eigenschaftsname<\/b>: Name der Eigenschaft f&uuml;r das Feld in der Klasse<\/li>\n<li class=\"aufz-hlung\"><b>Erzeugen<\/b>: Gibt an, ob das Feld beim Erzeugen des Klassencodes ber&uuml;cksichtigt werden soll<\/li>\n<li class=\"aufz-hlung\"><b>TabelleAbfrageID<\/b>: Fremdschl&uuml;sselfeld zur Tabelle <b>tblTabellenAbfragen<\/b><\/li>\n<li class=\"aufz-hlung\"><b>Datentyp<\/b>: Nummer des Datentyps des Feldes<\/li>\n<\/ul>\n<p>Die Beziehung zwischen den beiden Tabellen ist mit referentieller Integrit&auml;t definiert und L&ouml;schweitergabe. Wenn also ein Datensatz aus der Tabelle <b>tblTabellenAbfragen <\/b>gel&ouml;scht wird, entfernt Access auch die mit dem entsprechenden Datensatz verkn&uuml;pften Datens&auml;tze der Tabelle <b>tblFelder<\/b> (s. Bild 4).<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_01\/Klassengenerator-web-images\/pic004.png\" alt=\"pic004.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 3: Die Tabelle tblFelder speichert die Felder und ihre Einstellungen.<\/span><\/b><\/p>\n<p><b>Formular des Add-Ins<\/b><\/p>\n<p>Damit der Benutzer die Tabelle\/Abfrage f&uuml;r die Generierung der Klasse ausw&auml;hlen und die Felder festlegen kann, die das Add-In dabei ber&uuml;cksichtigen soll, zeigt das Add-In eine entsprechende Benutzeroberfl&auml;che in Form eines Formulars an. Dieses hei&szlig;t <b>frmKlassengenerator <\/b>und bietet zun&auml;chst ein Kombinationsfeld zur Auswahl der zu verwendenden Tabelle oder Abfrage an. Au&szlig;erdem soll das Hauptformular jeweils einen Datensatz der Tabelle <b>tblTabelleAbfrage <\/b>anzeigen &#8211; und zwar denjenigen, der vom Benutzer mit dem im Anschluss beschriebenen Kombinationsfeld ausgew&auml;hlt wurde. Dazu stellen Sie f&uuml;r das Formular die Eigenschaft <b>Datenherkunft <\/b>auf die Tabelle <b>tblTabelleAbfrage <\/b>ein. Ziehen Sie au&szlig;erdem die beiden Felder <b>Datenbank<\/b> und <b>Klassenname <\/b>aus der Feldliste in den Entwurf des Formulars. Lassen Sie dar&uuml;ber noch ein wenig Platz f&uuml;r ein Kombinationsfeld zur Auswahl der <b>Tabelle\/Abfrage<\/b> (s. Bild 5). Wir schauen uns zun&auml;chst das Kombinationsfeld an und den Mechanismus, der die Datensatzherkunft des Kombinationsfeldes f&uuml;llt und filtert.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_01\/Klassengenerator-web-images\/pic005.png\" alt=\"pic005.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 6: Kombinationsfeld zur Auswahl der Tabellen und Abfragen der Zieldatenbank<\/span><\/b><\/p>\n<p>Das Kombinationsfeld soll alle Tabellen der aktuellen Datenbank wie in Bild 6 anzeigen. Damit dieses &uuml;berhaupt Daten anzeigt, weisen Sie diesem zun&auml;chst eine entsprechende Datenherkunft zu &#8211; und zwar die Tabelle <b>tblTabellenAbfragen<\/b>. Damit das Kombinationsfeld das Prim&auml;rschl&uuml;sselfeld der Tabelle ausblendet und nur die Namen der Tabellen und Abfragen anzeigt, stellen Sie die beiden Eigenschaften <b>Spaltenanzahl <\/b>und <b>Spaltenbreiten <\/b>auf die Werte <b>2 <\/b>und <b>0cm <\/b>ein. Nachdem Sie in der Formularansicht gepr&uuml;ft haben, dass das Kombinationsfeld die Werte wie gew&uuml;nscht anzeigt, k&ouml;nnen Sie die Eigenschaft <b>Datensatzherkunft <\/b>wieder leeren &#8211; wir f&uuml;llen diese sp&auml;ter zur Laufzeit. Immerhin soll das Kombinationsfeld ja nur die Tabellen und Abfragen der aktuellen Datenbank anzeigen. Die Tabelle <b>tblTabellenAbfragen <\/b>soll jedoch nach der Verwendung des Add-Ins in verschiedenen Anwendungen auch die entsprechenden Daten zu den jeweiligen Anwendungen enthalten.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_01\/Klassengenerator-web-images\/pic002.png\" alt=\"pic002.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 5: Entwurfsansicht des aktuellen Stands des Formulars frmKlassengenerator<\/span><\/b><\/p>\n<p>Deshalb l&ouml;st das Formular beim &Ouml;ffnen das Ereignis <b>Beim Laden <\/b>aus und somit die Ereignisprozedur aus <span class=\"verweis-ohneumbruch\"><a href=\"#anker-63-anchor\">Listing 1<\/a><\/span>. Diese Prozedur speichert zun&auml;chst den Namen der Zieldatenbank in der Variablen <b>strDatenbank <\/b>(beim Erstellen und Testen des Add-Ins &ouml;ffnen Sie dieses direkt und nicht von einer anderen Anwendung aus, daher enth&auml;lt <b>strDatenbank <\/b>hier den Namen der Add-In-Datenbank selbst).<\/p>\n<p class=\"listingueberschrift\">Listing 1: F&uuml;llen des Kombinationsfeldes beim &Ouml;ffnen des Formulars<\/p>\n<pre>Private Sub Form_Load()\r\n    Dim strDatenbank As String\r\n    strDatenbank = CurrentProject.Name\r\n    If IsNull(FLookup(&quot;TabelleAbfrageID&quot;, &quot;tblTabellenAbfragen&quot;, &quot;Datenbank = ''&quot; &amp; strDatenbank _\r\n        &amp; &quot;''&quot;)) Then\r\n    TabellenAbfragenEinlesen\r\nEnd If\r\nMe!cboTabelleAbfrage.RowSource = &quot;SELECT * FROM tblTabellenAbfragen WHERE Datenbank = ''&quot; _\r\n    &amp; strDatenbank &amp; &quot;''&quot;\r\nEnd Sub<\/pre>\n<p>Ein Aufruf der Funktion <b>FLookup <\/b>mit den entsprechenden Parametern pr&uuml;ft, ob es in der Tabelle <b>tblTabellenAbfragen <\/b>bereits mindestens einen Datensatz gibt, dessen Feld <b>Datenbank <\/b>den Namen der aktuellen Datenbank enth&auml;lt. Falls ja, wird die Prozedur <b>TabellenAbfragenEinlesen <\/b>aufgerufen, welche die Tabelle <b>tblTabellenAbfragen <\/b>mit den Namen der Tabellen und Abfragen der Zieltabelle f&uuml;llt. Anschlie&szlig;end stellt die Prozedur die Datensatzherkunft des Kombinationsfeldes <b>cboTabelleAbfrage <\/b>auf eine SQL-Abfrage ein, die alle Datens&auml;tze der Tabelle <b>tblTabellenAbfragen <\/b>liefert, deren Feld <b>Datenbank<\/b> den Namen der aktuellen Zieldatenbank enth&auml;lt (beziehungsweise im Standalone-Modus den Namen der Add-In-Datenbank).<\/p>\n<p>Warum nutzen wir hier eine Funktion namens <b>FLookup <\/b>&#8211; hei&szlig;t diese nicht &uuml;blicherweise <b>DLookup<\/b> Das ist richtig. <b>FLookup <\/b>ist ein Nachbau der <b>DLookup<\/b>-Funktion, die allerdings auf eine Datensatzgruppe zugreift, die sich in der mit <b>CodeDB <\/b>referenzierten Datenbank befindet. <b>DLookup <\/b>greift, auch von einem Add-In aus, immer auf die Tabellen oder Abfragen der Datenbank zu, die das Add-In ge&ouml;ffnet hat.<\/p>\n<p><b>Tabellen und Abfragen einlesen<\/b><\/p>\n<p>Nun sind beim ersten Start des Formulars noch keine Tabellen oder Abfragen in der Tabelle <b>tblTabellenAbfragen <\/b>gespeichert. Also ruft die Prozedur <b>Form_Load <\/b>auf jeden Fall die Prozedur <b>TabellenAbfragenEinlesen <\/b>auf (s. <span class=\"verweis-ohneumbruch\"><a href=\"#anker-64-anchor\">Listing 2<\/a><\/span>). Diese Prozedur deklariert gleich zwei <b>Database<\/b>-Objekte. Das erste hei&szlig;t <b>dbHost <\/b>und wird mit der Funktion <b>CurrentDb <\/b>gef&uuml;llt. Dies liefert einen Verweis auf die aktuell in Access ge&ouml;ffnete Datenbank. Wenn Sie das Add-In von einer anderen Datenbank aus ge&ouml;ffnet haben, handelt es sich um die &ouml;ffnende Datenbank, wenn Sie das Add-In direkt ge&ouml;ffnet haben, wird hier die Add-In-Datenbank selbst referenziert. Die zweite Variable namens <b>dbAddIn<\/b> erh&auml;lt ihren Verweis auf das <b>Database<\/b>-Objekt &uuml;ber die Funktion <b>CodeDB<\/b>. Dieses liefert immer einen Verweis auf die Datenbank, in welcher sich der ausf&uuml;hrende Code befindet.<\/p>\n<p class=\"listingueberschrift\">Listing 2: F&uuml;llen der Tabelle tblTabellenAbfragen<\/p>\n<pre>Private Sub TabellenAbfragenEinlesen()\r\n    Dim dbHost As DAO.Database\r\n    Dim dbAddIn As DAO.Database\r\n    Dim rst As DAO.Recordset\r\n    Dim strKlassenname As String\r\n    Set dbHost = CurrentDb\r\n    Set dbAddIn = CodeDb\r\n    Set rst = dbHost.OpenRecordset(&quot;SELECT Name, Type FROM MSysObjects WHERE Type IN (1,4,5,6) &quot; _\r\n        &amp; &quot;AND Name NOT LIKE ''~*'' ORDER BY Name&quot;, dbOpenDynaset)\r\n    Do While Not rst.EOF\r\n        strKlassenname = KlassennameErmitteln(rst!Name)\r\n        dbAddIn.Execute &quot;INSERT INTO tblTabellenAbfragen(TabelleAbfrageName, Datenbank, Klassenname) &quot; _\r\n            &amp; &quot;VALUES(''&quot; &amp; rst!Name &amp; &quot;'', ''&quot; &amp; CurrentProject.Name &amp; &quot;'', ''&quot; &amp; strKlassenname &amp; &quot;'')&quot;, _\r\n        dbFailOnError\r\n        rst.MoveNext\r\n    Loop\r\n    Me.Requery\r\n    Me!cboTabelleAbfrage.Requery\r\n    Set dbHost = Nothing\r\n    Set dbAddIn = Nothing\r\nEnd Sub<\/pre>\n<p>Mit diesen beiden Verweisen ausgestattet &ouml;ffnet die Prozedur eine Datensatzgruppe auf Basis der Tabelle <b>MSysObjects <\/b>der Zieldatenbank. Die Datensatzgruppe liefert das Feld <b>Name <\/b>aller Datens&auml;tze zur&uuml;ck, deren Feld <b>Type <\/b>den Wert <b>1<\/b>, <b>4<\/b>, <b>5 <\/b>oder <b>6 <\/b>enth&auml;lt und deren Name nicht mit <b>~ <\/b>beginnt (dies sind Abfragen, die als Wert der Eigenschaften <b>Datenherkunft <\/b>beziehungsweise <b>Datensatzherkunft <\/b>gespeichert, aber nicht im Datenbankfenster oder Navigationsbereich angezeigt werden). Der Wert <b>1 <\/b>f&uuml;r das Feld <b>Type <\/b>gibt an, dass es sich um eine eingebaute Tabelle handelt. <b>4 <\/b>kennzeichnet eine per ODBC verkn&uuml;pfte Tabelle, <b>5 <\/b>eine Abfrage und <b>6 <\/b>eine per Jet verkn&uuml;pfte Tabelle &#8211; also beispielsweise eine externe Excel- oder Access-Tabelle oder Textdatei.<\/p>\n<p>In einer <b>Do While<\/b>-Schleife &uuml;ber diese Datens&auml;tze tr&auml;gt die Prozedur f&uuml;r jede Tabelle oder Abfrage einen Datensatz in die Tabelle <b>tblTabellenAbfragen <\/b>ein. Dazu ermittelt diese mit der Funktion <b>KlassennameErmitteln <\/b>den Namen der zu erzeugenden Klasse &#8211; mehr dazu weiter unten. Eine <b>INSERT INTO<\/b>-Anweisung f&uuml;llt die Felder <b>TabelleAbfrageName<\/b>, <b>Datenbank <\/b>und <b>Klassenname <\/b>mit den ermittelten Werten. Anschlie&szlig;end aktualisiert die Prozedur die Datenherkunft des Formulars und des Kombinationsfeldes.<\/p>\n<p><b>Felder der gew&auml;hlten Datenherkunft anzeigen<\/b><\/p>\n<p>Ein Unterformular namens <b>sfmKlassengenerator <\/b>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&auml;chst ein Unterformular namens <b>sfmKlassengenerator<\/b>. Weisen Sie seiner Eigenschaft <b>Datenherkunft <\/b>die Tabelle <b>tblFelder <\/b>zu. Ziehen Sie die drei Felder <b>Feldname<\/b>, <b>Eigenschaftsname <\/b>und <b>Erzeugen <\/b>in den Detailbereich des Formularentwurfs und stellen Sie die Eigenschaft <b>Standardansicht <\/b>des Formulars auf <b>Datenblatt <\/b>ein (s. Bild 7).<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_01\/Klassengenerator-web-images\/pic006.png\" alt=\"pic006.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 7: Unterformular zur Anzeige der Felder der Tabelle oder Abfrage<\/span><\/b><\/p>\n<p>Speichern Sie das Formular, &ouml;ffnen Sie das Hauptformular <b>frmKlassengenerator <\/b>in der Entwurfsansicht und ziehen Sie das Unterformular <b>sfmKlassengenerator <\/b>aus dem Datenbankfenster beziehungsweise dem Navigationsbereich in den Detailbereich des Hauptformulars. Das Ergebnis sieht nun etwa wie in Bild 8 aus. Nun sorgen Sie daf&uuml;r, dass nach der Auswahl einer Tabelle oder Abfrage durch den Benutzer die entsprechenden Felder im Unterformular angezeigt werden. Dazu m&uuml;ssen diese zun&auml;chst einmal in die Tabelle <b>tblFelder <\/b>eingetragen werden &#8211; dies ist bislang noch nicht geschehen.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_01\/Klassengenerator-web-images\/pic007.png\" alt=\"pic007.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 8: Hauptformular mit integriertem Unterformular in der Entwurfsansicht<\/span><\/b><\/p>\n<p>Dazu f&uuml;gen Sie f&uuml;r das Kombinationsfeld <b>cboTabelleAbfrage <\/b>eine neue Ereignisprozedur f&uuml;r das Ereignis <b>Nach Aktualisierung <\/b>hinzu (s. <span class=\"verweis-ohneumbruch\"><a href=\"#anker-66-anchor\">Listing 3<\/a><\/span>). Diese Prozedur verwendet wiederum zwei Objektvariablen des Typs <b>Database<\/b> &#8211; eines f&uuml;r die Add-In-Datenbank und eines f&uuml;r die aufrufende Datenbank. Die Prozedur pr&uuml;ft zun&auml;chst, ob der Benutzer &uuml;berhaupt einen Eintrag im Kombinationsfeld <b>cboTabelleAbfrage <\/b>ausgew&auml;hlt hat.<\/p>\n<p class=\"listingueberschrift\">Listing 3: F&uuml;llen der Tabelle tblFelder<\/p>\n<pre>Private Sub cboTabelleAbfrage_AfterUpdate()\r\n    Dim dbHost As DAO.Database\r\n    Dim dbAddIn As DAO.Database\r\n    Dim rst As DAO.Recordset\r\n    Dim fld As DAO.Field\r\n    Dim bolEinlesen As Boolean\r\n    If Not IsNull(Me!cboTabelleAbfrage) Then\r\n        bolEinlesen = True\r\n        If Not IsNull(FLookup(&quot;FeldID&quot;, &quot;tblFelder&quot;, &quot;TabelleAbfrageID = &quot; &amp; Me!cboTabelleAbfrage)) Then\r\n            bolEinlesen = _\r\n                MsgBox(&quot;Felder neu einlesen und vorhandene Daten &uuml;berschreiben&quot;, vbYesNo) = vbYes\r\n        End If\r\n        If bolEinlesen Then\r\n            Set dbHost = CurrentDb\r\n            Set dbAddIn = CodeDb\r\n            dbAddIn.Execute &quot;DELETE FROM tblFelder WHERE TabelleAbfrageID = &quot; _\r\n                &amp; Me!cboTabelleAbfrage, dbFailOnError\r\n            Set rst = dbHost.OpenRecordset(&quot;SELECT * FROM &quot; &amp; Me!cboTabelleAbfrage.Column(1) _\r\n                &amp; &quot; WHERE 1=2&quot;, dbOpenDynaset)\r\n            For Each fld In rst.Fields\r\n                dbAddIn.Execute &quot;INSERT INTO tblFelder(Feldname, Eigenschaftsname, &quot; _\r\n                    &quot;TabelleAbfrageID, Erzeugen, Datentyp) VALUES(''&quot; &amp; fld.Name &amp; &quot;'', ''&quot; _\r\n                    &amp; fld.Name &amp; &quot;'', &quot; &amp; Me!cboTabelleAbfrage &amp; &quot;, -1, &quot; &amp; fld.Type &amp; &quot;)&quot;, _\r\n                dbFailOnError\r\n            Next fld\r\n        End If\r\n        Me!sfmKlassengenerator.Form.Requery\r\n        Me.Filter = &quot;TabelleAbfrageID = &quot; &amp; Me!cboTabelleAbfrage\r\n        Me.FilterOn = True\r\n    End If\r\nEnd Sub<\/pre>\n<p><!--30percent--><\/p>\n<p>Falls ja, pr&uuml;ft eine weitere Bedingung, ob die Tabelle <b>tblFelder <\/b>bereits mindestens einen Datensatz enth&auml;lt, der mit der ausgew&auml;hlten Tabelle\/Abfrage verkn&uuml;pft ist. Falls ja, fragt die Prozedur den Benutzer, ob die Felder neu eingelesen und somit die gegebenenfalls bereits angepassten Eigenschaftsnamen und die Werte des Feldes <b>Erzeugen <\/b>zur&uuml;ckgesetzt werden sollen. Wenn der Benutzer hier auf <b>Nein <\/b>klickt, aktualisiert die Prozedur nur die Anzeige der Felder der gew&auml;hlten Datenherkunft. Man k&ouml;nnte hier noch weiter ins Detail gehen und pr&uuml;fen, ob sich die Anzahl oder die Eigenschaften der Felder ge&auml;ndert haben, aber das w&uuml;rde den Rahmen des Beitrags sprengen.<\/p>\n<p>Hat der Benutzer jedoch auf <b>Ja <\/b>geklickt oder sind noch keine Daten f&uuml;r diese Tabelle\/Abfrage vorhanden, f&uuml;llt die Prozedur die Variablen <b>dbHost <\/b>und <b>dbAddIn <\/b>mit den entsprechenden Verweisen und f&uuml;hrt eine Aktionsabfrage aus, die alle Eintr&auml;ge der Tabelle <b>tblFelder <\/b>zur aktuellen Tabelle oder Abfrage l&ouml;scht.<\/p>\n<p>Danach erstellt die Prozedur ein neues Recordset-Objekt auf Basis der mit <b>cboTabelleAbfrage <\/b>ausgew&auml;hlten Tabelle oder Abfrage. Da wir nur die Felder ermitteln m&ouml;chten, ben&ouml;tigen wir keine Daten &#8211; dementsprechend wird als Kriterium der Ausdruck <b>1=2 <\/b>eingestellt, der daf&uuml;r sorgt, dass die Datensatzgruppe keine Daten enth&auml;lt.<\/p>\n<p>Nun durchl&auml;uft die Prozedur alle <b>Field<\/b>-Elemente der <b>Fields<\/b>-Auflistung des <b>Recordset<\/b>-Objekts und tr&auml;gt diese mithilfe einer <b>INSERT INTO<\/b>-Aktionsabfrage in die Tabelle <b>tblFelder <\/b>ein. Dabei f&uuml;llt sie das Feld <b>Eigenschaftsname <\/b>ebenfalls mit dem Feldnamen und tr&auml;gt f&uuml;r das Feld <b>TabelleAbfrageID <\/b>die entsprechende ID des mit dem Kombinationsfeld <b>cboTabelleAbfrage <\/b>ausgew&auml;hlten Eintrags ein.<\/p>\n<p>Schlie&szlig;lich aktualisiert die Prozedur die im Unterformular <b>sfmKlassengenerator <\/b>angezeigten Daten. Damit dies funktioniert, m&uuml;ssen Sie das Unterformular etwas anpassen &#8211; genauer gesagt das Unterformular-Steuerelement. Damit das Unterformular nur solche Datens&auml;tze anzeigt, die zu dem im Steuerelement <b>cboTabelleAbfrage <\/b>ausgew&auml;hlten Eintrag passen, stellen Sie die Eigenschaften <b>Verkn&uuml;pfen von <\/b>und <b>Verkn&uuml;pfen nach <\/b>des Unterformulars wie in Bild 9 auf die Werte <b>TabelleAbfrageID <\/b>und <b>cboTabelleAbfrage <\/b>ein.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_01\/Klassengenerator-web-images\/pic008.png\" alt=\"pic008.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 9: Unterformular nach der ausgew&auml;hlten Tabelle oder Abfrage filtern<\/span><\/b><\/p>\n<p>Dadurch zeigt das Unterformular nur diejenigen Datens&auml;tze an, deren Fremdschl&uuml;sselfeld <b>TabelleAbfrageID <\/b>mit dem im Kombinationsfeld <b>cboTabelleAbfrage <\/b>ausgew&auml;hlten Wert &uuml;bereinstimmt (s. Bild 10). Hier kann der Benutzer nun ansetzen und einige Einstellungen vornehmen, die im weiteren Verlauf interessant werden. So kann er hier etwa die in der Klasse zu verwendenden Bezeichnungen f&uuml;r die Eigenschaften auf Basis der Feldnamen anpassen und mit dem <b>Ja\/Nein<\/b>-Feld <b>Erzeugen <\/b>grunds&auml;tzlich festlegen, ob ein Feld &uuml;berhaupt verwendet werden soll.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_01\/Klassengenerator-web-images\/pic009.png\" alt=\"pic009.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 10: Anzeige der Felder der gew&auml;hlten Datenherkunft<\/span><\/b><\/p>\n<p><b>Einstellungen f&uuml;r die Erzeugung der Klasse<\/b><\/p>\n<p>Ein Element einer Klasse f&uuml;r eine Tabelle oder Abfrage besteht aus drei Teilen: der Deklaration der privaten Variablen zum Speichern des Feldwertes, der <b>Public Property Set\/Let<\/b>-Prozedur zum Einstellen des Eigenschaftswertes und der <b>Public Property Let<\/b>-Prozedur zum Auslesen des Eigenschaftswertes (siehe <b>clsPerson<\/b>):<\/p>\n<pre>Dim m_Vorname As String\r\nPublic Property Let Vorname(strVorname As String)\r\n    m_Vorname = strVorname\r\nEnd Property\r\nPublic Property Get Vorname() As String\r\n    Vorname = m_Vorname\r\nEnd Property<\/pre>\n<p>Die Verwendung dieser Klasse sieht etwa wie folgt aus:<\/p>\n<pre>Public Sub Test_Klasse()\r\n    Dim objPerson As clsPerson\r\n    Set objPerson = New clsPerson\r\n    With objPerson\r\n        .Vorname = &quot;Andr&eacute;&quot;\r\n        Debug.Print .Vorname\r\n    End With\r\n    Set objPerson = Nothing\r\nEnd Sub<\/pre>\n<p>Die meisten hier verwendeten Informationen lassen sich beim Einlesen der Eigenschaften der Tabelle und der enthaltenen Felder ermitteln. Einige sollen jedoch gleich automatisch angepasst werden, andere erst beim Zusammenstellen des Codes der Klasse.<\/p>\n<p>Der Klassenname etwa wird aus dem Tabellen- oder Abfragenamen abgeleitet. Dort soll das Pr&auml;fix (etwa <b>tbl <\/b>oder <b>qry<\/b>) durch das Pr&auml;fix <b>cls <\/b>ersetzt werden. Und die Member-Variablen (wie <b>m_Vorname<\/b>) werden aus den Feldnamen abgeleitet und um ein Pr&auml;fix wie <b>m_ <\/b>erweitert. Wo aber legt der Benutzer diese Informationen fest Theoretisch k&ouml;nnte man es sich leicht machen und diese Daten einfach im Code verankern. Allerdings sollten diese Einstellungen durchaus flexibel vorgenommen werden k&ouml;nnen, weshalb wir daf&uuml;r eine entsprechende Optionen-Tabelle einrichten, deren Werte der Benutzer nach Belieben einstellen kann.<\/p>\n<p>Diese Tabelle hei&szlig;t <b>tblOptionen <\/b>und sieht im Entwurf wie in Bild 11 aus. Die Felder haben die folgende Funktion:<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_01\/Klassengenerator-web-images\/pic010.png\" alt=\"pic010.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 11: Entwurf der Tabelle tblOptionen<\/span><\/b><\/p>\n<ul>\n<li class=\"aufz-hlung\"><b>Klassenpraefix<\/b>: Legt fest, welches Pr&auml;fix die zu erstellenden Klassen erhalten sollen.<\/li>\n<li class=\"aufz-hlung\"><b>Memberpraefix<\/b>: Legt das Pr&auml;fix der Membervariablen fest (zum Beispiel <b>m_<\/b>).<\/li>\n<li class=\"aufz-hlung\"><b>TabelleAbfragePraefixErsetzen<\/b>: Enth&auml;lt eine per Semikola getrennte Auflistung der Pr&auml;fixe, die aus Tabellen und Abfragen entfernt werden sollen.<\/li>\n<\/ul>\n<p>Das Formular zum Bearbeiten dieser Einstellungen hei&szlig;t <b>frmOptionen <\/b>und verwendet die Tabelle <b>tblOptionen <\/b>als Datenherkunft (s. Bild 12). Es enth&auml;lt die Felder der Datenherkunft sowie eine Schaltfl&auml;che namens <b>cmdOK<\/b>, die das Formular wieder schlie&szlig;t. Dazu verwendet es die folgende Ereignisprozedur:<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_01\/Klassengenerator-web-images\/pic011.png\" alt=\"pic011.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 12: Das Formular frmOptionen zum Bearbeiten der Optionen<\/span><\/b><\/p>\n<pre>Private Sub cmdOK_Click()\r\n    DoCmd.Close acForm, Me.Name\r\nEnd Sub<\/pre>\n<p>Die Eigenschaften <b>Navigationsschaltfl&auml;chen<\/b>, <b>Datensatzmarkierer<\/b>, <b>Trennlinien <\/b>und <b>Bildlaufleisten <\/b>dieses Formulars stellen Sie auf <b>Nein<\/b>, die Eigenschaft <b>Automatisch zentrieren <\/b>auf <b>Ja <\/b>ein. Das Optionen-Formular rufen Sie mit einer Schaltfl&auml;che im Formular <b>frmKlassengenerator <\/b>auf (s. Bild 13). Diese l&ouml;st die folgende Prozedur aus:<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_01\/Klassengenerator-web-images\/pic012.png\" alt=\"pic012.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 13: Aufruf des Optionen-Formulars<\/span><\/b><\/p>\n<pre>Private Sub cmdOptionen_Click()\r\n    DoCmd.OpenForm &quot;frmOptionen&quot;, _\r\n        WindowMode:=acDialog\r\nEnd Sub<\/pre>\n<p>Wo kommen die in dieser Tabelle gespeicherten Optionen nun zum Einsatz Einen Fall haben Sie bereits kennengelernt. Wenn die Tabellen der Datenbank neu eingelesen werden, ruft die Prozedur <b>TabellenAbfragenEinlesen <\/b>die Funktion <b>KlassennameErmitteln <\/b>auf und &uuml;bergibt dieser den Namen der <b>Tabelle\/Abfrage<\/b>, f&uuml;r die ein Klassenname generiert werden soll. Aus <b>tblPersonen <\/b>soll so etwa <b>clsPersonen <\/b>werden.<\/p>\n<p>Diese Funktion finden Sie in <span class=\"verweis-ohneumbruch\"><a href=\"#anker-79-anchor\">Listing 4<\/a><\/span>. Sie liest zun&auml;chst die Liste der semikola-separierten und zu ersetzenden Pr&auml;fixe aus dem Feld <b>TabelleAbfragePraefixErsetzen <\/b>der Tabelle <b>tblOptionen <\/b>ein. Diese wird per <b>Split<\/b>-Funktion direkt in ein Array umgewandelt und in der Variablen <b>strPraefixe() <\/b>gespeichert.<\/p>\n<p class=\"listingueberschrift\">Listing 4: Ermitteln eines Klassennamens auf Basis des Namens der Tabelle\/Abfrage<\/p>\n<pre>Private Function KlassennameErmitteln(strDatenherkunft As String)\r\n    Dim strKlassenname As String\r\n    Dim strPraefixe() As String\r\n    Dim strPraefix As String\r\n    Dim i As Integer\r\n    strPraefixe = Split(FLookup(&quot;TabelleAbfragePraefixErsetzen&quot;, &quot;tblOptionen&quot;), &quot;;&quot;)\r\n    strKlassenname = strDatenherkunft\r\n    For i = LBound(strPraefixe) To UBound(strPraefixe)\r\n        strKlassenname = Replace(strKlassenname, strPraefixe(i), &quot;&quot;, 1, 1)\r\n    Next i\r\n    strPraefix = FLookup(&quot;Klassenpraefix&quot;, &quot;tblOptionen&quot;)\r\n    strKlassenname = strPraefix &amp; strKlassenname\r\n    KlassennameErmitteln = strKlassenname\r\nEnd Function<\/pre>\n<p>In einer <b>For&#8230;Next<\/b>-Schleife &uuml;ber alle Elemente dieses Arrays ersetzt die Prozedur alle vorkommenden Pr&auml;fixe durch eine leere Zeichenkette. Aus <b>tblPersonen <\/b>wird so zun&auml;chst <b>Personen<\/b>. Anschlie&szlig;end liest die Prozedur das Pr&auml;fix f&uuml;r Klassennamen aus dem Feld <b>Klassenpraefix <\/b>der Tabelle <b>tblOptionen <\/b>ein und f&uuml;gt dieses vorn an den Klassennamen an. Das Ergebnis wird als Funktionswert zur&uuml;ckgegeben.<\/p>\n<p><b>Klassen generieren<\/b><\/p>\n<p>Ein Klick auf die Schaltfl&auml;che <b>cmdKlasseGenerieren <\/b>soll den Klassencode zusammenstellen und im Textfeld <b>txtKlassencode <\/b>darstellen. Dieses Textfeld erfordert einige spezielle Einstellungen. Als Erstes legen Sie f&uuml;r die Eigenschaft <b>Schriftart <\/b>den Wert <b>Courier New<\/b> und <b>Schriftgrad <\/b>auf den Wert <b>8 <\/b>oder <b>9 <\/b>fest. Die Eigenschaft <b>Bildlaufleisten <\/b>erh&auml;lt den Wert <b>Vertikal<\/b>. Das Textfeld soll seinen Inhalt dann etwa wie in Bild 14 anzeigen.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_01\/Klassengenerator-web-images\/pic013.png\" alt=\"pic013.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 14: Das Formular frmKlassengenerator mit frisch erzeugtem Code<\/span><\/b><\/p>\n<p>Was geschieht nun nach einem Mausklick auf die Schaltfl&auml;che <b>cmdErzeugen<\/b> Dies l&ouml;st die Prozedur aus <span class=\"verweis-ohneumbruch\"><a href=\"#anker-83-anchor\">Listing 5<\/a><\/span> aus. Die Prozedur stellt nach und nach den kompletten Code der Klasse zusammen. Die Zwischenergebnisse speichert die Prozedur dabei in verschiedenen Variablen. Den Beginn macht die Variable <b>strKopf<\/b>, welche die beiden Kopfzeilen aufnimmt:<\/p>\n<p class=\"listingueberschrift\">Listing 5: Prozedur zum Zusammenstellen des Codes der Klasse auf Basis einer Tabelle oder Abfrage<\/p>\n<pre>Private Sub cmdErzeugen_Click()\r\n    Dim strKlasse As String\r\n    Dim strKopf As String\r\n    Dim dbAddIn As DAO.Database\r\n    Dim rstTabelle As DAO.Recordset\r\n    Dim rstFelder As DAO.Recordset\r\n    Dim strMembervariablen As String\r\n    Dim strMemberpraefix As String\r\n    Dim strEigenschaftsname As String\r\n    Dim strDatentyp As String\r\n    Dim strProperty As String\r\n    Dim strPraefixDatentyp As String\r\n    Dim strLetSet As String\r\n    Dim bolObjekt As Boolean\r\n    strKopf = strKopf &amp; &quot;Option Explicit&quot; &amp; vbCrLf\r\n    strKopf = strKopf &amp; &quot;Option Compare Database&quot; &amp; vbCrLf\r\n    strMemberpraefix = FLookup(&quot;Memberpraefix&quot;, &quot;tblOptionen&quot;)\r\n    Set dbAddIn = CodeDb\r\n    Set rstTabelle = dbAddIn.OpenRecordset(&quot;SELECT * FROM tblTabellenAbfragen &quot; _\r\n        &amp; &quot;WHERE TabelleAbfrageID = &quot; &amp; Me!cboTabelleAbfrage, dbOpenDynaset)\r\n    Set rstFelder = dbAddIn.OpenRecordset(&quot;SELECT * FROM tblFelder WHERE TabelleAbfrageID = &quot; _\r\n        &amp; Me!cboTabelleAbfrage &amp; &quot; AND Erzeugen = -1&quot;, dbOpenDynaset)\r\n    Do While Not rstFelder.EOF\r\n        DatentypErmitteln rstFelder!Datentyp, strPraefixDatentyp, strDatentyp, bolObjekt\r\n        If bolObjekt Then\r\n            strLetSet = &quot;Set&quot;\r\n        Else\r\n            strLetSet = &quot;Let&quot;\r\n        End If\r\n        strEigenschaftsname = rstFelder!Eigenschaftsname\r\n        strMembervariablen = strMembervariablen &amp; &quot;Dim &quot; &amp; strMemberpraefix &amp; rstFelder!Feldname _\r\n            &amp; &quot; As &quot; &amp; strDatentyp &amp; vbCrLf\r\n        strProperty = strProperty &amp; &quot;Public Property Get &quot; &amp; strEigenschaftsname &amp; &quot; As &quot; _\r\n            &amp; strDatentyp &amp; vbCrLf\r\n        strProperty = strProperty &amp; &quot; &quot; &amp; strEigenschaftsname &amp; &quot; = &quot; &amp; strMemberpraefix _\r\n            &amp; strEigenschaftsname &amp; vbCrLf\r\n        strProperty = strProperty &amp; &quot;End Property&quot; &amp; vbCrLf &amp; vbCrLf\r\n        strProperty = strProperty &amp; &quot;Public Property &quot; &amp; strLetSet &amp; &quot; &quot; &amp; strEigenschaftsname _\r\n            &amp; &quot;(&quot; &amp; strPraefixDatentyp &amp; strEigenschaftsname &amp; &quot; As &quot; &amp; strDatentyp &amp; &quot;)&quot; &amp; vbCrLf\r\n        strProperty = strProperty &amp; &quot; &quot; &amp; strMemberpraefix &amp; strEigenschaftsname &amp; &quot; = &quot; _\r\n            &amp; strPraefixDatentyp &amp; strEigenschaftsname &amp; vbCrLf\r\n        strProperty = strProperty &amp; &quot;End Property&quot; &amp; vbCrLf &amp; vbCrLf\r\n        rstFelder.MoveNext\r\n    Loop\r\n    strKlasse = strKlasse &amp; strKopf &amp; vbCrLf\r\n    strKlasse = strKlasse &amp; strMembervariablen &amp; vbCrLf\r\n    strKlasse = strKlasse &amp; strProperty\r\n    Me!txtKlassencode = strKlasse\r\nEnd Sub<\/pre>\n<p>Danach folgen einige Vorbereitungen. So ermittelt die Prozedur per FLookup das Pr&auml;fix f&uuml;r die Membervariablen (zum Beispiel <b>m_<\/b>) und speichert es in der Variablen <b>strMemberpraefix<\/b>. Dann erstellt es drei Objekte. <b>dbAddIn<\/b> referenziert die aktuelle Datenbank. <b>rstTabelleAbfrage <\/b>liefert den Datensatz der Tabelle <b>tblTabelleAbfrage<\/b>, zu dem die Prozedur den Klassencode erzeugen soll, und <b>rstFelder <\/b>enth&auml;lt ein Recordset mit allen Datens&auml;tzen der Tabelle <b>tblFelder<\/b>, die zur ausgew&auml;hlten Tabelle geh&ouml;ren.<\/p>\n<p>Eine <b>Do While<\/b>-Schleife durchl&auml;uft alle Datens&auml;tze der Datensatzgruppe <b>rstFelder<\/b>. Darin ruft die Prozedur die Routine <b>DatentypErmitteln <\/b>auf, die mit dem Datentyp f&uuml;r das aktuelle Feld gef&uuml;ttert wird und das Pr&auml;fix f&uuml;r diesen Datentyp und die Bezeichnung des Datentyps zur&uuml;ckliefert sowie einen Boolean-Wert, der angibt, ob es sich um einen Objektdatentyp handelt.<\/p>\n<p>Letztere Information landet in der Variablen <b>bolObjekt<\/b>. Ist diese <b>True<\/b>, wird zum &Uuml;bergeben eines Wertes f&uuml;r die entsprechende Eigenschaft eine Zeile wie <\/p>\n<pre>Public Property Let NichtObjekt(lngNichtObjekt As Long)<\/pre>\n<p>verwendet, sonst eine solche:<\/p>\n<pre>Public Property Set Objekt(objObjekt As Object)<\/pre>\n<p>Der Unterschied liegt in der Verwendung des Schl&uuml;sselworts <b>Let <\/b>oder <b>Set<\/b>. Dieses Schl&uuml;sselwort wird je nach dem Wert von <b>bolObjekt <\/b>in der Variablen <b>strLetSet <\/b>gespeichert (also <b>Let <\/b>oder <b>Set<\/b>).<\/p>\n<p>Das Recordset <b>rstFelder <\/b>liefert mit dem Feld <b>Eigenschaftsname <\/b>den in der Klasse zu verwendenden Namen f&uuml;r die Eigenschaft. Diesen speichert die Prozedur in der Variablen <b>strEigenschaftsname<\/b>.<\/p>\n<p>Danach setzt die Prozedur in einer Variablen namens <b>strMembervariablen<\/b> die Liste der Variablendeklarationen zusammen. Ein Element sieht etwa so aus:<\/p>\n<pre>Dim m_AbonnementID As Long<\/pre>\n<p>Die Variable <b>strMembervariablen <\/b>nimmt alle Variablendeklarationen auf &#8211; getrennt jeweils durch einen Zeilenumbruch (<b>vbCrLf<\/b>).<\/p>\n<p>Die Variable <b>strProperty <\/b>nimmt die <b>Get<\/b>&#8211; beziehungsweise die <b>Let\/Set<\/b>-Property-Prozeduren auf.<\/p>\n<p>Die erste Zeile der <b>Get<\/b>-Prozedur setzt sich beispielsweise aus den Schl&uuml;sselw&ouml;rtern <b>Public Property Get<\/b>, dem Eigenschaftsnamen aus <b>strEigenschaftsname<\/b>, dem Schl&uuml;sselwort <b>As <\/b>und dem Datentyp (aus <b>strDatentyp<\/b>) zusammen. Die &uuml;brigen Zeilen werden auf &auml;hnliche Weise zusammengestellt.<\/p>\n<p>Nach dem Durchlaufen der <b>Do While<\/b>-Schleife f&uuml;r alle Datens&auml;tze setzt die Prozedur noch die einzelnen Elemente, also <b>strKopf<\/b>, <b>strMembervariablen <\/b>und <b>strProperty <\/b>zusammen und tr&auml;gt das Ergebnis in das Textfeld <b>txtKlassencode <\/b>ein.<\/p>\n<p><b>Datentypabh&auml;ngige Elemente ermitteln<\/b><\/p>\n<p>Weiter oben haben wir bereits die Prozedur <b>DatentypErmitteln<\/b> erw&auml;hnt, die vier Parameter verwendet. Dabei erwartet der Eingangsparameter <b>intDatentyp <\/b>eine Zahl, die den Datentyp des Tabellenfeldes repr&auml;sentiert.<\/p>\n<p>Auf Basis dieses Wertes soll die Prozedur die drei R&uuml;ckgabeparameter <b>strPraefixDatentyp<\/b>, <b>strDatentyp <\/b>und <b>bolObjekt <\/b>f&uuml;llen.<\/p>\n<p>Die Prozedur sieht (in verk&uuml;rzter Form) wie in <span class=\"verweis-ohneumbruch\"><a href=\"#anker-87-anchor\">Listing 6<\/a><\/span> aus. Sie enth&auml;lt eine einfache <b>Select Case<\/b>-Bedingung, die abh&auml;ngig vom Wert von <b>intDatentyp <\/b>verzweigt und die R&uuml;ckgabeparameter mit den entsprechenden Werten f&uuml;llt.<\/p>\n<p class=\"listingueberschrift\">Listing 6: Ermitteln von Elementen abh&auml;ngig vom Datentyp<\/p>\n<pre>Private Sub DatentypErmitteln(intDatentyp As Integer, strPraefixDatentyp As String, _\r\n        strDatentyp As String, bolObjekt As Boolean)\r\n    Select Case intDatentyp\r\n        Case dbBinary, dbLongBinary\r\n            strDatentyp = &quot;Object&quot;\r\n            strPraefixDatentyp = &quot;obj&quot;\r\n            bolObjekt = True\r\n        Case dbBoolean\r\n            strDatentyp = &quot;Boolean&quot;\r\n            strPraefixDatentyp = &quot;bol&quot;\r\n        Case dbByte\r\n            strDatentyp = &quot;Byte&quot;\r\n            strPraefixDatentyp = &quot;byt&quot;\r\n        Case ... weitere Datentypel\r\n        Case Else ''dbTimeStamp, dbFloat, dbNumeric, dbBigInt, dbVarBinary, dbLongBinary\r\n            MsgBox &quot;Noch nicht implementierter Datentyp: &quot; &amp; intDatentyp\r\n    End Select\r\nEnd Sub<\/pre>\n<p><b>Prozedur zum Erzeugen einer Klasse <\/b><\/p>\n<p>Wenn man schon eine Klasse zum Speichern der Daten eines Datensatzes einer Tabelle oder Abfrage erstellt, m&ouml;chte man diese im Praxiseinsatz gegebenenfalls auch schnell mit den Daten aus der entsprechenden Datenherkunft f&uuml;llen. Die dazu ben&ouml;tigten Codezeilen lassen sich ebenfalls leicht automatisiert zusammenstellen.<\/p>\n<p>Der resultierende Code sollte beispielsweise wie in <span class=\"verweis-ohneumbruch\"><a href=\"#anker-90-anchor\">Listing 7<\/a><\/span> aussehen.<\/p>\n<p class=\"listingueberschrift\">Listing 7: Prozedur zum Erzeugen eines Objekts mit den Daten eines Kundendatensatzes<\/p>\n<pre>Public Function ErzeugeKunden(lngID As Long) As clsKunden\r\n    Dim db As DAO.Database\r\n    Dim rst As DAO.Recordset\r\n    Dim objKunden As clsKunden\r\n    Set db = CurrentDb\r\n    Set rst = db.OpenRecordset(&quot;SELECT * FROM tblKunden WHERE = &quot; &amp; lngID, dbOpenDynaset)\r\n    Set objKunden = New clsKunden\r\n    objKunden.KundeID = rst!KundeID\r\n    objKunden.Kundenbezeichnung = rst!Kundenbezeichnung\r\n    objKunden.AnredeID = rst!AnredeID\r\n    objKunden.Vorname = rst!Vorname\r\n    objKunden.Nachname = rst!Nachname\r\n    objKunden.Firma = rst!Firma\r\n    objKunden.Strasse = rst!Strasse\r\n    objKunden.PLZ = rst!PLZ\r\n    objKunden.Ort = rst!Ort\r\n    objKunden.Land = rst!Land\r\n    objKunden.EMail = rst!EMail\r\n    Set ErzeugeKunden = objKunden\r\n    Set db = Nothing\r\nEnd Function<\/pre>\n<p>Das Aufrufen der Prozedur und die Nutzung des zur&uuml;ckgelieferten Objekts erfordert dann nur noch wenige Zeilen:<\/p>\n<pre>Public Sub TestKundenklasse()\r\n    Dim objKunde As clsKunden\r\n    Set objKunde = ErzeugeKunden(71)\r\n    With objKunde\r\n        Debug.Print .EMail\r\n    End With\r\nEnd Sub<\/pre>\n<p>In diesem Beispiel erzeugt <b>ErzeugeKunden <\/b>ein neues Objekt auf Basis der Klasse <b>clsKunden<\/b>, f&uuml;llt seine Eigenschaften mit den Daten des Datensatzes mit dem Wert <b>71 <\/b>im Feld <b>KundeID <\/b>und gibt testweise die E-Mail-Adresse f&uuml;r diesen Kunden aus.<\/p>\n<p>Die Prozedur, welche Routinen wie etwa <b>ErzeugeKunden <\/b>zusammenstellt, sieht wie in <span class=\"verweis-ohneumbruch\"><a href=\"#anker-88-anchor\">Listing 8<\/a><\/span> aus. Die Prozedur ist &auml;hnlich aufgebaut wie die zum Erstellen des Klassenmoduls selbst, auf dessen Basis das Objekt erzeugt werden soll.<\/p>\n<p class=\"listingueberschrift\">Listing 8: Diese Prozedur erstellt eine Routine, die ein Objekt auf Basis einer Klasse erstellt und es mit den Daten eines Datensatzes der zugrunde liegenden Tabelle f&uuml;llt.<\/p>\n<pre>Private Function LadeprozedurErstellen() As String\r\n    Dim strKlassenname As String\r\n    Dim dbAddIn As DAO.Database\r\n    Dim rstTabelle As DAO.Recordset\r\n    Dim rstFelder As DAO.Recordset\r\n    Dim strProzedur As String\r\n    Dim strKlassenpraefix As String\r\n    Dim strObjekt As String\r\n    Dim strPraefixDatentyp As String\r\n    Dim strDatentyp As String\r\n    Dim bolObjekt As Boolean\r\n    Dim strEigenschaftsname As String\r\n    Dim strFeldname As String\r\n    Dim strLetSet As String\r\n    Set dbAddIn = CodeDb\r\n    Set rstTabelle = dbAddIn.OpenRecordset(&quot;SELECT * FROM tblTabellenAbfragen &quot; _\r\n        &amp; &quot;WHERE TabelleAbfrageID = &quot; &amp; Me!cboTabelleAbfrage, dbOpenDynaset)\r\n    Set rstFelder = dbAddIn.OpenRecordset(&quot;SELECT * FROM tblFelder WHERE TabelleAbfrageID = &quot; _\r\n        &amp; Me!cboTabelleAbfrage &amp; &quot; AND Erzeugen = -1&quot;, dbOpenDynaset)\r\n    strKlassenname = rstTabelle!Klassenname\r\n    strKlassenpraefix = FLookup(&quot;Klassenpraefix&quot;, &quot;tblOptionen&quot;)\r\n    strObjekt = Replace(strKlassenname, strKlassenpraefix, &quot;&quot;)\r\n    strProzedur = strProzedur &amp; &quot;Public Function Erzeuge&quot; &amp; strObjekt &amp; &quot;(lngID As Long) As &quot; _\r\n        &amp; strKlassenname &amp; vbCrLf\r\n    strProzedur = strProzedur &amp; &quot; Dim db As DAO.Database&quot; &amp; vbCrLf\r\n    strProzedur = strProzedur &amp; &quot; Dim rst as DAO.Recordset&quot; &amp; vbCrLf\r\n    strProzedur = strProzedur &amp; &quot; Dim obj&quot; &amp; strObjekt &amp; &quot; As &quot; &amp; strKlassenname &amp; vbCrLf\r\n    strProzedur = strProzedur &amp; &quot; Set db = CurrentDb&quot; &amp; vbCrLf\r\n    strProzedur = strProzedur &amp; &quot; Set rst = db.OpenRecordset(&quot;&quot;SELECT * FROM &quot; _\r\n        &amp; rstTabelle!TabelleAbfrageName &amp; &quot; WHERE &quot; &amp; rstTabelle!Primaerschluesselfeld &amp; &quot; = &quot;&quot; _\r\n        &amp; lngID, dbOpenDynaset)&quot; &amp; vbCrLf\r\n    strProzedur = strProzedur &amp; &quot; Set obj&quot; &amp; strObjekt &amp; &quot; = New &quot; &amp; strKlassenname &amp; vbCrLf\r\n    Do While Not rstFelder.EOF\r\n        DatentypErmitteln rstFelder!Datentyp, strPraefixDatentyp, strDatentyp, bolObjekt\r\n        strEigenschaftsname = rstFelder!Eigenschaftsname\r\n        strFeldname = rstFelder!Feldname\r\n        If bolObjekt Then\r\n            strLetSet = &quot;Set &quot;\r\n        End If\r\n        strProzedur = strProzedur &amp; &quot; &quot; &amp; strLetSet &amp; &quot;obj&quot; &amp; strObjekt &amp; &quot;.&quot; _\r\n            &amp; strEigenschaftsname &amp; &quot; = rst!&quot; &amp; strFeldname &amp; vbCrLf\r\n        rstFelder.MoveNext\r\n    Loop\r\n    strProzedur = strProzedur &amp; &quot; Set Erzeuge&quot; &amp; strObjekt &amp; &quot; = obj&quot; &amp; strObjekt &amp; vbCrLf\r\n    strProzedur = strProzedur &amp; &quot; Set db = Nothing&quot; &amp; vbCrLf\r\n    strProzedur = strProzedur &amp; &quot;End Function&quot; &amp; vbCrLf\r\n    LadeprozedurErstellen = strProzedur\r\nEnd Function<\/pre>\n<p>Sie erzeugt zun&auml;chst ein <b>Database<\/b>-Objekt f&uuml;r die Add-In-Datenbank und zwei <b>Recordset<\/b>-Objekte. Das erste enth&auml;lt wieder einen Verweis auf den Datensatz der Tabelle, f&uuml;r welche die Prozedur erstellt werden soll. Das zweite referenziert eine Datensatzgruppe aller Felder dieser Tabelle. Die Prozedur ermittelt wiederum den Klassennamen (hier <b>clsKunden<\/b>) und das Klassenpr&auml;fix (beispielsweise <b>cls<\/b>). In einer weiteren Variablen namens <b>strObjekt <\/b>speichert die Prozedur den Klassennamen ohne Pr&auml;fix (hier <b>Kunden<\/b>).<\/p>\n<p>Danach beginnt die Prozedur mit der Zusammenstellung des Codes der zu erstellenden Routine. Diese beginnt mit der Kopfzeile, die aus den Schl&uuml;sselw&ouml;rtern <b>Public Function<\/b>, dem Pr&auml;fix <b>Erzeuge <\/b>und dem Objektnamen (zusammen also etwa <b>ErzeugeKunden<\/b>), dem Parameter und dem Namen der zu liefernden Klasse (aus <b>strKlassenname<\/b>) besteht.<\/p>\n<p>Danach folgen die Zeilen zur Deklaration und Instanzierung des <b>Database<\/b>&#8211; und des <b>Recordset<\/b>-Objekts, mit denen die zu &uuml;bergebenden Daten ermittelt werden. Beim Recordset <b>rstFelder<\/b>, der alle Felder liefert, ist zu beachten, dass nur die Datens&auml;tze ber&uuml;cksichtigt werden, die zur betroffenen Tabelle geh&ouml;ren und die &uuml;ber das Boolean-Feld <b>Erzeugen <\/b>markiert wurden.<\/p>\n<p>Die Deklaration des zu erstellenden Objekts besteht aus <b>Dim obj<\/b>, dem Objektnamen (aus <b>strObjekt<\/b>), <b>As <\/b>und dem Klassennamen (aus <b>strKlassenname<\/b>), die Zeile zur Instanzierung wird auf &auml;hnliche Weise zusammengestellt.<\/p>\n<p>Danach folgen die Zeilen f&uuml;r die einzelnen Felder, also beispielsweise folgende:<\/p>\n<pre>objKunden.Vorname = rst!Vorname<\/pre>\n<p>Diese Zeilen stellt die Prozedur innerhalb einer <b>Do While<\/b>-Schleife &uuml;ber alle Datens&auml;tze des Recordsets <b>rstFelder <\/b>zusammen.<\/p>\n<p>Die Schleife ermittelt mit der Prozedur <b>DatentypErmitteln <\/b>(diese wurde bereits weiter oben vorgestellt) zun&auml;chst die Datentyp-Eigenschaften wie das Pr&auml;fix und den Namen des Datentyps, den Feldnamen und den Namen, der f&uuml;r das Feld als Eigenschaft der Klasse verwendet werden soll.<\/p>\n<p>Die eigentlichen Zuweisungszeilen entstehen aus dem Pr&auml;fix <b>obj<\/b>, dem reinen Objektnamen (etwa <b>Kunden<\/b>) und dem durch einen Punkt vom Objektnamen getrennten Eigenschaftsnamen (etwa <b>Vorname<\/b>) vor dem Gleichheitszeichen und dem Ausdruck <b>rst!<\/b> und dem Feldnamen rechts vom Gleichheitszeichen.<\/p>\n<p>Schlie&szlig;lich f&uuml;gt die Prozedur der Variablen <b>strProzedur<\/b> noch eine Zuweisungszeile wie die folgende hinzu:<\/p>\n<pre>Set ErzeugeKunden = objKunden<\/pre>\n<p>Damit ist die Prozedur komplett. Wie integrieren wir diese in das Formular Wir bringen dort ein Kontrollk&auml;stchen unter, mit dem Sie angeben k&ouml;nnen, ob auch eine Prozedur zum Erzeugen und F&uuml;llen der Klasse hinzugef&uuml;gt werden soll (s. Bild 15). F&uuml;gen Sie die folgenden drei Zeilen zur Prozedur <b>cmdErzeugen_Click <\/b>hinzu, damit die Prozedur <b>LadeprozedurErstellen <\/b>in Abh&auml;ngigkeit vom Wert des Kontrollk&auml;stchens ausgel&ouml;st wird:<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2013_01\/Klassengenerator-web-images\/pic014.png\" alt=\"pic014.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 15: Das Kontrollk&auml;stchen legt fest, ob eine Prozedur zum Erzeugen eines Objekts auf Basis der Klasse hinzugef&uuml;gt werden soll.<\/span><\/b><\/p>\n<pre>If Me!chkLadeprozedur Then\r\n    strKlasse = strKlasse &amp; LadeprozedurErstellen\r\nEnd If<\/pre>\n<p>Fertig. Wenn das Kontrollk&auml;stchen <b>chkLadeprozedur <\/b>aktiviert ist, erstellt ein Klick auf <b>Erzeugen <\/b>den Code der Klasse und zus&auml;tzlich eine Prozedur zum Instanzieren der Klasse und F&uuml;llen der Eigenschaften auf Basis der Felder eines Datensatzes der zugrunde liegenden Tabelle oder Abfrage.<\/p>\n<p><b>Zusammenfassung und Ausblick<\/b><\/p>\n<p>Auf die gleiche Weise k&ouml;nnen Sie noch eine Prozedur hinzuf&uuml;gen, die eine Routine zum Speichern der Eigenschaften einer neu erstellten oder bearbeiteten Instanz des Objekts des Klassenmoduls zusammenstellt.<\/p>\n<p>Die Beispieldatenbank enth&auml;lt noch die Einrichtungen, die daf&uuml;r n&ouml;tig sind, die Funktion als Add-In &uuml;ber das Add-In-Men&uuml; aufzurufen. Dies sind prim&auml;r die Tabelle <b>USysRegInfo <\/b>sowie die Funktion Autostart im Modul <b>mdlAddIn<\/b>.<\/p>\n<h3>Downloads zu diesem Beitrag<\/h3>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>aiuKlassengenerator.mda<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/{E46C13B8-D608-4339-BA13-FC5DFD009ECC}\/aiu_871.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Gelegentlich ist es sinnvoll, Daten eines Datensatzes aus einer Tabelle in einem Objekt auf Basis einer Klasse abzulegen &#8211; vor allem dann, wenn Sie nur auf einen kompakten Satz von Daten zugreifen m&ouml;chten und diese nicht &auml;ndern wollen. Leider ist der n&ouml;tige Code je nach Anzahl der Felder der Datenherkunft und somit der Eigenschaften recht umfangreich und die Erstellung eine m&uuml;hselige Arbeit. Mit dem in diesem Beitrag vorgestellten Add-In soll dies ganz schnell von der Hand gehen.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[66012013,662013,44000025],"tags":[],"class_list":["post-55000871","post","type-post","status-publish","format-standard","hentry","category-66012013","category-662013","category-VBA_und_Programmiertechniken"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Klassengenerator - Access im Unternehmen<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/access-im-unternehmen.de\/Klassengenerator\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Klassengenerator\" \/>\n<meta property=\"og:description\" content=\"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&ouml;chten und diese nicht &auml;ndern wollen. Leider ist der n&ouml;tige Code je nach Anzahl der Felder der Datenherkunft und somit der Eigenschaften recht umfangreich und die Erstellung eine m&uuml;hselige Arbeit. Mit dem in diesem Beitrag vorgestellten Add-In soll dies ganz schnell von der Hand gehen.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Klassengenerator\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2020-05-22T21:34:15+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg05.met.vgwort.de\/na\/fc20b5cf4a274becb4bb75ae4fd51aa9\" \/>\n<meta name=\"author\" content=\"Andr\u00e9 Minhorst\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andr\u00e9 Minhorst\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"28\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Klassengenerator\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Klassengenerator\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Klassengenerator\",\"datePublished\":\"2020-05-22T21:34:15+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Klassengenerator\\\/\"},\"wordCount\":4228,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Klassengenerator\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg05.met.vgwort.de\\\/na\\\/fc20b5cf4a274becb4bb75ae4fd51aa9\",\"articleSection\":[\"1\\\/2013\",\"2013\",\"VBA und Programmiertechniken\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Klassengenerator\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Klassengenerator\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Klassengenerator\\\/\",\"name\":\"Klassengenerator - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Klassengenerator\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Klassengenerator\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg05.met.vgwort.de\\\/na\\\/fc20b5cf4a274becb4bb75ae4fd51aa9\",\"datePublished\":\"2020-05-22T21:34:15+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Klassengenerator\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Klassengenerator\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Klassengenerator\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg05.met.vgwort.de\\\/na\\\/fc20b5cf4a274becb4bb75ae4fd51aa9\",\"contentUrl\":\"http:\\\/\\\/vg05.met.vgwort.de\\\/na\\\/fc20b5cf4a274becb4bb75ae4fd51aa9\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Klassengenerator\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Klassengenerator\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"name\":\"Access im Unternehmen\",\"description\":\"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access\",\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/access-im-unternehmen.de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\",\"name\":\"Andr\u00e9 Minhorst Verlag\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"contentUrl\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"width\":370,\"height\":111,\"caption\":\"Andr\u00e9 Minhorst Verlag\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\",\"name\":\"Andr\u00e9 Minhorst\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"caption\":\"Andr\u00e9 Minhorst\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Klassengenerator - Access im Unternehmen","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/access-im-unternehmen.de\/Klassengenerator\/","og_locale":"de_DE","og_type":"article","og_title":"Klassengenerator","og_description":"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&ouml;chten und diese nicht &auml;ndern wollen. Leider ist der n&ouml;tige Code je nach Anzahl der Felder der Datenherkunft und somit der Eigenschaften recht umfangreich und die Erstellung eine m&uuml;hselige Arbeit. Mit dem in diesem Beitrag vorgestellten Add-In soll dies ganz schnell von der Hand gehen.","og_url":"https:\/\/access-im-unternehmen.de\/Klassengenerator\/","og_site_name":"Access im Unternehmen","article_published_time":"2020-05-22T21:34:15+00:00","og_image":[{"url":"http:\/\/vg05.met.vgwort.de\/na\/fc20b5cf4a274becb4bb75ae4fd51aa9","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"28\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Klassengenerator\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Klassengenerator\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Klassengenerator","datePublished":"2020-05-22T21:34:15+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Klassengenerator\/"},"wordCount":4228,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Klassengenerator\/#primaryimage"},"thumbnailUrl":"http:\/\/vg05.met.vgwort.de\/na\/fc20b5cf4a274becb4bb75ae4fd51aa9","articleSection":["1\/2013","2013","VBA und Programmiertechniken"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Klassengenerator\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Klassengenerator\/","url":"https:\/\/access-im-unternehmen.de\/Klassengenerator\/","name":"Klassengenerator - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Klassengenerator\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Klassengenerator\/#primaryimage"},"thumbnailUrl":"http:\/\/vg05.met.vgwort.de\/na\/fc20b5cf4a274becb4bb75ae4fd51aa9","datePublished":"2020-05-22T21:34:15+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Klassengenerator\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Klassengenerator\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Klassengenerator\/#primaryimage","url":"http:\/\/vg05.met.vgwort.de\/na\/fc20b5cf4a274becb4bb75ae4fd51aa9","contentUrl":"http:\/\/vg05.met.vgwort.de\/na\/fc20b5cf4a274becb4bb75ae4fd51aa9"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Klassengenerator\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Klassengenerator"}]},{"@type":"WebSite","@id":"https:\/\/access-im-unternehmen.de\/#website","url":"https:\/\/access-im-unternehmen.de\/","name":"Access im Unternehmen","description":"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access","publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/access-im-unternehmen.de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/access-im-unternehmen.de\/#organization","name":"Andr\u00e9 Minhorst Verlag","url":"https:\/\/access-im-unternehmen.de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/","url":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","contentUrl":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","width":370,"height":111,"caption":"Andr\u00e9 Minhorst Verlag"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f","name":"Andr\u00e9 Minhorst","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","caption":"Andr\u00e9 Minhorst"}}]}},"_links":{"self":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55000871","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/comments?post=55000871"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55000871\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55000871"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55000871"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55000871"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}