{"id":55001422,"date":"2023-04-01T00:00:00","date_gmt":"2023-06-17T09:30:51","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=1422"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Zugriff_auf_lexoffice_per_RESTAPI_und_VBA","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\/","title":{"rendered":"Zugriff auf lexoffice per REST-API und VBA"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg08.met.vgwort.de\/na\/d98152f168a84f7aaa8191dcc8adf564\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>lexoffice ist ein Online-Buchhaltungsdienst, der es Unternehmen erm&ouml;glicht, Rechnungen, Bestellungen und Bankkonten zu verwalten und Berichte zu erstellen. Der Service bietet ein einfaches Dashboard, mit dem Benutzer Gesch&auml;ftsinformationen leicht auffinden und mit wenigen Klicks auswerten k&ouml;nnen. Rechnungen lassen sich online oder &uuml;ber die mobile App erstellen, Ums&auml;tze auf Bank- oder Paypalkonten liest lexoffice automatisch ein und es erm&ouml;glicht die Zuordnung von Ein- und Ausgangsrechnungen zu den Ums&auml;tzen. Aber das Beste ist: lexoffice bietet eine REST-API-Schnittstelle, die wir von einer Access-Datenbank aus per VBA ansteuern k&ouml;nnen. Grund genug, diese Schnittstelle einmal genauer anzusehen!<\/b><\/p>\n<h2>Von Access zu lexoffice<\/h2>\n<p>Die besten Beitr&auml;ge schreibt das Leben, und so ist auch f&uuml;r die Entstehung dieses Beitrags ein Schritt des Autors f&uuml;r das aktuelle Thema verantwortlich. Die Buchhaltung soll umgezogen werden, um den aktuellen Randparametern gerecht zu werden &#8211; zum Beispiel den Grunds&auml;tzen ordnungsgem&auml;&szlig;er F&uuml;hrung und Aufbewahrung von B&uuml;chern, Aufzeichnungen und Unterlagen in elektronischer Form sowie zum Datenzugriff (<b>GoBD<\/b>). Als Werkzeug f&uuml;r diese Aufgaben haben wir <b>lexoffice <\/b>ausgew&auml;hlt.<\/p>\n<p>Damit entstehen einige Aufgaben:<\/p>\n<ul>\n<li>Einige offene Rechnungen von 2022, die erst in 2023 beglichen wurden, sollen noch aufgenommen werden.<\/li>\n<li>Diese Rechnungen m&uuml;ssen als PDF importiert werden und wir m&uuml;ssen diesen noch Daten zum Rechnungsempf&auml;nger und einige weitere Daten hinzuf&uuml;gen.<\/li>\n<li>Um die Kundendaten nicht manuell eintragen zu m&uuml;ssen, wollen wir die relevanten Datens&auml;tze mit der API aus der Datenbank nach <b>lexoffice <\/b>&uuml;bertragen.<\/li>\n<li>Schlie&szlig;lich sollen neue Bestellungen direkt komplett mit <b>lexoffice<\/b> verwaltet werden. Diese kommen zum Teil aus dem Shopsystem, wozu es eine Schnittstelle gibt (die hier nicht Thema sein wird) und teilweise aus der Access-Bestellverwaltung. Bei letzteren handelt es sich um Rechnungen f&uuml;r die Verl&auml;ngerung von Abonnements.<\/li>\n<\/ul>\n<h2>Vorbereitungen f&uuml;r den Zugriff auf die API von lexoffice<\/h2>\n<p>Wie bei den meisten API, auf die wir von au&szlig;erhalb zugreifen wollen, ben&ouml;tigen wir auch hier eine M&ouml;glichkeit zur Authentifizierung.<\/p>\n<p>Dazu legen wir in <b>lexoffice<\/b> zun&auml;chst einen pers&ouml;nlichen Schl&uuml;ssel an. Um das zu erledigen, rufen wir nach dem Einloggen in unseren Account bei lexware den folgenden Link auf:<\/p>\n<pre>https:\/\/app.lexoffice.de\/addons\/public-api<\/pre>\n<p>Damit landen wir auf einer Seite, wo wir per Mausklick einen passenden Schl&uuml;ssel erstellen k&ouml;nnen (siehe Bild 1). Anschlie&szlig;end stimmen wir den Nutzungsbedingungen zu und erstellen den Schl&uuml;ssel.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2023_02\/pic_1422_001.png\" alt=\"Anfordern eines pers&ouml;nlichen Schl&uuml;ssels f&uuml;r die REST-Api\" width=\"649,559\" height=\"534,5775\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Anfordern eines pers&ouml;nlichen Schl&uuml;ssels f&uuml;r die REST-Api<\/span><\/b><\/p>\n<p>Im n&auml;chsten Schritt zeigt <b>lexoffice<\/b> den Schl&uuml;ssel bereits an und bietet die M&ouml;glichkeit, diesen per Schaltfl&auml;che in die Zwischenablage zu kopieren (siehe Bild 2).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2023_02\/pic_1422_002.png\" alt=\"Kopieren des Schl&uuml;ssels in die Zwischenablage\" width=\"524,559\" height=\"404,3112\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Kopieren des Schl&uuml;ssels in die Zwischenablage<\/span><\/b><\/p>\n<p>Um diesen dauerhaft zu sichern, legen wir in einem neuen VBA-Modul eine Konstante mit diesem Schl&uuml;ssel an:<\/p>\n<pre><span style=\"color:blue;\">Public <\/span>Const cstrAPIKey<span style=\"color:blue;\"> As String<\/span> = \"xxxxxxxxxxx-xxxxxxxx-xxxx\"<\/pre>\n<p>Anschlie&szlig;end schlie&szlig;en wir den Dialog.<\/p>\n<h2>Datenbank vorbereiten<\/h2>\n<p>F&uuml;r die nachfolgend vorgestellten VBA-Routinen ben&ouml;tigen wir im VBA-Projekt zus&auml;tzliche Verweise. Diese legen wir &uuml;ber den <b>Verweise<\/b>-Dialog an, den wir nach dem Aktivieren des VBA-Editors mit <b>Extras|Verweise <\/b>&ouml;ffnen (siehe Bild 3).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2023_02\/pic_1422_003.png\" alt=\"Verweise im VBA-Projekt\" width=\"499,5589\" height=\"393,8207\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Verweise im VBA-Projekt<\/span><\/b><\/p>\n<p>Wir ben&ouml;tigen die folgenden zus&auml;tzlichen Verweise:<\/p>\n<ul>\n<li><b>Microsoft XML, v6.0<\/b><\/li>\n<li><b>Microsoft Scripting Runtime<\/b><\/li>\n<\/ul>\n<h2>Basisfunktion zum Senden von Anfragen an lexoffice<\/h2>\n<p>Wir verwenden eine Basisfunktion f&uuml;r den Zugriff auf die REST-API von lexoffice. Diese erwartet die folgenden Parameter:<\/p>\n<ul>\n<li><b>strURL<\/b>: URL f&uuml;r den Zugriff auf die REST-API. Beginnt immer mit <b>https:\/\/api.lexoffice.io\/v1\/ <\/b>und mit der Bezeichnung der abzufragenden\/zu bearbeitenden Elemente, zum Beispiel <b>contacts <\/b>oder <b>invoices<\/b>. Anschlie&szlig;end folgen weitere Parameter wie beispielsweise die Angabe von Filterkriterien beim Abfragen von Elementen.<\/li>\n<li><b>strMethod<\/b>: Methode, die angibt, ob Daten beispielsweise gelesen (<b>GET<\/b>) oder geschrieben werden sollen (<b>POST<\/b>).<\/li>\n<li><b>strRequest<\/b>: Falls erforderlich, k&ouml;nnen mit diesem Parameter zus&auml;tzliche Informationen im JSON-Format &uuml;bergeben werden. Enth&auml;lt beispielsweise die Kundendaten, wenn ein neuer Kontakt angelegt werden soll.<\/li>\n<li><b>strResponse<\/b>: Liefert die Antwort im JSON-Format, also beispielsweise Daten &uuml;ber einen neu angelegten Kontakt oder abgefragte Kontaktdaten.<\/li>\n<\/ul>\n<p>Die Funktion Request aus Listing 1 erstellt ein neues Objekt des Typs <b>XMLHTTP60<\/b>, mit dem wir auf die REST-API zugreifen. Dabei rufen wir als Erstes die <b>Open<\/b>-Methode auf, der wir die Werte der Parameter <b>strMethod <\/b>und <b>strURL <\/b>&uuml;bergeben sowie f&uuml;r den dritten Parameter den Wert <b>False<\/b>. Damit geben wir an, dass der Aufruf asynchron erfolgen soll. Die folgenden Anweisungen stellen die Header f&uuml;r den Aufruf ein, unter anderem das Format f&uuml;r die hin- und herzuschickenden Daten (JSON) sowie f&uuml;r die Autorisierung f&uuml;r den Zugriff auf die Daten unseres Kontos bei <b>lexoffice<\/b>. Hier &uuml;bergeben wir einen Ausdruck, der aus dem Text <b>Bearer <\/b>und dem zuvor ermittelten API-Schl&uuml;ssel besteht. Die <b>send<\/b>-Methode schickt die Anfrage schlie&szlig;lich an die REST-API. Sie erh&auml;lt noch die in <b>strRequest<\/b> angegebenen zus&auml;tzlichen Daten f&uuml;r die Anfrage.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>Request(strRequest<span style=\"color:blue;\"> As String<\/span>, strURL<span style=\"color:blue;\"> As String<\/span>, strMethod<span style=\"color:blue;\"> As String<\/span>, strResponse<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Boolean<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>objXMLHTTP<span style=\"color:blue;\"> As <\/span>MSXML2.XMLHTTP60\r\n     <span style=\"color:blue;\">Set<\/span> objXMLHTTP = <span style=\"color:blue;\">New<\/span> MSXML2.XMLHTTP60\r\n     <span style=\"color:blue;\">With<\/span> objXMLHTTP\r\n         .Open strMethod, strURL, <span style=\"color:blue;\">False<\/span>\r\n         .setRequestHeader \"Content-Type\", \"application\/json\"\r\n         .setRequestHeader \"Accept\", \"application\/json\"\r\n         .setRequestHeader \"Authorization\", \"Bearer \" + cstrAPIKey\r\n         .send strRequest\r\n         <span style=\"color:blue;\">Select Case <\/span>.status\r\n             <span style=\"color:blue;\">Case <\/span>200\r\n                 Request = <span style=\"color:blue;\">True<\/span>\r\n                 strResponse = .responseText\r\n             <span style=\"color:blue;\">Case Else<\/span>\r\n                 <span style=\"color:blue;\">MsgBox<\/span> \"Fehler beim Request:\" & <span style=\"color:blue;\">vbCrLf<\/span> & .statusText & <span style=\"color:blue;\">vbCrLf<\/span> & .responseText\r\n         <span style=\"color:blue;\">End Select<\/span>\r\n     End <span style=\"color:blue;\">With<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Basisfunktion f&uuml;r den Zugriff auf die REST-API von lexware<\/span><\/b><\/p>\n<p>Liefert die Anfrage mit der Eigenschaft status den Wert 200 zur&uuml;ck, war die Anfrage erfolgreich. Dann erh&auml;lt die <b>Request<\/b>-Funktion als R&uuml;ckgabewert den Wert <b>True <\/b>und wir f&uuml;llen den Parameter <b>strResponse <\/b>mit der in der Eigenschaft <b>responseText <\/b>enthaltenen JSON-Antwort.<\/p>\n<p>Anderenfalls gibt die Funktion die Fehlernummer und den Statustext in einem Meldungsfenster aus.<\/p>\n<h2>Kundendaten abfragen<\/h2>\n<p>Als Finger&uuml;bung fragen wir als Erstes alle Kundendaten ab. Dazu verwenden wir einen Aufruf der Funktion <b>Request <\/b>mit der folgenden URL:<\/p>\n<pre>https:\/\/api.lexoffice.io\/v1\/contacts<\/pre>\n<p>Nach dem Aufruf der Funktion <b>Request <\/b>geben wir den Inhalt von <b>strResponse <\/b>im Direktbereich des VBA-Editors aus und speichern das Ergebnis einer Funktion namens <b>GetJSONDOM <\/b>mit der Hilfsfunktion <b>Zwischenablage <\/b>aus dem Modul <b>mdlZwischenablage <\/b>in der Zwischenablage:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>FilteringContacts_All()\r\n     <span style=\"color:blue;\">Dim <\/span>strRequest<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strURL<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strResponse<span style=\"color:blue;\"> As String<\/span>\r\n     strURL = \"https:\/\/api.lexoffice.io\/v1\/contacts\"\r\n     If Request(strURL, \"GET\", strRequest, _\r\n             strResponse) = <span style=\"color:blue;\">True<\/span> Then\r\n         <span style=\"color:blue;\">Debug.Print<\/span> strResponse\r\n         InZwischenablage GetJSONDOM(strResponse, _\r\n             True, <span style=\"color:blue;\">True<\/span>)\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Mit der Response allein k&ouml;nnen wir nicht viel anfangen. Diese sieht in gek&uuml;rzter Form wie folgt aus:<\/p>\n<pre>{\"content\":[{\"id\":\"3a856a88-ee3a-421a-9850-1fce2d01c8f0\",\"organizationId\":\"dd8bf92c-43e5-41bf-a57a-ba7b33eb980f\",\"version\":4,\"roles\":{\"customer\":{\"number\":10001}},\"person\":{\"salutation\":\"Herr\",\"firstName\":\"Andr&eacute;\",\"lastName\":\"Minhorst\"},\"addresses\":{\"billing\":[{\"supplement\":\"\",\"street\":\"Borkhofer Str. 17\",\"zip\":\"47137\",\"city\":\"Duisburg\",\"countryCode\":\"DE\"}],\"shippin\r\ng\":[{\"supplement\":\"\",\"street\":\"Borkhofer Str., 17\",\"zip\":\"47137\",\"city\":\"Duisburg\",\"countryCode\":\"DE\"}]},\"emailAddresses\":{\"other\":[\"andre@minhorst.com\"]},\"phoneNumbers\":{\"other\":[\"98989898\"]},\"note\":\"24284\",\"archived\":false},...}<\/pre>\n<p>Die Funktion <b>GetJSONDOM <\/b>haben wir im Rahmen des Beitrags <b>JSON-Daten auslesen <\/b>(<b>www.access-im-unternehmen.de\/1403<\/b>) entwickelt. Sie gibt die im JSON-Dokument enthaltenen Daten wie in Listing 2 aus.<\/p>\n<pre>objJson.Item(\"content\").Item(3).Item(\"id\"): 3a856a88-ee3a-421a-9850-1fce2d01c8f0\r\nobjJson.Item(\"content\").Item(3).Item(\"organizationId\"): dd8bf92c-43e5-41bf-a57a-ba7b33eb980f\r\nobjJson.Item(\"content\").Item(3).Item(\"version\"): 4\r\nobjJson.Item(\"content\").Item(3).Item(\"roles\").Item(\"customer\").Item(\"number\"): 10001\r\nobjJson.Item(\"content\").Item(3).Item(\"person\").Item(\"salutation\"): Herr\r\nobjJson.Item(\"content\").Item(3).Item(\"person\").Item(\"firstName\"): Andr&eacute;\r\nobjJson.Item(\"content\").Item(3).Item(\"person\").Item(\"lastName\"): Minhorst\r\nobjJson.Item(\"content\").Item(3).Item(\"addresses\").Item(\"billing\").Item(1).Item(\"supplement\"): \r\nobjJson.Item(\"content\").Item(3).Item(\"addresses\").Item(\"billing\").Item(1).Item(\"street\"): Borkhofer Str. 17\r\nobjJson.Item(\"content\").Item(3).Item(\"addresses\").Item(\"billing\").Item(1).Item(\"zip\"): 47137\r\nobjJson.Item(\"content\").Item(3).Item(\"addresses\").Item(\"billing\").Item(1).Item(\"city\"): Duisburg\r\nobjJson.Item(\"content\").Item(3).Item(\"addresses\").Item(\"billing\").Item(1).Item(\"countryCode\"): DE\r\nobjJson.Item(\"content\").Item(3).Item(\"addresses\").Item(\"shipping\").Item(1).Item(\"supplement\"): \r\nobjJson.Item(\"content\").Item(3).Item(\"addresses\").Item(\"shipping\").Item(1).Item(\"street\"): Borkhofer Str., 17\r\nobjJson.Item(\"content\").Item(3).Item(\"addresses\").Item(\"shipping\").Item(1).Item(\"zip\"): 47137\r\nobjJson.Item(\"content\").Item(3).Item(\"addresses\").Item(\"shipping\").Item(1).Item(\"city\"): Duisburg\r\nobjJson.Item(\"content\").Item(3).Item(\"addresses\").Item(\"shipping\").Item(1).Item(\"countryCode\"): DE\r\nobjJson.Item(\"content\").Item(3).Item(\"emailAddresses\").Item(\"other\").Item(1): andre@minhorst.com\r\nobjJson.Item(\"content\").Item(3).Item(\"phoneNumbers\").Item(\"other\").Item(1): 98989898\r\nobjJson.Item(\"content\").Item(3).Item(\"note\"): 24284\r\nobjJson.Item(\"content\").Item(3).Item(\"archived\"): Falsch<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Ausgabe f&uuml;r den Zugriff auf die Daten einer JSON-Antwort<\/span><\/b><\/p>\n<p>Diese Ausgabe dient als Vorlage f&uuml;r das systematische Durchlaufen der Daten, die zu diesem Zweck in ein Objektmodell bestehend aus Collections und Dictionaries &uuml;berf&uuml;hrt wurde &#8211; mehr dazu im oben genannten Beitrag. Um beispielsweise die E-Mail-Adressen aller Kunden im Direktbereich auszugeben, ben&ouml;tigen wir damit nur noch die folgenden Zeilen zur Prozedur <b>FilteringContacts_All <\/b>hinzuzuf&uuml;gen &#8211; und zwar als letzte Zeile innerhalb der <b>If&#8230;Then<\/b>-Bedingung:<\/p>\n<pre>AusgabeKontakte strResponse<\/pre>\n<p>Die Ausgabe der Nachnamen aller Personen w&uuml;rde dann wie folgt geschehen:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>AusgabeKontakte(strJSON<span style=\"color:blue;\"> As String<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>objJSON<span style=\"color:blue;\"> As Object<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>objContact<span style=\"color:blue;\"> As Object<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> objJSON = ParseJson(strJSON)\r\n     For Each objContact In objJSON.Item(\"content\")\r\n         On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n         <span style=\"color:blue;\">Debug.Print<\/span> objContact.Item(\"person\").Item(\"lastName\")\r\n         <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n     <span style=\"color:blue;\">Next<\/span> objContact\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Die Prozedur speichert das Objektmodell des JSON-Dokuments als Struktur aus Dictionaries und Collections, auf die wir &uuml;ber die entsprechenden Auflistungen zugreifen k&ouml;nnen. Jedes <b>content<\/b>-Element enth&auml;lt einen der Kontakte. Diese durchlaufen wir in einer <b>For Each<\/b>-Schleife und referenzieren das <b>content<\/b>-Element dabei mit der Variablen <b>objContact<\/b>.<\/p>\n<p>&Uuml;ber dieses k&ouml;nnen wir dann beispielsweise mit dem Ausdruck <b>objContact.Item(&#8222;person&#8220;).Item(&#8222;lastName&#8220;) <\/b>auf den Nachnamen der Person zugreifen. Da nicht sichergestellt ist, dass diese Eigenschaft f&uuml;r jeden Kontakt existiert, haben wir f&uuml;r den Zugriff die eingebaute Fehlerbehandlung deaktiviert. Damit k&ouml;nnen wir nun alle Kontakte und die vorhandenen Eigenschaften durchlaufen und diese beispielsweise in einer Tabelle der Datenbank speichern.<\/p>\n<h2>Einen bestimmten Kontakt auslesen<\/h2>\n<p>Wenn Sie nicht alle Kontakte auslesen wollen, sondern nur einen bestimmten, k&ouml;nnen Sie verschiedene Kriterien verwenden. Eines davon ist die E-Mail-Adresse. In der Prozedur <b>FilteringContacts_ByEMail<\/b>, die Sie im Modul <b>mdlLexOffice <\/b>finden, f&uuml;gen wir dazu an die URL noch einen Filterparameter an:<\/p>\n<pre>strURL = \"https:\/\/api.lexoffice.io\/v1\/contacts?email=andre@minhorst.com\"<\/pre>\n<p>Dies liefert alle Kunden mit der E-Mail-Adresse <b>andre@minhorst.com<\/b>. Wir k&ouml;nnen die folgenden Vergleichsfelder nutzen:<\/p>\n<ul>\n<li><b>email<\/b>: Filtert nach der E-Mail-Adresse.<\/li>\n<li><b>name<\/b>: Filtert nach dem Namen.<\/li>\n<li><b>number<\/b>: Filtert nach der Kundennummer, die beispielsweise in der Eigenschaft <b>roles\/customer\/number <\/b>enthalten ist.<\/li>\n<li><b>customer<\/b>: Filtert nach allen Kontakten, welche die Rolle <b>customer <\/b>haben.<\/li>\n<li><b>vendor<\/b>: Filtert nach allen Kontakten, welche die Rolle <b>vendor <\/b>haben.<\/li>\n<\/ul>\n<p>Die Dokumentation des passenden API-Befehls finden Sie unter folgender URL:<\/p>\n<pre>https:\/\/developers.lexoffice.io\/docs\/#contacts-endpoint-filtering-contacts<\/pre>\n<p>Wenn wir beispielsweise nach dem Namen filtern wollen und dieser Sonderzeichen enth&auml;lt wie in Andr&eacute;, dann m&uuml;ssen wir diesen zuvor enkodieren. Funktionen dazu stellen wir im Beitrag <b>URLs kodieren per VBA <\/b>(<b>www.access-im-unternehmen.de\/1423<\/b>) vor.<\/p>\n<p>Zur Verwendung der dortigen Funktion <b>URLEncode_UTF8 <\/b>ben&ouml;tigen wir noch einen Verweis auf die Bibliothek <b>Microsoft ActiveX Data Objects 6.1 Library<\/b>.<\/p>\n<p>Die URL stellen wir dann wie folgt zusammen:<\/p>\n<pre>strURL = \"https:\/\/api.lexoffice.io\/v1\/contacts?name=\" & URLEncode_UTF8(\"Andr&eacute;\")<\/pre>\n<h2>Kontakt nach der ID in lexoffice ermitteln<\/h2>\n<p>Wir k&ouml;nnen auch nach der ID eines Kontakts filtern, der in der Eigenschaft <b>id <\/b>gespeichert ist. Diesen &uuml;bergeben wir ohne Feldname, also beispielsweise wie folgt:<\/p>\n<pre>strURL = \"https:\/\/api.lexoffice.io\/v1\/contacts\/xxxxxxxx-ee3a-421a-9850-1fce2d01c8f0\"<\/pre>\n<p>Hier ist jedoch zu beachten, dass keine Liste von Kontakten zur&uuml;ckgeliefert wird, sondern nur das Kontakt-Objekt selbst. Wir w&uuml;rden also nicht wie zuvor auf den Kontakt zugreifen:<\/p>\n<pre>objJson.Item(\"content\").Item(3).Item(\"person\").Item(\"lastName\")<\/pre>\n<p>Stattdessen greifen wir so darauf zu:<\/p>\n<pre>objJSON.Item(\"lastName\")<\/pre>\n<p>Das JSON-Dokument ist in diesem Fall anders strukturiert, als wenn wir auf alle Kontakte zugreifen oder gefiltert nach der E-Mail-Adresse. Um die Daten aus dem JSON-Dokument auszulesen, kann man sich die Struktur f&uuml;r den Zugriff mit der Funktion <b>GetJSONDOM <\/b>ansehen.<\/p>\n<p>Die Dokumentation des passenden API-Befehls finden Sie unter folgender URL:<\/p>\n<pre>https:\/\/developers.lexoffice.io\/docs\/#contacts-endpoint-retrieve-a-contact<\/pre>\n<h2>Kundendaten aus der Datenbank nach lexoffice &uuml;bertragen<\/h2>\n<p>Damit n&auml;hern wir uns der eigentlichen Aufgabe: Wir wollen die Kundendaten aus unserer Bestellverwaltung nach <b>lexoffice <\/b>&uuml;bertragen. Dazu nutzen wir wieder die gleiche URL, diesmal allerdings mit der Methode <b>POST<\/b>. Au&szlig;erdem m&uuml;ssen wir mit dem Parameter <b>strRequest <\/b>ein JSON-Dokument &uuml;bergeben, welches die Daten des anzulegenden Kontakts enth&auml;lt.<\/p>\n<p>Hinzu kommt, dass wir eine Verbindung zwischen dem Kundendatensatz in unserer Rechnungsverwaltung und dem Kontakt in <b>lexoffice <\/b>herstellen wollen. <b>lexoffice <\/b>erlaubt leider keine &Uuml;bermittlung der Kundennummer und erstellt eine eigene Kundennummer. Also bleibt als einzige M&ouml;glichkeit, eine Verbindung zwischen dem Kontakt in <b>lexoffice <\/b>und dem Kundendatensatz in der Datenbank herzustellen, das Auslesen der ID des Kontakts beim Anlegen und das Speichern dieser ID in der Kundentabelle. Dazu hinterlegen wir in der Kundentabelle ein Feld namens <b>LexOfficeID<\/b>. Nun gibt es verschiedene M&ouml;glichkeiten, einen Kontakt anzulegen &#8211; und zwar als Person oder als Firma. Wir haben daf&uuml;r jeweils eine eigene Funktion entwickelt, damit die Funktionen nicht zu aufgebl&auml;ht werden.<\/p>\n<p>Die erste Funktion hei&szlig;t <b>AddOrUpdateContact_Person<\/b> (erster Teil in Listing 3). Sie erwartet die Daten der Person (Anrede, Vorname, Nachname), die Daten einer Zahlungs- und einer Lieferadresse (wenn identisch, geben wir einfach zwei Mal die gleichen Parameter an) sowie E-Mail, Telefon und Kundennummer aus der Datenbank. Die Funktion pr&uuml;ft nicht, ob leere Zeichenketten f&uuml;r Parameter &uuml;bergeben wurden, aber die meisten Parameter sind Pflichtparameter. Wenn regelm&auml;&szlig;ig verschiedene Daten nicht vorhanden sind, sollten Sie abfragen, ob die jeweiligen Parameter leer sind und gegebenenfalls die betroffenen Elemente weglassen, wenn m&ouml;glich.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>AddOrUpdateContact_Person(strSalutation<span style=\"color:blue;\"> As String<\/span>, strFirstname<span style=\"color:blue;\"> As String<\/span>, strLastname<span style=\"color:blue;\"> As String<\/span>, _\r\n         strStreetBilling<span style=\"color:blue;\"> As String<\/span>, strZipBilling<span style=\"color:blue;\"> As String<\/span>, strCityBilling<span style=\"color:blue;\"> As String<\/span>, strCountryCodeBilling<span style=\"color:blue;\"> As <\/span>_\r\n         String, strStreetShipping<span style=\"color:blue;\"> As String<\/span>, strZipShipping<span style=\"color:blue;\"> As String<\/span>, strCityShipping<span style=\"color:blue;\"> As String<\/span>, _\r\n         strCountryCodeShipping<span style=\"color:blue;\"> As String<\/span>, strEMail<span style=\"color:blue;\"> As String<\/span>, strPhone<span style=\"color:blue;\"> As String<\/span>, strCustomerID<span style=\"color:blue;\"> As String<\/span>, _\r\n         strID<span style=\"color:blue;\"> As String<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>strRequest<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strURL<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strResponse<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strMethod<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>intVersion<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>objJSON<span style=\"color:blue;\"> As Object<\/span>\r\n     strURL = \"https:\/\/api.lexoffice.io\/v1\/contacts\"\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(strID) = 0<span style=\"color:blue;\"> Then<\/span>\r\n         strMethod = \"POST\"\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         strMethod = \"PUT\"\r\n         strURL = strURL & \"\/\" & strID\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     ...<\/pre>\n<p>[<\/p>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Anlegen oder Aktualisieren eines Kontakts, Teil 1<\/span><\/b><\/p>\n<h2>Kontakt &uuml;berschreiben<\/h2>\n<p>Die Funktion schreibt zun&auml;chst die URL in die Variable <b>strURL <\/b>und pr&uuml;ft dann, ob der Parameter <b>strID <\/b>einen Wert enth&auml;lt oder eine leere Zeichenkette. <b>strID <\/b>soll, wenn der Kontakt bereits einmal angelegt wurde, im Feld <b>LexOfficeID <\/b>der Kundentabelle gespeichert werden.<\/p>\n<p>Dieser wird dann statt einer leeren Zeichenkette f&uuml;r den letzten Parameter <b>strID <\/b>&uuml;bergeben und bewirkt, dass in diesem Fall in <b>lexoffice <\/b>der entsprechende Kontakt mit neuen Daten &uuml;berschrieben werden soll. Daf&uuml;r gibt es einige Einschr&auml;nkungen, die Sie der entsprechenden Stelle der Dokumentation entnehmen k&ouml;nnen:<\/p>\n<pre>https:\/\/developers.lexoffice.io\/docs\/#contacts-endpoint-create-a-contact<\/pre>\n<p>Ist <b>strID <\/b>nicht gef&uuml;llt, verwenden wir als Methode <b>POST <\/b>&#8211; dies legt ein neues Element an &#8211; oder <b>PUT <\/b>zum Aktualisieren des vorhandenen Elements. Ist <b>strID <\/b>vorhanden, wird es au&szlig;erdem an <b>strURL <\/b>angeh&auml;ngt, sodass der Link beispielsweise wie folgt aussieht:<\/p>\n<pre>https:\/\/api.lexoffice.io\/v1\/contacts\/7d64ec31-4ebb-4f1c-9a68-b50718f82efc<\/pre>\n<p>Danach beginnt, wie in Listing 4 abgebildet, das Zusammenstellen des als Body &uuml;bergebenen JSON-Dokuments mit dem Request in der Variablen <b>strRequest<\/b>. Hier f&uuml;gen wir zuerst die Version hinzu, die f&uuml;r ein neues Element auf <b>0 <\/b>eingestellt wird. F&uuml;r ein vorhandenes Element m&uuml;ssen wir zuvor mit einer weiteren Funktion die aktuelle Version f&uuml;r dieses Element ermitteln, die bei jeder &Auml;nderung um <b>1 <\/b>erh&ouml;ht wird. Die Version holen wir mit der Funktion <b>GetContactVersion<\/b>, der wir ebenfalls die ID aus <b>strID <\/b>&uuml;bergeben.<\/p>\n<pre>     strRequest = \"{\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(strID) = 0<span style=\"color:blue;\"> Then<\/span>\r\n         strRequest = strRequest & \"  \"\"version\"\": 0,\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         intVersion = GetContactVersion(strID)\r\n         strRequest = strRequest & \"  \"\"version\"\": \" & intVersion & \",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     strRequest = strRequest & \"  \"\"roles\"\": {\"\"customer\"\": {}},\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"  \"\"person\"\": {\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"    \"\"salutation\"\": \"\"\" & strSalutation & \"\"\",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"    \"\"firstName\"\": \"\"\" & strFirstname & \"\"\",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"    \"\"lastName\"\": \"\"\" & strLastname & \"\"\"\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"  },\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"  \"\"addresses\"\": {\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"     \"\"billing\"\": [{\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"         \"\"supplement\"\": \"\"\"\",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"         \"\"street\"\": \"\"\" & strStreetBilling & \"\"\",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"         \"\"zip\"\": \"\"\" & strZipBilling & \"\"\",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"         \"\"city\"\": \"\"\" & strCityBilling & \"\"\",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"         \"\"countryCode\"\": \"\"\" & strCountryCodeBilling & \"\"\"\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"       }],\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"     \"\"shipping\"\":  [{\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"       \"\"supplement\"\": \"\"\"\",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"       \"\"street\"\": \"\"\" & strStreetShipping & \"\"\",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"       \"\"zip\"\": \"\"\" & strZipShipping & \"\"\",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"       \"\"city\"\": \"\"\" & strCityShipping & \"\"\",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"       \"\"countryCode\"\": \"\"\" & strCountryCodeShipping & \"\"\"\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"     }]\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"  },\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"  \"\"emailAddresses\"\":{\"\"other\"\":[\"\"\" & strEMail & \"\"\"]},\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"  \"\"phoneNumbers\"\":{\"\"other\"\":[\"\"\" & strPhone & \"\"\"]},\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"  \"\"note\"\":\"\"\" & strCustomerID & \"\"\"\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"}\"\r\n     <span style=\"color:blue;\">If <\/span>Request(strURL, strMethod, strRequest, strResponse)<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> objJSON = mdlJSON.ParseJson(strResponse)\r\n         AddOrUpdateContact_Person = <span style=\"color:blue;\">True<\/span>\r\n         strID = objJSON.Item(\"id\")\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 4: Anlegen oder Aktualisieren eines Kontakts, Teil 2<\/span><\/b><\/p>\n<p>Diese Funktion sieht wie folgt aus. Sie &uuml;bergibt der URL <b>https:\/\/api.lexoffice.io\/v1\/contacts\/ <\/b>die ID und liest aus dem JSON-Dokument den Wert des Feldes <b>version <\/b>aus:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>GetContactVersion(strID<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strRequest<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strURL<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strResponse<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>objJSON<span style=\"color:blue;\"> As Object<\/span>\r\n     strURL = \"https:\/\/api.lexoffice.io\/v1\/contacts\/\" & strID\r\n     <span style=\"color:blue;\">If <\/span>Request(strURL, \"GET\", strRequest, strResponse)<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> objJSON = ParseJson(strResponse)\r\n         GetContactVersion = objJSON.Item(\"version\")\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Haben wir die Version ermittelt, k&ouml;nnen wir mit dieser die korrekte Version des Kontaktes bei <b>lexoffice <\/b>&uuml;berschreiben. Danach folgen einige ineinander verschachtelte Elemente, in die wir per Code die mit den Parametern der Funktion gelieferten Werte einarbeiten.<\/p>\n<p>Wir f&uuml;gen dem Kontakt neben dem <b>person<\/b>-Element mit Anrede, Vorname und Nachname dabei im Unterelement <b>addresses <\/b>zwei Adressen hinzu &#8211; jeweils eine Rechnungs- und eine Lieferadresse.<\/p>\n<p>Danach folgen noch die E-Mail-Adressen und die Telefonnummern, von denen wir jeweils eine unter <b>other <\/b>hinzuf&uuml;gen. Bei den E-Mail-Adressen gibt es die Bereiche <b>business<\/b>, <b>office, private <\/b>und <b>other<\/b>. F&uuml;r die Telefonnummern gibt es die Bereiche <b>business<\/b>, <b>office<\/b>, <b>mobile<\/b>, <b>private<\/b>, <b>fax <\/b>und <b>other<\/b>. Unter <b>note<\/b> geben wir, falls wir diese als Referenz in einer Rechnung et cetera ben&ouml;tigen, die Kundennummer aus der Kundentabelle an.<\/p>\n<p>Danach folgt der eigentliche Aufruf der REST-API &uuml;ber die Funktion Request, der wir die URL, die Methode, das JSON-Dokument und eine leere Variable zum Entgegennehmen der Response &uuml;bergeben.<\/p>\n<p>Liefert die Funktion <b>Request <\/b>den Wert <b>True <\/b>zur&uuml;ck, war der Request erfolgreich, und das Ergebnis-Dokument ist im JSON-Format in der Variablen <b>strResponse <\/b>gelandet.<\/p>\n<p>Dann nutzen wir die im oben genannten Beitrag zum Thema JSON vorgestellte Funktion <b>ParseJSON<\/b>, um den Inhalt von strResponse als Objektmodell verf&uuml;gbar zu machen. Aus diesem lesen wir dann &uuml;ber <b>objJSON.Item(&#8222;id&#8220;) <\/b>die ID des neu angelegten Kontakts aus und speichern diesen im R&uuml;ckgabeparameter <b>strID<\/b>.<\/p>\n<p>Nun k&ouml;nnen wir die Funktion endlich aufrufen und verwenden dazu eine kleine Testprozedur, damit wir das Ergebnis aus <b>strID <\/b>auch auswerten k&ouml;nnen:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>Test_AddContact_Person()\r\n     <span style=\"color:blue;\">Dim <\/span>strID<span style=\"color:blue;\"> As String<\/span>\r\n     If AddOrUpdateContact_Person(\"Herr\", \"Klaus\", _\r\n             \"Schmitz\", \"Borkhofer Str. 17\", \"47137\", _\r\n             \"Duisburg\", \"DE\", \"Borkhofer Str. 17\", _\r\n             \"47137\", \"Duisburg\", \"DE\", _\r\n             \"andre@minhorst.com\", \"+1713145654\", _\r\n             \"99001234\", strID) Then\r\n         <span style=\"color:blue;\">Debug.Print<\/span> strID\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Das als Anfrage verschickte JSON-Dokument sieht mit diesen Daten wie folgt aus:<\/p>\n<pre>{\r\n   \"version\": 0,\r\n   \"roles\": {\"customer\": {}},\r\n   \"person\": {\r\n     \"salutation\": \"Herr\",\r\n     \"firstName\": \"Klaus\",\r\n     \"lastName\": \"Schmitz\"\r\n   },\r\n   \"addresses\": {\r\n      \"billing\": [{\r\n          \"supplement\": \"\",\r\n          \"street\": \"Borkhofer Str. 17\",\r\n          \"zip\": \"47137\",\r\n          \"city\": \"Duisburg\",\r\n          \"countryCode\": \"DE\"\r\n        }],\r\n      \"shipping\":  [{\r\n        \"supplement\": \"\",\r\n        \"street\": \"Borkhofer Str. 17\",\r\n        \"zip\": \"47137\",\r\n        \"city\": \"Duisburg\",\r\n        \"countryCode\": \"DE\"\r\n      }]\r\n   },\r\n   \"emailAddresses\":{\"other\":[\"andre@minhorst.com\"]},\r\n   \"phoneNumbers\":{\"other\":[\"+1713145654\"]},\r\n   \"note\":\"99001234\"\r\n}<\/pre>\n<p>Nachdem wir den Kunden so angelegt haben, k&ouml;nnen wir seinen Datensatz bereits in <b>lexoffice<\/b> im Bereich <b>Kontakte <\/b>ansehen (siehe Bild 4).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2023_02\/pic_1422_004.png\" alt=\"Daten des neuen Kontakts in der Webansicht von lexoffice\" width=\"599,559\" height=\"532,2945\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Daten des neuen Kontakts in der Webansicht von lexoffice<\/span><\/b><\/p>\n<h2>Anlegen von Firmen-Kontakten<\/h2>\n<p>Das Anlegen von Firmenkontakten erfolgt mit einer &auml;hnlich aufgebauten Funktion namens <b>AddOrUpdateContact_Company<\/b>. Die Unterschiede sind allein der etwas anderen Struktur der zu &uuml;bergebenden Daten geschuldet.<\/p>\n<p>Hier &uuml;bergeben wir als Objekt kein <b>person<\/b>-, sondern ein <b>company<\/b>-Element. Dieses hat unter <b>name <\/b>den Firmennamen, unter <b>vatRegistrationId <\/b>die UstIdNr und unter <b>allowTaxFreeInvoices <\/b>einen Wert, der angibt, ob steuerfreie Rechnungen &uuml;bergeben werden d&uuml;rfen, wenn eine UstIDNr vorliegt. Welchen Wert Sie hier angeben m&uuml;ssen, besprechen Sie am besten mit Ihrem Steuerberater.<\/p>\n<p>Danach folgt eine Auflistung namens <b>contactpersons<\/b>, wo ein oder mehrere Kontaktpersonen angegeben werden k&ouml;nnen. Schlie&szlig;lich folgt wieder der <b>addresses<\/b>-Block mit Rechnungs- und Lieferadressen.<\/p>\n<p>Wichtig: Wenn wir hier mehr als eine Adresse pro Kategorie angeben, k&ouml;nnen wir diese nicht mehr &uuml;ber die REST-API aktualisieren.<\/p>\n<p>Schlie&szlig;lich folgen noch allgemeine E-Mail-Adressen und Telefonnummern sowie wieder das Notizen-Feld, dem wir die Kundennummer aus der Kundentabelle zuweisen.<\/p>\n<h2>lexoffice mit Kundendaten aus der Datenbank f&uuml;llen<\/h2>\n<p>Wenn Sie die betroffenen Kundendatens&auml;tze aus der Datenbank nach lexoffice &uuml;bertragen wollen, k&ouml;nnen Sie ein Recordset auf Basis einer Tabelle oder Abfrage mit den betroffenen Datens&auml;tzen durchlaufen und f&uuml;r jeden Datensatz jeweils einmal die Prozedur <b>AddOrUpdateContact_Person <\/b>oder <b>AddOrUpdateContact_Company <\/b>aufrufen und die entsprechenden Werte mit den Parametern &uuml;bergeben.<\/p>\n<p>Zu Testzwecken haben wir eine Tabelle namens <b>tblContacts <\/b>erstellt, deren Felder wir nach den entsprechenden Feldern in den zu &uuml;bertragenden JSON-Dokumenten benannt haben (siehe Bild 5).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2023_02\/pic_1422_006.png\" alt=\"Tabelle zum Speichern von Kontaktdaten\" width=\"424,5589\" height=\"416,9434\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Tabelle zum Speichern von Kontaktdaten<\/span><\/b><\/p>\n<p>Wichtig sind die drei letzten Felder:<\/p>\n<ul>\n<li><b>LexOfficeID<\/b>: Speichert die bei lexoffice angelegte ID f&uuml;r diesen Kontakt. Auf diese Weise ist eine Verbindung zwischen dem Datensatz in der Datenbank und dem bei lexoffice hergestellt.<\/li>\n<li><b>LexOfficeRequest<\/b>: Speichert im Falle eines Problems den Request, mit dem versucht wurde, den Kunden bei lexoffice zu speichern.<\/li>\n<li><b>LexOfficeResponse<\/b>: Speichert im Falle eines Problems die Response von lexoffice, damit wir diese anschlie&szlig;end untersuchen k&ouml;nnen.<\/li>\n<\/ul>\n<p>Das Formular <b>frmContacts <\/b>zeigt die Daten dieser Tabelle an (siehe Bild 6). <\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2023_02\/pic_1422_005.png\" alt=\"Formular zur Eingabe von Kontaktdaten\" width=\"424,5589\" height=\"442,0407\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Formular zur Eingabe von Kontaktdaten<\/span><\/b><\/p>\n<p>Das Formular enth&auml;lt zwei Schaltfl&auml;chen. Die erste soll den aktuellen Kunden nach lexoffice &uuml;bertragen, die zweite soll den Kunden, wenn er schon in lexoffice angelegt ist, im Browser &ouml;ffnen.<\/p>\n<p>Der Code der ersten Schaltfl&auml;che ist in Listing 5 abgebildet. Die Prozedur ermittelt als Erstes den Wert des Feldes <b>LexOfficeID <\/b>aus dem Textfeld <b>txtLexOfficeID<\/b> und speichert diesen in der Variablen <b>strID<\/b>. Dann pr&uuml;ft sie, ob das Textfeld <b>txtCompany <\/b>eine leere Zeichenkette enth&auml;lt. Falls ja, ruft die Prozedur die Routine <b>AddOrUpdateContact_Person <\/b>auf, um einen Personen-Kontakt anzulegen oder zu aktualisieren. Falls <b>txtCompany <\/b>hingegen eine Firma enth&auml;lt, wird die Routine <b>AddOrUpdateContact_Company <\/b>aufgerufen. Beiden Routinen &uuml;bergibt die Prozedur <b>cmdNachLexoffice_Click <\/b>die Inhalte der relevanten Textfelder, bei Erstellung eines Firmen-Kontakts sind das ein paar Felder mehr als beim Personen-Kontakt.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdNachLexoffice_Click()\r\n     <span style=\"color:blue;\">Dim <\/span>strID<span style=\"color:blue;\"> As String<\/span>\r\n     strID = Nz(Me!txtLexOfficeID, \"\")\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(Nz(Me!txtCompany, \"\")) = 0<span style=\"color:blue;\"> Then<\/span>\r\n         If AddOrUpdateContact_Person(Me!txtSalutation, Me!txtFirstName, Me!txtLastName, Me!txtStreetBilling, _\r\n                 Me!txtZIPBilling, Me!txtCityBilling, Laendercode(Me!txtCountryBilling), Me!txtStreetShipping, _\r\n                 Me!txtZIPShipping, Me!txtCityShipping, Laendercode(Me!txtCountryShipping), Me!txtEMail, _\r\n                 Me!txtPhone, \"Importiert von Kundendatenbank, KundeID: \" & Me!txtContactID, strID, _\r\n                     \"tblContacts\", Me!txtContactID) Then\r\n             Me!txtLexOfficeID = strID\r\n             RunCommand acCmdSaveRecord\r\n             Me!cmdInLexOfficeAnzeigen.Enabled = <span style=\"color:blue;\">True<\/span>\r\n             <span style=\"color:blue;\">MsgBox<\/span> \"Kontakt erfolgreich angelegt. ID: \" & strID\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         If AddOrUpdateContact_Company(Me!txtCompany, Nz(Me!txtVATRegistrationID, \"\"), Nz(Me!txtSalutation, \"\"), _\r\n                 Nz(Me!txtFirstName, \"\"), Nz(Me!txtLastName, \"\"), Me!txtEMail, Me!txtPhone, Me!txtStreetBilling, _\r\n                 Me!txtZIPBilling, Me!txtCityBilling, Laendercode(Me!txtCountryBilling), Nz(Me!txtStreetShipping, \"\"), _\r\n                 Nz(Me!txtZIPShipping, \"\"), Nz(Me!txtCityShipping, \"\"), _\r\n                 Nz(Laendercode(Nz(Me!txtCountryShipping, \"\")), \"\"), Me!txtEMail, _\r\n                 Me!txtPhone, \"Importiert von Kundendatenbank, KundeID: \" & Me!txtContactID, strID, _\r\n                 \"tblContacts\", Me!txtContactID) Then\r\n             Me!txtLexOfficeID = strID\r\n             RunCommand acCmdSaveRecord\r\n             Me!cmdInLexOfficeAnzeigen.Enabled = <span style=\"color:blue;\">True<\/span>\r\n             <span style=\"color:blue;\">MsgBox<\/span> \"Kontakt erfolgreich angelegt. ID: \" & strID\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 Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: &Uuml;bertragen eines Kontakts nach lexoffice<\/span><\/b><\/p>\n<p>Den Wert des Feldes <b>LexOfficeID <\/b>haben wir zuvor in die Variable <b>strID <\/b>gepackt, damit sie gegebenenfalls von der aufgerufenen Funktion aktualisiert werden kann. Nachdem die jeweilige Funktion also aufgerufen wurde, schreiben wir den R&uuml;ckgabewert von <b>strID <\/b>in das Feld <b>txtLexOfficeID <\/b>und speichern den Datensatz. Schlie&szlig;lich aktivieren wir nach erfolgtem Anlegen die Schaltfl&auml;che <b>cmdInLexOfficeAnzeigen <\/b>f&uuml;r diesen Datensatz und geben eine Meldung &uuml;ber das erfolgreiche Anlegen aus.<\/p>\n<p>Damit diese Schaltfl&auml;che f&uuml;r solche Kontakte, die bereits in lexoffice erfasst wurden und die somit &uuml;ber einen Wert im Feld <b>LexOfficeID <\/b>verf&uuml;gen, immer aktiviert und f&uuml;r die anderen deaktiviert wird, f&uuml;gen wir noch die folgende Prozedur f&uuml;r das Ereignis <b>Beim Anzeigen <\/b>des Formulars hinzu:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Current()\r\n     Me!cmdInLexOfficeAnzeigen.Enabled = _\r\n         <span style=\"color:blue;\">Not<\/span> IsNull(Me!txtLexOfficeID)\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Die <b>LexOfficeID <\/b>ben&ouml;tigen wir im Folgenden auch noch, um den Kunden, f&uuml;r den wir eine Rechnung anlegen wollen, anzugeben.<\/p>\n<p>Wichtig ist an dieser Stelle, dass wir &Auml;nderungen an den Daten des Kontakts immer direkt nach lexoffice &uuml;bertragen, da sonst neue Rechnungen mit veralteten Kontaktdaten angelegt werden, was nur zus&auml;tzlichen Aufwand bedeutet.<\/p>\n<h2>Kunde in lexoffice anzeigen<\/h2>\n<p>Mit der Schaltfl&auml;che <b>cmdInLexOfficeAnzeigen <\/b>rufen wir schlie&szlig;lich noch die folgende Prozedur auf, mit der wir den Kunden direkt in lexoffice anzeigen &#8211; dies erfordert allerdings einen vorherigen Login:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdInLexOfficeAnzeigen_Click()\r\n     FollowHyperlink \"https:\/\/app.lexoffice.de\/contacts\/\" _\r\n         & Me!LexOfficeID & \"\/activities\"\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Der neue Kunde erscheint dort wie in Bild 7.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2023_02\/pic_1422_010.png\" alt=\"Neuer Kunde bei lexoffice\" width=\"649,559\" height=\"635,6555\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Neuer Kunde bei lexoffice<\/span><\/b><\/p>\n<h2>Rechnungsdaten aus der Datenbank nach lexoffice &uuml;bertragen<\/h2>\n<p>Die &Uuml;bertragung der Daten einer Rechnung ist nicht weniger aufwendig &#8211; wenn man allerdings einmal den Code zum Zusammenstellen des JSON-Dokuments generiert hat, kann man sich entspannt zur&uuml;cklehnen und die Anwendung die Rechnungen generieren lassen.<\/p>\n<p>Ein wenig Vorarbeit haben wir ja bereits geleistet, indem wir die Routinen zum &Uuml;bertragen der Kundendaten bereits programmiert haben.<\/p>\n<p>Wir k&ouml;nnen die Daten des Rechnungsempf&auml;ngers zwar auch direkt in den Aufruf zum Erstellen einer Rechnung integrieren, aber wir haben uns hier f&uuml;r die Aufteilung dieser beiden Aufgaben entschlossen.<\/p>\n<h2>Tabellen f&uuml;r die Rechnungsdaten<\/h2>\n<p>Die Tabellen f&uuml;r Rechnungsdaten haben wir in der Zusammenfassung des Datenmodells in Bild 8 dargestellt. Die Tabelle <b>tblInvoices <\/b>ist &uuml;ber das Feld <b>ContactID <\/b>mit dem jeweiligen Rechnungsempf&auml;nger aus der Tabelle <b>tblContacts <\/b>verkn&uuml;pft. Die Tabelle <b>tblLineItems <\/b>nimmt die einzelnen Positionen der Rechnung auf und ist &uuml;ber das Fremdschl&uuml;sselfeld <b>InvoiceID <\/b>mit der Tabelle <b>tblInvoices <\/b>verbunden.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2023_02\/pic_1422_007.png\" alt=\"Datenmodell der Beispieldatenbank\" width=\"649,559\" height=\"498,2053\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 8: Datenmodell der Beispieldatenbank<\/span><\/b><\/p>\n<p>Die Tabelle <b>tblInvoices <\/b>erh&auml;lt genau wie die Tabelle <b>tblContacts <\/b>die drei Felder <b>LexOfficeID<\/b>, <b>LexOfficeRequest <\/b>und <b>LexOfficeResponse<\/b>.<\/p>\n<p>Auf diese Weise k&ouml;nnen wir auch eine Referenz zu der in lexoffice erstellten Rechnung herstellen und eventuelle Probleme durch Speichern des Requests und des Responses anschlie&szlig;end untersuchen.<\/p>\n<p>Damit wir die Rechnungen und die Rechnungspositionen komfortabel eingeben und die Rechnungen an lexoffice schicken k&ouml;nnen, haben wir ein Formular namens <b>frmInvoices <\/b>mit einem Unterformular namens <b>sfmInvoices <\/b>erstellt. In der Formularansicht sieht das Formular wie in Bild 9 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2023_02\/pic_1422_009.png\" alt=\"Formular zur Eingabe der Rechnungsdaten\" width=\"700\" height=\"420,5912\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 9: Formular zur Eingabe der Rechnungsdaten<\/span><\/b><\/p>\n<p>Ein Klick auf die Schaltfl&auml;che <b>cmdRechnungNachLexoffice<\/b> ruft die Prozedur auf, deren ersten Teil Sie in Listing 6 finden. Diese pr&uuml;ft zuerst, ob der im Feld <b>ContactID <\/b>angegebene Kontakt aus der Tabelle <b>tblContacts <\/b>bereits nach lexoffice &uuml;bertragen wurde.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdRechnungNachLexoffice_Click()\r\n     <span style=\"color:blue;\">Dim <\/span>strURL<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strMethod<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strRequest<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strResponse<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>objJson<span style=\"color:blue;\"> As Object<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strID<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>rstLineItems<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">If <\/span>Nz(DLookup(\"LexofficeID\", \"tblContacts\", \"ContactID = \" & Me.ContactID), \"\") = \"\"<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Der Kontakt muss erst noch nach Lexoffice &uuml;bertragen werden.\"\r\n         <span style=\"color:blue;\">Exit Sub<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     strURL = \"https:\/\/api.lexoffice.io\/v1\/invoices?finalize=false\"\r\n     strMethod = \"POST\"\r\n     <span style=\"color:blue;\">Set<\/span> rstLineItems = Me!sfmLineItems.Form.RecordsetClone\r\n     strRequest = strRequest & \"{\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \" \"\"archived\"\": false,\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"   \"\"voucherDate\"\": \"\"\" & Format(Me!InvoiceDate, \"yyyy-mm-dd\") _\r\n         & \"T00:00:00.000+01:00\"\",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"   \"\"address\"\": {\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"    \"\"contactId\"\": \"\"\" & DLookup(\"LexOfficeID\", \"tblContacts\", \"ContactID = \" _\r\n         & Me!ContactID) & \"\"\"\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"  },\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"  \"\"lineItems\"\": [\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     rstLineItems.MoveFirst\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rstLineItems.EOF\r\n         strRequest = strRequest & \"    {\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         strRequest = strRequest & \"      \"\"type\"\": \"\"custom\"\",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         strRequest = strRequest & \"      \"\"name\"\": \"\"\" & rstLineItems!Description & \"\"\",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         strRequest = strRequest & \"      \"\"quantity\"\": \" & rstLineItems!Quantity & \",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         strRequest = strRequest & \"      \"\"unitName\"\": \"\"\" & rstLineItems!UnitName & \"\"\",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         strRequest = strRequest & \"      \"\"unitPrice\"\": {\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         strRequest = strRequest & \"        \"\"currency\"\": \"\"EUR\"\",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         Select Case Me!ogrRechnungstyp\r\n             <span style=\"color:blue;\">Case <\/span>1\r\n                 strRequest = strRequest & \"        \"\"netAmount\"\": \" & <span style=\"color:blue;\">Replace<\/span>(rstLineItems!UnitPrice, \",\", \".\") _\r\n                     & \",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n             <span style=\"color:blue;\">Case <\/span>2\r\n                 strRequest = strRequest & \"        \"\"grossAmount\"\": \" & <span style=\"color:blue;\">Replace<\/span>(rstLineItems!UnitPrice, \",\", \".\") _\r\n                     & \",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         <span style=\"color:blue;\">End Select<\/span>\r\n         strRequest = strRequest & \"        \"\"taxRatePercentage\"\": \" & rstLineItems!TaxRatePercentage * 100 & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         strRequest = strRequest & \"      },\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         strRequest = strRequest & \"      \"\"discountPercentage\"\": 0\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         strRequest = strRequest & \"    },\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         rstLineItems.Move<span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n...<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 6: Anlegen einer Rechnung in lexoffice, Teil 1<\/span><\/b><\/p>\n<p>Falls nicht, erscheint eine Meldung und die Prozedur wird abgebrochen.<\/p>\n<p>Danach legt die Prozedur die URL f&uuml;r den API-Endpunkt zum Hinzuf&uuml;gen einer neuen Rechnung in der Variablen strURL an:<\/p>\n<pre>https:\/\/api.lexoffice.io\/v1\/invoices?finalize=false<\/pre>\n<p>Als Methode w&auml;hlen wir wieder <b>POST<\/b>. Dann erstellt die Prozedur ein <b>RecordsetClone <\/b>auf Basis der Daten aus dem Unterformular und beginnt, das JSON-Dokument zusammenzustellen.<\/p>\n<p>Als Erstes landen das Rechnungsdatum und die Kontaktadresse im Dokument. Letztere geben wir in Form eines Elements namens <b>contactId <\/b>an, der wir den im Feld <b>LexOfficeID <\/b>des Kontakts gespeicherten Wert &uuml;bergeben. Danach folgen bereits die einzelnen Rechnungspositionen, die wir im <b>lineItems<\/b>-Element anlegen.<\/p>\n<p>Dazu durchlaufen wir eine Schleife &uuml;ber alle Elemente des <b>RecordsetClone<\/b>-Objekts und f&uuml;gen die Daten der Rechnungspositionen mit den entsprechenden Bezeichnern ein. Schlie&szlig;lich folgt die Angabe, ob die Preise der Rechnungspositionen brutto oder netto angegeben werden sollen.<\/p>\n<p>Nach dem Hinzuf&uuml;gen der Rechnungspositionen innerhalb der <b>Do While<\/b>-Schleife schauen wir uns den zweiten Teil der Prozedur in Listing 7 an. Hier haben wir zu Beispielzwecken noch eine Beschreibungszeile hinzugef&uuml;gt &#8211; nur, damit Sie einmal sehen, wie man eine solche definiert. Eine solche Beschreibungszeile kann verschiedene zus&auml;tzliche Informationen zu den Positionen enthalten.<\/p>\n<pre>     strRequest = strRequest & \"    {\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"      \"\"type\"\": \"\"text\"\",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"      \"\"name\"\": \"\"Strukturieren Sie Ihre Belege durch Text-Elemente.\"\",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"      \"\"description\"\": \"\"Das hilft beim Verst&auml;ndnis\"\"\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"    }\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"  ],\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"  \"\"totalPrice\"\": {\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"    \"\"currency\"\": \"\"EUR\"\"\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"   },\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"  \"\"taxConditions\"\": {\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     Select Case Me!ogrRechnungstyp\r\n         <span style=\"color:blue;\">Case <\/span>1\r\n             strRequest = strRequest & \"  \"\"taxType\"\": \"\"net\"\"\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         <span style=\"color:blue;\">Case <\/span>2\r\n             strRequest = strRequest & \"  \"\"taxType\"\": \"\"gross\"\"\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n     strRequest = strRequest & \"  },\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"  \"\"paymentConditions\"\": {\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"    \"\"paymentTermLabel\"\": \"\"10 Tage - 3 %, 30 Tage netto\"\",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"    \"\"paymentTermDuration\"\": 30,\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"    \"\"paymentDiscountConditions\"\": {\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"      \"\"discountPercentage\"\": 3,\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"      \"\"discountRange\"\": 10\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"    }\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"  },\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"  \"\"shippingConditions\"\": {\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"    \"\"shippingDate\"\": \"\"\" & Format(Me!ShippingDate, \"yyyy-mm-dd\") _\r\n         & \"T00:00:00.000+01:00\"\",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"    \"\"shippingType\"\": \"\"delivery\"\"\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"  },\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"  \"\"title\"\": \"\"Rechnung\"\",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"  \"\"introduction\"\": \"\"Ihre bestellten Positionen stellen wir Ihnen hiermit in \" _\r\n         & \"Rechnung\"\",\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \" \"\"remark\"\": \"\"Vielen Dank f&uuml;r Ihren Einkauf\"\"\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     strRequest = strRequest & \"}\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n     <span style=\"color:blue;\">If <\/span>Request(strURL, strMethod, strRequest, strResponse, \"tblInvoices\", \"InvoiceID\", Me!InvoiceID) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> objJson = ParseJson(strResponse)\r\n         GetJSONDOM strResponse, False, <span style=\"color:blue;\">False<\/span>\r\n         strID = objJson.Item(\"id\")\r\n         Me!LexOfficeID = strID\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Rechnung angelegt.\" & <span style=\"color:blue;\">vbCrLf<\/span> & \"ID: \" & strID\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Rechnung nicht angelegt. Antwort in Zwischenablage.\"\r\n         Inzwischenablage strResponse\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 7: Anlegen einer Rechnung in lexoffice, Teil 2<\/span><\/b><\/p>\n<p>Danach folgt noch ein Abschnitt, der die Steuerbedingungen angibt (<b>taxConditions<\/b>).<\/p>\n<p>Anschlie&szlig;end f&uuml;gen wir allgemeine Informationen hinzu wie die Zahlungskonditionen, die wir hier der Einfachheit halber auf Beispielwerte festgelegt haben. In einer professionellen Anwendung w&uuml;rde man noch eine Tabelle und ein Formular hinzuf&uuml;gen, mit denen man diese Einstellungen selbst anpassen k&ouml;nnte.<\/p>\n<p>Au&szlig;erdem geben wir noch Lieferinformationen an, die im Element <b>shippingConditions <\/b>landen. Hier taucht vor allem das Lieferdatum auf.<\/p>\n<p>Im letzten Teil geben wir dann noch den Titel, den Rechnungstext und den Text ein, der unter den Positionen angezeigt werden soll.<\/p>\n<p>Diesen Request senden wir nun mit den &uuml;brigen Informationen wie der URL und der Methode an die Funktion <b>Request<\/b>, die wir ja bereits weiter oben beschrieben haben.<\/p>\n<p>Falls die Funktion den Wert <b>True <\/b>zur&uuml;ckliefert, lesen wir aus der Antwort den Wert des Elements <b>id <\/b>aus. Diesen Wert tragen wir in das Feld <b>LexOfficeID <\/b>des aktuellen Datensatzes ein und zeigen in einer Meldung den Erfolg und die ID des neuen Elements an.<\/p>\n<p>Falls die Funktion die Rechnung nicht erfolgreich anlegen konnte, geben wir ebenfalls eine Meldung aus und schreiben die Antwort aus <b>strResponse <\/b>in die Zwischenablage, damit der Entwickler diese direkt in einen geeigneten Editor eingeben und analysieren kann.<\/p>\n<h2>Rechnung in lexoffice anzeigen<\/h2>\n<p>Zu Kontrollzwecken wollen wir uns die Rechnung nun in lexoffice ansehen. Dazu k&ouml;nnte man nun <b>lexoffice.de <\/b>&ouml;ffnen und zum Ordner der Belegentw&uuml;rfe navigieren. Wir k&ouml;nnen den Beleg aber auch direkt von Access aus anzeigen. Dazu hinterlegen wir f&uuml;r die Schaltfl&auml;che <b>cmdRechnungInLexofficeAnzeigen <\/b>die folgende Prozedur:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdRechnungInLexofficeAnzeigen_Click()\r\n     <span style=\"color:blue;\">Dim <\/span>strURL<span style=\"color:blue;\"> As String<\/span>\r\n     strURL = \"https:\/\/app.lexoffice.de\/vouchers#!\" _\r\n         & \"\/VoucherView\/Invoice\/\" & Me!LexOfficeID\r\n     FollowHyperlink strURL\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Das Ergebnis sehen wir in Bild 10. Wie bereits der Beschreibung zu entnehmen: Es gibt noch einige Elemente, die wir fest im Code verdrahtet haben und die noch durch dynamische Elemente ersetzt werden k&ouml;nnen &#8211; zum Beispiel der Beschreibungstext, die Zahlungsbedingungen et cetera.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2023_02\/pic_1422_011.png\" alt=\"Neu erstellte Rechnung in lexoffice\" width=\"700\" height=\"482,5992\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 10: Neu erstellte Rechnung in lexoffice<\/span><\/b><\/p>\n<h2>Zusammenfassung und Ausblick<\/h2>\n<p>Damit haben wir bereits zwei wichtige API-Funktionen beschrieben. Die &uuml;brigen sind mit Flei&szlig;arbeit und reger Nutzung der API-Dokumentation ebenfalls umsetzbar. Gegebenenfalls zeigen wir in weiteren Beitr&auml;gen, wie sich weitere Techniken realisieren lassen.<\/p>\n<h2>Downloads zu diesem Beitrag<\/h2>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>AccessUndLexoffice.accdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/6771C9DB-9591-4B4E-A43D-092665CA82AC\/aiu_1422.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>lexoffice ist ein Online-Buchhaltungsdienst, der es Unternehmen erm&ouml;glicht, Rechnungen, Bestellungen und Bankkonten zu verwalten und Berichte zu erstellen. Der Service bietet ein einfaches Dashboard, mit dem Benutzer Gesch&auml;ftsinformationen leicht auffinden und mit wenigen Klicks auswerten k&ouml;nnen. Rechnungen lassen sich online oder &uuml;ber die mobile App erstellen, Ums&auml;tze auf Bank- oder Paypalkonten liest lexoffice automatisch ein und es erm&ouml;glicht die Zuordnung von Ein- und Ausgangsrechnungen zu den Ums&auml;tzen. Aber das Beste ist: lexoffice bietet eine REST-API-Schnittstelle, die wir von einer Access-Datenbank aus per VBA ansteuern k&ouml;nnen. Grund genug, diese Schnittstelle einmal genauer anzusehen!<\/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":[66022023,662023,44000027],"tags":[],"class_list":["post-55001422","post","type-post","status-publish","format-standard","hentry","category-66022023","category-662023","category-Loesungen"],"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>Zugriff auf lexoffice per REST-API und VBA - 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\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Zugriff auf lexoffice per REST-API und VBA\" \/>\n<meta property=\"og:description\" content=\"lexoffice ist ein Online-Buchhaltungsdienst, der es Unternehmen erm&ouml;glicht, Rechnungen, Bestellungen und Bankkonten zu verwalten und Berichte zu erstellen. Der Service bietet ein einfaches Dashboard, mit dem Benutzer Gesch&auml;ftsinformationen leicht auffinden und mit wenigen Klicks auswerten k&ouml;nnen. Rechnungen lassen sich online oder &uuml;ber die mobile App erstellen, Ums&auml;tze auf Bank- oder Paypalkonten liest lexoffice automatisch ein und es erm&ouml;glicht die Zuordnung von Ein- und Ausgangsrechnungen zu den Ums&auml;tzen. Aber das Beste ist: lexoffice bietet eine REST-API-Schnittstelle, die wir von einer Access-Datenbank aus per VBA ansteuern k&ouml;nnen. Grund genug, diese Schnittstelle einmal genauer anzusehen!\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2023-06-17T09:30:51+00:00\" \/>\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=\"28\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Zugriff auf lexoffice per REST-API und VBA\",\"datePublished\":\"2023-06-17T09:30:51+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\\\/\"},\"wordCount\":4076,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg08.met.vgwort.de\\\/na\\\/d98152f168a84f7aaa8191dcc8adf564\",\"articleSection\":[\"2\\\/2023\",\"2023\",\"L\u00f6sungen\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\\\/\",\"name\":\"Zugriff auf lexoffice per REST-API und VBA - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg08.met.vgwort.de\\\/na\\\/d98152f168a84f7aaa8191dcc8adf564\",\"datePublished\":\"2023-06-17T09:30:51+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg08.met.vgwort.de\\\/na\\\/d98152f168a84f7aaa8191dcc8adf564\",\"contentUrl\":\"http:\\\/\\\/vg08.met.vgwort.de\\\/na\\\/d98152f168a84f7aaa8191dcc8adf564\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Zugriff auf lexoffice per REST-API und VBA\"}]},{\"@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":"Zugriff auf lexoffice per REST-API und VBA - 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\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\/","og_locale":"de_DE","og_type":"article","og_title":"Zugriff auf lexoffice per REST-API und VBA","og_description":"lexoffice ist ein Online-Buchhaltungsdienst, der es Unternehmen erm&ouml;glicht, Rechnungen, Bestellungen und Bankkonten zu verwalten und Berichte zu erstellen. Der Service bietet ein einfaches Dashboard, mit dem Benutzer Gesch&auml;ftsinformationen leicht auffinden und mit wenigen Klicks auswerten k&ouml;nnen. Rechnungen lassen sich online oder &uuml;ber die mobile App erstellen, Ums&auml;tze auf Bank- oder Paypalkonten liest lexoffice automatisch ein und es erm&ouml;glicht die Zuordnung von Ein- und Ausgangsrechnungen zu den Ums&auml;tzen. Aber das Beste ist: lexoffice bietet eine REST-API-Schnittstelle, die wir von einer Access-Datenbank aus per VBA ansteuern k&ouml;nnen. Grund genug, diese Schnittstelle einmal genauer anzusehen!","og_url":"https:\/\/access-im-unternehmen.de\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\/","og_site_name":"Access im Unternehmen","article_published_time":"2023-06-17T09:30:51+00:00","author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"28\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Zugriff auf lexoffice per REST-API und VBA","datePublished":"2023-06-17T09:30:51+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\/"},"wordCount":4076,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\/#primaryimage"},"thumbnailUrl":"http:\/\/vg08.met.vgwort.de\/na\/d98152f168a84f7aaa8191dcc8adf564","articleSection":["2\/2023","2023","L\u00f6sungen"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\/","url":"https:\/\/access-im-unternehmen.de\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\/","name":"Zugriff auf lexoffice per REST-API und VBA - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\/#primaryimage"},"thumbnailUrl":"http:\/\/vg08.met.vgwort.de\/na\/d98152f168a84f7aaa8191dcc8adf564","datePublished":"2023-06-17T09:30:51+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\/#primaryimage","url":"http:\/\/vg08.met.vgwort.de\/na\/d98152f168a84f7aaa8191dcc8adf564","contentUrl":"http:\/\/vg08.met.vgwort.de\/na\/d98152f168a84f7aaa8191dcc8adf564"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Zugriff_auf_lexoffice_per_RESTAPI_und_VBA\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Zugriff auf lexoffice per REST-API und VBA"}]},{"@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\/55001422","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=55001422"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001422\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55001422"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55001422"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55001422"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}