Inhalte von Anlagenfeldern verwalten

Anlagefelder sind eine prima Möglichkeit, um Dateien in Access-Tabellen zu speichern. Im Gegen-satz zu OLE-Feldern stehen dazu sogar geeignete Elemente in der Benutzeroberfläche zur Ver-fügung. Diese sind allerdings nicht besonders ausgereift – so kann man nicht direkt im For-mu-lar die in einem Anlagefeld gespeicherten Elemente anzeigen oder neue hinzufügen. Dieser Beitrag zeigt, wie Sie ein Formular um diese Möglichkeit erweitern. Dabei fügen wir auch gleich die im Beitrag Drag and Drop im Anlagefeld vorgestellte Technik hinzu.

Beispieltabelle

Als Beispiel nutzen wir eine Tabelle namens tblProjekte, die neben dem Primärschlüsselfeld und der Projektbezeichnung nur ein Anlagefeld namens Dateien zum Speichern projektrelevanter Dateien enthält. Dies ist natürlich stark vereinfacht, aber es soll ja auch nur ein Beispiel sein. Bild 1 zeigt die Entwurfsansicht der Tabelle tblProjekte.

Tabelle mit Anlagefeld

Bild 1: Tabelle mit Anlagefeld

Formular zum Verwalten der Anlagen

Das Formular zum Verwalten der Anlagen im Anlagefeld Dateien der Tabelle tblProjekte verwendet natürlich die Tabelle tblProjekte als Datenherkunft (s. Bild 2).

Formular zum Verwalten von Anlagefeld-Inhalten

Bild 2: Formular zum Verwalten von Anlagefeld-Inhalten

Dabei soll sie den Inhalten der beiden Felder Projekt-ID und Projektbezeichung in entsprechenden Textfeldern anzeigen. Die im Anlagefeld gespeicherten Anlagen sollen in einem ListView-Steuerelement erscheinen. Drei Schaltflächen stellen die Funktionen zum Löschen, öffnen und Speichern der aktuell markierten Anlage im ListView-Steuerelement bereit. Als Gimmick soll ein Anlage-Steuerelement im rechten Bereich auch noch die aktuell im Listenfeld markierte Anlage anzeigen. Im Falle einiger Dateien erscheint dann die Vorschau, wie in der Abbildung etwa für eine Bilddatei. Dateien können per Drag and Drop zum ListView-Steuerelement hinzugefügt werden. Eine neu hinzugefügte Datei wird gleich markiert und im Anlage-Steuerelement angezeigt.

Zu den Einträgen des ListView-Steuerelements haben wir noch jeweils drei Kontextmenü-Befehle hinzugefügt, und zwar Löschen, öffnen und Speichern unter (s. Bild 3).

Kontextmenü mit den Anlagen-spezifischen Befehlen

Bild 3: Kontextmenü mit den Anlagen-spezifischen Befehlen

Erstellen des Formulars

Das Formular sieht im Entwurf wie in Bild 4 aus. Hier können Sie erkennen, dass sich das Anlage-Steuerelement nicht direkt im Hauptformular befindet, sondern in ein Unterformular eingebettet ist. Dies haben wir so gemacht, weil wir ja das Anlagen-Feld der Datenherkunft nicht so an ein Anlagen-Steuerelement binden können, dass jeweils der Inhalt einer speziellen Anlage angezeigt wird. Wie dies technisch gelöst ist, schauen wir uns jedoch weiter unten an.

Das Formular frmAnlagefeldVerwalten in der Entwurfsansicht

Bild 4: Das Formular frmAnlagefeldVerwalten in der Entwurfsansicht

Laden des Formulars

Beim Laden des Formulars sind zunächst einige Schritte zur Konfiguration des ListView-Steuerelements nötig. Dies erledigen wir in der Ereignisprozedur Beim Laden (s. Listing 1).

Private Sub Form_Load()
     Dim objColumnheader As MSComctlLib.ColumnHeader
     With Me!ctlListview
         .ColumnHeaders.Clear
         Set objColumnheader = .ColumnHeaders.Add(, , "Dateien hierher ziehen:")
         objColumnheader.Width = Me!ctlListview.Width - 350
         .View = lvwReport
         .Font.Name = "Calibri"
         .Font.Size = 11
         .Appearance = ccFlat
         .OLEDropMode = ccOLEDropManual
         .ListItems.Clear
     End With
End Sub

Listing 1: Vorbereitungen, die beim Laden des Formulars durchgeführt werden

Die Prozedur leert eventuell vorhandene Spaltenköpfe im ListView-Steuerelement und fügt dann einen neuen Spaltenkopf mit dem Text Dateien hierher ziehen hinzu. Die Breite dieses Elements stellt sie auf die Breite des Steuerelements minus 350 ein. Dies sorgt dafür, dass die einzige Spalte auch beim Einblenden der vertikalen Bildlaufleiste noch vollständig sichtbar ist und keine horizontale Bildlaufleiste eingeblendet werden muss. Dann stellt sie die Ansicht auf lvwReport ein und legt die Schriftart und Schriftgröße so fest, dass diese zur Schrift der übrigen Steuerelemente passt. Der Wert ccFlat für die Eigenschaft Appearance sorgt dafür, dass das Steuerelement nicht vertieft angezeigt wird. OLEDropMode = ccOLEDropManual sorgt dafür, dass einige Ereignisse beim Drag and Drop auf das ListView-Steuerelement ausgelöst und implementiert werden können. Schließlich leert die Prozedur das ListView-Steuerelement, falls noch Einträge von vorherigen Anwendungen vorhanden sind.

Unterformular zur Ansicht der aktuell markierten Anlage

Das Unterformular sfmAnlagefeld enthält als einziges Steuerelement das Anlage-Steuerelement ctlAttachment. Das Formular selbst ist über die Eigenschaft Datenherkunft an eine Abfrage gebunden, welche die beiden Felder Dateien.FileData und Dateien.FileName liefert (s. Bild 5). Die “doppelten” Feldnamen mit dem trennenden Punkt erklären sich durch die Besonderheit des Anlagefeldes: Dieses hat in der Tabelle tblProjekte den Namen Dateien. Ein Anlagefeld enthält aber intern immer eine Tabelle, da es ja auch mehrere Anlagen samt Metadaten aufnehmen kann. Und zwei der Felder dieser Tabelle heißen FileData und FileName. Um direkt auf diese Felder zuzugreifen, verwendet man dann die Syntax ., also zum Beispiel Dateien.FileData.

Das Unterformular sfmAnlagefeld in der Entwurfsansicht

Bild 5: Das Unterformular sfmAnlagefeld in der Entwurfsansicht

Das Feld Dateien.FileData weisen wir direkt dem Anlage-Steuerelement ctlAttachment als Steuerelementinhalt zu, damit dieses den Inhalt der Datei oder ein entsprechendes Symbol anzeigt. Wofür aber benötigen wir das Feld Dateien.FileName Dieses verwenden wir, um den aktuellen Datensatz des Unterformulars mit dem im ListView-Steuerelement des Hauptformulars angezeigten Anlage-Datensatz zu synchronisieren.

Dazu verwenden wir die beiden Eigenschaften Verknüpfen von und Verknüpfen nach des Unterformular-Steuerelements, die sonst für die Verknüpfung von Daten in einer 1:n-Beziehung in Haupt- und Unterformular dienen. In diesem Fall stellen wir die Eigenschaft Verknüpfen von auf das Feld Dateien.FileName der Datenherkunft des Unterformulars und die Eigenschaft Verknüpfen nach auf das Textfeld txtDateiname ein. Dieses finden Sie samt den Eigenschaften des Unterformular-Steuerelements in Bild 6.

Einstellungen für das Unterformular-Steuerelement

Bild 6: Einstellungen für das Unterformular-Steuerelement

Nun müssen wir nur noch klären, wie das Textfeld txtDateiname an den Namen des aktuell im ListView-Steuerelement ausgewählten Eintrags kommt.

Beim Anzeigen eines Datensatzes

Jeder Datensatzwechsel, und damit auch das erste Anzeigen eines Datensatzes im Formular frmAnlagefeldVerwalten, löst das Ereignis Beim Anzeigen und somit die Prozedur aus Listing 2 aus. Diese prüft zunächst, ob das Formular aktuell überhaupt einen Datensatz anzeigt. Dies ist der Fall, wenn Me!ProjektID den Wert Null aufweist und geschieht etwa dann, wenn der Benutzer zu einem neuen, leeren Datensatz wechselt. In diesem Fall soll dann einfach das ListView-Steuerelement geleert werden – siehe Else-Teil der If…Then-Bedingung.

Private Sub Form_Current()
     Dim db As DAO.Database
     Dim rst As DAO.Recordset
     Dim rstDateien As DAO.Recordset
     Set db = CurrentDb
     If Not IsNull(Me!ProjektID) Then
         Set rst = db.OpenRecordset("SELECT Dateien.Filename FROM tblProjekte WHERE ProjektID = " & Me!ProjektID _
             & " ORDER BY Dateien.Filename", dbOpenDynaset)
         Me!ctlListview.ListItems.Clear
         Me!txtDateiname = rst("Dateien.Filename")
         Do While Not rst.EOF
             If Not IsNull(rst.Fields("Dateien.Filename")) Then
                 Me!ctlListview.ListItems.Add , , rst.Fields("Dateien.FileName")
             End If
             rst.MoveNext
         Loop
     Else
         Me!txtDateiname = ""
         Me!ctlListview.ListItems.Clear
     End If
End Sub

Listing 2: Diese Ereignisprozedur wird beim Anzeigen eines jeden Datensatzes ausgelöst.

Liegt jedoch ein Datensatz vor, erstellt die Prozedur ein neues Recordset, welches das Feld Dateien.FileName der Tabelle tblProjekte für alle Datensätze enthält, deren Feld ProjektID mit dem aktuellen Primärschlüsselwert des Datensatzes im Hauptformular übereinstimmt. Die Prozedur leert dann die Einträge des Listenfeldes.

Anschließend folgt eine Anweisung, die für die Synchronisierung mit dem Unterformular zur Anzeige der aktuell markierten Anlage verantwortlich ist: Sie stellt den Wert des Feldes txtDateiname auf den Dateinamen aus rst(“Dateien.FileName”) ein. Das Anlage-Steuerelement im Unterformular zeigt nun Inhalt des Anlagefeldes des ersten Datensatzes der Tabelle tblProjekte für das aktuellen Projekt an.

Nun durchläuft die Prozedur alle Datensätze der Abfrage und fügt dem ListView-Steuerelement jeweils einen neuen Eintrag hinzu, wobei dieser als Text jeweils den Inhalt des Feldes Dateien.FileName erhält.

Hinzufügen neuer Anlagen per Drag and Drop

Neue Dateien fügen Sie zum aktuellen Projekt hinzu, indem Sie diese aus dem Windows Explorer auf das Steuerelement ziehen. Wenn Sie ein beliebiges Objekt über dieses Steuerelement ziehen, löst dies das Ereignis OLEDragOver aus. Dieses liefert mit Data einen Verweis auf das gezogene Objekt. Die If…Then-Bedingung aus Listing 3 prüft, ob es sich bei dem Objekt um eine Datei handelt (ccDFFiles).

Private Sub ctlListview_OLEDragOver(Data As Object, Effect As Long, Button As Integer, Shift As Integer, x As Single, _
         y As Single, State As Integer)
     If Not Data.GetFormat(ccCFFiles) Then
         Effect = ccOLEDropEffectNone
     End If
End Sub

Listing 3: Ereignis beim überfahren des Drop-Ziels

Falls nicht, wird der Mauszeiger in ein Icon verwandelt, das andeutet, dass das aktuell gezogene Objekt nicht auf das ListView-Steuerelement fallen gelassen werden kann (Effect = ccOLEDropEffectNone), s. Bild 7.

Versuch, ein anderes Objekt als eine Datei auf das ListView-Steuerelement zu ziehen

Bild 7: Versuch, ein anderes Objekt als eine Datei auf das ListView-Steuerelement zu ziehen

Falls doch, kann der Benutzer das Objekt auf das List-View-Steuerelement fallen lassen. Dies löst dann das Ereignis OLEDragDrop aus (s. Listing 4). Auch hier erfolgt zunächst die Prüfung, ob es sich bei dem gezogenen Objekt um eine Datei handelt. Ist dies der Fall, startet die Prozedur eine For Each-Schleife über alle Elemente der Files-Auflistung des Data-Parameters. Dieser liefert alle Dateinamen der in Data enthaltenen Dateien – Sie können nämlich nicht nur eine einzige, sondern auch mehrere Dateien gleichzeitig in das Anlagefeld ziehen.

Private Sub ctlListview_OLEDragDrop(Data As Object, Effect As Long, Button As Integer, Shift As Integer, x As Single, _
         y As Single)
     Dim varDateipfad As Variant
     Dim strDateiname As String
     Dim objListItem As MSComctlLib.ListItem
     If Data.GetFormat(ccCFFiles) Then
         For Each varDateipfad In Data.Files
             strDateiname = Mid(varDateipfad, InStrRev(varDateipfad, "\") + 1)
             Set objListItem = Me!ctlListview.ListItems.Add(, , strDateiname)
             objListItem.Selected = True
             Me!ctlListview.SetFocus
             ctlListview_Click
             DateiSpeichern CStr(varDateipfad)
         Next
     End If
End Sub

Listing 4: Ereignis, das beim Fallenlassen einer Datei über dem ListView-Steuerelement ausgelöst wird

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