{"id":55001170,"date":"2019-04-01T00:00:00","date_gmt":"2020-05-13T21:06:19","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=1170"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\/","title":{"rendered":"Berechtigungen f&uuml;r Access-Objekte per SQL Server II: Formulare"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg06.met.vgwort.de\/na\/e677189bc90e48d3baff5217238ea822\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Im Beitrag &#8222;Berechtigungen f&uuml;r Access-Objekte per SQL Server I: Tabellen&#8220; haben wir ein Datenmodell entwickelt f&uuml;r die Verwaltung der Berechtigungen verschiedener Benutzergruppen auf die Formulare, Berichte und Steuer-elemente einer Access-Anwendung &#8211; gesteuert &uuml;ber die jeweilige Anmeldung an der SQL Server-Datenbank. Im zweiten Teil dieser Beitragsreihe verkn&uuml;pfen wir die Access-Anwendung mit diesen Tabellen und erstellen die Formulare, die zur Bearbeitung der f&uuml;r die Berechtigungsverwaltung notwendigen Tabellen erforderlich sind.<\/b><\/p>\n<p>F&uuml;r die im ersten Teil dieser Beitragsreihe namens <b>Berechtigungen f&uuml;r Access-Objekte per SQL Server I: Tabellen<\/b>, die Sie unter <b>www.access-im-unternehmen.de\/1159 <\/b>finden, ben&ouml;tigen wir prinzipiell zwei verschiedene Datenbanken: eine, mit der wir die Objektberechtigungen verwalten und eine, welche die Berechtigungen umsetzt. Die Formulare, mit denen wir die Objekte, Benutzergruppen und Berechtigungen einander zuordnen wollen, m&uuml;ssen nicht unbedingt in der eigentlichen Anwendung stecken. Andererseits kann es auch nicht schaden, damit gleich auszuprobieren, ob die Berechtigungen funktionieren &#8211; denn diese sollen weder durch Mitglieder der Gruppe <b>Bestellannahme <\/b>noch der Gruppe <b>Management <\/b>verwendet werden, sondern nur von den Administratoren. Wir werden also noch eine dritte Gruppe namens <b>Berechtigungsadministratoren <\/b>zu Windows hinzuf&uuml;gen, die wir dann auch in den SQL Server &uuml;bernehmen. Das erledigen Sie in der Eingabeaufforderung wie folgt:<\/p>\n<pre>net.exe LOCALGROUP \/ADD Berechtigungsadministratoren<\/pre>\n<p>Im SQL Server Management Studio f&uuml;gen wir diese Anmeldung wie folgt hinzu (Details siehe Beitrag <b>SQL Server: Sicherheit und Benutzerverwaltung<\/b>, <b>www.access-im-unternehmen.de\/1154<\/b>) &#8211; <b><Server><\/b> muss durch den entsprechenden Servernamen ersetzt werden:<\/p>\n<pre>USE [master]\r\nGO\r\nCREATE LOGIN [&lt;Server&gt;\\Berechtigungsadministratoren] FROM WINDOWS WITH DEFAULT_DATABASE=[Suedsturm_SQL]\r\nGO\r\nUSE [Suedsturm_SQL]\r\nGO\r\nCREATE USER [&lt;Server&gt;\\Berechtigungsadministratoren] FOR LOGIN [&lt;Server&gt;\\Berechtigungsadministratoren]\r\nGO\r\nALTER ROLE [db_datareader] ADD MEMBER [&lt;Server&gt;\\Berechtigungsadministratoren]\r\nGO\r\nALTER ROLE [db_datawriter] ADD MEMBER [&lt;Server&gt;\\Berechtigungsadministratoren]\r\nGO<\/pre>\n<p>Auf den folgenden Seiten zeigen wir Ihnen, wie Sie erstens die Verkn&uuml;pfung zu den relevanten Tabellen herstellen &#8211; also zu den Tabellen, die wir im ersten Teil entworfen haben -, und dann die Formulare programmieren, die zur Verwaltung der Berechtigungen erforderlich sind.<\/p>\n<h2>Verkn&uuml;pfung herstellen<\/h2>\n<p>Als Erstes ben&ouml;tigen wir eine Verkn&uuml;pfung von einer Access-Datenbank zu den im ersten Teil der Beitragsreihe erstellten Tabellen. Dazu bem&uuml;hen wir einfache ODBC-Verkn&uuml;pfungen. Diese legen wir mit einem Tool an, dass wir bereits im Beitrag <b>SQL Server-Tools <\/b>vorgestellt haben (<b>http:\/\/www.access-im-unternehmen.de\/1061<\/b>). Genaugenommen k&ouml;nnen wir die dort erstellte Datenbank auch als Grundlage f&uuml;r unsere Datenbank zur Verwaltung der Berechtigungen nutzen, denn sie enth&auml;lt einige praktische Werkzeuge, die wir noch brauchen.<\/p>\n<p>Das beginnt mit dem Formular <b>frmVerbindungszeichenfolgen<\/b> aus Bild 1, mit dem wir uns gleich eine passende Verbindungszeichenfolge zusammenstellen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_02\/pic_1180_001.png\" alt=\"Einrichten der Verbindungszeichenfolge\" width=\"424,7115\" height=\"299,5663\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Einrichten der Verbindungszeichenfolge<\/span><\/b><\/p>\n<p>Nachdem wir dies erledigt haben, k&ouml;nnen wir gleich das Formular <b>frmTabellenVerknuepfen <\/b>&ouml;ffnen, mit der wir die soeben angelegte Verbindung ausw&auml;hlen. Es erscheinen alle Tabellen der Datenbank <b>Suedsturm_SQL<\/b>, von denen wir die Tabellen <b>tblBenutzergruppen<\/b>, <b>tblBerechtigungsstufen<\/b>, <b>tblObjekte<\/b>, <b>tblObjekteBenutzergruppenBerechtigungsen <\/b>und <b>tblObjekttypen <\/b>ausw&auml;hlen &#8211; bei gedr&uuml;ckter Umschalttaste (siehe Bild 2). Diese Tabellen erscheinen kurz darauf im Navigationsbereich der Datenbank.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_02\/pic_1180_002.png\" alt=\"Hinzuf&uuml;gen der Verkn&uuml;pfungen\" width=\"424,7115\" height=\"334,5687\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Hinzuf&uuml;gen der Verkn&uuml;pfungen<\/span><\/b><\/p>\n<h2>Warum ODBC-Verkn&uuml;pfungen<\/h2>\n<p>Aus Performance-Gesichtspunkten w&auml;re es g&uuml;nstiger, &uuml;ber Abfragen und gespeicherte Prozeduren auf die Tabellen der SQL Server-Datenbank zuzugreifen. Allerdings werden wir nicht so viele Objekte, Benutzer oder Berechtigungen anlegen, dass die Performance bei Nutzung von ODBC-Verkn&uuml;pfungen in die Knie geht &#8211; und wir werden auch nicht mit vielen Benutzern gleichzeitig auf diese Daten zugreifen. Also ist die einfache Variante akzeptabel. Wenn wir sp&auml;ter die Berechtigungen beim Anzeigen des Ribbons oder beim &ouml;ffnen von Formularen und Berichten abfragen, werden wir auf die performantere Variante zur&uuml;ckgreifen.<\/p>\n<h2>Tabellen f&uuml;llen<\/h2>\n<p>Im ersten Teil dieser Beitragsreihe haben wir die Tabellen vorgestellt, mit denen wir die Objekte, die Berechtigungsstufen, die Berechtigungen und die Objekttypen speichern wollen. Nun kann es bei einer umfangreichen Datenbank relativ aufwendig werden, alle Objekte wie Formulare und Berichte sowie die enthaltenen Steuer-elemente in die Tabelle <b>tblObjekte <\/b>zu schreiben, um dann &uuml;ber die anderen Tabellen die Berechtigungen zuzuordnen.<\/p>\n<p>Also programmieren wir uns eine Prozedur, mit der wir die Formulare und Berichte sowie die enthaltenen Steuer-elemente in die Tabelle <b>tblObjekte <\/b>schreiben k&ouml;nnen.<\/p>\n<p>Diese hei&szlig;t <b>ObjekteSchreiben <\/b>und erwartet einen optionalen Parameter, mit dem Sie den Namen eines oder mehrerer Formulare angeben k&ouml;nnen, die nicht von der Prozedur ber&uuml;cksichtigt werden sollen, die also nicht samt Steuerelementen in die Tabelle <b>tblObjekte <\/b>geschrieben werden sollen. Der Aufruf der Prozedur sieht also so aus, wenn alle Formulare ber&uuml;cksichtigt werden sollen:<\/p>\n<pre>ObjekteSchreiben<\/pre>\n<p>Wenn Sie die Prozedur, wie wir es sp&auml;ter tun werden, von einem Formular wie <b>frmObjektberechtigungen <\/b>aus aufrufen werden, k&ouml;nnen Sie dieses auf folgende Weise ausschlie&szlig;en:<\/p>\n<pre>ObjekteSchreiben \"frmObjektberechtigungen\"<\/pre>\n<p>Wenn Sie mehr als ein Formular ausschlie&szlig;en wollen, geben Sie die Namen der Formulare einfach in einer durch Kommata getrennten Liste an:<\/p>\n<pre>ObjekteSchreiben \"frmObjektberechtigungen\", \"frmArtikel\", ...<\/pre>\n<p>Die Prozedur <b>ObjekteSchreiben <\/b>finden Sie in Listing 1. Damit Sie kein, ein oder mehrere Formulare von der Verarbeitung ausschlie&szlig;en k&ouml;nnen, verwenden wir ein <b>ParamArray <\/b>als Parameter. In einer <b>For&#8230;Next<\/b>-Schleife durchl&auml;uft die Prozedur alle Formulare der aktuellen Anwendung. Dabei ermitteln wir die Anzahl der zu durchlaufenden Formulare &uuml;ber die <b>Count<\/b>-Eigenschaft der Auflistung <b>CurrentProject.AllForms<\/b>.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>ObjekteSchreiben(ParamArray strNicht()<span style=\"color:blue;\"> As Variant<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database, frm<span style=\"color:blue;\"> As <\/span>Form, strForm<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As Integer<\/span>, j<span style=\"color:blue;\"> As Integer<\/span>, ctl<span style=\"color:blue;\"> As <\/span>Control\r\n     <span style=\"color:blue;\">Dim <\/span>bolNicht<span style=\"color:blue;\"> As Boolean<\/span>, strControl<span style=\"color:blue;\"> As String<\/span>, rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     For i = 0 To CurrentProject.AllForms.Count - 1\r\n         strForm = CurrentProject.AllForms(i).Name\r\n         bolNicht = <span style=\"color:blue;\">False<\/span>\r\n         For j = <span style=\"color:blue;\">LBound<\/span>(strNicht) To <span style=\"color:blue;\">UBound<\/span>(strNicht)\r\n             <span style=\"color:blue;\">If <\/span>strForm = strNicht(j)<span style=\"color:blue;\"> Then<\/span>\r\n                 bolNicht = <span style=\"color:blue;\">True<\/span>\r\n                 <span style=\"color:blue;\">Exit For<\/span>\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">Next<\/span> j\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> bolNicht<span style=\"color:blue;\"> Then<\/span>\r\n             DoCmd.OpenForm strForm, acDesign\r\n             <span style=\"color:blue;\">Set<\/span> frm = Forms(strForm)\r\n             On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n             db.Execute \"INSERT INTO tblObjekte(Bezeichnung, ObjekttypID) VALUES(''''\" & strForm & \"'''', 1)\", dbFailOnError\r\n             db.Execute \"INSERT INTO tblObjekte(Bezeichnung, Uebergeordnet, ObjekttypID) VALUES(''''Form'''', ''''\" _\r\n                 & strForm & \"'''', 4)\", dbFailOnError\r\n             For Each ctl In frm.Controls\r\n                 <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> ctl.ControlType = 100<span style=\"color:blue;\"> Then<\/span>\r\n                     strControl = ctl.Name\r\n                     db.Execute \"INSERT INTO tblObjekte(Bezeichnung, Uebergeordnet, ObjekttypID, SteuerelementtypID) \" _\r\n                         & \"VALUES(''''\" & strControl & \"'''', ''''\" & strForm & \"'''', 4, \" & ctl.ControlType & \")\", dbFailOnError\r\n                 <span style=\"color:blue;\">End If<\/span>\r\n             <span style=\"color:blue;\">Next<\/span> ctl\r\n             <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n             <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM tblObjekte WHERE Uebergeordnet = ''''\" & strForm _\r\n                 & \"'''' AND ObjekttypID = 4 AND NOT Bezeichnung = ''''Form''''\", dbOpenDynaset, dbSeeChanges)\r\n             <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n                 <span style=\"color:blue;\">Set<\/span> ctl = Nothing\r\n                 On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n                 <span style=\"color:blue;\">Set<\/span> ctl = frm.Controls(rst!Bezeichnung)\r\n                 <span style=\"color:blue;\">Debug.Print<\/span> Err.Number, Err.Description\r\n                 <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n                 <span style=\"color:blue;\">If <\/span>ctl Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n                     db.Execute \"DELETE FROM tblObjekte WHERE ObjektID = \" & rst!ObjektID, dbFailOnError Or dbSeeChanges\r\n                 <span style=\"color:blue;\">End If<\/span>\r\n                 rst.Move<span style=\"color:blue;\">Next<\/span>\r\n             <span style=\"color:blue;\">Loop<\/span>\r\n             DoCmd.Close acForm, strForm\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> i\r\n     FormularePruefen\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Prozedur zum Einlesen der Formulare und Steuer-elemente in die Tabelle tblObjekte<\/span><\/b><\/p>\n<p>Danach erfassen wir den Namen des ersten Formulars und speichern diesen in der Variablen <b>strForm<\/b>. Die <b>Boolean<\/b>-Variable <b>bolNicht <\/b>stellen wir auf den Wert <b>False <\/b>ein, da wir in der folgenden Schleife alle Elemente des per Parameter &uuml;bergebenen ParamArrays durchlaufen und pr&uuml;fen, ob das in <b>strForm <\/b>gespeicherte Formular einem der auszuschlie&szlig;enden Formulare entspricht. Dies erledigen wir in einer weiteren <b>For&#8230;Next<\/b>-Schleife, diesmal mit der Laufvariablen <b>j<\/b>.<\/p>\n<p>In dieser Schleife durchlaufen wir alle Elemente des ParamArrays und referenzieren diese &uuml;ber den mit <b>j <\/b>ermittelten Indexwert. Stimmen <b>strForm <\/b>und das aktuelle Element aus <b>strNicht(j) <\/b>&uuml;berein, stellen wir <b>bolNicht <\/b>auf <b>True <\/b>ein und verlassen die Schleife. Erhalten wir dabei den Wert <b>True <\/b>f&uuml;r die Variable <b>bolNicht<\/b>, dann wird der Inhalt der folgenden <b>If&#8230;Then<\/b>-Bedingung nicht ausgef&uuml;hrt, denn das aktuelle Formular samt Steuerelementen soll nicht eingelesen werden.<\/p>\n<p>Anderenfalls beginnt hier jedoch der Einlesevorgang. Dabei &ouml;ffnen wir das Formular aus <b>strForm <\/b>in der Entwurfsansicht und referenzieren es mit der Objektvariablen <b>objForm<\/b>. Danach deaktivieren wir die eingebaute Fehlerbehandlung, da es sein kann, dass beim Versuch, das aktuelle Formular als neuen Datensatz in die Tabelle <b>tblObjekte <\/b>zu schreiben, ein Fehler wegen einer Schl&uuml;sselverletzung ausgel&ouml;st wird.<\/p>\n<p>Dies kommt vor, wenn Sie beispielsweise neue Formulare oder Steuer-elemente hinzugef&uuml;gt haben und diese Elemente erneut einlesen. Wir haben der Prozedur keine &uuml;berpr&uuml;fung hinzugef&uuml;gt, mit der wir das Vorhandensein eines Formulars oder Steuerelements pr&uuml;fen, sondern lassen es auf den Fehler ankommen, den wir dann ignorieren. Die <b>INSERT INTO<\/b>-Anweisung schreibt den Namen des Formulars in das Feld <b>Bezeichnung <\/b>eines neuen Datensatzes der Tabelle <b>tblObjekte<\/b>.<\/p>\n<p>Au&szlig;erdem tr&auml;gt es dort den Wert <b>1 <\/b>f&uuml;r Formular in das Feld <b>ObjekttypID <\/b>ein. Die zweite <b>INSERT INTO<\/b>-Anweisung tr&auml;gt einen zweiten Datensatz f&uuml;r dieses Formular ein, wobei allerdings das Feld <b>Bezeichnung <\/b>mit dem Wert <b>Form <\/b>und das Feld <b>Uebergeordnet <\/b>mit dem Namen des Formulars gef&uuml;llt wird. Wozu wir das ben&ouml;tigen, erfahren Sie weiter unten.<\/p>\n<p>Danach durchlaufen wir in einer <b>For Each<\/b>-Schleife alle in dem mit <b>frm <\/b>referenzierten Formulare enthaltenen Steuer-elemente. Dabei pr&uuml;fen wir zun&auml;chst, ob es sich nicht um ein Bezeichnungsfeld handelt &#8211; diese sollen hier nicht ber&uuml;cksichtigt werden. Ist das aktuelle Steuerelement kein Bezeichnungsfeld, schreiben wir zun&auml;chst den Namen des aktuellen Steuerelements in die Variable <b>strControl<\/b>.<\/p>\n<p>Danach f&uuml;gen wir, wiederum bei deaktivierter Fehlerbehandlung, einen neuen Datensatz f&uuml;r das aktuelle Steuer-element in die Tabelle <b>tblObjekte <\/b>ein. Diesmal landet der Name des Steuerelements im Feld <b>Bezeichnung<\/b>. Der Name des &uuml;bergeordneten Formulars landet im Feld <b>Uebergeordnet<\/b>. F&uuml;r den Objekttyp landet der Wert <b>4 <\/b>f&uuml;r Steuer-element im Feld <b>ObjekttypID<\/b>. Au&szlig;erdem speichern wir noch den Steuerelementtyp aus der Eigenschaft <b>ControlType<\/b>, und zwar im Feld <b>Steuer-ele-ment-typ-ID<\/b>.<\/p>\n<p>Danach aktivieren wir die Fehlerbehandlung wieder und &ouml;ffnen ein Recordset, das alle Elemente der Tabelle <b>tblObjekte <\/b>enth&auml;lt, deren Feld <b>Uebergeordnet <\/b>dem Namen des aktuell untersuchten Formulars entspricht und die im Feld <b>ObjekttypID <\/b>den Wert <b>4 <\/b>aufweisen &#8211; mit Ausnahme der Datens&auml;tze, die im Feld <b>Bezeichnung <\/b>den Wert <b>Form <\/b>enthalten.<\/p>\n<p>Das Recordset enth&auml;lt also jeweils einen Datensatz f&uuml;r alle Steuer-elemente des aktuellen Formulars. Damit durchlaufen wir dann in einer <b>Do While<\/b>-Schleife alle Datens&auml;tze dieses Recordsets. Wir leeren die Objektvariable <b>ctl <\/b>und versuchen dann, bei deaktivierter Fehlerbehandlung das Steuer-element mit dem Namen aus dem Feld <b>Bezeichnung <\/b>im Formular zu referenzieren.<\/p>\n<p><!--30percent--><\/p>\n<p>Entspricht <b>ctl <\/b>danach dem Objekt <b>Nothing<\/b>, ist also leer, ist das Steuer-element zwar noch in der Tabelle <b>tblObjekte <\/b>gespeichert, aber nicht mehr im angegebenen Formulare vorhanden &#8211; vermutlich hat der Entwickler es in der Zwischenzeit gel&ouml;scht. In diesem Fall k&ouml;nnen wir auch den dazu geh&ouml;renden Datensatz aus der Tabelle <b>tblObjekte <\/b>l&ouml;schen.<\/p>\n<p>Danach schlie&szlig;en wir schlie&szlig;lich noch das aktuell untersuchte Formular und durchlaufen die Schleife f&uuml;r die weiteren Formulare, bis wir alle Formular durchlaufen haben.<\/p>\n<h2>Auf gel&ouml;schte Formulare pr&uuml;fen<\/h2>\n<p>Eine weitere Prozedur, die wir mit der letzten Anweisung der zuvor beschriebenen Prozedur aufrufen, hei&szlig;t <b>FormularePruefen<\/b> (siehe Listing 2). Sie untersucht alle Eintr&auml;ge der Tabelle <b>tblObjekte<\/b>, die den Wert <b>1 <\/b>im Feld <b>Objekttyp-ID <\/b>aufweisen dahingehend, ob die angegebenen Formular noch in der Datenbank vorhanden sind. Ist dies nicht der Fall, werden die Formulare-Eintr&auml;ge auch aus der Tabelle <b>tblObjekte <\/b>gel&ouml;scht &#8211; inklusive der Steuerelement-Eintr&auml;ge f&uuml;r diese Formulare.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>FormularePruefen()\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>i<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>bolBehalten<span style=\"color:blue;\"> As Boolean<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM tblObjekte WHERE ObjekttypID = 1\", dbOpenDynaset, dbSeeChanges)\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n         bolBehalten = <span style=\"color:blue;\">False<\/span>\r\n         For i = 0 To CurrentProject.AllForms.Count - 1\r\n             <span style=\"color:blue;\">If <\/span>CurrentProject.AllForms(i).Name = rst!Bezeichnung<span style=\"color:blue;\"> Then<\/span>\r\n                 bolBehalten = <span style=\"color:blue;\">True<\/span>\r\n                 <span style=\"color:blue;\">Exit For<\/span>\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">Next<\/span> i\r\n         <span style=\"color:blue;\">If <\/span>bolBehalten = <span style=\"color:blue;\">False<\/span><span style=\"color:blue;\"> Then<\/span>\r\n             db.Execute \"DELETE FROM tblObjekte WHERE Uebergeordnet = ''''\" & rst!Bezeichnung _\r\n                 & \"''''\", dbFailOnError Or dbSeeChanges\r\n             db.Execute \"DELETE FROM tblObjekte WHERE ObjektID = \" & rst!ObjektID, dbFailOnError Or dbSeeChanges\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         rst.Move<span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Prozedur zum Pr&uuml;fen und gegebenenfalls L&ouml;schen von Eintr&auml;gen f&uuml;r Formulare aus der Tabelle tblObjekte<\/span><\/b><\/p>\n<p>Wenn Sie die Prozedur <b>ObjekteSchreiben <\/b>einmal aufgerufen haben, etwa f&uuml;r die Beispieldatenbank zu diesem Beitrag, finden Sie Daten wie die aus Bild 3 in der Tabelle <b>tblObjekte<\/b>.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_02\/pic_1180_003.png\" alt=\"Daten &uuml;ber die mit Berechtigungen zu versehenden Objekte\" width=\"574,61\" height=\"455,1274\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Daten &uuml;ber die mit Berechtigungen zu versehenden Objekte<\/span><\/b><\/p>\n<h2>Formular zum Verwalten der Berechtigungen<\/h2>\n<p>Das Formular zum Verwalten der Berechtigungen hei&szlig;t <b>frmBerechtigungen<\/b>. Im linken Teil beherbergt es ein Listenfeld mit allen Formularen, die wir aus Eintr&auml;gen der Tabelle <b>tblObjekte<\/b> ermitteln, f&uuml;r die das Feld <b>ObjektID <\/b>den Wert <b>1 <\/b>enth&auml;lt. Den Entwurf dieses Formulars finden Sie in Bild 4.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_02\/pic_1180_004.png\" alt=\"Entwurf des Formulars frmBerechtigungen\" width=\"700\" height=\"351,8558\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Entwurf des Formulars frmBerechtigungen<\/span><\/b><\/p>\n<p>Damit das Listenfeld namens <b>lstFormulare <\/b>die gew&uuml;nschten Daten anzeigt, weisen wir diesem die folgende Abfrage als Datensatzherkunft zu:<\/p>\n<pre>SELECT DISTINCT tblObjekte.Bezeichnung FROM tblObjekte WHERE ObjekttypID = 1 ORDER BY tblObjekte.Bezeichnung;<\/pre>\n<p>Nach einem Wechsel in die Formularansicht liefert das bereits die Ansicht aus Bild 5.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_02\/pic_1180_005.png\" alt=\"Das Listenfeld lstFormulare mit den Daten der Tabelle tblObjekte\" width=\"424,7115\" height=\"343,2013\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Das Listenfeld lstFormulare mit den Daten der Tabelle tblObjekte<\/span><\/b><\/p>\n<h2>Steuer-elemente im Listenfeld anzeigen<\/h2>\n<p>Als N&auml;chstes wollen wir die Steuer-elemente zu dem jeweils im Listenfeld <b>lstFormulare <\/b>markierten Formular im zweiten Listenfeld <b>lstSteuerelemente <\/b>anzeigen. Da beim &ouml;ffnen noch kein Element des ersten Listenfeldes markiert ist, wollen wir einfach alle Elemente der Tabelle <b>tblObjekte <\/b>im zweiten Listenfeld anzeigen. Dazu f&uuml;gen wir der Eigenschaft <b>Datensatzherkunft <\/b>des Listenfeldes <b>lstElemente <\/b>die folgende SQL-Abfrage hinzu:<\/p>\n<pre>SELECT tblObjekte.ObjektID, [Bezeichnung]  & \" (\" & [Uebergeordnet] & \")\" AS ElementObjekt,  tblObjekte.Bezeichnung FROM tblObjekte;<\/pre>\n<p>Sobald der Benutzer jedoch einen Eintrag des Listenfeldes <b>lstFormulare<\/b> markiert, sollen nur noch die Elemente dieses Formulars im zweiten Listenfeld <b>lstElemente<\/b> angezeigt werden. Deshalb hinterlegen wir f&uuml;r die Ereignis-eigenschaft <b>Nach Aktualisierung <\/b>eine Ereignisprozedur, die das Listenfeld <b>lstElemente <\/b>so filtert, dass nur noch die zum gew&auml;hlten Formular geh&ouml;renden Elemente angezeigt werden &#8211; und so, dass die Bezeichnungsfelder nicht mit angezeigt werden:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>lstFormulare_AfterUpdate()\r\n     <span style=\"color:blue;\">Dim <\/span>strObjekte<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>var<span style=\"color:blue;\"> As Variant<\/span>\r\n     For Each var In Me!lstFormulare.ItemsSelected\r\n         strObjekte = strObjekte & \", ''''\" _\r\n             & Me!lstFormulare.ItemData(var) & \"''''\"\r\n     <span style=\"color:blue;\">Next<\/span> var\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(strObjekte) &gt; 0<span style=\"color:blue;\"> Then<\/span>\r\n         strObjekte = <span style=\"color:blue;\">Mid<\/span>(strObjekte, 3)\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     Me!lstElemente.RowSource = \"SELECT ObjektID,  Bezeichnung FROM tblObjekte WHERE Uebergeordnet  IN (\" & strObjekte & \")\"\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Die Ansicht im Formular <b>frmBerechtigungen <\/b>sieht dann nach der Auswahl eines der Formulare im linken Listenfeld wie in Bild 6 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_02\/pic_1180_006.png\" alt=\"Elemente eines Formulars\" width=\"499,6607\" height=\"338,8504\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Elemente eines Formulars<\/span><\/b><\/p>\n<h2>Das Form-Element<\/h2>\n<p>Hier taucht nun neben den Steuerelementen des markierten Formulars auch der Eintrag <b>Form <\/b>auf. Damit wollen wir eine einheitliche M&ouml;glichkeit schaffen, nicht nur die Berechtigungen f&uuml;r die Steuer-elemente zu definieren, sondern auch f&uuml;r das Formular selbst.<\/p>\n<h2>Listenfeld der Benutzergruppen<\/h2>\n<p>Ganz rechts im Formular haben wir zwei weitere Listenfelder vorgesehen. Das obere soll die Benutzergruppen anzeigen, die unter Windows eingerichtet sind und die wir tempor&auml;r in der Tabelle <b>tblBenutzergruppen <\/b>speichern.<\/p>\n<p>Dazu m&uuml;ssen wir diese allerdings erst einmal ermitteln.<\/p>\n<h2>Benutzergruppen einlesen<\/h2>\n<p>Die Benutzergruppen lesen wir mithilfe einer gespeicherten Prozedur ein, die wir entweder direkt im SQL Server Management Studio anlegen oder die wir im Formular <b>frmSQLBefehle<\/b> eingeben und ausf&uuml;hren (siehe Bild 7).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_02\/pic_1180_007.png\" alt=\"Erstellen einer gespeicherten Prozedur zum Ermitteln von Benutzergruppen\" width=\"649,559\" height=\"375,9817\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Erstellen einer gespeicherten Prozedur zum Ermitteln von Benutzergruppen<\/span><\/b><\/p>\n<p>Die gespeicherte Prozedur enth&auml;lt dabei genau eine Anweisung. Diese ermittelt per <b>SELECT <\/b>alle Eintr&auml;ge der Katalogsicht <b>sys.database_principals<\/b>, deren Feld <b>type <\/b>den Wert <b>G <\/b>aufweist, und schreibt diese mittels <b>INSERT INTO<\/b>-Anweisung in die Tabelle <b>tblBenutzergruppen<\/b>:<\/p>\n<pre>CREATE PROC [dbo].[spBenutzergruppenAktualisieren]\r\nAS\r\nSET NOCOUNT ON;\r\nINSERT INTO dbo.tblBenutzergruppen(Bezeichnung)\r\nSELECT name FROM sys.database_principals WHERE type = ''''G'''';<\/pre>\n<p>Die Katalogsicht <b>sys.database_principals <\/b>liefert dabei Elemente wie SQL-Benutzer, Windows-Benutzer, Windows-Benutzergruppen und so weiter. Der Wert <b>G <\/b>f&uuml;r das Feld <b>type <\/b>schr&auml;nkt die R&uuml;ckgabewerte dabei auf die Windows-Benutzergruppen ein.<\/p>\n<p>Danach f&uuml;hren wir die gespeicherte Prozedur noch aus, damit die Benutzergruppen auch in die Tabelle <b>tblBenutzergruppen <\/b>eingetragen werden. Das erledigen wir mit der folgenden Anweisung, die wir entweder in einer neuen Abfrage im SQL Server Management Studio ausf&uuml;hren oder wieder im Formular <b>frmSQLBefehle <\/b>in der aktuellen Datenbank:<\/p>\n<pre>Exec dbo.spBenutzergruppenAktualisieren<\/pre>\n<p>Danach finden wir in der Tabelle <b>tblBenutzergruppen <\/b>die Eintr&auml;ge etwa wie in Bild 8 vor.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_02\/pic_1180_008.png\" alt=\"Tabelle der Benutzergruppen\" width=\"424,7115\" height=\"169,8846\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 8: Tabelle der Benutzergruppen<\/span><\/b><\/p>\n<h2>Listenfeld lstBenutzergruppen f&uuml;llen<\/h2>\n<p>Um das Listenfeld rechts oben mit den Daten der Tabelle <b>tblBenutzergruppen <\/b>zu f&uuml;llen, stellen wir seine Eigenschaft Datensatzherkunft auf die entsprechende Tabelle ein, also <b>tblBenutzergruppen<\/b>. Damit das Listenfeld nur die Bezeichnung der Benutzergruppe anzeigt und nicht die Prim&auml;rschl&uuml;sselwerte aus dem Feld <b>BenutzergruppeID<\/b>, legen wir au&szlig;erdem f&uuml;r die Eigenschaft <b>Spaltenanzahl <\/b>den Wert <b>2 <\/b>und f&uuml;r <b>Spaltenbreiten <\/b>den Wert <b>0cm <\/b>fest.<\/p>\n<p>Wenn wir nun das Formular <b>frmBerechtigungen <\/b>&ouml;ffnen, zeigt das Listenfeld <b>lstBenutzergruppen<\/b> die Eintr&auml;ge der Tabelle <b>tblBenutzergruppen <\/b>an (siehe Bild 9).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_02\/pic_1180_009.png\" alt=\"Benutzergruppen im Listenfeld des Formulars frmBerechtigungen\" width=\"649,559\" height=\"166,1061\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 9: Benutzergruppen im Listenfeld des Formulars frmBerechtigungen<\/span><\/b><\/p>\n<h2>Berechtigungen setzen<\/h2>\n<p>Damit kommen wir der Fertigstellung dieses Formulars n&auml;her. Wir sollen nun daf&uuml;r sorgen, dass das vierte Listenfeld rechts unten verschiedene Berechtigungen f&uuml;r das jeweilige Objekt anzeigt, die dann markiert werden, wenn diese Berechtigung gesetzt ist. Die Berechtigungen speichern wir in der Tabelle <b>tblObjekteBenutzergruppenBerechtigungen<\/b>. Im Listenfeld <b>lstBerechtigungsstufen <\/b>zeigen wir die Datens&auml;tze der Tabelle <b>tblBerechtigungsstufen <\/b>an. Diese Tabelle enth&auml;lt ja lediglich die drei Datens&auml;tze aus Bild 10. Wie aber wollen wir nun f&uuml;r eines der Formulare oder die darin enthaltenen Steuer-elemente Berechtigungsstufen festlegen und im Listenfeld <b>lstBerechtigungsstufen <\/b>anzeigen<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_02\/pic_1180_010.png\" alt=\"Tabelle der Berechtigungsstufen\" width=\"424,7115\" height=\"168,4807\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 10: Tabelle der Berechtigungsstufen<\/span><\/b><\/p>\n<p>Das erledigen wir, indem wir die Werte der Tabelle <b>tblObjekteBenutzergruppenBerechtigungen <\/b>abh&auml;ngig von den aktuell in den drei Listenfeldern <b>lstFormulare<\/b>, <b>lst-Elemente <\/b>und <b>lstBenutzergruppen <\/b>markierten Eintr&auml;gen den passenden Eintrag im Listenfeld <b>lstBerechtigungsstufen <\/b>markieren.<\/p>\n<p>Dabei wollen wir zun&auml;chst daf&uuml;r sorgen, dass beim Ausw&auml;hlen eines Eintrags f&uuml;r die Listenfelder <b>lstElemente <\/b>und <b>lstBenutzergruppen <\/b>eine Prozedur aufgerufen wird, die pr&uuml;ft, welche Berechtigung f&uuml;r diese Kombination aus Benutzergruppe und Element vorliegt. Daher hinterlegen wir f&uuml;r diese beiden Listenfelder die folgenden Ereignisprozeduren, die jeweils durch das Ereignis <b>Nach Aktualisierung <\/b>ausgel&ouml;st werden:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>lstBenutzergruppen_AfterUpdate()\r\n     BerechtigungenAnzeigen\r\n<span style=\"color:blue;\">End Sub<\/span>\r\n<span style=\"color:blue;\">Private Sub <\/span>lstElemente_AfterUpdate()\r\n     BerechtigungenAnzeigen\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Die dadurch aufgerufene Prozedur namens <b>Be-rech-ti-gung&#8211;Anzeigen <\/b>finden Sie in Listing 3.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>BerechtigungenAnzeigen()\r\n     <span style=\"color:blue;\">Dim <\/span>varElement<span style=\"color:blue;\"> As Variant<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngElementID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>varBenutzergruppe<span style=\"color:blue;\"> As Variant<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngBenutzergruppeID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngBerechtigungsstufeID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As Integer<\/span>\r\n     For i = 0 To Me!lstBerechtigungsstufen.ListCount - 1\r\n         Me!lstBerechtigungsstufen.Selected(i) = <span style=\"color:blue;\">False<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> i\r\n     For Each varElement In Me!lstElemente.ItemsSelected\r\n         lngElementID = Me!lstElemente.ItemData(varElement)\r\n         For Each varBenutzergruppe In Me!lstBenutzergruppen.ItemsSelected\r\n             lngBenutzergruppeID = Me!lstBenutzergruppen.ItemData(varBenutzergruppe)\r\n             lngBerechtigungsstufeID = Nz(DLookup(\"BerechtigungsstufeID\", \"tblObjekteBenutzergruppenBerechtigungen\", _\r\n                 \"ObjektID = \" & lngElementID & \" AND BenutzergruppeID = \" & lngBenutzergruppeID), 3)\r\n             Me!lstBerechtigungsstufen.Selected(lngBerechtigungsstufeID - 1) = <span style=\"color:blue;\">True<\/span>\r\n         <span style=\"color:blue;\">Next<\/span> varBenutzergruppe\r\n     <span style=\"color:blue;\">Next<\/span> varElement\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Prozedur zum Aktualisieren der Anzeige der Berechtigungen f&uuml;r die Kombination aus Element und Benutzergruppe<\/span><\/b><\/p>\n<p>Die Prozedur durchl&auml;uft zun&auml;chst alle Elemente des Listenfeldes <b>lstBerechtigungsstufen <\/b>und stellt den Selektiert-Status auf nicht selektiert ein. Die dazu verwendete Schleife durchl&auml;uft dabei die Elemente mit dem Index von <b>0 <\/b>bis zur Anzahl der Eintr&auml;ge minus eins.<\/p>\n<p>Dann folgt eine <b>For Each<\/b>-Schleife &uuml;ber alle im Listenfeld <b>lstElemente <\/b>selektierten Elemente, die wir mit der Auflistung <b>ItemsSelected <\/b>referenzieren. Das jeweilige Element speichern wir in der Variablen <b>varElement<\/b>. F&uuml;r dieses Element ermitteln wir zun&auml;chst den Wert der ersten Spalte beziehungsweise den Prim&auml;rschl&uuml;sselwert und speichern diesen in der Variablen <b>lngElementID<\/b>.<\/p>\n<p>In einer zweiten <b>For Each<\/b>-Schleife durchlaufen wir alle Elemente des Listenfeldes <b>lstBenutzergruppen<\/b>. Den Prim&auml;rschl&uuml;sselwert des aktuellen Elements referenzieren wir dabei mit der Variablen <b>lngBenutzergruppeID<\/b>.<\/p>\n<p>Nun wird es interessant, denn wir m&uuml;ssen uns auch noch ansehen, unter welchen Bedingungen wir eine der Berechtigungsstufen f&uuml;r die Kombination aus Element und Benutzergruppe als aktiv betrachten wollen. Wenn wir nur ein Element und eine Benutzergruppe markiert haben, ist die Frage leicht zu beantworten, denn es gibt nur einen Wert f&uuml;r die Berechtigungsstufe.<\/p>\n<p>Wenn wir jedoch beispielsweise zwei Elemente markiert haben und eine Benutzergruppe und f&uuml;r das erste Element ist die Berechtigungsstufe <b>Keine <\/b>festgelegt und f&uuml;r das zweite Element die Berechtigungsstufe <b>Alle<\/b>, welche Berechtigungsstufe zeigen wir dann an Damit der Benutzer direkt erkennt, dass es keine eindeutige Berechtigungsstufe gibt, wollen wir hier einfach alle aktiven Berechtigungsstufen f&uuml;r die gew&auml;hlten Elemente markieren.<\/p>\n<p>Das erledigen wir, indem wir f&uuml;r jede Kombination aus Element und Benutzergruppe die Berechtigungsstufe mit <b>DLookup <\/b>ermitteln und das Ergebnis (entweder <b>1<\/b>, <b>2 <\/b>oder <b>3<\/b>) in der Variablen <b>lngBerechtigungsstufeID <\/b>speichern). Dann legen wir das Element des Listenfeldes <b>lstBerechtigungsstufen <\/b>als markiert fest, dessen Index den Wert aus <b>lngBerechtigungsstufeID <\/b>minus eins aufweist (der Index ist 0-basiert, unsere Werte f&uuml;r <b>lngBerechtigungsstufe <\/b>jedoch 1-basiert).<\/p>\n<p>Damit haben wir die Berechtigung eingestellt und k&ouml;nnen &uuml;ber die beiden <b>For Each<\/b>-Schleifen &uuml;ber die beiden Listenfelder die &uuml;brigen Kombinationen aus Element und Benutzergruppe abarbeiten.<\/p>\n<p>In der <b>DLookup<\/b>-Funktion ist noch ein wichtiges Detail versteckt: Wir f&uuml;hren f&uuml;r das Ergebnis n&auml;mlich noch die <b>Nz<\/b>-Funktion aus. Diese liefert den Wert des ersten Parameters, hier der <b>DLookup<\/b>-Funktion, zur&uuml;ck, wenn dieser nicht Null ist. Liefert <b>DLookup <\/b>den Wert <b>Null<\/b>, gibt die <b>Nz<\/b>-Funktion den als zweiten Parameter angegebenen Wert zur&uuml;ck, den wir hier als <b>3 <\/b>eingestellt haben.<\/p>\n<p>Die Berechtigungsstufe <b>3 <\/b>entspricht dem Wert <b>Alle<\/b>. Kombinationen aus Element und Benutzergruppe, f&uuml;r die kein Wert in der Tabelle <b>tblObjekteBenutzergruppenBerechtigungen <\/b>festgelegt ist, erhalten also die Berechtigungsstufe <b>Alle<\/b>.<\/p>\n<h2>Berechtigungen setzen<\/h2>\n<p>Damit kommen wir zu der Prozedur, die durch das Anklicken eines Eintrags des Listenfeldes <b>lstBerechtigungsstufen <\/b>ausgel&ouml;st wird, genau genommen durch das Ereignis <b>Nach Aktualisierung<\/b> (siehe Listing 4).<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>lstBerechtigungsstufen_AfterUpdate()\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>lngBerechtigungsstufeID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngObjektID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngBenutzergruppeID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>varElement<span style=\"color:blue;\"> As Variant<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>varBenutzergruppe<span style=\"color:blue;\"> As Variant<\/span>\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;\">If <\/span>Me!lstElemente.ItemsSelected.Count = 0<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"W&auml;hlen Sie mindestens ein Element aus.\"\r\n         <span style=\"color:blue;\">Exit Sub<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">If <\/span>Me!lstBenutzergruppen.ItemsSelected.Count = 0<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"W&auml;hlen Sie mindestens eine Benutzergruppe aus.\"\r\n         <span style=\"color:blue;\">Exit Sub<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     lngBerechtigungsstufeID = Me!lstBerechtigungsstufen.ListIndex + 1\r\n     For i = 0 To Me!lstBerechtigungsstufen.ListCount - 1\r\n         Me!lstBerechtigungsstufen.Selected(i) = <span style=\"color:blue;\">False<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> i\r\n     Me!lstBerechtigungsstufen.Selected(lngBerechtigungsstufeID - 1) = <span style=\"color:blue;\">True<\/span>\r\n     For Each varElement In Me!lstElemente.ItemsSelected\r\n         lngObjektID = Me!lstElemente.ItemData(varElement)\r\n         For Each varBenutzergruppe In Me!lstBenutzergruppen.ItemsSelected\r\n             lngBenutzergruppeID = Me!lstBenutzergruppen.ItemData(varBenutzergruppe)\r\n             db.Execute \"UPDATE tblObjekteBenutzergruppenBerechtigungen SET BerechtigungsstufeID = \" _\r\n                 & lngBerechtigungsstufeID & \" WHERE ObjektID = \" & lngObjektID & \" AND BenutzergruppeID = \" _\r\n                 & lngBenutzergruppeID, dbFailOnError\r\n             <span style=\"color:blue;\">If <\/span>db.RecordsAffected = 0<span style=\"color:blue;\"> Then<\/span>\r\n                 db.Execute \"INSERT INTO tblObjekteBenutzergruppenBerechtigungen(BerechtigungsstufeID, ObjektID, \" _\r\n                     & \"BenutzergruppeID) VALUES(\" & lngBerechtigungsstufeID & \", \" & lngObjektID & \", \" _\r\n                     & lngBenutzergruppeID & \")\"\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">Next<\/span> varBenutzergruppe\r\n     <span style=\"color:blue;\">Next<\/span> varElement\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Prozedur zum Setzen oder entfernen von Berechtigungen<\/span><\/b><\/p>\n<p>Die Prozedur setzt f&uuml;r die Variable <b>db <\/b>einen Verweis auf das <b>Database<\/b>-Objekt der aktuellen Datenbank. Dann pr&uuml;ft sie, ob mindestens ein Eintrag des Listenfeldes <b>lstElemente <\/b>markiert ist (der Benutzer kann ja auch mehrere Eintr&auml;ge gleichzeitig markieren). Ist das nicht der Fall, erscheint eine entsprechende Meldung und die Prozedur wird abgebrochen.<\/p>\n<p>Danach pr&uuml;ft die Prozedur auch f&uuml;r das Listenfeld <b>lstBenutzergruppen<\/b>, ob mindestens ein Eintrag markiert ist. Auch hier folgt in dem Fall, dass kein Eintrag markiert ist, eine Meldung und der Abbruch der Prozedur.<\/p>\n<p>Dann ermittelt die Prozedur die Berechtigungsstufe, die der Benutzer im Listenfeld <b>lstBerechtigungsstufen <\/b>angeklickt hat. Normalerweise k&ouml;nnten wir diese &uuml;ber <b>Me!lstBerechtigungsstufen <\/b>ermitteln, aber nur, wenn das Listenfeld nur die Auswahl eines Eintrags gleichzeitig erlaubt.<\/p>\n<p>Wir haben aber die Eigenschaft <b>Mehrfachauswahl <\/b>f&uuml;r dieses Listenfeld auf <b>Einzeln <\/b>eingestellt, damit wir, wenn der Benutzer Elemente ausgew&auml;hlt hat, f&uuml;r die verschiedene Berechtigungsstufen festgelegt wurden, dies auch abbilden k&ouml;nnen. <b>Me!lstBerechtigungsstufen <\/b>w&uuml;rde bei der Einstellung <b>Einzeln <\/b>f&uuml;r <b>Mehrfachauswahl <\/b>den Wert <b>Null <\/b>zur&uuml;ckliefern, was uns lediglich einen Fehler beschert.<\/p>\n<p>Also verwenden wir den Weg &uuml;ber die Eigenschaft <b>ListIndex<\/b>. Diese bringt allerdings einen der Wert <b>0<\/b>, <b>1 <\/b>oder <b>2<\/b>, da der Index 0-basiert ist.<\/p>\n<p>Da wir aber wissen, dass die Datens&auml;tze in der Tabelle <b>tblBerechtigungsstufen <\/b>die Prim&auml;rschl&uuml;sselwerte <b>1<\/b>, <b>2 <\/b>und <b>3 <\/b>aufweisen und auch in dieser Reihenfolge angezeigt werden, k&ouml;nnen wir einfach den Wert <b>1 <\/b>zur Eigenschaft <b>ListIndex <\/b>hinzuaddieren, um die Berechtigungsstufe f&uuml;r die zuletzt angeklickte Zeile zu ermitteln.<\/p>\n<p>Da wir, auch wenn zuvor f&uuml;r die angezeigte Kombination aus Element und Benutzergruppe mehr als eine Berechtigungsstufe zugewiesen war, durch einen Klick auf eine Stufe genau diese Stufe festlegen, wollen wir zun&auml;chst alle anderen aktuell markierten Berechtigungsstufen aus dem Listenfeld entfernen. Das erledigen wir in einer <b>For&#8230;Next<\/b>-Schleife &uuml;ber alle Listeneintr&auml;ge, in der wir die Eigenschaft <b>Selected <\/b>f&uuml;r den Eintrag mit dem aktuellen Wert der Laufvariable <b>i <\/b>auf <b>False <\/b>einstellen.<\/p>\n<p>Danach stellen wir die Eigenschaft <b>Selected <\/b>f&uuml;r den Eintrag mit dem Index <b>lngBerechtigungsstufe &#8211; 1 <\/b>auf <b>True <\/b>ein, damit der gew&uuml;nschte Eintrag im Listenfeld bereits als ausgew&auml;hlt angezeigt.<\/p>\n<p>Danach folgt der interessante Teil, in dem wir die neu festgelegten Berechtigungen in die Tabelle <b>tblObjekteBenutzergruppenBerechtigungen <\/b>eintragen. Hier durchlaufen wir zwei verschachtelte <b>For Each<\/b>-Schleifen. Die erste durchl&auml;uft alle im Listenfeld <b>lstElemente <\/b>selektierten Eintr&auml;ge und speichert den Index jeweils in der Laufvariablen <b>varElement<\/b>. &uuml;ber die Eigenschaft <b>ItemData <\/b>des Listenfeldes <b>lstElemente <\/b>ermitteln wir dann den Wert der gebundenen Spalte f&uuml;r diesen Eintrag, der dem Prim&auml;rschl&uuml;sselwert des Eintrags in der Tabelle <b>tblElemente <\/b>entspricht, und schreiben diese in die Variable <b>lngObjektID<\/b>.<\/p>\n<p>In der inneren <b>For Each<\/b>-Schleife &uuml;ber alle selektierten Eintr&auml;ge des Listenfeldes <b>lstBenutzergruppen <\/b>tragen wir zun&auml;chst den Prim&auml;rschl&uuml;sselwert des jeweils selektierten Eintrags in die Variable <b>lngBenutzergruppeID <\/b>ein. Danach f&uuml;hren wir eine <b>UPDATE<\/b>-Anweisung als Parameter der <b>Execute<\/b>-Methode des <b>Database<\/b>-Objekts aus, das versucht, den Eintrag in der Tabelle <b>tblObjekteBenutzergruppenBerechtigungen <\/b>zu aktualisieren, f&uuml;r den das Feld <b>ObjektID <\/b>dem Wert aus <b>lngObjektID <\/b>und <b>BenutzergruppeID <\/b>dem Wert auf <b>lngBenutzergruppe <\/b>entspricht. F&uuml;r diesen Datensatz soll die Abfrage den Wert des Feldes <b>BerechtigungsstufeID <\/b>auf den Wert der Variablen <b>lngBerechtigungsstufeID <\/b>einstellen.<\/p>\n<p>Da ja standardm&auml;&szlig;ig erst ein Datensatz f&uuml;r eine Kombination aus Element und Benutzergruppe in der Tabelle <b>tblObjekteBenutzergruppenBerechtigungen <\/b>angelegt werden soll, wenn der Benutzer eine Berechtigung definiert hat und ansonsten die Berechtigung <b>Alle <\/b>angenommen wird, findet die <b>UPDATE<\/b>-Abfrage gelegentlich noch gar keinen passenden Datensatz vor, den sie aktualisieren k&ouml;nnte.<\/p>\n<p>Dies pr&uuml;fen wir in der folgenden <b>If&#8230;Then<\/b>-Bedingung, in der wir untersuchen, ob die Eigenschaft <b>RecordsAffected <\/b>des <b>Database<\/b>-Objekts den Wert <b>0 <\/b>zur&uuml;ckgibt. Diese Eigenschaft enth&auml;lt jeweils die Anzahl der von der vorher ausgef&uuml;hrten SQL-Anweisung betroffenen Datens&auml;tze. Ist diese Anzahl <b>0<\/b>, wurde offensichtlich noch kein passender Datensatz gefunden.<\/p>\n<p>In diesem Fall f&uuml;hren wir eine weitere SQL-Anweisung mit der <b>Execute<\/b>-Methode aus, diesmal aber eine <b>INSERT INTO<\/b>-Anweisung. Diese f&uuml;gt einen neuen Datensatz zur Tabelle <b>tblObjekteBenutzergruppenBerechtigungen <\/b>hinzu und tr&auml;gt f&uuml;r die Felder <b>ObjektID<\/b>, <b>BenutzergruppeID <\/b>und <b>BerechtigungsstufeID <\/b>die Werte der Variablen <b>lngObjektID<\/b>, <b>lngBenutzergruppeID <\/b>und <b>lngBerechtigungsstufeID <\/b>ein.<\/p>\n<p>Damit ist die Prozedur auch abgeschlossen. Schauen wir uns das Ergebnis einmal im Formular <b>frmBerechtigungen <\/b>und in der Tabelle <b>tblObjekteBenutzergruppenBerechtigungen <\/b>an. Im Formular <b>frmBerechtigungen <\/b>markieren wir das Formular <b>frmIntro <\/b>und dort die beiden Elemente <b>cmdGo <\/b>und <b>Form<\/b>. Die Berechtigungen f&uuml;r das Startformular sollen f&uuml;r die beiden Benutzergruppen <b>Bestellannahme <\/b>und <b>Management <\/b>gesetzt werden, also markieren wir diese beiden Eintr&auml;ge. Nun klicken wir im Listenfeld <b>lstBerechtigungsstufen <\/b>auf den Eintrag <b>Alle<\/b> (siehe Bild 11).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_02\/pic_1180_011.png\" alt=\"Festlegen einiger Berechtigungen\" width=\"649,559\" height=\"286,7064\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 11: Festlegen einiger Berechtigungen<\/span><\/b><\/p>\n<p>Danach finden wir in der Tabelle <b>tblObjekteBenutzergruppenBerechtigungen <\/b>die Eintr&auml;ge wie in Bild 12 vor &#8211; vorausgesetzt, vorher hatten Sie noch keine Berechtigungen festgelegt.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2019_02\/pic_1180_012.png\" alt=\"Berechtigungen in der Tabelle \" width=\"424,7115\" height=\"164,0931\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 12: Berechtigungen in der Tabelle <\/span><\/b><\/p>\n<h3>Downloads zu diesem Beitrag<\/h3>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>BerechtigungenFuerAccessObjektePerSQLServerII.indd<\/p>\n<p>Suedsturm_SQL.bak<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/093BD23C-AEEC-4936-BD7C-1AC6611E6E76\/aiu_1170.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Im Beitrag &#8222;Berechtigungen f&uuml;r Access-Objekte per SQL Server I: Tabellen&#8220; haben wir ein Datenmodell entwickelt f&uuml;r die Verwaltung der Berechtigungen verschiedener Benutzergruppen auf die Formulare, Berichte und Steuer-elemente einer Access-Anwendung &#8211; gesteuert &uuml;ber die jeweilige Anmeldung an der SQL Server-Datenbank. Im zweiten Teil dieser Beitragsreihe verkn&uuml;pfen wir die Access-Anwendung mit diesen Tabellen und erstellen die Formulare, die zur Bearbeitung der f&uuml;r die Berechtigungsverwaltung notwendigen Tabellen erforderlich sind.<\/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":[66022019,662019,44000022],"tags":[],"class_list":["post-55001170","post","type-post","status-publish","format-standard","hentry","category-66022019","category-662019","category-SQL_Server_und_Co"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.4) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Berechtigungen f&uuml;r Access-Objekte per SQL Server II: Formulare - 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\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Berechtigungen f&uuml;r Access-Objekte per SQL Server II: Formulare\" \/>\n<meta property=\"og:description\" content=\"Im Beitrag &quot;Berechtigungen f&uuml;r Access-Objekte per SQL Server I: Tabellen&quot; haben wir ein Datenmodell entwickelt f&uuml;r die Verwaltung der Berechtigungen verschiedener Benutzergruppen auf die Formulare, Berichte und Steuer-elemente einer Access-Anwendung - gesteuert &uuml;ber die jeweilige Anmeldung an der SQL Server-Datenbank. Im zweiten Teil dieser Beitragsreihe verkn&uuml;pfen wir die Access-Anwendung mit diesen Tabellen und erstellen die Formulare, die zur Bearbeitung der f&uuml;r die Berechtigungsverwaltung notwendigen Tabellen erforderlich sind.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2020-05-13T21:06:19+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg06.met.vgwort.de\/na\/e677189bc90e48d3baff5217238ea822\" \/>\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\\\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Berechtigungen f&uuml;r Access-Objekte per SQL Server II: Formulare\",\"datePublished\":\"2020-05-13T21:06:19+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\\\/\"},\"wordCount\":3877,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg06.met.vgwort.de\\\/na\\\/e677189bc90e48d3baff5217238ea822\",\"articleSection\":[\"2\\\/2019\",\"2019\",\"SQL Server und Co.\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\\\/\",\"name\":\"Berechtigungen f&uuml;r Access-Objekte per SQL Server II: Formulare - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg06.met.vgwort.de\\\/na\\\/e677189bc90e48d3baff5217238ea822\",\"datePublished\":\"2020-05-13T21:06:19+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg06.met.vgwort.de\\\/na\\\/e677189bc90e48d3baff5217238ea822\",\"contentUrl\":\"http:\\\/\\\/vg06.met.vgwort.de\\\/na\\\/e677189bc90e48d3baff5217238ea822\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Berechtigungen f&uuml;r Access-Objekte per SQL Server II: Formulare\"}]},{\"@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":"Berechtigungen f&uuml;r Access-Objekte per SQL Server II: Formulare - 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\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\/","og_locale":"de_DE","og_type":"article","og_title":"Berechtigungen f&uuml;r Access-Objekte per SQL Server II: Formulare","og_description":"Im Beitrag \"Berechtigungen f&uuml;r Access-Objekte per SQL Server I: Tabellen\" haben wir ein Datenmodell entwickelt f&uuml;r die Verwaltung der Berechtigungen verschiedener Benutzergruppen auf die Formulare, Berichte und Steuer-elemente einer Access-Anwendung - gesteuert &uuml;ber die jeweilige Anmeldung an der SQL Server-Datenbank. Im zweiten Teil dieser Beitragsreihe verkn&uuml;pfen wir die Access-Anwendung mit diesen Tabellen und erstellen die Formulare, die zur Bearbeitung der f&uuml;r die Berechtigungsverwaltung notwendigen Tabellen erforderlich sind.","og_url":"https:\/\/access-im-unternehmen.de\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\/","og_site_name":"Access im Unternehmen","article_published_time":"2020-05-13T21:06:19+00:00","og_image":[{"url":"http:\/\/vg06.met.vgwort.de\/na\/e677189bc90e48d3baff5217238ea822","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\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Berechtigungen f&uuml;r Access-Objekte per SQL Server II: Formulare","datePublished":"2020-05-13T21:06:19+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\/"},"wordCount":3877,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\/#primaryimage"},"thumbnailUrl":"http:\/\/vg06.met.vgwort.de\/na\/e677189bc90e48d3baff5217238ea822","articleSection":["2\/2019","2019","SQL Server und Co."],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\/","url":"https:\/\/access-im-unternehmen.de\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\/","name":"Berechtigungen f&uuml;r Access-Objekte per SQL Server II: Formulare - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\/#primaryimage"},"thumbnailUrl":"http:\/\/vg06.met.vgwort.de\/na\/e677189bc90e48d3baff5217238ea822","datePublished":"2020-05-13T21:06:19+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\/#primaryimage","url":"http:\/\/vg06.met.vgwort.de\/na\/e677189bc90e48d3baff5217238ea822","contentUrl":"http:\/\/vg06.met.vgwort.de\/na\/e677189bc90e48d3baff5217238ea822"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Berechtigungen_fuer_AccessObjekte_per_SQL_Server_II_Formulare\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Berechtigungen f&uuml;r Access-Objekte per SQL Server II: Formulare"}]},{"@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\/55001170","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=55001170"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001170\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55001170"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55001170"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55001170"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}