Wenn mehrere Benutzer über Frontend-Anwendungen an verschiedenen Arbeitsplätzen auf die Daten einer Backend-Datenbank zugreifen, ist das kein Problem. In vielen Anwendungen ist es dabei sinnvoll, die Möglichkeit zum Speichern von Optionen je Benutzer vorzusehen. Oft legt man dabei eine Tabelle namens „tblOptionen“ im Frontend an. Das ist aber nur sinnvoll, wenn auch immer der gleiche Benutzer am gleichen Frontend arbeitet – anderenfalls würde er ja die Optionen eines anderen Benutzers vorgesetzt bekommen. Oder Sie führen ein Update des Frontends durch – auch dann wären die Optionen des Benutzers nicht mehr vorhanden. Welche Alternativen dazu gibt es Sie könnten zum Beispiel die Optionen in einer Tabelle im Backend speichern und diese beim Anmelden des Benutzers auslesen und in eine lokale Optionentabelle übertragen. Oder Sie fügen dem Frontend ein lokales Backend hinzu, das nur die Daten enthält, die beim Update des Frontends nicht überschrieben werden sollen. Wie das gelingt, zeigen wir im vorliegenden Artikel.
Am einfachsten ist das Speichern der Optionen eines Benutzers im Frontend. Und auch wenn wir das schon so in früheren Beiträgen propagiert haben: Die Lösung ist nur unter ganz bestimmten Rahmenbedingungen pragmatisch. Die folgenden Bedingungen würden es erlauben, die Optionen einfach in einer Tabelle namens tblOptionen im Frontend zu speichern:
- Am Rechner mit dem Frontend arbeitet immer nur der Mitarbeiter, dessen Optionen in der Tabelle tblOptionen dieses Frontends gespeichert sind.
- Es gibt keine Updates für das Frontend. Sonst würden mit einem Update, das durch einfaches Ersetzen über die vorhandene Version kopiert wird, immer die bestehenden Optionswerte gelöscht werden.
Es kann sein, dass beide Bedingungen erfüllt werden. Gerade wenn ein Frontend auf einem Notebook läuft, das einem Mitarbeiter fest zugeteilt ist, wird sich dort kaum ein anderer Mitarbeiter anmelden und die Access-Anwendung nutzen, der seinen eigenen Satz von Optionen erwartet. Und es gibt sicher auch Anwendungen, die bereits fertig programmiert sind und keinerlei Erweiterungen oder Änderungen mehr benötigen, sodass es schlicht und einfach keine Updates mehr zu diesen Anwendungen gibt.
Tatsächlich ist aber nicht sichergestellt, dass Microsoft nicht einmal einen Fehler in ein Update integriert, der die übliche Funktion von Access verhindert – und dann kann es gegebenenfalls doch einmal nötig sein, dass ein Update über die aktuelle Version mit den gespeicherten Optionen des Benutzers kopiert werden muss (tatsächlich ist genau das vor kurzem geschehen – plötzlich funktionierten nämlich Abfragen nicht mehr fehlerfrei, was sich entweder kurzfristig durch eine Änderung der Programmierung beheben ließ oder durch das Warten auf das nächste Update oder den Bugfix von Microsoft).
Wir gehen in diesem Beitrag zunächst davon aus, dass jeder Benutzer seinen eigenen Rechner hat und wir die Optionentabelle einfach in einem lokalen Backend anlegen. Später schauen wir uns an, wie die Lösung für das Speichern der Optionen aller Benutzer im Backend auf dem Server aussehen kann.
Die Optionentabelle
Die Optionentabelle kann unterschiedlich aufgebaut sein. Die erste Möglichkeit ist, die Optionentabelle so zu gestalten, dass jede Option fest als Feld vorgesehen ist. Das sieht dann etwa wie in Bild 1 aus. Diese Variante hat den Vorteil, dass man für jede Option den Felddatentyp individuell festlegen kann – so, wie wir es hier auch gemacht haben.
Bild 1: Optionstabelle mit je einem Feld pro Option
In dieser Variante braucht man eigentlich kein Primärschlüsselfeld, denn es gibt ja zumindest in einer Anwendung für nur einen Arbeitsplatz auch nur einen Datensatz mit Optionen. Da wir aber auch davon ausgehen müssen, dass einmal die Optionen für mehr als einen Anwender gespeichert werden müssen, haben wir vorsichtshalber schon einmal ein Primärschlüsselfeld hinzugefügt.
Die Alternative ist, für jede Option einen eigenen Datensatz anzulegen, der dann in einem Feld den Namen der Option enthält und in einem weiteren Feld den Optionswert. Das sieht im Entwurf wie in Bild 2 aus.
Bild 2: Optionstabelle mit einer Option je Datensatz
Der Vorteil dieser Variante ist, dass Sie für das Anlegen neuer Optionen nicht in den Entwurf des Datenmodells eingreifen müssen, sondern nur einen neuen Datensatz hinzuzufügen brauchen. Der Nachteil ist, dass wir ausschließlich Werte eines zuvor festzulegenden Datentyps als Optionswerte festlegen können. Dieser Nachteil ist aber nicht allzu gewichtig, denn wir können ja alle Datentypen auch im Textformat speichern und gegebenenfalls in den benötigten Datentyp umwandeln.
Optionentabelle im lokalen Backend
Wenn wir die Optionen updatesicher speichern wollen, müssen wir diese außerhalb des Frontends unterbringen. Updatesicher speichern bedeutet dabei, dass wir sicherstellen wollen, dass wir das Frontend durch eine neue Version ersetzen können, ohne dass die für den Benutzer der Anwendung gespeicherten Optionen verloren gehen. Das erledigen wir, indem wir die Optionentabelle in eine eigene Backenddatenbank auslagern, die wir dann im gleichen Verzeichnis wie die Frontendanwendung speichern. Wir fügen dem Frontend dann eine Verknüpfung zu dieser Tabelle hinzu, die automatisch beim Öffnen der Frontendanwendung geprüft und erneuert wird.
Verknüpfung beim Start aktualisieren
Die Aktualisierung der Verknüpfung zur Optionentabelle erledigen wir direkt beim Start der Anwendung. Dazu gibt es verschiedene Möglichkeiten, wo wir den Aufruf des dazu notwendigen VBA-Code platzieren:
- Im Load– oder Open-Ereignis eines Formulars, das automatisch beim Starten der Frontendanwendung angezeigt wird, oder
- in einer VBA-Prozedur, die durch die Makroaktion AusführenCode im automatisch beim Start ausgeführten AutoExec-Makro aufgerufen wird.
Wir gehen an dieser Stelle davon aus, dass Sie bereits eine Frontendanwendung vorliegen haben und eine Backenddatenbank, welche die Optionentabelle enthält. Was kann bei der Verknüpfung alles geschehen und den Vorgang blockieren
- Die Verknüpfung in der Frontenddatenbank ist vorhanden, aber verweist auf die falsche oder eine nicht vorhandene Tabelle.
- Die Verknüpfung in der Frontenddatenbank ist nicht vorhanden.
- Die Backenddatenbank ist nicht vorhanden.
- Die Backenddatenbank ist vorhanden, aber die Optionentabelle ist nicht darin enthalten.
Die folgenden Funktionen sollen all dies addressieren, um die in der Konstanten cStrOptionentabelle angegebene Tabelle der in der Konstanten cStrOptionenbackend angegebenen Datenbank aus dem Verzeichnis des Frontends zu verknüpfen.
Name von Backend und Tabelle speichern
Wir müssen an irgendeiner Stelle die Informationen darüber speichern, wie die Datenbankdatei mit der Optionentabelle und wie die darin enthaltene Optionentabelle heißt – was auch dem Namen der Verknüpfung für die Optionentabelle in der Frontend-Datenbank entspricht. Dazu legen wir im Modul mdlBackendoptionen, dem wir nachfolgend die Funktionen zum Prüfen und Wiederherstellen der Verknüpfung hinzufügen, die folgenden beiden Konstanten mit dem Datentyp String an:
Const cStrOptionenbackend As String = "Backend_Optionen.accdb" Const cStrOptionentabelle As String = "tblOptionen_Felder"
Die Backenddatenbank soll also Backend_Op-tio-nen.accdb heißen, als Backendtabelle mit den Optionen verwenden wir die Tabelle namens tblOptionen_Felder.
Wo aber speichern wir den Pfad, in dem sich die Back-end-datenbank befindet Diesen speichern wir gar nicht, denn die Backenddatenbank mit der Optionentabelle soll sich schlicht im gleichen Verzeichnis wie die Frontenddaten-bank befinden. Und diesen ermitteln wir per VBA zur Laufzeit mit der Eigenschaft CurrentProject.Path.
Prüfen, ob die Backenddatenbank vorhanden ist
Die erste Möglichkeit für eine Fehlfunktion ist, dass die Backenddatenbank gar nicht an Ort und Stelle ist. Das prüfen wir mit einer Funktion namens IstBackendVorhanden. Diese stellt in der Variablen strPfad den Pfad zum Backend zusammen, der aus dem Verzeichnis der aktuellen Datenbank und dem Datenbanknamen aus der Konstanten cStrOptionenbackend besteht.
Mit der Dir-Funktion ermitteln wir die erste Datei, die unter dieser Pfadangabe gefunden werden kann. Dies sollte die in cStrOptionenBackend angegebene Datei liefern oder, wenn diese Datei nicht gefunden werden kann, eine leere Zeichenkette. Beides landet in der Variablen strBackenddatei. Um zu prüfen, ob diese Variable nicht leer ist, ermitteln wir die Anzahl der Zeichen des Wertes dieser Variablen. Ist diese gleich 0, konnte die Datei nicht im angegebenen Verzeichnis gefunden werden und die Funktion liefert den Wert False zurück. Wenn die Zeichenkette aus strBackenddatei jedoch eine Länge größer als 0 aufweist, dann ist die Datei vorhanden und die Funktion liefert den Wert True zurück:
Public Function IstBackendVorhanden() As Boolean Dim strPfad As String Dim strBackenddatei As String strPfad = CurrentProject.Path & "" & cStrOptionenbackend strBackenddatei = Dir(strPfad) If Not Len(strBackenddatei) = 0 Then IstBackendVorhanden = True End If End Function
Prüfen, ob die Optionentabelle im Backend vorliegt
Damit gehen wir einen Schritt weiter, nämlich zur Prüfung des Vorhandenseins der Optionentabelle in der Backenddatenbank. Dazu referenzieren wir die Backenddatenbank und prüfen, ob dort ein TableDef-Objekt mit dem angegebenen Namen vorhanden ist.
Dazu stellen wir wieder in strPfad den Pfad zur Backenddatenbank zusammen. Diesmal prüfen wir allerdings nicht, ob diese vorhanden ist, sondern öffnen mit der OpenDatabase-Methode ein Database-Objekt auf Basis dieser Datenbank und speichern dieses in der Variablen db. Dann versuchen wir wieder, bei deaktivierter Fehlerbehandlung auf das TableDef-Objekt aus cStrOptionenbackend zuzugreifen. Ist die damit gefüllte Variable tdf danach nicht leer, ist die Tabelle in der Backenddatenbank enthalten:
Public Function IstOptionentabelleVorhanden() As Boolean Dim db As DAO.Database Dim tdf As DAO.TableDef Dim strPfad As String strPfad = CurrentProject.Path & "" & cStrOptionenbackend Set db = OpenDatabase(strPfad) On Error Resume Next Set tdf = db.TableDefs(cStrOptionentabelle) On Error GoTo 0 If Not tdf Is Nothing Then IstOptionentabelleVorhanden = True End If End Function
Prüfen, ob Verknüpfung vorhanden ist
Die erste Hilfsfunktion prüft, ob die Verknüpfung überhaupt im Frontend vorhanden ist. Sie heißt IstVerknuep-fungVorhanden und liefert einen Rückgabewert des Typs Boolean. Die Funktion erstellt ein Objekt mit einem Verweis auf das Database-Objekt der Frontenddatenbank. Dann deaktiviert sie die eingebaute Fehlerbehandlung und versucht, über die TableDefs-Auflistung des Database-Objekts auf die Tabelle mit dem in cStrOptionenTabelle gespeicherten Namen zuzugreifen und einen Verweis darauf mit der Variablen tdf zu referenzieren.
Wir prüfen danach gar nicht erst, ob dabei ein Fehler aufgetreten ist oder nicht (ein Fehler würde beim Zugriff auf ein nicht vorhandenes TableDef-Element ausgelöst werden), sondern aktivieren danach einfach die Fehlerbehandlung wieder und prüfen dann, ob tdf mit einem Objektverweis gefüllt ist. Falls ja, wurde die Verknüpfung offensichtlich gefunden, falls nicht, fehlt sie in der aktuellen Datenbank:
Public Function IstVerknuepfungVorhanden() As Boolean Dim db As DAO.Database Dim tdf As DAO.TableDef Set db = CurrentDb On Error Resume Next Set tdf = db.TableDefs(cStrOptionentabelle) On Error GoTo 0 If Not tdf Is Nothing Then IstVerknuepfungVorhanden = True End If End Function
Wenn die Verknüpfung gar nicht vorhanden ist, müssen wir diese anlegen. Das erledigen wir gleich in der Hauptfunktion, die auch die Funktion IstVerknuepfungVorhanden aufruft.
Prüfen, ob die Verknüpfung auf die richtige Tabelle in der richtigen Datenbank verweist
Es kann auch sein, dass die Verknüpfung zwar vorhanden ist, aber nicht auf die richtige Tabelle verweist. Oder dass sie zwar auf die Tabelle mit dem richtigen Namen verweist, diese sich aber nicht in der richtigen Datenbank im richtigen Verzeichnis befindet.
Dies prüfen wir beides in der Funktion IstVerknuepfungKorrekt (siehe Listing 1). Diese referenziert das TableDefs-Objekt aus cStrOptionentabelle und schreibt daraus die Inhalte der Connect-Eigenschaft in die Variable strConnect und der SourceTableName-Eigenschaft in die Variable strTabelle. Die Connect-Eigenschaft liefert einen Ausdruck, der mit ;DATABASE= beginnt und dann den Pfad zu der Datenbank liefert, in welcher sich die verknüpfte Tabelle befindet. Die SourceTableName-Eigenschaft enthält den Namen der Tabelle in dieser Backenddatenbank.
Public Function IstVerknuepfungKorrekt() As Boolean Dim db As DAO.Database Dim tdf As DAO.TableDef Dim strConnect As String Dim strTabelle As String Set db = CurrentDb Set tdf = db.TableDefs(cStrOptionentabelle) strConnect = tdf.Connect strTabelle = tdf.SourceTableName If strTabelle = cStrOptionentabelle Then If strConnect = ";DATABASE=" & CurrentProject.Path & "" _ & cStrOptionenbackend Then IstVerknuepfungKorrekt = True End If End If End Function
Listing 1: Prüfen, ob die Verknüpfung die richtige Datenbank und Tabelle addressiert
Wir prüfen zunächst, ob der Wert in strTabelle mit dem Namen aus cStrOptionentabelle übereinstimmt. Ist das der Fall, untersuchen wir, ob der Wert aus strConnect mit der Zeichenkette bestehend aus ;DATABASE=, dem Verzeichnis der aktuellen Datenbank und dem Datenbanknamen aus cStrOptionenbackend besteht. Sind beide Bedingungen erfüllt, stellen wir den Rückgabewert der Funktion auf True ein.
Prozedur zum Prüfen und Korrigieren der Verknüpfung
Mit diesen Hilfsfunktionen können wir nun entspannt in die Hauptprozedur einsteigen, die prüft, ob alle Bedingungen erfüllt sind und gegebenenfalls Korrekturen vornimmt, damit dies der Fall ist. Aber in welcher Reihenfolge prüfen wir die Bedingungen und wann und wie greifen wir korrigierend ein
Wir können beispielsweise damit einsteigen, dass wir mit der Funktion IstVerknuepfungVorhanden prüfen, ob die Verknüpfung zur Optionentabelle überhaupt im Frontend vorliegt. Aber was tun, wenn das schon nicht der Fall ist Sollen wir diese dann einfach anlegen und dann die weiteren Bedingungen prüfen Das ist wenig sinnvoll, denn wenn wir nicht wissen, ob die Backenddatenbank überhaupt vorhanden ist, brauchen wir auch nicht die Verknüpfung zu reparieren. Also starten wir in der ersten Version der Funktion OptionentabelleVerknuepfen bei den wesentlichen Voraussetzungen (siehe Listing 2). Die Erste lautet: Ist die Backenddatenbank überhaupt an Ort und Stelle Das prüfen wir mit der Funktion IstBackendVorhanden. Falls ja, gehen wir mit der Prüfung der nächsten Bedingung weiter. Falls nicht, müssen wir dem Benutzer mitteilen, was nicht in Ordnung ist oder dies selbst beheben.
Public Function OptionentabelleVerknuepfen() As Boolean Dim bol As Boolean If IstBackendVorhanden Then If IstOptionentabelleVorhanden Then If IstVerknuepfungVorhanden Then If IstVerknuepfungKorrekt Then bol = True Else MsgBox "Die Verknüpfung ist nicht korrekt." End If Else MsgBox "Die Verknüpfungstabelle fehlt." End If Else MsgBox "Die Tabelle '" & cStrOptionentabelle & "' konnte nicht in der folgenden Datenbank gefunden " _ & "werden:" & vbCrLf & vbCrLf & CurrentProject.Path & "" & cStrOptionenbackend End If Else MsgBox "Die Datenbank '" & cStrOptionenbackend & "' mit der Optionentabelle konnte nicht gefunden werden." End If OptionentabelleVerknuepfen = bol End Function
Listing 2: Prüfen aller Bedingungen in einer Funktion
Die nächste Bedingung prüfen wir mit der Funktion IstOptionentabelleVorhanden. Auch hier geben wir eine Meldung aus, wenn die Bedingung nicht erfüllt wurde.
Liefert die Funktion jedoch den Wert True, dann gehen wir mit der Prüfung der nächsten Bedingung weiter – also IstVerknuepfungVorhanden – und dann mit IstVerknuep-fungKorrekt. In beiden Fällen wird für den Wert False eine entsprechende Meldung ausgegeben.
Optionentabelle verknüpfen mit Korrekturmöglichkeit
Nun wollen wir dem Benutzer noch die Möglichkeit geben, selbst die nicht erfüllten Bedingungen zu erfüllen und die Bedingungen dann erneut zu prüfen. Dazu müssen wir die ganzen If…Then-Bedingungen in eine Schleife einfassen, die prüft, ob bol den Wert True liefert, was der Fall ist, wenn alle Bedingungen erfüllt sind.
Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...
den kompletten Artikel im PDF-Format mit Beispieldatenbank
diesen und alle anderen Artikel mit dem Jahresabo