{"id":55000950,"date":"2014-10-01T00:00:00","date_gmt":"2021-02-11T21:28:20","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=950"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Tabellen_per_IntelliSense","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Tabellen_per_IntelliSense\/","title":{"rendered":"Tabellen per IntelliSense"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg07.met.vgwort.de\/na\/be252cd5573c4daf801cc37385a338ae\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Wenn Sie mit dem VBA-Editor arbeiten und dort gelegentlich SQL-Anweisungen eingeben, m&uuml;ssen Sie die Namen der verwendeten Tabellen, Abfragen und Felder entweder kennen oder immer wieder zum Access-Fenster wechseln, um die Tabellen zu &ouml;ffnen und die fehlenden Informationen nachzuschlagen. Dies k&ouml;nnen Sie mit dem hier beschriebenen Vorgehen in Zukunft wesentlich vereinfachen! Dabei k&ouml;nnen Sie die Techniken entweder nur zur Vereinfachung beim Zusammensetzen von SQL-Anweisungen verwenden oder direkt den Zugriff auf Ihre Daten damit organisieren.<\/b><\/p>\n<p><b>Problem: Unkomfortable Dateneingabe<\/b><\/p>\n<p>Wenn Sie beispielsweise eine Datensatzgruppe erstellen wollen, welche die Felder <b>ArtikelID <\/b>und <b>Artikelname <\/b>liefern soll, verwenden Sie eine Anweisung wie die folgende (<b>rst <\/b>muss als <b>DAO.Recordset<\/b>, <b>db <\/b>als <b>DAO.Database <\/b>deklariert sein):<\/p>\n<pre><span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT tblArtikel.ArtikelID, &quot; _\r\n    &amp; &quot;tblArtikel.Artikelname FROM tblArtikel\", dbOpenDynaset)<\/pre>\n<p>Oder nehmen wir an, Sie m&ouml;chten eine Aktualisierungsabfrage ausf&uuml;hren, die den Einzelpreis eines Artikels anpasst. Dann verwenden Sie, die Deklaration einer <b>Database<\/b>-Variable namens <b>db <\/b>vorausgesetzt, etwa diese Anweisung:<\/p>\n<pre>db.Execute \"UPDATE tblArtikel SET tblArtikel.Einzelpreis = 10 &quot; _\r\n    &amp; &quot;WHERE tblArtikel.Artikelname  LIKE ''Chai''\"<\/pre>\n<p><b>Die L&ouml;sung: IntelliSense!<\/b><\/p>\n<p>Wie w&auml;re es denn, wenn Sie die SQL-Anweisung mit IntelliSense-Unterst&uuml;tzung erstellen k&ouml;nnten Dies k&ouml;nnten Sie wie in Bild 1 vom Direktfenster aus erledigen oder auch direkt im Codefenster.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_05\/pic_950_001.png\" alt=\"Auswahl der Tabelle per IntelliSense ...\" width=\"400\" height=\"174,4681\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Auswahl der Tabelle per IntelliSense &#8230;<\/span><\/b><\/p>\n<p>Dazu geben Sie einfach nur die ersten Zeichen des gesuchten Tabellennamens ein und bet&auml;tigen dann die Tastenkombination f&uuml;r IntelliSense, n&auml;mlich <b>Umschalt + Leertaste<\/b>.<\/p>\n<p>Und es kommt noch besser: Wenn Sie den Tabellennamen eingegeben haben und einen Punkt hinzuf&uuml;gen, zeigt IntelliSense alle Feldnamen an &#8211; s. Bild 2<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_05\/pic_950_002.png\" alt=\"... und auch die Feldnamen stehen zur Verf&uuml;gung!\" width=\"400\" height=\"174,4681\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: &#8230; und auch die Feldnamen stehen zur Verf&uuml;gung!<\/span><\/b><\/p>\n<p>Den so zusammengestellten SQL-Ausdruck m&uuml;ssen Sie nur noch mit vorangehendem<\/p>\n<pre>db.Open-Recordset(\"...\", dbOpenDynaset) <\/pre>\n<p>ausstatten, schon ist die SQL-Anweisung fertig.<\/p>\n<p><b>Wie es funktioniert<\/b><\/p>\n<p>Wie funktioniert das Ganze Nun: Wir haben f&uuml;r die Tabelle <b>tblArtikel <\/b>eine gleichnamige Klasse erstellt. Diese enth&auml;lt beispielsweise einige <b>Property Get<\/b>-Anweisungen, welche zwar noch Code enthalten, den wir weiter unten erl&auml;utern.<\/p>\n<p>Der prim&auml;re Zweck allerdings ist, die Namen der Felder als Eigenschaften zur Verf&uuml;gung zu stellen, damit diese per IntelliSense ausgew&auml;hlt werden k&ouml;nnen:<\/p>\n<pre><span style=\"color:blue;\">Public Property Get <\/span>ArtikelID()\r\n     ArtikelID = rst!ArtikelID\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Get <\/span>Artikelname()\r\n     Artikelname = rst!Artikelname\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Get <\/span>LieferantID()\r\n     LieferantID = rst!LieferantID\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Get <\/span>KategorieID()\r\n     KategorieID = rst!KategorieID\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Get <\/span>Liefereinheit()\r\n     Liefereinheit = rst!Liefereinheit\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Get <\/span>Einzelpreis()\r\n     Einzelpreis = rst!Einzelpreis\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Get <\/span>Lagerbestand()\r\n     Lagerbestand = rst!Lagerbestand\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Get <\/span>BestellteEinheiten()\r\n     BestellteEinheiten = _\r\n         rst!BestellteEinheiten\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Get <\/span>Mindestbestand()\r\n     Mindestbestand = rst!Mindestbestand\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property Get <\/span>Auslaufartikel()\r\n     Auslaufartikel = rst!Auslaufartikel\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Das erkl&auml;rt, warum nach Eingabe des Punktes die einzelnen Feldnamen angezeigt werden &#8211; es handelt sich schlicht um <b>Property Get<\/b>-Eigenschaften, wie sie in der Klassenprogrammierung verwendet werden. Aber warum k&ouml;nnen wir einfach so die Klassennamen wie <b>tblArtikel <\/b>per IntelliSense nutzen Dies gelingt bei herk&ouml;mmlichen Klassen nicht.<\/p>\n<p>Wir haben an dieser Stelle einen kleinen Trick angewendet, der die Klasse ohne Instanzierung ausf&uuml;hrbar macht. Dadurch erscheint auch der Klassenname direkt in der IntelliSense-Liste. Wie dies genau gelingt, erl&auml;utern wir weiter unten.<\/p>\n<p><b>tblArtikel statt rst<\/b><\/p>\n<p>Neben der Verwendung von IntelliSense haben wir noch ein cooles Feature zu der Klasse hinzugef&uuml;gt. Damit k&ouml;nnen Sie nun direkt &uuml;ber den Tabellennamen auf die enthaltenen Daten zugreifen statt erst ein Recordset erstellen zu m&uuml;ssen. Das sieht dann etwa wie folgt aus:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>Test()\r\n     <span style=\"color:blue;\">With<\/span> tblArtikel\r\n         <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> .EOF\r\n             <span style=\"color:blue;\">Debug.Print<\/span>  .ArtikelID, .Artikelname\r\n             .Move<span style=\"color:blue;\">Next<\/span>\r\n         <span style=\"color:blue;\">Loop<\/span>\r\n     End <span style=\"color:blue;\">With<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Sie k&ouml;nnen also einfach etwa in einer <b>Do While<\/b>-Schleife auf die Eigenschaft <b>EOF <\/b>der Klasse <b>tblArtikel <\/b>zugreifen, ohne diese zuvor als Recordset deklarieren und  f&uuml;llen zu m&uuml;ssen.<\/p>\n<p>Neben den einzelnen Feldern stehen auch noch ein paar weitere Methoden und Eigenschaften wie <b>MoveFirst<\/b>, <b>MoveLast<\/b>, <b>MovePrevious, MoveNext <\/b>oder auch <b>FindFirst <\/b>zur Verf&uuml;gung. All dies erreichen wir durch entsprechende Methoden in der Klasse, die so wie in Listing 1 aussehen.<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n<span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n<span style=\"color:blue;\">Private Sub <\/span>Class_Initialize()\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM tblArtikel\", dbOpenDynaset)\r\n<span style=\"color:blue;\">End Sub<\/span>\r\n<span style=\"color:blue;\">Public Sub <\/span>FindFirst(strFilter<span style=\"color:blue;\"> As String<\/span>)\r\n     rst.FindFirst strFilter\r\n<span style=\"color:blue;\">End Sub<\/span>\r\n<span style=\"color:blue;\">Public Function <\/span>FindFirstX(strFilter<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As <\/span>tblArtikel\r\n     <span style=\"color:blue;\">Dim <\/span>objX<span style=\"color:blue;\"> As <\/span>tblArtikel\r\n     <span style=\"color:blue;\">Set<\/span> objX = <span style=\"color:blue;\">New<\/span> tblArtikel\r\n     objX.FindFirst strFilter\r\n     <span style=\"color:blue;\">Set<\/span> FindFirstX = objX\r\n<span style=\"color:blue;\">End Function<\/span>\r\n<span style=\"color:blue;\">Public Sub <\/span>MoveNext()\r\n     rst.Move<span style=\"color:blue;\">Next<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span>\r\n<span style=\"color:blue;\">Public Sub <\/span>MovePrevious()\r\n     rst.MovePrevious\r\n<span style=\"color:blue;\">End Sub<\/span>\r\n<span style=\"color:blue;\">Public Sub <\/span>MoveFirst()\r\n     rst.MoveFirst\r\n<span style=\"color:blue;\">End Sub<\/span>\r\n<span style=\"color:blue;\">Public Sub <\/span>MoveLast()\r\n     rst.MoveLast\r\n<span style=\"color:blue;\">End Sub<\/span>\r\n<span style=\"color:blue;\">Public Function <\/span>Count()<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>var<span style=\"color:blue;\"> As Variant<\/span>\r\n     var = rst.Bookmark\r\n     rst.MoveLast\r\n     Count = rst.RecordCount\r\n     rst.MoveFirst\r\n     rst.Bookmark = var\r\n<span style=\"color:blue;\">End Function<\/span>\r\n<span style=\"color:blue;\">Public Function <\/span>Filter(strFilter<span style=\"color:blue;\"> As String<\/span>)\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM tblArtikel WHERE \" _\r\n         & strFilter, dbOpenDynaset)\r\n<span style=\"color:blue;\">End Function<\/span>\r\n<span style=\"color:blue;\">Public Sub <\/span>ClearFilter()\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM tblArtikel\", dbOpenDynaset)\r\n<span style=\"color:blue;\">End Sub<\/span>\r\n<span style=\"color:blue;\">Public Function <\/span>EOF()<span style=\"color:blue;\"> As Boolean<\/span>\r\n     EOF = rst.EOF\r\n<span style=\"color:blue;\">End Function<\/span>\r\n<span style=\"color:blue;\">Public Function <\/span>BOF()<span style=\"color:blue;\"> As Boolean<\/span>\r\n     BOF = rst.BOF\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Elemente der Klasse tblArtikel<\/span><\/b><\/p>\n<p>Die Klasse erstellt also direkt beim Initialisieren ein <b>Database<\/b>-Objekt und ein <b>Recordset<\/b>-Objekt mit allen Datens&auml;tzen der Tabelle. &uuml;ber die Methoden und Eigenschaften k&ouml;nnen Sie dann genau wie bei einem <b>Recordset<\/b>-Objekt auf die Tabelle zugreifen.<\/p>\n<p>F&uuml;r jede Tabellenklasse stehen dann die folgenden Eigenschaften, Methoden und Funktionen zur Verf&uuml;gung:<\/p>\n<ul>\n<li><b>FindFirst<\/b>: Verschiebt den Datensatzzeiger auf den ersten Datensatz, der dem angegebenen Suchkriterium entspricht<\/li>\n<li><b>FindFirstX<\/b>: Liefert ein Recordset-Objekt, dessen Datensatzzeiger auf den ersten Datensatz zeigt, der dem angegebenen Suchkriterium entspricht<\/li>\n<li><b>MoveNext<\/b>: Verschiebt den Datensatzzeiger zum folgenden Datensatz<\/li>\n<li><b>MovePrevious<\/b>: Verschiebt den Datensatzzeiger zum vorherigen Datensatz<\/li>\n<li><b>MoveFirst<\/b>: Verschiebt den Datensatzzeiger zum ersten Datensatz<\/li>\n<li><b>MoveLast<\/b>: Verschiebt den Datensatzzeiger zum letzten Datensatz<\/li>\n<li><b>Count<\/b>: Liefert die Anzahl der enthaltenen Datens&auml;tze. Im Gegensatz zu <b>Recordcount <\/b>liefert dies immer das korrekte Ergebnis, da der Datensatzzeiger zur Ermittlung auf den letzten Datensatz verschoben wird<\/li>\n<li><b>Filter<\/b>: Filtert das Recordset, das &uuml;ber den Tabellennamen beziehungsweise die Klasse geliefert wird, entsprechend dem angegebenen Filterkriterium<\/li>\n<li><b>ClearFilter<\/b>: Hebt den Filter wieder auf.<\/li>\n<li><b>EOF<\/b>: Gibt an, ob der Datensatzzeiger sich hinter dem letzten Datensatz befindet.<\/li>\n<li><b>BOF<\/b>: Gibt an, ob sich der Datensatzzeiger vor dem ersten Datensatz befindet.<\/li>\n<\/ul>\n<p>Was hat es nun mit der Funktion <b>FindFirstX <\/b>auf sich <b>FindFirst <\/b>verschiebt ja nur den Datensatzzeiger auf den gesuchten Datensatz. Wenn Sie auf einen der Werte zugreifen m&ouml;chten, m&uuml;ssen Sie diesen in einer weiteren Anweisung abfragen:<\/p>\n<pre>tblArtikel.FindFirst \"ArtikelID = 10\"\r\n<span style=\"color:blue;\">Debug.Print<\/span> tblArtikel.Artikelname<\/pre>\n<p><b>FindFirstX<\/b> hingegen liefert als Ergebnis direkt das Recordset mit dem verschobenen Datensatzzeiger. Das hei&szlig;t, dass Sie &uuml;ber die Eigenschaften der Klasse, also etwa die Feldnamen, direkt auf den gefundenen Datensatz zugreifen k&ouml;nnen:<\/p>\n<pre><span style=\"color:blue;\">Debug.Print<\/span> tblArtikel.FindFirstX (\"ArtikelID=10\").Artikelname<\/pre>\n<p>Bild 3 zeigt, dass Sie auch per IntelliSense auf die Felder des so ermittelten Datensatzes zugreifen k&ouml;nnen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_05\/pic_950_003.png\" alt=\"Direkter Zugriff auf das Ergebnis einer Suche\" width=\"450\" height=\"174,3856\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Direkter Zugriff auf das Ergebnis einer Suche<\/span><\/b><\/p>\n<p>Aber es kommt noch besser: Durch einen kleinen Trick, den wir weiter unten erl&auml;utern, sorgen wir daf&uuml;r, dass Sie die Funktion <b>FindFirstX<\/b> gar nicht angeben m&uuml;ssen, sondern das Suchkriterium gleich als Parameter der Tabellenklasse eingeben k&ouml;nnen:<\/p>\n<pre>tblArtikel(\"ArtikelID=10\").Artikelname<\/pre>\n<p>Nat&uuml;rlich gelingt auch dies mithilfe von IntelliSense (s. Bild 4).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_05\/pic_950_004.png\" alt=\"Die Suche steht auch als Standard-Member zur Verf&uuml;gung.\" width=\"450\" height=\"174,3856\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Die Suche steht auch als Standard-Member zur Verf&uuml;gung.<\/span><\/b><\/p>\n<p>Interessant ist auch noch die Ermittlung der Anzahl der Datens&auml;tze des Recordsets. Wenn Sie dies etwa bei einem mit dem Parameter <b>dbOpenDynaset <\/b>ge&ouml;ffneten Recordset erledigen m&ouml;chten, m&uuml;ssen Sie zun&auml;chst zum letzten Datensatz navigieren, damit die Anzahl der Datens&auml;tze korrekt erfasst und mit der Eigenschaft <b>RecordCount <\/b>ausgegeben werden kann.<\/p>\n<p>Dies erledigt die Eigenschaft <b>Count <\/b>in einem Zuge:  Sie merkt sich die aktuelle Position des Datensatzzeigers, bewegt diesen zum letzten Datensatz, ermittelt die Anzahl der Datens&auml;tze und verschiebt den Datensatzzeiger zur&uuml;ck zur zuvor gemerkten Position.<\/p>\n<p>Interessant sind auch noch die beiden Funktionen zum Setzen des Filters und zum Aufheben des Filters. Die Funktion <b>Filter <\/b>erstellt ein neues Recordset auf Basis der betroffenen Tabelle mit dem angegebenen Filterkriterium. Dabei wird das neu erstellte Recordset wieder der Variablen <b>rst <\/b>der Klasse zugewiesen, wodurch direkt wieder &uuml;ber die Methoden und Eigenschaften auf das gefilterte Recordset zugegriffen werden kann. Die Methode <b>ClearFilter<\/b> f&uuml;llt das Recordset lediglich wieder mit der beim Instanzieren der Klasse verwendeten Datenherkunft, also allen Datens&auml;tzen der betroffenen Tabelle.<\/p>\n<p><b>Tabellenklassen per Code erzeugen<\/b><\/p>\n<p>Nun w&auml;re es etwas viel Aufwand, f&uuml;r jede Tabelle von Hand eine entsprechende Klasse zu erzeugen. Deshalb haben wir eine Prozedur geschrieben, welche die Klassen f&uuml;r alle mit <b>tbl <\/b>beginnenden Tabellen der Datenbank anlegt.<\/p>\n<p>Diese kopieren Sie einfach in ein Standardmodul und starten sie. Achtung: Sie ben&ouml;tigen einen Verweis auf die Bibliothek <b>Microsoft Visual Basic For Applications Extensibility 5.3<\/b>.<\/p>\n<p>Was macht die Prozedur aus Listing 2 nun Sie  erstellt zun&auml;chst einen Verweis auf das aktuelle VBA-Projekt, denn diesem sollen ja im Anschluss einige neue Klassen hinzugef&uuml;gt werden &#8211; genau genommen f&uuml;r jede Tabelle, die mit <b>tbl <\/b>beginnt, eine.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>TabelleZuKlasse()\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>tdf<span style=\"color:blue;\"> As <\/span>DAO.TableDef\r\n     <span style=\"color:blue;\">Dim <\/span>objVBProject<span style=\"color:blue;\"> As <\/span>VBIDE.VBProject\r\n     <span style=\"color:blue;\">Dim <\/span>strCode<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> objVBProject = VBE.ActiveVBProject\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     KlassenLoeschen db, objVBProject\r\n     For Each tdf In db.TableDefs\r\n         <span style=\"color:blue;\">If <\/span>tdf.Name Like \"tbl*\"<span style=\"color:blue;\"> Then<\/span>\r\n             strCode = CodeZusammenstellen(tdf)\r\n             KlasseHinzufuegen objVBProject, strCode, tdf\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> tdf\r\n     <span style=\"color:blue;\">Set<\/span> db = Nothing\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><!--30percent--><\/p>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Prozedur zum Erstellen der Tabellenklassen<\/span><\/b><\/p>\n<p>Dann ruft die Prozedur eine weitere Routine namens <b>KlassenLoschen <\/b>auf, die sich um das L&ouml;schen eventuell bereits vorhandener gleichnamiger Klassen k&uuml;mmert.<\/p>\n<p>Bedenken Sie, dass die Klassen nach &auml;nderungen am Datenmodell neu erstellt werden sollten, damit beispielsweise hinzugekommene Felder als Eigenschaften abgebildet werden.<\/p>\n<p>Danach durchl&auml;uft die Prozedur in einer <b>For Each<\/b>-Schleife alle <b>TableDef<\/b>-Objekte der Datenbank und ruft f&uuml;r alle Eintr&auml;ge, deren Name mit <b>tbl <\/b>beginnt, die Funktion <b>CodeZusammenstellen <\/b>auf.<\/p>\n<p>Diese stellt den eigentlichen Klassencode zusammen und gibt diesen an die Variable <b>strCode <\/b>zur&uuml;ck. F&uuml;r jedes <b>TableDef<\/b>-Objekt ruft die Prozedur innerhalb der <b>For Each<\/b>-Schleife au&szlig;erdem die Routine <b>KlasseHinzuf&uuml;gen <\/b>auf. Diese erstellt die Klasse, f&uuml;gt den Code hinzu und f&uuml;gt die Klasse zum VBA-Projekt hinzu &#8211; mehr dazu weiter unten.<\/p>\n<p><b>Bestehende Tabellenklassen l&ouml;schen<\/b><\/p>\n<p>Damit kommen wir zu den drei Routinen, welche die Teilaufgaben &uuml;bernehmen. Die erste l&ouml;scht eventuell bestehende Tabellenklassen, also solche, die bereits zuvor mit der gleichen Routine erstellt wurden. Beachten Sie, dass nur solche Klassen gel&ouml;scht werden, die mit dem Pr&auml;fix <b>tbl <\/b>beginnen. Die Routine hei&szlig;t <b>KlassenLoeschen <\/b>und ist in Listing 3 zu finden. Sie durchl&auml;uft zun&auml;chst in einer <b>For Each<\/b>-Schleife alle Elemente der <b>TableDefs<\/b>-Auflistung, also alle Tabellen der Datenbank. Dabei pr&uuml;ft sie in einer <b>If&#8230;Then<\/b>-Bedingung, ob der Name des <b>TableDef<\/b>-Objekts mit <b>tbl <\/b>beginnt. Ist dies der Fall, wird die Fehlerbehandlung ausgeschaltet und das gleichnamige <b>VBComponent<\/b>-Objekt gel&ouml;scht. Danach schaltet die Prozedur die Fehlerbehandlung wieder ein. Auf die gleiche Weise werden alle Klassen gel&ouml;scht, deren Name mit dem Namen einer der Tabellen der Anwendung &uuml;bereinstimmt, die mit <b>tbl <\/b>beginnen.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>KlassenLoeschen(db<span style=\"color:blue;\"> As <\/span>DAO.Database, objVBProject<span style=\"color:blue;\"> As <\/span>VBProject)\r\n     <span style=\"color:blue;\">Dim <\/span>tdf<span style=\"color:blue;\"> As <\/span>DAO.TableDef\r\n     <span style=\"color:blue;\">Dim <\/span>objVBComponent<span style=\"color:blue;\"> As <\/span>VBComponent\r\n     <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As Integer<\/span>\r\n     For Each tdf In db.TableDefs\r\n         <span style=\"color:blue;\">If <\/span>tdf.Name Like \"tbl*\"<span style=\"color:blue;\"> Then<\/span>\r\n             On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n             objVBProject.VBComponents.Remove objVBProject.VBComponents(tdf.Name)\r\n             <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> tdf\r\n     For i = objVBProject.VBComponents.Count To 1 Step -1\r\n         <span style=\"color:blue;\">Set<\/span> objVBComponent = objVBProject.VBComponents(i)\r\n         <span style=\"color:blue;\">If <\/span>objVBComponent.Name Like \"tbl*\"<span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">MsgBox<\/span>(\"Klasse ''\" & objVBComponent.Name & \"'' l&ouml;schen &quot; _\r\n                 &amp; &quot;Es konnte  keine passende Tabelle mehr gefunden werden.\", vbYesNo) = vbYes<span style=\"color:blue;\"> Then<\/span>\r\n                 objVBProject.VBComponents.Remove objVBComponent\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> i\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: L&ouml;schen der bereits vorhandenen Klassen, deren Name mit tbl beginnt<\/span><\/b><\/p>\n<p>M&ouml;glicherweise hat der Entwickler aber in der Zwischenzeit eine oder mehrere Tabellen gel&ouml;scht, ohne die entsprechenden Klassen zu entfernen. F&uuml;r diesen Fall haben wir der Routine noch eine weitere Schleife hinzuf&uuml;gt, die alle <b>VBComponent<\/b>-Objekte durchl&auml;uft und pr&uuml;ft, ob nach dem ersten L&ouml;schdurchlauf noch Klassenmodule vorhanden sind, deren Name mit <b>tbl <\/b>beginnt. Dazu verwenden wir eine <b>For&#8230;Next<\/b>-Schleife, die r&uuml;ckw&auml;rts die Werte von der Anzahl aller noch vorhandenen <b>VBComponent<\/b>-Objekte bis <b>1 <\/b>durchl&auml;uft (<b>Step -1<\/b>). Das wir diesen Weg statt der sonst &uuml;blichen <b>For Each<\/b>-Schleife verwenden, liegt daran, dass wir hier gegebenenfalls Eintr&auml;ge l&ouml;schen, was die Auflistung durcheinander bringt und zu Fehlern f&uuml;hren kann. Alle Elemente, die noch mit <b>tbl <\/b>beginnen, werden auf diese Weise ebenfalls gel&ouml;scht, allerdings erst nach R&uuml;ckfrage per <b>MsgBox<\/b>-Anweisung.<\/p>\n<p><b>Zusammenstellen des Klassencodes<\/b><\/p>\n<p>Die danach aufgerufene Funktion <b>CodeZusammenstellen <\/b>erwartet als Parameter lediglich einen Verweis auf das <b>TableDef<\/b>-Objekt f&uuml;r die Tabelle, zu welcher der Code zusammengestellt werden soll (s. Listing 4). Der hier abgebildete erste Teil des Listings stellt zun&auml;chst die Anweisungen zum Deklarieren eines <b>Database<\/b>&#8211; und eines <b>Recordset<\/b>-Objekts dar. Au&szlig;erdem f&uuml;gt die Funktion das Ereignis <b>Class_Initialize <\/b>hinzu, welches beim Instanzieren der Klasse ausgel&ouml;st wird. Diese f&uuml;llt die beiden Variablen <b>db <\/b>und <b>rst <\/b>mit dem Verweis auf das aktuelle <b>Database<\/b>-Objekt sowie auf die betroffene Tabelle. Die Methode <b>FindFirst<\/b> erlaubt das Suchen nach dem ersten Datensatz mit dem angegebenen Filterausdruck.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>CodeZusammenstellen(tdf<span style=\"color:blue;\"> As <\/span>DAO.TableDef)\r\n     <span style=\"color:blue;\">Dim <\/span>strCode<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>fld<span style=\"color:blue;\"> As <\/span>DAO.Field\r\n     strCode = strCode & \"Dim db<span style=\"color:blue;\"> As <\/span>DAO.Database\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"Dim rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"Private Sub Class_Initialize()\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"    <span style=\"color:blue;\">Set<\/span> db = CurrentDb\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"    <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"\"SELECT * FROM \" _\r\n         & tdf.Name & \"\"\", dbOpenDynaset)\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"End Sub\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"Public Sub FindFirst(strFilter<span style=\"color:blue;\"> As String<\/span>)\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"    rst.FindFirst strFilter\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"End Sub\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & <span style=\"color:blue;\">vbCrLf<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Zusammenstellen des Codes der Klassen, Teil 1<\/span><\/b><\/p>\n<p>Weiter geht es in Listing 5. Hier wird zun&auml;chst die &ouml;ffentliche Funktion namens <b>FindFirstX <\/b>hinzugef&uuml;gt, die allerdings etwas anders deklariert ist wie <b>FindFirst <\/b>&#8211; n&auml;mlich als <b>Function<\/b>&#8211; und nicht als <b>Sub<\/b>-Prozedur. Dies hat den Hintergrund, dass diese Funktion gleich ein Recordset mit dem Datensatzzeiger auf dem Datensatz mit dem gew&uuml;nschten Kriterium liefern soll. Sp&auml;ter erkl&auml;ren wir noch, wie diese Funktion als Standardfunktion definiert wird, damit Sie etwa mit <b>tblArtikel(&#8222;ArtikelID = 10&#8220;).Artikelname <\/b>direkt auf einen gew&uuml;nschten Artikelnamen zugreifen k&ouml;nnen. Die &uuml;brigen Anweisungen erg&auml;nzen die Variable <b>strCode <\/b>um die anzulegenden Codezeilen f&uuml;r die &uuml;brigen Eigenschaften der Tabellenklasse.<\/p>\n<pre>     strCode = strCode & \"Public Function FindFirstX(strFilter<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As <\/span>\" & tdf.Name & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"    Dim objX<span style=\"color:blue;\"> As <\/span>\" & tdf.Name & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"    <span style=\"color:blue;\">Set<\/span> objX = <span style=\"color:blue;\">New<\/span> \" & tdf.Name & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"    objX.FindFirst strFilter\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"    <span style=\"color:blue;\">Set<\/span> FindFirstX = objX\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"End Function\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"Public Sub MoveNext()\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"    rst.MoveNext\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"End Sub\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"Public Sub MovePrevious()\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"    rst.MovePrevious\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"End Sub\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"Public Sub MoveFirst()\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"    rst.MoveFirst\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"End Sub\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"Public Sub MoveLast()\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"    rst.MoveLast\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"End Sub\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"Public Function Count()<span style=\"color:blue;\"> As Long<\/span>\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"    Dim var<span style=\"color:blue;\"> As Variant<\/span>\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"    var = rst.Bookmark\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"    rst.MoveLast\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"    Count = rst.RecordCount\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"    rst.MoveFirst\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"    rst.Bookmark = var\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"End Function\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"Public Function Filter(strFilter<span style=\"color:blue;\"> As String<\/span>)\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"    <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"\"SELECT * FROM \" & tdf.Name _\r\n         & \" WHERE \"\" & strFilter, dbOpenDynaset)\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"End Function\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"Public Sub ClearFilter()\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"    <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"\"SELECT * FROM \" _\r\n         & tdf.Name & \"\"\", dbOpenDynaset)\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"End Sub\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"Public Function EOF()<span style=\"color:blue;\"> As Boolean<\/span>\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"    EOF = rst.EOF\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"End Function\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"Public Function BOF()<span style=\"color:blue;\"> As Boolean<\/span>\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"    BOF = rst.BOF\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & \"End Function\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strCode = strCode & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     For Each fld In tdf.Fields\r\n         strCode = strCode & \"Public Property Get \" & fld.Name & \"()\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         strCode = strCode & \"    \" & fld.Name & \" = rst!\" & fld.Name & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         strCode = strCode & \"End Property\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> fld\r\n     CodeZusammenstellen = strCode\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: Zusammenstellen des Codes der Klassen, Teil 2<\/span><\/b><\/p>\n<p><b>Eigenschaften f&uuml;r die Felder festlegen<\/b><\/p>\n<p>Schlie&szlig;lich durchl&auml;uft die Prozedur in einer <b>For Each<\/b>-Schleife noch alle Felder des <b>TableDef<\/b>-Objekts und referenziert das aktuelle Feld mit der <b>Field<\/b>-Variablen <b>fld<\/b>. Innerhalb der Schleife legt die Prozedur f&uuml;r jedes Feld eine entsprechende <b>Property Get<\/b>-Eigenschaft mit dem Namen des Tabellenfeldes an.<\/p>\n<p>Der nun in der Variablen <b>strCode <\/b>befindliche Code wird schlie&szlig;lich als Ergebnis der Funktion <b>CodeZusammenstellen <\/b>an die aufrufende Prozedur zur&uuml;ckgegeben.<\/p>\n<p><b>Erstellen der Klassen<\/b><\/p>\n<p>Die eigentliche Erstellung der Klassen erfolgt in der Prozedur <b>KlasseHinzufuegen<\/b>, die einen Verweis auf das aktuelle VBA-Projekt der Anwendung, den Code in der Variablen <b>strCode <\/b>sowie den Verweis auf das <b>TableDef<\/b>-Objekt f&uuml;r die anzulegende Tabellenklasse als Parameter erwartet (s. Listing 6).<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>KlasseHinzufuegen(objVBProject<span style=\"color:blue;\"> As <\/span>VBProject, strCode<span style=\"color:blue;\"> As String<\/span>, tdf<span style=\"color:blue;\"> As <\/span>DAO.TableDef)\r\n     <span style=\"color:blue;\">Dim <\/span>objVBComponent<span style=\"color:blue;\"> As <\/span>VBIDE.VBComponent\r\n     <span style=\"color:blue;\">Dim <\/span>strKlasse<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> objVBComponent = objVBProject.VBComponents.Add(vbext_ct_ClassModule)\r\n     objVBComponent.Name = tdf.Name\r\n     objVBComponent.CodeModule.AddFromString strCode\r\n     objVBComponent.Export CurrentProject.Path & \"\\\" & objVBComponent.Name\r\n     objVBProject.VBComponents.Remove objVBComponent\r\n     Open CurrentProject.Path & \"\\\" & tdf.Name For Input<span style=\"color:blue;\"> As <\/span>#1\r\n     strKlasse = Input$(LOF(1), #1)\r\n     Close #1\r\n     strKlasse = <span style=\"color:blue;\">Replace<\/span>(strKlasse, \"Attribute VB_PredeclaredId = False\", _\r\n         \"Attribute VB_PredeclaredId = True\")\r\n     strKlasse = <span style=\"color:blue;\">Replace<\/span>(strKlasse, \"Public Function FindFirstX(strFilter<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As <\/span>\" _\r\n         & tdf.Name, \"Public Function FindFirstX(strFilter<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As <\/span>\" & tdf.Name & <span style=\"color:blue;\">vbCrLf<\/span> _\r\n         & \"Attribute DefaultMethod.VB_UserMemId = 0\")\r\n     Open CurrentProject.Path & \"\\\" & tdf.Name For Output<span style=\"color:blue;\"> As <\/span>#1\r\n     Print #1, strKlasse\r\n     Close #1\r\n     objVBProject.VBComponents.Import CurrentProject.Path & \"\\\" & tdf.Name\r\n     DoCmd.Save acModule, tdf.Name\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 6: Hinzuf&uuml;gen der Klassen zum VB-Projekt der Datenbank<\/span><\/b><\/p>\n<p>Die Prozedur f&uuml;gt zun&auml;chst &uuml;ber die <b>Add<\/b>-Methode ein neues <b>VBComponent<\/b>-Objekt zum VBA-Projekt hinzu. Dabei verwendet sie die Konstante <b>vbext_ct_ClassModule <\/b>als Parameter, der daf&uuml;r sorgt, dass ein Klassenmodul und kein Standardmodul angelegt wird. Die Variable <b>objVBComponent <\/b>nimmt einen Verweis auf die neu erstellte Klasse auf.<\/p>\n<p>&uuml;ber die Eigenschaft <b>Name <\/b>stellt die Prozedur den Namen der Klasse auf den Namen der Tabelle ein. Dann f&uuml;gt sie den VBA-Code aus der Variablen <b>strCode <\/b>mit der <b>AddFromString<\/b>-Methode in das <b>CodeModule <\/b>ein.<\/p>\n<p>Normalerweise k&ouml;nnten wir die Klasse nun schon speichern &#8211; sie hat den gew&uuml;nschten Namen und enth&auml;lt den VBA-Code. Allerdings gibt es noch zwei kleine &auml;nderungen, die wir am Code des Klassenmoduls vornehmen m&uuml;ssen:<\/p>\n<ul>\n<li>Die Funktion <b>FindFirstX <\/b>soll als Standardmember der Klasse festgelegt werden, damit der Entwickler ein Suchkriterium direkt als Parameter der jeweiligen Klasse eingeben kann &#8211; dies erm&ouml;glicht Ausdr&uuml;cke wie etwa <b>tblArtikel(&#8222;ArtikelID=10&#8220;).Artikelname<\/b>.<\/li>\n<li>Die Klasse soll so ge&auml;ndert werden, dass sie nicht explizit instanziert werden muss, sondern direkt bei Eingabe des Klassennamens zur Verf&uuml;gung steht.<\/li>\n<\/ul>\n<p>Beide &auml;nderungen k&ouml;nnen nicht &uuml;ber den VBA-Editor vorgenommen werden. Also speichert die Prozedur den Inhalt der Klasse mit der <b>Export<\/b>-Methode im gleichen Verzeichnis wie die Datenbank und l&ouml;scht die Klasse wieder aus dem VBA-Projekt, da diese gleich in ge&auml;nderter Form wieder importiert werden soll.<\/p>\n<p>Dann &ouml;ffnet die Prozedur die nun als Textdatei im Dateisystem verf&uuml;gbare Klasse und liest diese in die <b>String<\/b>-Variable <b>strKlasse <\/b>ein. Dort ersetzt die Prozedur nun zwei Ausdr&uuml;cke. Erstens wird die Zeile <\/p>\n<pre>Attribute VB_PredeclaredId = <span style=\"color:blue;\">False<\/span><\/pre>\n<p>durch die Zeile <\/p>\n<pre>Attribute VB_PredeclaredId = <span style=\"color:blue;\">True<\/span><\/pre>\n<p>ersetzt. Dies sorgt daf&uuml;r, dass die Klasse nicht mehr explizit instanziert werden muss. Zweitens f&uuml;gt die Prozedur hinter der Zeile <\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>FindFirstX(strFilter <span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As <\/span>\" & tdf.Name<\/pre>\n<p>noch die Zeile <\/p>\n<pre>\"Attribute DefaultMethod. VB_UserMemId = 0\"<\/pre>\n<p>ein. Dadurch wird die Funktion <b>FindFirstX <\/b>als Standardmethode der Klasse definiert.<\/p>\n<p>Damit sind die &auml;nderungen an der in der Variablen <b>strKlasse <\/b>befindlichen Klasse abgeschlossen (s. Bild 5). Der Inhalt wird nun zur&uuml;ck in die Datei geschrieben, aus der er auch ausgelesen wurde. Nach dem Schlie&szlig;en der Datei importiert die Prozedur die Datei wieder, und zwar mit der <b>Import<\/b>-Methode der <b>VBComponents<\/b>-Auflistung des VBA-Projekts. Schlie&szlig;lich speichert die Prozedur das Modul unter dem Namen der Tabelle als neues Klassenmodul.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_05\/pic_950_005.png\" alt=\"Die Textdatei mit dem kompletten Inhalt der Klasse\" width=\"650\" height=\"488,1633\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Die Textdatei mit dem kompletten Inhalt der Klasse<\/span><\/b><\/p>\n<p><b>Weitere Beispiele f&uuml;r den Einsatz der Tabellenklassen<\/b><\/p>\n<p>Zum Schluss schauen wir uns noch einige weitere Anwendungsm&ouml;glichkeiten der Tabellenklassen an.<\/p>\n<p><b>Z&auml;hlen von Datens&auml;tzen<\/b><\/p>\n<p>Im ersten Beispiel m&ouml;chte ich eine M&ouml;glichkeit schaffen, auf die Schnelle die Anzahl der Datens&auml;tze eines Recordsets zu ermitteln.<\/p>\n<p>Dazu bietet die Klasse die Eigenschaft <b>Count <\/b>(wieso eigentlich <b>Recordcount <\/b>&#8211; <b>Count <\/b>reicht doch v&ouml;llig aus!). Im Direktfenster ermitteln Sie beispielsweise wie in Bild 6 die Anzahl der Datens&auml;tze.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_05\/pic_950_006.png\" alt=\"Z&auml;hlen von Datens&auml;tzen\" width=\"425\" height=\"164,6976\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Z&auml;hlen von Datens&auml;tzen<\/span><\/b><\/p>\n<p><b>Filtern von Datens&auml;tzen<\/b><\/p>\n<p>Ebenfalls interessant ist nat&uuml;rlich das Filtern von Datens&auml;tzen, um diese sp&auml;ter zu durchlaufen. Das Filtern geschieht &uuml;ber die Eigenschaft <b>Filter<\/b> und der &uuml;bergabe des Filterkriteriums als Parameter. Dies wirkt sich auf das aktuell in <b>tblArtikel <\/b>gespeicherte Recordset aus, sodass Sie gleich danach etwa die Anzahl der gefilterten Datens&auml;tze ermitteln k&ouml;nnen (s. Bild 7).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2014_05\/pic_950_007.png\" alt=\"Filtern der Datens&auml;tze einer Tabelle\" width=\"425\" height=\"126,9376\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Filtern der Datens&auml;tze einer Tabelle<\/span><\/b><\/p>\n<p>Nach dem Filtern k&ouml;nnen Sie entsprechend noch die gefilterten Datens&auml;tze per <b>Do While<\/b>-Schleife durchlaufen und beispielsweise ausgeben (s. Listing 7):<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>BeispielFilter()\r\n     tblArtikel.Filter \"Artikelname LIKE ''C*''\"\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> tblArtikel.EOF\r\n         <span style=\"color:blue;\">Debug.Print<\/span> tblArtikel.Artikelname\r\n         tblArtikel.Move<span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 7: Beispiel f&uuml;r das Filtern einer Tabelle<\/span><\/b><\/p>\n<p><b>Filter aufheben<\/b><\/p>\n<p>Zum Aufheben des Filters verwenden Sie einfach die Methode <b>ClearFilter<\/b>:<\/p>\n<pre>tblArtikel.ClearFilter<\/pre>\n<p><b>Schnelle Suche<\/b><\/p>\n<p>Richtig cool ist das folgende Feature: Dort k&ouml;nnen Sie f&uuml;r die Tabelle gleich einen Suchausdruck eingeben und auf die Daten des gefundenen Datensatzes zugreifen. Das sieht wie folgt aus:<\/p>\n<pre>  tblArtikel(\"ArtikelID=10\").Artikelname\r\nIkura<\/pre>\n<p>Dies l&auml;sst sich sogar verschachteln. Wenn Sie also etwa den Namen der Kategorie ermitteln wollen, die f&uuml;r den Artikel mit dem Wert <b>1 <\/b>im Feld <b>Artikel-ID <\/b>gespeichert ist, verwenden Sie den folgenden Ausdruck:<\/p>\n<pre>  tblKategorien(\"KategorieID = \" & tblArtikel(\"ArtikelID = 1\").KategorieID).Kategoriename\r\nGetr&auml;nke<\/pre>\n<p>Dies ermittelt den Namen der Kategorie, deren <b>KategorieID <\/b>in der Tabelle <b>tblArtikel <\/b>f&uuml;r den Artikel mit dem Wert <b>1 <\/b>f&uuml;r die <b>ArtikelID<\/b> eingestellt wurde.<\/p>\n<p><b>Mehrere Recordsets<\/b><\/p>\n<p>Man k&ouml;nnte eine  Einschr&auml;nkung darin sehen, dass die hier vorgestellte Methode immer das gleiche Recordset verwendet, wenn man &uuml;ber den Tabellennamen auf die Klasse und somit auf das hinterlegte Recordset zugreift. Gegebenenfalls m&ouml;chte man zus&auml;tzlich zu diesem Recordset noch ein weiteres &ouml;ffnen, das auf der gleichen Tabelle basiert.<\/p>\n<p>Doch auch das ist kein Problem: Sie deklarieren und instanzieren dann einfach jeweils ein Objekt auf Basis der Tabellenklasse. Die Deklaration sieht dann wie hier aus:<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>rstArtikel1<span style=\"color:blue;\"> As <\/span>tblArtikel\r\n<span style=\"color:blue;\">Dim <\/span>rstArtikel2<span style=\"color:blue;\"> As <\/span>tblArtikel<\/pre>\n<p>Anschlie&szlig;end instanzieren Sie die beiden  Objekte wie folgt:<\/p>\n<pre><span style=\"color:blue;\">Set<\/span> rstArtikel1 = <span style=\"color:blue;\">New<\/span> tblArtikel\r\n<span style=\"color:blue;\">Set<\/span> rstArtikel2 = <span style=\"color:blue;\">New<\/span> tblArtikel<\/pre>\n<p>Wenn Sie nun beispielsweise in der ersten Instanz nach dem Artikel mit dem Wert <b>2 <\/b>im Feld <b>ArtikelID <\/b>suchen und in der zweiten Instanz nach dem Wert <b>3 <\/b>in diesem Feld, erledigen Sie das mit den folgenden Anweisungen:<\/p>\n<pre>rstArtikel1.FindFirst \"ArtikelID = 2\"\r\nrstArtikel2.FindFirst \"ArtikelID = 3\"<\/pre>\n<p>Das war es schon &#8211; Sie k&ouml;nnen nun &uuml;ber <b>rstArtikel1 <\/b>auf den Artikel mit dem Wert <b>2 <\/b>im Feld <b>ArtikelID <\/b>zugreifen und mit <b>rstArtikel2 <\/b>auf den dort gefundenen Artikel. Zusammengefasst sieht dies wie in Listing 8 aus.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>TestZweiInstanzen()\r\n     <span style=\"color:blue;\">Dim <\/span>rstArtikel1<span style=\"color:blue;\"> As <\/span>tblArtikel\r\n     <span style=\"color:blue;\">Dim <\/span>rstArtikel2<span style=\"color:blue;\"> As <\/span>tblArtikel\r\n     <span style=\"color:blue;\">Set<\/span> rstArtikel1 = <span style=\"color:blue;\">New<\/span> tblArtikel\r\n     <span style=\"color:blue;\">Set<\/span> rstArtikel2 = <span style=\"color:blue;\">New<\/span> tblArtikel\r\n     rstArtikel1.FindFirst \"ArtikelID = 2\"\r\n     rstArtikel2.FindFirst \"ArtikelID = 3\"\r\n     <span style=\"color:blue;\">Debug.Print<\/span> rstArtikel1.ArtikelID, rstArtikel1.Artikelname\r\n     <span style=\"color:blue;\">Debug.Print<\/span> rstArtikel2.ArtikelID, rstArtikel2.Artikelname\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 8: Beispiel f&uuml;r den Einsatz mehrerer Recordsets<\/span><\/b><\/p>\n<p><b>Formular zum Erstellen der Tabellenklassen<\/b><\/p>\n<p>Gelegentlich treten beim Erstellen der Tabellenklassen Fehler auf. Dies h&auml;ngt wahrscheinlich mit dem ge&ouml;ffneten VBA-Editor zusammen. Wir m&uuml;ssen also einen Weg finden, die Tabellenklassen zu erstellen, w&auml;hrend der VBA-Editor geschlossen ist. Kein Problem: Wir erstellen einfach ein Formular, das die ben&ouml;tigte Prozedur per Schaltfl&auml;che aufruft. Das Formular <b>frmTabellenPerIntelliSense <\/b>enth&auml;lt lediglich eine Schaltfl&auml;che namens <b>cmdKlassenErstellen<\/b>. Diese startet die Prozedur <b>TabelleZuKlasse<\/b>.<\/p>\n<p>Wichtig ist, dass Sie das Formular &ouml;ffnen und auf die Schaltfl&auml;che klicken, ohne den VBA-Editor zuvor ge&ouml;ffnet zu haben &#8211; zumindest seit dem Starten der Access-Anwendung.<\/p>\n<p>War der VBA-Editor w&auml;hrend dieser Sitzung schon einmal ge&ouml;ffnet, ist der Effekt durch das Starten vom Formular aus dahin. &ouml;ffnen Sie das Formular also direkt nach dem Starten der Anwendung und erstellen Sie die Tabellenklassen neu, wenn dies aufgrund von &auml;nderungen n&ouml;tig ist.<\/p>\n<p>Um den Import der Funktion zu vereinfachen, kopieren wir die Prozeduren aus dem Standardmodul noch in das Formular <b>frmTabellenPerIntelliSense<\/b>. Sie brauchen dann, wenn Sie Tabellenklassen in Ihrer Anwendung erstellen m&ouml;chten, lediglich das Formular zu der Anwendung hinzuzuf&uuml;gen.<\/p>\n<p>Au&szlig;erdem ben&ouml;tigen Sie noch den Verweis auf die Bibliothek <b>Microsoft Visual Basic for Applications Extensibility 5.3<\/b>. Das war es &#8211; ein Klick auf die Bibliothek erstellt dann die Tabellenklassen.<\/p>\n<p><b>Zusammenfassung und Ausblick<\/b><\/p>\n<p>Die hier vorgestellten Tabellenklassen erm&ouml;glichen den einfachen Zugriff auf die Tabellen einer Datenbank. Aktuell m&uuml;ssen Sie nur das Modul mdlTabellenPerIntelliSense und das Formular frmTabellenPerIntelliSense in die Zielanwendung importieren und die Schaltfl&auml;che auf dem Formular dr&uuml;cken. Eine m&ouml;gliche Erweiterung w&auml;re ein Add-In, das die hier enthaltene Funktion zum Erstellen der Datenklassen bietet, damit man den Code nicht in jede Datenbank einf&uuml;gen muss. Gegebenenfalls k&ouml;nnte man dies auch noch auf andere Objekte wie Abfragen oder Formulare und Berichte ausdehnen.<\/p>\n<h3>Downloads zu diesem Beitrag<\/h3>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>TabellenPerIntelliSense.mdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/C415E817-1B0B-4432-85CB-274C3615DA3B\/aiu_950.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wenn Sie mit dem VBA-Editor arbeiten und dort gelegentlich SQL-Anweisungen eingeben, m&uuml;ssen Sie die Namen der verwendeten Tabellen, Abfragen und Felder entweder kennen oder immer wieder zum Access-Fenster wechseln, um die Tabellen zu &ouml;ffnen und die fehlenden Informationen nachzuschlagen. Dies k&ouml;nnen Sie mit dem hier beschriebenen Vorgehen in Zukunft wesentlich vereinfachen! Dabei k&ouml;nnen Sie die Techniken entweder nur zur Vereinfachung beim Zusammensetzen von SQL-Anweisungen verwenden oder direkt den Zugriff auf Ihre Daten damit organisieren.<\/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":[662014,66052014,44000021],"tags":[],"class_list":["post-55000950","post","type-post","status-publish","format-standard","hentry","category-662014","category-66052014","category-Tabellen_und_Datenmodellierung"],"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>Tabellen per IntelliSense - 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\/Tabellen_per_IntelliSense\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Tabellen per IntelliSense\" \/>\n<meta property=\"og:description\" content=\"Wenn Sie mit dem VBA-Editor arbeiten und dort gelegentlich SQL-Anweisungen eingeben, m&uuml;ssen Sie die Namen der verwendeten Tabellen, Abfragen und Felder entweder kennen oder immer wieder zum Access-Fenster wechseln, um die Tabellen zu &ouml;ffnen und die fehlenden Informationen nachzuschlagen. Dies k&ouml;nnen Sie mit dem hier beschriebenen Vorgehen in Zukunft wesentlich vereinfachen! Dabei k&ouml;nnen Sie die Techniken entweder nur zur Vereinfachung beim Zusammensetzen von SQL-Anweisungen verwenden oder direkt den Zugriff auf Ihre Daten damit organisieren.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Tabellen_per_IntelliSense\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2021-02-11T21:28:20+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg07.met.vgwort.de\/na\/be252cd5573c4daf801cc37385a338ae\" \/>\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=\"22\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Tabellen_per_IntelliSense\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Tabellen_per_IntelliSense\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Tabellen per IntelliSense\",\"datePublished\":\"2021-02-11T21:28:20+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Tabellen_per_IntelliSense\\\/\"},\"wordCount\":3300,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Tabellen_per_IntelliSense\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/be252cd5573c4daf801cc37385a338ae\",\"articleSection\":[\"2014\",\"5\\\/2014\",\"Tabellen und Datenmodellierung\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Tabellen_per_IntelliSense\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Tabellen_per_IntelliSense\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Tabellen_per_IntelliSense\\\/\",\"name\":\"Tabellen per IntelliSense - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Tabellen_per_IntelliSense\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Tabellen_per_IntelliSense\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/be252cd5573c4daf801cc37385a338ae\",\"datePublished\":\"2021-02-11T21:28:20+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Tabellen_per_IntelliSense\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Tabellen_per_IntelliSense\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Tabellen_per_IntelliSense\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/be252cd5573c4daf801cc37385a338ae\",\"contentUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/be252cd5573c4daf801cc37385a338ae\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Tabellen_per_IntelliSense\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Tabellen per IntelliSense\"}]},{\"@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":"Tabellen per IntelliSense - 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\/Tabellen_per_IntelliSense\/","og_locale":"de_DE","og_type":"article","og_title":"Tabellen per IntelliSense","og_description":"Wenn Sie mit dem VBA-Editor arbeiten und dort gelegentlich SQL-Anweisungen eingeben, m&uuml;ssen Sie die Namen der verwendeten Tabellen, Abfragen und Felder entweder kennen oder immer wieder zum Access-Fenster wechseln, um die Tabellen zu &ouml;ffnen und die fehlenden Informationen nachzuschlagen. Dies k&ouml;nnen Sie mit dem hier beschriebenen Vorgehen in Zukunft wesentlich vereinfachen! Dabei k&ouml;nnen Sie die Techniken entweder nur zur Vereinfachung beim Zusammensetzen von SQL-Anweisungen verwenden oder direkt den Zugriff auf Ihre Daten damit organisieren.","og_url":"https:\/\/access-im-unternehmen.de\/Tabellen_per_IntelliSense\/","og_site_name":"Access im Unternehmen","article_published_time":"2021-02-11T21:28:20+00:00","og_image":[{"url":"http:\/\/vg07.met.vgwort.de\/na\/be252cd5573c4daf801cc37385a338ae","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"22\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Tabellen_per_IntelliSense\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Tabellen_per_IntelliSense\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Tabellen per IntelliSense","datePublished":"2021-02-11T21:28:20+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Tabellen_per_IntelliSense\/"},"wordCount":3300,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Tabellen_per_IntelliSense\/#primaryimage"},"thumbnailUrl":"http:\/\/vg07.met.vgwort.de\/na\/be252cd5573c4daf801cc37385a338ae","articleSection":["2014","5\/2014","Tabellen und Datenmodellierung"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Tabellen_per_IntelliSense\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Tabellen_per_IntelliSense\/","url":"https:\/\/access-im-unternehmen.de\/Tabellen_per_IntelliSense\/","name":"Tabellen per IntelliSense - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Tabellen_per_IntelliSense\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Tabellen_per_IntelliSense\/#primaryimage"},"thumbnailUrl":"http:\/\/vg07.met.vgwort.de\/na\/be252cd5573c4daf801cc37385a338ae","datePublished":"2021-02-11T21:28:20+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Tabellen_per_IntelliSense\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Tabellen_per_IntelliSense\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Tabellen_per_IntelliSense\/#primaryimage","url":"http:\/\/vg07.met.vgwort.de\/na\/be252cd5573c4daf801cc37385a338ae","contentUrl":"http:\/\/vg07.met.vgwort.de\/na\/be252cd5573c4daf801cc37385a338ae"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Tabellen_per_IntelliSense\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Tabellen per IntelliSense"}]},{"@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\/55000950","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=55000950"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55000950\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55000950"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55000950"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55000950"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}