{"id":55000276,"date":"2021-10-01T00:00:00","date_gmt":"2022-02-15T13:16:51","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=276"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Seminarverwaltung_III_Daten_vom_Shopsystem","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/Seminarverwaltung_III_Daten_vom_Shopsystem\/","title":{"rendered":"Seminarverwaltung III: Daten vom Shopsystem"},"content":{"rendered":"<p><b>Unsere Seminarverwaltung lebt unter anderen davon, dass Bestellungen &uuml;ber ein Shopsystem eingehen. Hier nutzen wir elopage, einen Anbieter, mit dem man verschiedene digitale Dienstleistungen online verkaufen kann. elopage &uuml;bernimmt dabei einige Aufgaben wie etwa die Bereitstellung von Produkt- und Bestellseiten. Nachdem eine Bestellung erfolgt ist, landen die Daten des Kunden inklusive der Daten zum bestellten Artikel in der Datenbank von elopage. Die Bestelldaten k&ouml;nnen wir per CSV-Datei exportieren und in unsere Seminarverwaltung einlesen. Dazu verwenden wir das NuGet-Paket CsvHelper, das wir in zwei weiteren Artikeln bereits vorgestellt haben. Der vorliegende Artikel zeigt, wie wir die beschriebenen Techniken f&uuml;r den Import in einem konkreten Anwendungsfall nutzen k&ouml;nnen.<\/b><\/p>\n<h2>Schritt f&uuml;r Schritt<\/h2>\n<p>Wir wollen den Import der CSV-Datei in die einzelnen Tabellen der Anwendung in mehreren Schritten vollziehen:<\/p>\n<ul>\n<li>Als Erstes wollen wir die Daten aus der CSV-Datei in einer einzigen Klasse verf&uuml;gbar machen, damit wir komfortabler auf die enthaltenen Daten zugreifen k&ouml;nnen. Dazu erstellen wir eine Klasse, die f&uuml;r jede Spalte der CSV-Datei ein Feld enth&auml;lt. Das wird hier und da etwas aufwendiger, wie wir glelich sehen werden.<\/li>\n<li>Die einzelnen Objekte mit den Daten aus jeweils einer Zeile f&uuml;gen wir zu einer Auflistung hinzu.<\/li>\n<li>Danach durchlaufen wir die Auflistung mit allen Datens&auml;tzen und lesen daraus die Informationen aus, die wir den einzelnen Entit&auml;ten unseres Entity Data Models zuweisen wollen. Diese legen wir dann an und speichern die enthaltenen Daten in der zugrunde liegenden Datenbank.<\/li>\n<\/ul>\n<h2>Herausfordernde CSV-Datei<\/h2>\n<p>Die von elopage exportierte Datei liefert uns einige Herausforderungen. Sie sieht wie in Bild 1 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2021_05\/pic_276_005.png\" alt=\"Der CSV-Export des Shopsystems\" width=\"700\" height=\"293,2527\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Der CSV-Export des Shopsystems<\/span><\/b><\/p>\n<p>Die Herausforderung ist, dass wir die Felder m&ouml;glichst so wie in der Kopfzeile dargestellt in Objekten einer neuen Klasse namens <b>ImportBestellung <\/b>abbilden wollen &#8211; um m&ouml;glichst ein 1:1-Mapping zu realisieren:<\/p>\n<pre>TOKEN;PRODUKT;ERSTELLT;ZAHLUNGSSTATUS;METHODE;PLAN;TESTZEITRAUM;ANZAHL ZAHLUNGEN;BEZAHLT;PRODUCT ID;FUER PS;FAELLIGER BETRAG;WAEHRUNG;UNTERNEHMEN;PLAN;ZAHLUNGSPLAN;ZAHLUNGSPLAN ID;GUTSCHEINCODE;CAMPAIGN-ID;MIT TESTZEITRAUM;FIXER FAELLIGKEITSTAG;PRODUKTNAME;EVENT;ORT;EVENT-DATUM;TICKETANZAHL;TICKET CODE;VORNAME;NACHNAME;E-MAIL;TELEFON;LAND;STADT;STRASSE;HAUSNUMMER;PLZ;UNTERNEHMEN;UST-IDNR.;EMPFAENGER NAME;EMPFAENGER E-MAIL-ADRESSE;EMPFAENGER TELEFON;EMPFAENGER LAND;EMPFAENGER STADT;EMPFAENGER STRASSE;EMPFAENGER HAUSNUMMER;EMPFAENGER PLZ;EMPFAENGER FIRMA;NUTZER;PUBLISHER ID;AELTESTE BEZAHLTE RATE;FAELLIGKEITSDATUM;BESTELL-ID;\"\";\"\";\"\";\"\";\"\";\"\";\"\";\"\";\"\";\"\";\"\";\"\";\"\";\"\";\"\";\"\";\"\";\"\";\"\"<\/pre>\n<p>Sie sehen hier aber direkt einige Elemente mit Namen, die so nicht als Eigenschaften einer .NET-Klasse verwendet werden k&ouml;nnen. Einige der Spalten&uuml;berschriften enthalten Leerzeichen (zum Beispiel <b>PRODUCT ID <\/b>oder <b>FAELLIGER BETRAG<\/b>), andere entsprechen reservierten Begriffen (<b>EVENT<\/b>), wieder andere kommen doppelt vor (<b>UNTERNEHMEN<\/b>). Zum Gl&uuml;ck bietet das <b>CsvHelper<\/b>-Paket M&ouml;glichkeiten, solche Felder &uuml;ber entsprechende Data Annotations zuzuordnen.<\/p>\n<p>Wir  haben im Folgenden die Klasse <b>ImportBestellung<\/b> ausschnittsweise abgebildet und vor allem die Spezialf&auml;lle aufgef&uuml;hrt. Die Klasse verwendet einige zus&auml;tzliche Namespaces:<\/p>\n<pre>Imports CsvHelper\r\nImports CsvHelper.Configuration\r\nImports CsvHelper.Configuration.Attributes<\/pre>\n<p>Die Klasse selbst sieht wie folgt aus:<\/p>\n<pre><span style=\"color:blue;\">Public Class<\/span> ImportBestellung\r\n     <span style=\"color:blue;\">Public <\/span>Property TOKEN<span style=\"color:blue;\"> As String<\/span>\r\n     ...\r\n     &lt;Name(\"PLAN\")&gt;\r\n     &lt;NameIndex(0)&gt;\r\n     <span style=\"color:blue;\">Public <\/span>Property PLAN1<span style=\"color:blue;\"> As String<\/span> ''Kommt zwei Mal vor\r\n     <span style=\"color:blue;\">Public <\/span>Property TESTZEITRAUM<span style=\"color:blue;\"> As String<\/span>\r\n     &lt;Name(\"ANZAHL ZAHLUNGEN\")&gt;\r\n     <span style=\"color:blue;\">Public <\/span>Property ANZAHLZAHLUNGEN<span style=\"color:blue;\"> As String<\/span> ''Enth&auml;lt Leerzeichen\r\n     &lt;Name(\"PRODUCT ID\")&gt;\r\n     <span style=\"color:blue;\">Public <\/span>Property PRODUCT_ID<span style=\"color:blue;\"> As String<\/span> ''Enth&auml;lt Leerzeichen\r\n     &lt;Name(\"FUER PS\")&gt;\r\n     ...\r\n     &lt;Name(\"UNTERNEHMEN\")&gt;\r\n     &lt;NameIndex(0)&gt;\r\n     <span style=\"color:blue;\">Public <\/span>Property UNTERNEHMEN<span style=\"color:blue;\"> As String<\/span> ''Kommt zwei Mal vor.\r\n     &lt;Name(\"PLAN\")&gt;\r\n     &lt;NameIndex(1)&gt;\r\n     <span style=\"color:blue;\">Public <\/span>Property PLAN2<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Public <\/span>Property ZAHLUNGSPLAN<span style=\"color:blue;\"> As String<\/span>\r\n     &lt;Name(\"EVENT\")&gt;\r\n     <span style=\"color:blue;\">Public <\/span>Property Event1<span style=\"color:blue;\"> As String<\/span> ''Event ist ein reserviertes Schl&uuml;sselwort\r\n     &lt;Name(\"EVENT-DATUM\")&gt;\r\n     <span style=\"color:blue;\">Public <\/span>Property Event_DATUM<span style=\"color:blue;\"> As String<\/span> ''Enth&auml;lt Leerzeichen\r\n     &lt;Name(\"UNTERNEHMEN\")&gt;\r\n     &lt;NameIndex(1)&gt;\r\n     <span style=\"color:blue;\">Public <\/span>Property UNTERNEHMEN_1<span style=\"color:blue;\"> As String<\/span> ''Zweites Vorkommen\r\n     &lt;Name(\"UST-IDNR.\")&gt;\r\n     ...\r\n<span style=\"color:blue;\">End Class<\/span><\/pre>\n<p>Die vollst&auml;ndige Klasse finden Sie im Beispielprojekt zu diesem Artikel.<\/p>\n<h2>Importieren der CSV-Datei<\/h2>\n<p>Das Importieren der CSV-Datei wollen wir m&ouml;glichst komfortabel gestalten, deshalb speichern wir das zuletzt verwendeten Verzeichnis in einer Option der Anwendung und rufen dieses beim n&auml;chsten Anzeigen des Dateiauswahl-Dialogs wieder ab.<\/p>\n<p>F&uuml;r das Importieren haben wir dem Ribbon eine Schaltlfl&auml;che namens <b>btnImportieren <\/b>hinzugef&uuml;gt. Diese l&ouml;st die folgende Ereignismethode aus:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>btnImportieren_Click(sender<span style=\"color:blue;\"> As Object<\/span>, e<span style=\"color:blue;\"> As <\/span>RoutedEventArgs)\r\n     <span style=\"color:blue;\">Dim <\/span>strDateiname<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>objImportBestellungen<span style=\"color:blue;\"> As <\/span>List(Of ImportBestellung)\r\n     strDateiname = DateinameErmitteln()\r\n     objImportBestellungen = CSVImport(strDateiname)\r\n     CSVImportVerarbeiten(objImportBestellungen)\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Hier rufen wir zuerst die Funktion <b>DateinameErmitteln <\/b>auf. Diese liest mit der Funktion <b>VerzeichnisLesen <\/b>das zuletzt verwendete Verzeichnis in die Variable <b>strImportverzeichnis <\/b>ein. Ist dieses leer, verwendet die Methode das Verzeichnis der <b>.exe<\/b>-Datei der Anwendung als Startverzeichnis f&uuml;r die Eigenschaft <b>InitialDirectory<\/b>. Anderenfalls kommt das Verzeichnis aus <b>strImportverzeichnis<\/b> zum Einsatz:<\/p>\n<pre><span style=\"color:blue;\">Private Function <\/span>DateinameErmitteln()<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strImportpfad<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strImportverzeichnis<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>objOpenFileDialog<span style=\"color:blue;\"> As <\/span><span style=\"color:blue;\">New<\/span> OpenFileDialog\r\n     strImportverzeichnis = VerzeichnisLesen()\r\n     <span style=\"color:blue;\">If <\/span>strImportverzeichnis.Length = 0<span style=\"color:blue;\"> Then<\/span>\r\n         objOpenFileDialog.InitialDirectory = AppDomain.CurrentDomain.BaseDirectory\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         objOpenFileDialog.InitialDirectory = strImportverzeichnis\r\n     <span style=\"color:blue;\">End If<\/span><\/pre>\n<p>Dann stellt die Methode <b>.csv <\/b>als Dateiendung f&uuml;r den <b>Datei &ouml;ffnen<\/b>-Dialog ein. Die Methode <b>ShowDialog <\/b>zeigt den Dialog an. Wird dieser unter Angabe eines Dateinamens geschlossen, weist die Methode diesen der Variablen <b>strImportpfad <\/b>zu. Schlie&szlig;lich sorgt die Methode <b>VerzeichnisAktualisieren <\/b>noch daf&uuml;r, dass das gew&auml;hlte Verzeichnis in die Optionen der Anwendung geschrieben wird:<\/p>\n<pre>     objOpenFileDialog.DefaultExt = \".csv\"\r\n     <span style=\"color:blue;\">If <\/span>(objOpenFileDialog.ShowDialog = <span style=\"color:blue;\">True<\/span>)<span style=\"color:blue;\"> Then<\/span>\r\n         strImportpfad = objOpenFileDialog.FileName\r\n         VerzeichnisAktualisieren(strImportpfad)\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     Return strImportpfad\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<h2>Speichern des Importverzeichnisses<\/h2>\n<div class=\"rcp_restricted\"><p><span style=\"color: #ff0000;\">M&ouml;chten Sie weiterlesen? Dann l&ouml;sen Sie Ihr Ticket!<\/span><br \/>\n<span style=\"color: #ff0000;\">Hier geht es zur Bestellung des Jahresabonnements des Magazins <strong>Visual Basic Entwickler<\/strong>:<\/span><br \/>\n<span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/shop.minhorst.com\/magazine\/363\/visual-basic-entwickler-jahresabonnement?c=77\">Zur Bestellung ...<\/a><\/span><br \/>\n<span style=\"color: #ff0000;\">Danach greifen Sie sofort auf <strong>alle rund 200 Artikel<\/strong> unseres Angebots zu - auch auf diesen hier!<\/span><br \/>\n<span style=\"color: #000000;\">Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:<\/span><\/p>\n<\/div>\n\n\t\n\t<form id=\"rcp_login_form\"  class=\"rcp_form\" method=\"POST\" action=\"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000276\/\">\n\n\t\t\n\t\t<fieldset class=\"rcp_login_data\">\n\t\t\t<p>\n\t\t\t\t<label for=\"rcp_user_login\">Username or Email<\/label>\n\t\t\t\t<input name=\"rcp_user_login\" id=\"rcp_user_login\" class=\"required\" type=\"text\"\/>\n\t\t\t<\/p>\n\t\t\t<p>\n\t\t\t\t<label for=\"rcp_user_pass\">Password<\/label>\n\t\t\t\t<input name=\"rcp_user_pass\" id=\"rcp_user_pass\" class=\"required\" type=\"password\"\/>\n\t\t\t<\/p>\n\t\t\t\t\t\t<p>\n\t\t\t\t<input type=\"checkbox\" name=\"rcp_user_remember\" id=\"rcp_user_remember\" value=\"1\"\/>\n\t\t\t\t<label for=\"rcp_user_remember\">Remember me<\/label>\n\t\t\t<\/p>\n\t\t\t<p class=\"rcp_lost_password\"><a href=\"\/data\/wp\/v2\/posts\/55000276?rcp_action=lostpassword\"><\/a><\/p>\n\t\t\t<p>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_action\" value=\"login\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_redirect\" value=\"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000276\/\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_login_nonce\" value=\"58f932c395\"\/>\n\t\t\t\t<input id=\"rcp_login_submit\" class=\"rcp-button\" type=\"submit\" value=\"Login\"\/>\n\t\t\t<\/p>\n\t\t\t\t\t<\/fieldset>\n\n\t\t\n\t<\/form>\n<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Unsere Seminarverwaltung lebt unter anderen davon, dass Bestellungen &uuml;ber ein Shopsystem eingehen. Hier nutzen wir elopage, einen Anbieter, mit dem man verschiedene digitale Dienstleistungen online verkaufen kann. elopage &uuml;bernimmt dabei einige Aufgaben wie etwa die Bereitstellung von Produkt- und Bestellseiten. Nachdem eine Bestellung erfolgt ist, landen die Daten des Kunden inklusive der Daten zum bestellten Artikel in der Datenbank von elopage. Die Bestelldaten k&ouml;nnen wir per CSV-Datei exportieren und in unsere Seminarverwaltung einlesen. Dazu verwenden wir das NuGet-Paket CsvHelper, das wir in zwei weiteren Artikeln bereits vorgestellt haben. Der vorliegende Artikel zeigt, wie wir die beschriebenen Techniken f&uuml;r den Import in einem konkreten Anwendungsfall nutzen k&ouml;nnen.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[662021,66052021,44000021,44000004,44000038],"tags":[],"yst_prominent_words":[],"class_list":["post-55000276","post","type-post","status-publish","format-standard","hentry","category-662021","category-66052021","category-Entity_Framework","category-Loesungen","category-Office_programmieren"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000276","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/comments?post=55000276"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000276\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000276"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000276"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000276"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000276"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}