Bilder mit OGL und GDI im Griff

Mit Access 2010 gibt es wieder mal neue Anforderungen, wenn es um den Zugriff auf Bilddokumente per VBA-Code geht. Der Anspruch der in diesem Beitrag vorgestellten Module zum Einlesen, Speichern und Anzeigen von Bilddateien in Access-Datenbanken ist es, unabhängig von der Windows- und Access-Version zuverlässig zu arbeiten (Ausnahme: Access 2010 64-bit).

Die Beispieldatenbank enthält einige Module mit Funktionen rund um Bilder.

Wenn Sie die nachfolgend beschriebenen Techniken in eigenen Datenbanken einsetzen wollen, importieren Sie dort die folgenden Module:

  • mdlOGL0710
  • mdlBLOBS0710
  • mdlOLE

Grundlagen

Bilder treten in den folgenden Beispielen in mehreren Formen auf:

  • als Datei,
  • als Picture-Objekt in einer Variablen oder
  • in einem OLE- oder Anlagefeld einer Tabelle.

Die Bilder werden beispielsweise an folgenden Stellen verwendet (einige Beispiele finden Sie am Ende des Beitrags):

  • in Symbolleisten und Kontextmenüs,
  • im ImageList-Steuerelement und somit in TreeView- und ListView-Steuerelementen,
  • im Bildsteuerelement,
  • als Icon im Ribbon (ab Access 2007) und
  • als Icon von Schaltflächen (ab Access 2007).

Normalerweise beginnt der Lebenslauf eines Bildes in Zusammenhang mit einer Access-Anwendung in Form einer Datei auf der Festplatte – etwa im Format .png, .gif, .bmp, .tif oder auch .ico. Die erste Aufgabe lautet daher, auf die gewünschte Bilddatei zuzugreifen und diese in der Datenbank verfügbar zu machen – am besten in Form einer Variablen des Typs StdPicture.

Die folgenden Beispiele führen wir anhand von Dateien im .png-Format durch. Dieses Format unterstützt Transparenz und kann überall problemlos eingesetzt werden.

Einmal Dateisystem und zurück

Das erste Beispiel zeigt, wie Sie eine Bilddatei in eine Variable laden. Dass das funktioniert, lässt sich am einfachsten nachweisen, indem wir das Bild in der gleichen Prozedur wieder im Dateisystem speichern. Die Bilddatei wird mit der Prozedur LoadPictureGDIP in einer Variable des Typs StdPicture gespeichert. LoadPictureGDIP erwartet mindestens den Dateinamen als Parameter. Gegebenenfalls können Sie noch einen Wert für FlattenColor angeben. Diesen Parameter lernen Sie später kennen.

Das Speichern des Bildes erledigt die Methode SavePicGDIPlus. Diese erwartet die Objektvariable, den Dateinamen und den Bildtyp als Parameter:

Public Sub BilddateiLadenUndSpeichern()
    Dim objPicture As StdPicture
    Dim strPfadQuelle As String
    Dim strPfadZiel As String
    strPfadQuelle = CurrentProject.Path & "\Screenshot.png"
    strPfadZiel = CurrentProject.Path & "\Screenshot_Kopie.png"
    Set objPicture = LoadPictureGDIP(strPfadQuelle)
    SavePicGDIPlus objPicture, strPfadZiel, pictypePNG
End Sub

Bilder in der Datenbank speichern

Wenn Sie kleinere Bilder in einer Anwendung verwenden möchten, um diese etwa im Ribbon, in Kontextmenüs, auf Schaltflächen oder im TreeView als Icon anzuzeigen, sollten Sie diese innerhalb der Datenbank speichern. Dazu gibt es zum Beispiel die folgenden beiden Varianten:

  • im OLE-Feld einer Tabelle
  • im Anlage-Feld einer Tabelle (ab Access 2007)

Die folgenden beiden Abschnitte zeigen beide Vorgehensweisen.

Bild aus Datei in OLE-Feld speichern

Bilder speichern Sie mit der Funktion SaveFileToOLEField im OLE-Feld einer Tabelle. Die Funktion erwartet die folgenden Parameter:

  • strFilename: Name der Quelldatei
  • strTable: Zieltabelle
  • strOLEField: OLE-Feld der Tabelle
  • boolEdit (optional): Soll das Bild in einem bestehenden Datensatz gespeichert werden
  • strIDField (optional): Primärschlüsselfeld der Tabelle
  • varID (optional): Wenn boolEdit den Wert True erhält, geben Sie hier die ID des Zieldatensatzes an, sonst können Sie hierüber die ID des neuen Datensatzes entnehmen.

Die Prozedur aus Listing 1 etwa speichert ein Bild in einem neuen Datensatz der Tabelle tblBilder und trägt nachträglich den Namen der Bilddatei ein.

Listing 1: Bild aus Datei in OLE-Feld speichern

Public Sub BilddateiInOLEFeld()
    Dim strPfadQuelle As String
    Dim lngID As Long
    Dim db As DAO.Database
    Set db = CurrentDb
    strPfadQuelle = CurrentProject.Path & "\Screenshot.png"
    If mdlOLE.SaveFileToOLEField(strPfadQuelle, "tblBilder", "Bild", False, "ID", lngID) Then
         db.Execute "UPDATE tblBilder SET Bildname = ''" & strPfadQuelle & "'' WHERE ID = " & lngID, dbFailOnError
    End If
End Sub

Diese Prozedur verwendet den Parameter lngID, um die ID des neuen Datensatzes zu speichern. Damit kann sie dann direkt danach auf diesen Datensatz zugreifen und weitere Felder füllen – wie hier etwa das mit dem Dateinamen des Bildes.

Wenn Sie eine Bilddatei in einen bestehenden Datensatz einfügen möchten, verwenden Sie einen Aufruf wie den aus der Prozedur in Listing 2.

Listing 2: Bild aus Datei in OLE-Feld speichern, diesmal in einem bestehenden Datensatz

Public Sub BilddateiInOLEFeld_BestehenderDatensatz()
    Dim strPfadQuelle As String
    Dim lngID As Long
    Dim lngResultat As Variant
    lngID = 25
    strPfadQuelle = CurrentProject.Path & "\Screenshot.png"
    lngResultat = SaveFileToOLEField(strPfadQuelle, "tblBilder", "Bild", True, "ID", lngID)
    If lngResultat = True Then
         Debug.Print "Erfolgreich gespeichert!"
    Else
         Debug.Print "Es ist ein Fehler aufgetreten: " & lngResultat & " " & AccessError(lngResultat)
    End If
End Sub

Die Prozedur legt fest, dass das angegebene Bild im Feld Bild der Tabelle tblBilder gespeichert werden soll, deren Feld ID den Wert 25 besitzt. Das Ergebnis sieht in beiden Fällen wie in Bild 1 aus.

pic001.png

Bild 1: Ein in einem OLE-Feld gespeichertes Bild

Bild aus OLE-Feld in Datei speichern

Andersherum funktioniert es natürlich auch. Vielleicht haben Sie ja eine Datenbank mit einer großen Menge Icons im OLE-Feld einer Tabelle und möchten diese mal schnell auf die Festplatte kopieren. Dann verwenden Sie die Prozedur SaveOLEFieldToFile des Moduls mdlOLE wie in Listing 3. Diese Prozedur erwartet die folgenden Parameter:

Listing 3: Bild aus einem OLE-Feld in eine Datei speichern

Public Sub OLEFEldInBilddatei()
    Dim strPfadZiel As String
    Dim lngID As Long
    strPfadZiel = CurrentProject.Path & "\BildAusOLEFeld.png"
    lngID = 25
    SaveOLEFieldToFile "tblBilder", "ID", lngID, "Bild", strPfadZiel
End Sub
  • strTable: Quelltabelle
  • strIDField: Primärschlüsselfeld
  • lngID: Wert des Primärschlüssels für den Datensatz, aus dem das Bild gespeichert werden soll
  • strOLEField: Name des OLE-Feldes
  • strFilename: Name der Zieldatei

Bild aus Datei in Anlagefeld speichern

Seit Access 2007 gibt es das Anlagefeld, in dem sich Bilder sogar ganz leicht über die Benutzeroberfläche speichern lassen. Natürlich wollen Sie dies auch automatisiert per VBA erledigen. Die dazu notwendigen Prozeduren finden Sie im Modul mdlBLOB0710.

Zum Anlagefeld ist zu sagen, dass es nicht wie ein OLE-Feld direkt in der Tabelle steckt, sondern dass es sich dabei prinzipiell um eine versteckte, per 1:n-Beziehung verknüpfte Tabelle handelt. Nach außen hin bedeutet dies, dass Sie mehrere Bilder in einem einzigen Datensatz speichern können.

Daher haben die Methoden zum Speichern und Auslesen von Bildern in Anlagefeldern einen Parameter mehr als die für den Zugriff auf OLE-Felder. Damit geben Sie noch den Namen der jeweiligen Datei an.

Die Methode StoreBLOB0710 speichert eine Datei in einem Anlagefeld und erwartet die folgenden Parameter:

  • strFilename: Name der Bilddatei
  • strTable: Zieltabelle
  • strFieldAttach: Name des Anlagefelds
  • boolEdit (optional): Soll die Datei in einen neuen oder vorhandenen Datensatz geschrieben werden
  • strIDField (optional): Name des Primärschlüsselfeldes
  • varID (optional): Wert des Primärschlüsselfeldes, wenn das Bild in einem bestehenden Datensatz gespeichert werden soll
  • strAttachment (optional): Name der Anlage, da mehrere Bilder pro Anlagefeld gespeichert werden können. Muss dem Dateinamen ohne Pfadangabe entsprechen!

Wir zeigen nachfolgend drei Varianten zum Speichern einer Bilddatei in einem Anlagefeld:

  • Speichern in einem neuen Datensatz
  • Speichern in einem bestehenden Datensatz über eine bestehende Anlage
  • Speichern in einem bestehenden Datensatz als neue Anlage

Die Prozedur aus Listing 4 verwendet StoreBLOB0710, um eine Datei in einem Anlagefeld zu speichern und gleich im Anschluss den soeben erstellten Datensatz um den Dateinamen der Bilddatei zu erweitern.

Listing 4: Bild aus einer Datei in ein Anlagefeld speichern

Public Sub BilddateiInAnlage_NeuerDatensatz()
    Dim strPfadQuelle As String
    Dim lngID As Long
    Dim db As DAO.Database
    Set db = CurrentDb
    strPfadQuelle = CurrentProject.Path & "\Screenshot.png"
    If StoreBLOB0710(strPfadQuelle, "tblAnlagen", "Anlage", False, "ID", lngID, "Beispielbild") Then
         db.Execute "UPDATE tblAnlagen SET Anlagename = ''" & strPfadQuelle & "'' WHERE ID = " & lngID, dbFailOnError
    End If
End Sub

Den so gespeicherten Anlage-Datensatz nimmt die Prozedur aus Listing 5 auf. Sie verwendet für den Parameter boolEdit den Wert True, weil ein bestehender Datensatz bearbeitet werden soll. Sie übergibt einen vorgegebenen Wert für varID und gibt außerdem für strAttachment den Namen der im vorherigen Beispiel gespeicherten Bilddatei an. Dadurch wird die Bilddatei erstens im gleichen Datensatz gespeichert und zweitens auch noch über die bestehende Datei mit dem gleichen Namen geschrieben. Die dritte Variante sieht ähnlich aus, allerdings soll hier eine weitere Datei als zweites Element des Anlagefeldes gespeichert werden.

Listing 5: Bestehendes Bild in einem Anlagefeld überschreiben

Public Sub BilddateiInAnlage_BestehenderDatensatz_BestehendeAnlage()
    Dim strPfadQuelle As String
    Dim lngID As Long
    Dim db As DAO.Database
    Set db = CurrentDb
    lngID = 13
    strPfadQuelle = CurrentProject.Path & "\Screenshot.png"
    StoreBLOB0710 strPfadQuelle, "tblAnlagen", "Anlage", True, "ID", lngID, "Screenshot.png"
End Sub

Dazu geben wir einen alternativen Quellpfad an, übergeben aber auch mit dem letzten Parameter strAttachment den im Quellpfad enthaltenen Dateinamen (s. Bild 2 aus.

Listing 6: Bild zu einem bestehenden Bild im Anlagefeld hinzufügen

Public Sub BilddateiInAnlage_BestehenderDatensatz_WeitereAnlage()
    Dim strPfadQuelle As String
    Dim lngID As Long
    Dim db As DAO.Database
    Set db = CurrentDb
    lngID = 13
    strPfadQuelle = CurrentProject.Path & "\pic001.png"
    StoreBLOB0710 strPfadQuelle, "tblAnlagen", "Anlage", True, "ID", lngID, "pic001.png"
End Sub

pic002.png

Bild 2: Ein Anlagefeld mit zwei verschiedenen Bilddateien

Bild aus Anlagefeld in Datei speichern

Natürlich können Sie die in einem Anlagefeld gespeicherten Bilddateien auch wieder ins Dateisystem schreiben. Dazu verwenden Sie die Prozedur RestoreBLOB0710, die folgende Parameter erwartet:

  • strTable: Tabelle, in der sich das Anlagefeld befindet
  • strFieldAttach: Name des Anlagefeldes
  • strIDField: Name des Primärschlüsselfeldes der Quelltabelle
  • varID: Wert des Primärschlüsselfeldes
  • strFilename: Gewünschter Name der zu speichernden Datei
  • strAttachment (optional): Dateiname im Anlagefeld, falls dieses mehr als eine Anlage enthält

Die Prozedur aus Listing 7 zeigt einen Beispielaufruf der Methode RestoreBLOB0710. In diesem Fall soll die erste Datei im Anlagefeld Anlage im Datensatz mit dem Wert 13 für das Feld ID der Tabelle tblAnlagen gespeichert werden.

Listing 7: Anlage auf der Festplatte speichern

Public Sub BilddateiAusAnlagefeldSpeichern()
    Dim strPfadZiel As String
    Dim lngID As Long
    Dim db As DAO.Database
    Set db = CurrentDb
    lngID = 13
    strPfadZiel = CurrentProject.Path & "\Screenshot1.png"
    RestoreBLOB0710 "tblAnlagen", "Anlage", "ID", lngID, strPfadZiel
End Sub

Sollte dieses Anlagefeld mehr als eine Anlage enthalten, können Sie mit dem letzten Parameter den Dateinamen der zu exportierenden Datei angeben.

Bild aus OLE-Feld lesen

Wenn Sie ein in einem OLE-Feld gespeichertes Bild irgendwo innerhalb der Access-Anwendung anzeigen möchten, müssen Sie dieses zunächst auslesen und in einer StdPicture-Variablen speichern.

Dies erledigen Sie mit der Methode PicFromField des Moduls mdlOGL0710. Dieser Methode müssen Sie als Parameter ein Field-Objekt übergeben, das dem OLE-Feld entspricht, in dem sich das Bild befindet. Wie dies funktioniert, zeigt die Prozedur aus Listing 8. Um zu beweisen, dass die Variable objPicture auch tatsächlich ein Bild enthält, wird es in der folgenden Anweisung noch auf der Festplatte gespeichert.

Listing 8: Bild aus OLE-Feld in einem StdPicture-Objekt speichern

Public Sub OLEInStdPictureSpeichern()
    Dim db As DAO.Database
    Dim objPicture As StdPicture
    Dim rst As DAO.Recordset
    Dim fld As DAO.Field
    Dim lngID As Long
    lngID = 25
    Set db = CurrentDb
    Set rst = db.OpenRecordset("SELECT Bild FROM tblBilder WHERE ID = " & lngID)
    Set fld = rst.Fields(0)
    Set objPicture = PicFromField(fld)
    mdlOGL0710.SavePicGDIPlus objPicture, CurrentProject.Path & "\test.gif", pictypeGIF
End Sub

Bild aus Anlagefeld lesen

Auch bei Verwendung eines Anlagefeldes zum Speichern der Bilddateien für eine Anwendung müssen Sie den Inhalt zunächst in ein StdPicture-Element übermitteln.

Dies erledigt die Prozedur AttachmentToPicture. Sie erwartet die folgenden Parameter:

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

Schreibe einen Kommentar