Icons in der Datenbank verwalten

Mit den neueren Versionen von Access ab der Version 2010 kann man Icons, die an verschiedenen Stellen der Benutzeroberfläche wie in Bildsteuerelementen oder Schaltflächen angezeigt werden sollen, relativ einfach verwalten. Sie landen nach dem Einfügen in einer Systemtabelle namens MSysResources, die ein Anlagefeld zum Speichern der Bilddateien und weitere Felder für die Metadaten wie Bildname oder Dateiendung enthält. Allerdings ist die Verwaltung nicht perfekt gelöst. Daher stellen wir in diesem Beitrag ein Formular vor, mit dem sich die Bilder wesentlich besser hinzufügen lassen. Außerdem enthält das Formular eine Suchfunktion, mit der sich die Bilder nach dem Namen filtern lassen, sowie eine Übersicht der Bilder, mit der sich die jeweiligen Bilddateien anschauen lassen. Schließlich können wir auch noch den Bildnamen herausfinden, um das gewünschte Icon schnell einer Schaltfläche oder einem Bildsteuerelement zuweisen zu können.

Nachteile der eingebauten Verwaltung von Icons

Die eingebauten Funktionen zum Hinzufügen von Icons zu einer Access-Datenbank sind bereits recht hilfreich, wenn man dies mit früheren Versionen vergleicht, wo man Bilder bestenfalls im OLE-Format nutzen konnte.

Wenn wir ein Formular in der Entwurfsansicht geöffnet haben, können wir im Ribbon auf den Befehl Formularentwurf|Steuerelemente|Bild einfügen einen Dateidialog öffnen, mit dem wir das einzufügende Bild auswählen (siehe Bild 1).

Funktion zum Hinzufügen von Bilddateien

Bild 1: Funktion zum Hinzufügen von Bilddateien

Unabhängig davon, ob wir danach in das Formular klicken und ein Bildsteuerelement gefüllt mit diesem Bild anlegen, wird das Bild in der Tabelle MSysResources gespeichert und steht nachfolgend in Steuerelementen wie der Schaltfläche oder dem Bildsteuerelement zur Auswahl bereit (siehe Bild 2).

Das hinzugefügte Bild

Bild 2: Das hinzugefügte Bild

Anschließend können wir uns einen Überblick über die enthaltenen Bilder verschaffen, indem wir erneut auf Bild einfügen klicken (siehe Bild 3).

Auswahl der verfügbaren Bilder der Tabelle MSysResources

Bild 3: Auswahl der verfügbaren Bilder der Tabelle MSysResources

Was hier fehlt, sind folgende Funktionen:

  • Wir können immer nur ein Bild gleichzeitig zur Tabelle MSysResources hinzufügen.
  • Die Bildergalerie zeigt nur eine begrenzte Anzahl von Bildern an. Unsere Sammlung von ca. 1.700 Icons konnte nicht vollständig angezeigt werden.
  • Es fehlt eine Suchmöglichkeit nach dem Bildnamen.

All diese Funktionen rüsten wir mit unserem Formular nach, dass sich leicht in eigene Anwendungen einbauen lässt.

Formular zum Verwalten von Icons

Das Formular dieser Lösung heißt frmIconsVerwalten und sieht wie in Bild 4 aus.

Formular zum Verwalten von Icons

Bild 4: Formular zum Verwalten von Icons

Es enthält 45 Schaltflächen in drei Reihen, die zur Anzeige der ersten verfügbaren Bilder dienen.

Wenn sich mehr als 45 Bilder in der Tabelle MSysResources befinden, können wir mit den beiden Nach oben– und Nach unten-Schaltflächen reihenweise vor- und zurücknavigieren.

Oben sehen wir ein Textfeld namens Filter. Hier können wir einen Filterausdruck eingeben, mit dem wir die Bilder in der Tabelle MSysResources nach dem Namen filtern können. Die Anzeige wird nach der Eingabe eines jeden Zeichens aktualisiert und sucht stets an beliebiger Stelle im Dateinamen der Bilder nach dem Filterbegriff.

Rechts daneben befindet sich eine Schaltfläche, mit der wir das aktuell markierte Bild aus der Tabelle MSysResources löschen können.

Die Schaltfläche Hinzufügen öffnet einen Dateiauswahl-Dialog, mit dem wir weitere Bilder zur Tabelle MSysResources hinzufügen können.

Unter der Anzeige der Bilder sehen wir die Anzahl der noch nachfolgend vorhandenen Bilder. Diese Anzahl ändert sich, wenn wir mit der Nach unten-Schaltfläche zu weiteren Zeilen navigieren.

Schließlich können wir ein Bild anklicken und erhalten im Textfeld Gewähltes Bild den Namen des Bildes, das wir mit einem Klick auf die Schaltfläche rechts davon in die Zwischenablage kopieren und beispielsweise für die Eigenschaft Bild einer Schaltfläche einfügen können.

Entwurf des Formulars

Das Formular enthält im Wesentlichen herkömmliche Steuerelemente (siehe Bild 5). Die 45 Schaltflächen, die mit cmd001 bis cmd045 benannt sind, haben wir mit der Funktion aus dem Beitrag Schaltflächen-Matrix per VBA erzeugen (www.access-im-unternehmen.de/1562) erstellt.

Das Formular frmIconsVerwalten in der Entwurfsansicht

Bild 5: Das Formular frmIconsVerwalten in der Entwurfsansicht

Füllen der Schaltflächen mit den verfügbaren Bildern

Die Prozedur LoadImages lädt die Bilder aus der Tabelle MSysResources als Icons in die 45 Schaltflächen (erster Teil in Listing 1). Sie nimmt optional mit dem Parameter strFilter ein Filterkriterium entgegen und stellt einen zweiten Parameter namens bolMove zur Verfügung. Dieser gibt an, ob die angezeigten Bilder bereits nach unten gescrollt wurden. Die Variable strResourcetable speichert den Namen der Tabelle, aus der die Bilder eingelesen werden, in diesem Fall MSysResources.

Private Sub LoadImages(Optional strFilter As String, Optional bolMove As Boolean)
     Dim db As DAO.Database
     Dim rst As DAO.Recordset
     Dim cmd As Access.CommandButton
     Dim strSQL As String
     Dim lngIndex As Long
     Dim lngFirstID As Long
     Dim strFirstPicture As String
     Dim strResourcetable As String
     
     strResourcetable = "MSysResources"    
     Set db = CurrentDb    
     Me.Painting = False
     
     If Len(strFilter) = 0 Then
         strSQL = "SELECT * FROM " & strResourcetable & " WHERE Extension = ''png'' ORDER BY Name ASC"
     Else
         strSQL = "SELECT * FROM " & strResourcetable & " WHERE Extension = ''png'' AND Name LIKE ''*" _
             & strFilter & "*'' ORDER BY Name ASC"
     End If
     
     Set rst = db.OpenRecordset(strSQL, dbOpenDynaset)
     If rst.EOF Then
         Call SchaltflaechenLeeren
         Me.Painting = True
         Me.cmdBildLoeschen.Enabled = False
         Exit Sub
     End If
     strFirstPicture = Nz(rst!Name, "")
     ... 

Listing 1: Die Prozedur zum Laden von Bildern in die Schaltflächen (Teil 1)

Die Prozedur referenziert das aktuelle Database-Objekt mit der Variablen db und deaktiviert das Painting während des Vorgangs, damit das Formular nicht flackert, wenn die Bilder zugewiesen werden.

Die erste If…Then-Bedingung prüft, ob der Parameter strFilter einen Wert enthält. Ist das nicht der Fall, stellt sie eine SQL-Abfrage zusammen, die alle Datensätze der Tabelle MSysResources enthält, deren Feld Extension die Dateiendung png aufweist. Die Daten werden aufsteigend nach dem Inhalt des Feldes Name sortiert.

Ist strFilter gefüllt, wird im Else-Zweig eine zusätzliche Bedingung in strSQL eingebaut, der das Feld Name nach dem enthaltenen Wert filtert.

Dann erstellt die Prozedur ein Recordset auf Basis von strSQL und prüft, ob das Recordset leer ist.

In diesem Fall ruft sie die Prozedur SchaltflaechenLeeren auf, die in einer Schleife über die Werte von 1 bis 45 sowohl die Picture– als auch die ControlTipText-Eigenschaften der entsprechenden Schaltflächen leert:

Private Sub SchaltflaechenLeeren()
     Dim lngIndex As Long
     For lngIndex = 1 To 45
         With Me.Controls("cmd" & Format(lngIndex, "000"))
             .Picture = ""
             .ControlTipText = ""
         End With
     Next lngIndex
End Sub

Danach aktiviert die Prozedur das Painting wieder, deaktiviert die Schaltfläche cmdBildLoeschen, da nun kein zu löschendes Bild angezeigt wird, und beendet die Prozedur mit Exit Sub.

Wenn diese Bedingung jedoch erfüllt ist, trägt die Prozedur den Namen des ersten Bildes in das Textfeld in die Variable strFirstPicture ein.

Im nun folgenden Teil prüft eine verschachtelte If…Then-Bedingung, ob die Variable bolMove den Wert True enthält und die Variable strFilter nicht leer ist. In diesem Fall stellt sie die Variable lngStart auf den Wert 0 ein (siehe Listing 2). lngStart wird, damit wir auch beim nächsten Laden der Bilder auf ihren Wert zugreifen können, wie folgt ganz oben im Modul deklariert:

     ...    
     If Not bolMove Then
         If Not Len(strFilter) = 0 Then
             lngStart = 0
         End If
     End If
     If lngStart > 0 Then
         rst.AbsolutePosition = lngStart * 15 - 1
         strFirstPicture = rst!Name
         Debug.Print strFirstPicture
         If Len(strFilter) = 0 Then
             strSQL = "SELECT * FROM " & strResourcetable & " WHERE Extension = ''png'' AND Name > ''" _
                 & strFirstPicture & "'' ORDER BY Name ASC"
         Else
             strSQL = "SELECT * FROM " & strResourcetable & " WHERE Extension = ''png'' AND Name LIKE ''*" _
                 & strFilter & "*'' AND Name > ''" & strFirstPicture & "'' ORDER BY Name ASC"
         End If
         Set rst = db.OpenRecordset(strSQL, dbOpenDynaset)
     End If    
     If Not rst.EOF Then
         Do While Not rst.EOF
             Set cmd = Me("cmd" & Format(rst.AbsolutePosition + 1, "000"))
             cmd.Picture = rst!Name
             cmd.ControlTipText = rst!Name
             If rst.AbsolutePosition = 44 Then Exit Do
             rst.MoveNext
         Loop
     Else
         Me.cmdBildLoeschen.Enabled = False
     End If
     ...

Listing 2: Die Prozedur zum Laden von Bildern in die Schaltflächen (Teil 2)

Private lngStart As Long

Recordset auf Basis vorheriger Scrollvorgänge ermitteln

lngStart könnte anderenfalls in einem zuvor durchgeführten Ladevorgang der Bilder auf einen anderen Wert als 0 eingestellt worden sein, weil der Benutzer bereits gescrollt hat. In diesem Fall können wir das aktuelle Recordset nur als Grundlage für ein neues Recordset verwenden. lngStart gibt prinzipiell die Zeile an, deren Bilder gerade in der obersten Zeile der Schaltflächen angezeigt werden sollen. Hat der Benutzer zuvor einmal auf die Nach unten-Schaltfläche geklickt, hat lngStart beispielsweise nicht mehr den Wert 0, sondern 1. Das heißt, wir können nicht die Bilder aus MSysResources beginnend mit dem ersten Bild anzeigen, sondern wir beginnen die Anzeige mit dem 16. Bild. Um ein Recordset zu erstellen, das die Bilder ab dem 16. Bild liefert, benötigen wir den Namen des Bildes dieser Position. Das holen wir uns innerhalb der Bedingung, die prüft, ob lngStart größer als 0 ist. Hier verschieben wir den Datensatzzeiger auf den letzten und dann wieder auf den ersten Datensatz, um alle Datensätze einmal eingelesen zu haben, um im nächsten Schritt die Position des Datensatzzeigers mit der Eigenschaft AbsolutePosition auf den entsprechenden Wert einzustellen, in diesem Fall lngStart x 15 – 1, also 14. Danach können wir mit rst!Name den Wert des Feldes Name für diesen Datensatz ermitteln. Auf dieser Basis erstellen wir in strSQL eine neue Abfrage, die wieder in Abhängigkeit von strFilter eine Filterbedingung enthält oder auch nicht. Danach öffnen wir ein neues Recordset auf Basis dieser SQL-Abfrage.

Schließlich können wir die Elemente dieses Recordsets durchlaufen. Dabei referenzieren wir die Schaltfläche mit der entsprechenden Nummer und weisen dieser für die Eigenschaft Picture den Namen des Bildes zu. Für den ControlTipText tragen wir ebenfalls diesen Namen ein, damit dieser beim Überfahren mit der Maus eingeblendet wird. Das Recordset kann mehr als 45 Einträge enthalten, daher brechen wir beim Erreichen von AbsolutePosition = 44 den Vorgang ab – mehr Bilder können nicht in den Schaltflächen angezeigt werden.

Sollte das Recordset an dieser Stelle jedoch bereits leer sein, weil der Filter keine Ergebnisse zurückliefert, deaktivieren wir die Schaltfläche cmdBildLoeschen.

Verbleibende Schaltflächen leeren

Hier kann es vorkommen, dass entweder der Filter so eingestellt ist, dass weniger als 45 Bilder angezeigt werden sollen oder wir haben bis zum Ende gescrollt und es verbleiben auf diese Weise weniger als 45 Bilder. Dann durchlaufen wir eine For…Next-Schleife mit der aktuellen Datensatzanzahl bis 45 und löschen die Bilder und die ControlTipText-Eigenschaft für die verbleibenden Schaltflächen (siehe Listing 3).

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