{"id":55001395,"date":"2022-10-01T00:00:00","date_gmt":"2022-10-03T14:37:11","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=1395"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"XRechnung_Teil_2_Rechnungen_einlesen","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/XRechnung_Teil_2_Rechnungen_einlesen\/","title":{"rendered":"XRechnung, Teil 2: Rechnungen einlesen"},"content":{"rendered":"<p><b>Nachdem wir im ersten Teil dieser Beitragsreihe gezeigt haben, wie Sie aus Daten wie Kundeninformationen, Rechnungsdatum und Rechnungspositionen ein XML-Dokument im XRechnung-Format erstellen, wollen wir in diesem Beitrag den umgekehrten Weg gehen: Wir wollen die Daten aus einer so generierten Rechnung auslesen und zur&uuml;ck in das Datenmodell schreiben. Dazu sind vor allem F&auml;higkeiten im Auslesen von XML-Dokumenten erforderlich &#8211; und der Umgang mit Namespace-Deklarationen in diesen Dokumenten. Nach der Lekt&uuml;re dieses Beitrags sind Sie in der Lage, die Daten aus einer XRechnung automatisiert in ein entsprechendes Datenmodell einzulesen.<\/b><\/p>\n<h2>Ausgangssituation<\/h2>\n<p>F&uuml;r bestimmte Empf&auml;nger m&uuml;ssen Rechnungen mittlerweile in einem automatisiert lesbaren Format vorliegen, zum Beispiel im Format <b>XRechnung<\/b>. Dieses Format hat gegen&uuml;ber Rechnungen im PDF-Format den Vorteil, dass alle Informationen an der entsprechenden in der vorgegebenen XML-Struktur zu finden sind und diese somit maschinell verarbeitet werden k&ouml;nnen. Im Beitrag <b>XRechnung, Teil 1: Rechnungen generieren <\/b>(<b>www.access-im-unternehmen.de\/1277<\/b>) haben wir die Daten aus einer Rechnungsverwaltung per Knopfdruck in ein solches Dokument geschrieben.<\/p>\n<p>Nun ist es zu erwarten und auch w&uuml;nschenswert, dass sich solche Formate allgemein durchsetzen, damit niemand mehr Rechnungen in gedruckter Form oder als PDF entgegennehmen und diese h&auml;ndisch verarbeiten muss. Deshalb werden fr&uuml;her oder sp&auml;ter alle Unternehmen in der Lage sein m&uuml;ssen, solche Rechnungen zu verarbeiten.<\/p>\n<p>Im vorliegenden Beitrag wollen wir die Daten aus einem solchen XRechnung-Dokument in ein vorgegebenes Datenmodell einlesen k&ouml;nnen. In einem weiteren Beitrag schauen wir uns dann an, wie wir die eingelesenen Daten in einem Bericht als herk&ouml;mmliche Rechnung, lesbar f&uuml;r das menschliche Auge, pr&auml;sentieren k&ouml;nnen.<\/p>\n<h2>&Auml;nderung im Datenmodell<\/h2>\n<p>Im Vergleich zum Datenmodell des ersten Teils der Beitragsreihe haben wir die Tabelle <b>tblRechnungen <\/b>leicht angepasst. Wir haben ein Feld namens <b>Rechnungsnummer<\/b> zum Speichern der jeweiligen Rechnungsnummer hinzugef&uuml;gt und das Feld <b>RechnungID <\/b>mit dem Datentyp <b>Autowert <\/b>versehen. Zuvor mussten wir die Beziehung zwischen dem Feld <b>RechnungID <\/b>der Tabelle <b>tblPositionen <\/b>und der Tabelle <b>tblRechnungen <\/b>l&ouml;schen und diese anschlie&szlig;end erneut anlegen.<\/p>\n<p>Au&szlig;erdem haben wir der Tabelle <b>tblPositionen <\/b>noch ein Feld namens <b>Position <\/b>hinzugef&uuml;gt, mit dem die in der XRechnung angegebenen Positionsnummern gespeichert werden k&ouml;nnen, sowie ein Feld namens <b>Einheit<\/b>.<\/p>\n<h2>Beispielhafter Import<\/h2>\n<p>Der Standard der XRechnung umfasst nat&uuml;rlich alle denkbaren Informationen. Diese k&ouml;nnen wir im Rahmen dieses Beitrags nicht alle erfassen. Es geht hier allein darum, die grundlegenden Techniken f&uuml;r die Erfassung der g&auml;ngigsten Informationen zu pr&auml;sentieren.<\/p>\n<p>Wenn Sie oder Ihre Kunden es mit Daten in XRechnungen zu tun bekommen, deren &Uuml;bertragung hier nicht ber&uuml;cksichtigt wurde, so lernen Sie dennoch die Techniken, die n&ouml;tig sind, die notwendigen Erg&auml;nzungen vorzunehmen.<\/p>\n<h2>Datenmodell f&uuml;r die Daten aus der <\/h2>\n<h2>XRechnung<\/h2>\n<p>Das Datenmodell finden Sie in Bild 1. Jede Rechnung wird grunds&auml;tzlich in der Tabelle <b>tblRechnungen <\/b>erfasst und enth&auml;lt dort einige grundlegende Daten wie das Rechnungsdatum, den Rechnungstyp, die W&auml;hrung, eine Kundenreferenz sowie Verweise auf den K&auml;ufer und den Verk&auml;ufer. K&auml;ufer und Verk&auml;ufer werden in je einem Datensatz der Tabelle <b>tblKontakte <\/b>gespeichert und &uuml;ber Fremdschl&uuml;sselfelder der Tabelle <b>tblRechnungen <\/b>zugewiesen. Der Rechnungstyp wird aus einer Tabelle namens <b>tblRechnungstypen <\/b>ausgew&auml;hlt.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2022_05\/pic_1395_001.png\" alt=\"Datenmodell f&uuml;r die Daten aus einer XRechnung\" width=\"700\" height=\"442,2929\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Datenmodell f&uuml;r die Daten aus einer XRechnung<\/span><\/b><\/p>\n<p>Die einzelnen Rechnungspositionen landen schlie&szlig;lich in der Tabelle <b>tblPositionen<\/b>, die &uuml;ber das Fremdschl&uuml;sselfeld <b>RechnungID <\/b>dem jeweiligen Datensatz aus der Tabelle <b>tblRechnungen <\/b>zugewiesen werden.<\/p>\n<p>Jede Position enth&auml;lt Bezeichnung, Einzelpreis, Mehrwertsteuersatz und Menge, wobei der Mehrwertsteuersatz wiederum &uuml;ber ein Fremdschl&uuml;sselfeld aus der Tabelle <b>tblMehrwertsteuersaetze <\/b>ausgew&auml;hlt wird.<\/p>\n<h2>Einlesen der Basisdaten<\/h2>\n<p>Der Anfang des XRechnung-Dokuments sieht wie in Listing 1 aus. Hier sehen wir zun&auml;chst das Root-Element <b>ubl<\/b>, das einige Namespaces aufweist, um die wir uns sp&auml;ter explizit k&uuml;mmern werden.<\/p>\n<pre>&lt;ubl:Invoice xmlns:ubl=\"urn:oasis:names:specification:ubl:schema:xsd:Invoice-2\" \r\n     xmlns:cac=\"urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2\" \r\n     xmlns:cbc=\"urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2\" \r\n     xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\" \r\n     xsi:schemaLocation=\"urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 \r\n     http:\/\/docs.oasis-open.org\/ubl\/os-UBL-2.1\/xsd\/maindoc\/UBL-Invoice-2.1.xsd\"&gt;\r\n     &lt;cbc:CustomizationID&gt;urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_1.2&lt;\/cbc:CustomizationID&gt;\r\n     &lt;cbc:ID&gt;1234&lt;\/cbc:ID&gt;\r\n     &lt;cbc:IssueDate&gt;2020-09-24&lt;\/cbc:IssueDate&gt;\r\n     &lt;cbc:InvoiceTypeCode&gt;380&lt;\/cbc:InvoiceTypeCode&gt;\r\n     &lt;cbc:DocumentCurrencyCode&gt;EUR&lt;\/cbc:DocumentCurrencyCode&gt;\r\n     &lt;cbc:BuyerReference&gt;1234&lt;\/cbc:BuyerReference&gt;\r\n     &lt;cac:OrderReference&gt;\r\n         &lt;cbc:ID\/&gt;\r\n     &lt;\/cac:OrderReference&gt;\r\n     &lt;cac:ContractDocumentReference&gt;\r\n         &lt;cbc:ID\/&gt;\r\n     &lt;\/cac:ContractDocumentReference&gt;\r\n     &lt;cac:ProjectReference&gt;\r\n         &lt;cbc:ID\/&gt;\r\n     &lt;\/cac:ProjectReference&gt;\r\n     ...\r\n&lt;\/ubl&gt;<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Basisdaten der Rechnung im XML-Dokument<\/span><\/b><\/p>\n<p>Als erste untergeordnete Elemente folgen nun bereits die grundlegenden Rechnungsdaten. Das Element <b>cbc:CustomizationID <\/b>liefert das Format, in dem die Rechnung verfasst wurde, hier in der Version 1.2.<\/p>\n<p>Das Element <b>cbc:ID <\/b>liefert die Rechnungsnummer, <b>cbc:IssueDate <\/b>das Rechnungsdatum. Mit dem Wert <b>380 <\/b>im Feld <b>cbc:InvoiceTypeCode <\/b>erhalten wir einen Hinweis auf die Art der Rechnung. <b>380<\/b> steht f&uuml;r <b>Commercial Invoice<\/b>.<\/p>\n<p>Das Element <b>cbc:DocumentCurrencyCode <\/b>liefert das K&uuml;rzel f&uuml;r die W&auml;hrung der Rechnung. In der Regel finden wir hier die Einstellung <b>EUR <\/b>f&uuml;r Euro vor. Das Feld <b>cbc:BuyerReference <\/b>nimmt die sogenannte Leitweg-ID auf.<\/p>\n<p>Au&szlig;erdem gibt es noch einige weitere Elemente f&uuml;r verschiedene Referenzen wie <b>OrderReference<\/b>, <b>ContractDocumentReference<\/b>, <b>ProjectReference <\/b>et cetera, die wir an dieser Stelle jedoch nicht verarbeiten wollen.<\/p>\n<p>Wir wollen den Einlesevorgang zun&auml;chst VBA-gesteuert ausf&uuml;hren, daher erstellen wir zuerst eine Prozedur, mit der wir die einzulesende Datei per Dateiauswahl-Dialog ermitteln und dann die eigentliche Prozedur zum Einlesen aufrufen. Die Prozedur zum Initialisieren des Einlesevorgangs sieht wie folgt aus:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>Test_XRechnungEinlesen()\r\n     <span style=\"color:blue;\">Dim <\/span>strPfad<span style=\"color:blue;\"> As String<\/span>\r\n     strPfad = OpenFileName(CurrentProject.Path, \"XRechnung ausw&auml;hlen\", \"XRechnung (*.xml)\")\r\n     XRechnungEinlesen strPfad\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Die Funktion <b>OpenFileName <\/b>finden Sie im Modul <b>mdlFileDialog<\/b>.<\/p>\n<h2>Die Funktion XRechnungEinlesen<\/h2>\n<p>Danach starten wir mit der Funktion <b>XRechnungEinlesen <\/b>den eigentlichen Einlesevorgang. Dazu pr&uuml;fen wir in einer <b>If&#8230;Then<\/b>-Bedingung zun&auml;chst, ob ein Dateipfad mit <b>strPfad <\/b>&uuml;bergeben wurde und ob die Datei &uuml;berhaupt vorhanden ist (siehe Listing 2).<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>XRechnungEinlesen(strPfad<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>objXML<span style=\"color:blue;\"> As <\/span>MSXML2.DOMDocument60\r\n     <span style=\"color:blue;\">Dim <\/span>objInvoice<span style=\"color:blue;\"> As <\/span>MSXML2.IXMLDOMNode\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">Len<\/span>(Dir(strPfad)) = 0<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> objXML = <span style=\"color:blue;\">New<\/span> MSXML2.DOMDocument60\r\n         objXML.SetProperty \"SelectionNamespaces\", \"xmlns:ubl=''urn:oasis:names:specification:ubl:schema:xsd:Invoice-2''\" _\r\n             & \"xmlns:cac=''urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2'' \" _\r\n             & \"xmlns:cbc=''urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2'' \" _\r\n             & \"xmlns:xsi=''http:\/\/www.w3.org\/2001\/XMLSchema-instance''\"\r\n         objXML.Load strPfad\r\n         <span style=\"color:blue;\">Set<\/span> objInvoice = objXML.childNodes.Item(0)\r\n         XRechnungEinlesen = RechnungsdatenEinlesen(objInvoice, db)\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Startprozedur zum Einlesen der XRechnung<\/span><\/b><\/p>\n<p>Ist das der Fall, erstellt die Funktion ein neues Objekt des Typs <b>MSXML2.DOMDocument60<\/b>. Um diese verwenden zu k&ouml;nnen, ben&ouml;tigen wir einen Verweis auf die Bibliothek <b>Microsoft XML, v6.0<\/b>, die wir im <b>Verweise<\/b>-Fenster, das wir mit dem Men&uuml;befehl <b>Extras|Verweise <\/b>des VBA-Editors &ouml;ffnen, markieren m&uuml;ssen (siehe Bild 2).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2022_05\/pic_1395_002.png\" alt=\"Hinzuf&uuml;gen eines Verweises auf die XML-Bibliothek\" width=\"499,5589\" height=\"393,8207\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Hinzuf&uuml;gen eines Verweises auf die XML-Bibliothek<\/span><\/b><\/p>\n<p>Nun kommt ein entscheidender Schritt, ohne den wir dieses mit einigen Namespace-Pr&auml;fixen gespickte XML-Dokument nicht einlesen k&ouml;nnen: Wir stellen die Eigenschaft <b>SelectionNamespaces <\/b>mit der Methode <b>SetProperty <\/b>auf einen Wert ein, der die Definition der im Element <b>ubl:Invoice <\/b>des XML-Dokuments angegebenen Namespaces enth&auml;lt.<\/p>\n<p>Danach k&ouml;nnen wir die <b>Load<\/b>-Methode des Objekts <b>objXML <\/b>nutzen, um die unter <b>strPfad <\/b>angegebene XRechnung zu laden. Dann referenzieren wir das Root-Element, das wir mit <b>objXML.childNodes.Item(0) <\/b>ermitteln, mit der Variablen <b>objInvoice<\/b> und &uuml;bergeben diese an die erste Unterfunktion <b>RechnungsdatenEinlesen<\/b>. Dieser &uuml;bergeben wir auch den zuvor mit <b>CurrentDb <\/b>ermittelten Verweis auf das <b>Database<\/b>-Objekt der aktuellen Datenbankdatei.<\/p>\n<p>Die Funktion <b>RechnungsdatenEinlesen <\/b>soll nach erfolgreichem Einlesen in die Tabelle <b>tblRechnungen <\/b>den Prim&auml;rsch&uuml;sselwert des neu erstellten Datensatzes zur&uuml;ckliefern, den wir wiederum als R&uuml;ckgabewert der aufrufenden Funktion <b>XRechnungEinlesen <\/b>festlegen.<\/p>\n<h2>Funktion zum Einlesen der Rechnungsdaten<\/h2>\n<p>Die Funktion <b>RechnungsdatenEinlesen <\/b>erwartet das Root-Element sowie einen Verweis auf das aktuelle <b>Database<\/b>-Objekt als Parameter (siehe Listing 3).<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>RechnungsdatenEinlesen(objInvoice<span style=\"color:blue;\"> As <\/span>MSXML2.IXMLDOMElement, db<span style=\"color:blue;\"> As <\/span>DAO.Database)<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>strID<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>datIssueDate<span style=\"color:blue;\"> As Date<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngInvoiceTypeCode<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strDocumentCurrencyCode<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strBuyerReference<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>objKaeufer<span style=\"color:blue;\"> As <\/span>MSXML2.IXMLDOMNode\r\n     <span style=\"color:blue;\">Dim <\/span>objVerkaeufer<span style=\"color:blue;\"> As <\/span>MSXML2.IXMLDOMNode\r\n     <span style=\"color:blue;\">Dim <\/span>objPaymentMeans<span style=\"color:blue;\"> As <\/span>MSXML2.IXMLDOMNode\r\n     <span style=\"color:blue;\">Dim <\/span>objInvoiceLines<span style=\"color:blue;\"> As <\/span>MSXML2.IXMLDOMNodeList\r\n     <span style=\"color:blue;\">Dim <\/span>lngVerkaeuferID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngKaeuferID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngRechnungID<span style=\"color:blue;\"> As Long<\/span>\r\n     strID = TextEinlesen(objInvoice, \"cbc:ID\")\r\n     datIssueDate = TextEinlesen(objInvoice, \"cbc:IssueDate\")\r\n     lngInvoiceTypeCode = TextEinlesen(objInvoice, \"cbc:InvoiceTypeCode\")\r\n     strDocumentCurrencyCode = TextEinlesen(objInvoice, \"cbc:DocumentCurrencyCode\")\r\n     strBuyerReference = TextEinlesen(objInvoice, \"cbc:BuyerReference\")\r\n     <span style=\"color:blue;\">Set<\/span> objKaeufer = ElementEinlesen(objInvoice, \"\/\/cac:AccountingCustomerParty\/cac:Party\")\r\n     lngKaeuferID = AdresseEinlesen(objKaeufer, db)\r\n     <span style=\"color:blue;\">Set<\/span> objVerkaeufer = ElementEinlesen(objInvoice, \"cac:AccountingSupplierParty\/cac:Party\")\r\n     lngVerkaeuferID = AdresseEinlesen(objVerkaeufer, db)\r\n     <span style=\"color:blue;\">Set<\/span> objPaymentMeans = ElementEinlesen(objInvoice, \"cac:PaymentMeans\")\r\n     ZahlungsinformationenSchreiben objPaymentMeans, db, lngVerkaeuferID\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM tblRechnungen WHERE 1=2\", dbOpenDynaset)\r\n     <span style=\"color:blue;\">With<\/span> rst\r\n         .Add<span style=\"color:blue;\">New<\/span>\r\n         !Rechnungsnummer = strID\r\n         !Rechnungsdatum = datIssueDate\r\n         !RechnungstypID = lngInvoiceTypeCode\r\n         !Waehrung = strDocumentCurrencyCode\r\n         !Kundenreferenz = strBuyerReference\r\n         !VerkaeuferID = lngVerkaeuferID\r\n         !KaeuferID = lngKaeuferID\r\n         lngRechnungID = !RechnungID\r\n         .Update\r\n     End <span style=\"color:blue;\">With<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> objInvoiceLines = ElementeEinlesen(objInvoice, \"cac:InvoiceLine\")\r\n     PositionenEinlesen objInvoiceLines, db, lngRechnungID\r\n     RechnungsdatenEinlesen = lngRechnungID\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Hauptprozedur zum Einlesen der Rechnungsdaten<\/span><\/b><\/p>\n<p>Sie deklariert einige Variablen des Typs <b>IXMLDOMNode<\/b>, um Unterelemente von <b>objInvoice <\/b>aufzunehmen, sowie ein Element des Typs <b>IXMLDOMNodeList <\/b>f&uuml;r die Rechnungspositionen in der XRechnung. Au&szlig;erdem ben&ouml;tigen wir eine <b>Recordset<\/b>-Variable namens <b>rst<\/b>, der wir die Tabelle <b>tblRechnungen <\/b>zuweisen und &uuml;ber die wir den neuen Rechnungsdatensatz anlegen. Daneben dienen einige weitere Variablen wie <b>strID<\/b>, <b>datIssueDate <\/b>et cetera dazu, die Werte aus der XRechnung nach dem Auslesen und vor dem Eintragen in den neuen Datensatz tempor&auml;r aufzunehmen.<\/p>\n<h2>Basisdaten der Rechnung aus der XRechnung einlesen<\/h2>\n<p>Die ersten Anweisungen lesen die Werte der entsprechenden Elemente aus der XRechnung ein. Dazu nutzen diese verschiedene Hilfsfunktionen, die wir am Ende des Beitrags beschreiben. Die erste hei&szlig;t <b>TextEinlesen<\/b> und sucht aus einem <b>IXMLDomNode<\/b>-Element den Text des mit dem zweiten Parameter &uuml;bergebenen Wertes aus &#8211; in der ersten Anweisung beispielsweise das Element <b>cbc:ID<\/b>. Dieser Wert landet in der Variablen <b>strID<\/b>. Das Gleiche geschieht mit den Elementen <b>cbc:IssueDate<\/b>, <b>cbc:InvoiceTypeCode<\/b>, <b>cbc:DocumentCurrencyCode <\/b>und <b>cbc:BuyerReference<\/b>. Damit erhalten wir die Basisdaten der Rechnung.<\/p>\n<p><!--30percent--><\/p>\n<p>Danach nutzen wir eine weitere Hilfsfunktion namens <b>ElementEinlesen<\/b>, um das Unterelement mit dem Namen <b>cac:AccountingCustomerParty\/cac:Party<\/b> mit der Variablen <b>objKaeufer<\/b> zu referenzieren. Dieser Teilbereich der XRechnung sieht beispielsweise wie in Listing 4 aus.<\/p>\n<pre>     &lt;cac:AccountingCustomerParty&gt;\r\n         &lt;cac:Party&gt;\r\n             &lt;cac:PostalAddress&gt;\r\n                 &lt;cbc:StreetName&gt;Teststr. 1&lt;\/cbc:StreetName&gt;\r\n                 &lt;cbc:AdditionalStreetName\/&gt;\r\n                 &lt;cbc:CityName&gt;Berlin&lt;\/cbc:CityName&gt;\r\n                 &lt;cbc:PostalZone&gt;12121&lt;\/cbc:PostalZone&gt;\r\n                 &lt;cac:Country&gt;\r\n                     &lt;cbc:IdentificationCode&gt;DE&lt;\/cbc:IdentificationCode&gt;\r\n                 &lt;\/cac:Country&gt;\r\n             &lt;\/cac:PostalAddress&gt;\r\n             &lt;cac:PartyTaxScheme&gt;\r\n                 &lt;cbc:CompanyID&gt;DE232323232&lt;\/cbc:CompanyID&gt;\r\n                 &lt;cac:TaxScheme&gt;\r\n                     &lt;cbc:ID&gt;VAT&lt;\/cbc:ID&gt;\r\n                 &lt;\/cac:TaxScheme&gt;\r\n             &lt;\/cac:PartyTaxScheme&gt;\r\n             &lt;cac:PartyLegalEntity&gt;\r\n                 &lt;cbc:RegistrationName&gt;M&uuml;ller AG&lt;\/cbc:RegistrationName&gt;\r\n             &lt;\/cac:PartyLegalEntity&gt;\r\n             &lt;cac:Contact&gt;\r\n                 &lt;cbc:Name&gt;Klaus M&uuml;ller&lt;\/cbc:Name&gt;\r\n                 &lt;cbc:Telephone&gt;0123-2121212&lt;\/cbc:Telephone&gt;\r\n                 &lt;cbc:ElectronicMail&gt;klaus@mueller.de&lt;\/cbc:ElectronicMail&gt;\r\n             &lt;\/cac:Contact&gt;\r\n         &lt;\/cac:Party&gt;\r\n     &lt;\/cac:AccountingCustomerParty&gt;<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Element mit den Daten des Rechnungsempf&auml;ngers<\/span><\/b><\/p>\n<p>Nachdem wir dieses Element aufgerufen haben, rufen wir die Funktion <b>AdresseEinlesen <\/b>auf und &uuml;bergeben dieser das <b>IXMLDOMNode<\/b>-Element aus <b>objKaeufer <\/b>sowie einen Verweis auf das <b>Database<\/b>-Objekt. Der &Uuml;bersicht halber beschreiben wir diese Funktion erst sp&auml;ter. An dieser Stelle interessiert uns nur das Ergebnis dieser Funktion. Diese schreibt n&auml;mlich die K&auml;uferdaten in die Tabelle <b>tblKontakte <\/b>und liefert den Wert des Prim&auml;rschl&uuml;ssels des neu hinzugef&uuml;gten Datensatzes zur&uuml;ck. Diesen k&ouml;nnen wir dann in der Variablen <b>lngKaeuferID <\/b>zwischenspeichern und beim Erstellen eines neuen Rechnungsdatensatzes direkt in die Tabelle <b>tblRechnungen <\/b>schreiben.<\/p>\n<p>Auf die gleiche Weise lesen wir auch noch die Daten des Verk&auml;ufers ein. Diese finden wir im Element <b>cac:AccountingSupplierParty\/cac:Party<\/b>. Auch f&uuml;r dieses Element rufen wir die Funktion <b>AdresseEinlesen <\/b>auf, was dazu f&uuml;hrt, dass auch der Verk&auml;ufer als neuer Datensatz in der Tabelle <b>tblKontakte <\/b>landet. Den Prim&auml;rschl&uuml;sselwert des neuen Datensatzes speichern wir in der Variablen <b>lngVerkaeuferID<\/b>, um ihn sp&auml;ter in der Tabelle <b>tblRechnungen <\/b>zu speichern.<\/p>\n<h2>Zahlungsinformationen erfassen<\/h2>\n<p>Mit der Variablen <b>objPaymentMeans <\/b>des Typs <b>IXMLDOMNode <\/b>referenzieren wir nun den folgenden Bereich der XRechnung, der die Zahlungsinformationen enth&auml;lt:<\/p>\n<pre>&lt;cac:PaymentMeans&gt;\r\n     &lt;cbc:PaymentMeansCode&gt;31&lt;\/cbc:PaymentMeansCode&gt;\r\n     &lt;cbc:PaymentID&gt;Debit transfer&lt;\/cbc:PaymentID&gt;\r\n     &lt;cac:PayeeFinancialAccount&gt;\r\n         &lt;cbc:ID&gt;DE12121212121212121212&lt;\/cbc:ID&gt;\r\n         &lt;cbc:Name&gt;Andre Minhorst&lt;\/cbc:Name&gt;\r\n         &lt;cac:FinancialInstitutionBranch&gt;\r\n             &lt;cbc:ID\/&gt;\r\n         &lt;\/cac:FinancialInstitutionBranch&gt;\r\n     &lt;\/cac:PayeeFinancialAccount&gt;\r\n&lt;\/cac:PaymentMeans&gt;<\/pre>\n<p>Mit den hier enthaltenen Informationen und der ID des Verk&auml;ufers rufen wir dann die Prozedur <b>ZahlungsinformationenSchreiben<\/b> auf. Diese f&uuml;gt die Zahlungsinformationen wie die IBAN und den Kontoinhaber zum Datensatz des Verk&auml;ufers in der Tabelle <b>tblKontakte <\/b>hinzu.<\/p>\n<p>Damit haben wir alle notwendigen Informationen eingelesen und k&ouml;nnen nun zum Schreiben der Daten in die Tabelle <b>tblRechnungen <\/b>schreiten. Das erledigen wir, indem wir ein neues Recordset auf Basis der Tabelle <b>tblRechnungen<\/b> erstellen, dass aber keine Datens&auml;tze enthalten soll &#8211; deshalb das Kriterium <b>1=2<\/b>.<\/p>\n<p>Hier f&uuml;gen wir mit der <b>AddNew<\/b>-Methode einen neuen Datensatz hinzu und f&uuml;llen die Felder der Tabelle mit den zuvor ermittelten Werten &#8211; unter anderem auch die Fremdschl&uuml;sselfelder <b>VerkaeuferID <\/b>und <b>KaeuferID <\/b>mit den Prim&auml;rschl&uuml;sselwerten der zuvor in der Tabelle <b>tblKontakte <\/b>angelegten Datens&auml;tzen.<\/p>\n<p>Im letzten Schritt vor dem Speichern des neuen Datensatzes mit der <b>Update<\/b>-Methode schreiben wir noch den Prim&auml;rschl&uuml;sselwert des neuen Datensatzes in die Variable <b>lngRechnung<\/b>. Dieser Zeitpunkt ist wichtig, weil der Datensatzzeiger durch die <b>Update<\/b>-Methode auf einen anderen Datensatz verschoben wird und der Autowert des erstellten Datensatzes nicht mehr verf&uuml;gbar ist.<\/p>\n<p>Nach dem Update folgt noch ein weiterer wichtiger Schritt: Mit der Hilfsfunktion <b>ElementeEinlesen <\/b>(Beschreibung sieht weiter unten) lesen wir alle Elemente des Typs <b>cac:InvoiceLine <\/b>in eine Variable des Typs <b>IXMLDOMNodeList <\/b>ein. Diese &uuml;bergeben wir dann samt der neuen Rechnungs-ID an die Prozedur <b>PositionenEinlesen<\/b>, welche die einzelnen Rechnungspositionen aus der XRechnung in die Tabelle <b>tblPositionen <\/b>schreibt und dabei gleich das Fremdschl&uuml;sselfeld <b>RechnungID <\/b>mit dem Prim&auml;rschl&uuml;sselfeld der soeben erstellten Rechnung f&uuml;llt.<\/p>\n<p>Zum Abschluss geben wir den Prim&auml;rsch&uuml;sselwert des neuen Datensatzes in der Tabelle <b>tblRechnungen <\/b>an die aufrufende Funktion <b>XRechnungEinlesen <\/b>zur&uuml;ck.<\/p>\n<h2>Anlegen von K&auml;ufer und Verk&auml;ufer in der Tabelle tblKontakte<\/h2>\n<p>Den Einsatzzweck der Funktion <b>AdresseEinlesen <\/b>haben wir bereits weiter oben vorgestellt. Die Funktion soll die Daten von K&auml;ufern und Verk&auml;ufern in der Tabelle <b>tblKontakte <\/b>speichern und den Prim&auml;rschl&uuml;sselwert des gegebenenfalls neu erstellten Datensatzes zur&uuml;ckliefern, damit dieser als Wert f&uuml;r eines der Fremdschl&uuml;sselfelder <b>KaeuferID <\/b>oder <b>VerkaeuferID <\/b>gespeichert werden kann (siehe Listing 5). Dazu &uuml;bergeben wir der Funktion das <b>IXMLDOMNode<\/b>-Element mit den Daten der jeweiligen Partei sowie den Verweis auf das aktuelle <b>Database<\/b>-Objekt.<\/p>\n<pre><span style=\"color:blue;\">Private Function <\/span>AdresseEinlesen(objParty<span style=\"color:blue;\"> As <\/span>MSXML2.IXMLDOMNode, db<span style=\"color:blue;\"> As <\/span>DAO.Database)<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>strStreetName<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strCityName<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strCountry<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strPostalZone<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strCompanyID<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strRegistrationName<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strName<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strTelephone<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strElectronicMail<span style=\"color:blue;\"> As String<\/span>\r\n     strStreetName = TextEinlesen(objParty, \"cac:PostalAddress\/cbc:StreetName\")\r\n     strCityName = TextEinlesen(objParty, \"cac:PostalAddress\/cbc:CityName\")\r\n     strCountry = TextEinlesen(objParty, \"cac:PostalAddress\/cac:Country\/cbc:IdentificationCode\")\r\n     strPostalZone = TextEinlesen(objParty, \"cac:PostalAddress\/cbc:PostalZone\")\r\n     strCompanyID = TextEinlesen(objParty, \"cac:PartyTaxScheme\/cbc:CompanyID\")\r\n     strRegistrationName = TextEinlesen(objParty, \"cac:PartyLegalEntity\/cbc:RegistrationName\")\r\n     strName = TextEinlesen(objParty, \"cac:Contact\/cbc:Name\")\r\n     strTelephone = TextEinlesen(objParty, \"cac:Contact\/cbc:Telephone\")\r\n     strElectronicMail = TextEinlesen(objParty, \"cac:Contact\/cbc:ElectronicMail\")\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM tblKontakte WHERE UstIDNr = ''\" & strCompanyID & \"''\", dbOpenDynaset)\r\n     <span style=\"color:blue;\">With<\/span> rst\r\n         <span style=\"color:blue;\">If <\/span>rst.EOF<span style=\"color:blue;\"> Then<\/span>\r\n             .Add<span style=\"color:blue;\">New<\/span>\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             .Edit\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         !Firma = strRegistrationName\r\n         !Ansprechpartner = strName\r\n         !Telefon = strTelephone\r\n         !EMail = strElectronicMail\r\n         !Strasse = strStreetName\r\n         !PLZ = strPostalZone\r\n         !Ort = strCityName\r\n         !LandID = DLookup(\"LandID\", \"tblLaender\", \"LandKuerzel = ''\" & strCountry & \"''\")\r\n         !UstIDNr = strCompanyID\r\n         AdresseEinlesen = !KontaktID\r\n         .Update\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 5: Funktion zum Anlegen eines Kontaktes in der Tabelle tblKontakte<\/span><\/b><\/p>\n<p>Die Funktion deklariert einige Variablen zum Zwischenspeichern der ermittelten Daten. Sie liest die Elemente in der Reihenfolge ein, in der sie in der XRechnung auftauchen. Also beginnen wir mit der Stra&szlig;e, die wir &uuml;ber die Hilfsfunktion <b>TextEinlesen <\/b>mit dem zu untersuchenden Elementnamen <b>cac:PostalAddress\/cbc:Streetname <\/b>einlesen und in der Variablen <b>strStreetName <\/b>speichern. Auf die gleiche Weise speichern wir den Namen der Stadt, das K&uuml;rzel f&uuml;r das Land, die PLZ, die Umsatzsteuer-Identifikationsnummer, den Firmennamen, den Namen des Ansprechpartners, die Telefonnummer und die E-Mail in entsprechenden Variablen.<\/p>\n<h2>Umsatzsteuer-Identifikationsnummer als eindeutiges Merkmal<\/h2>\n<p>Wir gehen an dieser Stelle davon aus, dass wir die Umsatzsteuer-Identifikationsnummer als eindeutiges Merkmal voraussetzen k&ouml;nnen. Das ist deswegen interessant, weil ja auch mehrere Leistungen vom gleichen Anbieter in Rechnung gestellt werden k&ouml;nnten. Wir wollen diesen Anbieter dann nicht immer wieder neu in der Tabelle <b>tblKontakte <\/b>speichern, sondern der neuen Rechnung den bestehenden Eintrag verwenden. Deshalb versuchen wir, ein Recordset auf Basis der Tabelle <b>tblKontakte <\/b>zu erstellen, das einen Datensatz mit der entsprechenden Umsatzsteuer-Identifikationsnummer enth&auml;lt. Mit der anschlie&szlig;enden <b>If&#8230;Then<\/b>-Bedingung pr&uuml;fen wir den Wert der Eigenschaft <b>EOF <\/b>des Recordsets. Ist dieser <b>True<\/b>, befindet sich der Datensatzzeiger am Ende des Recordsets und somit ist kein Datensatz im Recordset <b>rst <\/b>enthalten. Also legen wir mit <b>AddNew <\/b>einen neuen Datensatz an. Liefert <b>rst.EOF <\/b>hingegen den Wert <b>False<\/b>, ist ein Datensatz vorhanden und wir k&ouml;nnen diesen mit den aktuellen Daten &uuml;berschreiben. In diesem Fall schalten wir diesen Datensatz mit der <b>Edit<\/b>-Methode in den Bearbeitungsmodus.<\/p>\n<p>Unabh&auml;ngig davon, ob wir einen neuen Datensatz angelegt haben oder ob wir einen vorhandenen Kontakt bearbeiten, schreiben wir nun mit der letzten Rechnung gelieferten Daten in die Tabelle. F&uuml;r <b>strCountry <\/b>haben wir nur das K&uuml;rzel f&uuml;r das Land erhalten, zum Beispiel <b>DE<\/b>.<\/p>\n<p>In der Tabelle <b>tblLaender <\/b>haben wir diese K&uuml;rzel in einem eigenen Feld gespeichert, sodass wir die ID des entsprechenden Datensatzes der Tabelle <b>tblLaender <\/b>mit der <b>DLookup<\/b>-Funktion ermitteln und dann in das Feld <b>LandID <\/b>schreiben k&ouml;nnen.<\/p>\n<p>Schlie&szlig;lich schreiben wir auch hier vor dem Speichern der Datensatz&auml;nderungen noch den Wert des Prim&auml;rschl&uuml;sselfeldes in eine Variable, in diesem Fall als R&uuml;ckgabewert der Funktion <b>AdresseEinlesen<\/b>, und speichern anschlie&szlig;end den neu angelegten oder bearbeiteten Datensatz.<\/p>\n<p>Mit dieser Funktion legen wir nacheinander die Daten des in der XRechnung angegebenen K&auml;ufers und des Verk&auml;ufers an und geben die Prim&auml;rschl&uuml;sselwerte jeweils an die aufrufende Prozedur <b>RechnungsdatenEinlesen <\/b>zur&uuml;ck.<\/p>\n<h2>Bankverbindung speichern<\/h2>\n<p>Damit kommen wir zu einem Teil, der nur f&uuml;r den Verk&auml;ufer beziehungsweise Anbieter interessant ist, n&auml;mlich die Bankverbindung. Diese finden wir im Element <b>cac:PaymentMeans<\/b>, das wir bereits weiter oben vorgestellt haben. Um dieses auszulesen, verwenden wir die Prozedur <b>ZahlungsinformationenSchreiben<\/b>. Diese erwartet einen Verweis auf das entsprechende <b>IXMLDOMNode<\/b>-Element sowie auf das aktuelle <b>Database<\/b>-Objekt und den Prim&auml;rschl&uuml;sselwert des Anbieters aus der Tabelle <b>tblKontakte <\/b>als Parameter (siehe Listing 6).<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>ZahlungsinformationenSchreiben(objPaymentMeans<span style=\"color:blue;\"> As <\/span>MSXML2.IXMLDOMNode, db<span style=\"color:blue;\"> As <\/span>DAO.Database, lngKaeuferID<span style=\"color:blue;\"> As Long<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>strPayeeFinancialAccountID<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strPayeeFinancialAccountName<span style=\"color:blue;\"> As String<\/span>\r\n     strPayeeFinancialAccountID = TextEinlesen(objPaymentMeans, \"cac:PayeeFinancialAccount\/cbc:ID\")\r\n     strPayeeFinancialAccountName = TextEinlesen(objPaymentMeans, \"cac:PayeeFinancialAccount\/cbc:Name\")\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM tblKontakte WHERE KontaktID = \" & lngKaeuferID, dbOpenDynaset)\r\n     rst.Edit\r\n     rst!Kontoinhaber = strPayeeFinancialAccountName\r\n     rst!IBAN = strPayeeFinancialAccountID\r\n     rst.Update\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 6: Funktion zum Erweitern eines der Eintr&auml;ge der Tabelle tblKontakte um die Zahlungsinformationen<\/span><\/b><\/p>\n<p>Die Prozedur ermittelt die Werte der Elemente <b>cac:PayeeFinancialAccount\/cbc:ID <\/b>und <b>cac:PayeeFinancialAccount\/cbc:Name <\/b>und schreibt diese in entsprechende Variablen. Dann erstellt sie ein Recordset auf Basis der Tabelle <b>tblKontakte <\/b>mit dem Datensatz des zuvor angelegten Verk&auml;ufer-Kontakts und versetzt diesen mit der <b>Edit<\/b>-Methode in den Bearbeitungsmodus. Nachdem sie die beiden Felder <b>Kontoinhaber <\/b>und <b>IBAN <\/b>mit den Daten aus der XRechnung gef&uuml;llt hat, speichert sie den Datensatz wieder.<\/p>\n<h2>Rechnungspositionen einlesen<\/h2>\n<p>Damit kommen wir bereits zum letzten Teil der XRechnung, den wir einlesen wollen. Das betroffene Element kann einmal oder mehrmals in der XRechnung enthalten sein und hei&szlig;t <b>cac:InvoiceLine<\/b>. Im Beispiel aus Listing 7 sehen wir zwei solcher Elemente.<\/p>\n<pre>     &lt;cac:InvoiceLine&gt;\r\n         &lt;cbc:ID&gt;1&lt;\/cbc:ID&gt;\r\n         &lt;cbc:InvoicedQuantity unitCode=\"XPP\"&gt;1&lt;\/cbc:InvoicedQuantity&gt;\r\n         &lt;cbc:LineExtensionAmount currencyID=\"EUR\"&gt;12&lt;\/cbc:LineExtensionAmount&gt;\r\n         &lt;cac:Item&gt;\r\n             &lt;cbc:Description\/&gt;\r\n             &lt;cbc:Name&gt;Position 1&lt;\/cbc:Name&gt;\r\n             &lt;cac:ClassifiedTaxCategory&gt;\r\n                 &lt;cbc:ID&gt;S&lt;\/cbc:ID&gt;\r\n                 &lt;cbc:Percent&gt;7&lt;\/cbc:Percent&gt;\r\n                 &lt;cac:TaxScheme&gt;\r\n                     &lt;cbc:ID&gt;VAT&lt;\/cbc:ID&gt;\r\n                 &lt;\/cac:TaxScheme&gt;\r\n             &lt;\/cac:ClassifiedTaxCategory&gt;\r\n         &lt;\/cac:Item&gt;\r\n         &lt;cac:Price&gt;\r\n             &lt;cbc:PriceAmount currencyID=\"EUR\"&gt;12&lt;\/cbc:PriceAmount&gt;\r\n         &lt;\/cac:Price&gt;\r\n     &lt;\/cac:InvoiceLine&gt;\r\n     &lt;cac:InvoiceLine&gt;\r\n         &lt;cbc:ID&gt;2&lt;\/cbc:ID&gt;\r\n         &lt;cbc:InvoicedQuantity unitCode=\"XPP\"&gt;2&lt;\/cbc:InvoicedQuantity&gt;\r\n         &lt;cbc:LineExtensionAmount currencyID=\"EUR\"&gt;20&lt;\/cbc:LineExtensionAmount&gt;\r\n         &lt;cac:Item&gt;\r\n             &lt;cbc:Description\/&gt;\r\n             &lt;cbc:Name&gt;Position 2&lt;\/cbc:Name&gt;\r\n             &lt;cac:ClassifiedTaxCategory&gt;\r\n                 &lt;cbc:ID&gt;S&lt;\/cbc:ID&gt;\r\n                 &lt;cbc:Percent&gt;19&lt;\/cbc:Percent&gt;\r\n                 &lt;cac:TaxScheme&gt;\r\n                     &lt;cbc:ID&gt;VAT&lt;\/cbc:ID&gt;\r\n                 &lt;\/cac:TaxScheme&gt;\r\n             &lt;\/cac:ClassifiedTaxCategory&gt;\r\n         &lt;\/cac:Item&gt;\r\n         &lt;cac:Price&gt;\r\n             &lt;cbc:PriceAmount currencyID=\"EUR\"&gt;10&lt;\/cbc:PriceAmount&gt;\r\n         &lt;\/cac:Price&gt;\r\n     &lt;\/cac:InvoiceLine&gt;\r\n&lt;\/ubl:Invoice&gt;<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 7: Zwei Elemente mit den Daten je einer Rechnungsposition<\/span><\/b><\/p>\n<p>Diese lesen wir mit der Funktion <b>PositionenEinlesen <\/b>ein (siehe Listing 8). Die Funktion erwartet das in der aufrufenden Prozedur ermittelte <b>IXMLDOMNodeList<\/b>-Element mit den Rechnungspositionen, einen Verweis auf das <b>Database<\/b>-Objekt sowie den Prim&auml;rschl&uuml;sselwert der dort angelegten Rechnung als Parameter.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>PositionenEinlesen(objInvoiceLines<span style=\"color:blue;\"> As <\/span>MSXML2.IXMLDOMNodeList, db<span style=\"color:blue;\"> As <\/span>DAO.Database, lngRechnungID<span style=\"color:blue;\"> As Long<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>objInvoiceLine<span style=\"color:blue;\"> As <\/span>MSXML2.IXMLDOMNode\r\n     <span style=\"color:blue;\">Dim <\/span>objInvoicedQuantity<span style=\"color:blue;\"> As <\/span>MSXML2.IXMLDOMNode\r\n     <span style=\"color:blue;\">Dim <\/span>strID<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngInvoicedQuantity<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strUnitCode<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strName<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>curClassifiedTaxCategoryPercent<span style=\"color:blue;\"> As Currency<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>curPrice<span style=\"color:blue;\"> As Currency<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM tblPositionen WHERE 1=2\", dbOpenDynaset)\r\n     For Each objInvoiceLine In objInvoiceLines\r\n         strID = TextEinlesen(objInvoiceLine, \"cbc:ID\")\r\n         lngInvoicedQuantity = TextEinlesen(objInvoiceLine, \"cbc:InvoicedQuantity\")\r\n         <span style=\"color:blue;\">Set<\/span> objInvoicedQuantity = ElementEinlesen(objInvoiceLine, \"cbc:InvoicedQuantity\")\r\n         strUnitCode = AttributEinlesen(objInvoicedQuantity, \"unitCode\")\r\n         strName = TextEinlesen(objInvoiceLine, \"cac:Item\/cbc:Name\")\r\n         curClassifiedTaxCategoryPercent = TextEinlesen(objInvoiceLine, \"cac:Item\/cac:ClassifiedTaxCategory\/cbc:Percent\")\r\n         curPrice = TextEinlesen(objInvoiceLine, \"cac:Price\/cbc:PriceAmount\")\r\n         <span style=\"color:blue;\">With<\/span> rst\r\n             .Add<span style=\"color:blue;\">New<\/span>\r\n             !Position = strID\r\n             !Einheit = strUnitCode\r\n             !RechnungID = lngRechnungID\r\n             !Bezeichnung = strName\r\n             !Einzelpreis = curPrice\r\n             !MehrwertsteuersatzID = DLookup(\"MehrwertsteuersatzID\", \"tblMehrwertsteuersaetze\", ?\r\n                 \"Mehrwertsteuersatz = \" & <span style=\"color:blue;\">Replace<\/span>(curClassifiedTaxCategoryPercent \/ 100, \",\", \".\"))\r\n             !Menge = lngInvoicedQuantity\r\n             .Update\r\n         End <span style=\"color:blue;\">With<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> objInvoiceLine\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 8: Funktion zum Einlesen von Rechnungspositionen<\/span><\/b><\/p>\n<p>Die deklariert neben einigen andere Variablen eine Variable namens <b>objInvoiceLine <\/b>mit dem Typ <b>IXMLDOMNode<\/b>. Au&szlig;erdem erstellt sie ein <b>Recordset<\/b>-Objekt auf Basis der Tabelle <b>tblPositionen<\/b>, wobei das Kriterium wieder daf&uuml;r sorgt, dass wir ein leeres Recordset erhalten.<\/p>\n<p>Mit der Variablen <b>objInvoiceLine <\/b>durchl&auml;uft die Prozedur anschlie&szlig;end die Elemente aus <b>objInvoiceLines<\/b>. Dabei liest sie die Werte der enthaltenen Elemente in entsprechende Variablen ein, zum Beispiel die Rechnungsposition aus dem Feld <b>cbc:ID <\/b>in die Variable <b>strID<\/b>. Dabei kommt immer wieder die Hilfsfunktion <b>TextEinlesen <\/b>zum Einsatz. Zum Ermitteln der Einheit f&uuml;r die Menge einer Rechnungsposition nutzen wir einmal auch die Hilfsfunkton <b>AttributEinlesen<\/b>.<\/p>\n<p>Nachdem alle Eigenschaften der Rechnungsposition eingelesen wurden, schreibt die Prozedur diese in einen mit <b>AddNew <\/b>vorbereiteten neuen Datensatz der Tabelle <b>tblPositionen<\/b>. Hier ist lediglich die Ermittlung des Wertes f&uuml;r das Fremdschl&uuml;sselfeld <b>MehrwertsteuersatzID <\/b>zu erw&auml;hnen. Da die XRechnung nur den Mehrwertsteuersatz als Prozentzahl liefert, m&uuml;ssen wir noch per <b>DLookup <\/b>den entsprechenden Datensatz der Tabelle <b>tblMehrwertsteuersaetze <\/b>ermitteln, um seinen Prim&auml;rschl&uuml;sselwert f&uuml;r das entsprechende Fremdschl&uuml;sselfeld in der Tabelle <b>tblPositionen <\/b>einzutragen. Nachdem die Prozedur alle Positionen der XRechnung durchlaufen hat, ist das Einlesen der von uns ben&ouml;tigten Informationen abgeschlossen.<\/p>\n<h2>Hilfsfunktionen<\/h2>\n<p>In den vorherigen Prozeduren haben wir einige Hilfsfunktionen zum Auslesen verschiedener Informationen aus XML-Elementen verwendet. Diese sparen einige Zeilen Code, da sie immer wiederkehrende Anweisungen enthalten. Die Hilfsfunktionen stellen wir in den folgenden Abschnitten vor.<\/p>\n<h2>Hilfsfunktion zum Einlesen des Elementwertes<\/h2>\n<p>Die Hilfsfunktion <b>TextEinlesen <\/b>erwartet die Angabe eines <b>IXMLDOMNode<\/b>-Elements und den Namen des Elements, dessen Inhalt eingelesen werden soll.<\/p>\n<p>Die Funktion referenziert mit der Funktion <b>selectSingleNode <\/b>zun&auml;chst das mit <b>strElement <\/b>angegebene Unterelement mit der Variablen <b>objNode<\/b>. Ist dieses Element vorhanden, liest es seinen Wert &uuml;ber die Eigenschaft <b>nodeTypedValue <\/b>aus und gibt diesen als Ergebnis der Funktion zur&uuml;ck:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>TextEinlesen(objParent<span style=\"color:blue;\"> As <\/span>IXMLDOMNode,  strElement<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Variant<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>objNode<span style=\"color:blue;\"> As <\/span>IXMLDOMNode\r\n     <span style=\"color:blue;\">Set<\/span> objNode = objParent.selectSingleNode(strElement)\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> objNode Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n         TextEinlesen = objNode.nodeTypedValue\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<h2>Hilfsfunktion zum Einlesen eines Unterelements<\/h2>\n<p>Manchmal m&ouml;chte man ein Unterelement des Typs <b>IXMLDOMNode <\/b>referenzieren, um weitere Unterelemente oder Attribute auszulesen. F&uuml;r diesen Fall haben wir die Funktion <b>ElementEinlesen <\/b>verwendet, welche die gleichen Parameter wie die zuvor beschriebene Hilfsfunktion erwartet, aber statt des enthaltenen Textes ein Element des Typs <b>IXMLDOMNode <\/b>zur&uuml;ckliefert:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>ElementEinlesen( objParent<span style=\"color:blue;\"> As <\/span>IXMLDOMNode, strElement<span style=\"color:blue;\"> As String<\/span>) <span style=\"color:blue;\"> As <\/span>MSXML2.IXMLDOMNode\r\n     <span style=\"color:blue;\">Dim <\/span>objNode<span style=\"color:blue;\"> As <\/span>IXMLDOMNode\r\n     <span style=\"color:blue;\">Set<\/span> objNode = objParent.selectSingleNode(strElement)\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> objNode Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> ElementEinlesen = objNode\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Auch hier kann es vorkommen, dass das zu referenzierende Element nicht vorhanden ist &#8211; dann gibt die Funktion den Wert <b>Nothing <\/b>zur&uuml;ck.<\/p>\n<h2>Hilfsfunktion zum Einlesen einer Liste von Unterelementen<\/h2>\n<p>F&uuml;r die Verarbeitung der Rechnungspositionen in der XRechnung m&uuml;ssen wir einige Elemente gleichen Namens durchlaufen. Auch daf&uuml;r haben wir eine Hilfsfunktion programmiert, welche wieder die gleichen Parameter wie die zuvor beschriebenen verwendet. Diesmal nutzen wir allerdings nicht die Funktion <b>selectSingleNode<\/b>, sondern <b>selectNodes<\/b>, um das Ergebnis zu erhalten. Das Ergebnis wird dann als Element des Typs <b>IXMLDOMNodeList <\/b>an die aufrufende Routine zur&uuml;ckgegeben:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>ElementeEinlesen( objParent<span style=\"color:blue;\"> As <\/span>IXMLDOMNode, strElement<span style=\"color:blue;\"> As String<\/span>) <span style=\"color:blue;\"> As <\/span>IXMLDOMNodeList\r\n     <span style=\"color:blue;\">Dim <\/span>objNodeList<span style=\"color:blue;\"> As <\/span>IXMLDOMNodeList\r\n     <span style=\"color:blue;\">Set<\/span> objNodeList = objParent.selectNodes(strElement)\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> objNodeList Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> ElementeEinlesen = objNodeList\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<h2>Hilfsfunktion zum Einlesen von Attributwerten<\/h2>\n<p>Schlie&szlig;lich fehlt noch die Funktion, mit der wir den Wert von Attributen eines <b>IXMLDOMNode<\/b>-Elements einlesen k&ouml;nnen. Diese hei&szlig;t <b>AttributEinlesen <\/b>und erwartet einen Verweis auf das <b>IXMLDOMNode<\/b>-Element mit dem zu untersuchenden Attribut sowie den Namen des Attributs als Parameter. Es ermittelt mit der Funktion <b>getNamedItem <\/b>der <b>Attributes<\/b>-Auflistung des Elements das entsprechende Attribut und gibt dessen Wert als Ergebnis zur&uuml;ck:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>AttributEinlesen( objParent<span style=\"color:blue;\"> As <\/span>IXMLDOMNode,  strAttribut<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Variant<\/span>\r\n     AttributEinlesen = objParent.Attributes. getNamedItem(strAttribut).nodeTypedValue\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<h2>Einlesen der XRechnung per Formular<\/h2>\n<p>Das Formular <b>frmRechnung<\/b> zur Anzeige und Eingabe von Rechnungen sowie zur Erstellung von XRechnungen per Mausklick haben wir bereits im ersten Teil dieser Beitragsreihe vorgestellt. Nun wollen wir noch eine zweite Schaltfl&auml;che hinzuf&uuml;gen, mit der wir dem Formular eine neue Rechnung &uuml;ber den Import einer XRechnung hinzuf&uuml;gen k&ouml;nnen. Diese Schaltfl&auml;che f&uuml;gen wir direkt neben der ersten Schaltfl&auml;che ein (siehe Bild 3).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2022_05\/pic_1395_003.png\" alt=\"Neue Schaltfl&auml;che zum Importieren einer XRechnung\" width=\"499,5589\" height=\"295,269\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Neue Schaltfl&auml;che zum Importieren einer XRechnung<\/span><\/b><\/p>\n<p>Au&szlig;erdem f&uuml;gen wir einen Mechanismus hinzu, der daf&uuml;r sorgt, dass eine XRechnung nur in einen neuen, leeren Datensatz eingef&uuml;gt werden kann.<\/p>\n<p>Dazu aktivieren oder deaktivieren wir die beiden Schaltfl&auml;chen &#8211; je nachdem, ob das Formular gerade einen bereits gespeicherten oder einen neuen Datensatz anzeigt. Dies erledigen wir in der Ereignisprozedur, die durch das Ereignis <b>Beim Anzeigen <\/b>des Formulars ausgel&ouml;st wird:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Current()\r\n     Me!cmdXRechnungEinlesen.Enabled = Me.NewRecord\r\n     Me!cmdXRechnungErstellen.Enabled = <span style=\"color:blue;\">Not<\/span> Me.NewRecord\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Die Prozedur f&uuml;r die neue Schaltfl&auml;che <b>cmdXRechnungEinlesen <\/b>ermittelt &uuml;ber einen Dateiauswahl-Dialog zun&auml;chst die einzulesende Datei. Dann startet sie den Einlesevorgang &uuml;ber die Funktion <b>XRechnungEinlesen<\/b>. Diese liefert den Prim&auml;rschl&uuml;sselwert des neu angelegten Datensatzes in der Tabelle <b>tblRechnungen<\/b> zur&uuml;ck, sodass dieser dann nach einer Aktualisierung im Formular angezeigt werden kann:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdXRechnungEinlesen_Click()\r\n     <span style=\"color:blue;\">Dim <\/span>strPfad<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngRechnungID<span style=\"color:blue;\"> As Long<\/span>\r\n     strPfad = OpenFileName(CurrentProject.Path, _\r\n         \"XRechnung ausw&auml;hlen\", \"XRechnung (*.xml)\")\r\n     lngRechnungID = XRechnungEinlesen(strPfad)\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> lngRechnungID = 0<span style=\"color:blue;\"> Then<\/span>\r\n         Me.Requery\r\n         Me.Recordset.FindFirst _\r\n             \"RechnungID = \" & lngRechnungID\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Zusammenfassung und Ausblick<\/h2>\n<p>In diesem zweiten Teil haben wir gezeigt, wie wir die wichtigsten Daten aus XRechnungen einlesen k&ouml;nnen. In einem weiteren Teil erstellen wir eine f&uuml;r Nutzer einfacher lesbare Version der Rechnung in Form eines Berichts.<\/p>\n<h2>Downloads zu diesem Beitrag<\/h2>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>XRechnung.accdb<\/p>\n<p>XRechnung.xml<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/0DECF8DF-372A-4C60-AEC2-ACD56B6F510B\/aiu_1395.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Nachdem wir im ersten Teil dieser Beitragsreihe gezeigt haben, wie Sie aus Daten wie Kundeninformationen, Rechnungsdatum und Rechnungspositionen ein XML-Dokument im XRechnung-Format erstellen, wollen wir in diesem Beitrag den umgekehrten Weg gehen: Wir wollen die Daten aus einer so generierten Rechnung auslesen und zur&uuml;ck in das Datenmodell schreiben. Dazu sind vor allem F&auml;higkeiten im Auslesen von XML-Dokumenten erforderlich &#8211; und der Umgang mit Namespace-Deklarationen in diesen Dokumenten. Nach der Lekt&uuml;re dieses Beitrags sind Sie in der Lage, die Daten aus einer XRechnung automatisiert in ein entsprechendes Datenmodell einzulesen.<\/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":[662022,66052022,44000027],"tags":[],"class_list":["post-55001395","post","type-post","status-publish","format-standard","hentry","category-662022","category-66052022","category-Loesungen"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.4) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>XRechnung, Teil 2: Rechnungen einlesen - 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\/XRechnung_Teil_2_Rechnungen_einlesen\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"XRechnung, Teil 2: Rechnungen einlesen\" \/>\n<meta property=\"og:description\" content=\"Nachdem wir im ersten Teil dieser Beitragsreihe gezeigt haben, wie Sie aus Daten wie Kundeninformationen, Rechnungsdatum und Rechnungspositionen ein XML-Dokument im XRechnung-Format erstellen, wollen wir in diesem Beitrag den umgekehrten Weg gehen: Wir wollen die Daten aus einer so generierten Rechnung auslesen und zur&uuml;ck in das Datenmodell schreiben. Dazu sind vor allem F&auml;higkeiten im Auslesen von XML-Dokumenten erforderlich - und der Umgang mit Namespace-Deklarationen in diesen Dokumenten. Nach der Lekt&uuml;re dieses Beitrags sind Sie in der Lage, die Daten aus einer XRechnung automatisiert in ein entsprechendes Datenmodell einzulesen.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/XRechnung_Teil_2_Rechnungen_einlesen\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2022-10-03T14:37:11+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=\"25\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/XRechnung_Teil_2_Rechnungen_einlesen\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/XRechnung_Teil_2_Rechnungen_einlesen\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"XRechnung, Teil 2: Rechnungen einlesen\",\"datePublished\":\"2022-10-03T14:37:11+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/XRechnung_Teil_2_Rechnungen_einlesen\\\/\"},\"wordCount\":3501,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"articleSection\":[\"2022\",\"5\\\/2022\",\"L\u00f6sungen\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/XRechnung_Teil_2_Rechnungen_einlesen\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/XRechnung_Teil_2_Rechnungen_einlesen\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/XRechnung_Teil_2_Rechnungen_einlesen\\\/\",\"name\":\"XRechnung, Teil 2: Rechnungen einlesen - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"datePublished\":\"2022-10-03T14:37:11+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/XRechnung_Teil_2_Rechnungen_einlesen\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/XRechnung_Teil_2_Rechnungen_einlesen\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/XRechnung_Teil_2_Rechnungen_einlesen\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"XRechnung, Teil 2: Rechnungen einlesen\"}]},{\"@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":"XRechnung, Teil 2: Rechnungen einlesen - 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\/XRechnung_Teil_2_Rechnungen_einlesen\/","og_locale":"de_DE","og_type":"article","og_title":"XRechnung, Teil 2: Rechnungen einlesen","og_description":"Nachdem wir im ersten Teil dieser Beitragsreihe gezeigt haben, wie Sie aus Daten wie Kundeninformationen, Rechnungsdatum und Rechnungspositionen ein XML-Dokument im XRechnung-Format erstellen, wollen wir in diesem Beitrag den umgekehrten Weg gehen: Wir wollen die Daten aus einer so generierten Rechnung auslesen und zur&uuml;ck in das Datenmodell schreiben. Dazu sind vor allem F&auml;higkeiten im Auslesen von XML-Dokumenten erforderlich - und der Umgang mit Namespace-Deklarationen in diesen Dokumenten. Nach der Lekt&uuml;re dieses Beitrags sind Sie in der Lage, die Daten aus einer XRechnung automatisiert in ein entsprechendes Datenmodell einzulesen.","og_url":"https:\/\/access-im-unternehmen.de\/XRechnung_Teil_2_Rechnungen_einlesen\/","og_site_name":"Access im Unternehmen","article_published_time":"2022-10-03T14:37:11+00:00","author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"25\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/XRechnung_Teil_2_Rechnungen_einlesen\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/XRechnung_Teil_2_Rechnungen_einlesen\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"XRechnung, Teil 2: Rechnungen einlesen","datePublished":"2022-10-03T14:37:11+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/XRechnung_Teil_2_Rechnungen_einlesen\/"},"wordCount":3501,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"articleSection":["2022","5\/2022","L\u00f6sungen"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/XRechnung_Teil_2_Rechnungen_einlesen\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/XRechnung_Teil_2_Rechnungen_einlesen\/","url":"https:\/\/access-im-unternehmen.de\/XRechnung_Teil_2_Rechnungen_einlesen\/","name":"XRechnung, Teil 2: Rechnungen einlesen - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"datePublished":"2022-10-03T14:37:11+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/XRechnung_Teil_2_Rechnungen_einlesen\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/XRechnung_Teil_2_Rechnungen_einlesen\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/XRechnung_Teil_2_Rechnungen_einlesen\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"XRechnung, Teil 2: Rechnungen einlesen"}]},{"@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\/55001395","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=55001395"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001395\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55001395"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55001395"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55001395"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}