{"id":55000198,"date":"2013-08-01T00:00:00","date_gmt":"2020-01-24T15:58:51","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=198"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"aenderungen_protokollieren_Teil_I","status":"publish","type":"post","link":"https:\/\/access-basics.de\/index.php\/aenderungen_protokollieren_Teil_I.html","title":{"rendered":"&auml;nderungen protokollieren, Teil I"},"content":{"rendered":"<p class='introduction'>Textfelder sind das Hauptwerkzeug zur Eingabe von Daten. Sie k&ouml;nnen diese an die Felder der Datenherkunft eines Formulars binden oder diese ungebunden einsetzen. So intuitiv Textfelder zu benutzen sind, soviele M&ouml;glichkeiten und Fallstricke bieten sie auch. Dieser Artikel zeigt, was alles bei der Eingabe von Daten mit Textfeldern geschieht und wann welche Texte wo gespeichert werden.<\/p>\n<h2>Beispieldatenbank<\/h2>\n<p>Die Beispiele dieses Artikels finden Sie in der Datenbank <b>1304_AenderungenProtokollieren.mdb<\/b>.<\/p>\n<h2>Warum protokollieren<\/h2>\n<p>&auml;nderungen an Datens&auml;tzen sind in der Regel unumkehrbar, wenn der Datensatz einmal gespeichert ist. Solange dies noch nicht geschehen ist und Sie einfach nur die Werte eines oder mehrerer Felder aktualisiert haben, l&auml;sst sich dies noch r&uuml;ckg&auml;ngig machen &#8211; beispielsweise durch Bet&auml;tigen der <b>Escape<\/b>-Taste.<\/p>\n<p>Anderenfalls k&ouml;nnen Sie nach einer Fehleingabe nur hoffen, dass Sie den vorherigen Zustand des Datensatzes wiederherstellen k&ouml;nnen &#8211; oder dass eine Sicherungskopie noch den gew&uuml;nschten Stand enth&auml;lt. Wenn Sie dem vorbeugen m&ouml;chten, k&ouml;nnen Sie die &auml;nderungen an Datens&auml;tzen auch protokollieren. Dabei gibt es zwei Varianten:<\/p>\n<ul>\n<li>Sie speichern die &auml;nderung eines jeden Feldes als eigenen Datensatz in einer Tabelle, welche den Namen der betroffenen Tabelle und des Feldes, den alten und den neuen Wert, den betroffenen Datensatz sowie das &auml;nderungsdatum und gegebenenfalls den ausf&uuml;hrenden Benutzer speichert.<\/li>\n<li>Sie legen f&uuml;r jede Tabelle, f&uuml;r die Sie &auml;nderungen protokollieren m&ouml;chten, eine Kopie an. Vor einer &auml;nderung &uuml;bertragen Sie den vorherigen Zustand in diese Tabelle &#8211; auch hier wieder mit dem Datum der &auml;nderung und dem Namen der ausf&uuml;hrenden Person.<\/li>\n<\/ul>\n<p>In diesem Artikel schauen wir uns beide Varianten an.<\/p>\n<h2>Formularereignisse als Ausgangspunkt<\/h2>\n<p>W&auml;hrend es etwa unter dem SQL Server Trigger gibt, denen Sie Code zum Protokollieren von &auml;nderungen zuweisen k&ouml;nnen, m&uuml;ssen Sie in reinen Access-Datenbanken (also solchen, die ihre Daten wiederum in einer Access-Datenbank speichern &#8211; egal, ob in einer einzigen Datei oder aufgeteilt in Frontend und Backend) entsprechende Ereignisprozeduren zu den Formularen hinzuf&uuml;gen, in welchen die &auml;nderungen durchgef&uuml;hrt werden.<\/p>\n<p>In den meisten F&auml;llen werden Sie die &auml;nderungen beim Speichern des Datensatzes protokollieren. Der richtige Zeitpunkt ist das Ereignis <b>Vor Aktualisierung <\/b>des Formulars. Es wird unmittelbar vor dem Speichern ausgel&ouml;st &#8211; und vor dem Ereignis <b>Nach Aktualisierung<\/b>.<\/p>\n<p>Der Vorteil des Ereignisses <b>Vor Aktualisierung <\/b>ist: Sie k&ouml;nnen zu diesem Zeitpunkt sowohl auf den vorherigen als auch auf den aktuellen Wert eines Feldes der Datenherkunft zugreifen &#8211; und zwar &uuml;ber die Eigenschaften <b>OldValue <\/b>und <b>Value <\/b>(weitere Informationen hierzu finden Sie im Artikel <b>Textfelder: Value, OldValue und Text<\/b>.<\/p>\n<h2>Was soll protokolliert werden<\/h2>\n<p>Die Protokollierung soll so erfolgen, dass alle zur Kontrolle und sogar zur Wiederherstellung der ge&auml;nderten Daten notwendigen Informationen gespeichert weden. Dazu legen Sie eine Tabelle namens <b>tblAenderungen <\/b>an, die im Entwurf wie in Bild 1 aussieht.<\/p>\n<p class=\"image\"><a rel=\"lightbox\" href=\"..\/tl_files\/images\/pic_198_001.png\"><img decoding=\"async\" src=\"..\/tl_files\/images\/pic_198_001.png\" alt=\"Die Tabelle tblAenderungen in der Entwurfsansicht\" width=\"325\" \/><\/a><\/p>\n<p class='imagetext'>Bild 1: Die Tabelle tblAenderungen in der Entwurfsansicht<\/p>\n<p>Dabei kommen die folgenden Felder zum Einsatz:<\/p>\n<ul>\n<li><b>AenderungID<\/b>: Prim&auml;rschl&uuml;sselfeld der Tabelle<\/li>\n<li><b>Tabelle<\/b>: Name der Tabelle, deren Datensatz ge&auml;ndert wurde<\/li>\n<li><b>Aktion<\/b>: Wir wollen nicht nur &auml;nderungen, sondern auch das Anlegen oder L&ouml;schen von Datens&auml;tzen dokumentieren. Dieses Feld soll die Werte <b>New<\/b>, <b>Edit <\/b>und <b>Delete <\/b>aufnehmen.<\/li>\n<li><b>Feld<\/b>: Name des ge&auml;nderten Feldes<\/li>\n<li><b>PKName<\/b>: Name des Prim&auml;rschl&uuml;sselfeldes der betroffenen Tabelle<\/li>\n<li><b>PKWert<\/b>: Wert des Prim&auml;rschl&uuml;sselfeldes des ge&auml;nderten Datenatzes<\/li>\n<li><b>Zeit<\/b>: Datum und Uhrzeit der &auml;nderung<\/li>\n<li><b>Benutzer<\/b>: Aktueller Benutzer zum Zeitpunkt der &auml;nderung<\/li>\n<li><b>AlterWert<\/b>: Wert des Feldes vor der &auml;nderung<\/li>\n<li><b>NeuerWert<\/b>: Wert des Feldes nach der &auml;nderung<\/li>\n<\/ul>\n<p>Diese Art der Protokollierung erzeugt nat&uuml;rlich eine Menge Daten: Es wird tats&auml;chlich zu jedem ge&auml;nderten Feld ein eigener Datensatz in der Tabelle <b>tblAenderungen<\/b> angelegt.<\/p>\n<p>Wenn wir nun im Formular <b>frmArtikel <\/b>beispielsweise den Wert des Feldes <b>Artikelname <\/b>von <b>Chai <\/b>in <b>Chai (Tee) <\/b>&auml;ndern, soll die Tabelle einen Datensatz wie in Bild 2 erhalten.<\/p>\n<p class=\"image\"><a rel=\"lightbox\" href=\"..\/tl_files\/images\/pic_198_002.png\"><img decoding=\"async\" src=\"..\/tl_files\/images\/pic_198_002.png\" alt=\"Die Tabelle tblAenderungen mit einer ersten &auml;nderung\" width=\"325\" \/><\/a><\/p>\n<p class='imagetext'>Bild 2: Die Tabelle tblAenderungen mit einer ersten &auml;nderung<\/p>\n<p>Nun ben&ouml;tigen wir nur noch eine Ereignisprozedur, die genau dies erledigt.<\/p>\n<h2>&auml;nderung in Tabelle schreiben<\/h2>\n<p>Wir gehen zun&auml;chst vereinfachend davon aus, dass wir nur &auml;nderungen am Feld <b>Artikelname <\/b>in der Tabelle speichern m&ouml;chten. Dazu legen Sie f&uuml;r das Ereignis <b>Vor Aktualisierung <\/b>des Formulars die folgende Ereignisprozedur an:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_BeforeUpdate(Cancel<span style=\"color:blue;\"> As Integer<\/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;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM          tblAenderungen WHERE 1 = 2\", dbOpenDynaset)\r\n     If <span style=\"color:blue;\">Not<\/span> Me!txtArtikelname.Value = _\r\n             Me!txtArtikelname.OldValue Then\r\n         rst.Add<span style=\"color:blue;\">New<\/span>\r\n         rst!Tabelle = \"tblArtikel\"\r\n         rst!Aktion = \"Edit\"\r\n         rst!Feld = \"Artikelname\"\r\n         rst!PKName = \"ArtikelID\"\r\n         rst!PKWert = Me!ArtikelID\r\n         rst!Zeit = Now\r\n         rst!Benutzer = CurrentUser\r\n         rst!AlterWert = Me!txtArtikelname.OldValue\r\n         rst!NeuerWert = Me!txtArtikelname.Value\r\n         rst.Update\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = Nothing\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Diese Ereignisprozedur erstellt ein Recordset auf Basis der Tabelle <b>tblAenderungen<\/b>, das allerdings wegen des Kriteriums (<b>1=2<\/b>) keinen einzigen Datensatz enth&auml;lt. Dies ist auch nicht n&ouml;tig, denn wir wollen ja nur einen neuen Datensatz hinzuf&uuml;gen.<\/p>\n<p>Der &uuml;bersichtlichkeit halber legen wir diesen Datensatz zun&auml;chst mit der <b>AddNew<\/b>-Methode an und weisen alle Feldwerte einzeln zu. Die meisten Zuweisungen sind selbsterkl&auml;rend. Die Zeit wird mit der Funktion <b>Now <\/b>ermittelt, der aktuelle Access-Benutzer mit <b>CurrentUser <\/b>(hier k&ouml;nnte man noch den aktuellen Windows-Benutzer referenzieren &#8211; zumindest da Access seit der Version 2007 das Sicherheitssystem nicht mehr unterst&uuml;tzt). Den alten und den neuen Wert des gebundenen Steuerelements erhalten wir mit den Eigenschaften <b>OldValue <\/b>und <b>Value<\/b>.<\/p>\n<h2>Alle Felder protokollieren<\/h2>\n<div class=\"rcp_restricted\"><p><span style=\"color: #ff0000;\">M&ouml;chten Sie weiterlesen? Dann l&ouml;sen Sie Ihr Ticket!<\/span><br \/>\n<span style=\"color: #ff0000;\">Hier geht es zur Bestellung des Jahresabonnements des Magazins <strong>Access &#091;basics&#093;<\/strong>:<\/span><br \/>\n<span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/shop.minhorst.com\/magazine\/282\/access-basics?c=77\">Zur Bestellung ...<\/a><\/span><br \/>\n<span style=\"color: #ff0000;\">Danach greifen Sie sofort auf <strong>alle rund 400 Artikel<\/strong> unseres Angebots zu - auch auf diesen hier!<\/span><br \/>\n<span style=\"color: #000000;\">Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:<\/span><\/p>\n<\/div>\n\n\t\n\t<form id=\"rcp_login_form\"  class=\"rcp_form\" method=\"POST\" action=\"https:\/\/access-basics.de\/data\/wp\/v2\/posts\/55000198\/\">\n\n\t\t\n\t\t<fieldset class=\"rcp_login_data\">\n\t\t\t<p>\n\t\t\t\t<label for=\"rcp_user_login\">Username or Email<\/label>\n\t\t\t\t<input name=\"rcp_user_login\" id=\"rcp_user_login\" class=\"required\" type=\"text\"\/>\n\t\t\t<\/p>\n\t\t\t<p>\n\t\t\t\t<label for=\"rcp_user_pass\">Password<\/label>\n\t\t\t\t<input name=\"rcp_user_pass\" id=\"rcp_user_pass\" class=\"required\" type=\"password\"\/>\n\t\t\t<\/p>\n\t\t\t\t\t\t<p>\n\t\t\t\t<input type=\"checkbox\" name=\"rcp_user_remember\" id=\"rcp_user_remember\" value=\"1\"\/>\n\t\t\t\t<label for=\"rcp_user_remember\">Remember me<\/label>\n\t\t\t<\/p>\n\t\t\t<p class=\"rcp_lost_password\"><a href=\"\/index.php\/data\/wp\/v2\/posts\/55000198?rcp_action=lostpassword\"><\/a><\/p>\n\t\t\t<p>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_action\" value=\"login\"\/>\n\t\t\t\t\t\t\t\t\t<input type=\"hidden\" name=\"rcp_redirect\" value=\"https:\/\/access-basics.de\/data\/wp\/v2\/posts\/55000198\/\"\/>\n\t\t\t\t\t\t\t\t<input type=\"hidden\" name=\"rcp_login_nonce\" value=\"8d63f6cbe9\"\/>\n\t\t\t\t<input id=\"rcp_login_submit\" class=\"rcp-button\" type=\"submit\" value=\"Login\"\/>\n\t\t\t<\/p>\n\t\t\t\t\t<\/fieldset>\n\n\t\t\n\t<\/form>\n<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Textfelder sind das Hauptwerkzeug zur Eingabe von Daten. Sie k&ouml;nnen diese an die Felder der Datenherkunft eines Formulars binden oder diese ungebunden einsetzen. So intuitiv Textfelder zu benutzen sind, soviele M&ouml;glichkeiten und Fallstricke bieten sie auch. Dieser Artikel zeigt, was alles bei der Eingabe von Daten mit Textfeldern geschieht und wann welche Texte wo gespeichert werden.<\/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":[662013,66042013,44000014],"tags":[],"class_list":["post-55000198","post","type-post","status-publish","format-standard","hentry","category-662013","category-66042013","category-Loesungen"],"aioseo_notices":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v15.9.2 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>&auml;nderungen protokollieren, Teil I - Access [basics]<\/title>\n<meta name=\"description\" content=\"Textfelder sind das Hauptwerkzeug zur Eingabe von Daten. Sie k\u00f6nnen diese an die Felder der Datenherkunft eines Formulars binden oder diese ungebunden einsetzen. So intuitiv Textfelder zu benutzen sind, soviele M\u00f6glichkeiten und Fallstricke bieten sie auch. Dieser Artikel zeigt, was alles bei der Eingabe von Daten mit Textfeldern geschieht und wann welche Texte wo gespeichert werden.\" \/>\n<link rel=\"canonical\" href=\"https:\/\/access-basics.de\/index.php\/aenderungen_protokollieren_Teil_I.html\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"&auml;nderungen protokollieren, Teil I - Access [basics]\" \/>\n<meta property=\"og:description\" content=\"Textfelder sind das Hauptwerkzeug zur Eingabe von Daten. Sie k\u00f6nnen diese an die Felder der Datenherkunft eines Formulars binden oder diese ungebunden einsetzen. So intuitiv Textfelder zu benutzen sind, soviele M\u00f6glichkeiten und Fallstricke bieten sie auch. Dieser Artikel zeigt, was alles bei der Eingabe von Daten mit Textfeldern geschieht und wann welche Texte wo gespeichert werden.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-basics.de\/index.php\/aenderungen_protokollieren_Teil_I.html\" \/>\n<meta property=\"og:site_name\" content=\"Access [basics]\" \/>\n<meta property=\"article:published_time\" content=\"2020-01-24T15:58:51+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"-0001-11-30T00:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/..\/tl_files\/images\/pic_198_001.png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Gesch\u00e4tzte Lesezeit\">\n\t<meta name=\"twitter:data1\" content=\"13\u00a0Minuten\">\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"https:\/\/access-basics.de\/#website\",\"url\":\"https:\/\/access-basics.de\/\",\"name\":\"Access [basics]\",\"description\":\"DAS ACCESS-MAGAZIN F\\u00dcR ALLE, DIE VON 0 AUF 100 WOLLEN\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https:\/\/access-basics.de\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"de\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/access-basics.de\/index.php\/aenderungen_protokollieren_Teil_I.html#primaryimage\",\"inLanguage\":\"de\",\"url\":\"..\/tl_files\/images\/pic_198_001.png\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/access-basics.de\/index.php\/aenderungen_protokollieren_Teil_I.html#webpage\",\"url\":\"https:\/\/access-basics.de\/index.php\/aenderungen_protokollieren_Teil_I.html\",\"name\":\"&auml;nderungen protokollieren, Teil I - Access [basics]\",\"isPartOf\":{\"@id\":\"https:\/\/access-basics.de\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/access-basics.de\/index.php\/aenderungen_protokollieren_Teil_I.html#primaryimage\"},\"datePublished\":\"2020-01-24T15:58:51+00:00\",\"dateModified\":\"-0001-11-30T00:00:00+00:00\",\"author\":{\"@id\":\"https:\/\/access-basics.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f\"},\"description\":\"Textfelder sind das Hauptwerkzeug zur Eingabe von Daten. Sie k\\u00f6nnen diese an die Felder der Datenherkunft eines Formulars binden oder diese ungebunden einsetzen. So intuitiv Textfelder zu benutzen sind, soviele M\\u00f6glichkeiten und Fallstricke bieten sie auch. Dieser Artikel zeigt, was alles bei der Eingabe von Daten mit Textfeldern geschieht und wann welche Texte wo gespeichert werden.\",\"breadcrumb\":{\"@id\":\"https:\/\/access-basics.de\/index.php\/aenderungen_protokollieren_Teil_I.html#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/access-basics.de\/index.php\/aenderungen_protokollieren_Teil_I.html\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/access-basics.de\/index.php\/aenderungen_protokollieren_Teil_I.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"item\":{\"@type\":\"WebPage\",\"@id\":\"https:\/\/access-basics.de\/\",\"url\":\"https:\/\/access-basics.de\/\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"position\":2,\"item\":{\"@type\":\"WebPage\",\"@id\":\"https:\/\/access-basics.de\/index.php\/aenderungen_protokollieren_Teil_I.html\",\"url\":\"https:\/\/access-basics.de\/index.php\/aenderungen_protokollieren_Teil_I.html\",\"name\":\"&auml;nderungen protokollieren, Teil I\"}}]},{\"@type\":\"Person\",\"@id\":\"https:\/\/access-basics.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f\",\"name\":\"Andr\\u00e9 Minhorst\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/access-basics.de\/#personlogo\",\"inLanguage\":\"de\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"caption\":\"Andr\\u00e9 Minhorst\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","_links":{"self":[{"href":"https:\/\/access-basics.de\/index.php\/data\/wp\/v2\/posts\/55000198","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/access-basics.de\/index.php\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/access-basics.de\/index.php\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/access-basics.de\/index.php\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/access-basics.de\/index.php\/data\/wp\/v2\/comments?post=55000198"}],"version-history":[{"count":0,"href":"https:\/\/access-basics.de\/index.php\/data\/wp\/v2\/posts\/55000198\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-basics.de\/index.php\/data\/wp\/v2\/media?parent=55000198"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-basics.de\/index.php\/data\/wp\/v2\/categories?post=55000198"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-basics.de\/index.php\/data\/wp\/v2\/tags?post=55000198"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}