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/2005.

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

Dateien in Tabellen speichern

André Minhorst, Duisburg

"Dateien in einer Datenbank speichern - wer macht den so was? Schon mit ein paar kleinen Bildchen bläht man sich doch die Datenbank schon maßlos auf!" - so ähnlich ist die Meinung der meisten Access-Anwender zum Thema dieses Beitrags. Dass es auch ohne Aufblähen geht und dass auch das Speichern anderer Dateien als Bilddateien in der Datenbank sinnvoll sein kann, erfahren Sie nachfolgend - und natürlich lernen Sie auch Funktionen kennen, die Ihnen dabei eine Menge Arbeit abnehmen.

Warum Dateien in Tabellen speichern?

Wenn man nicht gerade zu den Leuten gehört, die gerade einen aktuellen Anwendungsfall zum Speichern von Dateien in einer Access-Datenbank haben, fragen Sie sich vielleicht, welche Gründe es überhaupt für das Speichern von Dateien in einer Tabelle gibt.

Dafür gibt es genügend Anwendungsbeispiele; die bekanntesten davon beschäftigen sich vermutlich mit der Verwaltung von Bildern. In den gängigen Foren fragen Besucher ständig nach Möglichkeiten, um Bilder in Access zu speichern - und das möglichst ohne dass die Datenbank schneller als gewünscht eine Größe von zwei Gigabyte erreicht.

Aber es gibt noch andere gute Gründe für das Speichern von Dateien in einer Datenbank. Wenn Sie beispielsweise eine Datenbank weitergeben, ohne direkt eine aufwändige Installationsroutine mitzuliefern, können Sie eventuell zusätzlich benötigte Anwendungen beim Start der Datenbankanwendung ins Datenbankverzeichnis kopieren und dort verwenden.

Und wenn der Autor hier einmal aus dem Nähkästchen plaudern darf: Er verwendet die weiter unten vorstellten Funktionen, um alle im Online-Archiv enthaltenen .pdf- und Beispieldateien in einer Datenbank zu verwalten und diese bei Bedarf inklusive entsprechender Verzeichnisstrukturen (Jahrgang/Ausgabe/Beitrag ...) auf der Festplatte zu speichern und entsprechend weiterzubearbeiten.

Ebenso leicht ist etwa die Verwendung eines kommandozeilengesteuerten Zip-Tools, um beliebige Dateien ins Filesystem zu kopieren, zu komprimieren und die Originaldateien anschließend wieder zu löschen.

Vorbereitungen

Um die Vorgehensweise in den folgenden Kapiteln nachvollziehen zu können, benötigen Sie eine Access-Datenbank mit einer Tabelle zum Speichern von Daten. Den Entwurf dieser Tabelle können Sie Abb. 1 entnehmen.

Abb. 1: Entwurf der Tabelle zum Speichern von Dateien

Public Function DateiInOLEFeld(strTabelle As String, strPrimaerschluessel As String, _
    strZielfeld As String, lngID As Long, Optional strFeldSpeicherort As String, _
    Optional strSpeicherort As String, Optional bolImDatenbankpfad As Boolean) As Long

    Dim cnn As ADODB.Connection

    Dim rst As New ADODB.Recordset

    Dim strSpeicherortTemp As String, strSpeicherortName As String

    Dim lngExportdateiID As Long

    Dim Buffer() As Byte

    Dim lngDateigroesse As Long

    On Error GoTo DateiInOLEFeld_Err

    Set cnn = CurrentProject.Connection

    If Not strFeldSpeicherort = "" Then

        strSpeicherortTemp = ", " & strFeldSpeicherort

    Else

        strSpeicherortTemp = ""

    End If

    rst.Open "SELECT " & strZielfeld & strSpeicherortTemp & " FROM " & strTabelle _
        & " WHERE " & strPrimaerschluessel & " = " & lngID, cnn, adOpenDynamic, _
        adLockOptimistic

    lngExportdateiID = FreeFile

    If Not strFeldSpeicherort = "" Then

        strSpeicherortName = rst(strFeldSpeicherort)

    Else

        strSpeicherortName = strSpeicherort

    End If

    If bolImDatenbankpfad = True Then

        strSpeicherortName = Datenbankpfad & strSpeicherortName

    End If

    If Dir(strSpeicherortName) = "" Then

        MsgBox "Die Datei '" & strSpeicherortName & "' existiert nicht."

        Exit Function

    End If

    Open strSpeicherortName For Binary Access Read Lock Read Write As lngExportdateiID

    lngDateigroesse = FileLen(strSpeicherortName)

    ReDim Buffer(lngDateigroesse)

    rst(strZielfeld) = Null

    Get lngExportdateiID, , Buffer

    rst(strZielfeld).AppendChunk Buffer

    rst.Update

    Close lngExportdateiID

    DateiInOLEFeld = True

DateiInOLEFeld_Exit:

    rst.Close : Set rst = Nothing : Set cnn = Nothing

    Exit Function

DateiInOLEFeld_Err:

    DateiInOLEFeld = Err.Number

    Resume DateiInOLEFeld_Exit

End Function

Quellcode 1

Dateien in einer Tabelle
speichern

Die Prozedur zum Speichern einer Datei in einem Feld einer Tabelle finden Sie in Quellcode 1. Der Code sieht relativ umfangreich aus, aber die Prozedur gleicht dies durch hohe Flexibilität aus.

Eingabeparameter der Prozedur

Schauen Sie sich zunächst die Eingabeparameter an:

  • strTabelle: Tabelle, in der die Datei gespeichert werden soll
  • strPrimaerschluessel: Name des Primärschlüsselfeldes in der Zieltabelle
  • strZielfeld: OLE-Feld, in dem die Datei gespeichert werden soll
  • lngID: ID des Datensatzes, dem die Datei hinzugefügt werden soll
  • strFeldSpeicherort: Optional für die Angabe des Namens eines Feldes mit dem Speicherort der zu importierenden Datei
  • strSpeicherort: Optional für die Angabe des Speicherorts der zu importierenden Datei
  • bolImDatenbankpfad: Gibt an, ob dem Speicherort das Verzeichnis, in dem sich die Datenbank befindet, vorangestellt werden soll
  • Beispielaufrufe der Prozedur

    Um nun beispielsweise eine Datei namens c:\test.pdf im Feld Datei der Beispieltabelle zu speichern, legen Sie zunächst einen neuen Datensatz in dieser Tabelle an (s. Abb. 2). Das Vorhandensein eines Datensatzes mit einem OLE-Feld ist Voraussetzung für den Einsatz dieser Prozedur.

    Rufen Sie die Funktion im Testfenster nun folgendermaßen auf:

    Abb. 2: Ein Datensatz vor dem Import einer Datei

    DateiInOLEFeld "tblDateien", "DateiID", "Datei", 1, ,"c:\test.pdf",False

    Dieser Aufruf speichert die Datei c:\test.pdf in der Tabelle tblDatei im Feld Datei des Datensatzes mit dem Wert 1 im Primärschlüsselfeld DateiID.

    Nun können Sie mit dem .pdf-Dokument im OLE-Feld nicht allzu viel anfangen. Dass es aber dort angekommen ist, zeigt das erneute Öffnen der Tabelle (s. Abb. 3).

    Abb. 3: Das OLE-Feld ist nicht mehr leer.

    Eine zweite Variante für den Aufruf verwendet den Inhalt des Feldes Dateiname als Pfad für die zu importierende Datei:

    DateiInOLEFeld "tblDateien", "DateiID", "Datei", 1, "Speicherort", , False

    Durch die Angabe des Wertes "Speicherort" für den Parameter strFeldSpeicherort importiert die Funktion die in diesem Feld angegebene Datei - falls Sie die Datei aus dem vorherigen Beispiel nicht gelöscht haben, wird diese einfach überschrieben.

    Diese beiden Varianten können beide mit der Möglichkeit, den aktuellen Datenbankpfad einzubauen, kombiniert werden.

    Wenn Sie den Dateinamen im Funktionsaufruf übergeben möchten, verwenden Sie den reinen Dateinamen ohne Pfadangabe und übergeben für den Parameter bolImDatenbankpfad den Wert True. Das Gleiche gilt, wenn Sie den in der Tabelle gespeicherten Dateinamen verwenden möchten - geben Sie einfach den puren Dateinamen an und verwenden Sie die obige Option.

    Aufbau der Prozedur

    Die Prozedur besteht zu einem Großteil aus If Then-Bedingungen, die einen den Parametern entsprechenden Dateinamen ermitteln. Außerdem wird im ersten Teil der Prozedur ein Recordset mit dem angegebenen Datensatz der Zieltabelle geöffnet. Erst mit der Open-Anweisung wird die Prozedur richtig interessant und führt folgende Aktionen durch:

  • Öffnen der einzulesenden Datei
  • Ermitteln der Dateigröße
  • Anpassen der Größe der Byte-Variablen Buffer
  • Schreiben der Datei als Binärdaten in die Variable Buffer
  • Einfügen des Inhalts dieser Variablen in das Feld Datei des Ziel-Recordsets
  • Aktualisieren und damit Speichern des bearbeiteten Datensatzes
  • Dateien aus einer Tabelle ins Filesystem exportieren

    Erst mit der Möglichkeit, die Dateien wieder ins Filesystem zu speichern, wird die im vorherigen Kapitel vorgestellte Prozedur interessant.

    Die entsprechende Funktion heißt OLEFeldInDatei und ist in Quellcode 2 zu finden. Die Eingabeparameter stimmen weitgehend mit denen der Funktion DateiInOLEFeld überein, wenn auch für die umgekehrte Richtung.

    Voraussetzung für den Export des Inhalts eines OLE-Feldes in eine Datei ist eine Tabelle mit einem OLE-Feld, das mindestens einen Datensatz mit einem gefüllten OLE-Feld enthält.

    Die folgenden Beispiele verdeutlichen die Anwendung dieser Funktion. Mit dem ersten Aufruf speichern Sie die soeben importierte Datei im gleichen Verzeichnis, aber unter einem anderen Dateinamen:

    OLEFeldInDAtei "tblDateien", "DateiID", "Datei", 1, ,"c:\ExportTest.pdf"

    Nun stellen Sie die Funktion beider Prozeduren gleichzeitig auf die Probe: Wenn sich das .pdf-Dokument öffnen lässt und mit dem ursprünglichen Dokument übereinstimmt, sind die Funktionen einsatzbereit. Und da der Autor mit diesen beiden Funktionen schon einige Dateien in einer Datenbank gespeichert und auch wieder dort hervorgeholt hat, sollte das nun auch bei Ihnen funktionieren.

    Im zweiten Beispiel soll die .pdf-Datei unter dem Namen ExportTest.pdf im aktuellen Datenbankverzeichnis gespeichert werden:

    OLEFeldInDAtei "tblDateien", "DateiID", "Datei", 1, ,"c:\ExportTest.pdf",True

    Auch dieser Aufruf tut seinen Dienst einwandfrei. Werfen Sie nun einen Blick auf den Quellcode: Wie bei der vorherigen Funktion ermittelt auch hier der erste Teil der Prozedur den zu verwendenden Dateinamen aus den übergebenen Parametern und öffnet den Datensatz, in dem die zu exportierende Datei enthalten ist.

    Der Rest ist eine genaue Umkehrung der Funktion DateiInOLEFeld: Die Prozedur ermittelt die Dateigröße, schreibt den Inhalt des Feldes in die entsprechend dimensionierte Buffer-Variable und bugsiert deren Inhalt in eine zuvor angelegte Datei.

    Beispielanwendung: Bilder

    Die erste Beispielanwendung für diese beiden Funktionen ist die Verwaltung von Bildern, ohne die Datenbank aufzublähen. Das passiert nämlich, wenn Bilder mit Access-Hausmitteln in ein OLE-Feld importiert werden. Access speichert die Bilder dann im Windows-eigenen Format, was entsprechend mehr Speicher frisst.

    Public Function OLEFeldInDatei(strTabelle As String, strPrimaerschluessel As String, _
        strQuellfeld As String, lngID As Long, Optional strFeldSpeicherort As String, _
        Optional strSpeicherort As String, Optional bolImDatenbankpfad As Boolean) As Long

        Dim cnn As ADODB.Connection

        Dim rst As New ADODB.Recordset

        Dim strSpeicherortTemp As String

        Dim strSpeicherortName As String

        On Error GoTo OLEFeldInDatei_Err

        Set cnn = CurrentProject.Connection

        If Not strFeldSpeicherort = "" Then

            strSpeicherortTemp = ", " & strFeldSpeicherort

        Else

            strSpeicherortTemp = ""

        End If

        rst.Open "SELECT " & strQuellfeld & strSpeicherortTemp & " FROM " & strTabelle _
            & " WHERE " & strPrimaerschluessel & " = " & lngID, cnn, adOpenDynamic, _
            adLockOptimistic

        Dim lngExportdateiID As Long

        Dim Buffer() As Byte

        Dim lngDateigroesse As Long

        lngExportdateiID = FreeFile

        If Not strFeldSpeicherort = "" Then

            strSpeicherortName = rst(strFeldSpeicherort)

        Else

            strSpeicherortName = strSpeicherort

        End If

        If bolImDatenbankpfad = True Then

            strSpeicherortName = Datenbankpfad & strSpeicherortName

        End If

        lngDateigroesse = Nz(LenB(rst(strQuellfeld)), 0)

        If lngDateigroesse > 0 Then

            ReDim Buffer(lngDateigroesse)

            Open strSpeicherortName For Binary Access Write As lngExportdateiID

            Buffer = rst(strQuellfeld).GetChunk(lngDateigroesse)

            Put lngExportdateiID, , Buffer

            Close lngExportdateiID

        End If

        OLEFeldInDatei = True

    OLEFeldInDatei_Exit:

        rst.Close

        Set rst = Nothing

        Set cnn = Nothing

        Exit Function

    OLEFeldInDatei_Err:

        OLEFeldInDatei = Err.Number

        Resume OLEFeldInDatei_Exit

    End Function

    Quellcode 2

    Mit der hier vorgestellten Methode speichern Sie die Bilder in Originaldateigröße, können diese aber nicht direkt in einem OLE-Steuerelement anzeigen lassen.

    Private Sub Form_Current()

        Dim strDateiname As String

        Dim strDatenbankpfad As String

        If Not Me.NewRecord Then

            strDateiname = DLookup("Dateiname", "tblDateien", "DateiID = " & Me.DateiID)

            strDateiname = DateinameOhnePfad(strDateiname)

            strDatenbankpfad = Datenbankpfad

            OLEFeldInDatei "tblDateien", "DateiID", "Datei", Me.DateiID, , strDateiname, _
                True

            If Dir(strDatenbankpfad & strDateiname) = "" Then

                Me.objPicture.Picture = ""

            Else

                Me.objPicture.Picture = strDatenbankpfad & strDateiname

            End If

        Else

            Me.objPicture.Picture = ""

        End If

    End Sub

    Quellcode 3

    Dazu sind dann der vorherige Export und das Einstellen der Herkunftsdatei im OLE-Steuerelement erforderlich.

    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:

    Verwandte Beiträge:

    Zippen ohne Zusatzkomponente

    © 2003-2015 André Minhorst Alle Rechte vorbehalten.