Berechtigungen per HTML verwalten

Wenn Sie ein Abonnement des Magazins 'Access im Unternehmen' besitzen, können Sie sich anmelden und den kompletten Artikel lesen.
Anderenfalls können Sie das Abonnement hier im Shop erwerben.

Berechtigungen per HTML verwalten

Im Beitrag »Benutzerverwaltung mit verschlüsselten Kennwörtern« stellen wir eine Lösung vor, in der wir die Berechtigungen von Benutzergruppen an Datenbankobjekten definieren. Dort benötigen wir ein Formular, mit dem wir die Berechtigungen für die einzelnen Objekte für die jeweilige Benutzergruppe definieren wollen. Dazu wollen wir eine Matrix anzeigen, welche die Berechtigungen und die Objekte als Spalten- und Zeilenüberschriften anzeigt und die Möglichkeit bietet, in den Zellen anzugeben, ob die Berechtigung gesetzt ist oder nicht. Dies erledigen wir mit einem Webbrowser-Steuerelement, indem wir die notwendigen Elemente per HTML darstellen.

Der erste Entwurf des Formulars sieht wie in Bild 1 aus. Wir haben dem Formular ein Kombinationsfeld namens cboBenutzergruppeID hinzugefügt sowie ein Webbrowser-Steuerelement namens objWebbrowser.

Erster Entwurf des Formulars

Bild 1: Erster Entwurf des Formulars

Das Kombinationsfeld soll die Benutzergruppen aus der Tabelle tblBenutzergruppen anzeigen, und zwar so, dass das Feld BenutzergruppeID als gebundene Spalte ausgeblendet wird und nur die Bezeichnung der Benutzergruppe erscheint. Dazu weisen wir der Eigenschaft Datensatzherkunft die folgende Abfrage zu:

SELECT BenutzergruppeID, Benutzergruppe 
FROM tblBenutzergruppen 
ORDER BYBenutzergruppe;

Damit nur die Benutzergruppe angezeigt wird, stellen wir die Eigenschaft Spaltenanzahl auf 2 und die Eigenschaft Spaltenbreiten auf 0cm ein.

Für das Zusammenstellen des HTML-Code benötigen wir noch die Objektbibliothek Microsoft HTML Object Library, die wir wie in Bild 2 über den Verweise-Dialog des VBA-Editors hinzufügen (Menüeintrag Extras|Verweise).

Verweise des VBA-Projekts

Bild 2: Verweise des VBA-Projekts

Gewünschte Darstellung

Wir möchten nicht einfach nur eine Darstellung mit Kontrollkästchen oder ähnlichen Steuer­elementen, sondern einmal etwas Besonderes programmieren: nämlich eine Darstellung, bei der die gesetzten Rechte in Grün und die nicht gesetzten Rechte in Rot dargestellt werden. Das sieht dann etwa für die Benutzergruppe Administratoren wie in Bild 3 aus.

Setzen der Berechtigungen über verschiedene Farben

Bild 3: Setzen der Berechtigungen über verschiedene Farben

Funktionen des Formulars

Das Formular soll, wie oben erwähnt, die Auswahl einer der Benutzergruppen über das Kombinationsfeld oben im Formular ermöglichen. Nach der Auswahl sollen die Berechtigungen für die gewählte Benutzergruppe angezeigt werden.

Außerdem wollen wir die folgenden Funktionen durch Anklicken der verschiedenen Bereiche der HTML-Seite im Webbrowser-Steuerelement realisieren:

  • Wenn der Benutzer auf die rot markierte Berechtigung Keine klickt und diese so auf Grün einstellt, sollen automatisch die übrigen Berechtigungen für die Tabelle für diesen Benutzer auf Rot eingestellt werden.
  • Wenn der Benutzer die grün markierte Berechtigung Keine anklickt und diese so auf Rot einstellt, sollen die übrigen Berechtigungen für diese Tabelle auf Grün eingestellt werden.
  • Wenn der Benutzer eine der Berechtigungen Lesen, Anlegen, Ändern oder Löschen anklickt, während diese Rot ist, soll diese auf Grün eingestellt werden und umgekehrt.
  • Dabei gilt die folgende Sonderregel: Wenn er die letzte grün markierte Berechtigung (also Lesen, Anlegen, Ändern oder Löschen) anklickt und diese so auf Rot einstellt, soll automatisch die Berechtigung Keine auf Grün eingestellt werden.
  • Klickt der Benutzer auf einen der Spaltenköpfe Keine, Lesen, Anlegen, Ändern oder Löschen, werden alle Einträge dieser Spalte auf Grün eingestellt. Handelt es sich um den Spaltenkopf Keine, werden alle anderen Spalten komplett auf Rot eingestellt. Handelt es sich um eine der anderen Spalten, wird diese komplett auf Grün eingestellt und die Spalte Keine logischerweise komplett auf Rot.

Wenn Keine grün ist, müssen also alle anderen Spalten für diese Tabelle rot sein, wenn eine der anderen Spalten grün ist, muss Keine rot sein.

Initialisieren des Formulars

Im Klassenmodul des Formulars deklarieren wir die folgenden Variablen im allgemeinen Teil, das heißt, die Variablen sind modulweit zugreifbar:

Dim WithEvents objWebbrowser As WebBrowser
Dim WithEvents objDocument As HTMLDocument
Public colCells As Collection
Public colCellWrapper As Collection

Die ersten beiden Variablen referenzieren später das Webbrowser-Steuerelement sowie das darin angezeigte Dokument. Die übrigen beiden, colCells und colCellWrapper, sind Collection-Objekte, welche Objekte aufnehmen, die wir auf Basis zweier weiter unten beschrieben Klassen erstellen – und zwar für jedes Element der Tabelle aus der Kopfzeile und den farbig zu markierenden Tabellenzellen.

Beim Öffnen des Formulars weisen wir der Variablen obj­Webbrowser das Steuer­element ctlWebbrowser.Object zu. Außerdem stellen wir die Eigenschaft TimerInterval auf 50 ein, was dazu führt, dass die Ereignisprozedur Bei Zeitgeber 50 Millisekunden nach dem Einstellen dieser Eigenschaft aufgerufen wird:

Private Sub Form_Open(Cancel As Integer)
     Set objWebbrowser = Me!ctlWebbrowser.Object
     Me.TimerInterval = 50
End Sub

Die durch das Ereignis Bei Zeitgeber ausgelöste Prozedur zeigt zunächst eine leere Seite im Webbrowser-Steuerelement an und stellt die Variable objDocument auf die Eigenschaft Document des Webbrowser-Steuerelements ein. Dann stellt sie TimerInterval auf 0, damit das Ereignis Bei Zeitgeber nicht nochmals ausgelöst wird. Schließlich stellt sie das Kombinationsfeld cboBenutzergruppeID auf den ersten Eintrag der Datensatzherkunft ein und ruft die Prozedur TabelleErstellen auf. Dieser übergibt sie die aktuell im Kombinationsfeld ausgewählte Benutzergruppe als Parameter, damit die Prozedur die dazu gehörenden Berechtigungen im Webbrowser-Steuerelement anzeigt:

Private Sub Form_Timer()
     objWebbrowser.Navigate "about:blank"
     Set objDocument = objWebbrowser.Document
     Me.TimerInterval = 0
     DoEvents
     Me!cboBenutzergruppeID =  Me!cboBenutzergruppeID.ItemData(0)
     TabelleErstellen Me!cboBenutzergruppeID
End Sub

Die Prozedur TabelleErstellen wird außerdem aufgerufen, wenn der Benutzer im Kombinationsfeld cboBenutzergruppe einen anderen Eintrag auswählt. Dazu legen wir die folgende Prozedur an, die durch das Ereignis Nach Aktualisierung des Kombinationsfeldes aufgerufen wird:

Private Sub cboBenutzergruppeID_AfterUpdate()
     TabelleErstellen Me!cboBenutzergruppeID
End Sub

CSS-Definition

In der nachfolgend mit der Prozedur TabelleErstellen zusammengestellten HTML-Tabelle verwenden wir auch einige Zeilen CSS-Code. Diese stellen wir mit der folgenden Funktion zusammen. Die ersten CSS-Anweisungen legen die Schriftart, Schriftgröße, Ausrichtung und Rahmeneigenschaften für die Tabellen fest:

Public Function CSS()
     Dim strCSS As String
     strCSS = strCSS & "table {"
     strCSS = strCSS & " font-family: Calibri;"
     strCSS = strCSS & "  text-align: center;"
     strCSS = strCSS & "  width: 100%;"
     strCSS = strCSS & "  border-collapse: collapse;"
     strCSS = strCSS & "}"
     strCSS = strCSS & "td.columnHeader {"
     strCSS = strCSS & "  font-weight: bold;"
     strCSS = strCSS & "  border-bottom: 1px solid black;"
     strCSS = strCSS & "}"
     strCSS = strCSS & "td.rowHeader {"
     strCSS = strCSS & "  font-weight: bold;"
     strCSS = strCSS & "  border-right: 1px solid black;"
     strCSS = strCSS & "  text-align: left;"
     strCSS = strCSS & "}"

Dann folgen zwei Definitionen für CSS-Klassen, welche die Hintergrundfarben für die roten und grünen Zellen festlegen:

     strCSS = strCSS & "td.redcell{"
     strCSS = strCSS & "  border-color: white;"
     strCSS = strCSS & "  border-width: 1px;"
     strCSS = strCSS & "  border-style: solid;"
     strCSS = strCSS & "  background: red;"
     strCSS = strCSS & "}"
     strCSS = strCSS & "td.greencell{"
     strCSS = strCSS & "  border-color: white;"
     strCSS = strCSS & "  border-width: 1px;"
     strCSS = strCSS & "  border-style: solid;"
     strCSS = strCSS & "  background: green;"
     strCSS = strCSS & "}"

Dann benötigen wir noch zwei Klassen für die Breite der ersten Spalte (50%) und die der folgenden fünf Spalten (jeweils 10%):

     strCSS = strCSS & ".th1 {"
     strCSS = strCSS & "  width:50%;"
     strCSS = strCSS & "  text-align:left;"
     strCSS = strCSS & "}"
     strCSS = strCSS & ".th2 {"
     strCSS = strCSS & "  width:10%;"
     strCSS = strCSS & "  text-align:left;"
     strCSS = strCSS & "}"

Schließlich fehlt noch eine CSS-Klasse namens scrolling, welche die Höhe des zu scrollenden Bereiches festlegt und dass dieser gescrollt werden kann:

     strCSS = strCSS & ".scrolling {"
     strCSS = strCSS & "  height:300px;"
     strCSS = strCSS & "  overflow:auto;"
     strCSS = strCSS & "}"
     CSS = strCSS
End Function

Tabelle zusammenstellen

Nach dieser Vorbereitung kommen wir zur Prozedur TabelleErstellen, deren ersten Teil Sie in Listing 1 finden. Diese Prozedur deklarieren wir als öffentliche Prozedur, damit wir später von Klassenobjekten, die wir von dieser Prozedur aus erstellt haben, erneut auf diese Prozedur zugreifen können, um die Tabelle neu zu erstellen.

Public Sub TabelleErstellen(lngBenutzergruppeID As Long)
     Dim db As DAO.Database
     Dim rstSpaltenkoepfe As DAO.Recordset
     Dim rstZeilen As DAO.Recordset
     Dim rstWerte As DAO.Recordset
     Dim objTable As MSHTML.HTMLTable
     Dim objRow As MSHTML.HTMLTableRow
     Dim objCell As MSHTML.HTMLTableCell
     Dim objCSS As Object
     Dim objCellHeaderWrapper As clsCellHeaderWrapper
     Dim objInnerTable As MSHTML.HTMLTable
     Dim objDiv As MSHTML.HTMLDivElement
     Set colCells = New Collection
     Set colCellWrapper = New Collection
     Set objCSS = objDocument.createStyleSheet("")
     objCSS.cssText = CSS
     Set db = CurrentDb
     objDocument.body.innerHTML = ""
     Set objTable = objDocument.createElement("Table")
     objDocument.body.appendChild objTable
     Set objRow = objTable.insertRow
     Set objCell = objRow.insertCell
     objCell.className = "columnHeader rowHeader th1"
     Set rstSpaltenkoepfe = db.OpenRecordset("SELECT BerechtigungID, Berechtigung FROM tblBerechtigungen", dbOpenDynaset)
     Do While Not rstSpaltenkoepfe.EOF
         Set objCell = objRow.insertCell
         objCell.className = "columnHeader th2"
         objCell.innerText = rstSpaltenkoepfe!Berechtigung
         Set objCellHeaderWrapper = New clsCellHeaderWrapper
         With objCellHeaderWrapper
             Set .cell = objCell
             .BerechtigungID = rstSpaltenkoepfe!BerechtigungID
             .BenutzergruppeID = Me!cboBenutzergruppeID
             Set .Form = Me
         End With
         colCellWrapper.Add objCellHeaderWrapper
         rstSpaltenkoepfe.MoveNext
     Loop

Listing 1: Prozedur TabelleErstellen, Teil 1

Die Prozedur erwartet die ID der Benutzergruppe, deren Berechtigungen an den verschiedenen Tabellen der Datenbank in der HTML-Tabelle dargestellt werden sollen. Sie deklariert eine ganze Reihe von Variablen. Die drei Variablen rstSpaltenkoepfe, rstZeilen und rstWerte nehmen die Recordsets auf, deren Daten wir in der HTML-Tabelle abbilden wollen. Wie wir diese genau füllen, erfahren Sie weiter unten.

Dazu benötigen wir einige Objekte, mit denen wir die Objekte der HTML-Seite definieren und hierarchisch anordnen. Wir wollen in diesem Beispiel nicht wie etwa in dem Beispiel zum Beitrag HTML-Tabellen mit fester Kopfzeile (www.access-im-unternehmen.de/1188) den HTML-Code in einer String-Variablen zusammensetzen, sondern diesmal das Objektmodell für HTML verwenden (DOM, Document Object Model).

Die ersten Anweisungen der Prozedur erzeugen jeweils neue Collection-Objekte für die beiden Variablen colCells und colCellWrapper, die wie im Kopf des Klassenmoduls deklariert haben. Dann erstellen wir die Klasse, welche den Code der Funktion CSS als Wert der Eigenschaft cssText aufnimmt. Außerdem benötigen wir ein Database-Objekt für den Zugriff auf die Objekte der aktuellen Datenbank.

Für das mit der Variablen objDocument referenzierten Objektvariablen für das Dokument im Webbrowser-Steuerelement stellen wir die Eigenschaft body.innerHTML auf eine leere Zeichenkette ein. Dann erstellen wir für objDocument mit der createElement-Methode ein neues Element des Typs Table und hängen es mit der appendChild-methode an das body-Objekt von objDocument an. Als Nächstes fügen wir unterhalb des Table-Objekts aus objTable mit der insertRow-Methode ein neues Row-Element ein und referenzieren es mit objRow. Darin fügen wir nun ein erstes Cell-Objekt ein, welches der linken, oberen Zelle entspricht, die keinen Text aufnehmen soll. Dazu verwenden wir die insertCell-Methode von objRow und speichern das Ergebnis in objCell. objCell ist das erste Objekt, dem wir CSS-Klassen zuweisen. Das erledigen wir über die Eigenschaft className, der wir den Text columnHeader rowHeader th1 zuweisen. Dadurch nimmt das Element die in den drei CSS-Klassen td.columnHeader, td.rowHeader und th1 angegebenen Attribute an.

Danach füllen wir die erste Recordset-Variable namens rstSpaltenkoepfe, und zwar mit den Feldern BerechtigungID und Berechtigung der Datensätze der Tabelle tblBerechtigungen. Diese durchlaufen wir anschließend in einer Do While-Schleife über alle Einträge des Recordsets. In der Do While-Schleife erstellen wir jeweils ein neues Cell-Objekt und referenzieren diese wieder mit objCell. Wir weisen über die Eigenschaft className die beiden CSS-Klassen columnHeader und th2 zu. Außerdem wollen wir den in den Zellen anzuzeigenden Text definieren. Diesen entnehmen wir dem Feld Berechtigung des aktuellen Datensatzes des Recordsets rstSpaltenkoepfe.

Ereignisse für Spaltenköpfe

Für diese Spaltenköpfe, jeweils einer für jeden Berechtigungstyp, wollen wir nun jeweils eine Ereignisprozedur definieren, die beim Anklicken des Spaltenkopfes ausgelöst wird. Das können wir nicht so einfach wie bei einer Schaltfläche in einem Access-Formular erledigen, denn es handelt sich ja bei den Tabellenzellen nicht um Steuerelemente, die wir dem Formularentwurf hinzufügen und deren Ereigniseigenschaften wir dann definieren und mit Ereignisprozeduren hinterlegen können. Es ist etwas komplizierter. Wir benötigen für jedes mit Ereignissen zu versehende Element eine eigene Instanz einer Klasse, die dann wiederum auf das darin deklarierte Element verweist und die gewünschten Ereignisse des Elements implementiert.

Wir schauen uns die Sache erst einmal der Seite unserer Prozedur an, mit der wir die HTML-Tabelle erstellen. Dort legen wir für jedes Cell-Element für eine Berechtigung ein neues Objekt auf Basis der Klasse clsCellHeaderWrapper an und speichern es in der Variablen objCellHeaderWrapper. Diesem weisen wir dann über die Eigenschaft cell die Objektvariable objCell zu. Die Eigenschaft BerechtigungID erhält den Wert des Feldes BerechtigungID des aktuellen Datensatzes des Recordsets rstSpaltenkoepfe. Die Eigenschaft BenutzergruppeID erhält den Wert des Kombinationsfeldes cboBenutzergruppeID des Formulars. Außerdem stellen wir über die Eigenschaft Form noch einen Verweis auf das Formular ein (Me).

Da wir objCellHeaderWrapper schon im nächsten Schleifendurchlauf mit den Eigenschaften des nächsten Cell-Objekts füllen, speichern wir die aktuelle Instanz noch schnell mit der Add-Methode in der Collection colCellWrapper. Danach bewegen wir den Datensatzzeiger zu nächsten Datensatz und beginnen die Schleife von vorn, bis alle fünf Berechtigungen durchlaufen sind. Damit steht schon einmal die erste Zeile der Tabelle.

Tabellenkörper hinzufügen

Den zweiten Teil der Prozedur TabelleErstellen finden Sie in Listing 2. Hier füllen wir das Recordset rstZeilen mit allen Datensätzen der Tabelle tblTabellen. Bevor wir diese durchlaufen, legen wir noch einige weitere Elemente an. Dem Objekt objTable fügen wir mit insertRow eine neue Zeile hinzu, die wir in objRow speichern. Dieser fügen wir diesmal nur eine einzige Zelle hinzu, die sich aber durch den Wert 6 für die Eigenschaft colSpan über die kompletten sechs Spalten der ersten Zeile der Tabelle erstreckt.

     Set rstZeilen = db.OpenRecordset("SELECT * FROM tblTabellen", dbOpenDynaset)
     Set objRow = objTable.insertRow
     Set objCell = objRow.insertCell
     objCell.colSpan = 6
     Set objDiv = objDocument.createElement("Div")
     objCell.appendChild objDiv
     objDiv.className = "scrolling"
     Set objInnerTable = objDocument.createElement("Table")
     objDiv.appendChild objInnerTable
     Do While Not rstZeilen.EOF
         Set objRow = objInnerTable.insertRow
         rstSpaltenkoepfe.MoveFirst
         Set objCell = objRow.insertCell
         objCell.innerText = rstZeilen!Tabelle
         objCell.className = "rowHeader th1"
         Set rstWerte = db.OpenRecordset("SELECT BerechtigungszuordnungID, BenutzergruppeID, TabelleID, " _
             "BerechtigungID FROM tblBerechtigungszuordnungen WHERE BenutzergruppeID = " & lngBenutzergruppeID _

Dies war die Leseprobe dieses Artikels.
Melden Sie sich an, um auf den vollständigen Artikel zuzugreifen.

Bitte geben Sie die Zeichenfolge in das nachfolgende Textfeld ein

Die mit einem * markierten Felder sind Pflichtfelder.

Ich habe die Datenschutzbestimmungen zur Kenntnis genommen.