Zur Hauptseite ... Zum Onlinearchiv ... Zum Abonnement ... Zum Newsletter ... Zu den Tools ... Zum Impressum ... Zum Login ...

Gedrucktes Heft

Diesen Beitrag finden Sie in Ausgabe 6/2015.

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

Drag and Drop in Anlagefelder

Mit den Anlagefeldern hat Microsoft unter Access 2007 eine Möglichkeit zum Speichern von Dateien in Tabellenfeldern eingeführt, die etwas einfacher zugänglich ist als das bis dahin für solche Zwecke verwendete OLE-Feld. Leider fehlt noch eine Möglichkeit, einfach per Drag and Drop eine Datei aus dem Windows Explorer in ein Anlagefeld einer Tabelle zu ziehen. Dieser Beitrag zeigt, wie Sie ein solches Feature nachträglich hinzufügen können.

Anlagefelder sind eigentlich eine prima Sache: Sie können ganz einfach über die Benutzeroberfläche Dateien hinzufügen und darauf ins Dateisystem übertragen. Auch ein Öffnen der Dateien direkt aus dem Anlagefeld heraus ist möglich. Allerdings ist der Zugriff auf die enthaltenen Dateien mitunter etwas mühselig.

Immerhin müssen Sie zunächst auf das Anlage-Steuerelement klicken und dann auf das erscheinende Menü, um überhaupt erst die Liste der enthaltenen Dateien anzuzeigen (s. Bild 1).

Öffnen des Dialogs zum Verwalten von Anlagen

Bild 1: Öffnen des Dialogs zum Verwalten von Anlagen

Dort erwartet Sie dann ein Dialog, der die im Anlagefeld enthaltenen Anlagen anzeigt und verschiedene Möglichkeiten bietet, zum Beispiel zum Hinzufügen, Entfernen oder Öffnen einer der im Anlagefeld gespeicherten Dateien (s. Bild 2).

Dialog zum Verwalten von Anlagen

Bild 2: Dialog zum Verwalten von Anlagen

Was hier für einige Anwendungen fehlen dürfte, ist eine Möglichkeit, mal eben eine Datei aus dem Windows Explorer auf ein Steuerelement zu ziehen und so die Datei im Anlagefeld zu speichern. Das stellen wir uns etwa wie in Bild 3 vor.

Formular mit Drag-and-Drop-Ziel für das Anlagefeld

Bild 3: Formular mit Drag-and-Drop-Ziel für das Anlagefeld

Hier wählen wir komfortabel die Zieltabelle und das darin enthaltene Anlagefeld aus. Das Listenfeld darunter zeigt alle Datensätze der Tabelle an. Hier markieren Sie den Datensatz, dem Sie eine Datei hinzufügen möchten. Dann ziehen Sie die gewünschte Datei aus dem Windows Explorer einfach auf das darunter befindliche ListView-Steuerelement. Das erfolgreiche Speichern wird noch durch eine kurze Meldung bestätigt.

Formular für Drag und Drop

Das Formular der Beispieldatenbank heißt frmDragAndDrop und soll zeigen, wie Sie Dateien flexibel in beliebige Anlagefelder hineinziehen können. Dies ist erstens sinnvoll, weil Sie so die relevanten Codezeilen leicht anpassen können, zweitens können Sie das Formular gleich nutzen, wenn Sie einem Anlagefeld einer beliebigen Tabelle Dateien hinzufügen möchten.

In der Entwurfsansicht sieht das Formular wie in Bild 4 aus. Im oberen Bereich finden Sie die beiden Kombinationsfelder, mit denen Sie die Zieltabelle und das darin enthaltene Anlagefeld auswählen können. Darunter befindet sich ein Listenfeld, das die Inhalte der ersten vier Felder der gewählten Tabelle anzeigt.

Das Formular mit dem Drag-and-Drop-Ziel in der Entwurfsansicht

Bild 4: Das Formular mit dem Drag-and-Drop-Ziel in der Entwurfsansicht

Hier können Sie festlegen, zu welchem Datensatz die Anlage hinzugefügt werden soll. Schließlich folgt das wichtigste Steuerelement – das ListView-Steuerelement, das als Drag-and-Drop-Ziel dient.

Warum ausgerechnet ein ListView-Steuerelement? Nun: Dieses bietet im Gegensatz zu den Standardsteuerelementen von Access die Möglichkeit, auf Drag-and-Drop-Ereignisse zu reagieren und diese zu implementieren.

Tabelle und Feld auswählen

Das Kombinationsfeld cboTabellen erhält als Datenherkunft die folgende Abfrage:

SELECT Name FROM MSysObjects WHERE Type = 1 
AND NOT Name LIKE 'MSys*' AND NOT Name LIKE '~*' 
AND NOT Name LIKE 'f_*' ORDER BY Name;

Diese liefert alle Einträge der Systemtabelle MSysObjects, deren Feld Type den Wert 1 enthält (für lokale Access-Tabellen) und deren Feld Name nicht mit MSys..., F_... oder ~... beginnt. Erstere sind die Systemtabellen, Letztere für den internen Gebrauch verwendete Tabellen.

Nach der Auswahl soll das zweite Kombinationsfeld die Felder der gewählten Tabelle anzeigen.

Dazu legen wir für cboTabellen eine Ereignisprozedur an, die durch das Ereignis Nach Aktualisierung ausgelöst wird:

Private Sub cboTabellen_AfterUpdate()
     Me!cboFelder.RowSource = Me!cboTabellen
     Me!lstDatensaetze.RowSource = Me!cboTabellen
End Sub

Die erste Anweisung stellt die Datensatzherkunft des Kombinationsfeldes zur Anzeige der Felder auf den Wert des ersten Kombinationsfeldes ein, also den Namen der Tabelle.

Die zweite legt die gleiche Tabelle als Datensatzherkunft des Listenfeldes lstDatensaetze zur Anzeige der enthaltenen Daten fest. Damit das zweite Kombinationsfeld nach der Angabe eines Tabellennamens als Datensatzherkunft auch die enthaltenen Felder anzeigt, stellen Sie zuvor noch die Eigenschaft Herkunftsart auf den Wert Feldliste ein (s. Bild 5).

Einstellen der Herkunftsart für das Kombinationsfeld cboFelder

Bild 5: Einstellen der Herkunftsart für das Kombinationsfeld cboFelder

Fehlen noch einige Einstellungen für das ListView-Steuerelement. Diese nehmen wir gleich beim Öffnen des Formulars in der Ereignisprozedur Beim Laden vor.

Diese Prozedur aus Listing 1 deklariert zunächst eine Variable des Datentyps ColumnHeader. Dieses benötigen wir gleich, um eine Referenz auf ein neu angelegtes Objekt dieses Typs zu speichern. Das ListView-Element enthält nämlich nicht automatisch Spalten und somit auch keine Spaltenköpfe.

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 - 100
         .View = lvwReport
         .OLEDropMode = ccOLEDropManual
         .ListItems.Clear
     End With
End Sub

Listing 1: Einstellen des ListView-Steuerelements beim Öffnen des Formulars

Nachdem die Prozedur eventuell noch vorhandene Spaltenköpfe mit der Clear-Anweisung gelöscht hat, legt sie mit der Add-Methode der ColumnHeaders-Auflistung des ListView-Steuerelements ctlListView einen neuen Spaltenkopf an und legt über den dritten Parameter dieser Methode die Spaltenbeschriftung fest. Im Grunde benötigen wir ja gar keine Spalten, aber wir wollen im ListView-Steuerelement die Beschriftung Dateien hierher ziehen: unterbringen, damit der Benutzer weiß, was er mit dem ListView-Steuerelement anfangen kann.

In der folgenden Anweisung stellen wir die Spaltenbreite für die neu erstellte und in der Variablen objColumnheader gespeicherten Spalte auf einen Wert ein, der etwas kleiner ist als die Breite des ListView-Steuerelements selbst. Schließlich legen wir noch die Ansicht auf lvwReport fest, damit der Spaltenkopf überhaupt erscheint, und stellen OLEDropMode auf ccOLEDropManual ein, damit wir das Ereignis für das Droppen von Elementen selbst programmieren können.

Die ListItems.Clear-Methode leert die Liste, falls diese aus irgendwelchen Gründen einen Eintrag enthalten sollte. Damit finden Sie das Formular in der Entwurfsansicht auch wie in der eingangs dargestellten Abbildung vor.

Drop-Ereignis

Wenn der Benutzer eine Datei über dem ListView-Steuerelement fallen lässt, löst dies das Ereignis OLEDragDrop aus. Dieses Ereignis können Sie nicht, wie bei den eingebauten Access-Steuerelementen üblich, über das Eigenschaftsfenster des Steuerelements anlegen. Stattdessen öffnen Sie direkt das Klassenmodul des Formulars. Wählen Sie dort im linken Kombinationsfeld im oberen Bereich den Wert ctlListView aus und im rechten OLEDragDrop. Der VBA-Editor legt nun die gewünschte Ereignisprozedur an.

Diese müssen Sie nun nur noch wie in Listing 2 auffüllen. Die Prozedur erwartet einen für uns wichtigen Parameter, nämlich Data. Dieses liefert eine Verweis auf das Objekt, das per Drag and Drop über dem ListView-Steuerelement fallen gelassen wurde.

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
     If Data.GetFormat(ccCFFiles) Then
         For Each varDateipfad In Data.Files
             DateiSpeichern CStr(varDateipfad)
             MsgBox "Datei hinzugefügt."
         Next
     End If
End Sub

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

Data kann eines oder mehrere Objekte enthalten. Deshalb durchlaufen wir in einer For Each-Schleife alle Einträge der Files-Auflistung des Data-Objekts. Dabei landet der Dateiname jeweils in der Variablen varDateipfad.

Die Funktion GetFormat des Data-Objekts prüft, ob das Format der aktuellen Datei einem bestimmten Wert entspricht – in diesem Fall ccDFFiles für eine Datei.

Ist dies der Fall, ruft die Prozedur die Routine DateiSpeichern auf und übergibt dieser den Dateinamen aus der Variablen varDateipfad.

Datei im Anlagefeld speichern

Fehlt noch die Prozedur DateiSpeichern, die den Dateinamen als Parameter entgegennimmt (s. Listing 3). Diese ermittelt zunächst mit der Funktion GetSinglePrimaryKey den Primärschlüssel der Tabelle (siehe Artikel Primärschlüsselfelder ermitteln, www.access-im-unternehmen.de/1004).

Private Sub DateiSpeichern(strDateiname As String)
     Dim db As DAO.Database
     Dim rst As DAO.Recordset
     Dim fld As DAO.Field2
     Dim rstDateien As DAO.Recordset2
     Dim strPK As String
     strPK = GetSinglePrimaryKey(Me!cboTabellen)
     Set db = CurrentDb
     Set rst = db.OpenRecordset("SELECT * FROM " & Me!cboTabellen & " WHERE " & strPK _
         & " = " & Me!lstDatensaetze, dbOpenDynaset)
     rst.Edit
     Set rstDateien = rst.Fields(Me!cboFelder).Value
     rstDateien.AddNew
     Set fld = rstDateien.Fields("FileData")
     fld.LoadFromFile strDateiname
     rstDateien.Update
     rst.Update
End Sub

Listing 3: Speichern einer Datei im Anlagefeld

Anschließend liest die Prozedur die Daten der in cboTabellen angegebenen Tabelle in ein Recordset ein, wobei der Primärschlüsselwert dem Wert der gebundenen Spalte des aktuell in lstDatensaetze markierten Eintrags entsprechen muss.

Die folgende Anweisung startet die Bearbeitung dieses Datensatzes, die übernächste weist dem Recordset2-Objekt den Inhalt des Feldes aus cboFelder zu – also den Inhalt des Anlagefeldes. Zur Erläuterung: Anlagefelder enthalten immer ein Recordset mit je einem Datensatz für jede gespeicherte Anlage.

Dies wird auch deutlich, wenn Sie einmal eine Tabelle mit einem Anlagefeld in den Entwurf einer Abfrage ziehen – dort finden Sie versetzt zum Anlagefeld weitere Felder (s. Bild 6). Dies sind die Felder der verknüpften, internen Tabelle, welche die eigentlichen Datensätze mit den Anlagen speichert. Die Tabelle enthält die Felder FileData, FileName und FileType. FileData ist das Feld, das die Datei selbst enthält.

Felder des Recordsets eines Anlagefeldes

Bild 6: Felder des Recordsets eines Anlagefeldes

Wie in der Prozedur können Sie nun über die Value-Eigenschaft des Anlagefeldes ein Recordset erstellen, das die verknüpfte Tabelle mit den Anlagedaten enthält. Diesem Recordset fügen wir nun einen neuen Datensatz hinzu. Das Feld FileData referenzieren wir mit der Objektvariablen fld des Typs Field2. Dieses bietet wiederum die Methode LoadFromFile an, welche die als Parameter angegebene Datei in das Anlagefeld lädt. Um die Änderungen zu speichern, rufen Sie erst die Update-Methode des Recordsets für das Anlagefeld auf und dann die Update-Methode für das Recordset auf Basis der Tabelle.

Zusammenfassung und Ausblick

Mit der in diesem Beitrag vorgestellten Technik können Sie Dateien aus dem Windows Explorer per Drag and Drop auf ein ListView-Steuerelement in einem Anlagefeld speichern. Das Beispiel in diesem Beitrag erlaubt es, die Tabelle und das Anlagefeld, das als Ziel verwendet werden soll, zur Laufzeit auszuwählen.

Die Lösung setzt voraus, dass die Tabelle mit dem Anlagefeld nur einen einfachen, aber keinen zusammengesetzten Primärschlüssel verwendet und dass diese das erste Feld der Tabelle ist – nur so wird dieses als erste und somit gebundene Spalte des Listenfeldes angezeigt, das zur Auswahl des Zieldatensatzes verwendet wird.

In einem weiteren Beitrag zeigen wir, wie Sie die Lösung zum Hinzufügen und Verwalten der Inhalte von Anlagefeldern nutzen können. Dort sollen auch die bereits gespeicherten Dateien in einem ListView-Steuerelement angezeigt werden.

Diese können Sie dann über ein Kontextmenü oder dafür vorgesehene Schaltflächen löschen, öffnen oder im Dateisystem speichern (Inhalte von Anlagefeldern verwalten, www.access-im-unternehmen.de/1013).

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:

Download

Download

Die .zip-Datei enthält folgende Dateien:

DragAndDrop.accdb

Beispieldateien downloaden

© 2003-2015 André Minhorst Alle Rechte vorbehalten.