Bilder in Formularen

By , 23. August 2008

Viele Anwendungen erfordern es, oder machen es zumindest sinnvoll zu einem Datensatz – z.B. ein Artikel – ein oder mehrere Bilder einzufügen und anzuzeigen. Dabei sollte man den Fokus auf nachfolgende Punkte richten. Wie füge ich ein Bild ein, wo soll es gespeichert sein, wie kann ich es anzeigen, wie kann ich es vergrößert anzeigen? Und dabei noch die Performance der Anwendung im Auge behalten. Nachfolgend wird eine Lösung für diese Punkte aufgezeigt, die aber nur eine von vielen ist, sich mir aber als Vorteilhaft erwießen hat.

A: Bilder speichern
Wenn Sie Bilder in einer Tabelle speichern und dabei den Datentyp OLE-Objekt wählen, werden die Bilder direkt in der Access-Datei codiert gespeichert. Wenn Sie Bilder einfügen werden Sie bald feststellen, dass die Dateigröße der Access-Datei riesig anwächst. Daher ist es vorteilhafter, die Bilder in einem bekannten Verzeichnis abzulegen und nur den Dateipfad und -name als Text zu speichern. Dann aber können Sie von den Möglichkeiten, die ein OLE-Feld mit sich bringt, nicht profitieren. Z.B. ein Bild per Doppelklick bearbeiten. Oder eine Zoomansicht eines Dokumentes zu erhalten etc. Wie das gelöst wird lesen Sie später.

B: Bilder einfügen
Um ein oder mehrere Bilder im Formular einzufügen benötigen Sie für jedes Bild ein sog. Bildfeld das Sie in der Toolbar finden. Nach dem Einfügen werden Sie aufgefordert eine Grafik auszuwahlen. Daher ist es sinnvoll wenn Sie z.B. mit MS Paint ein Bild erstellen mit 1×1 Pixel Größe. Ich verwende dazu eine Grafig im Gif-Format das transparent ist. Der Namen ist egal, könnte z.B. leer.gif oder blank.gif etc heißen. Wählen Sie also ihr leer.gif als Bild aus. Später können Sie das Bild unter den Eigenschaften wieder löschen, es ist nur für das Erstellen des Bildfeldes wichtig. Geben Sie die Anweisung weiter, wird Access den Pfad des Bildes nicht mehr finden, dann müssen sie zwingend entfernt werden. Wichtig! stellen Sie Eigenschaft Bildtyp auf „Verknüpft“ und Größenanpassung auf Zoomen. Geben Sie dem Bildfeld noch einen Namen, z.B. Bild1.
Erstelle unterhalb des Bildfeldes einen Button für das Einfügen. Beim Klicken dann folgender Code einfügen:

    Dim fd As New FileDialog
    Dim Dateiname As String, Bildpfad1 As String, SourcePath As String
    Dim db As DAO.Database, rs As DAO.Recordset
    Bildpfad1 = "c:DatenbankBilder"
    If Dir(Bildpfad1, vbDirectory) = "" Then
        MsgBox "Bitte legen Sie zuerst den Pfad für die Artikelbilder an!"
        Exit Sub
    End If
    Set db = CurrentDb
    Set rs = db.OpenRecordset("Select Bild1 From Tabelle_Artikel Where Artikelnummer = " & Me!Artikelnummer, dbOpenDynaset)
    If Not rs.EOF Then
        If Not IsNull(rs!Bild1) And Len(rs!Bild1) > 0 Then
            If MsgBox("Soll das vorhandene Bild überschrieben werden?", vbQuestion + vbYesNo) = vbYes Then
                Dateiname = fd.ShowOpen
                If Dateiname = "" Then Exit sub
                SourcePath = Bildpfad1 & "" & SplitFilename(Dateiname)
                FileCopy Dateiname, SourcePath
                rs.Edit
                rs!Bild1 = SourcePath
                rs.Update
            End If
        Else
            Dateiname = fd.ShowOpen
            If Dateiname = "" Then Exit sub
            SourcePath = Bildpfad1 & "" & SplitFilename(Dateiname)
            FileCopy Dateiname, SourcePath
            rs.Edit
            rs!Bild1 = SourcePath
            rs.Update
        End If
    Else
        MsgBox "Sie müssen den Artikel zuerst speichern!"
        Exit sub
    End If
    Call Bilderladen

Es wird zuerst geprüft ob das Verzeichnis existiert wo die Bilder hinkopiert werden sollen. Dann wird geprüft ob bereits ein Bild vorhanden ist und gefragt ob es überschrieben werden soll. Mittels Filedialog wird ein Dateidialog geöffnet, wo das Bild ausgewählt wird. Mit Filecopy wird es in das Verzeichnis kopiert.

Leider hatte ich bislang versäumt die Funktion SplitFileName zu posten. Diese sieht folgendermaßen aus:

Private Function SplitFilename(ByVal strPath As String) As String
    Dim strTmp As String

    strTmp = strPath
    While InStr(strTmp, "\") > 0
        strTmp = Right(strTmp, Len(strTmp) - InStr(strTmp, "\"))
    Wend
    SplitFilename = strTmp
End Function

In einer Schleife wird der Pfad/Dateinamen solange durchlaufen bis letztlich der reine Dateinamen übrig bleibt.

Damit der Filedialog funktioniert, benötigen Sie ein spezielles Klassenmodul. Das Modul „Filedialog“ finden Sie in der Datenbank Knowhow 3.0, die bei www.freeaccess.de unter Downloads erhältlich ist. Laden Sie sich die Datenbank herunter und fügen das Modul über Datei/Externe Daten (Datei auswählen, Modulauswählen und OK klicken) in Ihre Datenbank ein.

C: Bilder anzeigen
Sie haben nun ein oder mehrere Bildfelder mit einem „Leer-Bild“. Sie wollen aber, wenn der Datensatz gewechselt wird, dass dann auch die jeweiligen Bilder angezeigt werden. Dazu verwenden Sie das Form-Ereignis „Beim Anzeigen“, und schreiben nur den Aufruf einer Prozedur hinein, die dann die Bilder lädt:

Private Sub Form_Current()
    Call Bilderladen
End Sub

Das Anzeigen eines Bildes in einem Bildfeld geschieht mir der Eigenschaft „Pcture“, also z.B. Me!Bild1.Picture = „c:meinbild.jpg“. Das Nichtanzeigen eines Bildes erfolgt dadurch, indem man eine leere Zeichenfolge als Bild zuweist. An den Pfad und Namen des Bildes kommt man über ein Recordset auf die entsprechende Tabelle. Als Kriterium muss zwingend eine Angabe auf den Primärschlüssel oder einen anderen ID gemacht werden, damit auch die richtigen Bilder geladen werden.
Nachfolgend die Prozedur Bilderladen wie ich sie einsetze:

Private Sub Bilderladen()
    Dim db As DAO.Database
    Dim rs As DAO.Recordset
    Set db = CurrentDb
    Set rs = db.OpenRecordset("Select Bild1 From Tabelle_Artikel Where Artikelnummer = " & Me!Artikelnummer, dbOpenDynaset)
    If Not rs.EOF Then
        Me!Bild1.Picture = ""
        If Not IsNull(rs!Bild1) And rs!Bild1 <> "" Then Me!Bild1.Picture = rs!Bild1
    End If
    rs.Close
    Set rs = Nothing
    Set db = Nothing
End Sub

D: Zoom-Ansicht anzeigen
Hat man mehrere Bilder in einem Formular, so müssen die Bildfelder relativ klein gehalten werden. Um eine Zoom-Ansicht zu realisieren erstellt man ein neues Formular mit Popup-Eigenschaft. Darauf plaziert man ein großel Bildfeld, z.B. 15×20 cm und nennt es z.b. Zoombild. Als Bildtyp wieder Verknüpft und Größenanpassung auf Zoomen stellen. Das Formular unter dem Namen frmBilderzoom speichern.
In dem Formular mit den kleineren Bildfeldern gibt man dann folgenden Code bei dem Ereignis „Beim Doppelklicken“ auf die Bildfelder ein:

DoCmd.OpenForm "frmBilderzoom", , , , , , Me!Bild1.Picture

Im Formular frmBilderzoom beim Ereignis „Beim Laden“ dann noch folgender Code um die Bilder anzuzeigen:

Private Sub Form_Load()
    If Not IsNull(Me.OpenArgs) Then
        Me.ZoomBild.Picture = Me.OpenArgs
        Me.Caption = Me.OpenArgs
    End If
End Sub

Zusätzlich noch ein Button um das Formular wieder schließen eingefügt und fertig.

Was jetzt noch fehlen würde ist eine Möglichkeit ein Bild zu entfernen. Dazu einfach ein Button unter dem Bildfeld einfügen und beim Klicken folgenden Code:

    Dim db As DAO.Database
    Set db = CurrentDb
    If MsgBox("Soll das Bild wirklich entfernt werden?", vbQuestion + vbYesNo) = vbYes Then
        db.Execute "Update Artikel Set Bild1 = '' Where Artikelnummer = " & Me!Artikelnummer
    End If
    Set db = Nothing
    Call Bilderladen

Das Bild bleibt aber phys. in dem Verzeichnis erhalten – ich empfehle dies auch so zu belassen, verklickt hat man sich schnell.

Um nun die Anwendung mit samt Bildern weiterzugeben, stößt man jetzt auf das Problem, dass im Zielrechner sicherlich eine andere Ordnerstruktur vorherscht als auf dem Entwicklungsrechner. Entweder wird die Anwendung ohne Bilder verschickt, oder man verwendet einen Standardordner, oder man speichert eben nur die Bildnamen ohne Pfad und verwendet dann z.B. ein Unterordner vom Ordner wo die Anwendung liegt. Dann muss man zum Anzeigen der Bilder den Pfad dynamisch zusammenbauen. Den Pfad der Access Anwendung bekommt man mit Currentproject.Path. Das ist dann noch ein wenig Fleissarbeit nötig, um den Code umzubauen. Das könnte dann z.B. so aussehen:

Bei Form_Load:
Bildpfad1 = CurrentProject.Path & „Bilder“

Bei Funktion Bilderladen:
If Not IsNull(rs!Bild1) And rs!Bild1 <> „“ Then Me!Bild1.Picture = Bildpfad1 & „“ & rs!Bild1

AV 2008

6 Responses to “Bilder in Formularen”

  1. Andreas Vogt sagt:

    Hallo,
    ja richtig, diese Lösung ist nicht für Endlosformulare gedacht. Aber eine Suche in Google wird dir weiterhelfen, z.B. hier

    Andreas

  2. Stefan N. sagt:

    Hi Andreas,

    Du hast meine Frage wohl nicht richtig gelesen!
    Ich hab es doch schon so gemacht wie in dem Artikel beschrieben, nur geht das nicht bei Endlosforms!

    Stefan.

  3. Stefan N. sagt:

    Hallo Andreas,

    Danke für Deine super Tips. Ich habe nun eine
    Datenbank dementsprechend umgestaltet (ein Anderer
    hatte deren Bilder alle per OLE eingebettet – DB war nun 1GB gross). Die Bilder liegen nun als Pfad+Dateiname in der Tabelle, was auch gut klappt. Bei Einzelformularen werden die Bilder auch schön im Bildelement angezeigt. Jedoch suche ich nun noch eine Möglichkeit, mehrere Bilder von Datensätzen auf einmal anzuzeigen. Access zeigt ja bei Endlosforms nur jeweils ein und dasselbe Bild des ersten Datensatzes wiederholt an. Weißt Du noch einen Trick wie
    man das umgehen kann oder mit Listviews oder ähnlich mehrere verschiedene Bilder auf einer Seite darstellen kann?

    Gruss,
    Stefan

  4. Andreas Vogt sagt:

    Hallo Klaus,
    eigentlich ganz einfach wenn man im Debugger mal die Methoden und Eigenschaften des Bildes sich anzeigen lässt.
    Die gesuchte Eigenschaft heißt PictureAlignment.
    Me!Bild1.PictureAlignment = 0 bis 4
    0 bis 4 in genau der Reihenfolge wie in den Eigenschaften. Also 0 = links oben, 2 = Mitte und 4 = rechts unten.

    Andreas

  5. Klaus Bünning sagt:

    Hallo Andreas,
    danke für deine schnelle Antwort, jedoch ist mein Problem ein anderes. Ich möchte ein Bild als Logo im Bericht anzeigen und je nach Einstellung dieses links, rechts, zoom usw. formatieren. In den Bildeigenschaften kann man dies ja einstellen, aber in VBA weiss ich nicht wie das geht. Vielleicht hast du eine Idee.
    mfg Klaus

  6. Klaus Bünning sagt:

    Diesen Vorschlag verwende ich schon länger, funktioniert auch prima. Leider kann ich das Bild nicht formatieren, d.h. rechts oben, zoom, dehnen usw. Hast du hier eine Idee ?
    mfg Klaus

    Moderation:
    Hallo Klaus,
    zum Zoomen hab ich ja ein Beispiel gemacht über das zusätzliche Popup-Formular. Aber wenn man eine komfortable Bilderanzeige realisieren möchte sollte man das über das Webbrowser-Control machen da man da sehr gut mit JavaScript arbeiten kann. D.h. freie Scripte aus dem Netz die mit HTML/JavaScript funktionieren kannst du so verwenden.

    Gruß Andreas

Leave a Reply

You must be logged in to post a comment.

OfficeFolders theme by Themocracy