Kundenverwaltung mit Ribbon, Teil II

Lies diesen Artikel und viele weitere mit einem kostenlosen, einwöchigen Testzugang.

Im Beitrag “Ribbonklassen” (www.access-im-unternehmen.de/1069) haben wir Klassen für die Anzeige von Ribbons und den enthaltenen Steuer-elementen eingeführt, die wir in “Kundenverwaltung mit Ribbon, Teil I” (www.access-im-unternehmen.de/1091) in eine Anwendung eingebaut haben. Ein Leser fragte nun, ob man damit nicht auch benutzerabhängige Ribbons anzeigen kann. Natürlich geht das – wie es funktioniert, zeigt der vorliegende Beitrag. Darüber hinaus erweitern wir unser Beispiel noch um ein paar neue Elemente.

Benutzerdefinierte Ribbon-Einträge

Im ersten Beispiel wollen wir das Ribbon, das mit dem Formular frmKundenuebersicht angezeigt wird, in Abhängigkeit vom angemeldeten Benutzer die Schaltfläche zum Löschen eines Kunden aktiviert oder deaktiviert.

Zu diesem Zweck wollen wir nun keine Benutzerverwaltung zur Anwendung hinzufügen, sondern zeigen einfach beim öffnen der Anwendung ein Meldungsfenster an, das den Benutzer fragt, ob er ein Administrator ist oder nicht.

Nur Administratoren sollen Kunden löschen dürfen. Das Ergebnis dieser Abfrage speichern wir dann in einer temporären Variablen (TempVar).

Dazu ändern wir die beim öffnen durch das AutoExec-Makro aufgerufene Prozedur wie in Listing 1. Mit der MsgBox-Funktion ermitteln wir den Wert für die lokale Boolean-Variable bolAdministrator, deren Inhalt wir dann in die neu zu erstellende TempVar-Variable mit dem Namen IstAdministrator schreiben.

Public Function RibbonLaden()
     Dim bolAdministrator As Boolean
     bolAdministrator = MsgBox("Sind Sie ein Administrator (Ja) oder ein normaler Benutzer (Nein)", _
         vbYesNo) = vbYes
     TempVars.Add "IstAdministrator", bolAdministrator
     Startribbon.CreateRibbon
End Function

Listing 1: Speichern des Benutzer-Status beim öffnen der Anwendung

In der Code behind-Klasse des Formulars frmKundenuebersicht ist eine kleine änderung am Code notwendig. Sie müssen lediglich die Prozedur Form_Load, die beim Laden des Formulars ausgelöst wird, wie folgt erweitern:

Private Sub Form_Load()
     CreateRibbon
     If TempVars("IstAdministrator") = True Then
         btnKundeLoeschen.Enabled = True
     Else
         btnKundeLoeschen.Enabled = False
     End If
End Sub

Die Prozedur prüft nach dem Erstellen des Ribbons durch die Prozedur CreateRibbon, ob die TempVars-Variable IstAdministrator den Wert True enthält. Falls ja, wird die Eigenschaft Enabled des Objekts btnKundeLoeschen auf True eingestellt, sonst auf den Wert False.

Die kürzere Variante dieses Konstrukts sieht so aus:

Private Sub Form_Load()
     CreateRibbon
     btnKundeLoeschen.Enabled = TempVars("IstAdministrator")
End Sub

Wenn Sie beim öffnen der Anwendung nun die Meldung mit der Frage nach Administrator oder Benutzer mit Benutzer beantworten, sieht das Formular frmKundenübersicht wie in Bild 1 aus – mit deaktivierter Schaltfläche Kunde löschen.

Deaktivierte Löschen-Schaltfläche

Bild 1: Deaktivierte Löschen-Schaltfläche

Warum können Sie die Eigenschaft Enabled nicht gleich beim Definieren auf False einstellen In unserem Beispiel geschieht Folgendes: Sie erstellen das Ribbon mit seinen Tabs, Groups und Buttons. Für die Buttons wird dabei, soweit nicht anders angegeben, die get…-Version eines Attributs angegeben. Sie können also beispielsweise zum Festlegen eines Bildes, das sich nicht ändern soll, die image-Eigenschaft nutzen:

With btnKundeLoeschen
     .Label = "Kunde löschen"
     .Size = msoRibbonControlSizelarge
     .Image = "user_delete"
End With

Dies resultiert dann in der folgenden Definition:

<button label="Kunde löschen" id="ribKundenuebersicht_btnKundeLoeschen" size="large" image="user_delete" 
     onAction="OnAction" enabled="true" visible="true" />

Oder Sie wollen das Bild zur Laufzeit dynamisch zuweisen. Dann stellen Sie einfach noch keinen festen Wert für die Eigenschaft Image ein:

With btnKundeLoeschen
     .Label = "Kunde löschen"
     .Size = msoRibbonControlSizelarge
End With

In diesem Fall erzeugen die Ribbon-Klassen den folgenden XML-Code für das Element:

<button label="Kunde löschen" id="ribKundenuebersicht_btnKundeLoeschen" size="large" getImage="GetImage" 
     onAction="OnAction" getEnabled="GetEnabled" getVisible="GetVisible" />

Sie sehen, dass hier nicht mehr die Eigenschaft image verwendet wird, sondern die Eigenschaft getImage. Damit wird das Bild auch nicht mehr direkt festgelegt, sondern Sie können es zu einem späteren Zeitpunkt über die Eigenschaft Image der Objektvariablen für das Element einstellen.

Wichtig ist also der Zeitpunkt, zu dem Sie die Eigenschaft Image füllen – vor dem Erstellen der Ribbon-Definition durch die Methode GetRibbon der Klasse Ribbons oder erst danach. Vorher wird das Image über das Attribut image fest eingebunden, nachher wird es über die Callback-Methode getImage ermittelt.

Das Gleiche gilt auch für die beiden Eigenschaft Visible und Enabled. Deshalb dürfen Sie, wenn Sie Visible oder Enabled später dynamisch setzen wollen, die entsprechende Eigenschaft nicht vor dem Erstellen der Ribbon-Definition setzen, sondern erst danach.

Was ist der Unterschied Theoretisch könnte man auch einfach immer die get…-Attribute nutzen und die Werte bei jedem neuen Einblenden des Ribbons erneut abrufen. Allerdings kostet auch dies Performance, und warum sollten wir, wenn ein Element feste Attribute wie etwa Bilder hat, Zeit vergeuden – auch wenn es nur sehr wenig Zeit ist

Wenn Sie sich die Kunde löschen-Schaltfläche ansehen und entscheiden wollen, ob diese abhängig vom jeweiligen Benutzer entweder per Definition oder dynamisch aktiviert oder deaktiviert werden soll, gibt es beispielsweise nur einen praktischen Ansatz: Sie sollten diese vor der Definition mit btnKundeLoeschen.Enabled entsprechend des aktuellen Benutzers einstellen. Wenn Sie sich für die dynamische Variante entschieden, kann die Enabled-Eigenschaft später jederzeit per Code geändert werden – Sie müssen dann dort immer nochmals prüfen, ob der aktuelle Benutzer diese Schaltfläche überhaupt verwenden darf.

Schaltflächen mit Leben füllen

Damit kommen wir zu den im ersten Teil dieser Beitragsreihe versprochenen Funktionen, denn wir haben dort ja zunächst einige Schaltflächen im Ribbon zum Formular frmKundenuebersicht angelegt. Mit diesen wollen wir die folgenden Aktionen durchführen:

  • einen neuen Kunden anlegen,
  • den aktuell markierten Kunden bearbeiten und
  • den aktuell markierten Kunden löschen.

Die erste Aufgabe erfordert keine Vorarbeiten, denn wir können den Dialog zum Anlegen eines neuen Kunden direkt öffnen und dem Benutzer die Möglichkeit geben, den neuen Kunden zu bearbeiten.

Nach dem Klick auf die OK-Schaltfläche soll das Formular geschlossen und das Formular frmKundenuebersicht aktualisiert werden.

Die zweite und die dritte Aufgabe erfordern es, dass der Benutzer einen der Kunden im Formular frmKundenuebersicht markiert hat. Aber ist das überhaupt nötig Momentan können wir mindestens noch neue Datensätze über die letzte Zeile der Datenblattansicht hinzufügen (s. Bild 2). Da wir aber ein eigenes Formular für das Anlegen und Bearbeiten von Kunden einsetzen wollen, das auch Aufgaben wie die Validierung der eingegebenen Daten ausführen könnte, sollten wir die Möglichkeit der Eingabe neuer Datensätze unterbinden.

Aktuell können noch neue Einträge zum Formular frmKundenuebersicht hinzugefügt werden.

Bild 2: Aktuell können noch neue Einträge zum Formular frmKundenuebersicht hinzugefügt werden.

Dazu stellen Sie in den Eigenschaften des Formulars die Eigenschaft Anfügen zulassen auf den Wert Nein ein. Da wir auch zum Bearbeiten ein entsprechendes Detailformular öffnen wollen, können Sie auch die Eigenschaft Bearbeitungen zulassen auf Nein einstellen. Und schließlich soll auch das Löschen nur über die entsprechende Ribbon-Schaltfläche geschehen, sodass auch Löschen zulassen den Wert Nein erhält (s. Bild 3).

Löschen, Bearbeiten und Anlegen von Daten im Formular frmKundenuebersicht verhindern

Bild 3: Löschen, Bearbeiten und Anlegen von Daten im Formular frmKundenuebersicht verhindern

Müssen wir also noch prüfen, ob ein Artikel markiert ist, bevor der Benutzer auf eine der Schaltflächen Kunde bearbeiten oder Kunde löschen klickt Ja, denn es gibt noch eine einzige Möglichkeit, bei der kein Datensatz markiert ist – dann nämlich, wenn die zugrunde liegende Tabelle tblKunden überhaupt keinen Datensatz enthält.

Schaltflächen abhängig von Datensätzen aktivieren und deaktivieren

Wir sollten also dafür sorgen, dass eine entsprechende Meldung erscheint, wenn der Benutzer eine der beiden Schaltflächen Kunde bearbeiten oder Kunde löschen klickt, während kein Kunden-Datensatz markiert ist. Wobei dieser Ansatz nicht ganz ergonomisch ist, denn warum sollte der Benutzer überhaupt einen der Befehle anklicken können, obwohl wir die beiden Schaltflächen auch einfach deaktivieren könnten Immerhin haben wir mit unseren Ribbon-Klassen ja für eine einfache Steuerung dieser Elemente per VBA gesorgt.

Welches Ereignis aber nutzen wir, um zu prüfen, ob sich aktuell ein Datensatz in der Tabelle befindet oder nicht Der erste Ansatz wäre die Ereigniseigenschaft Beim Anzeigen, die bei jedem Wechsel auf einen anderen Datensatz ausgelöst wird. Wir legen dazu zunächst eine Ereignisprozedur für die Schaltfläche btnKundeLoeschen des Ribbons an, welche den aktuell markierten Datensatz im Formular frmKundenuebersicht löschen soll. Diese soll im ersten Ansatz wie in Listing 2 aussehen. Nachdem die Schaltfläche Kunde löschen wie im Artikel btnKundeLoeschen beschrieben wie folgt angelegt wurde, können Sie ihre Ereignisprozeduren implementieren:

Private Sub btnKundeLoeschen_OnAction(control As Office.IRibbonControl)
     Dim db As DAO.Database
     If MsgBox("Kunde wirklich löschen", vbYesNo) = vbYes Then
         Set db = CurrentDb
         db.Execute "DELETE FROM tblKunden WHERE KundeID = " & Me!KundeID, dbFailOnError
         Me.Requery
     End If
End Sub

Listing 2: Löschen eines Kunden per Ribbon-Schaltfläche

Dim WithEvents btnKundeLoeschen As clsButton

Dazu wählen Sie im Codefenster des Klassenmoduls des Formulars frmKundenuebersicht erst im linken Kombinationsfeld den Eintrag btnKundeLoeschen aus und dann im rechten den Eintrag OnAction (s. Bild 4). Dies erstellt eine neue, leere Ereignisprozedur namens btnKundeLoeschen_OnAction, die Sie dann entsprechend füllen.

Anlegen einer Ereignisprozedur für eine Ribbon-Schaltfläche

Bild 4: Anlegen einer Ereignisprozedur für eine Ribbon-Schaltfläche

Die Prozedur fragt den Benutzer, ob er den Datensatz wirklich löschen will und führt dann gegebenenfalls eine entsprechende SQL-Anweisung aus. Anschließend sorgt sie durch den Aufruf der Methode Requery des Formulars selbst (Me) für die Aktualisierung der angezeigten Datensätze. Und nun kommt das Problem: Wir legen zuvor die Ereignisprozedur an, die durch das Ereignis Beim Anzeigen ausgelöst wird, und fügen zwei Anweisungen hinzu, welche die beiden Schaltflächen btnKundeBearbeiten und btnKundeLoeschen des Ribbons aktivieren, wenn im Formular ein Datensatz markiert ist und deaktivieren, wenn kein Datensatz markiert ist:

Private Sub Form_Current()
     btnKundeLoeschen.Enabled = Not IsNull(Me!KundeID)
     btnKundeBearbeiten.Enabled = Not IsNull(Me!KundeID)
End Sub

Allerdings wird die Prozedur Form_Current genau nur dann ausgelöst, wenn der Datensatzzeiger auch auf einen Datensatz springt – aber nicht, wenn kein Datensatz mehr vorhanden ist! Wenn Sie den letzten Datensatz gelöscht haben, feuert dieses Ereignis also nicht und die Schaltflächen btnKundeBearbeiten und btnKundeLoeschen werden nicht deaktiviert.

Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...

Testzugang

eine Woche kostenlosen Zugriff auf diesen und mehr als 1.000 weitere Artikel

diesen und alle anderen Artikel mit dem Jahresabo

Schreibe einen Kommentar