Zur Hauptseite ... Zum Onlinearchiv ... Zum Abonnement ... Zum Newsletter ... Zu den Tools ... Zum Impressum ... Zum Login ...

Achtung: Dies ist nicht der vollständige Artikel, sondern nur ein paar Seiten davon. Wenn Sie hier nicht erfahren, was Sie wissen möchten, finden Sie am Ende Informationen darüber, wie Sie den ganzen Artikel lesen können.

Kompletten Artikel lesen?

Einfach für den Newsletter anmelden, dann lesen Sie schon in einer Minute den kompletten Artikel und erhalten die Beispieldatenbanken.

E-Mail:

Gedrucktes Heft

Diesen Beitrag finden Sie in Ausgabe 2/2004.

Unser Angebot für Sie!

Lesen Sie diesen Beitrag und 500 andere sofort im Onlinearchiv, und erhalten Sie alle zwei Monate brandheißes Access-Know-how auf 72 gedruckten Seiten! Plus attraktive Präsente, zum Beispiel das bald erscheinende Buch 'Access 2010 - Das Grundlagenbuch für Entwickler'!

Diesen Beitrag twittern

Datenbanken komprimieren,
sichern und packen

Manfred Hoffbauer, Düsseldorf, und André Minhorst, Duisburg

Access speichert alle Objekte einer Datenbank in einer einzigen Datei mit der Erweiterung .mdb. Wenn Sie einmal die Zeit für das Erstellen der Datenbankobjekte und die Zeit für die Datenbearbeitung zusammenrechnen, dann erhalten Sie einen Eindruck von dem Wert der Datenbankdatei. Der einzige wirksame Schutz gegen den totalen Verlust der .mdb-Datei ist die regelmäßige Datensicherung auf einem externen Medium. Dabei und bei einigen anderen Aufgaben hilft Ihnen das Tool, das wir Ihnen in diesem Beitrag vorstellen.

Um es vorwegzunehmen: Die Sicherung einer Datenbank ist immer lästig. Um hohe Sicherheit zu erlangen, müssen Sie die .mdb-Datei auf einem externen Medium (zum Beispiel Band, CD, DVD, FTP-Verzeichnis, Wechselplatte) sichern und dieses auch noch an einem sicheren Ort aufbewahren.

Die Datenbank sollte sich selbst bei einem Totalverlust des Server-PC beispielsweise durch Diebstahl oder Brand wieder rekonstruieren lassen.

Aufbau der Anwendung

Eine weniger sichere, aber weitaus einfacher zu realisierende Form der Datensicherung ist das regelmäßige Kopieren der Dateibankdatei. Hierbei tritt immer wieder das Problem auf, dass die .mdb-Dateien unter Umständen zahlreich und an verschiedensten Orten auf der Festplatte verstreut sind. An dieser Stelle hilft Ihnen das im Folgenden beschriebene Access-Programm weiter, das das Kopieren der Datenbanken für Sie übernimmt. Weiter unten in diesem Beitrag reichern wir das Basisprogramm um eine Funktion zum Komprimieren der Datenbanken an.

Zum Schluss erfahren Sie noch, wie Sie die Sicherungsvorgänge mit dem Windows-Dienst Geplante Tasks zeitlich planen können. Ein Verlegen der Sicherung auf die Nacht verringert die Wahrscheinlichkeit, dass Datenbanken nicht zuverlässig gesichert werden können, weil diese noch durch Benutzer gesperrt sind.

Hinweis

Access-Datenbanken können nur zuverlässig gesichert werden, wenn sie zum Zeitpunkt der Sicherung nicht geöffnet sind. Weitere Informationen zu diesem Thema erhalten Sie im Beitrag Datenbanksperre abfragen in der vorliegenden Ausgabe von Access im Unternehmen. (

Tabelle zum Speichern der
Sicherungsvorgänge

Die für die Steuerung der Sicherungsfunktion benötigten Daten werden in der Tabelle tblDatensicherung gespeichert (s. Tab. 1). Anhand des Tabellenentwurfs können Sie erkennen, dass das Tool einige Zusatzfunktionen enthält:

  • Sichern von Datenbanken
  • Komprimieren von Datenbanken
  • Packen von Datenbanken
  • Packen aller in einem Verzeichnis und dessen Unterverzeichnissen enthaltenen Datenbanken
  • Zeitliche Steuerung der Sicherungsvorgänge
  • Hinweis

    Zum Packen verwenden Sie das Programm Arj32.exe. Es dampft .mdb- und andere Dateien gewaltig ein und hilft damit, Festplattenspeicher zu sparen. Sie können das Programm von der Seite Fehler! Hyperlink-Referenz ungültig. kostenlos zum Test herunterladen. Die Datei befindet sich im Bereich Download. Zur Installation der Software starten Sie einfach die heruntergeladene Datei. (

    Parametertabelle

    Die Tabelle tblParameter besteht aus drei Feldern: ParamterID, Parameter und Wert. Hier speichern Sie unterschiedliche Parameter wie beispielsweise den Pfad zur Datei MSAccess.exe auf dem aktuellen Rechner oder den Pfad zu dem in dieser Anwendung verwendeten Packprogramm Arj.exe.

    Die Parameter werden von Hand in diese Tabelle eingetragen; bei Bedarf können Sie dazu ein geeignetes Formular anlegen.

    Formular zur Eingabe der
    Sicherungsdaten

    Um die Eingabe der Daten in die Tabelle zu vereinfachen, verwenden Sie ein geeignetes Formular (s. Abb. 1).

    In dem Formular können Sie beliebig viele Sicherungsvorgänge definieren, die verschiedene Dateien, Sicherungsarten und Zeitpunkte beinhalten. Durch das Speichern eines Datensatzes wird automatisch eine Aufgabe im Windows-Dienst Geplante Tasks erstellt.

    Hinweis

    Weitere Informationen zum Planen von Aktionen mit Geplante Tasks finden Sie im Beitrag Geplante Tasks mit Access in der vorliegenden Ausgabe von Access im Unternehmen. (

    Feldname

    Bedeutung

    DatenbankID

    Zahlenfeld. Als Primärschlüssel und zur Sortierung geeignet.

    Quelldatei

    Laufwerk, Pfad und Dateiname der Quelldatei.

    Zieldatei

    Laufwerk, Pfad und Dateiname der Zieldatei.

    IstKomprimieren

    Erhält den Wert ja, wenn die Datenbank vor der Sicherung komprimiert werden soll.

    IstPacken

    Erhält den Wert ja, wenn die Sicherung mit ARJ32 gepackt werden soll.

    IstRekursiv

    Nur bei IstPacken = JA relevant. Erhält den Wert ja, wenn ARJ32 Unterverzeichnisse rekursiv durchsuchen soll.

    IstGestartet

    Ja/Nein-Feld anhand dessen Sie feststellen können, ob der Vorgang begonnen wurde.

    IstAbgeschlossen

    Ja/Nein-Feld anhand dessen Sie feststellen können, ob der Vorgang abgeschlossen wurde.

    Fehlermeldung

    Textfeld, das das Ergebnis des Vorgangs beschreibt.

    LetzteÄnderung

    Zeitpunkt der letzten Änderung an diesem Datensatz.

    Uhrzeit

    Uhrzeit des Backups

    Samstag, Sonntag, ...

    Tag/e der Woche, an dem beziehungsweise denen gesichert werden soll

    JobID

    ID, unter der dieser Sicherungsvorgang in Geplante Tasks gespeichert ist

    Tab. 1: Die Felder der Tabelle tblDatensicherung

    Neben dem Festlegen der Eigenschaften eines Sicherungsvorgangs können Sie jeden Sicherungsvorgang einzeln starten. Dazu finden Sie am rechten Rand des Formulars für jeden Datensatz eine entsprechende Schaltfläche. Diese Funktion kann nicht nur zum manuellen Sichern, sondern auch zum Testen der Sicherungsfunktion verwendet werden.

    Ablauf eines
    Sicherungsvorgangs

    Abb. 1: Das Formular zeigt den Inhalt der Tabelle tblDatensicherung und steuert die Datensicherung.

    Der Start der Datensicherung erfolgt mit der Prozedur Sichere (s. Quellcode 1). Diese wird von zwei Stellen aus aufgerufen:

  • direkt über eine der Schaltflächen zum Starten eines Sicherungsvorgangs
  • über eine Funktion, die durch das AutoExec-Makro beim Starten der Datenbank durch den Windows-Dienst Geplante Tasks ausgelöst wird
  • Die Prozedur Sichere erwartet die DatenbankID eines Sicherungsdatensatzes aus der Tabelle tblDatensicherung.

    Die erste Aufgabe der Prozedur Sichere besteht darin, die Felder IstAbgeschlossen und Fehlermeldung zu initialisieren.

    Werte von einem vorhergehenden Durchlauf werden dadurch gelöscht. Das Feld LetzteÄnderung wird auf die aktuelle Systemzeit und das Feld IstGestartet auf Ja gesetzt.

    Steuerung

    Die anschließende If-Abfrage übernimmt die grundlegende Steuerung für den aktuellen Datensatz und verzweigt in verschiedene Prozeduren. Der Funktionsaufruf IstDateiVorhanden(rst!Quelldatei) prüft zunächst, ob die angegebene Quelldatei überhaupt existiert. Die dahinter liegende Funktion ermittelt das Vorhandensein mittels Dir-Funktion. Diese liefert sowohl bei einzelnen Dateien (zum Beispiel C:\Temp\Test.mdb) als auch bei der Verwendung von gültigen Wildcards (zum Beispiel C:\Temp\*.mdb) den Wert True zurück. Falls Laufwerk, Pfad oder Datei nicht existieren, zeigt die Funktion den Wert False an.

    Das Programm vermerkt das Fehlen der Quelldatei in dem Feld Fehlermeldung des aktuellen Datensatzes.

    Falls die Quelldatei gefunden werden kann, prüft das Programm zunächst, ob die Datenbank komprimiert werden soll. Falls ja, wird die Komprimierung mit dem Aufruf der Prozedur Komprimiere initiiert.

    Danach wird entweder mit SichereMitArj das einfache Kopieren der Datei oder mit SichereOhneArj das Komprimieren unter Verwendung des Arj32-Packers gestartet. Mit dieser Logik können Sie die .mdb-Datei zuerst komprimieren und sie dann kopieren oder packen.

    Public Sub Sichere(DatenbankID As Integer)

        On Error GoTo Sichere_Fehler

        Dim strQuelldatei As String

        Dim rst As Recordset

        Set rst = CurrentDb.OpenRecordset("SELECT * FROM tblDatensicherung " _
            & "WHERE DatenbankID = " & DatenbankID)

        Do While Not rst.EOF

            With rst

               .Edit

               !LetzteÄnderung = Now

               !IstGestartet = True

               !IstAbgeschlossen = False

               !Fehlermeldung = ""

               .Update

            End With

            If IstDateiVorhanden(Nz(rst!Quelldatei, "")) Then

                If rst!IstKomprimieren Then

                    Komprimiere rst

                End If

                If rst!IstPacken Then

                    SichereMitArj rst

                Else

                    SichereOhneArj rst

                End If

            Else

                rst.Edit

                rst!Fehlermeldung = rst!Fehlermeldung & _
                    "Quelldatei konnte nicht gefunden werden."

                rst!LetzteÄnderung = Now

                rst.Update

            End If

            rst.Edit

            rst!IstAbgeschlossen = True

            rst!LetzteÄnderung = Now

            rst.Update

    Sichere_WeiterNachFehler:

            rst.MoveNext

        Loop

        rst.Close

        Set rst = Nothing

        Exit Sub

    Sichere_Fehler:

        rst.Edit

        rst!Fehlermeldung = rst!Fehlermeldung & Err.Description

        rst!LetzteÄnderung = Now

        rst.Update

        GoTo Sichere_WeiterNachFehler

    End Sub

    Quellcode 1

    Falls Sie eine Datenbank eventuell zuerst sowohl kopieren als auch packen wollen, dann müssen Sie statt If Then...Else ein Konstrukt verwenden, mit dem Sie die beiden Prozeduren auch nacheinander aufrufen können. In diesem Fall wäre eventuell das Hinzufügen eines weiteren Feldes namens IstKopieren sinnvoll.

    Public Sub GetDateiListe(ByRef strDateiliste() As String, strDateimaske As String)

        Dim strDatei As String

        Dim strPfad As String

        ReDim strDateiliste(0)

        strPfad = GetPfad(strDateimaske)

        strDatei = Dir(strDateimaske)

        Do While Len(strDatei) > 0

            ReDim Preserve strDateiliste(UBound(strDateiliste) + 1) As String

            strDateiliste(UBound(strDateiliste) - 1) = strPfad & strDatei

            strDatei = Dir

        Loop

    End Sub

    Quellcode 2

    Unabhängig davon, welche Operationen im Einzelnen durchgeführt werden, schreibt die Prozedur Sichere am Ende den Wert True in das Feld IstAbgeschlossen. Außerdem wird die aktuelle Systemzeit im Feld LetzteÄnderung hinterlegt.

    Tritt ein Fehler auf, verzweigt das Programm direkt zur Sprungmarke Sichere_Fehler. Das Programm schreibt die Fehlermeldung in das Feld Fehlermeldung, vermerkt die Systemzeit und setzt den Programmablauf fort.

    Mit dieser Logik gewährleisten Sie, dass das Programm auch im Batchbetrieb ablaufen kann. Es dürfte nur noch äußerst selten vorkommen, dass das Programm auf Grund eines Fehlers unterbrochen wird. Sie haben vielmehr die Möglichkeit, eventuell aufgetretene Fehler auch nach einem längeren Programmdurchlauf in der Tabelle tblDatensicherung zu sichten, zu analysieren und die Fehlerursache zu beheben.

    Datenbank komprimieren

    Das Komprimieren der Datenbank erfolgt in der Prozedur Komprimiere. Diese dimensioniert ein dynamisches Stringarray. Der Aufruf der Prozedur GetDateiListe füllt dieses Array mit einer Liste der zu komprimierenden Dateinamen (s. Quellcode 2).

    Dateiliste lesen

    Die Prozedur GetDateiliste wird mit zwei Parametern aufgerufen. Der erste Parameter ist ein dynamisches Stringarray, der zweite eine Zeichenkette. Die Zeichenkette enthält den Wert des Feldes Quelldatei aus dem aktuellen Datensatz. Dies entspricht dem Laufwerk, dem Pfad und einem Dateinamen oder einer Dateimaskierung.

    Beim ersten Aufruf der Dir()-Funktion prüft die Prozedur, ob die Datei gefunden werden kann. Falls ja, wird das dynamische Array um ein Element vergrößert. Bitte achten Sie darauf, dass die Dir()-Funktion stets nur den gefundenen Dateinamen liefert. Da das Array aber vollständige Dateinamen enthalten muss, werden per GetPfad()-Funktion das Laufwerk und der Pfad hinzugefügt. Der Befehl ReDim Preserve redimensioniert das Stringarray unter Beibehaltung der bisher gespeicherten Daten. Mit UBound(strDateiliste) erhalten Sie den Index des höchsten Elements. Dieser wird um 1 erhöht und als neue Dimensionierung verwendet. Am Ende der Prozedur enthält das Array alle Dateinamen aus dem aktuellen Verzeichnis.

    Falls der Aufruf ohne Verwendung von Wildcards erfolgte, enthält das Array nur ein Element, beim Aufruf mit Wildcards enthält es für jeden passenden Dateinamen ein Element. Da der Parameter ByRef übergeben wird, kann die übergeordnete Prozedur die Dateiliste verwenden.

    Public Sub Komprimiere(ByRef rst As Recordset)

        Dim strDatei As String

        Dim strDateiliste() As String

        Dim i As Integer

        i = 0

        GetDateiListe strDateiliste, rst!Quelldatei

        rst.Edit

        For i = 0 To UBound(strDateiliste) - 1

            strDatei = strDateiliste(i)

            Dim strTempdatei As String

            strTempdatei = HoleZieldatei(strDatei, "", ".tmp")

            On Error GoTo Komprimiere_Fehler

            DBEngine.CompactDatabase strDatei, strTempdatei

            Kill strDatei

            Name strTempdatei As strDatei

            rst!Fehlermeldung = rst!Fehlermeldung & "Datenbank " & strDatei _
                & " wurde komprimiert."

            GoTo Komprimiere_Weiter

    Komprimiere_Fehler:

            rst!Fehlermeldung = rst!Fehlermeldung & "Fehler beim Komprimieren von " _
                & strDatei & ": " & Err.Description

            Resume Komprimiere_Weiter

    Komprimiere_Weiter:

        Next i

        rst.Update

    End Sub

    Quellcode 3

    Fehlerbehandlung

    Die Prozedur Komprimiere durchläuft die Dateiliste mit einer For Next-Schleife (s. Quellcode 3). Der einzelne Dateiname wird der Variablen strDatei zugewiesen. Die Anweisung

    strTempdatei = HoleZieldatei(strDatei, _
        "", ".tmp")

    ermittelt den Namen einer Zieldatei. Die Prozedur HoleZieldatei dient an dieser Stelle lediglich dazu, einen temporären Dateinamen zu ermitteln. Sie gewinnt im Zusammenhang mit dem Kopieren an Bedeutung und wird weiter unten in diesem Zusammenhang beschrieben. Das eigentliche Komprimieren erfolgt in drei Schritten:

  • Die Anweisung DBEngine.CompactDatabase komprimiert die angegebene Quelldatei und schreibt diese in die Zieldatei.
  • Die Kill-Anweisung löscht die Quelldatei.
  • Die Name-Anweisung weist der komprimierten Datei den ursprünglichen Namen der Quelldatei zu. (
  • Es gibt eine Reihe Fehler, die während dieser Prozedur auftreten können. Eine Datenbank kann von einem anderen Anwender gesperrt sein, eine Datenbank kann ein nicht lesbares Format haben (zum Beispiel eine Datenbank in einer höheren Access-Version), die Festplatte kann überlaufen und so weiter. Die On Error-Goto-Anweisung soll diese und andere nicht vorhergesehene Fehler abfangen. Sie verzweigt deshalb auf eine Sprungmarke mit VBA-Code, der die aktuelle Fehlermeldung im gleichnamigen Feld des Datensatzes hinzufügt.

    Private Sub SichereOhneArj(rst As Recordset)

        Dim strQuelle As String

        Dim strZiel As String

        rst.Edit

        strZiel = Nz(rst!Zieldatei, "")

        strQuelle = Nz(rst!Quelldatei, "")

        If IstMitWildcards(strQuelle) Then

            rst!Fehlermeldung = rst!Fehlermeldung & "Die Angabe von Wildcards in der " _
                "Quelldatei ist nur zusammen mit dem Packen (ARJ32) implementiert."

        Else

            If IstMitWildcards(strZiel) Then

                rst!Fehlermeldung = rst!Fehlermeldung & "Bitte geben Sie eine " _
                    "Zieldatei ohne Wildcards an."

            Else

                strZiel = HoleZieldatei(strQuelle, strZiel, ".bak")

                FileCopy strQuelle, strZiel

                If IstDateiVorhanden(strZiel) Then

                    rst!IstAbgeschlossen = True

                    rst!Fehlermeldung = rst!Fehlermeldung & "Sicherung in Datei " _
                        & strZiel & " ist erfolgt."

                Else

                    rst!Fehlermeldung = rst!Fehlermeldung & "Fehler beim Kopieren " _
                        "von Datei " & strQuelle & " zu Datei " & strZiel

                End If

            End If

        End If

        rst!LetzteÄnderung = Now

        rst.Update

    End Sub

    Quellcode 4

    Die Resume-Anweisung ist in diesem Zusammenhang besonders wichtig. Erst mit dieser Anweisung teilen Sie Access mit, dass der Fehler behandelt ist. Falls Sie die Resume-Anweisung weglassen, kann Access nur jeweils den ersten aufgetretenen Fehler behandeln. Beim zweiten On Error-Ereignis würde Access direkt in die aufrufende Prozedur verzweigen.

    Bei der Angabe einer Maskierung wie beispielsweise ...\Eigene Dateien\*.mdb durchläuft Access die Schleife für jede .mdb-Datei einmal. Die Prozeduren schreiben das Laufwerk und den vollständigen Pfad sowie eine Erfolgs- oder Fehlermeldung für jede Datei additiv in das Feld Fehlermeldung. Da der Text sehr lang werden kann, ist dieses Feld als Memofeld definiert. Falls Sie sich in der Datenblatt- oder Formularansicht einen guten Überblick über den Inhalt des Feldes schaffen wollen, können Sie mit Shift + F2 das Zoom-Fenster öffnen.

    Datenbank sichern

    Unter dem Sichern einer Datenbank ist das einfache Kopieren der .mdb-Datei mit der FileCopy-Anweisung zu verstehen. Diese Anweisung erfordert lediglich die Angabe einer Quelldatei und einer Zieldatei.

    Eingebettet wird der Kopiervorgang in die Prozedur SichereOhneArj (s. Quellcode 4). Die Prozedur erwartet als Parameter den kompletten Datensatz. Sie liest zunächst die Namen der Quell- und Zieldateien ein.

    Sollte die Quelldatei oder die Zieldatei Platzhalter enthalten, wird die Prozedur abgebrochen und eine entsprechende Fehlermeldung in die Tabelle tblDatensicherung geschrieben.

    Anschließend ermittelt die Prozedur HoleZieldatei aus dem Namen der Quelldatei und dem Namen der Zieldatei (soweit vorhanden) einen Namen für die Zieldatei (s. Quellcode 5).

    Private Function HoleZieldatei(strQuelle As String, strZiel As String, _
        strErweiterung As String) As String

        If Len(strZiel) = 0 Then

            HoleZieldatei = DateinameFestlegen(strQuelle) & strErweiterung

        Else

            If Not (GetErweiterung(strZiel) = strErweiterung) Then

                strZiel = strZiel & strErweiterung

            End If

            HoleZieldatei = strZiel

        End If

    End Function

    Quellcode 5

    Public Function DateinameFestlegen(strQuelle As String) As String

        DateinameFestlegen = GetPfad(strQuelle) & GetDateiOhneErweiterung(strQuelle) _
            & "_" & Format(Date, "YYYYMMDD") & "_" & Format(Time, "HHMMSS") & "." _
            & GetErweiterung(strQuelle)

    End Function

    Quellcode 6

    Public Function IstDateiVorhanden(ByVal strDatei As String) As Boolean

        If Dir(strDatei) = "" Then

            IstDateiVorhanden = False

        Else

            IstDateiVorhanden = True

        End If

    End Function

    Quellcode 7

    Schließlich wird der Kopiervorgang gestartet, das Ergebnis mit der Funktion IstDateiVorhanden (s. Quellcode 6) überprüft und es werden entsprechende Meldungen in die Tabelle tblDatensicherung geschrieben.

    Zieldatei ermitteln

    Genau hier liegt der Hase im Pfeffer. Was passiert, wenn die Zieldatei bereits existiert? Soll das Programm die Datei einfach überschreiben?

    Diese Methode wäre sicherlich zu unsicher. Zu schnell könnte so versehentlich eine wichtige .mdb-Datei für immer verloren gehen.

    Aus diesem Grund ermittelt die Funktion HoleZieldatei eine Zieldatei, die garantiert noch nicht existiert.

    Die Funktion unterscheidet zwei Fälle: Wenn keine Zieldatei angegeben wurde, dann wird der Name der Zieldatei mit der Funktion DateinameFestlegen ermittelt und die mit dem Parameter strErweiterung übergebene Dateiendung angehängt. Die Funktion DateinameFestlegen (s. Quellcode 6) setzt einen mit hoher Wahrscheinlichkeit einzigartigen Dateinamen zusammen, indem sie dem Namen der Quelldatei das Datum und die Uhrzeit zum Zeitpunkt des Backups hinzufügt. Wenn die Datenbank also nicht mehr als einmal pro Sekunde gesichert wird, ist dieser Dateiname einmalig.

    Public Function GetPfad(strPfadUndDatei As String) As String

        GetPfad = Left(strPfadUndDatei, Len(strPfadUndDatei) - _
            Len(GetDateiMitErweiterung(strPfadUndDatei)))

    End Function

    Quellcode 8

    Public Function GetDateiOhneErweiterung(strPfadUndDatei As String) As String

        Dim strDatei As String

        strDatei = GetDateiMitErweiterung(strPfadUndDatei)

        Dim strErweiterung As String

        strErweiterung = GetErweiterung(strDatei)

        If Len(strErweiterung) > 0 Then strErweiterung = "." & strErweiterung

        GetDateiOhneErweiterung = Left(strDatei, Len(strDatei) - Len(strErweiterung))

    End Function

    Quellcode 9

    Public Function GetErweiterung(strDateinameUndErweiterung As String) As String

        Dim p As Integer

        p = InStr(strDateinameUndErweiterung, ".")

        If p = 0 Then

            GetErweiterung = strDateinameUndErweiterung

        Else

            GetErweiterung = GetErweiterung(Mid(strDateinameUndErweiterung, p + 1))

        End If

    End Function

    Quellcode 10

    Public Function GetDateiMitErweiterung(strPfadUndDatei As String) As String

        Dim p As Integer

        p = InStr(strPfadUndDatei, "\")

        If p = 0 Then

            GetDateiMitErweiterung = strPfadUndDatei

        Else

            GetDateiMitErweiterung = GetDateiMitErweiterung(Mid(strPfadUndDatei, p + 1))

        End If

    End Function

    Quellcode 11

    Dabei verwendet die Funktion die drei Funktionen GetPfad (s. Quellcode 8), GetDateiOhneErweiterung (s. Quellcode 9) und GetErweiterung (s. Quellcode 10), um den Namen der Zieldatei auseinander zu nehmen und zu dem neuen, einzigartigen Namen zusammenzusetzen.

    Die Funktionen sind weitgehend selbsterklärend.

    Dateiname mit Erweiterung
    berechnen

    Eine besondere Erwähnung soll die Funktion GetDateiMitErweiterung finden (s. Quellcode 11).

    Diese Funktion erhält als Parameter die vollständige Angabe von Laufwerk, Pfad, Dateiname und Erweiterung einer Datei. Der daraus zu berechnende Dateiname entspricht der Zeichenkette nach dem letzten Backslash (\).

    Die Funktion berechnet bei ihrem ersten Aufruf zuerst die Position des ersten Backslash. Wenn Sie beispielsweise C:\Temp\Test.mdb als Parameter übergeben, dann erhält die Variable p den Wert 3. Solange p ungleich 0 ist, ruft die Funktion sich selbst rekursiv auf.

    Beim ersten rekursiven Aufruf lautet der Parameter Temp\Test.mdb. Dies entspricht der Zeichenkette ab p + 1. Beim zweiten Aufruf lautet der Parameter Test.mdb. Da diese Zeichenkette keinen Backslash enthält, wird p zum ersten Mal 0 und die Funktion gibt Test.mdb als Funktionswert an den ersten Aufruf zurück. Der erste Aufruf gibt den gleichen Wert zurück und so wird der Wert bis zur aufrufenden Programmzeile durchgereicht.

    Die nahezu identische Logik finden Sie in der Funktion GetErweiterung (s. Quellcode 10). Hier wird die Zeichenkette nach dem letzten Punkt als Erweiterung berechnet.

    Dateien packen

    Das gleichzeitige Packen der zu sichernden Datenbank ist in vielerlei Hinsicht effektiver als das einfache Kopieren: Mit dem Packen können Sie unter Umständen viel Speicherplatz sparen und gleichzeitig die Zusatzfeatures des Packprogramms nutzen.

    Das in diesem Beitrag verwendete Programm Arj32.exe-Programm läuft im DOS-Fenster ab und lässt sich deshalb problemlos im Batchbetrieb benutzen. Wenn Sie das Programm mit der Option -? starten, erhalten Sie einen umfangreichen Hilfstext, der etliche Parameter beschreibt.

    Am interessantesten dürfte allerdings der Parameter -r sein. Dieser veranlasst Arj32.exe ausgehend von einem angegebenen Ordner alle untergeordneten Ordner nach den zu archivierenden Dateien zu durchsuchen. Mit der folgenden Anweisung können Sie beispielsweise alle .mdb-Dateien auf Laufwerk C:\ in der Datei C:\Backup.arj sichern:

    ARJ32.exe a -r "C:\Backup.arj" "C:\*.mdb"

    Obwohl dies sicherlich eine einfache Methode zum Sichern von Datenbanken ist, dürfte sie nicht so ohne Weiteres praktikabel sein. Einerseits können auf diese Art und Weise trotz des Packens recht große .arj-Dateien entstehen. Gleichzeitig dauert es unter Umständen eine ganze Weile, bis alle .mdb-Dateien eines Verzeichnisses gesichert sind.

    Optimal ist die Kombination aus dedizierten Einträgen in tblDatensicherung und der Verwendung von Arj32.exe. So können Sie gezielt eines oder mehrere Datenverzeichnisse angeben und diese dann rekursiv durchsuchen lassen.

    Batch synchron ausführen

    Der Aufruf von Arj32.exe erfolgt in der Prozedur SichereMitArj (s. Quellcode 12). Diese Datei ermittelt zunächst wiederum über die Funktion HoleZieldatei einen Namen für die Zieldatei. Anschließend setzt Sie die Anweisung für den Aufruf von Arj32.exe zusammen. Hier ist zu beachten, dass lange Dateinamen mit Blanks und anderen Sonderzeichen in Anführungszeichen zu setzen sind. Deshalb werden sowohl der Quelldateiname als auch der Zieldateiname von Chr(34)-Zeichen eingefasst.

    Die auszuführende DOS-Anweisung wird in der Stringvariablen strCommand zusammengesetzt. Diese Anweisung ließe sich mit der Shell-Anweisung von VBA direkt ausführen. Windows führt die Shell-Anweisung jedoch asynchron aus. Es öffnet also ein DOS-Fenster und startet Arj32.exe, während es quasi gleichzeitig die Ausführung des VBA-Programms fortsetzt. Der anschließende Aufruf der Anweisung IstDateiVorhanden(strZiel) würde immer den Wert False liefern.

    Private Sub SichereMitArj(rst As Recordset)

        Dim strZiel As String

        Dim strCommand As String

        Dim vErgebnis As Variant

        ' Komprimieren mit und ohne Wildcards ist identisch

        strZiel = HoleZieldatei(Nz(rst!Quelldatei, ""), Nz(rst!Zieldatei, ""), ".arj")

        If rst!IstRekursiv Then

            strCommand = cArjExe & " a -r " & Chr(34) & strZiel & Chr(34) & " " _
                & Chr(34) & rst!Quelldatei & Chr(34)

        Else

            strCommand = cArjExe & " a -r " & Chr(34) & strZiel & Chr(34) & " " _
                & Chr(34) & rst!Quelldatei & Chr(34)

        End If

        rst.Edit

        ExecCmd (strCommand)

        DoEvents

        If IstDateiVorhanden(strZiel) Then

            rst!IstAbgeschlossen = True

            rst!Fehlermeldung = rst!Fehlermeldung & "Sicherung in Datei " _
                & strZiel & " ist erfolgt."

        Else

            rst!Fehlermeldung = rst!Fehlermeldung & "Die Zieldatei " & strZiel _
                & " ist nach dem Komprimieren nicht vorhanden."

        End If

        rst!LetzteÄnderung = Now

        rst.Update

    End Sub

    Quellcode 12

    Um dies zu umgehen und gleichzeitig zu vermeiden, dass zu viele DOS-Fenster gleichzeitig geöffnet werden, sollten Sie die Anweisung synchron ausführen lassen.

    Der Programmcode hierfür ist bereits in der Beispielanwendung enthalten. Er wurde von der Microsoft-Homepage heruntergeladen und in das Modul modShell eingefügt. Die genaue Adresse der Quelle lautet:

    http://support.microsoft.com/default.aspx?scid=kb;EN-US;178116

    Dort finden Sie den Quellcode und eine Beschreibung des Programmcodes für die Prozedur ExecCmd, die das Beispielprogramm verwendet.

    Erfolgsmeldung

    Nach der Ausführung der ExecCmd-Prozedur prüft das Programm mit IstVorhanden, ob Arj32.exe die spezifizierte Zieldatei wirklich geschrieben hat. Falls die Datei vorhanden ist, vermerkt das Programm eine Erfolgsmeldung in dem Datenfeld Fehlermeldung, andernfalls schreibt es einen Fehlertext in dieses Feld.

    Zeitgesteuerte
    Sicherungsvorgänge

    Die in den vorhergehenden Kapiteln vorgestellten Funktionen und Prozeduren zum Sichern von Datenbankdateien sollen nun als Grundlage für das zeitgesteuerte Sichern von Datenbanken verwendet werden.

    Private Sub Form_AfterUpdate()

        Dim db As DAO.Database

        Dim rst As DAO.Recordset

        Dim strAccessPfad As String

        Dim strDatenbankpfad As String

        Dim intWochentage As Integer

        Dim lngJobID As Long

        strDatenbankpfad = Datenbankpfad

        strAccessPfad = DLookup("Wert", "tblParameter", "Parameter = 'PfadZuAccess'")

        Set db = CurrentDb

        Set rst = db.OpenRecordset("SELECT * FROM tblDatensicherung " _
            & "WHERE DatenbankID = " & Me.DatenbankID, dbOpenDynaset)

        Do While Not rst.EOF

            If Not IsNull(rst!JobID) Then

                TaskLoeschen rst!JobID

            End If

            intWochentage = IIf(rst!Montag = True, 1, 0) + _
                IIf(rst!Dienstag = True, 2, 0) + IIf(rst!Mittwoch = True, 4, 0) _
                + IIf(rst!Donnerstag = True, 8, 0) + IIf(rst!Freitag = True, 16, 0) 
                + IIf(rst!Samstag = True, 32, 0) + IIf(rst!Sonntag = True, 64, 0)

            If (TaskAnlegen(Chr(34) & strAccessPfad & Chr(34) & " " & Chr(34) _
                & CurrentDb.Name & Chr(34) & " /cmd " & Chr(34) & rst!DatenbankID _
                & Chr(34), rst!Uhrzeit, True, intWochentage, , True, lngJobID)) > 0 Then

                MsgBox "Fehler beim Anlegen des Tasks für die Datenbank mit der Nummer " _
                    & rst!DatenbankID

            End If

            If Not IsNull(lngJobID) Then

                rst.Edit

                rst!JobID = lngJobID

                rst.Update

            End If

            rst.MoveNext

        Loop

    End Sub

    Quellcode 13

    Sie haben das Ende des frei verfügbaren Teils des Artikels erreicht. Lesen Sie weiter, um zu erfahren, wie Sie den vollständigen Artikel lesen und auf viele hundert weitere Artikel zugreifen können.

    Sind Sie Abonnent?Jetzt einloggen ...
     

    Kompletten Artikel lesen?

    Einfach für den Newsletter anmelden, dann lesen Sie schon in einer Minute den kompletten Artikel und erhalten die Beispieldatenbanken.

    E-Mail:

    © 2003-2015 André Minhorst Alle Rechte vorbehalten.