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 6/2012.

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

Zusammenfassung

Migrieren Sie eine .accdb-Datenbank in eine Datenbank im Format von Access 2003.

Techniken

Formulare, VBA, Ribbons, Menüleisten

Voraussetzungen

Access 2003 und höher

Beispieldateien

KVA.accdb, KVA.mdb

Shortlink

www.access-im-unternehmen.de/860

ACCDB nach Access 2003 migrieren

André Minhorst, Duisburg

Kennen Sie das auch? Sie haben eine schicke Datenbank mit Access 2007 oder 2010 erstellt, diese mit einem Ribbon und Schaltflächen mit Icons ausgestattet und nun kommt ein Kunde und möchte diese Datenbank unter Access 2003 einsetzen. Da kommt schon ein wenig Aufwand auf Sie zu! Deshalb nehmen wir ein solches Downgrade im vorliegenden Beitrag einmal unter die Lupe.

Ausgangspunkt ist die Datenbank KVA.accdb aus dem Beitrag Kunden, Verträge und Anschreiben verwalten (www.access-im-unternehmen.de/854). Diese Anwendung wurde sogar unter Access 2010 erstellt und soll nun, soweit möglich, unter Access 2003 lauffähig gemacht werden. Damit dies gelingt, muss die Anwendung zunächst einmal um solche Elemente erleichtert werden, die sogar ein Speichern im Format von Access 2002/2003 unmöglich machen.

Ob die Datenbank solche Elemente enthält, finden Sie etwa unter Access 2010 heraus, indem Sie auf Datei klicken, dann im Backstage-Bereich auf Speichern und Veröffentlichen und schließlich auf Access 2002-2003-Datenbank (*.mdb) - s. Abb. 1. Entweder führen Sie hier einen Doppelklick aus oder Sie betätigen nach der Auswahl die Schaltfläche Speichern unter.

pic001.png

Abb. 1: Speichern einer Datenbank im Format von Access 2002/2003

Unter Access 2007 verwenden Sie dazu den Eintrag Speichern unter|Access 2002 - 2003-Datenbank des Office-Menüs (s. Abb. 2).

pic002.png

Abb. 2: Datenbank von Access 2007 aus in anderen Formaten speichern

Tendenziell enthält eine Datenbank unter Access 2007 oder 2010 Elemente, die unter Access 2002/2003 noch nicht bekannt waren.

Ist dies der Fall, meldet Access den Fehler aus Abb. 3. Hier werden gleich einige potenzielle Probleme genannt - unter Access 2007 etwa Anlagefelder oder mehrwertige Felder; unter Access 2010 kommen noch Elemente wie Datenmakros, neue Verschlüsselungstypen oder Navigationssteuerelemente hinzu.

pic003.png

Abb. 3: Fehlermeldung beim Versuch, eine Datenbank mit reinen Access 2007/2010-Features in eine ältere Version umzuwandeln

Während Sie relativ sicher sein können, dass wir in Access im Unternehmen keine mehrwertigen Felder einsetzen, so sieht dies bei Anlagefeldern anders aus: Wenn Sie mit Access 2010 arbeiten und etwa Bilder in Schaltflächen darstellen möchten, kommen Sie nicht um den Einsatz einer Systemtabelle namens MSysResources herum (die standardmäßig ausgeblendet ist - machen Sie diese unter Access 2010 durch die Aktivierung der Optionen Ausgeblendete Objekte anzeigen und Systemobjekte anzeigen sichtbar), die wiederum Bilder in einem Anlagefeld speichert.

Diese Bilddateien können so bequem als Bilder für Bildsteuerelemente oder Schaltflächen ausgewählt werden.

Sollte diese Meldung erscheinen, beginnt die Arbeit also gleich in der Access-Version, mit der Sie die Anwendung erstellt haben. Sie müssen hier die Tabellen ausfindig machen, die Felder vom Typ Anlage enthalten.

Je nachdem, wie lange Sie die Anwendung bereits entwickeln und wie umfangreich diese geworden ist, haben Sie möglicherweise keinen Überblick mehr, wo sich die Felder mit dem betreffenden Datentyp befinden.

Wollen Sie nun alle Tabellen manuell durchsuchen oder lieber einen kleinen Codeschnipsel programmieren, der alle Anlage-Felder (und gegebenenfalls auch die mehrwertigen Felder) ausgibt? Wir entscheiden uns natürlich für letztere Variante, da diese auch zuverlässiger arbeiten dürfte.

Wechseln Sie also zum VBA-Editor und legen Sie in einem geeigneten Modul, beispielsweise mdlTools, eine neue Prozedur namens NeueDatentypenFinden an. Grundsätzlich soll die Prozedur alle Tabellen und alle darin enthaltenen Felder durchlaufen und die Datentypen auf die neuen Typen prüfen.

Die Type-Eigenschaft eines Field-Elements eines TableDef-Elements liefert aber Zahlenwerte. Und wo erhalten wir Informationen über die Konstanten zu diesen Zahlenwerten? Im Objektkatalog. Diesen öffnen Sie mit der Taste F2 und suchen nach dem Begriff Enum.

Darunter finden Sie dann alle möglichen Enumerationen wie DatabaseTypeEnum, FieldAttributeEnum oder auch die gesuchte DataTypeEnum. Klicken Sie auf DataTypeEnum, zeigt der Objektkatalog wie in Abb. 4 die verfügbaren Datentypen samt Zahlenwert an.

pic004.png

Abb. 4: Objektkatalog mit Felddatentypen

Die neuen Datentypen sind mit Zahlenwerten größer 100 versehen - dbAttachment hat etwa den Wert 101. Also soll die Prozedur einfach alle Feldnamen ausgeben, deren Felddatentyp einen Zahlenwert größer als 100 aufweist:

Public Sub NeueFelddatentypenFinden()

    Dim db As DAO.Database

    Dim tdf As DAO.TableDef

    Dim fld As DAO.Field

    Set db = CurrentDb

    For Each tdf In db.TableDefs

        For Each fld In tdf.Fields

            If fld.Type > 100 Then

                Debug.Print tdf.Name, fld.Name, fld.Type

            End If

        Next fld

    Next tdf

    Set db = Nothing

End Sub

Die Prozedur durchläuft nun alle Tabellen (also TableDef-Objekte) der TableDefs-Auflistung der Datenbank und für jede Tabelle alle Felder (also Field-Objekte) der Fields-Auflistung der aktuellen Tabelle. Weist die Type-Eigenschaft einen Wert größer als 100 auf, gibt die Prozedur Tabellenname, Feldname und Datentyp im Direktfenster aus.

Bei der Beispieldatenbank kommen wir glimpflich davon: Das einzige Anlagefeld heißt Data und stammt aus der bereits erwähnten Tabelle MSysResources:

MSysResources Data 101

Im Beispiel der Datenbank KVA.accdb ist allerdings möglicherweise eine zusätzliche Untersuchung notwendig: Die Anwendung verwendet ja ein Backend, in dem sich auch noch Tabellen befinden.

Auch diese müssen Sie selbstverständlich nach entsprechenden neuen Felddatentypen untersuchen. Diese Aufgabe nimmt uns die obige Prozedur jedoch bereits ab: Sie greift auch auf die per Verknüpfung eingebundenen Tabellen zu und untersucht deren Felddatentypen.

Behandlung von Anlage-Feldern

Da wir in Access 2002/2003 ohnehin nicht auf Daten in Anlagefeldern zugreifen können, wäre es am einfachsten, diese Tabelle direkt zu löschen. Allerdings kann es ja sein, dass wir die enthaltenen Bilder noch für Menü- und Symbolleisten oder für Kontextmenüs benötigen. Nun gibt es drei Möglichkeiten:

  • Sie verfügen über eine Kopie der Bilddateien im Dateisystem und können diese später wieder in die Access 2002/2003-Version Ihrer Anwendung einbinden,
  • Sie speichern alle Bilder dieser Tabelle in das Dateisystem, um diese später wieder einzubinden, oder
  • Sie übertragen die Bilder gleich in eine ähnliche aufgebaute Tabelle, welche die Bilder allerdings in einem OLE-Feld speichert.

Die erste Variante erfordert keinen Aufwand. Die zweite können Sie je nach der Anzahl der Bilder manuell durchführen oder Sie verwenden auch hier eine Prozedur, um die Bilder auf die Festplatte zu bannen. Dazu vewenden Sie die Prozedur aus Listing 1. Diese liest zunächst die drei Felder Data.Filedata, Name und Extension aus der Tabelle MSysResources ein.

Listing 1: Dateien aus MSysResources speichern

Public Function DateienSpeichern()

    Dim rst As DAO.Recordset2

    Dim strFilename As String

    On Error GoTo Fehler

    Set rst = CurrentDb.OpenRecordset("SELECT Data.Filedata, Name, Extension FROM MSysResources", _

        dbOpenSnapshot)

    Do While Not rst.EOF

        strFilename = CurrentProject.Path & "\" & rst!Name & "." & rst!Extension

        If Dir(strFilename) <> "" Then

            Kill strFilename

            DoEvents

        End If

        On Error Resume Next

        rst("Data.Filedata").SaveToFile strFilename

        If Err.Number = (-2146697202) Then

            rst!Data.SaveToFile strFilename & ".dat"

            DoEvents

            Name strFilename & ".dat" As strFilename

        End If

        rst.MoveNext

    Loop

Ende:

    On Error Resume Next

    Set rst = Nothing

    Exit Function

Fehler:

    MsgBox Err.Number & "/" & Err.Description, vbCritical

    Resume Ende

End Function

Dabei bezieht sich Data.Filedata direkt auf das Feld Filedata der intern im Anlagefeld Data gespeicherten Untertabelle. Dies verdeutlicht eine Abfrage auf Basis der Tabelle MSysResources in der Entwurfsansicht (s. Abb. 5).

pic005.png

Abb. 5: Zugriff auf die Felder eines Attachment-Felds

Wir gehen an dieser Stelle davon aus, dass jeder Datensatz der Tabelle MSysResources immer nur mit einer Datei befüllt wurde. Dazu durchläuft die Prozedur alle Datensätze dieser Tabelle in einer Do While-Schleife. Innerhalb dieser Schleife ermittelt die Prozedur zunächst den Dateinamen aus den beiden Feldern Name und Extension.

Die Dateien sollen im Verzeichnis der Datenbank gespeichert werden. Dabei prüft die Prozedur, ob eine Datei gleichen Namens bereits vorhanden ist, und löscht diese gegebenenfalls zuvor.

Dabei kommt die Dir-Funktion zum Einsatz, die eine leere Zeichenkette zurückliefert, wenn die als Parameter angegebene Datei nicht vorhanden ist.

Dann versucht die Prozedur, die im Feld Data.Filedata enthaltene Datei mit der SaveToFile-Methode unter dem in strFilename enthaltenen Dateinamen zu speichern.

Gelingt dies nicht, liegt dies in der Regel daran, dass Access Sicherheitsbedenken wegen des Dateityps hat.

Dies erkennt Access allein an der Dateiendung, weshalb die Prozedur in diesem Fall einfach die erlaubte Dateiendung .dat anhängt, die Datei speichert und dann die Dateiendung wieder entfernt.

Dieser Vorgang wird für jeden Datensatz wiederholt, was eine mehr oder weniger große Menge Dateien in das Verzeichnis der aktuellen Datenbank spült.

Wenn Sie die Dateien in einem anderen Verzeichnis speichern möchten, ändern Sie einfach die Zeile

strFilename = CurrentProject.Path & "\" & rst!Name & "." & rst!Extension

ab, indem Sie hinter "\" ein Unterverzeichnis anhängen - zum Beispiel so:

strFilename = CurrentProject.Path & "\pics\" & rst!Name & "." & rst!Extension

Auf diese Weise werden die Bilder in einem Unterverzeichnis namens pics gespeichert, welches zuvor noch erzeugt werden muss - beispielsweise so (gleich hinter der Zeile Dim strFilename ...):

On Error Resume Next

MkDir CurrentProject.Path & "\pics\"

Mit On Error Resume Next verhindern Sie, dass ein eventuell vorhandenes Verzeichnis gleichen Namens einen Fehler auslöst.

Vom Anlage-Feld zum OLE-Feld

Wenn Sie die im Anlagefeld gespeicherten Bilder und weitere Dateien anderweitig von der nach Access 2002/2003 migrierten Anwendung aus nutzen möchten und diese in einem Feld einer Tabelle speichern wollen, müssen Sie diese in einem OLE-Feld unterbringen.

Da die Tabelle MSysResources bereits vorhanden ist, können Sie diese gleich weiterverwenden: Dazu müssen Sie der Tabelle lediglich ein neues OLE-Feld etwa namens FileOLE hinzufügen und die Daten für jeden Datensatz aus dem Anlagefeld Data.Filedata in das OLE-Feld übertragen.

Das ist manuell gar nicht zu erledigen, sodass wir hier auf jeden Fall eine entsprechende VBA-Routine benötigen. Diese sieht wie in Listing 2 aus.

Listing 2: Inhalt vom Anlagefeld in ein OLE-Feld übertragen

Public Function Anlage2OLE()

    Dim db As DAO.Database

    Dim tdf As DAO.TableDef

    Dim fld As DAO.Field

    Dim rst As DAO.Recordset

    Dim bintmp() As Byte, bintmp2() As Byte

    Dim lOffset As Long

    Dim buffer() As Byte

    Set db = CurrentDb

    Set tdf = db.TableDefs("MSysResources")

    On Error Resume Next

    Set fld = tdf.Fields("FileOLE")

    If fld Is Nothing Then

        Set fld = tdf.CreateField("FileOLE", dbLongBinary)

        tdf.Fields.Append fld

    End If

    On Error GoTo 0

    Set rst = db.OpenRecordset("SELECT Data.Filedata, FileOle FROM MSysResources", dbOpenDynaset)

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.