Optionen und andere Daten updatesicher speichern

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.

Optionstabelle mit je einem Feld pro Option

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.

Optionstabelle mit einer Option je Datensatz

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

Möchten Sie weiterlesen? Dann lösen Sie Ihr Ticket!
Hier geht es zur Bestellung des Jahresabonnements des Magazins Access im Unternehmen:
Zur Bestellung ...
Danach greifen Sie sofort auf alle rund 1.000 Artikel unseres Angebots zu - auch auf diesen hier!
Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:

Schreibe einen Kommentar