{"id":55000782,"date":"2011-06-01T00:00:00","date_gmt":"2020-05-22T22:03:39","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=782"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"JavascriptVBABridge","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/JavascriptVBABridge\/","title":{"rendered":"Javascript-VBA-Bridge"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg06.met.vgwort.de\/na\/e7bdd377e53944cebff5d4912058730d\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Es gibt zahlreiche Anwendungsbereiche f&uuml;r einen eingebetteten Webbrowser in Access-Formularen. Ob es um die statische Anzeige von HTML-Dateien geht, um dynamisch generierte Webseiten, die etwa Berichte ausgeben, oder um die Nutzung von Webservices. Microsoft hat dies erkannt und in Access 2010 das neue Webbrowser-Steuerelement eingef&uuml;hrt. W&auml;hrend es einfach ist, den Inhalt einer Webseite von VBA aus zu steuern, sei der Content nun durch Stringverkettung erzeugt oder &uuml;ber das DOM-Objektmodell des Browsers, wird es schwierig, von einer eingebetteten Webseite aus &uuml;ber Skripte auf Access und VBA zuzugreifen, um etwa Daten abzuholen. Wie das dennoch geht, finden Sie im Folgenden beschrieben.<\/b><\/p>\n<p><b>Webbrowser-Steuerelemente<\/b><\/p>\n<p>Bis zu Access 2010 ist es notwendig, den Internet Explorer als ActiveX-Steuerelement in ein Formular einzuf&uuml;gen. &Uuml;ber das Entwurfsmen&uuml; <b>Einf&uuml;gen|ActiveX-Steuerelement&#8230;|Microsoft Web Browser <\/b>wird ein Browser-Fenster im Detailbereich angelegt. Der Internet Explorer, egal in welcher Version, stellt dieses Control von Haus aus zur Verf&uuml;gung. Das Control hat also mit Access oder dessen Installation selbst nichts zu tun.<\/p>\n<p>In Access 2010 bedient man sich der Steuerelementesammlung im Entwurfs-Ribbon und w&auml;hlt das Webbrowser-Steuerelement aus (s. Bild 1).<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2011_03\/WebbrowserVBABridge-web-images\/A2010CtlRibbon.png\" alt=\"A2010CtlRibbon.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 1: Auswahl des Webbrowser-Steuerelements im Entwurf-Ribbon von Access 2010<\/span><\/b><\/p>\n<p>Dieses neue Steuerelement ist im Grunde nichts anderes als ein Wrapper f&uuml;r das ActiveX-Control des Internet Explorers. Es weist somit weitgehend die gleichen Eigenschaften und Methoden auf. Der wesentliche Unterschied besteht darin, dass dieses Element sich direkt an ein Feld der Datenherkunft des Formulars binden l&auml;sst.<\/p>\n<p>Dabei muss es sich um ein Textfeld handeln, das die URL der Seite enth&auml;lt, zu welcher navigiert werden soll. HTML-Code kann man hier nicht direkt &uuml;bergeben.<\/p>\n<p>Dem ActiveX-Control hingegen muss man per VBA sagen, welche Seite es anzeigen soll. Dazu bedient man sich der Methode <b>Navigate2 <\/b>des Objekts:<\/p>\n<pre>Me!ctlWeb.Object.Navigate2 &quot;about:blank&quot;<\/pre>\n<p>In diesem Fall wird eine leere Webseite im Browser angelegt. Tats&auml;chlich funktioniert dasselbe auch mit dem Webbrowser-Steuerelement von Access 2010, das diese Methode eigentlich gar nicht kennt.<\/p>\n<p>Der feine Unterschied liegt hier in der Ansprache einmal des Steuerelements selbst (<b>Me!ctlWeb<\/b>) und davon abweichend des enthaltenen Steuerelements (<b>Me!ctlWeb.Object<\/b>). Das letztere Objekt stellt die <b>Webbrowser<\/b>-Klasse der Bibliothek <b>ShDocVw <\/b>dar, auf die automatisch ein Verweis im VBA-Projekt hinzugef&uuml;gt wird &#8211; sowohl im Falle des ActiveX-Controls, wie auch beim Access 2010-Steuerelement. Damit stehen dann auch im Access 2010-Steuerelement dieselben Eigenschaften und Methoden des DOM-Objektmodells der MSHTML-Bibliothek zur Verf&uuml;gung.<\/p>\n<p>Meist wird man das Steuerelement im Formular so ausstatten, dass es die verf&uuml;gbare Breite einnimmt. Bei ver&auml;nderbaren Formularen ist es dann bis Access 2007 notwendig, im <b>Resize<\/b>-Ereignis des Formulars das Webbrowser-Steuerelement neu zu dimensionieren, indem man seine Eigenschaften <b>Width <\/b>und <b>Height <\/b>setzt.<\/p>\n<p>Das klappt allerdings nur in Access 2003. In fr&uuml;heren Versionen &auml;ndert sich die einmal im gespeicherten Entwurf gesetzte Gr&ouml;&szlig;e nicht und wird auf ewig beibehalten. <\/p>\n<p>Unter Access 2007 und 2010 verwenden Sie daf&uuml;r das Verankern-Feature (Tab <b>Anordnen|Position|Anker<\/b>) und stellen das Control etwa auf <b>Nach unten und quer dehnen <\/b>ein.<\/p>\n<p><b>Web-Inhalte laden<\/b><\/p>\n<p>H&auml;ufig werden Sie einfach nur eine Webseite im Internet darstellen wollen. Das Laden dieser Webseite erledigt wieder die <b>Navigate2<\/b>-Methode des Webbrowsers:<\/p>\n<pre>Me!ctlWeb.Object.Navigate2 &quot;http:\/\/www.access-im-unternehmen.de&quot;<\/pre>\n<p>Ebenso k&ouml;nnen Sie nat&uuml;rlich eine lokal im Dateisystem vorhandene HTML-Datei aufrufen. Als Parameter dient dann der ganz normale Pfad, wie sie ihn auch im Explorer angeben w&uuml;rden.<\/p>\n<p>Interessant wird es, wenn Sie den Inhalt der Webseite dynamisch erzeugen m&ouml;chten. Eine g&auml;ngige Methode ist es, den HTML-Code dabei als String in VBA zusammenzusetzen, diesen lokal als Datei abzuspeichern und die Datei schlie&szlig;lich ins Webbrowser-Steuerelement zu laden. Dabei k&ouml;nnen etwa auch Inhalte aus Tabellen, die &uuml;ber Recordsets ausgelesen werden, zum Zuge kommen. <\/p>\n<p>Einfacher, da ohne Umweg &uuml;ber das Dateisystem, kann dem Browser aber der Inhalt auch direkt zugewiesen werden. Daf&uuml;r gibt es die <b>write<\/b>-Methode des geladenen Dokuments.<\/p>\n<p>Der einzige Grund, das Dateisystem zu bem&uuml;hen, w&auml;ren Webseiten, die Grafiken oder Bilder enthalten. In diesem Fall m&uuml;ssen die Bilddateien parallel zu den aufgerufenen HTML-Dateien im Verzeichnis liegen. Per <b>write <\/b>oder andere Methoden gibt es keine M&ouml;glichkeit, Bildobjekte in eine Seite zu bekommen.<\/p>\n<p>Ausnahme sind hier Systeme mit installiertem Internet Explorer 9, dem man neuerdings &uuml;ber HTML5 oder SVG dynamisch Bilder &uuml;ber Skripte und das MSHTML-Modell zuweisen kann. Aber das w&auml;re Thema f&uuml;r einen weiteren Beitrag.<\/p>\n<p><b>Web-Inhalte schreiben<\/b><\/p>\n<p>Das Vorgehen, um den HTML-Code &uuml;ber die <b>write<\/b>-Methode in die Browser-Seite zu schreiben, l&auml;sst sich anhand <span class=\"verweis-ohneumbruch\"><a href=\"#anker-34-anchor\">Listing 1<\/a><\/span> verdeutlichen, das in der Beispieldatenbank im Formular <b>frmWeb <\/b>zu finden ist.<\/p>\n<p class=\"listingueberschrift\">Listing 1: Webinhalt dynamisch schreiben<\/p>\n<pre>Private Sub cmdScriptor_Click()\r\n    Dim oDoc As Object\r\n    Dim sHTML As String\r\n    CWeb.Navigate2 &quot;about:blank&quot;\r\n    WaitForReady\r\n    Set oDoc = CWeb.Document\r\n    sHTML = &quot;&lt;form&gt;&lt;input type=&quot;&quot;button&quot;&quot; value=&quot;&quot;Knopf&quot;&quot; onClick=&quot;&quot;javascript:alert(''Huhu!'');&quot;&quot;&gt;&lt;\/input&gt;&lt;\/form&gt;&quot;\r\n    oDoc.write sHTML\r\n    oDoc.body.Style.background = CStr(&quot;#D0D0B0&quot;)\r\n    oDoc.write &quot;Seite mit Knopf&quot;\r\nEnd Sub<\/pre>\n<p>Damit die <b>write<\/b>-Methode &uuml;berhaupt angewandt werden kann, muss im Browser bereits ein Dokument geladen sein &#8211; schlie&szlig;lich ist <b>write <\/b>eine Methode des <b>Document<\/b>-Objekts.<\/p>\n<p>Und das l&auml;sst sich am einfachsten erledigen, indem zun&auml;chst eine leere Seite mit <b>about:blank <\/b>erzeugt wird.<\/p>\n<p>In der Prozedur sehen Sie, dass eine Hilfsvariable <b>CWeb <\/b>eingesetzt wird, die in der Prozedur nicht deklariert ist. Diese enth&auml;lt einen Verweis auf das Webbrowser-Steuerelement und ist im Kopf des Moduls so deklariert, dass sie Ereignisse ausl&ouml;sen kann:<\/p>\n<pre>Private WithEvents CWeb As SHDocVw.WebBrowser<\/pre>\n<p>Die Zuweisung geschieht im <b>Load<\/b>-Ereignis des Formulars:<\/p>\n<pre>Set CWeb = Me!ctlWeb.Object<\/pre>\n<p>In weiteren Prozeduren des Formulars kann fortan diese Objektvariable verwendet werden, statt der l&auml;nglichen Form mit dem Verweis auf das Steuerelement. <\/p>\n<p>Nachdem der Browser angewiesen wurde, ein leeres Dokument zu erzeugen, kann auf dieses in VBA noch nicht unmittelbar zugegriffen werden. Der Browser braucht daf&uuml;r einige Zeit, die asynchron zum VBA-Code abl&auml;uft.<\/p>\n<p>Aus diesem Grund gibt es den Aufruf einer Warteschleife, die in die zus&auml;tzliche Prozedur <b>WaitForReady <\/b>ausgelagert ist:<\/p>\n<pre>Private Sub WaitForReady()\r\n    Do\r\n        DoEvents\r\n    Loop Until CWeb.ReadyState &gt;= READYSTATE_INTERACTIVE\r\nEnd Sub<\/pre>\n<p>Der Browser gibt anhand eines Flags der Eigenschaft <b>ReadyState <\/b>kund, wie es um den Zustand des Dokuments bestellt ist. Ist dieser Wert gr&ouml;&szlig;er oder gleich <b>3<\/b>, was der Konstanten <b>READYSTATE_INTERACTIVE <\/b>entspricht, dann steht das Dokument f&uuml;r den Zugriff bereit.<\/p>\n<p>Das geladene Dokument wird im weiteren Verlauf der Objektvariablen <b>oDoc <\/b>zugewiesen, die im Prozedurkopf <b>As Object <\/b>deklariert ist. An sich k&ouml;nnte man daf&uuml;r auch gleich den korrekten Typ <b>HTMLDocument <\/b>verwenden. Doch in diesem Fall streikt VBA beim Aufruf der <b>write<\/b>-Methode wegen inkompatibler Variant-Datentypen.<\/p>\n<p>Im String <b>sHTML <\/b>wird der Inhalt der Seite zusammengestellt. Dabei muss man sich vergegenw&auml;rtigen, dass das leere Dokument bereits durchaus HTML-Code enth&auml;lt &#8211; n&auml;mlich die Elemente <b>HTML <\/b>und <b>BODY<\/b>. Die <b>write<\/b>-Methode schreibt also innerhalb der <b>body<\/b>-Tags.<\/p>\n<p>Wie am Listing zu erkennen ist, k&ouml;nnen dabei auch mehrere <b>write<\/b>-Anweisungen hintereinander folgen. Der Code wird dann sequenziell in die Seite geschrieben.<\/p>\n<p>Um zu demonstrieren, dass die Seite auch anders als durch HTML-Code zu beeinflussen ist, wird ihre Hintergrundfarbe &uuml;ber das DOM-Modell manipuliert, was &uuml;ber die <b>style<\/b>-Eigenschaft <b>background <\/b>des <b>body<\/b>-Elements geschieht.<\/p>\n<p>Nach dem Ausl&ouml;sen der Prozedur &uuml;ber die Schaltfl&auml;che (s. Bild 2) &auml;ndert sich das Browser-Fenster und zeigt die rudiment&auml;re Webseite an.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2011_03\/WebbrowserVBABridge-web-images\/frmWeb.png\" alt=\"frmWeb.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 2: Das per VBA generierte Webformular im Browser-Steuerelement<\/span><\/b><\/p>\n<p>Der HTML-Code der Variablen <b>sHTML <\/b>im Listing besteht aus einem HTML-Formular mit einem <b>input<\/b>-Element, also einer Schaltfl&auml;che, die direkt eine Zeile Javascript ausf&uuml;hrt, n&auml;mlich die Anzeige eines Meldungsfensters.<\/p>\n<p>Es l&auml;sst sich festhalten, dass dem Webbrowser-Steuerelement Web-Inhalte unmittelbar per VBA zugewiesen und dabei auch Javascript-Abschnitte integriert werden k&ouml;nnen.<\/p>\n<p><b>Javascript-Funktionen per VBA aufrufen<\/b><\/p>\n<p>&Uuml;blicherweise werden Javascript-Funktionen in Webseiten dazu verwendet, um auf Aktionen zu reagieren, welche von Ereignissen hervorgerufen werden. In der Regel handelt es sich dabei um Elemente innerhalb eines <b>form<\/b>-Tags, wie eben der <b>input<\/b>-Button in Bild 2.<\/p>\n<p>Andere Ereignisquellen k&ouml;nnten das Laden der Seite selbst sein, Maus-Klick-Events auf bestimmte Elemente oder Zeitgeber, die in Intervallen Aufgaben erledigen sollen.<\/p>\n<p>Geht der Umfang des Scripts &uuml;ber eine Zeile hinaus, dann werden solche Funktionen im Interesse besserer Strukturierung separat in den Quelltext geschrieben, anstatt, wie im Beispiel, das Skript direkt in das <b>Element<\/b>-Tag einzubinden. Der Quelltext h&auml;tte alternativ so wie in <span class=\"verweis-ohneumbruch\"><a href=\"#anker-46-anchor\">Listing 2<\/a><\/span> ausgesehen.<\/p>\n<p class=\"listingueberschrift\">Listing 2: Einfache Webseite mit Javascript-Funktion<\/p>\n<pre>&lt;script type=&quot;text\/javascript&quot;&gt;\r\nfunction fuScript() {\r\n     alert(''Huhuu!'');\r\n}\r\n&lt;\/script&gt;\r\n&lt;form&gt;\r\n    &lt;input type=&quot;button&quot; value=&quot;Knopf&quot; onClick=&quot;fuScript()&quot;\/&gt;\r\n&lt;\/form&gt;<\/pre>\n<p>Hier wird im <b>input<\/b>-Element angegeben, dass auf Klick die Skript-Funktion <b>fuScript <\/b>aufgerufen werden soll.<\/p>\n<p>Interessant w&auml;re nun, wenn sich solche Funktionen, die ja auch weit umfangreicher programmiert sein k&ouml;nnen, nicht nur durch Ereignisse der Webseitenelemente ausf&uuml;hren lie&szlig;en, sondern auch direkt aus VBA heraus.<\/p>\n<p><!--30percent--><\/p>\n<p>Das w&uuml;rde eventuell umfangreiche Manipulationen der Seite &uuml;ber das Objektmodell <b>DOM <\/b>&uuml;berfl&uuml;ssig machen, denn &uuml;ber Javascripte lassen sich Webinhalte erheblich einfacher steuern als &uuml;ber MSHTML. <\/p>\n<p>Tats&auml;chlich ist dies auf verbl&uuml;ffend einfache Weise m&ouml;glich. Das <b>window<\/b>-Objekt des DOM-Modells kennt die Anweisung <b>execScript<\/b>, mit der beliebige Skripte im Quelltext aufgerufen werden k&ouml;nnen. Dabei wird sogar ein etwaiger R&uuml;ckgabewert der Funktion ber&uuml;cksichtigt. An das <b>window<\/b>-Objekt kommt man wiederum einfach &uuml;ber die Eigenschaft <b>parentWindow <\/b>eines geladenen Dokuments.<\/p>\n<p>Dieses <b>window<\/b>-Objekt stellt im Prinzip das Rahmenfenster des Browsers beziehungsweise eines Browser-Tabs dar.<\/p>\n<p>Um das Skript in Listing 2 anzusprechen, reicht eine einzige VBA-Zeile aus:<\/p>\n<pre>Web.Document.parentWindow.execScript &quot;fuScript()&quot;<\/pre>\n<p>Wichtig ist, dass die Klammern f&uuml;r die Funktion mit angegeben werden. Innerhalb dieser Klammern k&ouml;nnen Sie auch Parameter &uuml;bergeben, falls die Javascript-Funktion diese verlangen sollte. Selbstverst&auml;ndlich hat die Parameter-Syntax als String exakt so auszusehen, als w&uuml;rde die Funktion von einem Web-Element oder einem anderen Javascript aufgerufen. <\/p>\n<p>Im Formular <b>frmIDocHost <\/b>der Beispieldatenbank finden Sie ein Beispiel daf&uuml;r. Dort l&ouml;st die Schaltfl&auml;che <b>cmdExecScript <\/b>eine Prozedur aus, welche die Zeile oben aufruft. Nur die Meldung wurde, wie in Bild 3 zu sehen, etwas ver&auml;ndert.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2011_03\/WebbrowserVBABridge-web-images\/frmIDocHost1.png\" alt=\"frmIDocHost1.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 3: Aufruf einer Javascript-Funktion aus VBA heraus<\/span><\/b><\/p>\n<p>Im zweiten Teil des Beitrags zeigen wir Ihnen, wie sich diese Schnittstelle von VBA nach Javascript gewinnbringend einsetzen l&auml;sst, um eine GoogleMaps-Seite zu steuern.<\/p>\n<p><b>VBA-Funktionen von Javascript aus aufrufen<\/b><\/p>\n<p>So einfach sich die Schnittstelle in Richtung Browser gestaltet, so kompliziert wird sie leider in die andere. Woher sollen schlie&szlig;lich eine Webseite oder das Webbrowser-Steuerelement wissen, in welcher Anwendung sie zum Einsatz kommen und wo sie eingebettet sind<\/p>\n<p>Daf&uuml;r gibt es zwei speziell vorbereitete Schnittstellen des Internet Explorers, die Interfaces <b>IDocHostUIHandler <\/b>und <b>ICustomDoc<\/b>. Der Mechanismus sieht im Prinzip so aus:<\/p>\n<p>Ist eine Webseite im Browser geladen, dann fragt das Webbrowser-Steuerelement in der Applikation, die es enth&auml;lt, nach, ob diese das COM-Interface <b>IDocHostUIHandler <\/b>unterst&uuml;tzt.<\/p>\n<p>Im Fall des in einem Access-Formular enthaltenen Webbrowser-Steuerelements ist das die Formularklasse, die befragt wird. Diese muss das Interface implementiert haben.<\/p>\n<p>F&auml;llt die Antwort positiv aus, dann ruft der Browser, je nach Situation und Zustand, verschiedene Methoden des Interfaces auf. Die wichtigste davon ist die Funktion <b>GetExternal<\/b>. Sie verlangt als R&uuml;ckgabewert das Klassenobjekt, das quasi als Rahmen f&uuml;r Skripte im Browser herhalten soll.<\/p>\n<p>Man &uuml;bergibt ihr etwa die Formularklasse, also <b>Me<\/b>. Daraufhin leitet jede Angabe des <b>window.external<\/b>-Objekts in Javascript genau auf diese Klasse und ihre Methoden. Ist etwa im Formular eine VBA-Funktion <b>fuTest() <\/b>untergebracht, dann kann Javascript diese so ansprechen:<\/p>\n<pre>window.external.fuTest();<\/pre>\n<p>Das ist allerdings noch nicht die ganze Wahrheit. Damit der Browser &uuml;berhaupt nach dieser Schnittstelle fragt, ist zuvor noch anzugeben, wo er nachfragen soll, wo sich also die Klasse mit dem implementierten Interface befindet. Diese ist ihm &uuml;ber Umwege mitzuteilen:<\/p>\n<p>Erst muss wieder ein spezielles Interface des Browsers bem&uuml;ht werden, das <b>ICustomDoc<\/b>. Es ist automatisch in jedem geladenen Web-Dokument implementiert.<\/p>\n<p>Man kann deshalb per <b>Set<\/b>-Anweisung ein <b>HTMLDocument <\/b>auf ein <b>ICustomDoc <\/b>casten. Und schlie&szlig;lich &uuml;bergibt man mit dessen Methode <b>SetUIHandler <\/b>dem Browser die Information, dass die Formularklasse das Objekt der Begierde ist.<\/p>\n<p>Wie funktioniert dieses kompliziert wirkende Gebilde nun in der Realit&auml;t<\/p>\n<p><b>Schnittstellen bereitstellen<\/b><\/p>\n<p>Zuerst brauchen wir die Definitionen der Schnittstellen <b>ICustomDoc <\/b>und <b>IDocHostUIHandler<\/b>. Leider sind diese in keiner Bibliothek zu finden, die Windows mitbringen w&uuml;rde. Daher wird eine externe Typbibliothek gebraucht, die diese Interface-Deklarationen enth&auml;lt.<\/p>\n<p>Wie so oft wird man bei E. Morcillos Bibliothek <b>olelib.tlb <\/b>f&uuml;ndig, die einen gro&szlig;en Teil der COM-Interfaces und Objektklassen enth&auml;lt, welche von Windows und seinen Komponenten intern verwendet werden. Die Bibliothek ist Teil des Downloads zu diesem Beitrag, hei&szlig;t aber, da etwas modifiziert, <b>olelib_moss.tlb<\/b>.<\/p>\n<p>Diese Bibliothek muss als Verweis in das VBA-Projekt eingebunden werden. Im Unterschied zu ActiveX-Komponenten muss eine Typbibliothek in Form einer <b>.tlb<\/b>-Datei nicht zwingend im System registriert werden.<\/p>\n<p>Es reicht, wenn VBA die Datei findet. Das ist allerdings eben nicht der Pfad der Datenbankdatei, denn der wird in die Suche nicht einbezogen.<\/p>\n<p>Die <b>.tlb<\/b>-Datei sollte deshalb in das Systemverzeichnis von Windows gespeichert werden, also etwa <b>windows\\system32 <\/b>oder <b>windows\\SysWOW64 <\/b>bei 64bit-Windows. Leider sind hierf&uuml;r wieder mal Administratorrechte n&ouml;tig.<\/p>\n<p><b>Handler definieren<\/b><\/p>\n<p>Nun muss dem Webbrowser-Steuerelement gesagt werden, welche Klasse den <b>IDocUIHost<\/b>-Handler bereitstellt. Wie erw&auml;hnt, l&auml;uft das &uuml;ber das Interface <b>ICustomDoc<\/b>, das seinerseits Bestandteil eines jeglichen Webdokuments ist.<\/p>\n<p>Ein solches muss also zun&auml;chst geladen sein, was abermals &uuml;ber ein leeres mit <b>about:blank <\/b>erzeugtes Dokument l&auml;uft. Ein passendes Ereignis des Webbrowser-Steuerelements schlie&szlig;lich, in dem auf das <b>Document<\/b>-Objekt zugegriffen werden kann, ist <b>DocumentComplete<\/b>.<\/p>\n<p>Im Formular legen Sie also eine Ereignisprozedur daf&uuml;r an und statten sie mit einem Code wie in <span class=\"verweis-ohneumbruch\"><a href=\"#anker-44-anchor\">Listing 3<\/a><\/span> aus.<\/p>\n<p class=\"listingueberschrift\">Listing 3: Setzen des UI-Handlers auf die Formularklasse<\/p>\n<pre>Private Sub ctlWeb_NavigateComplete2(ByVal pDisp As Object, URL As Variant)\r\n    Dim ICDoc As ICustomDoc\r\n    Dim V As Variant\r\n    Set ICDoc = CWeb.Document\r\n    ICDoc.SetUIHandler Me\r\n    Set ICDoc = Nothing\r\nEnd Sub<\/pre>\n<p>Im Verlauf wird zuerst die Hilfsvariable <b>ICDoc <\/b>vom Typ <b>ICustomDoc <\/b>per <b>Set<\/b>-Anweisung auf das Web-Dokument gecastet und dann die Formularklasse <b>Me <\/b>&uuml;ber die Methode <b>SetUIHandler <\/b>&uuml;bergeben.<\/p>\n<p>Anschlie&szlig;end reagiert die Webseite mit dem Abfragen der Handler-Schnittstelle.<\/p>\n<p><b>Handler-Schnittstelle implementieren<\/b><\/p>\n<p>Wie angedeutet, muss die Formularklasse nun das Interface <b>IDocHostUIHandler <\/b>bereitstellen. Die Klasse muss so tun, als h&auml;tte sie diese Schnittstelle eingebaut. Und daf&uuml;r gibt es unter VBA die Direktive <b>Implements<\/b>, die im Kopf des Klassenmoduls unterzubringen ist.<\/p>\n<pre>Implements IDocHostUIHandler<\/pre>\n<p>Sobald das geschehen ist, will VBA beim Kompilieren, dass alle Schnittstellenmethoden in der Klasse vorhanden sind, und meldet sonst einen Fehler (s. Bild 4).<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2011_03\/WebbrowserVBABridge-web-images\/ImplementsError.png\" alt=\"ImplementsError.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 4: Fehlermeldung, wenn nicht alle Methoden einer Schnittstelle vorhanden sind<\/span><\/b><\/p>\n<p>Also w&auml;hlen Sie im linken Kombinationsfeld des Code-Editors erst den Eintrag <b>IDocHostUIHandler <\/b>aus und anschlie&szlig;end aus dem rechten nacheinander die Schnittstellenmethoden.<\/p>\n<p>Dabei werden dann automatisch die passenden Prozedurr&uuml;mpfe angelegt, etwa dieser:<\/p>\n<pre>Private Sub IDocHostUIHandler_EnableModeless(ByVal fEnable As olelib.BOOL)\r\nEnd Sub<\/pre>\n<p>Diese Prozeduren m&uuml;ssen zwar vorhanden sein, interessieren uns aber nicht weiter, bis auf die <b>GetExternal<\/b>-Prozedur, die mit Leben zu f&uuml;llen ist.<\/p>\n<p>Im Formular <b>frmIDocHost <\/b>der Beispieldatenbank sind dennoch rein informativ in die einzelnen Schnittstellenprozeduren Zeilen zur Ausgabe in einem Textfenster enthalten. Sie sehen damit, wie der Browser beim Abfragen der Schnittstelle tickt (s. Bild 5).<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2011_03\/WebbrowserVBABridge-web-images\/UIHandlerMsgs.png\" alt=\"UIHandlerMsgs.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 5: Die Schnittstellenmethoden werden vom Browser aufgerufen<\/span><\/b><\/p>\n<p>Bleibt noch der letzte Teil der &Uuml;bung, n&auml;mlich dem <b>window<\/b>-Objekt des Browsers zu sagen, auf was dessen <b>external<\/b>-Objekt zu verweisen hat:<\/p>\n<pre>Private Function IDocHostUIHandler_GetExternal() As Object\r\n    Set IDocHostUIHandler_GetExternal = Me\r\nEnd Function<\/pre>\n<p>Der R&uuml;ckgabewert der Schnittstellenfunktion ist einfach <b>Me<\/b>, also die Formularklasse selbst. Hier k&ouml;nnte man &uuml;brigens genauso gut eine andere Objektvariable, etwa eines zus&auml;tzlichen Klassenmoduls, angeben.<\/p>\n<p>Damit ist die R&uuml;ckkopplung zwischen Javascript und VBA perfekt. Um die VBA-Funktionen des Formularklassenmoduls aus Javascript aufzurufen, muss nun lediglich deren Namen an das <b>external<\/b>-Objekt angeh&auml;ngt werden:<\/p>\n<pre>window.external.fuFormularfunktion();<\/pre>\n<p>Weist die VBA-Funktion Parameter auf, so sieht der Aufruf etwa dergestalt aus:<\/p>\n<pre>window.external.fuFormularfunktion(8 &euro;&#154;Trowitzsch&euro;&#153;);<\/pre>\n<p>Hier sollte die VBA-Funktion als ersten Parameter eine Zahl enthalten, als zweiten einen String.<\/p>\n<p>Das Gesamtkunstwerk finden Sie im angesprochenen Formular der Beispieldatenbank (s. Bild 5).<\/p>\n<p>Klicken Sie auf der Webseite auf das <b>Button<\/b>-Element, so wird &uuml;ber das <b>External<\/b>-Objekt eine VBA-Funktion im Formular aufgerufen, die schlicht das Quadrat der als Parameter &uuml;bergebenen Zahl berechnet und zur&uuml;ckgibt. Das Javascript zeigt das Ergebnis anschlie&szlig;end mit einem Meldungsfenster an.<\/p>\n<p><b>Praktischer Einsatz<\/b><\/p>\n<p>Die bisherigen Beispiele waren wohl eher didaktischer Natur, auch wenn man sich mit etwas Fantasie allerlei Verwendungszwecke f&uuml;r diese Bridge ausdenken kann.<\/p>\n<p>So k&ouml;nnte man etwa Daten aus einem Recordset an das Javascript &uuml;bergeben und dort weiterverarbeiten, um etwa Tabellen oder Textfelder zu f&uuml;llen.<\/p>\n<p>Weil aber immer wieder Fragen zum Umgang mit in Formulare eingebetteten Google Maps die Runde machen, soll im Weiteren beschrieben werden, wie die Bridge hier sinnvoll eingesetzt werden k&ouml;nnte.<\/p>\n<p><b>Google Maps steuern<\/b><\/p>\n<p>Das Formular <b>frmGooglemaps <\/b>der Beispieldatenbank ist im Prinzip genau so aufgebaut, wie das oben beschriebene Formular mit der Implementation des <b>IDocHostUIHandlers<\/b>.<\/p>\n<p>Nur wird hier die Webseite nicht dynamisch erzeugt, sondern eine Webadresse aufgerufen, in der Code zum Anzeigen einer Google Maps-Karte enthalten ist, wenn Sie auf die Schaltfl&auml;che <b>Maps-URL laden <\/b>klicken. Das sieht dann so aus wie in Bild 6.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2011_03\/WebbrowserVBABridge-web-images\/frmGoogleMaps.png\" alt=\"frmGoogleMaps.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 6: Das Beispielformular mit Webbrowser und geladener Google Maps-Seite<\/span><\/b><\/p>\n<p>Die Funktionalit&auml;t von Google Maps wird komplett &uuml;ber Javascripte erreicht. Wie diese zu programmieren sind, kann an dieser Stelle nicht dargestellt werden, denn die M&ouml;glichkeiten sind zu umfangreich. Wir verweisen auf die API-Dokumentation zu GoogleMaps [2], die auch zahlreiche Code-Beispiele enth&auml;lt, wie die Skripte zu gestalten und die Seiten anzulegen sind.<\/p>\n<p>Den Quelltext finden Sie im Download in der Datei <b>mapsrouter.htm <\/b>und zus&auml;tzlich als kommentierten Text im Modul <b>GooglemapsHTML <\/b>der Datenbank.<\/p>\n<p>Sollten Sie diesen als Basis f&uuml;r eigene Seiten verwenden wollen, dann bedenken Sie, dass der im Kopf des Skript-Codes enthaltene erforderliche API-Key nur f&uuml;r unsere Webadresse gilt und gegen Ihren eigenen ausgetauscht werden muss. Anderenfalls wird Google beim Aufruf der Seite eine entsprechende Meldung ausgeben und einige Funktionen, wie das Routing, deaktivieren.<\/p>\n<p>Unsere Seite ist so aufgebaut, dass sie eigentlich auch ohne Fremdsteuerung ausk&auml;me. Sie k&ouml;nnen die Karte verschieben, den Zoom-Modus einstellen oder zwischen Satelliten- und Kartendarstellung umschalten. Bei einfachem Klick auf die Karte werden Marker auf ihr erstellt, die die Wegpunkte f&uuml;r eine Strecke festhalten, zwischen denen anschlie&szlig;end die Streckenf&uuml;hrung geroutet werden kann. Das Ergebnis k&ouml;nnen Sie in Bild 7 begutachten. <\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2011_03\/WebbrowserVBABridge-web-images\/router.png\" alt=\"router.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 7: Per VBA aufgerufenes Strecken-Routing in GoogleMaps mit Ausgabe der Punktkoordinaten<\/span><\/b><\/p>\n<p>Die Besonderheit besteht darin, dass eine Interaktion zwischen den Skripten der Seite und VBA-Funktionen im Formular stattfindet, wof&uuml;r die zuvor erl&auml;uterte Bridge zum Einsatz kommt.<\/p>\n<p>Zun&auml;chst k&ouml;nnen Sie &uuml;ber eine Formularschaltfl&auml;che das Routing ausl&ouml;sen. Dabei wird eine Javascript-Funktion angesprungen.<\/p>\n<p>Au&szlig;erdem k&ouml;nnen Sie spa&szlig;eshalber ein Tannensymbol mitten in Berlin &uuml;ber die Schaltfl&auml;che <b>Marker setzen <\/b>einf&uuml;gen.<\/p>\n<p>Der Clou aber ist, dass eine Javascript-Funktion nach vollzogenem Routing die einzelnen Punktkoordinaten der Strecke an eine VBA-Funktion im Formular ausgibt, die sie dann im unteren Teil des Formulars in einem Textfeld auflistet. <\/p>\n<p>In diesem Info-Fenster werden zus&auml;tzlich die Weltkoordinaten des Mauszeigers &uuml;ber der Karte ausgegeben, wenn Sie das Kontrollk&auml;stchen <b>MouseOver <\/b>melden aktiviert haben.<\/p>\n<p><b>Interaktion in K&uuml;rze<\/b><\/p>\n<p>Nach dem Laden der Webseite wird die VBA-Javascript-Bridge wie zuvor beschrieben aktiviert. Der Klick auf <b>Marker setzen <\/b>f&uuml;hrt diese Zeile aus:<\/p>\n<pre>CWeb.Document.parentWindow.execScript &quot;vbaMarker(52.6,13.4)&quot;<\/pre>\n<p>Hier wird also eine Javascript-Funktion <b>vbaMarker <\/b>der Seite aufgerufen und es werden ihr als Parameter die L&auml;ngen- und Breitengrade des zu setzenden Markers &uuml;bergeben. Die Skript-Funktion hat dabei den Quelltext aus <span class=\"verweis-ohneumbruch\"><a href=\"#anker-36-anchor\">Listing 4<\/a><\/span>.<\/p>\n<p class=\"listingueberschrift\">Listing 4: Javascript zum Setzen eines Markers in Google Maps<\/p>\n<pre>function vbaMarker(lat,lng){\r\n    alert(''Setze nun Marker auf '' + lat + ''\/'' + lng);\r\n    var coord = new GLatLng(lat,lng);\r\n    map.setCenter(coord, 12);\r\n    marker = new GMarker(coord);\r\n    map.addOverlay(marker);\r\n}<\/pre>\n<p>Die Funktion erwartet die Marker-Koordinate als Eingangsparameter, zeigt diese zur Kontrolle in einem Meldungsfenster an, zentriert die Karte auf den Ort und erzeugt schlie&szlig;lich das Marker-Objekt, welches wiederum auf einem <b>GLatLng<\/b>-Objekt basiert. Der Code zum Setzen des Tan-nensymbols (<b>GIcon<\/b>) f&uuml;r den Marker ist im Listing ausgespart.<\/p>\n<p>Auf &auml;hnliche Weise wird das Routing angesto&szlig;en:<\/p>\n<pre>CWeb.Document.parentWindow.execScript &quot;calculate()&quot;<\/pre>\n<p>Hier das zugeh&ouml;rige Javascript:<\/p>\n<pre>function calculate() {\r\n    map.clearOverlays();\r\n    directions.loadFromWaypoints(points, _\r\n    {avoidHighways:true, _\r\n        travelMode:G_TRAVEL_MODE_WALKING});\r\n}<\/pre>\n<p>In der Routine wird Google Maps gesagt, dass es &uuml;ber das <b>directions<\/b>-Objekt die Strecke finden soll, die zwischen den per Markern gesetzten Punkten liegt, welche zuvor im globalen Array <b>points <\/b>zwischengespeichert wurden.<\/p>\n<p>In geschweiften Klammern sind einige benannte Optionen f&uuml;r die Streckenf&uuml;hrung gesetzt, wie etwa der Fu&szlig;g&auml;nger-Modus.<\/p>\n<p>Danach hat Google zu tun und berechnet die Route.<\/p>\n<p>Wenn es fertig ist, dann teilt es dies der Seite &uuml;ber ein Ereignis mit, welches zuvor beim Laden der Seite erst aktiviert worden sein muss:<\/p>\n<pre>GEvent.addListener(directions, ''load'', calcready);<\/pre>\n<p>Das bedeutet, dass Google Maps die Skript-Funktion <b>calcready <\/b>aufruft, wenn das Ergebnis auf deren Servern vorliegt. Diese Funktion sehen Sie in <span class=\"verweis-ohneumbruch\"><a href=\"#anker-47-anchor\">Listing 5<\/a><\/span>.<\/p>\n<p class=\"listingueberschrift\">Listing 5: Ermitteln der Wegpunkte der Route und &Uuml;bergabe dieser an VBA<\/p>\n<pre>function calcready() {\r\n    pline=directions.getPolyline();\r\n    nodes=pline.getVertexCount();\r\n    window.external.VBAFunction(''message'',''Die Route besteht aus '' + nodes + '' Punkten.'');\r\n    nodes = pline.getVertexCount()\r\n    window.external.VBAFunction(''vertexcount'',nodes);\r\n    for (i = 0; i &lt; nodes; i++) {\r\n        coord = pline.getVertex(i);\r\n        window.external.VBAFunction(''vertexcoord'',coord.lat(),coord.lng());\r\n    }\r\n}<\/pre>\n<p>Das Skript ruft nun gleich dreimal eine VBA-Funktion &uuml;ber das <b>External<\/b>-Objekt im Formular auf, die den Namen <b>VBAFunction <\/b>tr&auml;gt. Diese f&uuml;hrt unterschiedliche Operationen aus, die im ersten angegebenen Parameter gew&uuml;nscht werden &#8211; etwa die Ausgabe der Zahl von Wegpunkten, wenn als Operator der String <b>vertexcount <\/b>angegeben ist.<\/p>\n<p>Man h&auml;tte ebenso drei unterschiedliche Funktionen des Formulars einsetzen k&ouml;nnen, die jede eine bestimmte Aufgabe erf&uuml;llen.<\/p>\n<p>Der &Uuml;bersichtlichkeit halber nahmen wir nur eine Funktion, die den Operator-String innerhalb eines <b>Select Case<\/b>-Statements auswertet und in den einzelnen Zweigen die gew&uuml;nschten Aufgaben erledigt (s. <span class=\"verweis-ohneumbruch\"><a href=\"#anker-45-anchor\">Listing 6<\/a><\/span>).<\/p>\n<p class=\"listingueberschrift\">Listing 6: Die vom Javascript aufgerufene VBA-Prozedur f&uuml;r unterschiedliche Aufgaben<\/p>\n<pre>Public Function VBAFunction(sFunktion As String, _\r\n        Optional Param1 As Variant, Optional Param2 As Variant) As String\r\n    Dim sRet As String\r\n    sRet = &quot;OK&quot;\r\n    Select Case sFunktion\r\n        Case &quot;message&quot;\r\n            OutputText &quot;MESSAGE: &quot; &amp; Param1\r\n        Case &quot;vertexcount&quot;\r\n            OutputText &quot;Punktzahl ist &quot; &amp; Param1\r\n        Case &quot;vertexcoord&quot;\r\n            OutputText &quot;Wegkoordinate: &quot; &amp; Param1 &amp; &quot; \/ &quot; &amp; Param2\r\n        Case &quot;marker&quot;\r\n            OutputText &quot;Marker gesetzt auf &quot; &amp; Param1 &amp; &quot; \/ &quot; &amp; Param2\r\n        Case &quot;mousemove&quot;\r\n            If Me!chkMouseover.Value = True Then\r\n                OutputText &quot;Cursor liegt auf &quot; &amp; Param1 &amp; &quot; \/ &quot; &amp; Param2\r\n            End If\r\n        Case Else\r\n            OutputText &quot;H&auml;&quot;\r\n            sRet = &quot;!Unbekannt!&quot;\r\n    End Select\r\n    VBAFunction = sRet\r\nEnd Function<\/pre>\n<p>Viel passiert hier allerdings nicht. Es werden lediglich Informationen &uuml;ber Operation und Parameter an die Hilfsfunktion <b>OutputText <\/b>&uuml;bergeben, welche ihrerseits die Zeilen in ein Textfeld des Formulars schreibt.<\/p>\n<p>Die vom Skript &uuml;bermittelten Wegkoordinaten lie&szlig;en sich nat&uuml;rlich auch sinnvoller weiterverwenden, indem man sie etwa in einer Tabelle abgespeichert und sie damit sp&auml;ter jederzeit zur Verf&uuml;gung st&uuml;nden.<\/p>\n<p>Interessant ist hier, dass die Funktion zwei optionale Parameter aufnehmen kann. Das Javascript kann also wahlweise zwei, einen oder gar keinen Parameter an das <b>External<\/b>-Objekt &uuml;bergeben. Das lie&szlig;e sich beliebig fortsetzen.<\/p>\n<p>Wie die Wegpunkte in <span class=\"verweis-ohneumbruch\"><a href=\"#anker-45-anchor\">Listing 6<\/a><\/span> ermittelt werden, lassen wir an dieser Stelle au&szlig;en vor und verweisen nochmals auf die Google Maps-API-Referenz [2].<\/p>\n<p><b>Zusammenfassung<\/b><\/p>\n<p>Mit der hier dargestellten Javascript-VBA-Bridge l&auml;sst sich quasi ein Kommunikationskanal zwischen im Webbrowser-Steuerelement geladenen Seiten und VBA herstellen.<\/p>\n<p>Dieser erspart h&auml;ufig das umst&auml;ndliche Steuern von Webseiten &uuml;ber String-Verkettungen, tempor&auml;re HTML-Dateien oder umfangreiche DOM-Aktionen. <\/p>\n<p>Die Kehrseite der Medaille: Ohne einen Verweis auf eine zus&auml;tzliche externe Typbibliothek ist die Sache nicht zu l&ouml;sen.<\/p>\n<p><b>Quellen<\/b><\/p>\n<p class=\"quellen\">[1] IDocHostUIHandler: http:\/\/msdn.microsoft.com\/en-us\/library\/aa753260%28v=vs.85%29.aspx<\/p>\n<p class=\"quellen\">[2] Google Maps API: http:\/\/code.google.com\/intl\/de\/apis\/maps\/documentation\/javascript\/v2\/index.html<\/p>\n<h3>Downloads zu diesem Beitrag<\/h3>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>olelib_moss.tlb<\/p>\n<p>VBAJavascript.mdb<\/p>\n<p>VBAJavascript2010.accdb<\/p>\n<p>mapsrouter.htm<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/{195C551E-E4FE-42AC-AA39-7FAE548B8453}\/aiu_782.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Es gibt zahlreiche Anwendungsbereiche f&uuml;r einen eingebetteten Webbrowser in Access-Formularen. Ob es um die statische Anzeige von HTML-Dateien geht, um dynamisch generierte Webseiten, die etwa Berichte ausgeben, oder um die Nutzung von Webservices. Microsoft hat dies erkannt und in Access 2010 das neue Webbrowser-Steuerelement eingef&uuml;hrt. W&auml;hrend es einfach ist, den Inhalt einer Webseite von VBA aus zu steuern, sei der Content nun durch Stringverkettung erzeugt oder &uuml;ber das DOM-Objektmodell des Browsers, wird es schwierig, von einer eingebetteten Webseite aus &uuml;ber Skripte auf Access und VBA zuzugreifen, um etwa Daten abzuholen. Wie das dennoch geht, finden Sie im Folgenden beschrieben.<\/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":[662011,66032011,44000026],"tags":[],"class_list":["post-55000782","post","type-post","status-publish","format-standard","hentry","category-662011","category-66032011","category-Interaktiv"],"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>Javascript-VBA-Bridge - 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\/JavascriptVBABridge\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Javascript-VBA-Bridge\" \/>\n<meta property=\"og:description\" content=\"Es gibt zahlreiche Anwendungsbereiche f&uuml;r einen eingebetteten Webbrowser in Access-Formularen. Ob es um die statische Anzeige von HTML-Dateien geht, um dynamisch generierte Webseiten, die etwa Berichte ausgeben, oder um die Nutzung von Webservices. Microsoft hat dies erkannt und in Access 2010 das neue Webbrowser-Steuerelement eingef&uuml;hrt. W&auml;hrend es einfach ist, den Inhalt einer Webseite von VBA aus zu steuern, sei der Content nun durch Stringverkettung erzeugt oder &uuml;ber das DOM-Objektmodell des Browsers, wird es schwierig, von einer eingebetteten Webseite aus &uuml;ber Skripte auf Access und VBA zuzugreifen, um etwa Daten abzuholen. Wie das dennoch geht, finden Sie im Folgenden beschrieben.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/JavascriptVBABridge\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2020-05-22T22:03:39+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg06.met.vgwort.de\/na\/e7bdd377e53944cebff5d4912058730d\" \/>\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=\"21\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/JavascriptVBABridge\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/JavascriptVBABridge\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Javascript-VBA-Bridge\",\"datePublished\":\"2020-05-22T22:03:39+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/JavascriptVBABridge\\\/\"},\"wordCount\":3748,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/JavascriptVBABridge\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg06.met.vgwort.de\\\/na\\\/e7bdd377e53944cebff5d4912058730d\",\"articleSection\":[\"2011\",\"3\\\/2011\",\"Interaktiv\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/JavascriptVBABridge\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/JavascriptVBABridge\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/JavascriptVBABridge\\\/\",\"name\":\"Javascript-VBA-Bridge - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/JavascriptVBABridge\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/JavascriptVBABridge\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg06.met.vgwort.de\\\/na\\\/e7bdd377e53944cebff5d4912058730d\",\"datePublished\":\"2020-05-22T22:03:39+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/JavascriptVBABridge\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/JavascriptVBABridge\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/JavascriptVBABridge\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg06.met.vgwort.de\\\/na\\\/e7bdd377e53944cebff5d4912058730d\",\"contentUrl\":\"http:\\\/\\\/vg06.met.vgwort.de\\\/na\\\/e7bdd377e53944cebff5d4912058730d\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/JavascriptVBABridge\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Javascript-VBA-Bridge\"}]},{\"@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":"Javascript-VBA-Bridge - 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\/JavascriptVBABridge\/","og_locale":"de_DE","og_type":"article","og_title":"Javascript-VBA-Bridge","og_description":"Es gibt zahlreiche Anwendungsbereiche f&uuml;r einen eingebetteten Webbrowser in Access-Formularen. Ob es um die statische Anzeige von HTML-Dateien geht, um dynamisch generierte Webseiten, die etwa Berichte ausgeben, oder um die Nutzung von Webservices. Microsoft hat dies erkannt und in Access 2010 das neue Webbrowser-Steuerelement eingef&uuml;hrt. W&auml;hrend es einfach ist, den Inhalt einer Webseite von VBA aus zu steuern, sei der Content nun durch Stringverkettung erzeugt oder &uuml;ber das DOM-Objektmodell des Browsers, wird es schwierig, von einer eingebetteten Webseite aus &uuml;ber Skripte auf Access und VBA zuzugreifen, um etwa Daten abzuholen. Wie das dennoch geht, finden Sie im Folgenden beschrieben.","og_url":"https:\/\/access-im-unternehmen.de\/JavascriptVBABridge\/","og_site_name":"Access im Unternehmen","article_published_time":"2020-05-22T22:03:39+00:00","og_image":[{"url":"http:\/\/vg06.met.vgwort.de\/na\/e7bdd377e53944cebff5d4912058730d","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"21\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/JavascriptVBABridge\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/JavascriptVBABridge\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Javascript-VBA-Bridge","datePublished":"2020-05-22T22:03:39+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/JavascriptVBABridge\/"},"wordCount":3748,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/JavascriptVBABridge\/#primaryimage"},"thumbnailUrl":"http:\/\/vg06.met.vgwort.de\/na\/e7bdd377e53944cebff5d4912058730d","articleSection":["2011","3\/2011","Interaktiv"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/JavascriptVBABridge\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/JavascriptVBABridge\/","url":"https:\/\/access-im-unternehmen.de\/JavascriptVBABridge\/","name":"Javascript-VBA-Bridge - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/JavascriptVBABridge\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/JavascriptVBABridge\/#primaryimage"},"thumbnailUrl":"http:\/\/vg06.met.vgwort.de\/na\/e7bdd377e53944cebff5d4912058730d","datePublished":"2020-05-22T22:03:39+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/JavascriptVBABridge\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/JavascriptVBABridge\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/JavascriptVBABridge\/#primaryimage","url":"http:\/\/vg06.met.vgwort.de\/na\/e7bdd377e53944cebff5d4912058730d","contentUrl":"http:\/\/vg06.met.vgwort.de\/na\/e7bdd377e53944cebff5d4912058730d"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/JavascriptVBABridge\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Javascript-VBA-Bridge"}]},{"@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\/55000782","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=55000782"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55000782\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55000782"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55000782"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55000782"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}