Home > Artikel > Ausgabe 8/2014 > Anwendungseinstellungen abspeichern

Anwendungseinstellungen abspeichern

Achtung: Sie sind nicht angemeldet. Wenn Sie Abonnent sind und sich anmelden, lesen Sie den kompletten Artikel, laden das PDF herunter oder probieren die Beispieldatenbank aus (sofern vorhanden).

Sie haben eine umfangreiche Datenbank entwickelt und möchten Ihren Anwendern die Möglichkeit bieten bestimmte Einstellungen etwa der Benutzeroberfläche selbst festlegen zu können - so, wie sie das in anderen Anwendungen von den Einstellungen- und Optionen-Menüs her kennen. Damit lassen sich etwa das Erscheinungsbild steuern oder Pfade für Auswahldialoge vorgeben. Wie sich das sinnvoll per VBA umsetzen lässt möchten wir in diesem Beitrag beleuchten.

Beispieldatenbank

Die Beispiele dieses Artikels finden Sie in der Datenbank 1408_Einstellungen.mdb.

Benutzerdefinierte Einstellungen der Datenbank

Viele Einstellungen einer Datenbank verwaltet Access selbst. Sie können bei der Entwicklung etwa über das Optionen-Menü verschiedene Einstellungen fest vorgeben. Dort finden sich etwa Vorgaben für das Layout von Datenblättern, die Darstellung von Menüs oder die Ansicht von Steuerelementen, aber auch technische Vorgaben, wie das Verhalten bei Datensatzsperrung.

Unter Access 2003 war noch nicht ersichtlich, ob sich diese Vorgaben auf den Arbeitsplatz, also Access generell, beziehen, oder auf die eben geöffnete Datenbank. Unter Access 2007 wurde im Optionen-Dialog dann der Bereich Aktuelle Datenbank eingeführt, der deutlich macht, was genau in der geöffneten Datenbank festgelegt wird und nur in dieser.

Doch auch der Anwender kann manche Änderungen dauerhaft abspeichern. Änderungen an Spaltenbreiten von Datenblättern oder an der Größe von Formularen werden verewigt, wenn anschließend über Menü oder Symbolleiste die Speichern-Aktion ausgeführt wird. Die Schriftart der Steuerelemente eines Formulars etwa kann er hingegen nicht beeinflussen.

Wollten Sie dem Anwender diese Möglichkeit einräumen, so müssten neben dem Code, der die Schriften der Textfelder beim Laden des Formulars steuert, und einem Dialog, der die Schriften anböte, auch noch das Feature hinzukommen, die Schrifteinstellungen irgendwo abzuspeichern, damit sie beim nächsten Laden wieder zur Anwendung gelangten. Oft ist die Aufgabe jedoch trivialer. Besteht beispielsweise in der Anwendung die Notwendigkeit, öfter Dateien per Auswahldialog auszuwählen, dann ist es sicher nützlich, wenn man jeweils im zuvor geöffneten Ordner landet und nicht immer neu dorthin navigieren muss.

Der zuletzt ausgewählte Pfad könnte hier abgespeichert und bei erneutem Öffnen des Auswahldialogs gleich angeboten werden. Oder nehmen wir den selbstgebauten Drucker-Dialog aus dem Artikel Access-Berichte drucken: Günstig wäre, wenn hier der zuletzt verwendete Drucker im Kombinationsfeld voreingestellt wäre und nicht jedes Mal neu in der Liste gesucht werden müsste.

Nun stellt sich die Frage, wo genau die Parameter dieser Einstellungen abgespeichert werden sollten?

Entwicklereinstellungen und Anwendereinstellungen

Diese beiden Bereiche wären zu trennen. Es gibt Einstellungen, die der Anwender nicht beeinflussen können sollte. Nehmen wir an, sie hätten eine Schnittstelle zu einem Webservice in Ihrer Datenbank implementiert. Die URL zu diesem Webservice kann sich ändern. Statt die URL als String hart in ein VBA-Modul zu kodieren, eignet sich eine benutzerdefinierte abspeicherbare Variable für diesem Zweck besser. So müssen Sie nur den Wert der Speicherstelle ändern und kein Modul modifizieren. Der Anwender sollte von alledem nichts mitbekommen.

Umgekehrt braucht Sie als Entwickler nicht zu interessieren, welchen Drucker der Anwender verwendet oder einstellt. Je nach Anwender- oder Entwicklerbereich unterscheiden sich dann auch die Speicherorte für die Einstellungsvariablen. Ein gewichtiger Grund dafür : Wenn Sie ein Update Ihrer Datenbank verteilen, die Einstellungen aber in der Datenbank selbst gespeichert sind, so gehen alle vom Anwender vorgenommenen Änderungen flöten und er wird mit Ihren Entwicklereinstellungen konfrontiert. Deshalb müssen Anwendereinstellungen zwingend extern abgespeichert werden.

Speicherorte für Einstellungen

Möglichkeiten bieten sich dafür viele an. Früher gab es einmal INI-Dateien, die Einstellungen aufnahmen. Heute verwendet man stattdessen die Registry – dazu mehr in einem anderen Beitrag dieser Ausgabe. Statt INI-Dateien kommen auch einfache Textdateien infrage, in die per VBA und dessen Open-Anweisung Variablenwerte geschrieben würden.

Doch was liegt in einer Datenbank näher, als solche Daten in Tabellen zu schreiben? Für die Entwicklereinstellungen nimmt man eine Tabelle in der Anwendungsdatenbank selbst, für die Anwender eine externe verknüpfte Datenbank, die nur die eine Tabelle mit den Einstellungen enthält. Als weitere Alternative kämen auch andere Datenbanksysteme infrage, wie etwa SQLite, das für diesen Zweck von diversen Applikationen verwendet wird – der Firefox Browser ist ein Beispiel dafür. Doch warum in die Ferne schweifen... Schließlich gibt es noch eine weitere Alternative, derer sich auch Access selbst bedient: Die Datenbank-Properties.

Datenbank-Properties

Access speichert die ganzen Optionen, die Sie über das entsprechende Menü öffnen, in den Properties der Datenbank. Über VBA und DAO erhalten Sie Zugriff auf die Datenbank über das Zauberwort CurrentDb. Dessen Eigenschaften sind die

CurrentDB.Properties

Es handelt sich dabei um ein Auflistungsobjekt, das, wie so oft, entweder über eine Ordinalzahl oder einen String abgefragt werden kann.

CurrentDb.Properties(33).Value

und

CurrentDb.Properties ("AllowSpecialKeys").Value

sind dasselbe und stellen den Wert der Eigenschaft "Access-Spezialtasten zulassen" dar. Diese Auflistung ist nicht statisch, sondern kann selbst erweitert werden. Heißt: Neue Elemente können hinzugefügt, geändert, oder gelöscht werden. So auch Variablen für die eigenen Einstellungen.

Übrigens speichert Access diese Properties auch wieder in einer Tabelle – wo auch sonst? In diesem Fall ist es die ausgeblendete Systemtabelle MSysObjects und dort das Feld LvProp des Datensatzes MSysDb (siehe Ausschnitt in Bild 1). Die Binärdaten darin haben einen proprietären Aufbau.

Properties in der Tabelle MSysObjects

Bild 1: Properties in der Tabelle MSysObjects

Sie können sich alle Datenbank-Properties ansehen, indem Sie eine Routine wie in Listing 1 aus dem Modul mdlProperties verwenden. In dieser werden alle Properties ausgelesen und die Namen, Datentypen und Werte im VBA-Direktfenster ausgegeben. Komfortabler geht es mit dem Formular frmProps der Beispieldatenbank, die eine ähnliche Prozedur nutzt, um die Properties in einem Listenfeld darzustellen (siehe Bild 2).

Eigenschaften der Datenbank im Formula frmProps der Beispieldatenbank

Bild 2: Eigenschaften der Datenbank im Formula frmProps der Beispieldatenbank

Die Prozedur durchläuft alle Elemente der Properties-Auflistung in einer Schleife, und setzt sie jeweils auf oPrp, eine DAO.Property-Variable. Dieser Objekttyp hat die wesentlichen Eigenschaften Name, Type und Value. Als Value kann ein beliebiger Variant-Wert gesetzt sein, Type ist auf den Datentyp der Eigenschaft eingestellt. Die Schleife einhält eine Ausnahme: Die Standardeigenschaft Connection muss außen vor bleiben, weil sie einen Datentyp aufweist, den VBA nicht verarbeiten kann. Wundern Sie sich nicht, dass die Routine an manchen Stellen stockt. Für das Auslesen mancher eingebauter Eigenschaften braucht Access offenbar etwas Bedenkzeit.

Mehr, als das Auslesen, interessiert uns die Anlage neuer Properties. Auch hierzu finden Sie eine allgemeinverwendbare Routine in der Beispieldatenbank, die Prozedur SetProperty (Listing 2). Als Parameter übergeben Sie ihr den Namen der Eigenschaft sowie ihren Wert. Es spielt dabei keine Rolle, ob die Eigenschaft bereits existiert oder nicht. Denn zunächst versucht die Prozedur das Property-Objekt auf eine existierende Eigenschaft zu setzen. Gibt es diese unter dem übergebenen Namen nicht, so löst dies normal einen Fehler aus. Die Fehlerbehandlung wurde jedoch außer Kraft gesetzt. Bei Erfolg ist das Property-Objekt gültig, bei Misserfolg entspricht es Nothing. Davon hängt ab, wie der Code weiter verzweigt. Ist das Objekt leer, so fährt er mit dem Erzeugen der Eigenschaft per CreateProperty fort. Dieser Methode der Properties-Auflistung ist neben dem Namen und Wert der Eigenschaft auch noch der Datentyp in Form einer Konstanten zu übergeben.

Sub SetProperty(sName, Value As Variant)

     Dim dbs As Database

     Dim oPrp As DAO.Property

     Set dbs = CurrentDb

     On Error Resume Next

     Set oPrp = dbs.Properties(sName)

     If oPrp Is Nothing Then

         On Error GoTo 0

         Set oPrp = dbs.CreateProperty(sName, VbTypeToDAO(Value), Value)

         dbs.Properties.Append oPrp

     Else

         On Error GoTo 0

         oPrp.Value = Value

     End If

End Sub

Listing 2: Code zum Anlegen neuer Properties

Leider handelt es sich hier um eine DAO-Konstante, nicht um eine VBA-Konstante, denn sonst könnte der Typ des Werts Value einfach über die VBA-Funktion VarType() ermittelt werden. Deshalb ist im Modul eine Hilfsfunktion VbTypeToDAO eingebaut, die die Übersetzung von VBA-Datentyp zu DAO-Datentyp gewährleistet. In Kurzform enthält es Zeilen wie diese:

If VarType (Value) = vbDate Then Result = DAO.dbDate

Properties verwenden

Machen wir die Probe und legen mithilfe dieser SetProperty-Prozedur eine neue Eigenschaft an:

SetProperty "Version", "1.0"

Das Auslesen gibt uns indessen Ratsel auf:

CurrentDb.Properties("Version")

Wir erhalten seltsamerweise "4.0". Der Grund dafür ist, dass diese Eigenschaft von Access aus bereits existiert, aber schreibgeschützt ist. Sie müssen also darauf achten, dass sie bei eigenen Properties nicht die Namen verwenden, die Access intern verwendet. Die reservierten Namen erhalten Sie ja über das Formular (Bild 2). Nehmen Sie im Beispiel stattdessen den Namen DBVersion, so läuft alles glatt und die Rückgabe entspricht dem übergebenen Wert.

Sie können für den Test auch einfach die beiden Prozeduren BeispielSetzen und BeispielLesen im Modul mdlProperties der Beispieldatenbank heranziehen. Dort finden Sie auch weitere Routinen, wie solche zum Löschen einer Eigenschaft (RemoveProperty) und zum Löschen aller Eigenschaften (ClearAllProperties). In beiden ist der Einfachheit halber die Fehlerbehandlung außer Kraft gesetzt. Denn diverse eingebaute Access-Eigenschaften lassen sich nicht löschen. Genaugenommen sind dies die Properties 1 bis 13.

Die über darüber liegende Ordinalzahlen angesprochenen Properties lassen sich löschen. Aber Achtung: Mit dabei sind dann auch solche, die schon über den Optionen-Dialog für die Datenbank eingestellt wurden! Das führt dazu, dass Access Default-Werte für bestimmte Eigenschaften verwendet. Nach dem Löschen aller Eigenschaften finden Sie im Optionen-Dialog etwa wieder die Objektnamenkorrektur aktiviert! Die Eigenschaften werden von Access ansonsten spätestens beim Neuöffnen der Datenbank automatisch wieder angelegt – aber nicht unbedingt mit den Werten, die Ihnen vorschweben ...

Es bleibt festzuhalten, dass Sie mit den Properties-Routinen nicht nur eigene Eigenschaften erzeugen, sondern auch jene von Access modifizieren können. Änderungen an Menüleisten können Sie etwa unterbinden, indem Sie die Eigenschaft AllowToolbarChanges auf den Wert False setzen. Darüberhinaus macht eine neue Eigenschaft wie DBVersion, durchaus Sinn. Setzen Sie den Wert bei Entwicklung und zeigen Sie ihn in der Datenbank zur Laufzeit als Suffix des Titels an:

GetProperty("AppTitle") & "V." & _ GetProperty("DBVersion")

Variablen für Eigenschaften in Tabellen

Statt über Properties lassen sich Eigenschaften auch in einer eigens dafür angelegten Tabelle abspeichern. Der Vorteil ist hier zumindest, dass Sie sich um die Namen der Eigenschaften keine Gedanken machen müssen und mit den Einstellungen von Access nicht ins Gehege kommen. Legen Sie etwa eine Tabelle an, die im Entwurf so aussieht, wie in Bild 3. VName speichert den Namen der Eigenschaft; Typ enthält analog zum Property den Datentyp, hier jedoch als Text – etwa Date. Der Wert wird ebenfalls als Text gespeichert, da Felder nun mal keine Variant-Werte aufnehmen können. Die Konvertierung von etwa einer Datumsvariablen zu Text muss dann von einer Routine geleistet werden – umgekehrt genauso. Sollten Ihre Eigenschaftswerte längere Texte enthalten, so verwenden Sie für das Wert-Feld besser den Memo- statt des Text-Typs.

Variablentabelle für Eigenschaften im Entwurf

Bild 3: Variablentabelle für Eigenschaften im Entwurf

Die Routinen zum Umgang mit dieser Tabelle finden Sie in der Beispieldatenbank im Modul mdlVariables.

Damit die Anwender die Tabelle nicht zu Gesicht bekommen und auch sonst keinen Unfug mit ihrem Inhalt anstellen können, blenden sie sie aus. Rufen Sie dazu einfach HideVariablesTable im VBA-Direktfenster auf. Die Prozedur setzt die entsprechenden Attribute dbHiddenObject und dbSystemObject für die Tabelle. Das weist die Tabelle dann zusätzlich als Systemobjekt aus, und Dateneingabe, Löschen und Ändern von Daten sind danach in der Tabellenansicht gesperrt (Bild 4).Sie können den Vorgang rückgängig machen, indem Sie die Prozedur UnHideVariablesTable aufrufen.

Änderungen an Datensätzen sind in Systemtabellen grundsätzlich gesperrt

Sie haben das Ende des frei verfügbaren Teil dieses Artikels erreicht!

Wenn Sie mehr lesen und auf viele weitere Artikel zugreifen möchten, melden Sie sich als Abonnent unter Login an. Falls nicht, bestellen Sie doch einfach ein Jahresabonnement!