{"id":55000968,"date":"2015-02-01T00:00:00","date_gmt":"2020-05-22T21:06:42","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=968"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"DebuggingHilfsfunktionen","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/DebuggingHilfsfunktionen\/","title":{"rendered":"Debugging-Hilfsfunktionen"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg07.met.vgwort.de\/na\/a9a214ba5e104c03a2c99c93fbe91df8\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Beim Debuggen von VBA-Code, der Anweisungen f&uuml;r den Zugriff auf die Daten der Anwendung per DAO enth&auml;lt, ben&ouml;tigt man immer wieder mal Detailinformationen. Welche Felder enth&auml;lt die Tabelle noch Welchen Wert enthalten die Felder des aktuellen Datensatzes Wie viele Datens&auml;tze liefert das aktuelle Recordset Die notwendigen Informationen kann man sich mithilfe entsprechender Ausdr&uuml;cke &uuml;ber das Direktfenster holen, aber meist kostet dies unn&ouml;tig Zeit. Warum also nicht einfach eine kleine Hilfsklasse programmieren, die solche Fragen sehr einfach beantwortet Dieser Beitrag zeigt, wie es gelingt.<\/b><\/p>\n<p>Die Idee f&uuml;r diesen Betrag stammt aus meinen allt&auml;glichen Bed&uuml;rfnissen. Erstens habe ich wirklich oft den Bedarf, mal eben die Werte der Felder eines gerade in Bearbeitung befindlichen Datensatzes auszugeben oder auch nur dessen Feldnamen, zweitens kamen mit der Zeit noch weitere Ideen hinzu &#8211; abgeleitet zum Beispiel von MySQL, wo es einen einfachen Befehl etwa zur Anzeige aller Tabellen (<b>ShowTables<\/b>) oder zur Ausgabe der Beschreibung einer Tabelle gibt (<b>Describe <Tabellenname><\/b>).<\/p>\n<p>Also habe ich eine Klasse entwickelt, die solche Fragen beantwortet. In den folgenden Abschnitten schauen wir uns an, wie die Klasse aufgebaut ist und welche Fragen sie beantworten kann.<\/p>\n<p><b>Alle Tabellen ausgeben<\/b><\/p>\n<p>Den Befehl <b>ShowTables<\/b> unter MySQL fand ich schon immer praktisch. Gerade wenn man nicht so oft mit einer Datenbank arbeitet, merkt man sich nicht unbedingt alle Tabellennamen &#8211; und zum Nachschlagen eines Tabellennamens immer vom VBA-Editor zum Access-Fenster zu wechseln macht auch keinen Spa&szlig;, vor allem, wenn der Navigationsbereich einige hundert Elemente enth&auml;lt, durch die man sich erst mal zu den Tabellen durchk&auml;mpfen muss.<\/p>\n<p>Also entwickeln wir zun&auml;chst einmal die Methode <b>ShowTables<\/b>, die eine Liste aller Tabellen der Datenbank in alphabetischer Reihenfolge im Direktfenster ausgeben soll.<\/p>\n<p>Die Ausgabe k&ouml;nnte etwa wie in Bild 1 aussehen, sobald man den Befehl <b>ShowTables <\/b>dort eingibt und die Eingabetaste bet&auml;tigt.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_01\/pic_968_001.png\" alt=\"Ausgabe der Tabellen einer Datenbank mit Detailinformationen\" width=\"575\" height=\"443,6258\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Ausgabe der Tabellen einer Datenbank mit Detailinformationen<\/span><\/b><\/p>\n<p>Daf&uuml;r ben&ouml;tigen wir nat&uuml;rlich eine entsprechende Prozedur, die Sie in Listing 1 finden. Die Prozedur verwendet eine Enumeration, die im gleichen Modul wie folgt deklariert wird:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>ShowTables(<span style=\"color:blue;\">Optional<\/span> intType<span style=\"color:blue;\"> As <\/span>TableType, _\r\n         <span style=\"color:blue;\">Optional<\/span> bolSystem<span style=\"color:blue;\"> As Boolean<\/span> = True, <span style=\"color:blue;\">Optional<\/span> bolHidden<span style=\"color:blue;\"> As Boolean<\/span> = <span style=\"color:blue;\">True<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database, rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>strType<span style=\"color:blue;\"> As String<\/span>, strTable<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>intLen<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strSystem<span style=\"color:blue;\"> As String<\/span>, strHidden<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>bolShow<span style=\"color:blue;\"> As Boolean<\/span>\r\n     <span style=\"color:blue;\">If <\/span>intType = 0<span style=\"color:blue;\"> Then<\/span> intType = dbLocal + dbODBC + dbLinked\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT Name, Type FROM MSysObjects &quot; _\r\n         &quot;WHERE Type IN (1,4,6) ORDER BY Name\", dbOpenDynaset)\r\n     int<span style=\"color:blue;\">Len<\/span> = DMax(\"<span style=\"color:blue;\">Len<\/span>(Name)\", \"MSysObjects\")\r\n     <span style=\"color:blue;\">Debug.Print<\/span>\r\n     <span style=\"color:blue;\">Debug.Print<\/span> \"Table\" & Space(int<span style=\"color:blue;\">Len<\/span> - 4) & \"Type\"\r\n     <span style=\"color:blue;\">Debug.Print<\/span> String(int<span style=\"color:blue;\">Len<\/span> + 25, \"-\")\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n         strTable = rst!Name & Space(int<span style=\"color:blue;\">Len<\/span> - <span style=\"color:blue;\">Len<\/span>(rst!Name))\r\n         bolShow = <span style=\"color:blue;\">True<\/span>\r\n         strSystem = \"\"\r\n         <span style=\"color:blue;\">If <\/span>(db.TableDefs(rst!Name).Attributes And dbSystemObject)<span style=\"color:blue;\"> Then<\/span>\r\n             strSystem = \"|System\"\r\n             <span style=\"color:blue;\">If <\/span>bolSystem = <span style=\"color:blue;\">False<\/span><span style=\"color:blue;\"> Then<\/span> bolShow = <span style=\"color:blue;\">False<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         strHidden = \"\"\r\n         <span style=\"color:blue;\">If <\/span>(db.TableDefs(rst!Name).Attributes And dbHiddenObject)<span style=\"color:blue;\"> Then<\/span>\r\n             strHidden = \"|Hidden\"\r\n             <span style=\"color:blue;\">If <\/span>bolHidden = <span style=\"color:blue;\">False<\/span><span style=\"color:blue;\"> Then<\/span> bolShow = <span style=\"color:blue;\">False<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">If <\/span>bolShow = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n             Select Case rst!Type\r\n                 <span style=\"color:blue;\">Case <\/span>1\r\n                     <span style=\"color:blue;\">If <\/span>(intType And dbLocal) = dbLocal<span style=\"color:blue;\"> Then<\/span>\r\n                         strType = \"Local Table\"\r\n                         <span style=\"color:blue;\">Debug.Print<\/span> strTable & \" \" & strType & strSystem & strHidden\r\n                     <span style=\"color:blue;\">End If<\/span>\r\n                 <span style=\"color:blue;\">Case <\/span>4\r\n                     <span style=\"color:blue;\">If <\/span>(intType And dbODBC) = dbODBC<span style=\"color:blue;\"> Then<\/span>\r\n                         strType = \"ODBC Table\"\r\n                         <span style=\"color:blue;\">Debug.Print<\/span> strTable & \" \" & strType & strSystem & strHidden\r\n                     <span style=\"color:blue;\">End If<\/span>\r\n                 <span style=\"color:blue;\">Case <\/span>6\r\n                     <span style=\"color:blue;\">If <\/span>(intType And dbLinked) = dbLinked<span style=\"color:blue;\"> Then<\/span>\r\n                         strType = \"Linked Table\"\r\n                         <span style=\"color:blue;\">Debug.Print<\/span> strTable & \" \" & strType & strSystem & strHidden\r\n                     <span style=\"color:blue;\">End If<\/span>\r\n             <span style=\"color:blue;\">End Select<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         rst.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 1: Ausgabe der Tabellen einer Datenbank im Direktfenster des VBA-Editors<\/span><\/b><\/p>\n<pre><span style=\"color:blue;\">Public <\/span>Enum TableType\r\n     dbLocal = 1\r\n     dbODBC = 2\r\n     dbLinked = 4\r\nEnd Enum<\/pre>\n<p>Die Enumeration stellt die Werte f&uuml;r den Parameter der Prozedur <b>ShowTables <\/b>bereit. Sie sollen mit der Prozedur n&auml;mlich nicht nur alle Tabellen ausgeben k&ouml;nnen, sondern auch nur alle lokalen Tabellen, alle ODBC-Tabellen oder auch nur die verkn&uuml;pften Tabellen.<\/p>\n<p>Um nur die lokalen Tabellen auszugeben, geben Sie etwa den folgenden Befehl im Direktfenster ein:<\/p>\n<pre>ShowTables dbLocal<\/pre>\n<p>Aber es gibt noch weitere M&ouml;glichkeiten, die auszugebenden Tabellen einzuschr&auml;nken: Mit dem zweiten Parameter namens <b>bolSystem<\/b> legen Sie fest, ob Systemtabellen ausgegeben werden sollen. Der dritte Parameter <b>bolHidden <\/b>gibt schlie&szlig;lich an, ob auch versteckte Dateien in der Liste erscheinen sollen. Da beide Parameter standardm&auml;&szlig;ig auf den Wert <b>True <\/b>eingestellt sind, m&uuml;ssten Sie etwa den folgenden Aufruf verwenden, um nur die lokalen Tabellen ohne versteckte Tabellen und Systemtabellen auszugeben:<\/p>\n<pre>ShowTables dbLocal, False, <span style=\"color:blue;\">False<\/span><\/pre>\n<p>Die Prozedur pr&uuml;ft zun&auml;chst, ob der Benutzer eines der Enumeration-Elemente zur Einschr&auml;nkung des Tabellentyps angegeben hat. Falls nicht, ist <b>intType = 0 <\/b>und wir k&ouml;nnen intType per logischer Und-Verkn&uuml;pfung auf alle Typen einstellen (<b>dbLocal + dbODBC + dbLinked<\/b>).<\/p>\n<p>Danach &ouml;ffnet die Prozedur ein Recordset mit allen Tabellen auf Basis der Systemtabelle <b>MSysObjects<\/b>. Man k&ouml;nnte zwar auch die <b>TableDefs<\/b>-Auflistung verwenden, um auf die Tabellen zuzugreifen, aber mit <b>MSysObjects <\/b>k&ouml;nnen wir die Tabellen direkt alphabetisch sortieren.<\/p>\n<p>Die Abfrage enth&auml;lt direkt einen Filter nach den entsprechenden Objekttypen &#8211; hier <b>1 <\/b>f&uuml;r lokale Tabellen, <b>4 <\/b>f&uuml;r ODBC-Tabellen und <b>6 <\/b>f&uuml;r eingebundene Tabellen.<\/p>\n<p>Damit wir eine saubere Darstellung in zwei Spalten erreichen, ben&ouml;tigen wir noch die maximale L&auml;nge der Tabellennamen. Diese holt die Prozedur mit einer <b>DMax<\/b>-Abfrage &uuml;ber den Ausdruck <b>Len(Name) <\/b>f&uuml;r die Tabelle <b>MSysObjects<\/b>.<\/p>\n<p>Danach bildet die Prozedur die Spalten&uuml;berschriften im Direktfenster ab, wobei nach einer Leerzeile die beiden &uuml;berschriften <b>Table <\/b>und <b>Type <\/b>folgen. Den Abstand dazwischen liefert die <b>Space<\/b>-Funktion, die den Text <b>Type <\/b>so platziert, dass er knapp rechts neben dem l&auml;ngsten Tabellennamen landet. Auch die Anzahl der als Linie dienenden Minuszeichen wird anhand der L&auml;nge des l&auml;ngsten Tabellennamens ermittelt.<\/p>\n<p>Danach steigt die Prozedur in eine <b>Do While<\/b>-Schleife &uuml;ber alle Datens&auml;tze des Recordsets <b>rst <\/b>ein. Darin erg&auml;nzt sie den Inhalt des Feldes Name des Recordsets um die entsprechende Menge Leerzeichen, damit alle Tabellennamen die L&auml;nge des l&auml;ngsten Namens haben, und speichert das Ergebnis in der Variablen <b>strTable<\/b>.<\/p>\n<p>Dann stellt sie die Variable <b>bolShow <\/b>auf <b>True <\/b>ein. Diese legt fest, ob die Tabelle aus dem aktuellen Datensatz ausgegeben wird, und kann in den folgenden Pr&uuml;fungen noch auf <b>False <\/b>eingestellt werden.<\/p>\n<p>Zun&auml;chst jedoch k&uuml;mmern wir uns darum, ob es sich um eine Systemtabelle handelt. Zun&auml;chst gehen wir nicht davon aus und setzen die Variable <b>strSystem <\/b>auf eine leere Zeichenkette. Sollte die Tabelle sich allerdings als Systemtabelle herausstellen, was die Prozedur durch den Vergleich der Eigenschaft <b>Attributes <\/b>des entsprechenden Eintrags der Auflistung <b>TableDefs <\/b>mit der Konstanten <b>dbSystemObject <\/b>herausfindet, erh&auml;lt <b>strSystem <\/b>den Wert <b>|System<\/b>. Dieser wird sp&auml;ter an einen Ausdruck angeh&auml;ngt, der den Typ der Tabelle charakterisiert.<\/p>\n<p>Sollte der Benutzer f&uuml;r den Parameter <b>bolSystem <\/b>jedoch den Wert <b>False <\/b>&uuml;bergeben haben, was bedeutet, dass er keine Systemtabellen in der Ausgabeliste w&uuml;nscht, stellt die Prozedur nun die Variable <b>bolShow <\/b>ebenfalls auf <b>False <\/b>ein.<\/p>\n<p>Danach folgt das gleiche Spiel f&uuml;r versteckte Tabellen. Diesmal wird die Variable <b>strHidden <\/b>gegebenenfalls mit dem Wert <b>|Hidden <\/b>gef&uuml;llt, falls es sich bei der Tabelle um eine versteckte Tabelle handelt, und die Variable <b>bolShow <\/b>erh&auml;lt den Wert <b>False<\/b>, wenn der Parameter <b>bolHidden <\/b>auch diesen Wert enth&auml;lt.<\/p>\n<p>Schlie&szlig;lich entscheidet der Wert von <b>bolShow <\/b>dar&uuml;ber, ob die Tabelle in der Ausgabe landet. Hat die Variable den Wert <b>False<\/b>, geschieht nichts weiter, anderenfalls werden die verschiedenen Tabellentypen anhand des Wertes des Feldes <b>Type <\/b>des Recordsets entweder ausgegeben oder nicht.<\/p>\n<p>Schauen wir uns das f&uuml;r den ersten <b>Case<\/b>-Zweig der <b>Select Case<\/b>-Anweisung an: Hat <b>rst!Type <\/b>den Wert <b>1<\/b>, was auf eine lokale Tabelle hindeutet, pr&uuml;ft die Prozedur durch eine logische Konjunktion, ob der mit <b>intType <\/b>&uuml;bergebene Wert die Konstante <b>dbLocal <\/b>enth&auml;lt (mehr &uuml;ber logische Konjunktionen erfahren Sie im Beitrag <b>Rund um Bin&auml;rzahlen<\/b>, <b>www.access-im-unternehmen.de\/556<\/b>).<\/p>\n<p>In diesem Fall erh&auml;lt die Variable <b>strType <\/b>den Wert <b>Local Table<\/b>. Au&szlig;erdem gibt eine <b>Debug.Print<\/b>-Anweisung den Namen der Tabelle (zuz&uuml;glich der weiter oben hinzugef&uuml;gten Leerzeichen) und die Inhalte der Variablen <b>strType<\/b>, <b>strSystem <\/b>und <b>strHidden <\/b>aus. Letztere k&ouml;nnten beispielsweise den Wert <b>|Local Table|System|Hidden <\/b>liefern, wenn es sich um eine lokale, versteckte Systemtabelle handelt.<\/p>\n<p>Die beiden &uuml;brigen <b>Case<\/b>-Zweige erledigen dies &auml;hnlich f&uuml;r ODBC-Tabellen und verkn&uuml;pfte Tabellen.<\/p>\n<p>Auf diese Weise gibt die Prozedur Informationen &uuml;ber alle Tabellen im Direktfenster aus.<\/p>\n<p><b>Tabellenbeschreibungen<\/b><\/p>\n<p>Die zweite Prozedur soll &auml;hnliche Informationen liefern wie die Anweisung <b>Describe <Tabellenname> <\/b>unter MySQL. Dort sieht die Ausgabe beispielsweise wie in Bild 2 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_01\/pic_968_002.png\" alt=\"Beschreibung einer Tabelle unter MySQL\" width=\"575\" height=\"286,4151\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Beschreibung einer Tabelle unter MySQL<\/span><\/b><\/p>\n<p>Das k&ouml;nnen wir allerdings auch: Die nachfolgend beschriebene Prozedur namens <b>Describe<\/b> liefert etwa die Ausgabe aus Bild 3.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_01\/pic_968_003.png\" alt=\"Baugleiche Beschreibung im Direktbereich des VBA-Editors\" width=\"575\" height=\"265,8334\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Baugleiche Beschreibung im Direktbereich des VBA-Editors<\/span><\/b><\/p>\n<p>Den ersten Teil der Prozedur, die diese Ausgabe liefert, finden Sie in Listing 2. Die Prozedur nimmt mit dem Parameter <b>strTable <\/b>den Namen der zu untersuchenden Tabelle entgegen. Sie f&uuml;llt die Variable <b>db <\/b>mit einem Verweis auf die aktuelle Datenbank. Die Auflistung <b>TableDefs <\/b>dieses Objekts liefert dann mit dem Namen der Tabelle als Parameter ein <b>TableDef<\/b>-Objekt, das die Beschreibung der Tabelle sowie Auflistungen etwa der Tabellenfelder liefert. Dieses referenzieren wir mit der Variablen <b>tdf<\/b>.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>Describe(strTable<span style=\"color:blue;\"> As String<\/span>)\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>fld<span style=\"color:blue;\"> As <\/span>DAO.Field\r\n     <span style=\"color:blue;\">Dim <\/span>intLen<span style=\"color:blue;\"> As Integer<\/span>, intLenDefault<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strType<span style=\"color:blue;\"> As String<\/span>, strNull<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>idx<span style=\"color:blue;\"> As <\/span>DAO.Index\r\n     <span style=\"color:blue;\">Dim <\/span>fldidx<span style=\"color:blue;\"> As <\/span>DAO.Field\r\n     <span style=\"color:blue;\">Dim <\/span>strIndex<span style=\"color:blue;\"> As String<\/span>, strExtra<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = Currentdb\r\n     <span style=\"color:blue;\">Set<\/span> tdf = db.TableDefs(strTable)\r\n     For Each fld In tdf.Fields\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(fld.Name) &gt; intLen<span style=\"color:blue;\"> Then<\/span>\r\n             int<span style=\"color:blue;\">Len<\/span> = <span style=\"color:blue;\">Len<\/span>(fld.Name)\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(fld.DefaultValue) &gt; intLenDefault<span style=\"color:blue;\"> Then<\/span>\r\n             intLenDefault = <span style=\"color:blue;\">Len<\/span>(fld.DefaultValue)\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> fld\r\n     int<span style=\"color:blue;\">Len<\/span> = int<span style=\"color:blue;\">Len<\/span> + 2\r\n     <span style=\"color:blue;\">If <\/span>int<span style=\"color:blue;\">Len<\/span> &lt; 16<span style=\"color:blue;\"> Then<\/span>\r\n         int<span style=\"color:blue;\">Len<\/span> = 16\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     intLenDefault = intLenDefault + 2\r\n     <span style=\"color:blue;\">If <\/span>intLenDefault &lt; 7<span style=\"color:blue;\"> Then<\/span>\r\n         intLenDefault = 7\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Debug.Print<\/span> \"Table\" & Space(int<span style=\"color:blue;\">Len<\/span> - 5) _\r\n         & \"| Type          | NULL | Key | DEFAULT\" & Space(intLenDefault - 7) _\r\n         & \" | EXTRA\"\r\n     <span style=\"color:blue;\">Debug.Print<\/span> \"-----\" & String(int<span style=\"color:blue;\">Len<\/span> - 5, \"-\") & \"+---------------+------+-----+-\" _\r\n         & String(intLenDefault - 7, \"-\") & \"--------+------------------\"\r\n     For Each fld In tdf.Fields\r\n         strType = \"\"\r\n         Select Case fld.Type\r\n             <span style=\"color:blue;\">Case <\/span>dbAttachment\r\n                 strType = \"ATTACHMENT\"\r\n             <span style=\"color:blue;\">Case <\/span>dbBoolean\r\n                 strType = \"BOOLEAN\"\r\n             <span style=\"color:blue;\">Case <\/span>dbCurrency\r\n                 strType = \"CURRENCY\"\r\n             <span style=\"color:blue;\">Case <\/span>dbDate\r\n                 strType = \"DATE\"\r\n             <span style=\"color:blue;\">Case <\/span>dbDouble\r\n                 strType = \"DOUBLE\"\r\n             <span style=\"color:blue;\">Case <\/span>dbGUID\r\n                 strType = \"GUID\"\r\n             <span style=\"color:blue;\">Case <\/span>dbInteger\r\n                 strType = \"INTEGER\"<\/pre>\n<p><!--30percent--><\/p>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Ausgabe der Felder einer Tabelle im Direktfenster des VBA-Editors (Teil I)<\/span><\/b><\/p>\n<p><b>Zeichenl&auml;nge von Feldnamen und Standardwerten bestimmen<\/b><\/p>\n<p>Im ersten Schritt durchlaufen wir alle Felder der Tabelle in einer <b>For Each<\/b>-Schleife &uuml;ber die Auflsitung <b>Fields<\/b>. Das jeweils aktuelle Element landet in der Variablen <b>fld<\/b>.<\/p>\n<p>Hier nehmen wir erstmal grundlegende Informationen auf, damit wir sp&auml;ter die Breite der Spalten optimal auslegen k&ouml;nnen.<\/p>\n<p>Die erste Information ist die Anzahl der Zeichen des l&auml;ngsten Feldnamens der Tabelle. Innerhalb der <b>For Each<\/b>-Schleife pr&uuml;ft die Prozedur jeweils, ob die L&auml;nge des Feldnamens gr&ouml;&szlig;er als die bereits in der Variablen <b>intLen <\/b>gespeicherte L&auml;nge ist.<\/p>\n<p>Falls ja, landet die L&auml;nge des aktuellen Feldnamens in dieser Variablen. Nach dem Durchlaufen der Schleife enth&auml;lt <b>intLen <\/b>somit die Anzahl der Zeichen des l&auml;ngsten Feldnamens.<\/p>\n<p>Auf &auml;hnliche Weise ermittelt die Prozedur anschlie&szlig;end die L&auml;nge des l&auml;ngsten Ausdrucks f&uuml;r die Eigenschaft <b>DefaultValue <\/b>(zu deutsch: <b>Standardwert<\/b>) und speichert diese in der Variablen <b>intLenDefault<\/b>.<\/p>\n<p>Danach wird <b>intLen <\/b>um zwei erh&ouml;ht, weil wir auf jeder Seite ein Zeichen Platz einr&auml;umen m&ouml;chten.<\/p>\n<p>Sollte das Feld mit dem l&auml;ngsten Feldnamen weniger als 16 Zeichen aufweisen, stellen wir <b>intLen <\/b>auf <b>16 <\/b>ein.<\/p>\n<p>Das Gleiche erledigt die Prozedur f&uuml;r die Variable <b>intLenDefault<\/b>, nur dass hier die Mindestzeichenl&auml;nge sieben betr&auml;gt.<\/p>\n<p>Damit k&ouml;nnen wir nun bereits die Spalten&uuml;berschriften im Direktfenster ausgeben. Die Ausgabe besteht zun&auml;chst aus der Spalten&uuml;berschrift Table, gefolgt von einer Reihe von Leerzeichen. Die Anzahl richtet sich nach der Anzahl Zeichen des l&auml;ngsten Feldnamens, die <b>Space<\/b>-Funktion sorgt f&uuml;r die Ausgabe der entsprechenden Leerzeichen. Dann folgen die Spalten&uuml;berschriften <b>Type<\/b>, <b>NULL<\/b>, <b>KEY<\/b>, <b>DEFAULT <\/b>und <b>EXTRA<\/b>, jeweils durch das Pipe-Zeichen (|) voneinander getrennt. Auch hinter der Spalte <b>DEFAULT <\/b>f&uuml;gt die Anweisung einige Leerzeichen ein &#8211; hier in Abh&auml;ngigkeit vom Wert der Variablen <b>intLenDefault<\/b>.<\/p>\n<p>Danach folgt die Trennlinie zwischen den Spalten&uuml;berschriften und den eigentlichen Werten. Dabei ber&uuml;cksichtigen wir wieder die variable Breite der Spalten f&uuml;r die Feldnamen und die Standardwerte, diesmal durch den Aufruf der <b>String<\/b>-Funktion, welche die ben&ouml;tigte Anzahl Minus-Zeichen liefert. Die &uuml;berg&auml;nge von einem Spaltenkopf zum n&auml;chsten sind mit Plus-Zeichen versehen.<\/p>\n<p><b>Felddatentypen bestimmen<\/b><\/p>\n<p>Anschlie&szlig;end folgt eine weitere <b>For Each<\/b>-Schleife &uuml;ber alle Felder des <b>TableDef<\/b>-Objekts. Diesmal enth&auml;lt diese einige Anweisungen zum Ermitteln der Feldeigenschaften sowie die Ausgabe der Informationen im Direktfenster.<\/p>\n<p>Die erste Anweisung innerhalb der Schleife leert die Variable <b>strType<\/b>. Diese nimmt gleich den Felddatentyp des aktuellen Feldes auf. Diesen ermittelt die Prozedur in einer <b>Select Case<\/b>-Bedingung. Je nach dem Wert der Eigenschaft Type des <b>Field<\/b>-Objekts tr&auml;gt die Prozedur Werte wie <b>ATTACHMENT<\/b>, <b>BOOLEAN <\/b>oder <b>CURRENCY <\/b>in <b>strType <\/b>ein. Dies setzt sich im zweiten Teil der Prozedur, den Sie in Listing 3 finden, fort.<\/p>\n<pre>             <span style=\"color:blue;\">Case <\/span>dbLong\r\n                 strType = \"LONG\"\r\n             <span style=\"color:blue;\">Case <\/span>dbLongBinary\r\n                 strType = \"LONGBINARY\"\r\n             <span style=\"color:blue;\">Case <\/span>dbMemo\r\n                 strType = \"MEMO\"\r\n             <span style=\"color:blue;\">Case <\/span>dbSingle\r\n                 strType = \"SINGLE\"\r\n             <span style=\"color:blue;\">Case <\/span>dbText\r\n                 strType = \"TEXT\"\r\n             <span style=\"color:blue;\">Case Else<\/span>\r\n                 <span style=\"color:blue;\">Debug.Print<\/span> fld.Type\r\n         <span style=\"color:blue;\">End Select<\/span>\r\n         strType = strType & Space(13 - <span style=\"color:blue;\">Len<\/span>(strType))\r\n         <span style=\"color:blue;\">If <\/span>fld.Required<span style=\"color:blue;\"> Then<\/span>\r\n             strNull = \"NO  \"\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             strNull = \"YES \"\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         strIndex = \"   \"\r\n         For Each idx In tdf.Indexes\r\n             For Each fldidx In idx.Fields\r\n                 <span style=\"color:blue;\">If <\/span>fldidx.Name = fld.Name<span style=\"color:blue;\"> Then<\/span>\r\n                     <span style=\"color:blue;\">If <\/span>idx.Primary<span style=\"color:blue;\"> Then<\/span>\r\n                         strIndex = \"PRI\"\r\n                     <span style=\"color:blue;\">Else<\/span>\r\n                         <span style=\"color:blue;\">If <\/span>idx.Unique<span style=\"color:blue;\"> Then<\/span>\r\n                             strIndex = \"UNI\"\r\n                         <span style=\"color:blue;\">End If<\/span>\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> fldidx\r\n         <span style=\"color:blue;\">Next<\/span> idx\r\n         strExtra = \"\"\r\n         <span style=\"color:blue;\">If <\/span>(fld.Attributes And dbAutoIncrField) = dbAutoIncrField<span style=\"color:blue;\"> Then<\/span>\r\n             strExtra = strExtra & \", AUTOINCREMENT\"\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(strExtra) &gt; 0<span style=\"color:blue;\"> Then<\/span>\r\n             strExtra = <span style=\"color:blue;\">Mid<\/span>(strExtra, 3)\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">Debug.Print<\/span> fld.Name & Space(int<span style=\"color:blue;\">Len<\/span> - <span style=\"color:blue;\">Len<\/span>(fld.Name)) & \"| \" & strType _\r\n             & \" | \" & strNull & \" | \" & strIndex & \" | \" & fld.DefaultValue _\r\n             & Space(intLenDefault - <span style=\"color:blue;\">Len<\/span>(fld.DefaultValue)) & \" | \" & strExtra\r\n     <span style=\"color:blue;\">Next<\/span> fld\r\n     <span style=\"color:blue;\">Debug.Print<\/span> \"-----\" & String(int<span style=\"color:blue;\">Len<\/span> - 5, \"-\") & \"+---------------+------+-----+-\" _\r\n         & String(intLenDefault - 7, \"-\") & \"--------+------------------\"\r\n     <span style=\"color:blue;\">Debug.Print<\/span> tdf.Fields.Count & \" Fields\"\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Ausgabe der Felder einer Tabelle im Direktfenster des VBA-Editors (Teil II)<\/span><\/b><\/p>\n<p>Anschlie&szlig;end f&uuml;llt die Prozedur den Inhalt von <b>strType <\/b>so mit Leerzeichen auf, dass die Gesamtl&auml;nge der enthaltenen Zeichenkette <b>13 <\/b>betr&auml;gt.<\/p>\n<p>Nun folgt die Spalte, die angibt, ob das Feld Null-Werte enthalten darf oder nicht. Dies ermittelt die Prozedur mit der Eigenschaft <b>Required<\/b>. Hat diese den Wert <b>True<\/b>, erh&auml;lt <b>strNull <\/b>den Wert <b>NO<\/b>, anderenfalls den Wert <b>YES<\/b>. <b>NO <\/b>enth&auml;lt noch ein folgendes Leerzeichen, damit beide Werte drei Zeichen lang sind.<\/p>\n<p>Danach folgen die Indizes, in diesem Fall k&uuml;mmern wir uns allerdings lediglich um Prim&auml;rschl&uuml;ssel und eindeutige Indizes. Der entsprechende Ausdruck soll in der Variablen <b>strIndex <\/b>landen, die vorab mit drei Leerzeichen gef&uuml;llt wird. Warum nicht einfach mit einer leeren Zeichenkette Weil es auch sein kann, dass kein Index f&uuml;r dieses Feld festgelegt wurde &#8211; und dann ben&ouml;tigen wir eine entsprechend lange Zeichenkette, damit die Spalte die gew&uuml;nschte Breite einh&auml;lt.<\/p>\n<p>Um die Indizes und deren Typ zu ermitteln, durchl&auml;uft die Prozedur zun&auml;chst die <b>Indexes<\/b>-Auflistung des jeweiligen <b>TableDef<\/b>-Objekts. Jedes <b>Index<\/b>-Objekt enth&auml;lt wiederum eine Auflistung der Felder, die zum Index geh&ouml;ren. Diese durchlaufen wir ebenfalls. Innerhalb der inneren <b>For Each<\/b>-Schleife vergleicht die Prozedur dann den Namen des Feldes des Indexes mit dem Namen des aktuellen Tabellenfeldes. Stimmen beide &uuml;berein, haben wir einen Index gefunden, der sich auf das aktuelle Tabellenfeld bezieht. Nun wollen wir noch herausfinden, um welche Art von Index es sich handelt. Hat die Eigenschaft <b>Primary <\/b>des Index-Objekts den Wert <b>True<\/b>, handelt es sich um einen Prim&auml;rschl&uuml;ssel.<\/p>\n<p>Dies vermerken wir mit dem Wert <b>PRI <\/b>in der Variablen <b>strIndex<\/b>. Liegt kein Prim&auml;rindex vor, pr&uuml;fen wir den Index auf Eindeutigkeit. Diese Information liefert die Eigenschaft <b>Unique<\/b>.<\/p>\n<p>Liegt ein eindeutiger Index vor, soll <b>strIndex <\/b>den Wert <b>UNI <\/b>erhalten. Das war es f&uuml;r die Indizes &#8211; weitere Indexarten k&ouml;nnen Sie nach Wunsch erg&auml;nzen.<\/p>\n<p>Fehlt noch eine Spalte, die weitere Informationen aufnimmt &#8211; in unserem Fall zun&auml;chst nur den Wert <b>AUTOINCREMENT<\/b> f&uuml;r die Variable <b>strExtra<\/b>, falls es sich um ein <b>Autowert<\/b>-Feld handelt. Auch hier k&ouml;nnen Sie noch weitere Elemente hinzuf&uuml;gen.<\/p>\n<p>Schlie&szlig;lich haben wir alle wichtigen Informationen gesammelt. Diese geben wir nun je Feld in einer einzigen <b>Debug.Print<\/b>-Anweisung aus. Dabei werden wiederum die Spaltenbreiten durch gezielten Einsatz der <b>Space<\/b>-Funktion angepasst.<\/p>\n<p>Zu guter Letzt folgt eine Zeile mit einer Linie sowie eine mit der Anzahl der Felder in dieser Tabelle.<\/p>\n<p><b>Feldwerte eines Datensatzes<\/b><\/p>\n<p>W&auml;hrend die ersten beiden Prozeduren eher Informationen liefern, die man beim Programmieren mal eben abruft, folgen nun einige Beispiele, mit denen Sie auch beim Debuggen arbeiten k&ouml;nnen. Diese liefern n&auml;mlich konkrete Informationen zu den Werten, mit denen etwa die Felder des aktuellen Datensatzes gef&uuml;llt sind.<\/p>\n<p>Daher erwarten die folgenden Prozeduren auch die &uuml;bergabe von Objektverweisen als Parameter und nicht nur die Namen etwa einer Tabelle oder eines Feldes.<\/p>\n<p>Stellen Sie sich vor, Sie debuggen eine soeben programmierte Prozedur, weil scheinbar etwas mit den Werten eines  Recordsets nicht stimmt &#8211; etwa an einer Stelle wie in Bild 4.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_01\/pic_968_004.png\" alt=\"Sie wollen an dieser Stelle die Feldinhalte erfahren\" width=\"575\" height=\"250,7979\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Sie wollen an dieser Stelle die Feldinhalte erfahren<\/span><\/b><\/p>\n<p>Normalerweise w&uuml;rden Sie dann manuell die entsprechenden Informationen im Direktfenster ausgeben lassen:<\/p>\n<pre><span style=\"color:blue;\">Debug.Print<\/span> rst!Artikelname<\/pre>\n<p>Dies setzt nat&uuml;rlich voraus, dass Sie den betroffenen Feldnamen kennen. Sonst arbeiten Sie sich vielleicht mit der folgenden Anweisung durch die einzelnen Felder:<\/p>\n<pre><span style=\"color:blue;\">Debug.Print<\/span> rst(0).Name, rst(0).Value<\/pre>\n<p>Dies ist zeitraubend, vor allem, wenn Sie dies &ouml;fter erledigen m&uuml;ssen. Wie w&auml;re es denn, wenn Sie diese Informationen wie in Bild 5 f&uuml;r alle Felder des aktuellen Recordsets mit einer einzigen Anweisung im Direktfenster ausgeben k&ouml;nnten<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_01\/pic_968_005.png\" alt=\"Feldnamen und -werte des aktuellen Recordsets mit einer einzigen Anweisung im Direktfenster ausgeben\" width=\"575\" height=\"250,3044\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Feldnamen und -werte des aktuellen Recordsets mit einer einzigen Anweisung im Direktfenster ausgeben<\/span><\/b><\/p>\n<p>Das h&auml;tte mir zu mancher Gelegenheit jedenfalls eine Menge Zeit gespart. Also schauen wir uns die Prozedur <b>RecordsetValues<\/b> an, die wie in Listing 4 aussieht.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>RecordsetValues(rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset)\r\n     <span style=\"color:blue;\">Dim <\/span>fld<span style=\"color:blue;\"> As <\/span>DAO.Field\r\n     <span style=\"color:blue;\">Dim <\/span>intLen<span style=\"color:blue;\"> As Integer<\/span>\r\n     For Each fld In rst.Fields\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(fld.Name) &gt; intLen<span style=\"color:blue;\"> Then<\/span>\r\n             int<span style=\"color:blue;\">Len<\/span> = <span style=\"color:blue;\">Len<\/span>(fld.Name)\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         int<span style=\"color:blue;\">Len<\/span> = int<span style=\"color:blue;\">Len<\/span> + 2\r\n         <span style=\"color:blue;\">If <\/span>int<span style=\"color:blue;\">Len<\/span> &lt; 15<span style=\"color:blue;\"> Then<\/span>\r\n             int<span style=\"color:blue;\">Len<\/span> = 15\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> fld\r\n     <span style=\"color:blue;\">Debug.Print<\/span> \"FIELD\" & Space(int<span style=\"color:blue;\">Len<\/span> - 4) & \"| VALUE\"\r\n     <span style=\"color:blue;\">Debug.Print<\/span> \"-----\" & String(int<span style=\"color:blue;\">Len<\/span> - 4, \"-\") & \"+--------------------\"\r\n     For Each fld In rst.Fields\r\n         <span style=\"color:blue;\">Debug.Print<\/span> fld.Name & Space(int<span style=\"color:blue;\">Len<\/span> - <span style=\"color:blue;\">Len<\/span>(fld.Name)) & \" | \" & fld.Value\r\n     <span style=\"color:blue;\">Next<\/span> fld\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Ausgabe des Inhalts eines Recordsets im Direktfenster<\/span><\/b><\/p>\n<p>Die Prozedur erwartet ein Objekt des Typs <b>Recordset <\/b>als Parameter, was bedeutet, dass diese auch nur beim Debuggen einer Routine aufgerufen werden kann, welche einen Verweis auf das zu untersuchende Recordset enth&auml;lt. Die Prozedur untersucht in einem ersten Durchlauf &uuml;ber alle Felder des Recordsets die L&auml;nge der Feldnamen und speichert die maximale L&auml;nge in der Variablen <b>intLen<\/b>. Diese sollte mindestens 15 Zeichen betragen. Dann gibt sie die Spalten&uuml;berschriften sowie eine Zeile mit einer Trennlinie im Direktfenster aus. Danach folgen die eigentlichen Informationen, f&uuml;r welche die Prozedur nochmals alle Felder in einer <b>For Each<\/b>-Schleife durchl&auml;uft. Dabei gibt sie per <b>Debug.Print <\/b>jeweils den Namen des Feldes sowie den Inhalt (<b>Value<\/b>) im Direktfenster aus. Der Feldname wird um eine entsprechende Menge Leerzeichen erg&auml;nzt, damit die durch Pipe-Zeichen (<b>|<\/b>) angedeutete vertikale Linie und die Werte dahinter f&uuml;r die einzelnen Felder untereinander abgebildet werden.<\/p>\n<p><b>Formulareigenschaften ausgeben<\/b><\/p>\n<p>Praktisch ist es auch, sich mal eben eine Liste der Eigenschaften des Formulars ausgeben zu lassen. W&auml;hrend man das Formular ausprobiert, ist das Eigenschaftsfenster ja seit Access 2007 immer ausgeblendet, vorher konnte man dieses noch w&auml;hrend der Laufzeit anzeigen. Also behelfen wir uns wiederum mit einer Hilfsprozedur, welche die Eigenschaften eines Formulars ausgibt. Das Ergebnis sieht &#8211; ausschnittsweise &#8211; wie in Bild 6 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_01\/pic_968_006.png\" alt=\"Ausgabe von Formulareigenschaften im Direktfenster\" width=\"575\" height=\"304,5662\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Ausgabe von Formulareigenschaften im Direktfenster<\/span><\/b><\/p>\n<p>Sie sehen hier, dass die Prozedur <b>FormProperties <\/b>komplett ohne Parameter aufgerufen wurde. Wie soll sie denn dann wissen, f&uuml;r welches Formular sie die Eigenschaften liefern soll Ganz einfach: Wenn Sie keinen Formularnamen mit dem ersten Parameter &uuml;bergeben, versucht die Prozedur, einfach das aktuelle Formular zu referenzieren.<\/p>\n<p>Die Prozedur <b>FormProperties <\/b>finden Sie in Listing 5. Sie erwartet neben dem optionalen Parameter zur &uuml;bergabe des Formularnamens noch einen weiteren optionalen Parameter. Mit diesem k&ouml;nnen Sie festlegen, ob Ereigniseigenschaften ausgegeben werden sollen oder nicht. Der Hintergrund ist einfach: Der Platz im Direktfenster reicht sonst nicht f&uuml;r alle Eigenschaften aus. Die Ereigniseigenschaften scheinen mir recht unwichtig zu sein, daher habe ich die Option eingebaut, diese wegzulassen &#8211; was auch standardm&auml;&szlig;ig geschieht. Wenn die Ereigniseigenschaften auch ausgegeben werden sollen, &uuml;bergeben Sie den Wert <b>True <\/b>f&uuml;r den zweiten Parameter.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>FormProperties(<span style=\"color:blue;\">Optional<\/span> strForm<span style=\"color:blue;\"> As String<\/span>, _\r\n         <span style=\"color:blue;\">Optional<\/span> bolEvents<span style=\"color:blue;\"> As Boolean<\/span> = <span style=\"color:blue;\">False<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>prp<span style=\"color:blue;\"> As <\/span>Property, intLen<span style=\"color:blue;\"> As Integer<\/span>, col<span style=\"color:blue;\"> As <\/span>Collection\r\n     <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As Integer<\/span>, bolPrint<span style=\"color:blue;\"> As Boolean<\/span>, frm<span style=\"color:blue;\"> As <\/span>Form\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(strForm) = 0<span style=\"color:blue;\"> Then<\/span>\r\n         On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> frm = Screen.ActiveForm\r\n         <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n         <span style=\"color:blue;\">If <\/span>frm Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">Debug.Print<\/span> \"Kein Formular &uuml;bergeben\/markiert.\"\r\n             <span style=\"color:blue;\">Exit Sub<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> frm = Forms(strForm)\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> col = <span style=\"color:blue;\">New<\/span> Collection\r\n     For Each prp In frm.Properties\r\n         bolPrint = <span style=\"color:blue;\">True<\/span>\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> bolEvents<span style=\"color:blue;\"> Then<\/span>\r\n             If <span style=\"color:blue;\">Left<\/span>(prp.Name, 5) = \"After\" Or <span style=\"color:blue;\">Left<\/span>(prp.Name, 6) = \"Before\" _\r\n                     Or <span style=\"color:blue;\">Left<\/span>(prp.Name, 2) = \"On\" Then\r\n                 bolPrint = <span style=\"color:blue;\">False<\/span>\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">If <\/span>bolPrint<span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(prp.Name) &gt; intLen<span style=\"color:blue;\"> Then<\/span> int<span style=\"color:blue;\">Len<\/span> = <span style=\"color:blue;\">Len<\/span>(prp.Name)\r\n             For i = 1 To col.Count\r\n                 <span style=\"color:blue;\">If <\/span>prp.Name &lt; col(i)<span style=\"color:blue;\"> Then<\/span>\r\n                     <span style=\"color:blue;\">Exit For<\/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;\">If <\/span>col.Count = 0 Or col.Count &lt; i<span style=\"color:blue;\"> Then<\/span>\r\n                 col.Add prp.Name, prp.Name\r\n             <span style=\"color:blue;\">Else<\/span>\r\n                 col.Add prp.Name, prp.Name, col(i)\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> prp\r\n     int<span style=\"color:blue;\">Len<\/span> = int<span style=\"color:blue;\">Len<\/span> + 2\r\n     <span style=\"color:blue;\">If <\/span>int<span style=\"color:blue;\">Len<\/span> &lt; 15<span style=\"color:blue;\"> Then<\/span> int<span style=\"color:blue;\">Len<\/span> = 15\r\n     <span style=\"color:blue;\">Debug.Print<\/span> \"PROPERTY\" & Space(int<span style=\"color:blue;\">Len<\/span> - 8) & \"| VALUE\"\r\n     <span style=\"color:blue;\">Debug.Print<\/span> String(intLen, \"-\") & \"+\" & String(30, \"-\")\r\n     For i = 1 To col.Count\r\n         <span style=\"color:blue;\">Debug.Print<\/span> col(i) & Space(int<span style=\"color:blue;\">Len<\/span> - <span style=\"color:blue;\">Len<\/span>(col(i))) & \"| \" _\r\n             & frm.Properties(col(i)).Value\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 5: Ausgabe der Eigenschaften eines Formulars im Direktfenster<\/span><\/b><\/p>\n<p>Die Prozedur pr&uuml;ft zun&auml;chst, ob der Benutzer den Namen des zu untersuchenden Formulars mit &uuml;bergeben hat. Falls nicht, versucht die Prozedur, das aktuelle Formular zu ermitteln und zu referenzieren. Gelingt auch dies nicht, liefert sie eine entsprechende Ausgabe im Direktfenster.<\/p>\n<p>Hat der Benutzer einen Formularnamen &uuml;bergeben, versucht die Prozedur, dieses zu referenzieren. Gelingt dies nicht (im Listing aus Platzgr&uuml;nden nicht abgebildet), erscheint ebenfalls eine entsprechende Meldung.<\/p>\n<p><b>Alphabetische Sortierung<\/b><\/p>\n<p>Da ein Formular eine gro&szlig;e Menge Eigenschaften besitzt, sollen diese in alphabetischer Reihenfolge ausgegeben werden. Um diese Sortierung k&uuml;mmern sich die folgenden Zeilen.<\/p>\n<p>Diese instanzieren zun&auml;chst ein <b>Collection<\/b>-Objekt. Danach durchl&auml;uft die Prozedur in einer Schleife alle <b>Properties <\/b>des Formulars. Die Variable <b>bolPrint <\/b>wird hier zun&auml;chst auf den Wert <b>True <\/b>eingestellt. Wir ben&ouml;tigen diese, um festzulegen, ob es sich um eine Ereigniseigenschaft handelt, die ja gegebenenfalls nicht mit ausgegeben werden soll. Hat der Benutzer <b>bolEvents <\/b>auf <b>False <\/b>belassen, pr&uuml;ft die Prozedur f&uuml;r das aktuelle <b>Property<\/b>-Objekt, ob dessen <b>Name<\/b>-Eigenschaft einen Wert liefert, der mit <b>After<\/b>, <b>Before <\/b>oder <b>On <\/b>beginnt &#8211; dies ist nur bei Ereigniseigenschaften der Fall. Trifft dies zu, stellt sie <b>bolPrint <\/b>auf <b>False <\/b>ein.<\/p>\n<p>Hat <b>bolPrint <\/b>danach den Wert <b>False<\/b>, &uuml;berspringt die <b>For Each<\/b>-Schleife die weitere Verarbeitung dieser Eigenschaft.<\/p>\n<p>Anderenfalls folgt nun die bereits bekannte Vorgehensweise zum Ermitteln der L&auml;nge des l&auml;ngsten Eintrags der ersten Spalte, hier der Eigenschaftsnamen.<\/p>\n<p>Parallel k&uuml;mmert sich die Prozedur darum, die Eigenschaftsnamen in der richtigen Reihenfolge in das <b>Collection<\/b>-Objekt einzusortieren. Dazu durchl&auml;uft die Prozedur in einer <b>For&#8230;Next<\/b>-Schleife alle bisher in der Collection angelegten Objekte und pr&uuml;ft, ob der aktuelle Eigenschaftsname (<b>prp.Name<\/b>) kleiner als der aktuelle <b>Collection<\/b>-Eintrag ist (<b>col(i)<\/b>). Ist dies der Fall, verl&auml;sst die Prozedur die <b>For&#8230;Next<\/b>-Schleife.<\/p>\n<p>Nun folgt eine Fallunterscheidung, ob die Collection gegebenenfalls noch leer ist &#8211; dann soll der Name der aktuellen Eigenschaft einfach hinten an die Collection angeh&auml;ngt werden. Dies ist auch der Fall, wenn in der vorherigen <b>For&#8230;Next<\/b>-Schleife die Bedingung <b>prp.Name < col(i) <\/b>nicht erf&uuml;llt wurde, was bedeutet, dass der neue Eigenschaftsname hinter den bisher vorhandenen Elementen einsortiert werden muss.<\/p>\n<p>Der <b>Else<\/b>-Teil der <b>If&#8230;Then<\/b>-Bedingung geht davon aus, dass die neue Eigenschaft irgendwo in der Collection einsortiert werden muss &#8211; und zwar genau an der Position, die dem Wert der Laufvariablen <b>i <\/b>entspricht.<\/p>\n<p>Wurde die vorherige <b>For&#8230;Next<\/b>-Schleife vorzeitig verlassen, beh&auml;lt <b>i <\/b>ja den zu dem Zeitpunkt festgelegten Wert. Dieser Wert entspricht dann der Position des Elements in der Collection, vor dem die neue Eigenschaft eingetragen werden muss.<\/p>\n<p>Damit kommen wir zur Ausgabe der Eigenschaften. Die Zeilen mit den Spalten&uuml;berschriften und der Trennlinie sind wie in den vorherigen Beispielen aufgebaut. Die Zeilen zur Ausgabe der Eigenschaften enthalten nun den Namen der Eigenschaft aus der Collection sowie den Wert, den die Prozedur &uuml;ber den Ausdruck <b>frm.Properties(col(i)).Value <\/b>ermittelt.<\/p>\n<p><b>Steuerelementeigenschaften ausgeben<\/b><\/p>\n<p>Eine &auml;hnliche Prozedur wollen wir nat&uuml;rlich auch f&uuml;r einzelne Steuerelemente nutzen. Hier k&ouml;nnen wir nun nicht einfach nur den Namen des Steuerelements &uuml;bergeben, sondern wir ben&ouml;tigen auch noch den Namen des Formulars, in dem sich das Steuerelement befindet.<\/p>\n<p>Beide Parameter sollen jedoch wieder optional sein: Wenn der Benutzer beispielsweise keine Parameter &uuml;bergibt, soll die Prozedur das aktuell aktive Steuerelement untersuchen. Alternativ kann er nur den Namen eines Steuerelements angeben, dann versucht die Prozedur, dieses Steuerelement im aktiven Formular zu finden. Nat&uuml;rlich kann der Benutzer auch sowohl den Formular- als auch den Steuerelementnamen &uuml;bergeben.<\/p>\n<p>Zus&auml;tzlich wollen wir die Anzahl der ausgegebenen Eigenschaften wieder eingrenzen k&ouml;nnen, indem wir die Ereigniseigenschaften nur optional ausgeben lassen.<\/p>\n<p>Die Prozedur <b>ControlProperties <\/b>erledigt diese Aufgabe f&uuml;r uns (s. Listing 6). Der erste Parameter nimmt den Namen des Steuerelements entgegen, der zweite den des Formulars, der dritte die Angabe, ob Ereigniseigenschaften mit ausgegeben werden sollen. Alle drei sind optionale Parameter.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>ControlProperties(<span style=\"color:blue;\">Optional<\/span> strControl<span style=\"color:blue;\"> As String<\/span>, _\r\n         <span style=\"color:blue;\">Optional<\/span> strForm<span style=\"color:blue;\"> As String<\/span>, <span style=\"color:blue;\">Optional<\/span> bolEvents<span style=\"color:blue;\"> As Boolean<\/span> = <span style=\"color:blue;\">False<\/span>)\r\n     ...\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(strControl) = 0<span style=\"color:blue;\"> Then<\/span>\r\n         On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> ctl = Screen.ActiveControl\r\n         <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n         <span style=\"color:blue;\">If <\/span>ctl Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">Debug.Print<\/span> \"Kein Steuerelement aktiv.\"\r\n             <span style=\"color:blue;\">Exit Sub<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(strForm) = 0<span style=\"color:blue;\"> Then<\/span>\r\n             On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n             <span style=\"color:blue;\">Set<\/span> ctl = Screen.ActiveForm.Controls(strControl)\r\n             <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n             <span style=\"color:blue;\">If <\/span>ctl Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n                 <span style=\"color:blue;\">Debug.Print<\/span> \"Steuerelement kann nicht gefunden werden.\"\r\n                 <span style=\"color:blue;\">Exit Sub<\/span>\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n             <span style=\"color:blue;\">Set<\/span> ctl = Forms(strForm).Controls(strControl)\r\n             <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n             <span style=\"color:blue;\">If <\/span>ctl Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n                 <span style=\"color:blue;\">Debug.Print<\/span> \"Steuerelement kann nicht gefunden werden.\"\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     ...\r\n     For i = 1 To col.Count\r\n         On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n         <span style=\"color:blue;\">Debug.Print<\/span> col(i) & Space(int<span style=\"color:blue;\">Len<\/span> - <span style=\"color:blue;\">Len<\/span>(col(i))) & \"| \" _\r\n             & ctl.Properties(col(i)).Value\r\n         Select Case Err.Number\r\n             <span style=\"color:blue;\">Case <\/span>0\r\n             <span style=\"color:blue;\">Case Else<\/span>\r\n                 <span style=\"color:blue;\">Debug.Print<\/span> col(i) & Space(int<span style=\"color:blue;\">Len<\/span> - <span style=\"color:blue;\">Len<\/span>(col(i))) & \"| \" _\r\n                     & Err.Description\r\n         <span style=\"color:blue;\">End Select<\/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 6: Ausgabe der Eigenschaften eines Steuerelements im Direktfenster<\/span><\/b><\/p>\n<p>Wir haben die Abbildung der Prozedur gek&uuml;rzt und zeigen nur die Teile, die sich  wesentlich von der Prozedur <b>FormProperties <\/b>unterscheiden. Dies betrifft zun&auml;chst die Pr&uuml;fung der Parameter und davon abh&auml;ngig das Referenzieren des entsprechenden Steuerelements.<\/p>\n<p>Die Prozedur pr&uuml;ft zun&auml;chst, ob <b>strControl<\/b> leer ist. Falls ja, versucht sie, mit <b>Screen.ActiveControl <\/b>das aktuelle Steuerelement zu referenzieren. Gelingt dies nicht, erscheint eine Meldung im Direktfenster. Wurde <b>strControl <\/b>angegeben, kann es sein, dass <b>strForm <\/b>auch angegeben wurde oder auch nicht.<\/p>\n<p>Falls nicht, ermittelt die Prozedur zun&auml;chst mit <b>Screen.ActiveForm <\/b>das aktuelle Formular und versucht, darin das Steuerelement mit dem in <b>strControl <\/b>&uuml;bergebenen Namen zu referenzieren.<\/p>\n<p>Anderenfalls versucht die Prozedur, das Steuerelement mit dem Namen <b>strControl <\/b>im Formular namens <b>strForm <\/b>zu ermitteln und dieses mit der Variablen <b>ctl <\/b>zu referenzieren.<\/p>\n<p>Gelingt einer dieser Versuche nicht, erscheint ebenfalls eine entsprechende Meldung im Direktfenster. Der folgende Teil ist weitgehend mit dem aus <b>FormProperties <\/b>identisch, mit dem Unterschied, dass nicht die Eigenschaften des <b>Form<\/b>-Objekts, sondern die des <b>Control<\/b>-Objekts in alphabetischer Reihenfolge in die Collection <b>col <\/b>geschrieben werden.<\/p>\n<p>Auch die Spaltenk&ouml;pfe und die Trennlinien werden wie &uuml;blich im Direktfenster ausgegeben. Bei der Ausgabe der einzelnen Properties ergibt sich jedoch eine wichtige &auml;nderung: Bei den Steuerelementeigenschaften kann es durchaus vorkommen, dass der Zugriff auf die <b>Value<\/b>-Eigenschaft einen Fehler ausl&ouml;st &#8211; beziehungsweise der Versuch, den Inhalt der <b>Value<\/b>-Eigenschaft als String zu behandeln und diesen im Direktfenster ausgeben zu wollen.<\/p>\n<p>Diesem Fall wollen wir vorbeugen: Wir versuchen einfach, die Zeile wie gewohnt auszugeben. Allerdings deaktivieren wir zuvor die Fehlerbehandlung mit <b>On Error Resume Next<\/b>. Nach der Ausgabe pr&uuml;fen wir in einer <b>Select Case<\/b>-Bedingung den Wert von <b>Err.Number<\/b>. Ist dieser nicht <b>Null<\/b>, soll statt dem Wert der Eigenschaft der Text der Fehlermeldung ausgegeben werden.<\/p>\n<p><b>Zusammenfassung und Ausblick<\/b><\/p>\n<p>Dieser Beitrag zeigt einige Hilfsfunktionen, mit denen Sie sich den Programmierer-Alltag vereinfachen k&ouml;nnen. Wir haben Prozeduren vorgestellt, mit denen Sie alle Tabellen einer Datenbank ausgeben k&ouml;nnen, alle Felder einer Tabelle, alle Daten eines Recordsets, alle Eigenschaften samt Werten eines Formulars und das Gleiche f&uuml;r ein einzelnes Steuerelement.<\/p>\n<p>Es gibt sicher noch eine ganze Reihe von n&uuml;tzlichen Prozeduren, die wir dieser Sammlung hinzuf&uuml;gen k&ouml;nnen. Wenn Ihnen eine einf&auml;llt, melden Sie sich einfach unter <b>info@access-im-unternehmen.de <\/b>&#8211; wir schauen uns an, ob Ihr Wunsch f&uuml;r das Magazin interessant ist, und wer wei&szlig;: Vielleicht setzen wir Ihren Vorschlag dann in einem zweiten Teil dieses Beitrags um.<\/p>\n<h3>Downloads zu diesem Beitrag<\/h3>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>DAODebuggingHilfsfunktionen.mdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/{25EF36C9-31E6-4FC6-BA50-B6BF7EEEE0D4}\/aiu_968.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Beim Debuggen von VBA-Code, der Anweisungen f&uuml;r den Zugriff auf die Daten der Anwendung per DAO enth&auml;lt, ben&ouml;tigt man immer wieder mal Detailinformationen. Welche Felder enth&auml;lt die Tabelle noch Welchen Wert enthalten die Felder des aktuellen Datensatzes Wie viele Datens&auml;tze liefert das aktuelle Recordset Die notwendigen Informationen kann man sich mithilfe entsprechender Ausdr&uuml;cke &uuml;ber das Direktfenster holen, aber meist kostet dies unn&ouml;tig Zeit. Warum also nicht einfach eine kleine Hilfsklasse programmieren, die solche Fragen sehr einfach beantwortet Dieser Beitrag zeigt, wie es gelingt.<\/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":[66012015,662015,44000025],"tags":[],"class_list":["post-55000968","post","type-post","status-publish","format-standard","hentry","category-66012015","category-662015","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>Debugging-Hilfsfunktionen - 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\/DebuggingHilfsfunktionen\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Debugging-Hilfsfunktionen\" \/>\n<meta property=\"og:description\" content=\"Beim Debuggen von VBA-Code, der Anweisungen f&uuml;r den Zugriff auf die Daten der Anwendung per DAO enth&auml;lt, ben&ouml;tigt man immer wieder mal Detailinformationen. Welche Felder enth&auml;lt die Tabelle noch Welchen Wert enthalten die Felder des aktuellen Datensatzes Wie viele Datens&auml;tze liefert das aktuelle Recordset Die notwendigen Informationen kann man sich mithilfe entsprechender Ausdr&uuml;cke &uuml;ber das Direktfenster holen, aber meist kostet dies unn&ouml;tig Zeit. Warum also nicht einfach eine kleine Hilfsklasse programmieren, die solche Fragen sehr einfach beantwortet Dieser Beitrag zeigt, wie es gelingt.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/DebuggingHilfsfunktionen\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2020-05-22T21:06:42+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg07.met.vgwort.de\/na\/a9a214ba5e104c03a2c99c93fbe91df8\" \/>\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=\"25\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/DebuggingHilfsfunktionen\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/DebuggingHilfsfunktionen\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Debugging-Hilfsfunktionen\",\"datePublished\":\"2020-05-22T21:06:42+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/DebuggingHilfsfunktionen\\\/\"},\"wordCount\":4036,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/DebuggingHilfsfunktionen\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/a9a214ba5e104c03a2c99c93fbe91df8\",\"articleSection\":[\"1\\\/2015\",\"2015\",\"VBA und Programmiertechniken\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/DebuggingHilfsfunktionen\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/DebuggingHilfsfunktionen\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/DebuggingHilfsfunktionen\\\/\",\"name\":\"Debugging-Hilfsfunktionen - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/DebuggingHilfsfunktionen\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/DebuggingHilfsfunktionen\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/a9a214ba5e104c03a2c99c93fbe91df8\",\"datePublished\":\"2020-05-22T21:06:42+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/DebuggingHilfsfunktionen\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/DebuggingHilfsfunktionen\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/DebuggingHilfsfunktionen\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/a9a214ba5e104c03a2c99c93fbe91df8\",\"contentUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/a9a214ba5e104c03a2c99c93fbe91df8\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/DebuggingHilfsfunktionen\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Debugging-Hilfsfunktionen\"}]},{\"@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":"Debugging-Hilfsfunktionen - 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\/DebuggingHilfsfunktionen\/","og_locale":"de_DE","og_type":"article","og_title":"Debugging-Hilfsfunktionen","og_description":"Beim Debuggen von VBA-Code, der Anweisungen f&uuml;r den Zugriff auf die Daten der Anwendung per DAO enth&auml;lt, ben&ouml;tigt man immer wieder mal Detailinformationen. Welche Felder enth&auml;lt die Tabelle noch Welchen Wert enthalten die Felder des aktuellen Datensatzes Wie viele Datens&auml;tze liefert das aktuelle Recordset Die notwendigen Informationen kann man sich mithilfe entsprechender Ausdr&uuml;cke &uuml;ber das Direktfenster holen, aber meist kostet dies unn&ouml;tig Zeit. Warum also nicht einfach eine kleine Hilfsklasse programmieren, die solche Fragen sehr einfach beantwortet Dieser Beitrag zeigt, wie es gelingt.","og_url":"https:\/\/access-im-unternehmen.de\/DebuggingHilfsfunktionen\/","og_site_name":"Access im Unternehmen","article_published_time":"2020-05-22T21:06:42+00:00","og_image":[{"url":"http:\/\/vg07.met.vgwort.de\/na\/a9a214ba5e104c03a2c99c93fbe91df8","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"25\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/DebuggingHilfsfunktionen\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/DebuggingHilfsfunktionen\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Debugging-Hilfsfunktionen","datePublished":"2020-05-22T21:06:42+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/DebuggingHilfsfunktionen\/"},"wordCount":4036,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/DebuggingHilfsfunktionen\/#primaryimage"},"thumbnailUrl":"http:\/\/vg07.met.vgwort.de\/na\/a9a214ba5e104c03a2c99c93fbe91df8","articleSection":["1\/2015","2015","VBA und Programmiertechniken"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/DebuggingHilfsfunktionen\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/DebuggingHilfsfunktionen\/","url":"https:\/\/access-im-unternehmen.de\/DebuggingHilfsfunktionen\/","name":"Debugging-Hilfsfunktionen - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/DebuggingHilfsfunktionen\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/DebuggingHilfsfunktionen\/#primaryimage"},"thumbnailUrl":"http:\/\/vg07.met.vgwort.de\/na\/a9a214ba5e104c03a2c99c93fbe91df8","datePublished":"2020-05-22T21:06:42+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/DebuggingHilfsfunktionen\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/DebuggingHilfsfunktionen\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/DebuggingHilfsfunktionen\/#primaryimage","url":"http:\/\/vg07.met.vgwort.de\/na\/a9a214ba5e104c03a2c99c93fbe91df8","contentUrl":"http:\/\/vg07.met.vgwort.de\/na\/a9a214ba5e104c03a2c99c93fbe91df8"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/DebuggingHilfsfunktionen\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Debugging-Hilfsfunktionen"}]},{"@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\/55000968","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=55000968"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55000968\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55000968"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55000968"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55000968"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}