{"id":55001312,"date":"2021-08-01T00:00:00","date_gmt":"2021-07-31T10:13:17","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=1312"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"APIFunktionen_finden_und_speichern","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/APIFunktionen_finden_und_speichern\/","title":{"rendered":"API-Funktionen finden und speichern"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg07.met.vgwort.de\/na\/280458dc65f84b30898c6a959c292c1f\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Eine umfangreiche Access-Anwendung kann in ihrem VBA-Projekt einige API-Deklarationen enthalten. Je l&auml;nger diese Anwendung bereits entwickelt wird, desto mehr solcher Deklarationen haben sich im Laufe der Zeit in vielen verschiedenen Modulen angesammelt. Und umso mehr dieser APIs werden vielleicht gar nicht mehr verwendet, weil man sie grunds&auml;tzlich nicht mehr braucht oder sie durch andere Funktionen oder DLLs ersetzt hat. Daher ist es grunds&auml;tzlich interessant, nicht mehr verwendete Deklarationen von API-Funktionen aus der Anwendung zu entfernen. Noch interessanter wird dies, wenn die Migration einer f&uuml;r 32-Bit-Access ausgelegten Anwendung zu einer Anwendung ansteht, die auch unter 64-Bit-Access ihren Dienst tun soll. Je weniger API-Funktionen dann deklariert sind, umso weniger Anpassungen sind notwendig. Im vorliegenden Beitrag schauen wir uns zun&auml;chst an, wie Sie die API-Deklarationen und die gegebenenfalls ben&ouml;tigten Konstanten und Typen &uuml;berhaupt finden.<\/b><\/p>\n<p>Sp&auml;testens, wenn man Funktionen nutzen m&ouml;chte, die nicht typischerweise von den eingebundenen Bibliotheken oder anderen, &uuml;ber den <b>Verweise<\/b>-Dialog hinzugef&uuml;gten Bibliotheken bereitgestellt werden, ben&ouml;tigt man API-Funktionen.<\/p>\n<p>G&auml;ngige S&auml;tze solcher Funktionen dienen beispielsweise f&uuml;r folgende und viele weitere Anwendungszwecke:<\/p>\n<ul>\n<li>Anzeige von Dialogen zum Ausw&auml;hlen von Dateien und Ordnern<\/li>\n<li>Arbeiten mit Bildern<\/li>\n<li>Einsatz von FTP<\/li>\n<li>Verwenden von Verschl&uuml;sselungstechniken<\/li>\n<li>Erzeugen von GUIDs<\/li>\n<\/ul>\n<p>F&uuml;r manche Szenarien f&uuml;gt man dazu umfangreiche Module mit vielen Deklarationen von API-Funktionen zu einem VBA-Projekt hinzu. In vielen F&auml;llen verwendet die Anwendung jedoch nur einen Bruchteil der in den Modulen enthaltenen Befehle &#8211; zum Beispiel bei Modulen mit Funktionen f&uuml;r den Umgang mit Bildern per GDI.<\/p>\n<h2>&Uuml;berblick &uuml;ber die API-Deklarationen verschaffen<\/h2>\n<p>Bevor man sich daran machen kann, die API-Funktionen in der mit 32-Bit-Access kompatiblen Fassung nach 64-Bit zu konvertieren, verschafft man sich erstmal einen &Uuml;berblick &uuml;ber alle in einem Projekt enthaltenen APIs. Nun meinen wir damit nicht, dass Sie alle enthaltenen Module &ouml;ffnen und diese manuell nach API-Deklarationen durchsuchen. Und wir wollen auch nicht die Suchfunktion nutzen, sondern uns selbst eine Routine schreiben, mit der wir alle Deklarationen von API-Funktionen finden.<\/p>\n<p>Dazu nutzen wir die Klassen, Eigenschaften und Methoden der Bibliothek <b>Microsoft Visual Basic for Applications 5.3 Extensibility<\/b>, die wir &uuml;ber den <b>Verweise<\/b>-Dialog (Men&uuml;punkt <b>Extras|Verweise <\/b>im VBA-Editor) zum Projekt hinzuf&uuml;gen (siehe Bild 1).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2021_04\/pic_1312_001.png\" alt=\"Verweis auf die Bibliothek Microsoft Visual Basic for Applications 5.3 Extensibility\" width=\"499,5589\" height=\"393,8207\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Verweis auf die Bibliothek Microsoft Visual Basic for Applications 5.3 Extensibility<\/span><\/b><\/p>\n<h2>Aktuelles VBA-Projekt identifizieren<\/h2>\n<p>Als Erstes ben&ouml;tigen wir einen Verweis auf das aktuelle VBA-Projekt. Es kann n&auml;mlich sein, dass der VBA-Editor mehr als ein Projekt gleichzeitig im Projekt-Explorer anzeigt &#8211; zum Beispiel, wenn gerade ein Access-Add-In ge&ouml;ffnet ist oder wenn der Benutzer eine Bibliotheksdatenbank als Verweis eingebunden hat.<\/p>\n<p>Um dieses VBA-Projekt zu ermitteln, verwenden wir die Hilfsfunktion <b>GetCurrentVBProject<\/b>. Es durchl&auml;uft alle Elemente der <b>VBProjects<\/b>-Auflistung des VBA-Editors, den wir mit der Klasse <b>VBE <\/b>referenzieren, in einer <b>For Each<\/b>-Schleife.<\/p>\n<p>Dabei vergleicht die Funktion den Dateinamen des <b>VBProject<\/b>-Objekts mit dem der aktuell ge&ouml;ffneten Access-Datenbank.<\/p>\n<p>Stimmen diese &uuml;berein, enth&auml;lt <b>objVBProject <\/b>einen Verweis auf das VBA-Projekt der aktuellen Datenbank-Datei und die Funktion liefert diesen als Funktionsergebnis zur&uuml;ck:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>GetCurrentVBProject()<span style=\"color:blue;\"> As <\/span>VBProject\r\n     <span style=\"color:blue;\">Dim <\/span>objVBProject<span style=\"color:blue;\"> As <\/span>VBProject\r\n     <span style=\"color:blue;\">Dim <\/span>objVBComponent<span style=\"color:blue;\"> As <\/span>VBComponent\r\n     For Each objVBProject In VBE.VBProjects\r\n         <span style=\"color:blue;\">If <\/span>(objVBProject.FileName = CurrentDb.Name)<span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">Set<\/span> GetCurrentVBProject = objVBProject\r\n             <span style=\"color:blue;\">Exit Function<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> objVBProject\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<h2>Suche nach den API-Deklarationen<\/h2>\n<p>Dann beginnt der spannende Teil: die Suche nach den Deklarationen. Wie finden wir API-Deklarationen M&uuml;ssen wir dazu jede einzelne Codezeile durchsuchen &#8211; und wonach genau suchen wir dabei<\/p>\n<p>Der erste Hinweis ist: Jede Deklaration einer API-Funktion enth&auml;lt das Schl&uuml;sselwort <b>Declare<\/b>. Dieses finden wir in keiner anderen Prozedur oder Funktion.<\/p>\n<p>Der zweite Hinweis lautet: Jedes Modul ist unterteilt in den oberen Bereich mit den Deklarationen und den unteren Bereich mit den Funktionen und Prozeduren. Vielleicht haben Sie schon einmal festgestellt, dass Sie die Deklaration einer Variable oder auch einer API-Funktion in einem VBA-Modul nicht unterhalb der ersten Routine platzieren k&ouml;nnen.<\/p>\n<p>Probieren Sie dies dennoch, erhalten Sie beim Kompilieren des Projekts die Fehlermeldung aus Bild 2. Genau genommen ist der Text der Meldung nicht ganz korrekt, denn hinter <b>End Sub <\/b>und so weiter k&ouml;nnen nat&uuml;rlich auch noch weitere <b>Sub<\/b>-, <b>Function<\/b>&#8211; oder <b>Property<\/b>-Funktionen stehen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2021_04\/pic_1312_002.png\" alt=\"Fehler beim Deklarieren einer Variablen hinter einer Routine\" width=\"424,5589\" height=\"180,7528\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Fehler beim Deklarieren einer Variablen hinter einer Routine<\/span><\/b><\/p>\n<p>Das ist jedoch hier irrelevant &#8211; es geht nur darum, dass jegliche Deklaration von Variablen, Kontanten und API-Funktionen immer vor der ersten <b>Sub<\/b>-, <b>Function<\/b>&#8211; oder <b>Property<\/b>-Prozedur stehen muss.<\/p>\n<h2>Alle Module durchlaufen<\/h2>\n<p>Wir m&uuml;ssen auf jeden Fall alle Module durchlaufen, um alle Deklarationen von API-Funktionen zu finden.<\/p>\n<p>Das erledigen wir in einer einfachen <b>For Each<\/b>-Schleife &uuml;ber alle Elemente des Typs <b>VBComponent <\/b>der Auflistung <b>VBComponents <\/b>des aktuellen <b>VBProject<\/b>-Elements:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>FindAPIDeclares()\r\n     <span style=\"color:blue;\">Dim <\/span>objVBProject<span style=\"color:blue;\"> As <\/span>VBProject\r\n     <span style=\"color:blue;\">Dim <\/span>objVBComponent<span style=\"color:blue;\"> As <\/span>VBComponent\r\n     <span style=\"color:blue;\">Set<\/span> objVBProject = GetCurrentVBProject\r\n     For Each objVBComponent In objVBProject.VBComponents\r\n         <span style=\"color:blue;\">Debug.Print<\/span> objVBComponent.Name\r\n     <span style=\"color:blue;\">Next<\/span> objVBComponent\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>In diesem Fall geben wir die Namen aller Module im Direktbereich des VBA-Editors aus.<\/p>\n<p>Das Durchsuchen der Codezeilen eines <b>VBComponent<\/b>-Elements umfasst einige Anweisungen, daher erstellen wir daf&uuml;r direkt eine eigene Routine, die wir innerhalb der Schleife aufrufen:<\/p>\n<pre>...\r\nFor Each objVBComponent In objVBProject.VBComponents\r\n     FindAPIDeclaresInModule objVBComponent\r\n<span style=\"color:blue;\">Next<\/span> objVBComponent\r\n...<\/pre>\n<h2>Alle Deklarationszeilen untersuchen<\/h2>\n<p>Die Prozedur <b>FindAPIDeclaresInModule <\/b>nimmt den Verweis auf das <b>VBComponent<\/b>-Objekt entgegen und weist das enthaltene <b>CodeModule<\/b>-Objekt der Variablen <b>objCodeModule <\/b>hinzu:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>FindAPIDeclaresInModule( objVBComponent<span style=\"color:blue;\"> As <\/span>VBComponent)\r\n     <span style=\"color:blue;\">Dim <\/span>objCodeModule<span style=\"color:blue;\"> As <\/span>CodeModule\r\n     <span style=\"color:blue;\">Dim <\/span>lngLine<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> objCodeModule = objVBComponent.CodeModule\r\n     For lngLine = 1 To objCodeModule.CountOfDeclarationLines\r\n         <span style=\"color:blue;\">Debug.Print<\/span> objCodeModule.Lines(lngLine, 1)\r\n     <span style=\"color:blue;\">Next<\/span> lngLine\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>F&uuml;r die danach folgende <b>For&#8230;Next<\/b>-Schleife muss man wissen, dass das <b>CodeModule<\/b>-Objekt eine eigene Eigenschaft bereitstellt, welche das Ende des Deklarationsbereichs des jeweiligen Moduls in Form der Zeilennummer liefert. Diese hei&szlig;t <b>CountOfDeclarationLines<\/b>.<\/p>\n<p>Wir brauchen also nur alle Zeilen von der ersten bis zu der mit <b>CountOfDeclarationLines <\/b>angegebenen Zeile zu durchlaufen, um alle m&ouml;glichen Zeilen mit API-Deklarationen zu erwischen.<\/p>\n<h2>Aufgabe: Zeilenumbr&uuml;che<\/h2>\n<p>API-Deklarationen findet man oft in der mehrzeiligen Darstellung. Das ist &uuml;bersichtlicher, wenn man beispielsweise jeden Parameter in einer neuen Zeile anzeigt:<\/p>\n<pre>Declare Function GetDiskFreeSpace Lib \"kernel32\" Alias \"GetDiskFreeSpaceA\" ( _\r\n     ByVal lpRootPathName<span style=\"color:blue;\"> As String<\/span>, _\r\n     lpSectorsPerCluster<span style=\"color:blue;\"> As Long<\/span>, _\r\n     lpBytesPerSector<span style=\"color:blue;\"> As Long<\/span>, _\r\n     lpNumberOfFreeClusters<span style=\"color:blue;\"> As Long<\/span>, _\r\n     lpTotalNumberOfClusters<span style=\"color:blue;\"> As Long<\/span>) _\r\nAs Long<\/pre>\n<p>Die Untersuchung wird dadurch jedoch erschwert. Um jegliche interessante Idee von Entwicklern auszuschlie&szlig;en, wollen wir vor der Untersuchung einer Zeile auf eine API-Funktion zun&auml;chst die mit dem Unterstrich-Zeichen gesplitteten Zeilen in einer Variablen zusammenf&uuml;hren. Das gelingt in der Prozedur wie in Listing 1.<\/p>\n<pre>...\r\nFor lngLine = 1 To objCodeModule.CountOfDeclarationLines\r\n     strLine = objCodeModule.Lines(lngLine, 1)\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">InStr<\/span>(1, objCodeModule.Lines(lngLine, 1), \" _\") = 0\r\n         strLine = VBA.<span style=\"color:blue;\">Replace<\/span>(strLine, \" _\", \" \")\r\n         strLine = VBA.<span style=\"color:blue;\">Replace<\/span>(strLine, \"  \", \" \")\r\n         strLine = VBA.<span style=\"color:blue;\">Replace<\/span>(strLine, \"  \", \" \")\r\n         strLine = VBA.<span style=\"color:blue;\">Replace<\/span>(strLine, \"  \", \" \")\r\n         strLine = VBA.<span style=\"color:blue;\">Replace<\/span>(strLine, \"( \", \"(\")\r\n         strLine = VBA.<span style=\"color:blue;\">Replace<\/span>(strLine, \" )\", \")\")\r\n         lngLine = lngLine + 1\r\n         strLine = strLine & objCodeModule.Lines(lngLine, 1)\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">InStr<\/span>(1, strLine, \"''\") = 0<span style=\"color:blue;\"> Then<\/span>\r\n         strLine = <span style=\"color:blue;\">Mid<\/span>(strLine, <span style=\"color:blue;\">InStr<\/span>(1, strLine, \"''\"))\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Debug.Print<\/span> strLine\r\n<span style=\"color:blue;\">Next<\/span> lngLine\r\n...<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Einlesen von mehrzeiligen Anweisungen als einzeilige Anweisungen<\/span><\/b><\/p>\n<p>Hier durchlaufen wir nach wie vor alle Zeilen des Deklarationsbereichs, also bis zur Zeile aus <b>CountOfDeclarationLines<\/b>. Dabei schreiben wir zuerst den Inhalte der aktuellen Zeile in die Variable <b>strLine<\/b>.<\/p>\n<p>In der folgenden <b>Do While<\/b>-Schleife pr&uuml;fen wir, ob die Anweisung der aktuellen Zeile mit einem Unterstrich endet, was bedeutet, dass diese in der folgenden Zeile fortgesetzt wird. In diesem Fall nehmen wir einige &Auml;nderungen vor:<\/p>\n<ul>\n<li>Wir ersetzen Unterstriche, die auf Leerzeichen folgen, durch Leerzeichen.<\/li>\n<li>Wir ersetzen doppelte Leerzeichen durch einfache Leerzeichen, um die Einr&uuml;ckungen folgender Zeilen zu entfernen.<\/li>\n<li>Wir ersetzen &ouml;ffnende Klammern mit folgendem Leerzeichen durch &ouml;ffnende Klammern und schlie&szlig;ende Klammern mir vorangestelltem Leerzeichen durch schlie&szlig;ende Klammern.<\/li>\n<\/ul>\n<p>Schlie&szlig;lich erh&ouml;hen wir innerhalb des <b>Do While<\/b>-Schleifendurchlaufs den Wert der Z&auml;hlervariablen <b>lngZeile <\/b>um <b>1<\/b>, damit die gleiche Zeile nicht beim n&auml;chsten Durchlauf der <b>For&#8230;Next<\/b>-Schleife erneut untersucht wird.<\/p>\n<p><!--30percent--><\/p>\n<p>Au&szlig;erdem f&uuml;gen wir den Inhalt der aktuellen Zeile an den Inhalt von <b>strLine <\/b>an.<\/p>\n<p>Danach pr&uuml;fen wir noch, ob die Zeile noch weitere Hochkommata enth&auml;lt, was auf angeh&auml;ngte Kommentare hinweist. Hier schneiden wir den Kommentar ab dem Hochkomma ab:<\/p>\n<pre><span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">InStr<\/span>(1, strLine, \"''\") = 0<span style=\"color:blue;\"> Then<\/span>\r\n     strLine = <span style=\"color:blue;\">Mid<\/span>(strLine, <span style=\"color:blue;\">InStr<\/span>(1, strLine, \"''\"))\r\n<span style=\"color:blue;\">End If<\/span><\/pre>\n<h2>Das Schl&uuml;sselwort Declare finden<\/h2>\n<p>Als Ergebnis landen mehrzeilige Anweisungen als einzeilige Anweisung in der Variablen <b>strLine<\/b>, wo wir diese dann weiter untersuchen k&ouml;nnen. In diesem Fall wollen wir wissen, ob die Zeile das Schl&uuml;sselwort <b>Declare <\/b>enth&auml;lt. Dieses Schl&uuml;sselwort kann sich allerdings an verschiedenen Positionen befinden. Die Erste ist der Anfang der Zeile:<\/p>\n<pre>Declare Function CloseClipboard Lib \"user32\" ()<span style=\"color:blue;\"> As Long<\/span><\/pre>\n<p>Oder es folgt auf eines der Schl&uuml;sselw&ouml;rter <b>Private <\/b>oder <b>Public<\/b>:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>Declare Function CloseClipboard Lib \"user32\" ()<span style=\"color:blue;\"> As Long<\/span><\/pre>\n<p>Es k&ouml;nnte sich auch in einem Routinen- oder Parameternamen verstecken:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>FindDeclares()<\/pre>\n<p>Und zu guter Letzt kann eine <b>Declare<\/b>-Zeile auch auskommentiert sein:<\/p>\n<pre>''Declare Function CloseClipboard Lib \"user32\" ()<span style=\"color:blue;\"> As Long<\/span><\/pre>\n<p>Wir machen also nichts verkehrt, wenn wir eine kleine Funktion programmieren, die pr&uuml;ft, ob es sich tats&auml;chlich um eine <b>Declare<\/b>-Zeile f&uuml;r eine API-Funktion handelt und die wir jeweils nach dem Einlesen einer vollst&auml;ndigen, gegebenenfalls auch aus mehreren Zeilen bestehenden Anweisung aufrufen. Hier zun&auml;chst der Aufruf der Funktion aus der Prozedur <b>FindAPIDeclaresInModule <\/b>heraus:<\/p>\n<pre>For lngLine = 1 To objCodeModule.CountOfDeclarationLines\r\n     ...\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">InStr<\/span>(1, strLine, \"Declare \") = 0<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">If <\/span>IsDeclare(strLine)<span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">Debug.Print<\/span> strLine\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> lngLine<\/pre>\n<p>Die Funktion <b>IsDeclare <\/b>finden Sie in Listing 2. Die Funktion entfernt mit der <b>Trim<\/b>-Funktion alle f&uuml;hrenden und folgenden Leerzeichen der Zeile aus <b>strLine<\/b>. Dann pr&uuml;ft sie, ob das erste Zeichen ein Kommentarzeichen ist (<b>&#8220;<\/b>). Falls nicht, untersucht sie, ob die Zeile die Zeichenfolge <b>Declare <\/b>direkt zu Beginn aufweist oder ob die Zeichenfolge <b>Declare <\/b>mit f&uuml;hrendem und folgendem Leerzeichen weiter hinten folgt.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>IsDeclare(strLine<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Boolean<\/span>\r\n     strLine = <span style=\"color:blue;\">Trim<\/span>(strLine)\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">Left<\/span>(strLine, 1) = \"''\"<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">InStr<\/span>(1, strLine, \"Declare\") = 1 Or <span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">InStr<\/span>(1, strLine, \" Declare \") = 0<span style=\"color:blue;\"> Then<\/span>\r\n             IsDeclare = <span style=\"color:blue;\">True<\/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;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Ermitteln, ob eine Zeile eine Declare-Anweisung enth&auml;lt<\/span><\/b><\/p>\n<p>Damit k&ouml;nnen wir innerhalb der <b>If IsDeclare(strLine) Then<\/b>-Bedingung per <b>Debug.Print<\/b> alle tats&auml;chlichen API-Deklarationen ausgeben.<\/p>\n<h2>API-Funktionsdeklarationen in Tabelle speichern<\/h2>\n<p>Damit ist die Arbeit allerdings noch nicht zu Ende. Wir wollen die API-Deklarationen zun&auml;chst in einer Tabelle namens <b>tblAPIDeclarations<\/b> speichern (siehe Bild 3).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2021_04\/pic_1312_003.png\" alt=\"Entwurf der Tabelle zum Speichern der API-Deklarationen\" width=\"549,559\" height=\"383,7209\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Entwurf der Tabelle zum Speichern der API-Deklarationen<\/span><\/b><\/p>\n<p>Diese Tabelle soll die folgenden Felder enthalten:<\/p>\n<ul>\n<li><b>APIDeclarationID<\/b>: Prim&auml;rschl&uuml;sselwert der API-Deklaration<\/li>\n<li><b>APIDeclaration<\/b>: Komplette Deklaration<\/li>\n<li><b>APICall<\/b>: Aufruf der API-Funktion<\/li>\n<li><b>APIReturnType<\/b>: Typ des R&uuml;ckgabewerts der API-Funktion<\/li>\n<li><b>Module<\/b>: Name des Moduls, in dem sich die Deklaration der API-Funktion befindet<\/li>\n<\/ul>\n<p>Au&szlig;erdem legen wir noch eine weitere Tabelle namens <b>tblAPIParameters <\/b>an. Diese soll die einzelnen Parameter der Deklaration der API-Funktionen speichern:<\/p>\n<ul>\n<li><b>APIParameterID<\/b>: Prim&auml;rschl&uuml;sselwert der Tabelle<\/li>\n<li><b>APIDeclarationID<\/b>: Fremdschl&uuml;sselfeld zur Zuordnung zur API-Deklaration<\/li>\n<li><b>APIParameter<\/b>: Bezeichnung des Parameters<\/li>\n<li><b>APIParameterType<\/b>: Datentyp des Paramters<\/li>\n<li><b>APIByVal<\/b>: Gibt an, ob der Parameter mit dem Schl&uuml;sselwort <b>ByVal<\/b> ausgezeichnet ist und somit als Wert &uuml;bergeben wird statt als Referenz<\/li>\n<\/ul>\n<p>Den Entwurf dieser Tabelle finden Sie in Bild 4.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2021_04\/pic_1312_004.png\" alt=\"Entwurf der Tabelle zum Speichern der API-Parameter\" width=\"549,559\" height=\"385,3935\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Entwurf der Tabelle zum Speichern der API-Parameter<\/span><\/b><\/p>\n<p>Die Beziehung zwischen den beiden Tabellen stellen wir &uuml;ber das Fremdschl&uuml;sselfeld <b>APIDeclarationID <\/b>der Tabelle <b>tblAPIParameters <\/b>und das gleichnamige Prim&auml;rschl&uuml;sselfeld der Tabelle <b>tblAPIDeclarations <\/b>her. F&uuml;r die Beziehung mit referenzieller Integrit&auml;t legen wir au&szlig;erdem die L&ouml;schweitergabe fest, damit beim L&ouml;schen von Deklarationen auch gleich die Parameter gel&ouml;scht werden (siehe Bild 5).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2021_04\/pic_1312_005.png\" alt=\"Beziehung zwischen den beiden beteiligten Tabellen\" width=\"549,559\" height=\"413,8076\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Beziehung zwischen den beiden beteiligten Tabellen<\/span><\/b><\/p>\n<h2>Prozedur zum Speichern der API-Deklarationen<\/h2>\n<p>Die Prozedur <b>SaveAPIDeclarations <\/b>erledigt das Speichern der API-Deklaration in der Tabelle <b>tblAPIDeclarations<\/b>. Sie wird von der Prozedur <b>FindAPIDeclaresInModule <\/b>innerhalb der <b>For&#8230;Next<\/b>-Schleife wie folgt aufgerufen:<\/p>\n<pre><span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">InStr<\/span>(1, strLine, \"Declare \") = 0<span style=\"color:blue;\"> Then<\/span>\r\n     <span style=\"color:blue;\">If <\/span>IsDeclare(strLine)<span style=\"color:blue;\"> Then<\/span>\r\n         SaveAPIDeclaration objVBComponent.Name, strLine\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End If<\/span><\/pre>\n<p>Die Prozedur <b>SaveAPIDeclarations <\/b>selbst finden Sie in Listing 3. Sie erwartet den Namen des Moduls, in dem sich die API-Deklaration befindet, sowie die Zeile mit der API-Deklaration als Parameter. Die Prozedur ermittelt als Erstes das erste Auftreten der Zeichenkette <b>Sub <\/b>(mit f&uuml;hrendem und folgendem Leerzeichen) und speichert es in der Variablen <b>lngPosStart<\/b>.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>SaveAPIDeclaration(strModule<span style=\"color:blue;\"> As String<\/span>, strLine<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>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>strAPICall<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngPosStart<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngPosEnde<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strAPIReturnType<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strAPIParameters<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngAPIDeclarationID <span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     lngPosStart = <span style=\"color:blue;\">InStr<\/span>(1, strLine, \" Sub \")\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> lngPosStart = 0<span style=\"color:blue;\"> Then<\/span>\r\n         lngPosEnde = <span style=\"color:blue;\">InStr<\/span>(lngPosStart + 5, strLine, \" \")\r\n         strAPI<span style=\"color:blue;\">Call<\/span> = <span style=\"color:blue;\">Mid<\/span>(strLine, lngPosStart + 5, lngPosEnde - lngPosStart - 5)\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         lngPosStart = <span style=\"color:blue;\">InStr<\/span>(1, strLine, \" Function \")\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> lngPosStart = 0<span style=\"color:blue;\"> Then<\/span>\r\n             lngPosEnde = <span style=\"color:blue;\">InStr<\/span>(lngPosStart + 10, strLine, \" \")\r\n             strAPI<span style=\"color:blue;\">Call<\/span> = <span style=\"color:blue;\">Mid<\/span>(strLine, lngPosStart + 10, lngPosEnde - lngPosStart - 10)\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     lngPosStart = <span style=\"color:blue;\">InStr<\/span>(1, strLine, \"(\")\r\n     lngPosEnde = <span style=\"color:blue;\">InStr<\/span>(1, strLine, \")\")\r\n     strAPIParameters = <span style=\"color:blue;\">Mid<\/span>(strLine, lngPosStart + 1, lngPosEnde - lngPosStart - 1)\r\n     strAPIReturnType = <span style=\"color:blue;\">Mid<\/span>(strLine, <span style=\"color:blue;\">InStr<\/span>(1, strLine, \")\") + 1)\r\n     strAPIReturnType = VBA.<span style=\"color:blue;\">Replace<\/span>(strAPIReturnType, \"AS \", \"\")\r\n     strAPIReturnType = <span style=\"color:blue;\">Trim<\/span>(strAPIReturnType)\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM tblAPIDeclarations\", dbOpenDynaset)\r\n     rst.Add<span style=\"color:blue;\">New<\/span>\r\n     rst!APIDeclaration = strLine\r\n     rst!API<span style=\"color:blue;\">Call<\/span> = strAPI<span style=\"color:blue;\">Call<\/span>\r\n     rst!APIReturnType = strAPIReturnType\r\n     rst!Module = strModule\r\n     lngAPIDeclarationID = rst!APIDeclarationID\r\n     rst.Update\r\n     SaveAPIParameters db, lngAPIDeclarationID, strAPIParameters\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Speichern der API-Deklaration in der Tabelle tblAPIDeclarations<\/span><\/b><\/p>\n<p>Ist <b>lngPosStart <\/b>danach nicht <b>0<\/b>, handelt es sich um eine <b>Sub<\/b>-API-Deklaration und der Routinenname folgt ab dem f&uuml;nften Zeichen hinter dem <b>Sub<\/b>-Schl&uuml;sselwort. Dann ermitteln wir mit einem weiteren Aufruf von <b>Instr <\/b>die Position des ersten Leerzeichens hinter dem Funktionsnamen.<\/p>\n<p>Mit der <b>Mid<\/b>-Funktion k&ouml;nnen wir nun aufgrund der Start- und der Endposition die Bezeichnung der API-Deklaration aus der Zeile auslesen und in der Variablen <b>strAPICall <\/b>speichern.<\/p>\n<p>Hatte <b>lngPosStart <\/b>hingegen den Wert <b>0<\/b>, dann handelt es sich um eine <b>Function<\/b>-API-Deklaration. Hier lesen wir dann wiederum die Position des ersten Leerzeichens hinter dem Funktionsnamen aus, speichern diesen in <b>lngPosEnde <\/b>und ermitteln mit <b>Mid <\/b>den Namen der API-Deklaration.<\/p>\n<p>Nun wollen wir die Parameterliste ermitteln. Diese befindet sich zwischen der &ouml;ffnenden und der schlie&szlig;enden Klammer, zum Beispiel:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>Declare Function GlobalAlloc Lib \"kernel32\" (ByVal uFlags<span style=\"color:blue;\"> As Long<\/span>, ByVal dwBytes<span style=\"color:blue;\"> As Long<\/span>)<span style=\"color:blue;\"> As Long<\/span><\/pre>\n<p>Also ermitteln wir wieder die Position der &ouml;ffnenden und der schlie&szlig;enden Klammer und speichern diese in <b>lngPosStart <\/b>und <b>lngPosEnde<\/b>. Dann lesen wir mit diesen beiden Werten &uuml;ber die <b>Mid<\/b>-Funktion die enthaltene Parameterliste in die Variable <b>strAPIParameters <\/b>ein.<\/p>\n<p>Danach folgt im Falle einer <b>Function <\/b>noch der R&uuml;ckgabewert der API-Deklaration. Dieser befindet sich in der Regel hinter dem Klammernpaar mit den Parametern, sodass wir den Teil ab der schlie&szlig;enden Klammer in die Variable <b>strAPIReturnType <\/b>einlesen k&ouml;nnen. Da hier immer noch das Schl&uuml;sselwort <b>As <\/b>vorliegt, entfernen wir dieses mit der folgenden <b>Replace<\/b>-Funktion und schneiden dann mit <b>Trim <\/b>alle f&uuml;hrenden und folgenden Leerzeichen ab.<\/p>\n<p>Schlie&szlig;lich &ouml;ffnen wir ein Recordset auf Basis der Tabelle <b>tblAPIDeclarations <\/b>und legen mit <b>AddNew <\/b>einen neuen Datensatz an, dessen Felder wir mit den in den entsprechenden Variablen gespeicherten Werten f&uuml;llen.<\/p>\n<p>Anschlie&szlig;end speichern wir den Datensatz aus dem Recordset mit der <b>Update<\/b>-Methode in der zugrunde liegenden Tabelle, aber nicht ohne zuvor noch den neuen Wert im Prim&auml;rschl&uuml;sselfeld <b>APIDeclarationID <\/b>zu ermitteln und in <b>lngAPIDeclarationID <\/b>zu schreiben.<\/p>\n<h2>Parameter in Tabelle speichern<\/h2>\n<p>Damit rufen wir die n&auml;chste Funktion namens <b>SaveAPIParameters <\/b>auf, der wir einen Verweis auf das <b>Database<\/b>-Objekt, den Prim&auml;rschl&uuml;sselwert der neu hinzugef&uuml;gten Deklaration sowie den Inhalt der Variablen <b>strAPIParameters <\/b>&uuml;bergeben (siehe Listing 4).<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>SaveAPIParameters(db<span style=\"color:blue;\"> As <\/span>DAO.Database, lngID<span style=\"color:blue;\"> As Long<\/span>, strParameterList<span style=\"color:blue;\"> As String<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>strParameters()<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>bolByVal<span style=\"color:blue;\"> As Boolean<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strParameter<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strParameterType<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strElements()<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM tblAPIParameters\", dbOpenDynaset)\r\n     strParameters = <span style=\"color:blue;\">Split<\/span>(strParameterList, \",\")\r\n     For i = <span style=\"color:blue;\">LBound<\/span>(strParameters) To <span style=\"color:blue;\">UBound<\/span>(strParameters)\r\n         strElements = <span style=\"color:blue;\">Split<\/span>(strParameters(i), \" \")\r\n         Select Case <span style=\"color:blue;\">UBound<\/span>(strElements) - <span style=\"color:blue;\">LBound<\/span>(strElements) + 1\r\n             <span style=\"color:blue;\">Case <\/span>4\r\n                 bolByVal = (strElements(0) = \"ByVal\")\r\n                 strParameter = strElements(1)\r\n                 strParameterType = strElements(3)\r\n             <span style=\"color:blue;\">Case <\/span>3\r\n                 strParameter = strElements(0)\r\n                 strParameterType = strElements(2)\r\n             <span style=\"color:blue;\">Case <\/span>2\r\n                 bolByVal = (strElements(0) = \"ByVal\")\r\n                 strParameter = strElements(1)\r\n             <span style=\"color:blue;\">Case <\/span>1\r\n                 strParameter = strElements(0)\r\n         <span style=\"color:blue;\">End Select<\/span>\r\n         rst.Add<span style=\"color:blue;\">New<\/span>\r\n         rst!APIDeclarationID = lngID\r\n         rst!APIParameter = strParameter\r\n         rst!APIParameterType = strParameterType\r\n         rst!APIByVal = CInt(bolByVal)\r\n         rst.Update\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 4: Speichern der Parameter einer API-Deklaration in der Tabelle tblAPIParameters<\/span><\/b><\/p>\n<p>Dieser Parameter enth&auml;lt nun beispielsweise den folgenden Ausdruck:<\/p>\n<pre>ByVal uFlags<span style=\"color:blue;\"> As Long<\/span>, ByVal dwBytes<span style=\"color:blue;\"> As Long<\/span><\/pre>\n<p>Um diese Werte gleich einzeln zu untersuchen, deklariert die Prozedur ein Array namens <b>strParameters()<\/b>. Um die enthaltenen Bestandteile weiter aufzuschl&uuml;sseln, verwenden wir ein weiteres Array namens <b>strElements()<\/b>.<\/p>\n<p>Auch hier deklarieren wir wieder ein <b>Recordset<\/b>-Objekt, dass wir mit den Datens&auml;tzen der Tabelle <b>tblAPIParameters <\/b>f&uuml;llen und mit der Variablen <b>rst <\/b>referenzieren.<\/p>\n<p>Anschlie&szlig;end teilen wir die einzelnen Parameter aus <b>strParameterList <\/b>mit der <b>Split<\/b>-Funktion an den Stellen mit Kommata auf und weisen diese dem Array <b>strParameters <\/b>zu.<\/p>\n<p>Die darin enthaltenen Eintr&auml;ge durchlaufen wir dann in einer <b>For&#8230;Next<\/b>-Schleife mit der Laufvariablen <b>i<\/b>. Den Bereich f&uuml;r die Schleife ermitteln wir mit den Funktionen <b>LBound <\/b>und <b>UBound <\/b>des Arrays, welche den Index des ersten und des letzten Elements liefern. In der Schleife teilen wir jeden Parameter mit der <b>Split<\/b>-Funktion an den Stellen mit den Leerzeichen weiter auf und schreiben das resultierende Array in die Variable <b>strElements<\/b>.<\/p>\n<p>Hier kann es nun verschiedene Konstellationen geben:<\/p>\n<ul>\n<li><b>strElements <\/b>enth&auml;lt vier Elemente, n&auml;mlich <b>ByVal<\/b>\/<b>ByRef<\/b>, Parametername, <b>As <\/b>und Parameterdatentyp<\/li>\n<li><b>strElements <\/b>enth&auml;lt drei Elemente, n&auml;mlich Parametername, <b>As <\/b>und Parameterdatentyp<\/li>\n<li><b>strElements <\/b>enth&auml;lt zwei Elemente, n&auml;mlich <b>ByVal<\/b>\/<b>ByRef <\/b>und Parametername (ohne Datentyp)<\/li>\n<li><b>strElements <\/b>enth&auml;lt nur den Parameternamen<\/li>\n<\/ul>\n<p>Diese Konstellationen pr&uuml;fen wir in einer <b>Select Case<\/b>-Bedingung, deren Vergleichsausdruck die Anzahl der Elemente enth&auml;lt.<\/p>\n<p>Diese ermitteln wir aus der Differenz des gr&ouml;&szlig;ten Indexwertes (<b>UBound<\/b>) und des kleinsten Indexwertes (<b>LBound<\/b>) plus <b>1<\/b>.<\/p>\n<p>Der erste <b>Case<\/b>-Zweig mit dem Vergleichswert <b>4 <\/b>weist <b>bolByVal <\/b>einen Ausdruck zu, der <b>True <\/b>ist, wenn das erste Element aus <b>strElements <\/b>den Wert <b>ByVal <\/b>aufweist. Ansonsten beh&auml;lt <b>bolByVal <\/b>den Wert <b>False<\/b>.<\/p>\n<p>Die Variable <b>strParameter <\/b>erh&auml;lt das zweite Element aus <b>strElements<\/b>. Das dritte Element ist das <b>As<\/b>-Schl&uuml;sselwort. Das vierte Element ist der Datentyp, der in der Variablen <b>strParameterType <\/b>landet.<\/p>\n<p>Der zweite <b>Case<\/b>-Zweig mit dem Vergleichswert <b>3 <\/b>weist der Variablen <b>strParameter <\/b>den ersten Wert aus <b>strElements <\/b>zu und <b>strParameterType <\/b>den dritten Wert.<\/p>\n<p>Der dritte <b>Case<\/b>-Zweig mit dem Vergleichswert <b>2 <\/b>stellt <b>bolByVal <\/b>wieder auf den Wert ein, den der Vergleichsausdruck <b>strElements(0) = &#8222;ByVal&#8220; <\/b>liefert und <b>strParameter <\/b>auf das zweite Element aus <b>strElements<\/b>.<\/p>\n<p>Bleibt noch der vierte Zweig, der lediglich der Variablen <b>strParameter <\/b>den ersten Wert aus <b>strElement <\/b>zuweist.<\/p>\n<p>Anschlie&szlig;end legt die Prozedur mit der Methode <b>AddNew <\/b>einen neuen Datensatz im Recordset <b>rst <\/b>an und weist den Feldern <b>APIDeclarationID<\/b>, <b>APIParameter<\/b>, <b>APIParameterType <\/b>und <b>APIByVal <\/b>die zuvor ermittelten Werte zu.<\/p>\n<p>Dann speichert sie den Datensatz mit der <b>Update<\/b>-Methode in der zugrunde liegenden Tabelle <b>tblAPIParameters<\/b>.<\/p>\n<h2>Die gef&uuml;llten Tabellen<\/h2>\n<p>Die Tabelle <b>tblAPIDeclarations<\/b> enth&auml;lt nun beispielsweise Datens&auml;tze wie in Bild 6.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2021_04\/pic_1312_006.png\" alt=\"Tabelle mit den gespeicherten API-Deklarationen\" width=\"700\" height=\"287,3184\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Tabelle mit den gespeicherten API-Deklarationen<\/span><\/b><\/p>\n<p>Die passenden Parameter zu den dort aufgef&uuml;hrten API-Deklarationen finden Sie in der Tabelle <b>tblAPIParameters<\/b> (siehe Bild 7).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2021_04\/pic_1312_007.png\" alt=\"Tabelle mit den gespeicherten Parametern der API-Deklarationen\" width=\"649,559\" height=\"525,012\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Tabelle mit den gespeicherten Parametern der API-Deklarationen<\/span><\/b><\/p>\n<h2>Zusammenfassung und Ausblick<\/h2>\n<p>Was k&ouml;nnen Sie nun mit Daten dieser Tabellen erledigen Eine ganze Menge! Als Erstes stehen Ihnen nun die Informationen aus den ganzen API-Deklarationen einer Anwendung in zwei Tabellen zur Verf&uuml;gung.<\/p>\n<p>Sie k&ouml;nnen darauf aufbauen und beispielsweise die Datentypen der R&uuml;ckgabewerte der API-Funktionen sowie die der Parameter betrachten und diese beispielsweise in einem weiteren Feld mit dem jeweiligen, unter 64-Bit-Access verwendeten Datentypen erweitern. Dann k&ouml;nnen Sie auf Basis dieser Tabellen den API-Code f&uuml;r die komplette Anwendung f&uuml;r die 64-Bit-Version erzeugen.<\/p>\n<p>Eine Aufgabe, die noch offen ist und die f&uuml;r die Migration zur 64-Bit-Version neben der Anpassung der Datentypen der API-Deklarationen ebenfalls sehr wichtig ist, sind die als Parameter oder R&uuml;ckgabewerte verwendeten Typen, also Konstruktionen aus mehreren Elementen verschiedener Datentypen.<\/p>\n<p>Auch hier m&uuml;ssen Sie f&uuml;r die Migration genau die richtigen Datentypen w&auml;hlen. Wie Sie diese Typen ermitteln, zeigen wir in einem weiteren Beitrag namens <b>API-Typen und Konstanten finden und speichern <\/b>(<b>www.access-im-unternehmen.de\/1313<\/b>).<\/p>\n<p>Und schlie&szlig;lich k&ouml;nnen Sie die in den Tabellen erfasste Liste der verwendeten API-Deklarationen dahingehend untersuchen, welche API-Funktionen &uuml;berhaupt im Rest des VBA-Projekts verwendet werden.<\/p>\n<p>Solche, die nicht zum Einsatz kommen, brauchen Sie gar nicht erst in 64-Bit zu migrieren.<\/p>\n<p>Wie Sie dies identifizieren und einen entsprechenden Vermerk in der Tabelle <b>tblAPIDeclarations <\/b>vornehmen, beschreiben wir im Beitrag <b>Verwaiste API-Funktionen finden <\/b>(<b>www.access-im-unternehmen.de\/1314<\/b>).<\/p>\n<p>Au&szlig;erdem schauen wir uns in der n&auml;chsten Ausgabe im Beitrag <b>VBA-Code von 32-Bit zu 64-Bit migrieren <\/b>(<b>www.access-im-unternehmen.de\/1318<\/b>) an, wie Sie weitgehend automatisiert den Code f&uuml;r die 64-Bit-Version eines VBA-Projekts erzeugen k&ouml;nnen.<\/p>\n<h2>Downloads zu diesem Beitrag<\/h2>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>APIFunktionenFinden.accdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/5DBD1F2F-992A-4AE1-B2E4-7779B5297D55\/aiu_1312.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Eine umfangreiche Access-Anwendung kann in ihrem VBA-Projekt einige API-Deklarationen enthaltenen. Je l&auml;nger diese Anwendung bereits entwickelt wird, desto mehr solcher Deklarationen haben sich im Laufe der Zeit in vielen verschiedenen Modulen angesammelt. Und umso mehr dieser APIs werden vielleicht gar nicht mehr verwendet, weil man sie grunds&auml;tzlich nicht mehr braucht oder sie durch andere Funktionen oder DLLs ersetzt hat. Daher ist es grunds&auml;tzlich interessant, nicht mehr verwendete Deklarationen von API-Funktionen aus der Anwendung zu entfernen. Noch interessanter wird dies, wenn die Migration einer f&uuml;r 32-Bit-Access ausgelegten Anwendung zu einer Anwendung ansteht, die auch unter 64-Bit-Access ihren Dienst tun soll. Je weniger API-Funktionen dann deklariert sind, umso weniger Anpassungen sind notwendig. Im vorliegenden Beitrag schauen wir uns zun&auml;chst an, wie Sie die API-Deklarationen und die gegebenenfalls ben&ouml;tigten Konstanten und Typen &uuml;berhaupt finden.<\/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":[662021,66042021,44000025],"tags":[],"class_list":["post-55001312","post","type-post","status-publish","format-standard","hentry","category-662021","category-66042021","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>API-Funktionen finden und speichern - 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\/APIFunktionen_finden_und_speichern\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"API-Funktionen finden und speichern\" \/>\n<meta property=\"og:description\" content=\"Eine umfangreiche Access-Anwendung kann in ihrem VBA-Projekt einige API-Deklarationen enthaltenen. Je l&auml;nger diese Anwendung bereits entwickelt wird, desto mehr solcher Deklarationen haben sich im Laufe der Zeit in vielen verschiedenen Modulen angesammelt. Und umso mehr dieser APIs werden vielleicht gar nicht mehr verwendet, weil man sie grunds&auml;tzlich nicht mehr braucht oder sie durch andere Funktionen oder DLLs ersetzt hat. Daher ist es grunds&auml;tzlich interessant, nicht mehr verwendete Deklarationen von API-Funktionen aus der Anwendung zu entfernen. Noch interessanter wird dies, wenn die Migration einer f&uuml;r 32-Bit-Access ausgelegten Anwendung zu einer Anwendung ansteht, die auch unter 64-Bit-Access ihren Dienst tun soll. Je weniger API-Funktionen dann deklariert sind, umso weniger Anpassungen sind notwendig. Im vorliegenden Beitrag schauen wir uns zun&auml;chst an, wie Sie die API-Deklarationen und die gegebenenfalls ben&ouml;tigten Konstanten und Typen &uuml;berhaupt finden.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/APIFunktionen_finden_und_speichern\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2021-07-31T10:13:17+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg07.met.vgwort.de\/na\/280458dc65f84b30898c6a959c292c1f\" \/>\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=\"17\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/APIFunktionen_finden_und_speichern\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/APIFunktionen_finden_und_speichern\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"API-Funktionen finden und speichern\",\"datePublished\":\"2021-07-31T10:13:17+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/APIFunktionen_finden_und_speichern\\\/\"},\"wordCount\":2906,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/APIFunktionen_finden_und_speichern\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/280458dc65f84b30898c6a959c292c1f\",\"articleSection\":[\"2021\",\"4\\\/2021\",\"VBA und Programmiertechniken\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/APIFunktionen_finden_und_speichern\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/APIFunktionen_finden_und_speichern\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/APIFunktionen_finden_und_speichern\\\/\",\"name\":\"API-Funktionen finden und speichern - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/APIFunktionen_finden_und_speichern\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/APIFunktionen_finden_und_speichern\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/280458dc65f84b30898c6a959c292c1f\",\"datePublished\":\"2021-07-31T10:13:17+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/APIFunktionen_finden_und_speichern\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/APIFunktionen_finden_und_speichern\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/APIFunktionen_finden_und_speichern\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/280458dc65f84b30898c6a959c292c1f\",\"contentUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/280458dc65f84b30898c6a959c292c1f\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/APIFunktionen_finden_und_speichern\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"API-Funktionen finden und speichern\"}]},{\"@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":"API-Funktionen finden und speichern - 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\/APIFunktionen_finden_und_speichern\/","og_locale":"de_DE","og_type":"article","og_title":"API-Funktionen finden und speichern","og_description":"Eine umfangreiche Access-Anwendung kann in ihrem VBA-Projekt einige API-Deklarationen enthaltenen. Je l&auml;nger diese Anwendung bereits entwickelt wird, desto mehr solcher Deklarationen haben sich im Laufe der Zeit in vielen verschiedenen Modulen angesammelt. Und umso mehr dieser APIs werden vielleicht gar nicht mehr verwendet, weil man sie grunds&auml;tzlich nicht mehr braucht oder sie durch andere Funktionen oder DLLs ersetzt hat. Daher ist es grunds&auml;tzlich interessant, nicht mehr verwendete Deklarationen von API-Funktionen aus der Anwendung zu entfernen. Noch interessanter wird dies, wenn die Migration einer f&uuml;r 32-Bit-Access ausgelegten Anwendung zu einer Anwendung ansteht, die auch unter 64-Bit-Access ihren Dienst tun soll. Je weniger API-Funktionen dann deklariert sind, umso weniger Anpassungen sind notwendig. Im vorliegenden Beitrag schauen wir uns zun&auml;chst an, wie Sie die API-Deklarationen und die gegebenenfalls ben&ouml;tigten Konstanten und Typen &uuml;berhaupt finden.","og_url":"https:\/\/access-im-unternehmen.de\/APIFunktionen_finden_und_speichern\/","og_site_name":"Access im Unternehmen","article_published_time":"2021-07-31T10:13:17+00:00","og_image":[{"url":"http:\/\/vg07.met.vgwort.de\/na\/280458dc65f84b30898c6a959c292c1f","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"17\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/APIFunktionen_finden_und_speichern\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/APIFunktionen_finden_und_speichern\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"API-Funktionen finden und speichern","datePublished":"2021-07-31T10:13:17+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/APIFunktionen_finden_und_speichern\/"},"wordCount":2906,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/APIFunktionen_finden_und_speichern\/#primaryimage"},"thumbnailUrl":"http:\/\/vg07.met.vgwort.de\/na\/280458dc65f84b30898c6a959c292c1f","articleSection":["2021","4\/2021","VBA und Programmiertechniken"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/APIFunktionen_finden_und_speichern\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/APIFunktionen_finden_und_speichern\/","url":"https:\/\/access-im-unternehmen.de\/APIFunktionen_finden_und_speichern\/","name":"API-Funktionen finden und speichern - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/APIFunktionen_finden_und_speichern\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/APIFunktionen_finden_und_speichern\/#primaryimage"},"thumbnailUrl":"http:\/\/vg07.met.vgwort.de\/na\/280458dc65f84b30898c6a959c292c1f","datePublished":"2021-07-31T10:13:17+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/APIFunktionen_finden_und_speichern\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/APIFunktionen_finden_und_speichern\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/APIFunktionen_finden_und_speichern\/#primaryimage","url":"http:\/\/vg07.met.vgwort.de\/na\/280458dc65f84b30898c6a959c292c1f","contentUrl":"http:\/\/vg07.met.vgwort.de\/na\/280458dc65f84b30898c6a959c292c1f"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/APIFunktionen_finden_und_speichern\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"API-Funktionen finden und speichern"}]},{"@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\/55001312","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=55001312"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001312\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55001312"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55001312"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55001312"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}