Home > Artikel > Ausgabe 1/2015 > Datenbanken und Objekte sichern

Datenbanken und Objekte sichern

  PDF ansehen

  Download PDF und Beispieldatenbank

Während der Entwicklung Ihrer Datenbank kann einiges schief gehen. Sei es, dass Sie sich vertan haben und einen Schritt zurückgehen müssen, versehentlich Objekte oder Code löschten, oder die Datenbankdatei selbst aus unerfindlichen Gründen korrupt wird. Wohl dem, der da regelmäßig Sicherungen anlegt, auf die später zurückgegriffen werden kann!

Beispieldatenbank

Die Beispiele dieses Artikels finden Sie in der Datenbank 1501_Sicherung.mdb.

Sichern über die Benutzeroberfläche

Die einfachste Art, um Scherereien aus dem Weg zu gehen, ist das regelmäßige Backup Ihrer Datenbankdatei. Hier können Sie auf die Backup-Funktionen des Betriebssystems zurückgreifen, oder auf die Hilfe und Software von Drittanbietern, die häufig etwas ausgefeiltere Möglichkeiten aufweisen. Grundsätzlich ist dabei ratsam, die Backup-Dateien nicht immer mit der aktuellsten Version zu überschreiben, sondern sie mit einem Datum im Dateinamen zu versehen, damit verschiedene frühere Versionen und Entwicklungsstände zur Verfügung stehen.

Denn häufig wird man erst nach einiger Zeit gewahr, dass ein ehemals verworfenes Modul doch noch benötigt wird. Die Arbeit, es dann neu zu schreiben, können Sie sich bei regelmäßiger Sicherung ersparen.

Backup-Möglichkeiten außerhalb von Access sollen aber nicht Thema dieses Beitrags sein. Schauen wir einmal, welche Möglichkeiten es selbst anbietet.

Seit Access-Version 2003 sieht es eine Funktion vor, mit der sich die aktuell geöffnete Datenbank in eine neue Datei speichern lässt. Sie nennt sich schlicht Datenbank sichern. Unter Access 2003 findet sie sich über das Menü Datei, in den Folgenversionen im sogenannten Backstage, der sich bei Access 2007 über den Office-Button, unter Access 2010 über den Reiter Datei öffnen lässt (siehe Bild 1). Doppelklicken Sie auf die Fläche zum Sichern, dann fragt sie Access in einem Dateiauswahldialog, wohin es die Sicherung speichern soll und schlägt auch gleich einen Namen für die Backup-Datei vor. Dieser bildet sich in der Regel aus dem Originalnamen der Datenbank und einem Datum-String, der das aktuelle Datum enthält. Die Uhrzeit bleibt außen vor. Sichern Sie eine Datenbank mehrmals am Tag, so wird zusätzlich nach dem Datum automatisch ein Zähler angehängt. Das ist unproblematisch, da Sie die Erstellzeit ja aus dem Explorer ersehen können.

Backstage-Ansicht unter Access 2010, Rubrik Speichern und Veröffentlichen

Bild 1: Backstage-Ansicht unter Access 2010, Rubrik Speichern und Veröffentlichen

Access merkt sich nun, welchen Ordner Sie auswählten und schlägt diesen in der Folge immer wieder vor. Es handelt sich dabei um eine Eigenschaft der Datenbank, die in ihr automatisch benutzerdefiniert gesetzt wird:

CurrentDb.Properties _

("DefaultBackupLocation")

Nach der Lektüre des Beitrags zu DAO-TableDef-Objekten dieser Ausgabe werden Sie wissen, dass sich diese Eigenschaft per Code auch ändern oder neu anlegen lässt. Sie ist nämlich nur dann vorhanden, wenn die Sicherung nicht am gleichen Ort erfolgt, in dem die Datenbank selbst liegt. Gleiches gilt für das übergeordnete Verzeichnis. Den Ort für die Sicherung können Sie also per VBA bestimmen, die Sicherung jedoch nicht programmatisch anstoßen, wie wir noch sehen werden.

Empfehlenswert ist jedenfalls die Anlage eines gesonderten Ordners für die Backups.

Wie in Bild 1 zu sehen, sieht Access 2010 noch weitere Funktionen im Backstage vor, die sich für ein Backup missbrauchen ließen.

Da gibt es einmal direkt die Anweisung Datenbank speichern als, welche ebenfalls einen Dateiauswahldialog hervorbringt, über den Sie die aktuelle Datenbank in einem Verzeichnis Ihrer Wahl kopieren können. Unter Speichern und Veröffentlichen findet sich diese Funktion abermals, zusätzlich aber auch die erwähnte Sicherungsfunktion und die Möglichkeit, die Datenbank in einem anderen Format abzuspeichern. Das ist für eine Sicherung wahrscheinlich nicht unbedingt sinnvoll, aber die Speicherung einer ACCDB- in eine MDB-Datenbank bringt unter Umständen auch Vorteile mit sich. So können Sie bei Parallelinstallationen auch von Access 2003 aus auf diese Backups zugreifen.

Wenn Sie hart an einer Neuentwicklung arbeiten, so ist ein Backup in Stundenabständen anzuraten. Dabei ist der Umstand, dass Sie immer den Weg über den schwerfälligen Backstage gehen müssen, etwas hinderlich. Aber stellen Sie sich doch einfach eine neue Gruppe von Sicherungsanweisungen im Ribbon zusammen, die Sie dann mit nur einem Klick ausführen können! Öffnen Sie dazu den Ribbon-Editor (Bild 2) über Rechtsklick auf den Ribbon (Menüband anpassen...) oder die Optionen von Access. Wählen Sie aus dem Kombinationsfeld oben links die Anweisungsgruppe Registerkarte "Datei". Hier finden Sie schnell jene Befehle, die auch im Backstage vorkommen. Klicken Sie auf den Button Neue Registerkarte. Es entsteht nun im Baum oben ein neuer Eintrag, den Sie erst mal etwa in FileTools umbenennen. Markieren Sie dazu den Eintrag und klicken auf den Button Umbenennen.... Wiederholen Sie dies für die ebenfalls neue Untergruppe, der Sie die Bezeichnung Sicherung geben. Hier allerdings öffnet sich nicht nur ein Texteingabedialog, sondern der in Bild 3 gezeigte, welcher außer der Benennung auch noch die Auswahl eines Icons für die Gruppe zulässt.

Umbennen eines Eintrags und Auswahl eines Icons für die Anweisung

Bild 2: Umbennen eines Eintrags und Auswahl eines Icons für die Anweisung

Anpassen des Ribbon unter Access 2010 zum Anlegen eines neuen Reiters und seiner Elemente

Bild 3: Anpassen des Ribbon unter Access 2010 zum Anlegen eines neuen Reiters und seiner Elemente

Im Folgenden markieren Sie aus der Liste der Befehle links nacheinander jene, die für die Sicherungen in Betracht kommen. Klicken Sie dabei jeweils auf den Button Hinzufügen, der den Eintrag in die markierte Gruppe Sicherung verfrachtet. Wenn Ihnen die von Access vorgesehene Bezeichnung, wie Access 2002-2003-Datenbank, nicht zusagt, so können Sie anschließend über die Umbenennen-Funktion der Anweisung einen anderen Namen und ein anderes Icon verabreichen, etwa Sichern als Access 2003-Datenbank.Schlussendlich lässt sich der neue Reiter auch noch über die Pfeil-Buttons nach oben oder unten verschieben, so dass er nach Beenden des Ribbon-Editors ganz rechts positioniert erscheint, wie in Bild 4. Was es mit dem Button für die Heiße Sicherung auf sich hat, welcher das Makro makBackup ausführt, kommt später noch zur Sprache.

Der neue Ribbon-Reiter Tools mit den angelegten Sicherungsschaltflächen

Bild 4: Der neue Ribbon-Reiter Tools mit den angelegten Sicherungsschaltflächen

Soll der Zugriff besonders schnell gehen, so legen Sie die Sicherungsanweisungen zusätzlich in der Schnellzugriffsleiste an; in Bild 4 ganz oben zu finden. Rechts steht dort ein neuer Auswahlbutton zur Verfügung, welcher, so betätigt, die Sicherungsgruppe (Bild 5) an die Oberfläche bringt.

Die modifizierte Schnellzugriffsleiste mit den Sicherungsbefehlen

Bild 5: Die modifizierte Schnellzugriffsleiste mit den Sicherungsbefehlen

Die Schnellzugriffsleiste lässt sich ähnlich einrichten, wie das Ribbon. Klicken Sie rechts auf sie und wählen den Eintrag Symbolleiste für den Schnellzugriff anpassen.... Der Editor für die Anpassungen (Bild 6) funktioniert weitgehend genau so, wie der Menüband-Editor. Statt nun aber wie zuvor alle Befehle aus der Liste links in die Leiste rechts zu ziehen, wählen Sie im Kombinationsfeld einfach die FileTools-Registerkarte aus. Im Listenfeld werden dann alle Elemente der Registerkarte angezeigt, aber auch deren übergeordnete Gruppe Sicherung selbst. Ziehen Sie diese einfach in die Schnellzugriffsleiste und positionieren sie anschließend ganz nach unten, wodurch sie nach Beenden des Editors ganz rechts als Auswahlbutton erscheint.

Anpassen der Schnellzugriffsleiste unter Access 2010 auf Grundlage der neuen Ribbon-Gruppe

Bild 6: Anpassen der Schnellzugriffsleiste unter Access 2010 auf Grundlage der neuen Ribbon-Gruppe

Die Anpassungsmöglichkeiten unter Access 2007 sind nicht ganz so komfortabel, doch auch hier lassen sich Ribbon und Schnellzugriffsweise so anpassen, dass es zum gewünschten Ergebnis kommt.

Nach diesem Ausflug in die Welt der Oberfläche von Access stellt sich die Frage, ob es nicht auch möglich wäre, den ganzen Prozess ohne manuelles Zutun per VBA zu automatisieren?

Sichern über VBA-Routinen

Sie werden sehen, dass das Unterfangen gar nicht so einfach ist. Denn eine Sicherung der geöffneten Datenbank ist eigentlich nur sinnvoll, wenn sie bereits geschlossen ist. Genau das tun auch die Oberflächenbefehle von Access. Beim Sichern schließt Access die offene Datenbank, führt das Backup aus, und öffnet sie danach erst wieder.

Aber experimentieren wir Auch der Suche nach VBA-Anweisungen, die dem Sichern-Befehl entsprächen, stößt man auf die Methode ConvertAccessProject des Application-Objekts. Im Modul mdlSicherung der Beispieldatenbank finden Sie die Prozedur Test1, wie in Listing 1. Hier wird versucht, die aktuelle Datenbank, deren voller Pfad als Parameter anzugeben ist, in eine neue Datei mit der Endung bak zu speichern und dabei das Datenbankformat beizubehalten. Bei Ausführung der Routine passiert schlicht gar nichts. Access ignoriert die Anweisung ohne Fehlermeldung, wenn die angegebene Datei die aktuell geöffnete ist.

Sub Test1() 'Nichts passiert

     ConvertAccessProject _

         CurrentDb.Name, _

         CurrentDb.Name & ".bak", _

         acFileFormatAccess2007

End Sub

Listing 1: Backup-Versuch per Code

Nun könnte man auf die Idee kommen, die aktuelle Datenbank zunächst per Code zu schließen, danach Anweisungen zum Kopieren auszuführen und sie schließlich wieder zu öffnen. Das sähe etwa aus, wie in Listing 2. Doch auch dieser Versuch ist zum Scheitern verurteilt. Denn die Methode CloseCurrentDatabase schließt die Datenbank so gründlich, dass auch die Code-Ausführung abgebrochen wird, weshalb sie nie zur nächsten Zeile mit FileCopy gelangt.

Public Function BackupThisDB()

     sDBFile = CurrentDb.Name

     sDBPath = CurrentProject.Path

     

     Application.CloseCurrentDatabase

     'An dieser Stelle bricht es ab!

     FileCopy sDBFile, _

              sDBPath & "\backup.accdb"

     OpenCurrentDatabase sDBFile

     BackupThisDB = True

End Sub

Listing 2: Neuer Versuch per Code

Dies macht deutlich, dass ein korrektes Sichern aus VBA heraus nicht möglich ist. Eine Lösung bestünde darin, den Code aus Listing 2 modifiziert in eine Addin-Datenbank auszulagern. Sie könnte die Routine regelmäßig über einen Formular-Timer aufrufen. Wirklich praktisch wäre jedoch auch das nicht, denn wer will schon mitten in der Arbeit von einem erzwungenen Backup überrascht werden?

Damit wir hier nicht leer ausgehen, zeigt Listing 3 eine Lösung, die zwar die aktuelle Datenbank nicht schließt, aber immerhin alle geöffneten Objekte, bevor der Kopiervorgang startet. RunCommand acCmdCloseAll ist dabei das Zauberwort. Die Anweisung schließt alle offenen Objekte der Datenbank, wobei unter Umständen auch nach dem Speichern von Änderungen gefragt wird. Die Routine speichert im weiteren Verlauf die Datei dann im Ordner der Datenbank unter dem Namen Backup.accdb.

Private Type SHFILEOPSTRUCT

     hwnd As Long

     wFunc As Long

     pFrom As String

     pTo As String

     fFlags As Integer

     fAnyOperationsAborted As Boolean

     hNameMappings As Long

     lpszProgressTitle As String

End Type

Private Declare Function SHFileOperation Lib "shell32.dll" _

     Alias "SHFileOperationA" (lpFileOp As SHFILEOPSTRUCT) As Long

Function BackupThisDB4()

     DoCmd.Hourglass True

     DoEvents

     RunCommand acCmdCloseAll

     If Len(Dir(CurrentProject.Path & "\Backup.accdb")) > 0 Then

         Kill CurrentProject.Path & "\Backup.accdb"

     End If

     DoEvents

     FCopy CurrentDb.Name, CurrentProject.Path & "\Backup.accdb"

     DoCmd.Hourglass False

     If Len(Dir(CurrentProject.Path & "\Backup.accdb")) > 0 Then

         MsgBox "Backup OK", vbInformation

     End If

End Function

Private Function FCopy(strFile, strDestination) As Boolean

     Dim FileOp As SHFILEOPSTRUCT

     With FileOp

         .wFunc = &H2

         .hwnd = hWndAccessApp 'Oder 0&

         .pFrom = strFile & vbNullChar

         .pTo = strDestination & vbNullChar

         .fFlags = &H190

     End With

     FCopy = (0 = SHFileOperation(FileOp))

End Function

Listing 3: Heißes Kopieren der geöffneten Datenbank in eine neue Datei

Man könnte BackupThisDB4 auch etwas aufbohren und für die Zieldatei einen sinnvolleren Namen generieren, anstatt ein bereits bestehendes Backup jedes Mal zu überschreiben.

Der Code ist deshalb so lang geraten, weil die VBA-Funktion FileCopy zum Kopieren von Dateien in diesem Fall fehlschlägt. Sie lässt kein Kopieren einer Datei zu, die sich im Zugriff befindet, was bei der geöffneten Datenbank automatisch der Fall ist. Also muss auf eine Windows-API-Funktion ausgewichen werden, die weniger zimperlich ist. SHFileOperation ist so eine Funktion und in der Prozedur FCopy wird sie zum Kopieren verwendet. Unsere Hauptroutine ruft sie mit den benötigten Parametern auf.

Das Ganze funktioniert tatsächlich. Deshalb kann die Routine in der Beispieldatenbank auch über das Makro makBackup aufgerufen werden, welches seinerseits vom Button Heiße Sicherung der neuen Ribbon-Gruppe ausgeführt wird – Ribbon-Buttons können im Gegensatz zu Access 2003-Menüleisten nur Makros aufrufen, aber keine VBA-Funktionen direkt.

Machen Sie sich klar, dass diese Lösung mit Gefahren verbunden ist. Ohne Schließen der Datenbank ist nicht sichergestellt, dass alles korrekt in den Systemtabellen gespeichert ist und der Datenbank-Cache der Engine ist ebenfalls in ungewissem Zustand. Rein aus Erfahrung lässt sich jedoch sagen, dass es dabei recht selten zu beschädigten Backups kommt.

Einzelne Datenbankobjekte sichern

Manchmal ist es nicht nötig, die gesamte Datenbank zu sichern, wenn lediglich ein paar Änderungen an einem Modul oder einer Abfrage getätigt wurden. Es reicht aus, nur das fragliche Objekt zwischenzuspeichern. Dabei hilft die versteckte Methode SaveAsText des Application-Objekts weiter. Die Syntax sieht so aus:

SaveAsText [Objekttyp], _

[ObjektName], [Dateiname]

Um etwa ein Formular als Textdatei extern abzuspeichern, bediente man sich dieser Zeile:

SaveAsText acForm, _

"frmTest", "c:\frmtest.txt"

Aus der Textdatei lässt sich später wieder das komplette Formular herstellen, und das auch in einer anderen Datenbank. Dafür gibt es das ebenfalls versteckte Pendant LoadFromText:

LoadFromText acForm, _

"frmTest", "c:\frmtest.txt"

Dabei ist Vorsicht geboten. Denn Access überschreibt ein möglicherweise bereits vorhandenes Objekt gleichen Namens ohne jede Rückmeldung! Es vergibt also keinen neuen Namen. Sicherheitshalber könnten Sie daher als Name des zu importierenden Objekts einen anderen angeben, als den bestehenden. Statt frmTest nähmen Sie besser frmTest2. Sie können danach immer noch das ursprüngliche Formular löschen und das neue umbenennen.

SaveAsText und LoadFromText funktionieren bei allen Typen von Datenbankobjekten, außer für Tabellen. Im Modul mdlSaveObjects der Beispieldatenbank, die hier aus Platzgründen nicht abgebildet ist, wird von diesen beiden VBA-Methoden Gebrauch gemacht. Rufen Sie die Prozedur ObjektSicherung des Moduls auf. Sie werden dann in einem Dialog gefragt, ob Sie alle Objekte der Datenbank extern als Textdateien abspeichern möchten. Falls Sie das bestätigen, finden Sie anschließend im Verzeichnis der Datenbank einen Haufen von Textdateien, die jeweils dem Namen der Objekte entsprechen. Im Namen ist zusätzlich als Zahl der Objekttyp enthalten, damit die Wiederherstellungsroutine SicherungWiederherstellen aus dem Namen der Textdateien erkennen kann, welcher Parameter für LoadFormText zu verwenden ist.

Wenn Sie die Nachfrage im Dialog verneinen – Sie können auch den Abbrechen-Button nehmen –, so werden Sie in der Folge für jedes Objekt gesondert gefragt, ob es gesichert werden soll. Aber auch hier kann die Routine abgebrochen werden.

In einer Schleife arbeite die Routine alle Datenbankenobjekte ab, wobei sie die Systemtabelle MSysObjects zurate zieht. Für jedes Objekt erfolgt ein Aufruf von SaveAsText.

Die Prozedur SicherungWiederherstellen ist vergleichsweise einfacher gehalten. Sie schaut im Verzeichnis der Datenbank nach, welche Backup-Textdateien zu finden sind, erkennbar an der Endung .back.txt. Aus dem Dateinamen werden schließlich der Objekttyp und der Objektname extrahiert.

Für jedes einzelne gefundene Objekt fragt ein Dialog dann nach, ob man es wiederherstellen möchte. Bei Bestätigung wird es importiert. Sollte ein Objekt gleichen Namens bereits existieren, so wird es kommentarlos überschieben! Modifizieren Sie diesen Code gegebenenfalls, falls sie dieses "Feature" aufheben möchten.