{"id":55000995,"date":"2015-10-01T00:00:00","date_gmt":"2020-05-22T19:10:44","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=995"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Aenderungshistorie_implantieren","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Aenderungshistorie_implantieren\/","title":{"rendered":"&Auml;nderungshistorie implantieren"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg07.met.vgwort.de\/na\/3620227acb9f46c18f884c24e28a851a\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Die neuen Tabellenereignisse, die mit Access 2010 eingef&uuml;hrt wurden, erlauben die automatische Sicherung von Tabellendaten vor der Durchf&uuml;hrung von &auml;nderungen an den Datens&auml;tzen. Dazu legen Sie entsprechende Datenmakros an, die durch die Tabellenereignisse ausgel&ouml;st werden. Au&szlig;erdem ben&ouml;tigen Sie eine Tabelle, welche die ge&auml;nderten Datens&auml;tze speichert. Wenn Sie beides f&uuml;r mehrere Tabellen durchf&uuml;hren wollen, ist dies eine Menge Handarbeit. Grund genug, diesen Vorgang zu automatisieren.<\/b><\/p>\n<p>Dazu eignet sich nat&uuml;rlich ein Access-Add-In am besten: Dieses k&ouml;nnen Sie in allen betroffenen Datenbanken starten und die Tabellen mit den zu sichernden Daten pr&auml;parieren. Dazu soll die Tabelle zun&auml;chst kopiert und unter einem passenden Namen gespeichert werden &#8211; bei der Tabelle <b>tblArtikel <\/b>beispielsweise unter dem Namen <b>_tblArtikel_Backup<\/b>. Diese Tabelle soll zus&auml;tzlich noch zwei Felder enthalten, die das &auml;nderungsdatum oder das L&ouml;schdatum aufnehmen.<\/p>\n<p>Die L&ouml;sung setzt auf dem Beitrag <b>Ge&auml;nderte Daten archivieren <\/b>auf (<b>www.access-im-unternehmen.de\/925<\/b>).<\/p>\n<h2>Aussehen der Makros zum Erstellen des Backups<\/h2>\n<p>Das Makro f&uuml;r das Speichern der Daten der Tabelle etwa nach der Aktualisierung eines Datensatzes sieht wie in Bild 1 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_05\/pic_995_001.png\" alt=\"Aufbau des Makros zum Sichern der Daten vor dem Aktualisieren\" width=\"500\" height=\"830,018\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Aufbau des Makros zum Sichern der Daten vor dem Aktualisieren<\/span><\/b><\/p>\n<p>Der erste Teil pr&uuml;ft, ob die Option zum Deaktivieren der Sicherung gegebenenfalls deaktiviert ist. Dazu muss eine Tabelle namens <b>tblOptionen <\/b>vorhanden sein. Diese k&ouml;nnen Sie gegebenenfalls auch unter einem anderen Namen anlegen, da viele Anwendungen bereits &uuml;ber eine solche Tabelle verf&uuml;gen.<\/p>\n<p>Die folgenden Befehle erstellen einen neuen Datensatz in der jeweiligen Zieltabelle und stellen die Werte der Felder auf die Werte vor der &auml;nderung ein. Diese Werte liefert jeweils die Tabelle <b>Alt<\/b>.<\/p>\n<p>Schlie&szlig;lich weist das Makro dem Feld <b>GeaendertAm <\/b>noch den &auml;nderungszeitpunkt zu.<\/p>\n<p>Beim L&ouml;schen eines Datensatzes sieht es &auml;hnlich aus &#8211; der einzige Unterschied besteht darin, dass der L&ouml;schzeitpunkt im Feld <b>GeloeschtAm <\/b>gesichert wird.<\/p>\n<h2>Einschr&auml;nkungen<\/h2>\n<p>F&uuml;r das Sichern von Daten per Tabellenereignis gibt es eine Einschr&auml;nkung bez&uuml;glich der Felddatentypen: Von der Sicherung sind n&auml;mlich sowohl Memofelder als auch Anlagefelder und mehrwertige Felder ausgeschlossen. Die Backup-Tabellen m&uuml;ssen diese Felder also gar nicht erst aufnehmen und auch das Tabellenereignis ber&uuml;cksichtigt diese nicht.<\/p>\n<h2>Deutsch-Englisch<\/h2>\n<p>Ein weiteres Problem ist die automatische &uuml;bersetzung des Makro-Codes. Wenn Access n&auml;mlich ein deutsches Literal erkennt, das in der englischen Version irgendeinem Access-Schl&uuml;sselwort entspricht, dann &uuml;bersetzt Access dieses automatisch.<\/p>\n<p>Sollten Sie also in einem Datenmakro den Feldnamen <b>[Old].[Beschreibung] <\/b>verwenden, wird dieser in <b>[Old].[Description] <\/b>ge&auml;ndert. Das ist unbefriedigend, aber au&szlig;er durch Umgehung der entsprechenden Feldnamen wohl kaum zu l&ouml;sen.<\/p>\n<h2>Aufgaben des geplanten Add-Ins<\/h2>\n<p>Das zu erstellende Add-In soll also folgende Aufgaben erledigen:<\/p>\n<ul>\n<li>Erstellen einer Tabelle zum Speichern der Optionen, falls noch nicht vorhanden<\/li>\n<li>Erstellen der Tabelle zum Sichern der Daten einer Tabelle<\/li>\n<li>Bereitstellen des Tabellenereignisses und des Datenmakros zum Kopieren der Daten vor der &auml;nderung beziehungsweise vor dem L&ouml;schen des Datensatzes.<\/li>\n<\/ul>\n<p>Das einzige Formular des Add-Ins dazu sieht wie in Bild 2 aus. Es bietet die folgenden Steuerelemente:<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_05\/pic_995_003.png\" alt=\"Add-In-Formular zum Anlegen von Sicherungstabellen und zum Generieren der ben&ouml;tigten Makros\" width=\"500\" height=\"520,213\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Add-In-Formular zum Anlegen von Sicherungstabellen und zum Generieren der ben&ouml;tigten Makros<\/span><\/b><\/p>\n<ul>\n<li>Das oberste Textfeld <b>txtOptionentabelle <\/b>gibt den Namen der Tabelle an, welche die Optionen f&uuml;r das Add-In speichert. Diese wird, wenn das Add-In erstmalig von einer Anwendung aus ge&ouml;ffnet wird, automatisch angelegt. Der Benutzer darf den Namen der Optionentabelle dabei beliebig anpassen.<\/li>\n<li>Das zweite Textfeld <b>txtSicherungstabelle <\/b>legt das Schema f&uuml;r die Benennung der Archivtabellen fest. Einziges fixes Element ist der Platzhalter <b>[Tabelle]<\/b>. Dieser wird beim Zusammenstellen des Tabellennamens durch den Namen der Originaltabelle ersetzt.<\/li>\n<li>Das Listenfeld <b>lstTabellen <\/b>zeigt alle Tabellen der aktuellen Datenbank an. Hier w&auml;hlen Sie die Tabelle aus, f&uuml;r die eine Archivtabelle erstellt werden soll und f&uuml;r die das Add-In die Datenmakros zum automatischen Archivieren generieren soll.<\/li>\n<li>Die Schaltfl&auml;che <b>cmdProtokollierungEinrichten <\/b>startet die wesentlichen Schritte, n&auml;mlich das Anlegen der Archivtabelle sowie die Generierung der beiden Makros.<\/li>\n<li>Das Textfeld <b>txtMakroAktualisierung <\/b>zeigt das Makro an, das Sie dem Tabellenereignis <b>Nach Aktualisierung <\/b>hinzuf&uuml;gen.<\/li>\n<li>Das Textfeld <b>txtMakroLoeschung <\/b>liefert das entsprechende Datenmakro f&uuml;r das Ereignis <b>Nach L&ouml;schung<\/b>.<\/li>\n<li>Schlie&szlig;lich gibt es noch zwei Schaltfl&auml;chen, mit denen Sie die XML-Dokumente f&uuml;r die Datenmakros in die Zwischenablage kopieren und dann f&uuml;r die Makros einsetzen k&ouml;nnen.<\/li>\n<\/ul>\n<h2>Datenmakros kopieren<\/h2>\n<p>Wenn Sie die Tabelle ausgew&auml;hlt und die Schaltfl&auml;che <b>Protokollierung einrichten <\/b>angeklickt haben, erhalten Sie die beiden ben&ouml;tigten Datenmakros mit den XML-Dokumenten aus den beiden unteren Textfeldern.<\/p>\n<p>Diese k&ouml;nnen Sie zur Ansicht oder f&uuml;r Notf&auml;lle nutzen, falls das automatische Hinzuf&uuml;gen der Datenmakros zu den Tabellen nicht gelingt.<\/p>\n<p>Und hier ist der Notfallplan: Wenn Sie beispielsweise die Datens&auml;tze der Tabelle <b>tblAnreden <\/b>archivieren m&ouml;chten, erhalten Sie mit der Konfiguration aus dem Screenshot eine neue Tabelle namens <b>tblAnreden_Archiv<\/b>.<\/p>\n<p>Kopieren Sie dann den Inhalt des Textfeldes mit dem Makro f&uuml;r den Fall der Aktualisierung in die Zwischenablage. &ouml;ffnen Sie dann die Tabelle, hier <b>tblAnreden<\/b>, beispielsweise in der Datenblattansicht.<\/p>\n<p>Nun w&auml;hlen Sie im Ribbon den Eintrag <b>Tabelle|Nach-folge-er-eignisse|Nach Aktualisierung <\/b>aus (s. Bild 3). Es erscheint ein leeres Makro, das Sie nun einfach markieren und dann per <b>Strg + C <\/b>den Inhalt der Zwischenablage einf&uuml;gen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_05\/pic_995_004.png\" alt=\"Ribbon-Befehl zum Anzeigen des Datenmakros, das durch das Tabellenereignis Nach Aktualisierung ausgel&ouml;st wird\" width=\"500\" height=\"302,1032\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Ribbon-Befehl zum Anzeigen des Datenmakros, das durch das Tabellenereignis Nach Aktualisierung ausgel&ouml;st wird<\/span><\/b><\/p>\n<p>Und siehe da: Der Generator hat tats&auml;chlich einen XML-Code zusammengestellt, der die ben&ouml;tigten Makrobefehle liefert (s. Bild 4).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_05\/pic_995_005.png\" alt=\"Frisch eingef&uuml;gtes Datenmakro\" width=\"425\" height=\"557,3295\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Frisch eingef&uuml;gtes Datenmakro<\/span><\/b><\/p>\n<p>Auf die gleiche Weise gehen Sie nun noch f&uuml;r das Datenmakro <b>Nach L&ouml;schung <\/b>vor. Damit haben Sie der Tabelle zwei Makros hinzugef&uuml;gt, die daf&uuml;r sorgen, dass die letzte Version eines Datensatzes vor einer &auml;nderung oder L&ouml;schung in der jeweiligen Archivtabelle, hier <b>tblAnreden_Archiv<\/b>, gespeichert wird.<\/p>\n<p>Aber, wie eingangs erw&auml;hnt: Normalerweise sollte das Add-In die Datenmakros automatisch hinzuf&uuml;gen.<\/p>\n<h2>Achtung: Ersetzen vorhandener Datenmakros<\/h2>\n<p>Beim Testen des Add-Ins ist aufgefallen, dass es beim &uuml;berschreiben vorhandener Datenmakros zu Problemen kommen kann. Wir sind so vorgegangen, dass wir den kompletten vorhandenen Inhalt des Datenmakros mit <b>Strg + A <\/b>markiert und diesen dann durch Bet&auml;tigen der Tastenkombination <b>Strg + C <\/b>durch den Inhalt der Zwischenablage ersetzt haben. Zumindest haben wir das gedacht! Der Inhalt wurde n&auml;mlich mitnichten ersetzt, sondern blieb einfach an Ort und Stelle. Also gehen Sie beim Ersetzen des Inhalts eines Datenmakros einfach wie folgt vor: Markieren Sie den kompletten Inhalt mit <b>Strg + A<\/b>, l&ouml;schen Sie diesen und f&uuml;gen dann den neuen Inhalt mit <b>Strg + C <\/b>aus der Zwischenablage ein.<\/p>\n<h2>Technischer Hintergrund des Add-Ins<\/h2>\n<p>In den folgenden Abschnitten schauen wir uns die technischen Hintergr&uuml;nde des Add-Ins an. Dabei arbeiten wir uns anhand des Formulars und des oben beschriebenen Ablaufs vor.<\/p>\n<p>Den Start macht dabei das Ereignis <b>Beim Laden<\/b>, das die Ereignisprozedur aus Listing 1 ausl&ouml;st. Sie ruft zun&auml;chst eine Funktion namens <b>OptionentabelleFinden <\/b>auf und &uuml;bergibt dieser einen R&uuml;ckgabeparameter namens <b>strOptionentabelle<\/b>, der modulweit wie folgt deklariert wird:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Load()\r\n     <span style=\"color:blue;\">If <\/span>OptionentabelleFinden(strOptionentabelle) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n         Me!txtOptionentabelle = strOptionentabelle\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         strOptionentabelle = \"tblOptionenArchiv\"\r\n         strOptionentabelle = InputBox(\"Keine Optionentabelle gefunden. &quot; _\r\n             &amp; &quot;Geben Sie den Namen der zu erstellenden  Tabelle ein.\", _\r\n             \"Optionentabelle fehlt\", strOptionentabelle)\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">Len<\/span>(strOptionentabelle) = 0<span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">If <\/span>OptionentabelleAnlegen(strOptionentabelle) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n                 Me!txtOptionentabelle = strOptionentabelle\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     Me!lstTabellen.RowSourceType = \"Value List\"\r\n     Me!lstTabellen.RowSource = TabellenEinlesen\r\n     Me!txtSicherungstabelle = DLookup(\"NameDerArchivtabelle\", strOptionentabelle)\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Diese Prozedur wird beim Laden des Formulars ausgel&ouml;st.<\/span><\/b><\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>strOptionentabelle<span style=\"color:blue;\"> As String<\/span><\/pre>\n<p>Die Funktion hat die Aufgabe, aus den Tabellen der Anwendung diejenige zu identifizieren, die vom Add-In als Optionentabelle definiert wurde. Diese wird nicht am Namen erkannt, sondern anhand einer speziell zu diesem Zweck zu der Tabelle hinzugef&uuml;gten Eigenschaft namens <b>Optionentabelle<\/b>. Die Funktion <b>OptionentabelleFinden <\/b>schauen wir uns weiter unten an, zun&auml;chst reicht es uns zu wissen, dass diese Funktion die Variable <b>strOptionentabelle <\/b>mit dem Namen der Tabelle f&uuml;llt &#8211; oder aber den Wert <b>False <\/b>als Funktionswert zur&uuml;ckliefert, wenn keine passende Tabelle vorhanden ist.<\/p>\n<p>Liegt eine Optionentabelle vor, tr&auml;gt die Prozedur ihren Namen in das Textfeld <b>txtOptionentabelle <\/b>ein, anderenfalls fragt sie vom Benutzer per <b>InputBox <\/b>den gew&uuml;nschten Namen f&uuml;r die Optionentabelle ab. Damit ruft die Prozedur eine weitere Funktion namens <b>OptionentabelleAnlegen <\/b>auf und &uuml;bergibt dieser den Namen der anzulegenden Tabelle. Diese Funktion (siehe weiter unten) legt die Tabelle an und liefert im Erfolgsfall den Wert <b>True <\/b>zur&uuml;ck.<\/p>\n<p>Schlie&szlig;lich stellt die Prozedur die Eigenschaft <b>Datensatzherkunft <\/b>f&uuml;r das Listenfeld <b>lstTabellen <\/b>auf einen Wert ein, den die Funktion <b>TabellenEinlesen <\/b>liefert. Das Ergebnis dieser Funktion ist eine kommaseparierte Liste der Tabellennamen der aktuellen Anwendung. Schlie&szlig;lich liest die Prozedur noch den aktuellen Ausdruck f&uuml;r die Erstellung der Archivtabellen aus dem Feld <b>NameDerArchivtabelle <\/b>aus der Optionentabelle aus und tr&auml;gt diesen in das Textfeld <b>txtSicherungstabelle <\/b>ein.<\/p>\n<h2>Optionstabelle erstellen<\/h2>\n<p>In der Regel m&uuml;ssen Sie einer Anwendung immer erst eine Optionentabelle hinzuf&uuml;gen, sofern diese noch nicht vorhanden ist. Dies erledigt die Funktion <b>OptionentabelleAnlegen<\/b> aus Listing 2. Diese erwartet den Namen der zu erstellenden Tabelle als Parameter. Die Funktion erstellt zun&auml;chst die Tabelle mit dem angegebenen Namen als neues <b>TableDef<\/b>-Objekt und f&uuml;gt dieser dann das Feld <b>ArchivierungDeaktiviert <\/b>sowie das Feld <b>NameDerArchivtabelle <\/b>hinzu. Dies geschieht in zwei Schritten &#8211; dem eigentlichen Erstellen mit der Methode <b>CreateField <\/b>des <b>TableDef<\/b>-Objekts und dem Anh&auml;ngen an die <b>Fields<\/b>-Auflistung der Tabelle. Danach h&auml;ngt die Funktion die Tabelle selbst an die <b>TableDefs<\/b>-Auflistung an.<\/p>\n<pre><span style=\"color:blue;\">Private Function <\/span>OptionentabelleAnlegen(strOptionentabelle<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Boolean<\/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>tdf<span style=\"color:blue;\"> As <\/span>DAO.TableDef\r\n     <span style=\"color:blue;\">Dim <\/span>prp<span style=\"color:blue;\"> As <\/span>DAO.Property\r\n     <span style=\"color:blue;\">Dim <\/span>fld<span style=\"color:blue;\"> As <\/span>DAO.Field\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> tdf = db.CreateTableDef(strOptionentabelle)\r\n     <span style=\"color:blue;\">Set<\/span> fld = tdf.CreateField(\"ArchivierungDeaktiviert\", dbBoolean)\r\n     tdf.Fields.Append fld\r\n     <span style=\"color:blue;\">Set<\/span> fld = tdf.CreateField(\"NamederArchivtabelle\", dbText, 255)\r\n     tdf.Fields.Append fld\r\n     db.TableDefs.Append tdf\r\n     <span style=\"color:blue;\">Set<\/span> prp = tdf.CreateProperty(\"Optionentabelle\", dbBoolean, <span style=\"color:blue;\">True<\/span>)\r\n     tdf.Properties.Append prp\r\n     db.TableDefs.Refresh\r\n     Application.RefreshDatabaseWindow\r\n     db.Execute \"INSERT INTO \" & strOptionentabelle _\r\n         & \"(ArchivierungDeaktiviert, NameDerArchivTabelle)  &quot; _\r\n         &amp; &quot;VALUES(0, ''[Tabelle]_Archiv'')\", dbFailOnError\r\n     OptionentabelleAnlegen = <span style=\"color:blue;\">True<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><!--30percent--><\/p>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Anlegen der Optionentabelle<\/span><\/b><\/p>\n<p>Damit das Add-In sp&auml;ter auf irgendeine Weise die neu erstellte Optionentabelle identifizieren kann, f&uuml;gen wir dieser noch eine benutzerdefinierte Eigenschaft hinzu. Dazu erstellt die Funktion mit der <b>CreateProperty<\/b>-Funktion eine neue Property namens <b>Optionentabelle <\/b>und stellt den Datentyp auf <b>Boolean <\/b>ein. Danach h&auml;ngt sie die <b>Property <\/b>an die <b>Properties<\/b>-Auflistung an. Die <b>Refresh<\/b>-Methode aktualisiert die <b>TableDefs<\/b>-Auflistung und die Methode <b>RefreshDatabaseWindow <\/b>sorgt daf&uuml;r, dass die neue Tabelle gleich im Navigationsbereich erscheint.<\/p>\n<p>Schlie&szlig;lich f&uuml;gt die Funktion direkt noch einen einzigen Datensatz zur Tabelle hinzu und stellt diesen auf den Wert <b>False <\/b>ein. Die Tabelle sieht nun wie in Bild 5 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_05\/pic_995_002.png\" alt=\"Tabelle zum Speichern einer Option\" width=\"420\" height=\"160,137\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Tabelle zum Speichern einer Option<\/span><\/b><\/p>\n<h2>Optionentabelle auffinden<\/h2>\n<p>Nat&uuml;rlich m&uuml;ssen wir dem Add-In auch eine Funktion hinzuf&uuml;gen, mit der dieses beim Starten pr&uuml;fen kann, ob die ben&ouml;tigte Optionentabelle bereits vorhanden ist. Dies erledigt die Funktion <b>OptionentabelleFinden<\/b> aus Listing 3. Diese erwartet ebenfalls einen Parameter namens <b>strOptionentabelle<\/b>, dieser soll jedoch mit dem Namen der gefundenen Tabelle als R&uuml;ckgabewert gef&uuml;llt werden. Au&szlig;erdem gibt der Funktionswert selbst einen <b>Boolean<\/b>-Wert zur&uuml;ck, der aussagt, ob eine Optionentabelle gefunden wurde.<\/p>\n<pre><span style=\"color:blue;\">Private Function <\/span>OptionentabelleFinden(strOptionentabelle<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Boolean<\/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>tdf<span style=\"color:blue;\"> As <\/span>DAO.TableDef\r\n     <span style=\"color:blue;\">Dim <\/span>strTemp<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>bolOptionentabelle<span style=\"color:blue;\"> As Boolean<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     For Each tdf In db.TableDefs\r\n         On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n         strTemp = tdf.Properties(\"Optionentabelle\").Name\r\n         bolOptionentabelle = Err.Number = 0 And <span style=\"color:blue;\">Not<\/span> (<span style=\"color:blue;\">Left<\/span>(tdf.Name, 1) = \"~\")\r\n         <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n         <span style=\"color:blue;\">If <\/span>bolOptionentabelle = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n             strOptionentabelle = tdf.Name\r\n             OptionentabelleFinden = <span style=\"color:blue;\">True<\/span>\r\n             <span style=\"color:blue;\">Exit Function<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> tdf\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Auffinden einer bereits vorhandenen Optionentabelle<\/span><\/b><\/p>\n<p>Die Funktion <b>OptionenTabelleFinden <\/b>durchl&auml;uft alle Tabellen der Datenbank und tr&auml;gt bei deaktivierter Fehlerbehandlung den Wert der Property <b>Optionentabelle <\/b>der aktuellen Tabelle in die Variable <b>strTemp <\/b>ein. L&ouml;st dies einen Fehler aus, hat <b>Err.Number <\/b>danach nicht mehr den Wert <b>0 <\/b>und es handelt sich nicht um die passende Tabelle. Erst wenn diese Eigenschaft f&uuml;r eine Tabelle gefunden werden konnte und somit <b>Err.Number <\/b>den Wert <b>0 <\/b>aufweist, durchl&auml;uft die Funktion den Teil innerhalb der <b>If&#8230;Then<\/b>-Bedingung. In diesem Fall stellt die Prozedur den Wert des R&uuml;ckgabeparameters <b>strOptionentabelle <\/b>auf den Namen der aktuell untersuchten Tabelle ein und legt als R&uuml;ckgabewert der Funktion den Wert <b>True <\/b>fest.<\/p>\n<p>Au&szlig;erdem wird die Funktion an dieser Stelle beendet, da die Optionentabelle ja hier gefunden wurde.<\/p>\n<h2>Tabellen der Host-Datenbank einlesen<\/h2>\n<p>Zur Vervollst&auml;ndigung des Starts des Formulars fehlt noch die Funktion <b>TabellenEinlesen<\/b>, die eine Liste der Tabellen der Host-Datenbank, von der aus Sie das Add-In starten, enth&auml;lt. Diese Liste wird dann der Datensatzherkunft des Listenfeldes des Formulars zugewiesen.<\/p>\n<p>Sie werden nun sicher fragen, warum man nicht einfach eine Abfrage auf Basis der Tabelle <b>MSysObjects <\/b>erstellt. Die Frage ist leicht zu beantworten: Das Formular befindet sich ja in der Add-In-Datenbank und kann somit nur an Tabellen oder Abfragen dieser Datenbank gebunden werden &#8211; das Gleiche gilt nat&uuml;rlich auch f&uuml;r das Listenfeld. Daher m&uuml;ssen wir uns manuell an diese Aufgabe begeben.<\/p>\n<p>Die Funktion aus Listing 4 f&uuml;llt ein <b>Database<\/b>-Objekt mit einem Verweis auf die Add-In-Datenbank, den wir mit der Funktion <b>CodeDb <\/b>einlesen. Dann erstellt sie ein Recordset auf Basis der Tabelle <b>MSysObjects<\/b>, das die Namen aller Tabellen liefert, die lokal vorliegen (das Feld <b>Connect <\/b>hat den Wert <b>Null<\/b>), die keine Systemtabelle sind (Name beginnt nicht mit <b>MSys<\/b>) und die nicht als Hintergrundtabelle f&uuml;r Anlage- oder mehrwertige Felder dienen (Name beginnt nicht mit <b>~<\/b>) &#8211; all dies noch nach dem Feld <b>Name <\/b>sortiert.<\/p>\n<pre><span style=\"color:blue;\">Private Function <\/span>TabellenEinlesen()<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>strTabellen<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CodeDb\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT Name FROM MSysObjects WHERE Connect IS NULL &quot; _\r\n          &amp; &quot;And <span style=\"color:blue;\">Not<\/span> Name LIKE ''~*'' And <span style=\"color:blue;\">Not<\/span>  Name LIKE ''MSys*'' ORDER BY Name\", dbOpenDynaset)\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n         strTabellen = strTabellen & rst!Name & \";\"\r\n         rst.Move<span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n     TabellenEinlesen = strTabellen\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Einlesen der Tabellen der Host-Anwendung<\/span><\/b><\/p>\n<p>Die folgende <b>Do While<\/b>-Schleife durchl&auml;uft das Recordset und schreibt alle Tabellennamen durch Semikola getrennt in die Variable <b>strTabellen<\/b>, die schlie&szlig;lich als Funktionswert zur&uuml;ckgegeben wird.<\/p>\n<h2>Sicherungstabelle erstellen<\/h2>\n<p>Damit k&ouml;nnen wir uns der Schaltfl&auml;che <b>cmdProtokollierungEinrichten<\/b> zuwenden. Diese l&ouml;st die Ereignisprozedur aus Listing 5 aus. Die Prozedur pr&uuml;ft zun&auml;chst, ob der Benutzer im Listenfeld <b>lstTabellen <\/b>die zu behandelnde Tabelle ausgew&auml;hlt hat und bricht die Prozedur im Zweifelsfall ab.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdProtokollierungEinrichten_Click()\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>tdf<span style=\"color:blue;\"> As <\/span>DAO.TableDef\r\n     <span style=\"color:blue;\">Dim <\/span>fld<span style=\"color:blue;\"> As <\/span>DAO.Field\r\n     <span style=\"color:blue;\">Dim <\/span>strTabelle<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strTabelleNeu<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strMakros<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">If <\/span>IsNull(Me!lstTabellen)<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"W&auml;hlen Sie eine Tabelle aus.\"\r\n         <span style=\"color:blue;\">Exit Sub<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     strTabelle = Me!lstTabellen\r\n     strTabelleNeu = <span style=\"color:blue;\">Replace<\/span>(Me!txtSicherungstabelle, \"[Tabelle]\", strTabelle)\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> tdf = db.TableDefs(strTabelleNeu)\r\n     <span style=\"color:blue;\">If <\/span>Err.Number = 0<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Die Tabelle ''\" & strTabelleNeu & \"'' ist bereits vorhanden.\"\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n         db.Execute \"SELECT * INTO \" & strTabelleNeu & \" FROM \" & strTabelle _\r\n             & \" WHERE 1 = 2\", dbFailOnError\r\n         db.TableDefs.Refresh\r\n         Application.RefreshDatabaseWindow\r\n         <span style=\"color:blue;\">Set<\/span> tdf = db.TableDefs(strTabelleNeu)\r\n         <span style=\"color:blue;\">Set<\/span> fld = tdf.CreateField(\"GeaendertAm\", dbDate)\r\n         tdf.Fields.Append fld\r\n         <span style=\"color:blue;\">Set<\/span> fld = tdf.CreateField(\"GeloeschtAm\", dbDate)\r\n         tdf.Fields.Append fld\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     Me!txtMakroAktualisierung = MakrosErstellen(strTabelle, strTabelleNeu, 1, 1)\r\n     Me!txtMakroLoeschung = MakrosErstellen(strTabelle, strTabelleNeu, 2, 2)\r\n     If <span style=\"color:blue;\">MsgBox<\/span>(\"Datenmakros in die Tabelle einf&uuml;gen &quot; _\r\n                  &quot;Dies &uuml;berschreibt bereits vorhandene Datenmakros.\", vbYesNo) = vbYes Then\r\n         strMakros = MakrosErstellen(strTabelle, strTabelleNeu, 1, 2)\r\n         MakrosInZieldatenbank strMakros, strTabelle\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Die Datenmakros k&ouml;nnen nun kopiert und zur Tabelle ''\" & strTabelle _\r\n             & \"'' hinzugef&uuml;gt werden.\"\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: Einrichten der Archivtabelle<\/span><\/b><\/p>\n<p>Anderenfalls liest sie den Namen der gew&auml;hlten Tabelle in die Variable <b>strTabelle <\/b>ein. Eine weitere Variable namens <b>strTabelleNeu <\/b>f&uuml;llt die Prozedur mit dem Namen der zu erstellenden Tabelle.<\/p>\n<p>Dazu verwendet sie die Vorgabe aus der Optionentabelle, zum Beispiel <b>[Tabelle]_Archiv<\/b>, und ersetzt hier <b>[Tabelle]<\/b> durch den tats&auml;chlichen Namen der zu archivierenden Tabelle. Im Falle der Tabelle <b>tblAnreden <\/b>w&uuml;rde hier etwa <b>tblAnreden_Archiv <\/b>herauskommen.<\/p>\n<p>Danach versucht die Tabelle, ein <b>TableDef<\/b>-Objekt auf Basis der zu erstellenden Tabelle zu referenzieren. W&uuml;rde dies keinen Fehler ausl&ouml;sen, hie&szlig;e das, dass die Tabelle bereits vorhanden ist. In diesem Fall gibt die Prozedur eine entsprechende Meldung aus.<\/p>\n<p>Anderenfalls erstellt die Prozedur die Archivtabelle neu, indem sie die vorhandene Tabelle mit einer <b>SELECT INTO<\/b>-Anweisung in eine neue Tabelle kopiert. Durch das Kriterium <b>1=2 <\/b>werden dabei keine Datens&auml;tze kopiert, sondern es wird nur die Tabellenstruktur angelegt. Die folgenden beiden Anweisungen aktualisieren die <b>TableDefs<\/b>-Auflistung und den Navigationsbereich. Nun wird die <b>TableDef<\/b>-Variable <b>tdf <\/b>mit einem Verweis auf die neu erstellte Tabelle gef&uuml;llt, damit die Prozedur zwei weitere notwendige Felder hinzuf&uuml;gen kann, n&auml;mlich <b>Geaendert-Am <\/b>und <b>GeloeschtAm<\/b>.<\/p>\n<p>Dazu verwendet sie jeweils zun&auml;chst die <b>CreateField<\/b>-Methode des <b>TableDef<\/b>-Objekts, um das so erstellte und mit <b>fld <\/b>referenzierte Feld dann mit der <b>Append<\/b>-Methode an die <b>Fields<\/b>-Auflistung der Tabelle anzuh&auml;ngen. Dies geschieht f&uuml;r beide Felder analog.<\/p>\n<p>Nun folgt der interessante Teil: Die Funktion <b>MakrosErstellen <\/b>erh&auml;lt den Namen der alten und der neuen Tabelle sowie zwei weitere Parameter, die angeben, welche Makros erstellt werden sollen. Wenn das <b>Nach Aktualisierung<\/b>-Makro erstellt werden soll, erhalten <b>int1 <\/b>und <b>int2 <\/b>jeweils den Wert <b>1<\/b>, f&uuml;r das <b>Nach L&ouml;schung<\/b>-Makro erhalten beide Parameter den Wert <b>2<\/b>. Das Ergebnis des ersten Aufrufs mit dem Wert <b>1 <\/b>f&uuml;r <b>int1 <\/b>und <b>int2 <\/b>landet im Textfeld <b>txtMakroAktualisierung<\/b>, das Ergebnis f&uuml;r den Wert <b>2 <\/b>f&uuml;r die beiden Parameter <b>int1 <\/b>und <b>int2  <\/b>im Textfeld <b>txtMakroLoeschung<\/b>.<\/p>\n<p>Das folgende Meldungsfenster fragt den Benutzer, ob die Datenmakros direkt in die Originaltabelle eingef&uuml;gt werden sollen. Dies ist wichtig, weil die Tabellen ja immerhin auch bereits Datenmakros enthalten k&ouml;nnen. In diesem Fall k&ouml;nnten Sie das Datenmakro aus dem Textfeld kopieren, das Datenmakro der Tabelle &ouml;ffnen und den Inhalt der Zwischenablage hinter dem vorhandenen Makro einf&uuml;gen.<\/p>\n<p>Wenn die Datenmakros direkt in die Tabelle eingef&uuml;gt werden sollen, ruft die Prozedur wiederum die Prozedur <b>MakrosErstellen <\/b>auf, diesmal aber mit dem Wert <b>1 <\/b>f&uuml;r den Parameter <b>int1 <\/b>und den Wert <b>2 <\/b>f&uuml;r den Parameter <b>int2<\/b>. Warum dies so ist, wird gleich bei der Beschreibung der Funktion <b>MakrosErstellen <\/b>deutlich. Dann ruft die Prozedur die Routine <b>MakroInZieldatenbank <\/b>auf und &uuml;bergibt den Makro-Text sowie den Namen der Zieltabelle als Parameter. Diese Prozedur erl&auml;utern wir weiter unten.<\/p>\n<p>Damit ist die Tabelle bereits mit den Makros ausgestattet und die Archivtabelle erstellt. Bei &auml;nderungen oder L&ouml;schungen in der Originaltabelle wird der urspr&uuml;ngliche Datensatz nun direkt in die Archivtabelle geschrieben. Wichtig ist an dieser Stelle, das Verhalten einmal zu testen. Sollten die Datens&auml;tze nicht in der Zieltabelle erscheinen, klicken Sie im Ribbon auf Datei und dann auf Informationen. Dort sollte nun eine Schaltfl&auml;che namens <b>Anwendungsprotokolltabelle anzeigen <\/b>erscheinen (s. Bild 6).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_05\/pic_995_006.png\" alt=\"Schaltfl&auml;che zum &ouml;ffnen der Anwendungsprotokolltabelle\" width=\"650\" height=\"273,4193\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Schaltfl&auml;che zum &ouml;ffnen der Anwendungsprotokolltabelle<\/span><\/b><\/p>\n<p>Damit &ouml;ffnen Sie die Tabelle aus Bild 7. Hier finden Sie eine Liste aller bisher aufgetretenen Fehler beim Ausf&uuml;hren von Datenmakros. Hier suchen Sie zun&auml;chst nach Eintr&auml;gen, deren Feld <b>SourceObjekt <\/b>den Namen der Tabelle plus dem Zusatz <b>AfterUpdate <\/b>oder <b>AfterDelete <\/b>enth&auml;lt.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2015_05\/pic_995_007.png\" alt=\"Protokollierung von Fehlern bei der Ausf&uuml;hrung von Datenmakros\" width=\"700\" height=\"143,7608\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Protokollierung von Fehlern bei der Ausf&uuml;hrung von Datenmakros<\/span><\/b><\/p>\n<p>Hier erhalten Sie dann im Feld <b>Description <\/b>Informationen &uuml;ber die aufgetretenen Fehler und k&ouml;nnen diese analysieren. Meist treten solche Fehler in Zusammenhang mit der Verwendung von Memo-, Anlage- oder mehrwertigen Feldern auf oder wenn Access die Feldnamen beim Interpretieren des Makros als &uuml;bersetzung englischer Schl&uuml;sselw&ouml;rter erkennt.<\/p>\n<h2>Makro per VBA erstellen<\/h2>\n<p>Die Funktion <b>MakrosErstellen <\/b>stellt den XML-Code f&uuml;r die Datenmakros zusammen (s. Listing 6). Dabei gibt es verschiedene Varianten.<\/p>\n<pre><span style=\"color:blue;\">Private Function <\/span>MakrosErstellen(strTabelle<span style=\"color:blue;\"> As String<\/span>, strTabelleNeu<span style=\"color:blue;\"> As String<\/span>, _\r\n         int1<span style=\"color:blue;\"> As Integer<\/span>, int2<span style=\"color:blue;\"> As Integer<\/span>)<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strMakro<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>tdf<span style=\"color:blue;\"> As <\/span>DAO.TableDef\r\n     <span style=\"color:blue;\">Dim <\/span>fld<span style=\"color:blue;\"> As <\/span>DAO.Field\r\n     <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> tdf = db.TableDefs(strTabelle)\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(strOptionentabelle) = 0<span style=\"color:blue;\"> Then<\/span>\r\n         OptionentabelleFinden strOptionentabelle\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     strMakro = \"&lt;xml version=\"\"1.0\"\" encoding=\"\"UTF-16\"\" standalone=\"\"no\"\"&gt;\"\r\n     strMakro = strMakro & \"&lt;DataMacros  &quot; _\r\n         &quot;xmlns=\"\"http:\/\/schemas.microsoft.com\/office\/accessservices\/2009\/11\/application\"\"&gt;\"\r\n     For i = int1 To int2\r\n         <span style=\"color:blue;\">If <\/span>i = 1<span style=\"color:blue;\"> Then<\/span>\r\n             strMakro = strMakro & \"&lt;DataMacro Event=\"\"AfterUpdate\"\"&gt;\"\r\n         <span style=\"color:blue;\">Else<\/span>\r\n            strMakro = strMakro & \"&lt;DataMacro Event=\"\"AfterDelete\"\"&gt;\"\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         strMakro = strMakro & \"&lt;Statements&gt;\"\r\n         strMakro = strMakro & \"&lt;LookUpRecord&gt;\"\r\n         strMakro = strMakro & \"&lt;Data&gt;\"\r\n         strMakro = strMakro & \"&lt;Reference&gt;\" & strOptionentabelle & \"&lt;\/Reference&gt;\"\r\n         strMakro = strMakro & \"&lt;\/Data&gt;\"\r\n         strMakro = strMakro & \"&lt;Statements&gt;\"\r\n         strMakro = strMakro & \"&lt;ConditionalBlock&gt;\"\r\n         strMakro = strMakro & \"&lt;If&gt;\"\r\n         strMakro = strMakro & \"&lt;Condition&gt;[\" & strOptionentabelle _\r\n               & \"].[ArchivierungDeaktiviert]=-1&lt;\/Condition&gt;\"\r\n         strMakro = strMakro & \"&lt;Statements&gt;\"\r\n         strMakro = strMakro & \"&lt;Action Name=\"\"LogEvent\"\"&gt;\"\r\n         strMakro = strMakro & \"&lt;Argument Name=\"\"Description\"\"&gt;&quot; _\r\n             &amp; &quot;Archivierung deaktiviert&lt;\/Argument&gt;\"\r\n         strMakro = strMakro & \"&lt;\/Action&gt;\"\r\n         strMakro = strMakro & \"&lt;Action Name=\"\"StopMacro\"\"\/&gt;\"\r\n         strMakro = strMakro & \"&lt;\/Statements&gt;\"\r\n         strMakro = strMakro & \"&lt;\/If&gt;\"\r\n         strMakro = strMakro & \"&lt;\/ConditionalBlock&gt;\"\r\n         strMakro = strMakro & \"&lt;\/Statements&gt;\"\r\n         strMakro = strMakro & \"&lt;\/LookUpRecord&gt;\"\r\n         strMakro = strMakro & \"&lt;CreateRecord&gt;\"\r\n         strMakro = strMakro & \"&lt;Data&gt;\"\r\n         strMakro = strMakro & \"&lt;Reference&gt;\" & strTabelleNeu & \"&lt;\/Reference&gt;\"\r\n         strMakro = strMakro & \"&lt;\/Data&gt;\"\r\n         strMakro = strMakro & \"&lt;Statements&gt;\"<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 6: Zusammenstellen der Makros (Teil 1)<\/span><\/b><\/p>\n<p>Im einfachsten Fall erstellt man ein XML-Dokument, das gleich beide Datenmakros f&uuml;r die Aktionen <b>Nach Aktualisierung <\/b>und <b>Nach L&ouml;schung <\/b>enth&auml;lt. Es kann aber auch sein, dass die Tabelle bereits Datenmakros f&uuml;r die Tabellenereignisse enth&auml;lt.<\/p>\n<p>In diesem Fall sollen die Tabellenmakros nicht direkt in die Tabelle geschrieben werden, dass diese sonst die vorhandenen Makros &uuml;berschreiben w&uuml;rden. Stattdessen sollen die Datenmakros f&uuml;r die Aktionen <b>Nach Aktualisierung <\/b>und <b>Nach L&ouml;schung <\/b>einzeln zusammengestellt und als XML-Dokumente in den beiden unteren Textfeldern des Formulars bereitgestellt werden, damit der Benutzer diese &uuml;ber die Zwischenablage zu den bestehenden Makros hinzuf&uuml;gen kann.<\/p>\n<p>Nun hat die Funktion <b>MakrosErstellen <\/b>ja diese omin&ouml;sen beiden Parameter <b>int1 <\/b>und <b>int2<\/b>. Der Hintergrund ist einfach: Die XML-Dokumente bestehen jeweils aus einem Kopf, der wie folgt aussieht:<\/p>\n<pre>&lt;xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"&gt;\r\n&lt;DataMacros xmlns=\"http:\/\/schemas.microsoft.com\/office\/accessservices\/2009\/11\/application\"&gt;<\/pre>\n<p>Danach folgen die Datenmakros: also entweder nur das Makro <b>Nach Aktualisierung<\/b>, nur <b>Nach L&ouml;schung <\/b>oder <b>Nach Aktualisierung <\/b>und <b>Nach L&ouml;schung<\/b>.<\/p>\n<p>Der Teil f&uuml;r <b>Nach Aktualisierung <\/b>sieht verk&uuml;rzt so aus:<\/p>\n<pre>&lt;DataMacro Event=\"AfterUpdate\"&gt;\r\n   &lt;Statements&gt;\r\n     &lt;LookUpRecord&gt;\r\n       ...\r\n     &lt;\/LookUpRecord&gt;\r\n     &lt;CreateRecord&gt;\r\n         ...\r\n     &lt;\/CreateRecord&gt;\r\n   &lt;\/Statements&gt;\r\n&lt;\/DataMacro&gt;<\/pre>\n<p>Und dies ist der Teil f&uuml;r <b>Nach L&ouml;schung<\/b>:<\/p>\n<pre>&lt;DataMacro Event=\"AfterDelete\"&gt;\r\n   &lt;Statements&gt;\r\n     &lt;LookUpRecord&gt;\r\n       ...\r\n     &lt;\/LookUpRecord&gt;\r\n     &lt;CreateRecord&gt;\r\n         ...\r\n     &lt;\/CreateRecord&gt;\r\n   &lt;\/Statements&gt;\r\n&lt;\/DataMacro&gt;<\/pre>\n<p>Schlie&szlig;lich folgt der Fu&szlig;teil des XML-Dokuments:<\/p>\n<pre>&lt;\/DataMacros&gt;<\/pre>\n<p>Sie sehen: die beiden Hauptelemente des XML-Dokuments sehen fast genau gleich aus. Daher wollen wir einige Zeilen Code sparen und haben um das Hinzuf&uuml;gen dieser Codezeilen eine <b>For&#8230;Next<\/b>-Schleife aufgebaut. Diese l&auml;uft entweder von <b>1 <\/b>bis <b>1<\/b>, von <b>2 <\/b>bis <b>2 <\/b>oder von <b>1 <\/b>bis <b>2 <\/b>&#8211; je nachdem, welche Werte mit den Parametern <b>int1 <\/b>und <b>int2 <\/b>&uuml;bergeben wurden.<\/p>\n<p>Wird die Schleife das erste Mal durchlaufen, hat <b>i <\/b>den Wert <b>1 <\/b>und es wird neben den &uuml;brigen Elementen das folgende Element zum Makro hinzugef&uuml;gt:<\/p>\n<pre>&lt;DataMacro Event=\"AfterUpdate\"&gt;<\/pre>\n<p>Hat <b>i <\/b>den Wert <b>2<\/b>, erg&auml;nzt die Prozedur dieses Element:<\/p>\n<pre>&lt;DataMacro Event=\"AfterDelete\"&gt;<\/pre>\n<p>Innerhalb der Schleife gibt es noch eine weitere Schleife, welche dynamisch die Makrobefehle f&uuml;r das &uuml;bertragen der Feldinhalte des ge&auml;nderten oder gel&ouml;schten Datensatzes in die Archivtabelle zusammenstellt. Dazu durchl&auml;uft eine <b>For Each<\/b>-Schleife die <b>Fields<\/b>-Auflistung eines <b>TableDef<\/b>-Objekts auf Basis der betroffenen Tabelle (s. Listing 7). Sie schlie&szlig;t gleich alle Felder mit den Datentypen Memo, Anlagefeld und mehrwertiges Feld aus und f&uuml;gt dann etwa die folgende Zeile je Feld hinzu:<\/p>\n<pre>         For Each fld In tdf.Fields\r\n             Select Case fld.Type\r\n                 <span style=\"color:blue;\">Case <\/span>dbMemo, dbComplexByte, dbComplexDecimal, dbComplexDouble, dbComplexGUID, dbComplexInteger, _\r\n                     dbComplexLong, dbComplexSingle, dbComplexText, dbAttachment\r\n                 <span style=\"color:blue;\">Case Else<\/span>\r\n                     strMakro = strMakro & \"&lt;Action Name=\"\"SetField\"\"&gt;\"\r\n                     strMakro = strMakro & \"&lt;Argument Name=\"\"Field\"\"&gt;\" _\r\n                         & fld.Name & \"&lt;\/Argument&gt;\"\r\n                     strMakro = strMakro & \"&lt;Argument Name=\"\"Value\"\"&gt;[Old].[\" _\r\n                         & fld.Name & \"]&lt;\/Argument&gt;\"\r\n                     strMakro = strMakro & \"&lt;\/Action&gt;\"\r\n             <span style=\"color:blue;\">End Select<\/span>\r\n         <span style=\"color:blue;\">Next<\/span> fld\r\n         <span style=\"color:blue;\">If <\/span>i = 1<span style=\"color:blue;\"> Then<\/span>\r\n             strMakro = strMakro & \"&lt;Action Name=\"\"SetField\"\"&gt;&lt;Argument Name=\"\"Field\"\"&gt;&quot; _\r\n                 &amp; &quot;GeaendertAm&lt;\/Argument&gt; &lt;Argument Name=\"\"Value\"\"&gt;Now()&lt;\/Argument&gt;&lt;\/Action&gt;&lt;\/Statements&gt;\"\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             strMakro = strMakro & \"&lt;Action Name=\"\"SetField\"\"&gt;&lt;Argument Name=\"\"Field\"\"&gt;&quot; _\r\n                 &amp; &quot;GeloeschtAm&lt;\/Argument&gt; &lt;Argument Name=\"\"Value\"\"&gt;Now()&lt;\/Argument&gt;&lt;\/Action&gt;&lt;\/Statements&gt;\"\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         strMakro = strMakro & \"&lt;\/CreateRecord&gt;\"\r\n         strMakro = strMakro & \"&lt;\/Statements&gt;\"\r\n         strMakro = strMakro & \"&lt;\/DataMacro&gt;\"\r\n     <span style=\"color:blue;\">Next<\/span> i\r\n     strMakro = strMakro & \"&lt;\/DataMacros&gt;\"\r\n     MakrosErstellen = strMakro\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 7: Zusammenstellen der Makros (Teil 2)<\/span><\/b><\/p>\n<pre>&lt;Action Name=\"SetField\"&gt;\r\n   &lt;Argument Name=\"Field\"&gt;AnredeID&lt;\/Argument&gt;\r\n   &lt;Argument Name=\"Value\"&gt;[Old].[AnredeID]&lt;\/Argument&gt;\r\n&lt;\/Action&gt;<\/pre>\n<p>Schlie&szlig;lich f&uuml;gt die Funktion noch die &uuml;brigen Zeilen hinzu und gibt das zusammengesetzte XML-Dokument f&uuml;r das oder die Makros an die aufrufende Routine zur&uuml;ck.<\/p>\n<h2>Weitere Prozeduren<\/h2>\n<p>Es fehlen noch drei kleinere Prozeduren. Die erste wird durch das Ereignis <b>Nach Aktualisierung<\/b> ausgel&ouml;st, wenn Sie die Benennungskonvention f&uuml;r die Archivtabelle im Textfeld <b>txtSicherungstabelle <\/b>&auml;ndern. Die Prozedur schreibt den neuen Wert in die Optionentabelle, deren Name im Textfeld <b>txtOptionentabelle <\/b>angezeigt wird:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>txtSicherungstabelle_AfterUpdate()\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     db.Execute \"UPDATE \" & Me!txtOptionentabelle _\r\n         & \" SET NameDerArchivtabelle = ''\" _\r\n         & Me!txtSicherungstabelle & \"''\", dbFailOnError\r\n     <span style=\"color:blue;\">Set<\/span> db = Nothing\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Zwei weitere Prozeduren l&ouml;sen Sie aus, wenn Sie auf die Schaltfl&auml;chen <b>cmdMakroAktualisierungZwischenablage <\/b>beziehungsweise <b>cmdMakroLoeschungZwischenablage <\/b>klicken. Dies kopiert den Inhalt des jeweils dar&uuml;ber befindlichen Textfeldes mit der Routine <b>InZwischenablage <\/b>in die Zwischenablage:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdMakroAktualisierungZwischenablage_Click()\r\n     Inzwischenablage Me!txtMakroAktualisierung\r\n<span style=\"color:blue;\">End Sub<\/span>\r\n<span style=\"color:blue;\">Private Sub <\/span>cmdMakroLoeschungZwischenablage_Click()\r\n     Inzwischenablage Me!txtMakroLoeschung\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Diese Prozedur finden Sie samt der ben&ouml;tigten API-Funktionen und -Deklarationen im Modul <b>mdlZwischenablage<\/b>.<\/p>\n<h2>Umr&uuml;sten der Datenbank zum Add-In<\/h2>\n<p>Damit das Formular <b>frmAddIn <\/b>&uuml;ber den Ribbon-Eintrag <b>Datenbanktools|Add-Ins|Add-Ins|Tabellenhistorie <\/b>aufgerufen werden kann, enth&auml;lt die Datenbank eine Tabelle namens <b>USysRegInfo <\/b>mit den Informationen f&uuml;r die Installation in Form eines Add-Ins. Damit k&ouml;nnen Sie die Datenbank &uuml;ber den Add-In-Manager (Ribbon-Eintrag <b>Datenbanktools|Add-Ins|Add-In-Manager<\/b>) als Add-In zu Access hinzuf&uuml;gen.<\/p>\n<h2>Zusammenfassung und Ausblick<\/h2>\n<p>Die hier vorgestellte Add-In-L&ouml;sung hilft dabei, Tabellen f&uuml;r eine automatische Archivierung der vorherigen Version ge&auml;nderter oder gel&ouml;schter Datens&auml;tze auszustatten. Dabei legt sie erstens die Archivtabelle an und zweitens zwei Datenmakros, die daf&uuml;r sorgen, dass die aktuellen Versionen eines Datensatzes vor der &auml;nderung oder L&ouml;schung in der Archivtabelle gespeichert werden.<\/p>\n<p>Mit Formularen wie im Beitrag <b>Ge&auml;nderte Daten archivieren<\/b> (<b>www.access-im-unternehmen.de\/925<\/b>) k&ouml;nnen Sie die so gesicherten Datens&auml;tze sp&auml;ter wieder herstellen.<\/p>\n<h3>Downloads zu diesem Beitrag<\/h3>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>Tabellenhistorie.accda<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/{192C5DBA-6D37-471C-B756-9F2F2DEB0043}\/aiu_995.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Die neuen Tabellenereignisse, die mit Access 2010 eingef&uuml;hrt wurden, erlauben die automatische Sicherung von Tabellendaten vor der Durchf&uuml;hrung von &Auml;nderungen an den Datens&auml;tzen. Dazu legen Sie entsprechende Datenmakros an, die durch die Tabellenereignisse ausgel&ouml;st werden. Au&szlig;erdem ben&ouml;tigen Sie eine Tabelle, welche die ge&auml;nderten Datens&auml;tze speichert. Wenn Sie beides f&uuml;r mehrere Tabellen durchf&uuml;hren wollen, ist dies eine Menge Handarbeit. Grund genug, diesen Vorgang zu automatisieren.<\/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":[662015,66052015,44000021],"tags":[],"class_list":["post-55000995","post","type-post","status-publish","format-standard","hentry","category-662015","category-66052015","category-Tabellen_und_Datenmodellierung"],"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>&Auml;nderungshistorie implantieren - 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\/Aenderungshistorie_implantieren\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"&Auml;nderungshistorie implantieren\" \/>\n<meta property=\"og:description\" content=\"Die neuen Tabellenereignisse, die mit Access 2010 eingef&uuml;hrt wurden, erlauben die automatische Sicherung von Tabellendaten vor der Durchf&uuml;hrung von &Auml;nderungen an den Datens&auml;tzen. Dazu legen Sie entsprechende Datenmakros an, die durch die Tabellenereignisse ausgel&ouml;st werden. Au&szlig;erdem ben&ouml;tigen Sie eine Tabelle, welche die ge&auml;nderten Datens&auml;tze speichert. Wenn Sie beides f&uuml;r mehrere Tabellen durchf&uuml;hren wollen, ist dies eine Menge Handarbeit. Grund genug, diesen Vorgang zu automatisieren.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Aenderungshistorie_implantieren\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2020-05-22T19:10:44+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg07.met.vgwort.de\/na\/3620227acb9f46c18f884c24e28a851a\" \/>\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=\"23\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Aenderungshistorie_implantieren\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Aenderungshistorie_implantieren\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"&Auml;nderungshistorie implantieren\",\"datePublished\":\"2020-05-22T19:10:44+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Aenderungshistorie_implantieren\\\/\"},\"wordCount\":3612,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Aenderungshistorie_implantieren\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/3620227acb9f46c18f884c24e28a851a\",\"articleSection\":[\"2015\",\"5\\\/2015\",\"Tabellen und Datenmodellierung\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Aenderungshistorie_implantieren\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Aenderungshistorie_implantieren\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Aenderungshistorie_implantieren\\\/\",\"name\":\"&Auml;nderungshistorie implantieren - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Aenderungshistorie_implantieren\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Aenderungshistorie_implantieren\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/3620227acb9f46c18f884c24e28a851a\",\"datePublished\":\"2020-05-22T19:10:44+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Aenderungshistorie_implantieren\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Aenderungshistorie_implantieren\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Aenderungshistorie_implantieren\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/3620227acb9f46c18f884c24e28a851a\",\"contentUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/3620227acb9f46c18f884c24e28a851a\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Aenderungshistorie_implantieren\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"&Auml;nderungshistorie implantieren\"}]},{\"@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":"&Auml;nderungshistorie implantieren - 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\/Aenderungshistorie_implantieren\/","og_locale":"de_DE","og_type":"article","og_title":"&Auml;nderungshistorie implantieren","og_description":"Die neuen Tabellenereignisse, die mit Access 2010 eingef&uuml;hrt wurden, erlauben die automatische Sicherung von Tabellendaten vor der Durchf&uuml;hrung von &Auml;nderungen an den Datens&auml;tzen. Dazu legen Sie entsprechende Datenmakros an, die durch die Tabellenereignisse ausgel&ouml;st werden. Au&szlig;erdem ben&ouml;tigen Sie eine Tabelle, welche die ge&auml;nderten Datens&auml;tze speichert. Wenn Sie beides f&uuml;r mehrere Tabellen durchf&uuml;hren wollen, ist dies eine Menge Handarbeit. Grund genug, diesen Vorgang zu automatisieren.","og_url":"https:\/\/access-im-unternehmen.de\/Aenderungshistorie_implantieren\/","og_site_name":"Access im Unternehmen","article_published_time":"2020-05-22T19:10:44+00:00","og_image":[{"url":"http:\/\/vg07.met.vgwort.de\/na\/3620227acb9f46c18f884c24e28a851a","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"23\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Aenderungshistorie_implantieren\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Aenderungshistorie_implantieren\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"&Auml;nderungshistorie implantieren","datePublished":"2020-05-22T19:10:44+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Aenderungshistorie_implantieren\/"},"wordCount":3612,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Aenderungshistorie_implantieren\/#primaryimage"},"thumbnailUrl":"http:\/\/vg07.met.vgwort.de\/na\/3620227acb9f46c18f884c24e28a851a","articleSection":["2015","5\/2015","Tabellen und Datenmodellierung"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Aenderungshistorie_implantieren\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Aenderungshistorie_implantieren\/","url":"https:\/\/access-im-unternehmen.de\/Aenderungshistorie_implantieren\/","name":"&Auml;nderungshistorie implantieren - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Aenderungshistorie_implantieren\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Aenderungshistorie_implantieren\/#primaryimage"},"thumbnailUrl":"http:\/\/vg07.met.vgwort.de\/na\/3620227acb9f46c18f884c24e28a851a","datePublished":"2020-05-22T19:10:44+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Aenderungshistorie_implantieren\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Aenderungshistorie_implantieren\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Aenderungshistorie_implantieren\/#primaryimage","url":"http:\/\/vg07.met.vgwort.de\/na\/3620227acb9f46c18f884c24e28a851a","contentUrl":"http:\/\/vg07.met.vgwort.de\/na\/3620227acb9f46c18f884c24e28a851a"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Aenderungshistorie_implantieren\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"&Auml;nderungshistorie implantieren"}]},{"@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\/55000995","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=55000995"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55000995\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55000995"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55000995"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55000995"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}