{"id":55000039,"date":"2016-06-01T00:00:00","date_gmt":"2020-03-27T19:20:13","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=39"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"CDLL_fuer_COMVBA_erstellen","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/CDLL_fuer_COMVBA_erstellen\/","title":{"rendered":"C#-DLL f&uuml;r COM\/VBA erstellen"},"content":{"rendered":"<p><b>Das .NET-Framework bietet im Vergleich zu VBA eine schier unendliche Menge nutzbarer Bibliotheken mit Objekten, Methoden und Eigenschaften f&uuml;r die verschiedensten Anwendungsf&auml;lle. Wer noch nicht komplett auf eine .NET-Anwendung umsteigen m&ouml;chte, mag sich aber vielleicht die M&ouml;glichkeiten des Frameworks unter VBA erschlie&szlig;en. Dazu programmieren Sie eine DLL-Bibliothek, welche die ben&ouml;tigen .NET-Elemente enth&auml;lt und f&uuml;r externe Anwendungen wie etwa eine Access-Datenbank bereith&auml;lt. Der vorliegende Artikel erkl&auml;rt, wie dies funktioniert.<\/b><\/p>\n<h2>Grundlagen<\/h2>\n<p>Wenn es darum geht, von einem VBA-Projekt etwa auf die Methoden einer mit C# programmierten DLL zuzugreifen, ben&ouml;tigen Sie eine Technologie namens COM (Component Object Model). Diese wurde von Microsoft bereits vor einer ganzen Weile eingef&uuml;hrt, n&auml;mlich in den fr&uuml;hen neunziger Jahren. Das Ziel war, dass Komponenten, die mit verschiedenen Programmiersprachen programmiert wurden, miteinander kommunizieren k&ouml;nnen.<\/p>\n<p>COM liefert die Vorgaben f&uuml;r die Schnittstellen, die diese Interaktion erm&ouml;glichen. Damit nun auch noch Komponenten, die auf .NET basieren, mit COM-Objekten zusammenarbeiten, gibt es eine weitere Technologie, die sich COM Interop nennt. Diese erlaubt es beispielsweise, die in einer .NET-DLL definierten Objekte, Methoden und Eigenschaften auch f&uuml;r eine COM-Komponente zug&auml;nglich zu machen.<\/p>\n<p>Eine .NET-Komponente ist beispielsweise eine DLL-Datei. Damit Sie von COM-Objekten auf diese DLL-Datei zugreifen k&ouml;nnen, m&uuml;ssen Sie zun&auml;chst eine COM-Type Library (<b>.tlb<\/b>) erstellen, welche die relevanten Informationen bereith&auml;lt. Dies erledigen Sie mit einem Befehlszeilentool namens <b>REGASM.EXE <\/b>oder <b>TLBEXP.EXE<\/b>.<\/p>\n<h2>Wichtig: Admin-Modus!<\/h2>\n<p>Wenn Sie eine DLL erstellen und registrieren m&ouml;chten, m&uuml;ssen Sie Visual Studio als Administrator ausf&uuml;hren. Dazu klicken Sie mit der rechten Maustaste auf den Visual Studio-Eintrag, der beispielsweise erscheint, wenn Sie im Suchfeld den Suchbegriff <b>Visual Studio <\/b>eingeben. Im folgenden Kontextmen&uuml; w&auml;hlen Sie den Eintrag <b>Als Administrator ausf&uuml;hren<\/b> aus (siehe Bild 1). In diesem Modus k&ouml;nnen die notwendigen Registry-Eintr&auml;ge gesetzt werden.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2016_03\/pic_39_004.png\" alt=\"Visual Studio als Administrator starten\" width=\"299,6891\" height=\"475,0795\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Visual Studio als Administrator starten<\/span><\/b><\/p>\n<h2>Stolperfalle: DLL in Verwendung<\/h2>\n<p>Sollten Sie die DLL bereits einmal erstellt haben, wollen Sie diese nat&uuml;rlich im VBA-Projekt einer Access-Anwendung testen. Wenn Sie die DLL etwa per Verweis referenzieren und die Datenbank ge&ouml;ffnet ist, kann die referenzierte DLL nicht &uuml;berschrieben werden, da diese schreibgesch&uuml;tzt ist. Sollten Sie das C#-Projekt mit der DLL zu diesem Zeitpunkt also in Visual Studio editieren und neu erstellen wollen, gelingt dies nicht, da die DLL ja nicht &uuml;berschrieben werden kann. Dies erfahren Sie dann auch im Bereich <b>Fehlerliste<\/b> (siehe Bild 2).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2016_03\/pic_39_005.png\" alt=\"Fehler beim Versuch, eine aktuell in Verwendung befindliche DLL neu zu erstellen\" width=\"700\" height=\"160,8275\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Fehler beim Versuch, eine aktuell in Verwendung befindliche DLL neu zu erstellen<\/span><\/b><\/p>\n<p>Also, auch wenn es mit der Zeit nervt: Nicht vergessen, die Anwendung, mit der Sie die DLL testen, vor dem Neuerstellen der DLL zu schlie&szlig;en. Aber: Es gibt eine einfachere Methode, die wir weiter unten nach der Erstellung des ersten Beispiels erl&auml;utern.<\/p>\n<h2>DLL erstellen<\/h2>\n<p>Um eine DLL zu erstellen, deren Funktionen Sie sp&auml;ter von einem VBA-Projekt n&uuml;tzen k&ouml;nnen, legen Sie in Visual Studio ein Projekt auf Basis der Vorlage <b>Klassenbibliothek <\/b>an (siehe Bild 3). &Auml;ndern Sie den Namen der automatisch hinzugef&uuml;gten Klassendatei namens <b>Class1 <\/b>in <b>LateBinding <\/b>um und erledigen Sie dies auch f&uuml;r den Klassennamen selbst.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2016_03\/pic_39_001.png\" alt=\"Hinzuf&uuml;gen eines Projekts, das wir als DLL verwenden k&ouml;nnen\" width=\"599,378\" height=\"380,4146\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Hinzuf&uuml;gen eines Projekts, das wir als DLL verwenden k&ouml;nnen<\/span><\/b><\/p>\n<p>Danach f&uuml;gen Sie dem Klassenmodul den folgenden einfachen Code hinzu. Die Klasse deklariert zwei Variablen namens <b>zahl1 <\/b>und <b>zahl2<\/b>, die &uuml;ber die Eigenschaften <b>Zahl1 <\/b>und <b>Zahl2 <\/b>gef&uuml;llt werden sollen. Die Methode <b>Produkt <\/b>soll dann das Produkt der beiden Zahlen zur&uuml;ckliefern:<\/p>\n<pre>namespace DLLFuerVBA {\r\n     public class NoIntelliSense {\r\n         int zahl1;\r\n         int zahl2;\r\n         public int Zahl1 {\r\n             set { zahl1 = value; }\r\n         }\r\n         public int Zahl2 {\r\n             set { zahl2 = value; }\r\n         }\r\n         public int Produkt() {\r\n             return zahl1 * zahl2;\r\n         }\r\n     }\r\n}<\/pre>\n<p>Dass wir die Klasse <b>NoIntelliSense <\/b>nennen, hat seinen Grund &#8211; mehr dazu weiter unten.<\/p>\n<p>Der Clou ist nun, dass diese Klasse nicht innerhalb des C#-Projekts genutzt werden soll, sondern von einem VBA-Projekt in einer Access-Anwendung. Dazu sind zwei bereits durchgef&uuml;hrte und noch zwei weitere Schritte notwendig:<\/p>\n<ul>\n<li>Der erste bereits erledigte Schritt ist, dass die Klassendefinition als <b>Public <\/b>deklariert wird.<\/li>\n<li>Der zweite Schritt war, dass auch die Member der Klasse, die von au&szlig;en erreicht werden sollen, das Schl&uuml;sselwort <b>Public <\/b>enthalten.<\/li>\n<li>Der dritte Schritt ist, dass Sie die Option <b>F&uuml;r COM-Interop registrieren <\/b>aktivieren (siehe weiter unten).<\/li>\n<li>Der vierte Schritt ist das Aktivieren der Option <b>Assembly COM-sichtbar machen <\/b>(siehe ebenfalls weiter unten).<\/li>\n<\/ul>\n<h2>F&uuml;r COM-Interop registrieren<\/h2>\n<p>Die Option <b>F&uuml;r COM-Interop registrieren <\/b>finden Sie, wenn Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Projektnamen klicken, den Eintrag <b>Eigenschaften <\/b>anklicken und im dann erscheinenden Fenster zum Bereich <b>Erstellen <\/b>wechseln. Unten unter <b>Ausgabe<\/b> finden Sie die gesuchte Option, die Sie per Klick auf das Kontrollk&auml;stchen aktivieren (siehe Bild 4). Wenn Sie diese Option nicht aktivieren, erstellt Visual Studio beim Erstellen des Projekts im Unterordner <b>\\bin\\debug <\/b>nur die &uuml;bliche <b>.dll<\/b>-Datei plus einer <b>.pdb<\/b>-Datei. Damit Sie die DLL von einem VBA-Projekt aus nutzen k&ouml;nnen, m&uuml;ssen Sie diese jedoch entsprechend registrieren. Das k&ouml;nnen Sie auf zwei Arten erledigen &#8211; entweder mit einem Kommandozeilentool oder durch die Aktivierung der obigen Option vor dem Erstellen des Projekts. Dabei werden zwei Schritte durchgef&uuml;hrt: Visual Studio erstellt eine weitere Datei mit der Endung <b>.tlb<\/b>, welche die Definition der Schnittstelle enth&auml;lt, die Sie sp&auml;ter vom VBA-Projekt aus nutzen k&ouml;nnen. Au&szlig;erdem legt Visual Studio auch gleich einige Eintr&auml;ge in der Registry an, damit Sie die Bibliothek &uuml;ber den Verweise-Dialog des VBA-Editors ausw&auml;hlen k&ouml;nnen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2016_03\/pic_39_006.png\" alt=\"Einstellen der Option F&uuml;r COM-Interop registrieren\" width=\"549,43\" height=\"493,6336\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Einstellen der Option F&uuml;r COM-Interop registrieren<\/span><\/b><\/p>\n<h2>Assembly COM-sichtbar machen<\/h2>\n<p>Der zweite notwendige Schritt ist wieder mit dem Setzen einer einfachen Option erledigt. Diese ist jedoch etwas besser versteckt. Wechseln Sie in den Projekteigenschaften zum Bereich <b>Anwendungen <\/b>und klicken Sie dort auf die Schaltfl&auml;che <b>Assemblyinformationen<\/b>. Dies &ouml;ffnet den Dialog <b>Assemblyinformationen<\/b>, der wie in Bild 5 aussieht. Hier aktivieren Sie im unteren Bereich die Option <b>Assembly COM-sichtbar machen <\/b>und schlie&szlig;en den Dialog wieder.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2016_03\/pic_39_007.png\" alt=\"Aktivieren der Option Assembly COM-sichtbar machen\" width=\"549,43\" height=\"491,4237\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Aktivieren der Option Assembly COM-sichtbar machen<\/span><\/b><\/p>\n<h2>Einfaches Projekt erstellen<\/h2>\n<p>Wenn Sie nun das Projekt mit dem obigen Code erstellen, legt Visual Studio einige Eintr&auml;ge in der Registry des aktuellen Rechners an. Der erste Eintrag, der f&uuml;r uns wichtig ist, befindet sich in der Registry, die Sie mit dem Befehl <b>RegEdit <\/b>&ouml;ffnen, unter dem Pfad <b>HKEY_CLASSES_ROOT\\DLLFuerVBA.LateBinding<\/b>. Die wichtige Information dieses Pfades befindet sich im Schl&uuml;ssel CLSID. Dort finden Sie n&auml;mlich eine GUID, die auf den Schl&uuml;ssel mit weiteren Informationen hinweist (siehe Bild 6).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2016_03\/pic_39_008.png\" alt=\"Erster Eintrag in der Registry\" width=\"549,43\" height=\"148,3389\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Erster Eintrag in der Registry<\/span><\/b><\/p>\n<p>Diesen finden Sie in unserem Beispiel unter folgendem Pfad (die GUID kann variieren): <b>HKEY_CLASSES_ROOT\\WOW6432Node\\CLSID\\{190B6748-30DB-391F-952E-9EE41A931356}<\/b>. Unterhalb dieses Schl&uuml;ssels finden Sie den Schl&uuml;ssel <b>InprocServer32<\/b>, der einige Informationen liefert (siehe Bild 7).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2016_03\/pic_39_009.png\" alt=\"Details zur Registrierung der DLL\" width=\"700\" height=\"166,1479\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Details zur Registrierung der DLL<\/span><\/b><\/p>\n<h2>Objektbibliothek verf&uuml;gbar<\/h2>\n<p>Zu diesem Zeitpunkt k&ouml;nnen Sie auch bereits einen Verweis vom VBA-Projekt einer Access-Datenbank auf die DLL beziehungsweise die erstellte <b>.tlb<\/b>-Datei setzen &#8211; dazu &ouml;ffnen Sie einfach den <b>Verweise<\/b>-Dialog (VBA-Editor, Men&uuml;eintrag <b>Extras|Verweise<\/b>) und suchen den Eintrag <b>DLLFuerVBA <\/b>(siehe Bild 8).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2016_03\/pic_39_010.png\" alt=\"Der Verweis auf die Objektbibliothek l&auml;sst sich bereits setzen.\" width=\"424,5595\" height=\"334,696\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 8: Der Verweis auf die Objektbibliothek l&auml;sst sich bereits setzen.<\/span><\/b><\/p>\n<p>Wenn wir uns das Objekt nun allerdings im Objektkatalog ansehen, finden wir dort noch keine Eigenschaften, Methoden oder Ereignisse (siehe Bild 9).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2016_03\/pic_39_011.png\" alt=\"Der Objektkatalog offenbart keinerlei Eigenschaften, Methoden oder Ereignisse.\" width=\"424,5595\" height=\"368,6029\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 9: Der Objektkatalog offenbart keinerlei Eigenschaften, Methoden oder Ereignisse.<\/span><\/b><\/p>\n<p>Nun erfahren Sie, warum wir unsere erste Klasse <b>NoIntelliSense <\/b>genannt haben: Wie zu erwarten, finden sich nicht nur keine Elemente im Objektkatalog, sondern auch der Versuch, per IntelliSense auf die Eigenschaften eines Objekts auf Basis der Klasse <b>DLLFuerVBA.NoIntelliSense <\/b>zuzugreifen, schl&auml;gt fehl. Immerhin k&ouml;nnen wir die Eigenschaften <b>Zahl1 <\/b>und <b>Zahl2 <\/b>sowie die Methode <b>Produkt <\/b>&uuml;berhaupt nutzen:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>Test_EarlyBinding()\r\n     <span style=\"color:blue;\">Dim <\/span>obj<span style=\"color:blue;\"> As <\/span>DLLFuerVBA.NoIntelliSense\r\n     <span style=\"color:blue;\">Set<\/span> obj = <span style=\"color:blue;\">New<\/span> DLLFuerVBA.NoIntelliSense\r\n     <span style=\"color:blue;\">With<\/span> obj\r\n         .Zahl1 = 2\r\n         .Zahl2 = 3\r\n         <span style=\"color:blue;\">Debug.Print<\/span> .Produkt\r\n     End <span style=\"color:blue;\">With<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<div class=\"rcp_restricted\"><p><span style=\"color: #ff0000;\">M&ouml;chten Sie weiterlesen? Dann l&ouml;sen Sie Ihr Ticket!<\/span><br \/>\n<span style=\"color: #ff0000;\">Hier geht es zur Bestellung des Jahresabonnements des Magazins <strong>Visual Basic Entwickler<\/strong>:<\/span><br \/>\n<span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/shop.minhorst.com\/magazine\/363\/visual-basic-entwickler-jahresabonnement?c=77\">Zur Bestellung ...<\/a><\/span><br \/>\n<span style=\"color: #ff0000;\">Danach greifen Sie sofort auf <strong>alle rund 200 Artikel<\/strong> unseres Angebots zu - auch auf diesen hier!<\/span><br \/>\n<span style=\"color: #000000;\">Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:<\/span><\/p>\n<\/div>\n\n\t\n\t<form id=\"rcp_login_form\"  class=\"rcp_form\" method=\"POST\" action=\"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000039\/\">\n\n\t\t\n\t\t<fieldset class=\"rcp_login_data\">\n\t\t\t<p>\n\t\t\t\t<label for=\"rcp_user_login\">Username or Email<\/label>\n\t\t\t\t<input name=\"rcp_user_login\" id=\"rcp_user_login\" class=\"required\" type=\"text\"\/>\n\t\t\t<\/p>\n\t\t\t<p>\n\t\t\t\t<label for=\"rcp_user_pass\">Password<\/label>\n\t\t\t\t<input name=\"rcp_user_pass\" id=\"rcp_user_pass\" class=\"required\" type=\"password\"\/>\n\t\t\t<\/p>\n\t\t\t\t\t\t<p>\n\t\t\t\t<input type=\"checkbox\" name=\"rcp_user_remember\" id=\"rcp_user_remember\" value=\"1\"\/>\n\t\t\t\t<label for=\"rcp_user_remember\">Remember me<\/label>\n\t\t\t<\/p>\n\t\t\t<p class=\"rcp_lost_password\"><a href=\"\/data\/wp\/v2\/posts\/55000039?rcp_action=lostpassword\"><\/a><\/p>\n\t\t\t<p>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_action\" value=\"login\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_redirect\" value=\"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000039\/\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_login_nonce\" value=\"123b777de9\"\/>\n\t\t\t\t<input id=\"rcp_login_submit\" class=\"rcp-button\" type=\"submit\" value=\"Login\"\/>\n\t\t\t<\/p>\n\t\t\t\t\t<\/fieldset>\n\n\t\t\n\t<\/form>\n<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Das .NET-Framework bietet im Vergleich zu VBA eine schier unendliche Menge nutzbarer Bibliotheken mit Objekten, Methoden und Eigenschaften f&uuml;r die verschiedensten Anwendungsf&auml;lle. Wer noch nicht komplett auf eine .NET-Anwendung umsteigen m&ouml;chte, mag sich aber vielleicht die M&ouml;glichkeiten des Frameworks unter VBA erschlie&szlig;en. Dazu programmieren Sie eine DLL-Bibliothek, welche die ben&ouml;tigen .NET-Elemente enth&auml;lt und f&uuml;r externe Anwendungen wie etwa eine Access-Datenbank bereith&auml;lt. Der vorliegende Artikel erkl&auml;rt, wie dies funktioniert.<\/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":[662016,66032016,44000009,44000027,44000012],"tags":[],"yst_prominent_words":[],"class_list":["post-55000039","post","type-post","status-publish","format-standard","hentry","category-662016","category-66032016","category-CProgrammiertechnik","category-Excel_programmieren","category-Interaktiv"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000039","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/comments?post=55000039"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000039\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000039"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000039"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000039"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000039"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}