{"id":55001215,"date":"2019-12-01T00:00:00","date_gmt":"2020-07-10T09:50:33","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=1215"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Von_Access_nach_Wordpress","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Von_Access_nach_Wordpress\/","title":{"rendered":"Von Access nach WordPress"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg09.met.vgwort.de\/na\/02af00feb9b943fe8648a068edd71520\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>WordPress ist das g&auml;ngigste System f&uuml;r die Erstellung und Pflege eines Blogs. Mittlerweile gibt es so viele Erweiterungen, dass ein Blog nur noch eine von vielen M&ouml;glichkeiten ist, eine Webseite &uuml;ber die WordPress-Plattform zu bauen. Da f&uuml;r Access im Unternehmen der Umzug auf ein moderneres System anstand, haben wir uns f&uuml;r WordPress entschieden. Es bietet gleichzeitig viele M&ouml;glichkeiten und ist dennoch recht einfach zu bedienen. Das gilt allerdings auch nur, wenn Sie keine besonderen Anforderungen haben &#8211; was in unserem Fall anders aussieht: Immerhin sollen mehr als 1.000 Beitr&auml;ge samt Bildern und Downloads &uuml;bertragen werden. Und es darf auch nicht jeder alle Beitr&auml;ge vollst&auml;ndig betrachten, sondern nur &uuml;ber eine Benutzerverwaltung erfasste Abonnenten. Wie wir das realisiert haben, zeigen wir in diesem Beitrag.<\/b><\/p>\n<p><b>Aus Alt mach Neu<\/b><\/p>\n<p>Am Anfang stand die Erkenntnis, dass das im Jahre 2003 aufgesetzte Typo3-System zwar noch klaglos seinen Dienst tut, aber leider nicht der Server, auf dem das Content-Management-System l&auml;uft. Bei einem 16 Jahre alten Ger&auml;t muss man sich freuen, dass es &uuml;berhaupt noch l&auml;uft. Leider wurden keine regelm&auml;&szlig;igen Updates gemacht, sodass es nur mit erheblichem Aufwand m&ouml;glich gewesen w&auml;re, das System nochmal auf eine aktuellere Version zu &uuml;bertragen. Also musste ein neues System her, und zwar WordPress.<\/p>\n<p><b>Zwei WordPress-Varianten<\/b><\/p>\n<p>Es gibt zwei WordPress-Varianten: <b>WordPress.com <\/b>bietet die Software inklusive Hosting an. Sie melden dort eine neue WordPress-Seite an und bekommen die komplette Infrastruktur gestellt. Daf&uuml;r gibt es allerdings auch Einschr&auml;nkungen: Sie k&ouml;nnen nicht nach Lust und Laune auf Datenbank, Dateien und sonstige Elemente zugreifen, was unseren Spieltrieb und auch die Flexibilit&auml;t erheblich einschr&auml;nkte. <\/p>\n<p>Die zweite WordPress-Variante findet sich auf <b>WordPress.org <\/b>zum Download und kann auf Ihrem eigenen oder gemieteten Webserver installiert werden. Einige Anbieter bieten auch Pakete an, auf denen alle Voraussetzungen f&uuml;r den Einsatz von WordPress vorliegen. Hier k&ouml;nnen Sie je nach den durch den Hoster angebotenen M&ouml;glichkeiten auf alle notwendigen Bereiche zugreifen, also auf die Datenbank, das Dateisystem und mehr. Diese Variante haben wir gew&auml;hlt. Als Hoster nutzen wir <b>aixpro.de<\/b>.<\/p>\n<p><b>Voraussetzungen<\/b><\/p>\n<p>Schon unter Verwendung des in die Jahre gekommen Typo3-Systems sah der Workflow f&uuml;r die Ver&ouml;ffentlichung der Beitr&auml;ge wie folgt aus: Die Beitr&auml;ge wurden in InDesign geschrieben und gesetzt.<\/p>\n<p>Von dort haben wir die PDFs f&uuml;r den Drucker erstellt und auch die f&uuml;r den Downloadbereich f&uuml;r registrierte Abonnenten. Au&szlig;erdem haben wir daraus per VBA eine HTML-Version erstellt, die wir in einer Access-Datenbank gespeichert haben.<\/p>\n<p>Es gibt eine Tabelle f&uuml;r die Beitr&auml;ge namens <b>tblBeitraege<\/b>, eine Tabelle f&uuml;r die Kategorien (<b>tblKategorien<\/b>) sowie eine Verkn&uuml;pfungstabelle, damit wir den Kategorien die Beitr&auml;ge zuweisen konnten (<b>tblBeitraegeKategorien<\/b>). Dies sind die wesentlichen Tabellen, die wir f&uuml;r die &Uuml;bertragung der Inhalte in das WordPress-System ben&ouml;tigen. In der Beispieldatenbank haben wir diese Tabellen mit ein paar Beispielartikeln im HTML-Format untergebracht.<\/p>\n<p>Wichtig ist noch zu wissen, dass die HTML-Version mit Verweisen auf Bilder versehen sind, die sich in einem speziellen Unterverzeichnis befinden. Dieses kann man also so, wie es ist, auf den Webserver legen.<\/p>\n<p>Und auch die Beispieldatenbanken und sonstige Downloaddateien liegen in einer bestimmten Verzeichnisstruktur vor, die man problemlos so auf den Server &uuml;bertragen kann. Hier sind nur die Verlinkungen in den Beitr&auml;gen noch anzupassen.<\/p>\n<p>Eine weitere Voraussetzung ist nat&uuml;rlich das Vorhandensein einer WordPress-Installation, auf deren SQL-Datenbank Sie auf irgendeinen Weg Zugriff haben &#8211; mehr dazu weiter unten.<\/p>\n<p><b>Ins HTML-Format<\/b><\/p>\n<p>Wenn Sie Beitr&auml;ge aus einer Datenbank in eine WordPress-Anwendung &uuml;bertragen wollen, ist es sinnvoll, wenn diese Daten bereits im HTML-Format in der Tabelle <b>tblBeitraege <\/b>gespeichert sind. Aber woher &uuml;berhaupt kommen die Beitr&auml;ge, die Sie mit der Datenbank verwalten und nach WordPress &uuml;berf&uuml;hren wollen In meinem Fall kommen diese, wie oben beschrieben, aus InDesign. InDesign bietet die M&ouml;glichkeit, Dateien in das HTML-Format zu exportieren. Das Ergebnis dieses Exports war jedoch f&uuml;r meine Zwecke nicht passend, sodass ich den Export selbst programmiert habe.<\/p>\n<p>Da vermutlich nicht viele Entwickler mit InDesign arbeiten werden, hier nur eine kurze Zusammenfassung: InDesign bietet eine VBA-Bibliothek f&uuml;r den VBA-gesteuerten Zugriff auf das Objektmodell. Auf dieser Basis habe ich einen Satz von Routinen geschrieben, die das InDesign-Dokument Absatz f&uuml;r Absatz durchlaufen und pr&uuml;fen, welches Absatzformat vorliegt, und einen entsprechenden HTML-Absatz daraus erstellen. Aus einem Absatz mit dem Absatzformat Fliesstext wird dann etwa ein Text, der von den entsprechenden HTML-Tags eingefasst wird, beispielsweise <b><\/p>\n<p>&#8230;<\/p>\n<p><\/b>.<\/p>\n<p>Die Programmierung geht jedoch &uuml;ber diese recht einfache Vorgehensweise hinaus, denn die Texte enthalten auch Verweise auf Bilder oder Listings in K&auml;sten. Diese werden von den Routinen identifiziert und entsprechend behandelt. Bei einem Bild, das im InDesign-Satz unabh&auml;ngig vom Flie&szlig;text in einem Kasten an beliebiger Stelle im Dokument platziert ist, landet etwa das <b><img ... \/><\/b>-Element direkt hinter dem <b><\/p>\n<p>&#8230;<\/p>\n<p><\/b>-Absatz, der im Originaldokument auf das Bild verweist.<\/p>\n<p>Gleiches gilt f&uuml;r K&auml;sten mit Listings. Die Bilder im InDesign-Dokument werden &auml;hnlich wie in Word &uuml;ber Verkn&uuml;pfungen angezeigt. Diese Verkn&uuml;pfungen k&ouml;nnen wir auch &uuml;ber VBA auslesen und so den Pfad der angezeigten Bilder ermitteln.<\/p>\n<p>Die Bilder aus dem Originaldokument kopiere ich dann ebenfalls per VBA in ein Verzeichnis, das alle Bilddateien f&uuml;r das entsprechende Dokument enth&auml;lt.<\/p>\n<p>Damit erhalte ich also f&uuml;r jeden Artikel einen Datensatz in der Tabelle <b>tblBeitrage<\/b>, der den Titel des Artikels in einem Feld enth&auml;lt, au&szlig;erdem die Ausgabe, das Erscheinungsjahr und den HTML-Code in einem Memofeld.<\/p>\n<p>Die Kategorie des Artikels f&uuml;ge ich dann selbst &uuml;ber die Benutzeroberfl&auml;che hinzu. Und auch die Ausgabe und das Erscheinungsjahr w&auml;hle ich im Formular f&uuml;r die importierten Artikel aus. Damit ergibt sich dann das Datenmodell aus Bild 1.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_06\/pic_1215_001.png\" alt=\"Datenmodell der Access-Anwendung\" width=\"549,6265\" height=\"436,3016\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Datenmodell der Access-Anwendung<\/span><\/b><\/p>\n<p><b>Formular zur Anzeige der Beitr&auml;ge<\/b><\/p>\n<p>Um die Prozeduren zum Erstellen der WordPress-Daten aufrufen zu k&ouml;nnen, erstellen wir uns noch ein Formular namens <b>frmBeitraege<\/b>, mit dem wir die einzelnen Datens&auml;tze der Tabelle <b>tblBeitraege <\/b>anzeigen (siehe Bild 2). Aus dieser Tabelle zeigen wir dabei die Werte der Felder <b>BeitragID<\/b>, <b>Titel<\/b>, <b>Jahr<\/b>, <b>Ausgabe<\/b>, <b>Kurztext<\/b> und <b>Inhalt <\/b>an.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_06\/pic_1215_002.png\" alt=\"Formular mit den Beitr&auml;gen und den Schaltfl&auml;chen zum &Uuml;bertragen nach WordPress\" width=\"599,593\" height=\"494,1164\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Formular mit den Beitr&auml;gen und den Schaltfl&auml;chen zum &Uuml;bertragen nach WordPress<\/span><\/b><\/p>\n<p>Au&szlig;erdem liefert ein Unterformular namens <b>sfmKategorien <\/b>die Daten der Verkn&uuml;pfungstabelle <b>tblBeitraegeKategorien<\/b>, genau genommen die des Feldes <b>KategorieID<\/b>. Damit k&ouml;nnen wir die zugeordneten Kategorien ausw&auml;hlen.<\/p>\n<p>Unten im Formular legen wir zwei Schaltfl&auml;chen an. Die erste hei&szlig;t <b>cmdBeitragNachWordpress<\/b>. Sie soll den aktuell angezeigten Beitrag behandeln. Die zweite namens <b>cmdAlleNachWordpress <\/b>soll sich um alle Beitr&auml;ge k&uuml;mmern, die sich in der Tabelle <b>tblBeitraege <\/b>befinden.<\/p>\n<p>Was aber hei&szlig;t &#8222;behandeln&#8220; oder &#8222;k&uuml;mmern&#8220; in diesem Fall Das m&uuml;ssen wir noch kl&auml;ren.<\/p>\n<p><b>&Uuml;bertragen der Artikel nach WordPress<\/b><\/p>\n<p>Es gibt verschiedene M&ouml;glichkeiten, wie wir die HTML-Artikel nach WordPress &uuml;bertragen. WordPress hat logischerweise ebenfalls eine Datenbank, welche die enthaltenen Artikel und weitere Daten speichert. Theoretisch k&ouml;nnten wir die Tabellen dieser meist unter MySQL verwalteten Datenbank in unsere Access-Datenbank einbinden und so direkt auf diese Tabellen zugreifen. Aus Sicherheitsgr&uuml;nden bieten die meisten Provider dies jedoch nicht an.<\/p>\n<p>Das &Uuml;bertragen von Daten aus den Tabellen einer lokalen Tabelle in die verkn&uuml;pften Tabellen einer Datenbank auf einem Webserver ist aber auch nicht besonders herausfordernd.<\/p>\n<p>Also gehen wir direkt den alternativen Weg, der von den meisten Providern angeboten werden sollte: die M&ouml;glichkeit, SQL-Skripte auszuf&uuml;hren. Das k&ouml;nnen Sie, wenn Sie kompletten Zugriff auf den Server etwa &uuml;ber eine Konsole haben, erledigen, indem Sie die Datei mit den entsprechenden SQL-Anweisungen auf den Server kopieren und diese dort in der Konsole aufrufen.<\/p>\n<p>Unser Provider <b>Aixpro <\/b>stellt uns eine komfortable Benutzeroberfl&auml;che f&uuml;r die Verwaltung unserer Webseiten zur Verf&uuml;gung stellt.<\/p>\n<p>Die Benutzeroberfl&auml;che hei&szlig;t <b>Plesk <\/b>und bietet die M&ouml;glichkeit, die Webseiten zu administrieren, Dateien zu verwalten und ein Tool f&uuml;r den Zugriff auf die SQL-Datenbanken zu &ouml;ffnen, n&auml;mlich <b>phpMyAdmin<\/b>.<\/p>\n<p>Diese Tools sind wirklich sehr hilfreich, wenn es um die Verwaltung von Webanwendungen geht. phpMyAdmin bietet die M&ouml;glichkeit, SQL-Skripte als Datei hochzuladen und diese direkt in der aktuell angezeigten Datenbank auszuf&uuml;hren.<\/p>\n<p>Unser Ziel ist es also auf jeden Fall, eine Datei mit den auszuf&uuml;hrenden SQL-Anweisungen zu erstellen, die wir dann auf dem Webserver laden und dort ausf&uuml;hren k&ouml;nnen. Dies ist dann auch der kleinste gemeinsame Nenner f&uuml;r die verschiedenen Konfigurationsm&ouml;glichkeiten f&uuml;r eine WordPress-Installation.<\/p>\n<p><b>Die relevanten Tabellen von WordPress<\/b><\/p>\n<p>WordPress hat in der Basisinstallation, also ohne zus&auml;tzliche Plugins, ein recht &uuml;berschaubares Datenmodell. Die f&uuml;r uns interessanten Tabellen befinden sich auf der &Uuml;bersicht des Datenmodells, die wir der Webseite <b>https:\/\/codex.wordpress.org <\/b>entnommen haben, im markierten Bereich (siehe Bild 3).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_06\/pic_1215_004.png\" alt=\"Datenmodell von WordPress\" width=\"649,559\" height=\"915,7715\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Datenmodell von WordPress<\/span><\/b><\/p>\n<p>Die Tabelle <b>wp_posts <\/b>enth&auml;lt die einzelnen Artikel. Das Feld <b>postTitle <\/b>nimmt dabei den Titel auf, das Feld <b>post_content <\/b>(im Screenshot <b>post_content_filtered <\/b>benannt) nimmt den Artikel selbst auf. Die Kategorien k&ouml;nnen wir in der Tabelle <b>wp_Terms <\/b>hinterlegen. Die Tabelle <b>wp_term_taxonomy <\/b>weist den Kategorien aus <b>wp_terms <\/b>eine Funktion zu, n&auml;mlich Kategorie, Link oder Tag, und definiert die Hierarchie der Eintr&auml;ge der Tabelle <b>wp_Terms <\/b>&#8211; das ist f&uuml;r die Erschaffung einer Kategorien-Hierarchie wichtig.<\/p>\n<p>Die Hierarchie wird &uuml;ber das Feld <b>parent <\/b>erzeugt, das auf das Prim&auml;rschl&uuml;sselfeld <b>term_taxonomy_id <\/b>der gleichen Tabelle verweist. Die Tabelle <b>wp_term_relationsships <\/b>verkn&uuml;pft wiederum die Eintr&auml;ge der Tabelle <b>wp_term_taxonomy <\/b>und die Artikel aus der Tabelle <b>wp_posts <\/b>miteinander. F&uuml;r uns ist diese Tabelle also wichtig, weil wir &uuml;ber diese die Artikel den Kategorien zuweisen k&ouml;nnen, die wir in der Tabelle <b>wp_terms <\/b>definiert haben.<\/p>\n<p><b>Zu beachten<\/b><\/p>\n<p>Bevor wir die Daten einfach von Access in die WordPress-Tabellen &uuml;bertragen, ist etwas unter Umst&auml;nden sehr wichtiges zu beachten &#8211; zumindest war das bei meinem Projekt der Fall. Die Artikel existierten ja zuvor bereits auf einer anderen Webseite, in diesem Fall einer auf Basis des CMS-Systems Typo3. Hier sind die Links auf die Artikel wie folgt aufgebaut:<\/p>\n<pre>http:\/\/www.access-im-unternehmen.de\/index1.phpid=300&BeitragID=1<\/pre>\n<p>Dabei war die einzige Variable die Zahl f&uuml;r den Parameter <b>BeitragID<\/b>. Wenn man eine Webseite neu aufbaut, die bei Google bereits ein gutes Ranking erreicht hat, sollte man sicherstellen, dass die Adresse, unter welcher die gerankten Artikel erreichbar sind, gleich bleibt. Nat&uuml;rlich gibt es technische M&ouml;glichkeiten, daf&uuml;r zu sorgen, dass wenn der Benutzer einen Google-Link auf die Seite anklickt, auch die auf dem neuen Server unter einer anderen Adresse gespeicherte Seite angezeigt wird. Unter WordPress sehen die Links normalerweise wie folgt aus:<\/p>\n<pre>http:\/\/www.access-im-unternehmen.de\/p=1<\/pre>\n<p>Man kann nun auf dem Server bestimmte Regeln einrichten, nach denen etwa der obige, alte Link in den neuen Link umbenannt wird &#8211; das ist allerdings ein Thema, das wir in diesem Beitrag nicht mehr anrei&szlig;en wollen.<\/p>\n<p>F&uuml;r uns ist nur interessant, dass es zum Definieren einer solchen Regel einfach ist, wenn wir den dynamischen Teil der alten Adresse, hier also den Parameter <b>BeitragID<\/b>, auslesen und diesen dann in Form des Parameters <b>p <\/b>f&uuml;r den Link zur neuen Webseite nutzen k&ouml;nnen.<\/p>\n<p>Mein Plan war also zun&auml;chst, die Artikel in der Tabelle <b>wp_posts <\/b>genauso zu nummerieren wie in der Tabelle <b>tblBeitraege<\/b>. So w&auml;re es dann am einfachsten, per URL auf die Artikel zuzugreifen.<\/p>\n<p>Das hat auch zu Beginn gut geklappt, n&auml;mlich als die WordPress-Datenbank und speziell die Tabelle <b>wp_posts <\/b>noch komplett leer war. Dann allerdings habe ich zum Beispiel einen Beitrag bearbeitet oder Men&uuml;eintr&auml;ge hinzugef&uuml;gt.<\/p>\n<p>Und sowohl f&uuml;r die Bearbeitungsst&auml;nde von WordPress-Artikeln als auch f&uuml;r Men&uuml;eintr&auml;ge werden neue Datens&auml;tze in der Tabelle <b>wp_posts <\/b>angelegt. Ich hatte zwar nun die Datens&auml;tze mit den Prim&auml;rschl&uuml;sselwerten bis etwa 1.200 mit Beitr&auml;gen gef&uuml;llt und jeder dieser Artikel hatte den seiner ID entsprechenden Prim&auml;rschl&uuml;sselwert.<\/p>\n<p>Die angelegten Men&uuml;s und die Bearbeitungsst&auml;nde der editierten Artikel haben dann allerdings die Prim&auml;rschl&uuml;sselwerte ab 1.200 in Beschlag genommen &#8211; die n&auml;chsten Werte wie 1.201, 1.202 und so weiter waren also belegt. Neue Beitr&auml;ge h&auml;tte ich dann also mit L&uuml;cken in den ID-Werten hinzuf&uuml;gen m&uuml;ssen. Das war erstens ein Problem, weil ich die Beitrag-IDs zumindest einigerma&szlig;en l&uuml;ckenlos halten wollte und zweitens die Beitr&auml;ge ja bereits weit vor der Ver&ouml;ffentlichung in der Artikeldatenbank angelegt wurden und somit bereits feste ID-Werte erhalten haben. Also sollten diese dann auch unter den vergebenen ID-Werten in der Tabelle <b>wp_posts <\/b>landen.<\/p>\n<p>Es musste also eine alternative L&ouml;sung her, die zukunftssicher war und gleichzeitig die IDs der Beitr&auml;ge im Prim&auml;rschl&uuml;sselfeld enthielt. Also habe ich mich entschieden, einfach eine recht gro&szlig;e Zahl zu den IDs hinzuzuaddieren &#8211; in diesem Fall 55.000.000 &#8211; und somit f&uuml;r alle Zeiten gen&uuml;gend freie IDs f&uuml;r alle sonstigen Zwecke vorzuhalten. Der Beitrag mit der ID <b>1.201 <\/b>w&uuml;rde also in der Tabelle <b>wp_posts <\/b>unter dem Prim&auml;rschl&uuml;sselwert <b>55.001.201 <\/b>abgespeichert werden.<\/p>\n<p>Sie m&ouml;gen jetzt einwerfen, dass man dann nicht mehr so einfach &uuml;ber einer URL wie <b>www.access-im-unternehmen.de\/1201 <\/b>auf den Beitrag zugreifen kann. Das h&auml;tte nat&uuml;rlich gravierende Folgen, denn wir haben diese Nummern in jedem Beitrag in den gedruckten Heften angegeben, damit die Leser darunter die Downloads mit den Beispieldatenbanken zu dem jeweiligen Beitrag beziehen k&ouml;nnen.<\/p>\n<p>Das ist aber auch kein Problem: Wir haben ja bereits beschrieben, dass wir auf dem Server definieren k&ouml;nnen, dass URLs ge&auml;ndert werden k&ouml;nnen. Und so l&auml;sst sich auch aus <b>www.access-im-unternehmen.de\/1201 <\/b>relativ leicht <b>www.access-im-unternehmen.de\/p=1201 <\/b>erzeugen. Der Leser soll dann also sowohl &uuml;ber den im Heft angegebenen Link <b>www.access-im-unternehmen.de\/1201 <\/b>als auch &uuml;ber die bei Google gespeicherten URLs wie <b>www.access-im-unternehmen.de\/index1.phpid=300&#038;BeitragID=1201 <\/b>auf die Beitr&auml;ge zugreifen k&ouml;nnen. Und das k&ouml;nnen wir durch entsprechende Regeln auch erreichen, wenn die ID eigentlich <b>55001201 <\/b>lautet.<\/p>\n<p><b>L&ouml;schen und neu anlegen<\/b><\/p>\n<p>Gerade in der Testphase wird es oft vorkommen, dass Sie die Datens&auml;tze in der WordPress-Datenbank l&ouml;schen und neu anlegen wollen. Wir haben dies in den folgenden Prozeduren ber&uuml;cksichtigt.<\/p>\n<p>Da wir nicht nur f&uuml;r die Beitr&auml;ge Prim&auml;rschl&uuml;sselwerte in einem bestimmten Bereich verwenden wollen (ab 55.000.001), sondern auch f&uuml;r die Kategorien in der Tabelle <b>wp_terms <\/b>(ab 88.000.001) und f&uuml;r die ebenfalls dort definierten Jahre (ab 99.001) und die untergeordneten Ausgaben (ab 99.000.001), k&ouml;nnen wir die Datens&auml;tze jeweils auch wieder entfernen, damit wir sie anschlie&szlig;end jederzeit wieder reproduzieren k&ouml;nnen.<\/p>\n<p>Das ist aber nicht der alleinige Grund daf&uuml;r, dass wir auch Kategorien, Ausgaben und Jahre mit solch hohen Werten gef&uuml;llt werden sollen. Der n&auml;chste Grund ist, dass wir sp&auml;ter noch eine Men&uuml;struktur auf Basis der Kategorien, Ausgaben und Jahre aufbauen wollen. Und damit wir diese nicht immer wieder neu erstellen m&uuml;ssen, wenn wir die Kategorien, Ausgaben und Jahre neu hinzugef&uuml;gt haben, verwenden wir f&uuml;r diese genau wie f&uuml;r die Beitr&auml;ge immer die gleichen ID-Werte.<\/p>\n<p><b>Beitr&auml;ge und Kategorien nur per Access<\/b><\/p>\n<p>Damit dies funktioniert, d&uuml;rfen Sie &Auml;nderungen an Beitr&auml;gen und Kategorien nat&uuml;rlich nur &uuml;ber die Datenbank durchf&uuml;hren. Jede &Auml;nderung, die Sie &uuml;ber den Editor von WordPress durchgef&uuml;hrt haben, wird ja sonst bei einem erneuten Einspielen der Daten der Access-Datenbank wieder &uuml;berschrieben.<\/p>\n<p><b>Prozedur zum &Uuml;bertragen der Beitr&auml;ge<\/b><\/p>\n<p>Beginnen wir mit der Prozedur, die durch die beiden Ereignisprozeduren des Formulars aufgerufen wird. Diese beiden Ereignisprozeduren sehen wie folgt aus:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdAlleNachWordpress_Click()\r\n     WordPressExport\r\n<span style=\"color:blue;\">End Sub<\/span>\r\n<span style=\"color:blue;\">Private Sub <\/span>cmdBeitragNachWordpress_Click()\r\n     WordPressExport Me!BeitragID\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Die Prozeduren rufen beide die Routine <b>WordPressExport <\/b>auf (siehe Listing 1). Diese erwartet als optionalen Parameter eine Beitrag-ID. Wird kein Wert &uuml;bergeben, nimmt der Parameter <b>lngBeitragID <\/b>den Standardwert <b>0 <\/b>an.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>WordPressExport(<span style=\"color:blue;\">Optional<\/span> lngBeitragID<span style=\"color:blue;\"> As Long<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\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>strSQL<span style=\"color:blue;\"> As String<\/span>, strSQLDelete<span style=\"color:blue;\"> As String<\/span>, strDateiname<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strInhalt<span style=\"color:blue;\"> As String<\/span>, strTitel<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strKurztext<span style=\"color:blue;\"> As String<\/span>, strWhere<span style=\"color:blue;\"> As String<\/span>\r\n     strDateiname = CurrentProject.Path & \"SQLBeitraege.sql\"\r\n     On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n     Kill strDateiname\r\n     <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> lngBeitragID = 0<span style=\"color:blue;\"> Then<\/span>\r\n         strWhere = \"tblBeitraege.BeitragID = \" & lngBeitragID & \" AND NOT \" & cstrFeldInhalt & \" IS NULL\"\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         strWhere = \"NOT \" & cstrFeldInhalt & \" IS NULL\"\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM tblBeitraege WHERE \" & strWhere, dbOpenDynaset)\r\n     Open strDateiname For Append<span style=\"color:blue;\"> As <\/span>#1\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n         strSQLDelete = \"DELETE FROM wp_posts WHERE ID = \" & 55000000 + rst!BeitragID & \";\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         DoEvents\r\n         Print #1, strSQLDelete\r\n         rst.Move<span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n     rst.MoveFirst\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n         strInhalt = rst(cstrFeldInhalt)\r\n         strTitel = rst!Titel\r\n         strTitel = Ersetzen(strTitel)\r\n         strKurztext = rst!Kurztext\r\n         strKurztext = Ersetzen(strKurztext)\r\n         strSQL = \"INSERT INTO wp_posts(ID, post_author, post_date, post_date_gmt, post_content, post_title, \" _\r\n             & \"post_excerpt, post_status, comment_status, ping_status, post_name, post_parent, guid, menu_order, \" _\r\n             & \"post_type, comment_count) VALUES(\" & 55000000 + rst!BeitragID & \", 1, '\" _\r\n             & format(DateSerial(rst!Jahr, rst!Ausgabe * 2, 1), \"yyyy-mm-dd hh:nn:ss\") & \"', '\" & format(Now, _\r\n             \"yyyy-mm-dd hh:nn:ss\") & \"', '\" & strInhalt & \"', '\" & strTitel & \"', '\" & strKurztext _\r\n             & \"', 'publish', 'open', 'open', '\" & <span style=\"color:blue;\">Replace<\/span>(<span style=\"color:blue;\">Replace<\/span>(rst!Titel, \" \", \"_\"), \"'\", \"''\") & \"', \" _\r\n             & \"0, 'http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/p=\" & rst!BeitragID & \"', 0, 'post', 0);\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         Print #1, strSQL\r\n         DoEvents\r\n         rst.Move<span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n     Print #1, KategorienArtikel(strWhere)\r\n     Print #1, KategorienAusgaben(strWhere)\r\n     Close #1\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><!--30percent--><\/p>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Prozedur zum Erstellen des SQL-Skripts f&uuml;r die Beitr&auml;ge<\/span><\/b><\/p>\n<p>Die Prozedur legt zun&auml;chst einen Dateinamen fest &#8211; und zwar f&uuml;r die Datei, in der wir die SQL-Anweisungen speichern wollen, die wir zum &Uuml;bertragen der Daten ben&ouml;tigen. Bei der in unserem Fall anfallenden Datenmenge reicht das Kopieren in die Zwischenablage zum direkten Eingeben in MySQL nicht mehr aus, daher legen wir gleich eine Datei mit dem Namen <b>SQLBeitraege.sql <\/b>im Verzeichnis der aktuellen Datenbank an. Danach l&ouml;schen wir die Datei, falls diese schon vorhanden ist. Dann erstellen wir f&uuml;r die Variable <b>db <\/b>einen Verweis auf das aktuelle <b>Database<\/b>-Objekt.<\/p>\n<p>Die folgende <b>If&#8230;Then<\/b>-Bedingung stellt eine <b>WHERE<\/b>-Klausel f&uuml;r die zu ber&uuml;cksichtigenden Beitr&auml;ge zusammen. Diese legt auf jeden Fall fest, dass das Feld, dessen Namen wir in der Konstanten <b>cstrFeldInhalt <\/b>festlegen, nicht Null sein darf und welche Beitr&auml;ge abh&auml;ngig vom &uuml;bergebenen Wert f&uuml;r den Parameter <b>lngBeitragID <\/b>ber&uuml;cksichtigt werden sollen. Die Konstante <b>cstrFeldInhalt <\/b>haben wir festgelegt, damit wir das Feld, das den Inhalt liefert, flexibel an einer Stelle &auml;ndern k&ouml;nnen.<\/p>\n<p>Danach f&uuml;llen wir eine Recordset-Variable namens <b>rst <\/b>mit einer Abfrage, die Daten der Tabelle <b>tblBeitraege <\/b>liefert &#8211; abh&auml;ngig davon, ob einer oder alle Beitr&auml;ge ber&uuml;cksichtigt werden sollen. Danach legt die Prozedur mit der <b>Open<\/b>-Anweisung die zu f&uuml;llende Textdatei an.<\/p>\n<p>In einer <b>Do While<\/b>-Schleife &uuml;ber alle Datens&auml;tze des Recordsets stellt die Prozedur in der Variablen <b>strSQLDelete <\/b>eine Anweisung zusammen, welche den Eintrag aus der Tabelle <b>wp_posts <\/b>l&ouml;scht, dessen ID-Wert der Zahl <b>55.000.000 <\/b>plus dem Prim&auml;rschl&uuml;sselwert aus der Tabelle <b>tblBeitraege <\/b>entspricht. Der Inhalt der Variablen <b>strSQLDelete <\/b>wird dann mit der <b>Print<\/b>-Anweisung in die Textdatei geschrieben. Diese Anweisungen sehen dann beispielsweise wie folgt aus:<\/p>\n<pre>DELETE FROM wp_posts WHERE ID = 55000001;<\/pre>\n<p>Nachdem so alle <b>DELETE<\/b>-Anweisungen in die Textdatei geschrieben wurden, springen wir mit der <b>MoveFirst<\/b>-Methode wieder zum ersten Datensatz des Recordsets zur&uuml;ck und durchlaufen die Schleife erneut. Diesmal stellen wir in einigen String-Variablen die Werte aus dem Feldern der Tabelle <b>tblBeitraege <\/b>zusammen, die in der Tabelle <b>wp_posts <\/b>landen sollen.<\/p>\n<p>Hier nutzen wir dann beispielsweise noch eine Funktion namens <b>Ersetzen<\/b>, die noch vorhandene Umlaute et cetera durch die entsprechenden HTML-Entit&auml;ten ersetzt. Diese Funktion stellen wir weiter unten vor.<\/p>\n<p>Dann stellen wir die <b>INSERT INTO<\/b>-Anweisung in der Variablen <b>strSQL <\/b>zusammen. Diese Abfragen sind nat&uuml;rlich etwas umfangreicher, da sie unter anderem den kompletten HTML-Code enthalten:<\/p>\n<pre>INSERT INTO wp_posts(ID, post_author, post_date, post_date_gmt, post_content, post_title, post_excerpt, post_status, comment_status, ping_status, post_name, post_parent, guid, menu_order, post_type, comment_count) VALUES(55000001, 1, '2000-02-01 00:00:00', '2019-09-17 13:10:32', '&lt;p&gt;&lt;b&gt;Wenn Sie bereits einmal Datenbankanwendungen mit VBA-Funktionen und -Prozeduren entwickelt haben, kennen Sie bereits das Vergn&uuml;gen, sich mit dem Auffinden und Beheben der unterschiedlichsten Fehler herumzuschlagen - es sei denn, Sie programmieren so gut, dass nie Fehler auftreten. Im vorliegenden Beitrag erfahren Sie, welche Fehlerarten bei der Arbeit mit VBA auftreten k&ouml;nnen, wie man die Fehler findet und sie schlie&szlig;lich behebt. Dabei lernen Sie auch die unterschiedlichen M&ouml;glichkeiten der Fehlersuche kennen.&lt;\/b&gt;&lt;\/p&gt;\r\n&lt;h2&gt;Fehlerarten in VBA&lt;\/h2&gt;\r\n&lt;p&gt;Die Fehlerarten, die bei der Programmierung mit VBA auftreten, k&ouml;nnen in drei unterschiedliche Gruppen eingeteilt werden.&lt;\/p&gt;...', 'Fehlersuche und -behandlung mit Access', 'Wenn Sie bereits einmal Datenbankanwendungen mit VBA-Funktionen und -Prozeduren entwickelt haben, kennen Sie bereits ....', 'publish', 'open', 'open', 'Fehlersuche_und_-behandlung_mit_Access', 0, 'http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/p=1', 0, 'post', 0);<\/pre>\n<p>F&uuml;r viele der Felder der Tabelle <b>wp_posts <\/b>haben wir Standardwerte verwendet. Einige haben wir jedoch mit den Inhalten aus der Quelltabelle <b>tblBeitraege <\/b>versehen. Dazu geh&ouml;ren nat&uuml;rlich die drei Felder <b>post_content<\/b>, <b>post_title <\/b>und <b>post_excerpt<\/b>. Das Feld <b>post_date <\/b>haben wir mit einem Datum gef&uuml;llt, das wir aus den Feldern <b>Ausgabe <\/b>und <b>Jahr <\/b>des jeweiligen Beitrags zusammengestellt haben.<\/p>\n<p>Somit kann der Benutzer direkt erkennen, wann der Beitrag urspr&uuml;nglich geschrieben wurde. Das Feld <b>post_type <\/b>erh&auml;lt den Wert <b>post<\/b>. Und nat&uuml;rlich weisen wir dem Feld <b>ID <\/b>den Wert des Prim&auml;rschl&uuml;sselfeldes <b>BeitragID <\/b>plus <b>55.000.000 <\/b>zu.<\/p>\n<p>Auch diese Anweisung schreiben wir wieder in die Textdatei. Zwischendurch ist Ihnen sicher die Anweisung <b>DoEvents <\/b>aufgefallen. Diese bauen wir immer ein, wenn Schleifen sehr oft durchlaufen werden, da es sonst passieren kann, dass der VBA-Editor zwischendurch nicht mehr ansprechbar ist.<\/p>\n<p>Dem wirken Sie entgegen, indem Sie in Schleifen die <b>DoEvents<\/b>-Anweisung einbauen. Dann k&ouml;nnen Sie solche Schleifen immer mit der Tastenkombination <b>Strg + Rollen\/Unterbrechen<\/b> unterbrechen.<\/p>\n<p>Danach rufen wir noch zwei weitere Routinen namens <b>KategorienArtikel <\/b>und <b>KategorienAusgaben <\/b>auf und schlie&szlig;en die ge&ouml;ffnete Textdatei mit der <b>Close<\/b>-Methode.<\/p>\n<p>Mit der ersten Prozedur allein haben wir jedoch schon erreicht, dass all unsere Beitr&auml;ge aus der Tabelle <b>tblBeitraege <\/b>in der WordPress-Tabelle <b>wp_posts <\/b>gelandet sind.<\/p>\n<p><b>Kategorien in WordPress<\/b><\/p>\n<p>Weiter oben haben wir bereits erw&auml;hnt, dass wir zus&auml;tzlich zu den Beitr&auml;gen auch noch Kategorien in WordPress importieren wollen. Aber ist das &uuml;berhaupt n&ouml;tig Je nach Einsatzzweck nicht unbedingt. Es gibt in Blog-Systemen wie WordPress so viele M&ouml;glichkeiten, auf die Beitr&auml;ge zuzugreifen.<\/p>\n<p>Zun&auml;chst einmal werden die aktuellsten Beitr&auml;ge standardm&auml;&szlig;ig auf der Startseite angezeigt. Dann gibt es Archive, die meist in der Seitenleiste (&#8222;Sidebar&#8220;) aufgef&uuml;hrt werden und &uuml;ber die man die Beitr&auml;ge eines Monats oder eines anderen Zeitraums anzeigen kann.<\/p>\n<p>Ein weiteres beliebtes Mittel zur Anzeige von Artikeln ist die Schlagwortwolke oder Wordwolke, welche die beliebtesten Begriffe auf verschiedene, mehr oder weniger verspielte Art darstellt.<\/p>\n<p>Und schlie&szlig;lich w&auml;re da noch die Suchfunktion, die alle Beitr&auml;ge liefert, welche die gew&uuml;nschten Suchbegriffe enth&auml;lt.<\/p>\n<p>Aber wir wollen ja ein f&uuml;r den Benutzer &auml;hnliches oder besseres Erlebnis bieten, wie es mit der vorherigen Webseite der Fall war. Diese hat eine &Uuml;bersicht mit allen Artikeln angeboten. Eine solche &Uuml;bersicht gibt es, wenn auch nicht auf einer Seite, sondern mit vielen Seiten zum Durchbl&auml;ttern, bereits standardm&auml;&szlig;ig &uuml;ber die Startseite.<\/p>\n<p>Aber damit der Benutzer schnell einen Beitrag einer bestimmten Ausgabe findet, soll er sowohl die Jahre als auch die Ausgaben angezeigt bekommen. Au&szlig;erdem wollen wir die bereits mit den Beitr&auml;gen verkn&uuml;pften Kategorien anzeigen, damit der Benutzer sich beispielsweise alle Beitr&auml;ge zu einem bestimmten Thema ansehen kann.<\/p>\n<p><b>Kategorien &uuml;bertragen und mit Beitr&auml;gen verkn&uuml;pfen<\/b><\/p>\n<p>Wie dem Datenmodell von WordPress von weiter oben zu entnehmen ist, ben&ouml;tigen wir f&uuml;r die Kategorien jeweils die folgenden Elemente (unter Bild 4 nochmal der relevante Ausschnitt des Datenmodells):<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_06\/pic_1215_003.png\" alt=\"Datenmodell von WordPress mit den f&uuml;r die Kategorien relevanten Tabellen\" width=\"549,6265\" height=\"613,3175\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Datenmodell von WordPress mit den f&uuml;r die Kategorien relevanten Tabellen<\/span><\/b><\/p>\n<ul>\n<li>Ein Eintrag in der Tabelle <b>wp_terms<\/b>, der den Namen der Kategorie enth&auml;lt.<\/li>\n<li>Ein Eintrag in der Tabelle <b>wp_term_taxonomy <\/b>f&uuml;r jede Kategorie aus <b>wp_terms<\/b>, die eine <b>term_taxonomy_id <\/b>zu jeder Kategorie zuweist und die &uuml;ber das Feld <b>parent <\/b>die Hierarchie der Elemente definiert.<\/li>\n<li>Ein Eintrag f&uuml;r jede Kombination aus Beitrag und Kategorie in der Tabelle <b>wp_term_relationships<\/b>, wo der Beitrag aus <b>wp_posts <\/b>mit einem Eintrag aus <b>wp_term_taxonomy <\/b>verkn&uuml;pft wird. Die Beziehung zur Kategorie wird dann wiederum durch die Verkn&uuml;pfung von <b>wp_term_taxonomy <\/b>zu <b>wp_terms <\/b>definiert.<\/li>\n<\/ul>\n<p>Genau wie bei den Beitr&auml;gen wollen wir auch bei den IDs f&uuml;r die Kategorien in <b>wp_terms <\/b>und in <b>wp_term_taxonomy <\/b>sicherstellen, dass wir einen freien Bereich haben.<\/p>\n<p>Dementsprechend wollen wir f&uuml;r die IDs f&uuml;r die Eintr&auml;ge in <b>wp_terms <\/b>zu 88.000.000 hinzuaddieren, wenn wir die IDs aus der Tabelle <b>tblKategorien <\/b>unserer lokalen Access-Datenbank beziehen.<\/p>\n<p>Diese Aufgabe erledigen wir mit der Funktion <b>KategorienArtikel<\/b>, die von der weiter oben beschriebenen Prozedur <b>WordPressExport <\/b>aufgerufen wird, nachdem die Beitr&auml;ge in die Tabelle <b>wp_posts <\/b>geschrieben worden sind (siehe Listing 2).<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>KategorienArtikel(strWhere<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\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>rstBeitraege<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strSQLDelete<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM qryAlleBenutztenKategorien WHERE \" & strWhere, dbOpenDynaset)\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n         strSQLDelete = strSQLDelete & \"DELETE FROM wp_terms WHERE term_id = \" & 88000000 + rst!KategorieID & \";\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         strSQLDelete = strSQLDelete & \"DELETE FROM wp_term_taxonomy WHERE term_id = \" & 88000000 + rst!KategorieID _\r\n             & \";\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         strSQLINSERT = strSQLINSERT & \"INSERT INTO wp_terms(term_id, name, slug, term_group) VALUES(\" & 88000000 _\r\n             + rst!KategorieID & \", '\" & rst!Kategorie & \"', '\" & <span style=\"color:blue;\">Replace<\/span>(rst!Kategorie, \" \", \"_\") & \"', 0);\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         strSQLINSERT = strSQLINSERT & \"INSERT INTO wp_term_taxonomy(term_taxonomy_id, term_id, taxonomy, \" _\r\n             & \"description, parent, count) VALUES(\" & 88000000 + rst!KategorieID & \", \" & 88000000 + rst!KategorieID _\r\n             & \", 'category', '', 0, 0);\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> rstBeitraege = db.OpenRecordset(\"SELECT tblBeitraege.* FROM tblBeitraege INNER JOIN \" _\r\n             & \"tblBeitraegeKategorien ON tblBeitraege.BeitragID = tblBeitraegeKategorien.BeitragID WHERE \" & strWhere _\r\n             & \" AND KategorieID = \" & rst!KategorieID & \";\", dbOpenDynaset)\r\n         <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rstBeitraege.EOF\r\n             strSQLDelete = strSQLDelete & \"DELETE FROM wp_term_relationships WHERE object_id = \" & 55000000 + _\r\n                 & rstBeitraege!BeitragID & \" AND term_taxonomy_id = \" & 88000000 + rst!KategorieID & \";\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n             strSQLINSERT = strSQLINSERT & \"INSERT INTO wp_term_relationships(object_id, term_taxonomy_id, \" _\r\n                 & \"term_order) VALUES(\" & 55000000 + rstBeitraege!BeitragID & \", \" & 88000000 + CLng(rst!KategorieID) _\r\n                 & \", 0);\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n             rstBeitraege.Move<span style=\"color:blue;\">Next<\/span>\r\n         <span style=\"color:blue;\">Loop<\/span>\r\n         rst.Move<span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n     KategorienArtikel = strSQLDelete & strSQLINSERT\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Prozedur zum Erstellen des SQL-Codes f&uuml;r die Kategorien<\/span><\/b><\/p>\n<p>Die Kategorien liegen in der Tabelle <b>tblKategorien <\/b>etwa wie in Bild 5 vor. Die Funktion <b>KategorienArtikel <\/b>erwartet einen Parameter namens <b>strWhere<\/b>, den wir bereits in der aufrufenden Prozedur zusammenstellen und der die zu ber&uuml;cksichtigenden Artikel einschr&auml;nkt, f&uuml;r die wir eine Beziehung zu einer oder mehreren Kategorien herstellen wollen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_06\/pic_1215_005.png\" alt=\"Kategorien-Tabelle in Access\" width=\"424,7115\" height=\"230,9112\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Kategorien-Tabelle in Access<\/span><\/b><\/p>\n<p>Um alle relevanten Kategorien zu ermitteln, verwenden wir die Abfrage <b>qryAlleBenutztenKategorien<\/b> aus Bild 6. Diese liefert alle Kategorien der Tabelle <b>tblKategorien<\/b>, die &uuml;ber die Verkn&uuml;pfungstabelle <b>tblBeitraegeKategorien <\/b>mit einem Beitrag aus der Tabelle <b>tblBeitraege <\/b>verkn&uuml;pft sind. In der folgenden <b>OpenRecordset<\/b>-Methode verwenden wir diese Abfrage und f&uuml;gen das mit <b>strWhere <\/b>gelieferte Kriterium noch zur Abfrage hinzu.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_06\/pic_1215_006.png\" alt=\"Abfrage mit allen benutzten Tabellen\" width=\"499,6607\" height=\"350,807\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Abfrage mit allen benutzten Tabellen<\/span><\/b><\/p>\n<p>Dann durchlaufen wir alle Datens&auml;tze dieser Abfrage in einer <b>Do While<\/b>-Schleife. Im Gegensatz zur aufrufenden Prozedur schreiben wir die hier zusammengestellten Anweisungen nicht direkt in die Textdatei, sondern stellen diese in zwei <b>String<\/b>-Variablen namens <b>strSQLDelete <\/b>und <b>strSQL <\/b>zusammen. Die erste Anweisung in <b>strSQLDelete <\/b>soll den Eintrag in der Tabelle <b>wp_terms <\/b>l&ouml;schen und sieht f&uuml;r die Kategorie mit der ID <b>25 <\/b>in der Access-Tabelle wie folgt aus: <\/p>\n<pre>DELETE FROM wp_terms WHERE term_id = 88000025;<\/pre>\n<p>Dann folgt die Anweisung, mit der wir die SQL-Anweisung zum L&ouml;schen des entsprechenden Eintrags der Tabelle <b>wp_term_taxonomy <\/b>hinzuf&uuml;gen, der hier so aussieht:<\/p>\n<pre>DELETE FROM wp_term_taxonomy WHERE term_id = 88000025;<\/pre>\n<p>Dann f&uuml;gen wir die beiden <b>INSERT INTO<\/b>-Anweisungen zur Variablen <b>strSQLINSERT <\/b>hinzu, mit denen die entsprechenden Eintr&auml;ge neu hinzugef&uuml;gt werden. Diese sehen so aus:<\/p>\n<pre>INSERT INTO wp_terms(term_id, name, slug, term_group) VALUES(88000025, 'VBA und Programmiertechniken', 'VBA_und_Programmiertechniken', 0);\r\nINSERT INTO wp_term_taxonomy(term_taxonomy_id, term_id, taxonomy, description, parent, count) VALUES(88000025, 88000025, 'category', '', 0, 0);<\/pre>\n<p>Ein solcher Aufruf f&uuml;r nur einen Beitrag, der nur einer Kategorie zugeordnet ist, w&auml;re also zum Beispiel schon sinnvoll, wenn Sie in der Access-Datenbank den Namen dieser Kategorie ge&auml;ndert h&auml;tten.<\/p>\n<p>Aber wir erneuern ja auch noch die Daten in der Tabelle <b>wp_term_relationships<\/b>, um die Daten der Tabelle <b>wp_term_taxonomy <\/b>mit den Daten der Tabelle <b>wp_posts <\/b>zu verkn&uuml;pfen. Das erledigen wir in einer weiteren Schleife, diesmal &uuml;ber alle Eintr&auml;ge der Tabelle <b>tblBeitraege<\/b>, die mit der aktuellen Kategorie des &uuml;bergeordneten Recordsets verkn&uuml;pft sind &#8211; zus&auml;tzlich selektiert nach der mit <b>strWhere <\/b>&uuml;bergebenen Bedingung.<\/p>\n<p>In dieser Schleife f&uuml;gen wir sowohl <b>strSQLDelete <\/b>als auch <b>strSQLInsert <\/b>je eine Anweisung f&uuml;r jede Kombination aus Beitrag und Kategorie hinzu. Als Erstes die <b>DELETE<\/b>-Anweisung, die den Eintrag f&uuml;r die aktuelle Kombination aus Beitrag und Kategorie aus der Tabelle <b>wp_term_relationsships <\/b>entfernt:<\/p>\n<pre>DELETE FROM wp_term_relationships WHERE object_id = 55000001 AND term_taxonomy_id = 88000025;<\/pre>\n<p>Und die <b>INSERT INTO<\/b>-Anweisung f&uuml;gt jeweils einen Eintrag f&uuml;r die Kombination aus Beitrag und Kategorie zur Tabelle <b>wp_term_relationships <\/b>hinzu:<\/p>\n<pre>INSERT INTO wp_term_relationships(object_id, term_taxonomy_id, term_order) VALUES(55000001, 88000025, 0);<\/pre>\n<p>Wenn wir beim Aufruf der Prozedur <b>WordPressExport <\/b>einen Parameter f&uuml;r den gegebenenfalls zu l&ouml;schenden und neu hinzuzuf&uuml;genden Beitrag &uuml;bergeben, liefert die Funktion <b>KategorienArtikel<\/b> die beschriebenen sechs Anweisungen &#8211; vorausgesetzt, der Beitrag ist nur einer Kategorie zugeordnet. Sonst werden es entsprechend mehr Anweisungen.<\/p>\n<p>Wenn kein Parameter &uuml;bergeben wird, stellt die Funktion <b>KategorienArtikel <\/b>die Anweisungen f&uuml;r alle Kombinationen aus Beitr&auml;gen und Kategorien zusammen und gibt die SQL-Anweisungen als Funktionswert an die aufrufende Prozedur zur&uuml;ck, die diese dann ebenfalls in die Textdatei mit dem SQL-Skript einf&uuml;gt.<\/p>\n<p><b>Kategorien f&uuml;r Jahre und Ausgaben<\/b><\/p>\n<p>Neben den eigentlichen Kategorien wollen wir auch f&uuml;r die Jahre und Ausgaben noch Men&uuml;eintr&auml;ge erschaffen, wof&uuml;r vorher noch die entsprechenden Kategorien angelegt werden m&uuml;ssen. Das Ergebnis soll sp&auml;ter wie in Bild 7 aussehen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_06\/pic_1215_007.png\" alt=\"Kategorien f&uuml;r Jahre und Ausgaben\" width=\"499,6607\" height=\"457,4359\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Kategorien f&uuml;r Jahre und Ausgaben<\/span><\/b><\/p>\n<p>Die f&uuml;r die Erstellung der Kategorien f&uuml;r die Jahre und Ausgaben verantwortliche Funktion hei&szlig;t <b>KategorienAusgaben <\/b>und sieht wie in Listing 3 aus. Genau wie die vorherige Funktion erwartet sie einen Parameter, der festlegt, f&uuml;r welche Beitr&auml;ge die Datens&auml;tze hinzugef&uuml;gt werden sollen.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>KategorienAusgaben(strWhere<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\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>rstAusgaben<span style=\"color:blue;\"> As <\/span>DAO.Recordset, rstBeitraege<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>strSQLDelete<span style=\"color:blue;\"> As String<\/span>, strSQLInsert<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT DISTINCT Jahr FROM tblBeitraege WHERE \" & strWhere _\r\n         & \" AND NOT Jahr = 0 ORDER BY Jahr DESC\", dbOpenDynaset)\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n         strSQLDelete = strSQLDelete & \"DELETE FROM wp_terms WHERE term_id = \" & 990000 + rst!Jahr & \";\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         strSQLDelete = strSQLDelete & \"DELETE FROM wp_term_taxonomy WHERE term_taxonomy_id = \" & 990000 + rst!Jahr _\r\n             & \";\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         strSQLInsert = strSQLInsert & \"INSERT INTO wp_terms(term_id, name, slug, term_group) VALUES(\" & 990000 _\r\n             + rst!Jahr & \", '\" & rst!Jahr & \"', '\" & rst!Jahr & \"', 0);\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         strSQLInsert = strSQLInsert & \"INSERT INTO wp_term_taxonomy(term_taxonomy_id, term_id, taxonomy, \" _\r\n             & \"description, parent, count) VALUES(\" & 990000 + rst!Jahr & \", \" & 990000 + rst!Jahr _\r\n             & \", 'category', '', 0, 0);\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> rstAusgaben = db.OpenRecordset(\"SELECT DISTINCT Ausgabe FROM tblBeitraege WHERE \" & strWhere _\r\n             & \" AND Jahr = \" & rst!Jahr & \" ORDER BY Ausgabe ASC\", dbOpenDynaset)\r\n         <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rstAusgaben.EOF\r\n             strSQLDelete = strSQLDelete & \"DELETE FROM wp_terms WHERE term_id = \" & 99000000 _\r\n                 + CLng(rstAusgaben!Ausgabe & rst!Jahr) & \";\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n             strSQLDelete = strSQLDelete & \"DELETE FROM wp_term_taxonomy WHERE term_taxonomy_id = \" & 99000000 _\r\n                 + CLng(rstAusgaben!Ausgabe & rst!Jahr) & \";\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n             strSQLInsert = strSQLInsert & \"INSERT INTO wp_terms(term_id, name, slug, term_group) VALUES(\" & 99000000 _\r\n                 + Lng(rstAusgaben!Ausgabe & rst!Jahr) & \", '\" & rstAusgaben!Ausgabe & \"\/\" & rst!Jahr & \"', '\" _\r\n                 & rstAusgaben!Ausgabe & \"\/\" & rst!Jahr & \"', 0);\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n             strSQLInsert = strSQLInsert & \"INSERT INTO wp_term_taxonomy(term_taxonomy_id, term_id, taxonomy, \" _\r\n                 & \"description, parent, count) VALUES(\" & 99000000 + CLng(rstAusgaben!Ausgabe & rst!Jahr) & \", \" _\r\n                 & 99000000 + CLng(rstAusgaben!Ausgabe & rst!Jahr) & \", 'category', '', \" & 990000 + rst!Jahr _\r\n                 & \", 0);\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n             <span style=\"color:blue;\">Set<\/span> rstBeitraege = db.OpenRecordset(\"SELECT * FROM tblBeitraege WHERE \" & strWhere & \" AND Jahr = \" _\r\n                 & rst!Jahr & \" AND Ausgabe = \" & rstAusgaben!Ausgabe, dbOpenDynaset)\r\n             <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rstBeitraege.EOF\r\n                 strSQLDelete = strSQLDelete & \"DELETE FROM wp_term_relationships WHERE object_id = \" & 55000000 _\r\n                     + rstBeitraege!BeitragID & \" AND term_taxonomy_id = \" & 99000000 + CLng(rstAusgaben!Ausgabe _\r\n                     & rst!Jahr) & \";\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n                 strSQLInsert = strSQLInsert & \"INSERT INTO wp_term_relationships(object_id, term_taxonomy_id, \" _\r\n                     & \"term_order) VALUES(\" & 55000000 + rstBeitraege!BeitragID & \", \" & 99000000 _\r\n                     + CLng(rstAusgaben!Ausgabe & rst!Jahr) & \", 0);\" & <span style=\"color:blue;\">vbCrLf<\/span>\r\n                 rstBeitraege.Move<span style=\"color:blue;\">Next<\/span>\r\n             <span style=\"color:blue;\">Loop<\/span>\r\n             rstAusgaben.Move<span style=\"color:blue;\">Next<\/span>\r\n         <span style=\"color:blue;\">Loop<\/span>\r\n         rst.Move<span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n     KategorienAusgaben = strSQLDelete & strSQLInsert\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Prozedur zum Erstellen des SQL-Codes f&uuml;r die Kategorien f&uuml;r die Jahre und Ausgaben<\/span><\/b><\/p>\n<p>Diese Funktion erstellt zun&auml;chst ein Recordset, das alle Eintr&auml;ge des Feldes <b>Jahr<\/b> der Tabelle <b>tblBeitraege <\/b>enth&auml;lt. Dabei kommt zum ersten Mal die Bedingung aus dem Parameter <b>strWhere <\/b>zum Tragen. Au&szlig;erdem sortieren wir die Eintr&auml;ge aufsteigend nach dem Jahr. Die <b>DISTINCT<\/b>-Klausel sorgt daf&uuml;r, dass jeder Wert des Feldes Jahr nur einmal zur&uuml;ckgeliefert wird.<\/p>\n<p>Dieses Recordset durchlaufen wir dann in einer <b>Do While<\/b>-Schleife. Die ersten beiden Anweisungen f&uuml;gen der Variablen <b>strSQLDelete <\/b>die folgenden beiden Anweisungen hinzu:<\/p>\n<pre>DELETE FROM wp_terms WHERE term_id = 992000;\r\nDELETE FROM wp_term_taxonomy WHERE term_taxonomy_id = 992000;<\/pre>\n<p>Wir l&ouml;schen also Eintr&auml;ge aus der Tabelle <b>wp_terms<\/b>, die der Jahreszahl plus 990.000 entsprechen, und die passenden Eintr&auml;ge aus der Tabelle <b>wp_term_taxonomy<\/b>.<\/p>\n<p>Die n&auml;chsten beiden Anweisungen f&uuml;gen genau diese Eintr&auml;ge wieder (oder erstmalig) zu diesen beiden Tabellen hinzu:<\/p>\n<pre>INSERT INTO wp_terms(term_id, name, slug, term_group) VALUES(992000, '2000', '2000', 0);\r\nINSERT INTO wp_term_taxonomy(term_taxonomy_id, term_id, taxonomy, description, parent, count) VALUES(992000, 992000, 'category', '', 0, 0);<\/pre>\n<p>Danach erstellt die Prozedur ein weiteres Recordset namens <b>rstAusgaben<\/b>. Dieses erfasst alle Werte des Feldes <b>Ausgabe <\/b>der Tabelle <b>tblBeitraege<\/b>, die zu dem Jahr geh&ouml;ren, das wir in der &uuml;bergeordneten Schleife durchlaufen und welche die Bedingungen aus <b>strWhere <\/b>erf&uuml;llen. Auch hier verwenden wir die <b>DISTINCT<\/b>-Klausel, damit jede Ausgabe nur einmal zur&uuml;ckgegeben wird, und sortieren aufsteigend nach dem Feld <b>Ausgabe<\/b>.<\/p>\n<p>Dieses Recordset durchlaufen wir nun in einer untergeordneten <b>Do While<\/b>-Schleife. In dieser kommen zwei weitere <b>DELETE<\/b>-Anweisungen zu <b>strSQLDelete <\/b>hinzu:<\/p>\n<pre>DELETE FROM wp_terms WHERE term_id = 99012000;\r\nDELETE FROM wp_term_taxonomy WHERE term_taxonomy_id = 99012000;<\/pre>\n<p>Hier l&ouml;schen wir also Eintr&auml;ge aus den Tabellen <b>wp_terms <\/b>und <b>wp_term_taxonomy<\/b>, welche aus der Ausgabe (<b>01<\/b>), und dem Jahr (<b>2000<\/b>) zusammengesetzt und zu denen der Wert <b>99.000.000 <\/b>addiert wurde.<\/p>\n<p>Und nat&uuml;rlich fehlen nicht die <b>INSERT INTO<\/b>-Anweisungen, um die gew&uuml;nschten Datens&auml;tze in die Tabellen <b>wp_terms <\/b>und <b>wp_term_taxonomy <\/b>einzutragen:<\/p>\n<pre>INSERT INTO wp_terms(term_id, name, slug, term_group) VALUES(99012000, '1\/2000', '1\/2000', 0);\r\nINSERT INTO wp_term_taxonomy(term_taxonomy_id, term_id, taxonomy, description, parent, count) VALUES(99012000, 99012000, 'category', '', 992000, 0);<\/pre>\n<p>Schlie&szlig;lich fehlt noch ein drittes Recordset und damit verbunden eine dritte Schleife, in der wir die Beitr&auml;ge der jeweiligen Ausgabe zur Kategorie hinzuf&uuml;gen.<\/p>\n<p>Dieses Recordset verwendet wieder eine Abfrage auf Basis der Tabelle <b>tblBeitraege<\/b>, die diesmal nach <b>strWhere<\/b>, dem <b>Jahr <\/b>und der <b>Ausgabe <\/b>gefiltert wird. Die <b>Do While<\/b>-Schleife auf Basis dieses Recordsets f&uuml;gt zun&auml;chst eine Anweisung zum L&ouml;schen des Eintrags der Tabelle <b>wp_term_relationsships <\/b>hinzu, welcher den Beitrag mit dem Eintrag der Tabelle <b>wp_term_taxonomy <\/b>verkn&uuml;pft:<\/p>\n<pre>DELETE FROM wp_term_relationships WHERE object_id = 55000001 AND term_taxonomy_id = 99012000;<\/pre>\n<p>Die letzte Anweisung der Schleife f&uuml;gt den <b>INSERT INTO<\/b>-Befehl zum Hinzuf&uuml;gen des ben&ouml;tigten Datensatzes hinzu:<\/p>\n<pre>INSERT INTO wp_term_relationships(object_id, term_taxonomy_id, term_order) VALUES(55000001, 99012000, 0);<\/pre>\n<p>Schlie&szlig;lich gibt die Funktion die so erstellten SQL-Anweisungen als Funktionswert an die aufrufende Prozedur zur&uuml;ck.<\/p>\n<p><b>Von der Kategorie zum Men&uuml;eintrag<\/b><\/p>\n<p>Nun haben wir zwar die Kategorien zur Tabelle <b>wp_terms <\/b>hinzugef&uuml;gt, zu jeder Kategorie einen Eintrag in <b>wp_term_taxonomy <\/b>angelegt und die Beziehung zwischen den Beitr&auml;gen aus <b>wp_posts <\/b>mit den Eintr&auml;gen aus <b>wp_term_taxonomy <\/b>&uuml;ber die Tabelle <b>wp_term_relationships <\/b>definiert.<\/p>\n<p>Allerdings erscheinen die Kategorien noch immer nicht als Men&uuml;eintr&auml;ge. Und an dieser Stelle hat der Forschungsdrang nicht mehr ausgereicht und wir haben die Men&uuml;-Eintr&auml;ge manuell &uuml;ber die Benutzeroberfl&auml;che von WordPress erstellt. Das gelingt, wenn Sie den Men&uuml;eintrag <b>Design|Men&uuml;s <\/b>ausw&auml;hlen. Es erscheint dann der Bereich aus Bild 8, wo Sie links auf <b>Kategorien <\/b>wechseln und alle Kategorien anzeigen lassen. Sie f&uuml;gen dann erst einmal alle gew&uuml;nschten Kategorien hinzu und k&ouml;nnen diese per Drag and Drop wie gew&uuml;nscht anordnen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_06\/pic_1215_008.png\" alt=\"Verwalten der Men&uuml;s in WordPress\" width=\"649,559\" height=\"424,1523\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 8: Verwalten der Men&uuml;s in WordPress<\/span><\/b><\/p>\n<p>Dies erzeugt unter anderem Eintr&auml;ge in der Tabelle <b>wp_posts<\/b>, deren Feld <b>post_type <\/b>den Wert <b>nav_menu_item <\/b>aufnimmt. Da sich diese Eintr&auml;ge auf die von uns immer mit den gleichen IDs gespeicherten Kategorien beziehen, k&ouml;nnen Sie diese einmal anlegen. Wenn Sie dann sp&auml;ter die Beitr&auml;ge und Kategorien, Jahre und Ausgaben &uuml;ber die Access-Datenbank neu hochladen, greifen auch die Men&uuml;eintr&auml;ge immer noch auf diese Kategorien zu.<\/p>\n<p><b>Problem Autowert<\/b><\/p>\n<p>Nachdem wir so gearbeitet haben, ist uns allerdings aufgefallen, dass WordPress uns durch die Autowert-Funktion beim Anlegen neuer Eintr&auml;ge etwa in der Tabelle <b>wp_posts <\/b>immer noch einen Strich durch die Rechnung macht, was das Reservieren bestimmter Bereiche f&uuml;r unsere Beitr&auml;ge und Kategorien angeht.<\/p>\n<p>Wenn wir also etwa Beitr&auml;ge bis zur ID <b>55.001.200 <\/b>angelegt haben, was <b>55.000.000 <\/b>plus Beitrags-ID <b>1.200 <\/b>entspricht, dann wird ein &uuml;ber die Benutzeroberfl&auml;che angelegter Men&uuml;eintrag die ID <b>55.001.201 <\/b>erhalten.<\/p>\n<p>Wenn wir dann beim Anlegen neuer Beitr&auml;ge einen Beitrag mit der ID <b>55.001.201 <\/b>anlegen, wird der Men&uuml;eintrag &uuml;berschrieben. Was wir aber machen k&ouml;nnen, ist das Hinzuf&uuml;gen von Dummy-Datens&auml;tzen. F&uuml;r die Tabelle <b>wp_posts <\/b>legen wir also etwa einen Datensatz mit der ID <b>60.000.000 <\/b>an.<\/p>\n<p>Dann reichen die ID noch f&uuml;r eine knappe Million Beitr&auml;ge, was auch bei sehr hoher Produktivit&auml;t ausreichend sein sollte. Und die folgenden, automatisch von WordPress beim Anlegen neuer Eintr&auml;ge in der Tabelle <b>wp_posts <\/b>vergebenen Prim&auml;rschl&uuml;sselwerte sind dann gr&ouml;&szlig;er als 60.000.000.<\/p>\n<p><b>Die Funktion Ersetzen<\/b><\/p>\n<p>Weiter oben haben wir noch die Funktion <b>Ersetzen <\/b>angesprochen, die in der Prozedur <b>WordPressExport <\/b>an zwei Stellen eingesetzt wird &#8211; einmal f&uuml;r den in <b>strTitel <\/b>gespeicherten Text und einmal f&uuml;r <b>strKurztext<\/b>.<\/p>\n<p>Die Funktion hat den Zweck, Vorkommen von Texten oder Zeichen, die unter HTML nicht angezeigt werden k&ouml;nnen, durch entsprechende HTML-Entit&auml;ten zu ersetzen. Dazu geh&ouml;ren etwa die Umlaute oder Sonderzeichen.<\/p>\n<p>In dieser Funktion haben wir auch noch Bereiche untergebracht, die HTML-Tags von Abs&auml;tzen untersuchen und ersetzen k&ouml;nnen.<\/p>\n<p>Das ist wichtig, wenn Ihnen zwar Beitr&auml;ge bereits im HTML-Format vorliegen, aber dort noch &Auml;nderungen durchgef&uuml;hrt werden m&uuml;ssen, damit der Inhalt des Dokuments in WordPress korrekt dargestellt wird.<\/p>\n<p>Wie diese Funktion funktioniert, zeigen wir im Beitrag <b>HTML-Code optimieren per VBA <\/b>(<b>www.access-im-unternehmen.de\/1218<\/b>) in der kommenden Ausgabe.<\/p>\n<p><b>Zusammenfassung und Ausblick<\/b><\/p>\n<p>Wenn Sie eine WordPress-Seite haben und diese mit Beitr&auml;gen f&uuml;ttern wollen, die bereits in einer Access-Tabelle vorliegen, hat dieser Beitrag alle notwendigen Informationen geliefert.<\/p>\n<p>Sie lernen die relevanten Teile des Datenmodells von WordPress kennen und erfahren, wie Sie die Daten aus einer einfachen, aus den Tabellen <b>tblBeitraege<\/b>, <b>tblKategorien <\/b>und <b>tblBeitraegeKategorien <\/b>bestehendem Datenmodell nach WordPress &uuml;bertragen k&ouml;nnen.<\/p>\n<p>Sollten die Daten bei Ihnen in einem anderen Format vorliegen wie etwa nur in den Tabellen <b>tblBeitraege <\/b>und <b>tblKategorien<\/b>, k&ouml;nnen Sie den Code leicht anpassen.<\/p>\n<h3>Downloads zu diesem Beitrag<\/h3>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>WordPress.accdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/EC3E9E40-FA79-4625-B921-AD2AEC8D86DD\/aiu_1215.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wordpress ist das g&auml;ngigste System f&uuml;r die Erstellung und Pflege von Blog. Mittlerweile gibt es so viele Erweiterungen, dass ein Blog nur noch eine von vielen M&ouml;glichkeiten ist, eine Webseite &uuml;ber die Wordpress-Plattform zu bauen. Da f&uuml;r Access im Unternehmen der Umzug auf ein ein moderneres System anstand, haben wir uns f&uuml;r Wordpress entschieden. Es bietet gleichzeitig viele M&ouml;glichkeiten und ist dennoch recht einfach zu bedienen. Das gilt allerdings auch nur, wenn Sie keine besonderen Anforderungen haben &#8211; was in unserem Fall anders aussieht: Immerhin vollen mehr als 1.000 Beitr&auml;ge samt Bildern und Downloads &uuml;bertragen werden. Und es darf auch nicht jeder alle Beitr&auml;ge vollst&auml;ndig betrachten, sondern nur &uuml;ber eine Benutzerverwaltung erfasste Abonnenten. Wie wir das realisiert haben, zeigen wir in diesem Beitrag.<\/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":[662019,66062019,44000027],"tags":[],"class_list":["post-55001215","post","type-post","status-publish","format-standard","hentry","category-662019","category-66062019","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>Von Access nach Wordpress - 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\/Von_Access_nach_Wordpress\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Von Access nach Wordpress\" \/>\n<meta property=\"og:description\" content=\"Wordpress ist das g&auml;ngigste System f&uuml;r die Erstellung und Pflege von Blog. Mittlerweile gibt es so viele Erweiterungen, dass ein Blog nur noch eine von vielen M&ouml;glichkeiten ist, eine Webseite &uuml;ber die Wordpress-Plattform zu bauen. Da f&uuml;r Access im Unternehmen der Umzug auf ein ein moderneres System anstand, haben wir uns f&uuml;r Wordpress entschieden. Es bietet gleichzeitig viele M&ouml;glichkeiten und ist dennoch recht einfach zu bedienen. Das gilt allerdings auch nur, wenn Sie keine besonderen Anforderungen haben - was in unserem Fall anders aussieht: Immerhin vollen mehr als 1.000 Beitr&auml;ge samt Bildern und Downloads &uuml;bertragen werden. Und es darf auch nicht jeder alle Beitr&auml;ge vollst&auml;ndig betrachten, sondern nur &uuml;ber eine Benutzerverwaltung erfasste Abonnenten. Wie wir das realisiert haben, zeigen wir in diesem Beitrag.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Von_Access_nach_Wordpress\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2020-07-10T09:50:33+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg09.met.vgwort.de\/na\/02af00feb9b943fe8648a068edd71520\" \/>\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=\"35\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Von_Access_nach_Wordpress\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Von_Access_nach_Wordpress\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Von Access nach WordPress\",\"datePublished\":\"2020-07-10T09:50:33+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Von_Access_nach_Wordpress\\\/\"},\"wordCount\":5829,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Von_Access_nach_Wordpress\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg09.met.vgwort.de\\\/na\\\/02af00feb9b943fe8648a068edd71520\",\"articleSection\":[\"2019\",\"6\\\/2019\",\"L\u00f6sungen\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Von_Access_nach_Wordpress\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Von_Access_nach_Wordpress\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Von_Access_nach_Wordpress\\\/\",\"name\":\"Von Access nach Wordpress - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Von_Access_nach_Wordpress\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Von_Access_nach_Wordpress\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg09.met.vgwort.de\\\/na\\\/02af00feb9b943fe8648a068edd71520\",\"datePublished\":\"2020-07-10T09:50:33+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Von_Access_nach_Wordpress\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Von_Access_nach_Wordpress\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Von_Access_nach_Wordpress\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg09.met.vgwort.de\\\/na\\\/02af00feb9b943fe8648a068edd71520\",\"contentUrl\":\"http:\\\/\\\/vg09.met.vgwort.de\\\/na\\\/02af00feb9b943fe8648a068edd71520\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Von_Access_nach_Wordpress\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Von Access nach WordPress\"}]},{\"@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":"Von Access nach Wordpress - 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\/Von_Access_nach_Wordpress\/","og_locale":"de_DE","og_type":"article","og_title":"Von Access nach Wordpress","og_description":"Wordpress ist das g&auml;ngigste System f&uuml;r die Erstellung und Pflege von Blog. Mittlerweile gibt es so viele Erweiterungen, dass ein Blog nur noch eine von vielen M&ouml;glichkeiten ist, eine Webseite &uuml;ber die Wordpress-Plattform zu bauen. Da f&uuml;r Access im Unternehmen der Umzug auf ein ein moderneres System anstand, haben wir uns f&uuml;r Wordpress entschieden. Es bietet gleichzeitig viele M&ouml;glichkeiten und ist dennoch recht einfach zu bedienen. Das gilt allerdings auch nur, wenn Sie keine besonderen Anforderungen haben - was in unserem Fall anders aussieht: Immerhin vollen mehr als 1.000 Beitr&auml;ge samt Bildern und Downloads &uuml;bertragen werden. Und es darf auch nicht jeder alle Beitr&auml;ge vollst&auml;ndig betrachten, sondern nur &uuml;ber eine Benutzerverwaltung erfasste Abonnenten. Wie wir das realisiert haben, zeigen wir in diesem Beitrag.","og_url":"https:\/\/access-im-unternehmen.de\/Von_Access_nach_Wordpress\/","og_site_name":"Access im Unternehmen","article_published_time":"2020-07-10T09:50:33+00:00","og_image":[{"url":"http:\/\/vg09.met.vgwort.de\/na\/02af00feb9b943fe8648a068edd71520","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"35\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Von_Access_nach_Wordpress\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Von_Access_nach_Wordpress\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Von Access nach WordPress","datePublished":"2020-07-10T09:50:33+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Von_Access_nach_Wordpress\/"},"wordCount":5829,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Von_Access_nach_Wordpress\/#primaryimage"},"thumbnailUrl":"http:\/\/vg09.met.vgwort.de\/na\/02af00feb9b943fe8648a068edd71520","articleSection":["2019","6\/2019","L\u00f6sungen"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Von_Access_nach_Wordpress\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Von_Access_nach_Wordpress\/","url":"https:\/\/access-im-unternehmen.de\/Von_Access_nach_Wordpress\/","name":"Von Access nach Wordpress - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Von_Access_nach_Wordpress\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Von_Access_nach_Wordpress\/#primaryimage"},"thumbnailUrl":"http:\/\/vg09.met.vgwort.de\/na\/02af00feb9b943fe8648a068edd71520","datePublished":"2020-07-10T09:50:33+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Von_Access_nach_Wordpress\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Von_Access_nach_Wordpress\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Von_Access_nach_Wordpress\/#primaryimage","url":"http:\/\/vg09.met.vgwort.de\/na\/02af00feb9b943fe8648a068edd71520","contentUrl":"http:\/\/vg09.met.vgwort.de\/na\/02af00feb9b943fe8648a068edd71520"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Von_Access_nach_Wordpress\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Von Access nach WordPress"}]},{"@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\/55001215","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=55001215"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001215\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55001215"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55001215"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55001215"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}