Access-Datenbankanwendungen sind bekanntlich niemals fertig. Das ist an sich kein Nachteil, sondern stellt eher einen Vorteil dar: Im Gegensatz zu fertigen Anwendungen, bei denen Anpassungen entweder gar nicht möglich sind oder viel Geld kosten, kann man Access-Datenbanken einfach selbst um neue Funktionen erweitern. Spannend wird das, wenn die Datenbank von mehreren Nutzern eingesetzt wird. Dann stellt sich die Frage: Wie bekomme ich die neue Version einer Datenbank am einfachsten auf die unterschiedlichen Arbeitsplätze? Das gelingt auf verschiedene Arten, und in diesem Beitrag schauen wir uns eine an, mit der das Update vom Arbeitsplatz des Benutzers aus getriggert werden soll.
Wenn wir eine klassische Konstellation vorliegen haben, bei der jeder Benutzer einen eigenen Rechner hat, der an das Firmennetzwerk angeschlossen ist, ist die nachfolgende beschriebene Vorgehensweise perfekt geeignet. In diesem Fall agieren wir also als Entwickler in oder für das entsprechende Unternehmen. Es gibt noch einen anderen Fall, den wir in einem weiteren Beitrag besprechen wollen – hier ist der Entwickler selbständig und verteilt seine Anwendung an Anwender aus verschiedenen Unternehmen.
Im ersten Fall würden wir die neue Version der Anwendung auf einem Server im Unternehmen platzieren, von wo aus diese dann heruntergeladen werden kann. Im zweiten Fall steht die Datenbankdatei im Internet zum Download bereit.
Normalerweise startet der Benutzer seine Kopie der Datenbankanwendung, indem er eine entsprechende Verknüpfung aufruft oder doppelt auf die Datenbankdatei klickt.
Wir wollen diesen Ablauf so ändern, dass er nicht direkt die eigentliche Datenbankanwendung startet, sondern dass die Verknüpfung eine Startdatenbank öffnet. Diese prüft dann, ob es eine neue Version der eigentlichen Datenbank gibt und lädt diese gegebenenfalls herunter und kopiert sie über die vorhandene Version der Anwendung.
Anschließend soll die Startdatenbank die eigentliche Datenbank starten. Wenn keine neue Version vorliegt, soll die Startdatenbank einfach die vorhandene Anwendung aufrufen.
Code automatisch aufrufen beim Start der Startdatenbank
Die erste Technik, die wir benötigen, ist ein automatischer Aufruf der Prozeduren zum Prüfen auf Updates und der weiteren Schritte beim Start der Startdatenbank.
Das erledigen wir zuverlässig mit einem AutoExec-Makro. Wir legen also ein neues Makro an und speichern dieses unter dem Namen AutoExec. Dieses wird beim Starten von Access automatisch aufgerufen.
Dem Makro weisen wir eine einzige Makroaktion zu. Diese heißt AusführenCode und erhält für den Parameter Funktionsname den Wert =StartDb(). Das Makro sieht in der Entwurfsansicht wie in Bild 1 aus.
Bild 1: AutoExec-Makro, das beim Start automatisch ausgeführt wird
Die aufzurufende Funktion gestalten wir erst einmal wie folgt:
Public Function StartDb() MsgBox "Start" End Function
Das Speichern aller Änderungen und das Schließen und erneute Öffnen der Anwendung sollte nun die Anwendung öffnen und das Meldungsfenster anzeigen.
Erkennen einer neuen Version
Bevor wir uns die Techniken ansehen, mit denen wir eine Datenbank durch eine neuere Version ersetzen, benötigen wir erst einmal die Merkmale, mit denen wir eine neue Version erkennen können.
Üblicherweise verwendet man hier eine Versionsnummer, die auf unterschiedliche Arten gestaltet sein kann. Am einfachsten, auch für den hier vorgesehenen Zweck, ist ein einfacher Long-Wert für die Version. Damit können wir schnell und einfach vergleichen: Ist der Versionswert der aktuellen Version kleiner als der entsprechenden Version der Datenbank auf dem Serverlaufwerk?
Gelegentlich verwendet man auch umfangreichere Versionsnummern wie 1.0.0.4. Auch das können wir umsetzen, allerdings ist der Aufwand minimal höher, da wir Stelle für Stelle vergleichen müssen.
Wenn man davon ausgeht, dass es maximal eine neue Version pro Tag gibt, könnten wir auch einfach das Datum der jeweiligen Version heranziehen. Dann spielt es keine Rolle, ob wir nur einen einfachen Long-Wert als Versionsnummer verwenden oder einen Ausdruck wie 1.0.0.4.
Wir wollen an dieser Stelle Komplexität herausnehmen und verwenden einfach ein Datumsfeld als Kriterium für die Notwendigkeit, die Anwendung mit einer neueren Version zu aktualisieren. Zusätzlich wollen wir die Versionsnummer in einem weiteren Feld speichern, dem wir den Datentyp Kurzer Text geben.
Die folgende Tabelle tblVersion legen wir in der jeweiligen Produktdatenbank an.
Die Tabelle tblVersion sieht in der Entwurfsansicht wie in Bild 2 aus. Hier kann man bei Bedarf noch weitere Felder hinzufügen, zum Beispiel zur Angabe von weiteren Informationen zu dieser Version wie den Neuerungen oder Fehlerkorrekturen, die in dieser Version enthalten sind.
Bild 2: Tabelle zum Speichern der Versionsinformationen in der Entwurfansicht
Wechseln wir in dieser Tabelle zur Datenblattansicht, tragen wir beispielsweise Informationen wie in Bild 3 ein.
Bild 3: Tabelle mit der Versionsnummer
Für die Versionsnummer können wir nun ein beliebiges Format verwenden. Wir sollten nur sicherstellen, dass diese korrekt erhöht werden, damit der Benutzer nicht plötzlich eine neue Version mit einer niedrigeren Versionsnummer vorfindet.
Standort der Startdatenbank und der Produktivdatenbank
Der Einfachheit halber sollten die Startdatenbank und die Produktivdatenbank immer im gleichen Verzeichnis liegen.
So können wir von der Startdatenbank ganz einfach den Pfad zur Produktivdatenbank ermitteln, indem wir mit CurrentProject.Path den Pfad der beiden Datenbankdateien ermitteln und dann den Namen der Produktivdatenbank anhängen.
Die jeweils neuere Version, durch welche die aktuell auf dem Clientrechner vorliegende Version ersetzt werden soll, wird logischerweise nicht im gleichen Verzeichnis liegen, sondern an einer zentral zugänglichen Stelle auf einem Server im Unternehmen oder auch in der Cloud. Hier müssen wir daher den kompletten Pfad in der Startdatenbank speichern.
Insgesamt benötigen wir also zwei Felder in einer Konfigurationstabelle, die wir der Startdatenbank hinzufügen. Diese Tabelle heißt tblKonfiguration und enthält den Entwurf aus Bild 4.
Bild 4: Tabelle zum Speichern der Konfiguration der Startdatenbank
Das erste Feld namens DatenbanknameClient nimmt den Namen der aktuellen Version der Datenbankdatei im aktuellen Verzeichnis der Startdatenbank auf. Das zweite Feld heißt DatenbankpfadServer und enthält den vollständigen Pfad der zu prüfenden, gegebenenfalls aktuelleren Version der Datenbankdatei. Beide haben den Datentyp Kurzer Text.
Gegebenenfalls kommt es vor, dass die 255 Zeichen eines Feldes mit dem Datentyp Kurzer Text nicht ausreichen, um den vollständigen Pfad zu speichern. In diesem Fall haben wir zwei Möglichkeiten:
- Wir teilen das Feld DatenbankpfadServer auf zwei Felder auf, die das Verzeichnis und den Dateinamen speichern.
- Oder wir verwenden einfach den Felddatentyp Langer Text.
Grundstruktur der Aktualisierung
Bevor wir uns an die Details begeben, mit denen wir die verschiedenen Bedingungen prüfen und Aktionen durchführen, bauen wir eine Grundstruktur für den Vorgang auf.
Diese finden wir in Listing 1.
Public Function DatenbankAktualisieren(ByRef strErgebnis As String, ByRef bolFehler As Boolean) As Boolean Dim strPfadClient As String Dim strPfadServer As String strPfadClient = CurrentProject.Path & "\" & DLookup("DatenbanknameClient", "tblKonfiguration") strPfadServer = DLookup("DatenbankpfadServer", "tblKonfiguration") If Not DateiVorhanden(strPfadClient) Then strErgebnis = "Client-Datei fehlt: " & strPfadClient bolFehler = True Exit Function End If If Not DateiVorhanden(strPfadServer) Then strErgebnis = "Server-Datei fehlt: " & strPfadServer bolFehler = True Exit Function End If If IstDatenbankGeoeffnet(strPfadClient) Then strErgebnis = "Client-Datenbank ist geöffnet." bolFehler = True Exit Function End If If IstDatenbankGeoeffnet(strPfadServer) Then strErgebnis = "Server-Datenbank ist geöffnet." bolFehler = True Exit Function End If If NeuereVersionVorhanden(strPfadClient, strPfadServer, strErgebnis) Then If KopiereServerdateiAufClient(strPfadClient, strPfadServer, strErgebnis) Then strErgebnis = "Datenbank erfolgreich aktualisiert." & vbCrLf & strErgebnis DatenbankAktualisieren = True Else strErgebnis = "Fehler beim Aktualisieren: " & strErgebnis bolFehler = True End If Else strErgebnis = "Es konnte keine neue Version gefunden werden." & vbCrLf & strErgebnis End If End Function
Listing 1: Hauptfunktion zum Aktualisieren einer Datenbankdatei
Die Funktion liefert als Ergebnis den Wert True oder False und außerdem mit dem Parameter strErgebnis eine Meldung mit weiteren Details. Da strErgebnis sowohl im Fehlerfall als auch bei Aktualisierung/Nicht-Aktualisierung ohne Fehler geliefert wird, verwenden wir mit bolFehler einen weiteren Parameter, der angibt, ob ein Fehler aufgetreten ist. bolFehler wird immer auf True eingestellt, wenn ein Ereignis eintritt, das die Prüfung der Versionen oder die Aktualisierung an sich verhindert.
Zu Beginn deklariert die Funktion einige Variablen für die Versionsdaten der beiden Datenbankdateien und ihre Pfade.
Danach lesen wir aus der Tabelle tblKonfiguration den Pfad der zu prüfenden aktuellen Datenbankdatei auf dem Clientrechner aus. Dazu stellen wir den Pfad aus dem aktuellen Pfad der Startdatenbank und dem Namen der Datenbank aus der Tabelle zusammen und speichern diesen in der Variablen strClientpfad.
Das Gleiche erledigen wir anschließend für den Pfad der Datenbank auf dem Server, die gegebenenfalls die Version auf dem Client ersetzen soll. Dieser Pfad landet in der Variablen strServerpfad.
Danach folgt eine Reihe If…Then-Bedingungen. Die erste prüft, ob die Datei aus strClientpfad überhaupt vorhanden ist. Dazu nutzen wir die Hilfsfunktion DateiVorhanden, die wir weiter unten beschreiben.
Ist die Daten nicht vorhanden, endet die Funktion hier mit Exit Function, nachdem sie für strErgebnis eine entsprechende Rückmeldung eingetragen hat. Anderenfalls wird die Funktion fortgesetzt.
Die nachfolgende Bedingung ist identisch aufgebaut und prüft das Vorhandensein der zu prüfenden Version der Datenbank auf dem Server. Auch hier gilt: Ist diese Datenbank nicht vorhanden, endet die Funktion mit einer entsprechenden Meldung.
Damit ist nun sichergestellt, dass beide betroffenen Datenbankdateien vorhanden sind.
Nun folgt eine weitere wichtige Prüfung für die beiden Datenbankdateien. Diese untersucht, ob diese nicht geöffnet sind. Das ist zumindest bei der aktuellen Clientdatenbank essenziell, da diese sonst nicht durch eine eventuell vorhandene neue Version ersetzt werden kann.
Diese Prüfung nehmen wir in zwei aufeinanderfolgenden If…Then-Bedingungen vor, die jeweils die Funktion IstDatenbankGeoeffnet nutzen.
Liefern beide Prüfungen den Wert True, geht es weiter, ansonsten endet die Funktion hier wiederum mit entsprechenden Einträgen für den Parameter strErgebnis.
Sind die Grundvoraussetzungen geschaffen, können wir endlich mit der Funktion NeuereVersionVorhanden prüfen, ob die unter strServerPfad gespeicherte Datenbankdatei in einer neueren Version vorhanden ist als die unter strClientPfad gespeicherte.
Auch diese Funktion beschreiben wir weiter unten im Detail. Erwartungsgemäß führt ein negatives Ergebnis zum Abbruch der Funktion mit entsprechendem Eintrag für strErgebnis.
Schließlich sind alle Bedingungen erfüllt und die Routine ruft die Funktion DatenbankAktualisiert auf. Dieser übergeben wir die Pfade zu den beiden Datenbanken. Sie soll das eigentliche Ersetzen der alten durch die neue Version erledigen.
Nachfolgend beschreiben wir nun die verwendeten Funktionen.
Prüfen, ob Dateien vorhanden sind
Die Funktion DateiVorhanden nimmt mit dem Parameter strPfad den Pfad der Datei entgegen, deren Vorhandensein wir prüfen wollen.
Sie verwendet einen verschachtelten Aufruf der beiden Funktionen Len und Dir. Wenn wir der Dir-Funktion einen Dateipfad übergeben, liefert sie bei Vorhandensein den Namen der Datei selbst zurück. Wenn nicht, liefert sie eine leere Zeichenkette.
Dieses Ergebnis unterziehen wir der Len-Funktion. Bei einer leeren Zeichenkette liefert diese den Wert 0, anderenfalls einen Wert ungleich 0.
Im Falle des Wertes 0 lautet das Ergebnis der Funktion True, sonst False. Da der Standardwert einer Funktion mit dem Rückgabedatentyp Boolean gleich False ist, könnten wir uns die explizite Zuweisung von DateiVorhanden sparen. Allerdings wollen wir hier einmal alle Pfade abbilden.
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