Wer den Anlagen-Datentyp und das dazugehörige Steuerelement mag, möchte vielleicht die Funktionen des Dialogs zum Verwalten von Anlagen gleich in eigene Formulare integrieren. Damit würde man auch die etwas unübersichtliche Darstellung in den Griff bekommen. Wie Sie ein solches Formular erstellen und einsetzen, lesen Sie in diesem Beitrag.
Das Anlage-Feld ist in der Standardansicht nicht besonders übersichtlich, erst nach dem Öffnen des Anlagen-Dialogs erscheint eine Liste der im Anlagefeld enthaltenen Dateien (s. Bild 1).
Bild 1: Anlage-Feld mit Anlagen-Dialog
Ziel dieses Beitrags ist, alle im Anlage-Feld gespeicherten Dateien gleich in einer Liste anzuzeigen und die Schaltflächen bereitzustellen, um Dateien hinzuzufügen, zu entfernen, zu öffnen, unter einem anderen Dateinamen zu speichern oder alle enthaltenen Dateien zu speichern – also genau wie im Standarddialog zur Verwaltung von Anlagen.
Um dieses Element einfach wiederverwertbar zu machen, verwenden wir dazu ein Unterformular, dem wir beim Öffnen einen Parameter mit dem Verweis auf das entsprechende Anlage-Feld übergeben. Das Unterformular soll die Dateien dann im einfachsten Fall in einem Listenfeld anzeigen. Denkbar wäre natürlich auch der Einsatz eines ListView-Steuerelements, das zusätzlich noch dem Dateityp entsprechende Icons anzeigen könnte.
Das benötigte Unterformular sieht im Entwurf wie in Bild 1 – mit Ausnahme der Schaltfläche Abbrechen, die ohnehin keinen anderen Nutzen als die OK-Schaltfläche besitzt.
Bild 2: Entwurf des Anlagen-Unterformulars
Das Hauptformular muss dem Unterformular irgendwie mitteilen, aus welchem Feld die anzuzeigenden Dateien eingelesen werden sollen. Da das übergeordnete Formular vermutlich einen Datensatz der Tabelle anzeigt, in dem sich das Anlagenfeld befindet, greifen wir entweder vom Unterformular auf das Hauptformular zu oder übergeben vom Hauptformular aus eine Referenz auf dieses Feld. Für den Moment verwenden wir im Unterformular zwei Objektvariablen namens m_AttachmentRecordset und m_Attachmentfield, die wie folgt im Klassenmodul des Formulars deklariert sind:
Dim m_Attachmentfield As DAO.Field2 Dim m_AttachmentRecordset As DAO.Recordset
Außerdem brauchen wir einen Verweis auf das Hauptformular, damit wir später auf das Wechseln des Datensatzes reagieren können:
Dim WithEvents m_Form As Form
Zusätzlich definieren wir eine öffentliche Prozedur zum Initialisieren des Formulars (s. Listing 1).
Listing 1: Initialisieren des Anlagen-Formulars
Public Sub Initialize(frm As Form, strAttachmentfield As String) Set m_Form = frm m_Form.OnCurrent = "[Event Procedure]" Set m_AttachmentRecordset = frm.RecordsetClone Set m_Attachmentfield = rstAttachment.Fields(strAttachmentfield) AnlagenAktualisieren End Sub
Diese Prozedur speichert den Verweis auf das Formular, in dem sich das Unterformular befindet. Die Variable m_AttachmentRecordset wird mit einem Verweis auf den RecordsetClone des Hauptformulars gefüllt und m_AttachmentField mit einem Verweis auf das Anlage-Feld selbst.
Schließlich ruft die Prozedur noch eine weitere Routine namens AnlagenAktualisieren auf, die dafür verantwortlich ist, das Listenfeld mit den im Anlagefeld des aktuellen Datensatzes enthaltenen Anlagen zu füllen – dazu später mehr.
Listing 2: Anlagefeld aktualisieren
Private Sub AnlagenAktualisieren() m_AttachmentRecordset.Bookmark = m_Form.Recordset.Bookmark If Not m_Form.NewRecord Then AnlagenAuflisten Me!lstAnlagen = Me!lstAnlagen.ItemData(0) Else Me!lstAnlagen.RowSource = "" End If SchaltflaechenAktivieren End Sub
Da das Formular frmAnlagen später als Unterformular dienen soll, fügen Sie es auch während der Entwicklung in ein weiteres Formular ein. In unserem Fall heißt dieses Formular frmKunden und zeigt die Daten der Tabelle tblKunden der Beispieldatenbank an (s. Bild 3).
Bild 3: Das Anlageformular als Unterformular
Fügen Sie das Unterformular in das Hauptformular ein und legen Sie für das Hauptformular eine Ereignisprozedur für die Eigenschaft Beim Laden an, die wie folgt aussieht:
Private Sub Form_Load() Me!frmAnlagen.Form.Initialize Me, "Dateianlagen" End Sub
Diese Prozedur übergibt nur einen Verweis auf das Hauptformular sowie den Namen des Anlage-Feldes an die Initialize-Prozedur des Unterformulars.
Anlagen aktualisieren
Die oben referenzierte Prozedur AnlagenAktualisieren fasst einige Anweisungen zusammen, die sowohl beim erstmaligen Anzeigen des Anlagen-Listenfeldes, als auch beim späteren Datensatzwechsel im Hauptformular aufgerufen werden sollen (s. Listing 2). Die Prozedur prüft zunächst, ob das Hauptformular überhaupt einen Datensatz anzeigt. Falls ja, verschiebt es den Datensatzzeiger des unter m_AttachmentRecordset referenzierten Recordsets auf den aktuell im Formular angezeigten Datensatz und ruft die Routine AnlagenAuflisten auf, welche die Anlagen ausliest und das Listenfeld mit deren Dateinamen füllt. Zeigt das Formular einen neuen Datensatz an, wird lediglich das Listenfeld geleert. In beiden Fällen ruft die Prozedur die gleich vorgestellte Routine SchaltflaechenAktualisieren auf.
Listing 3: Füllen des Listenfeldes mit den Anlagen
Public Sub AnlagenAuflisten() Dim db As DAO.Database Dim rstAttachments As Recordset2 Dim rstAttachmentsSortiert As Recordset2 Set rstAttachments = m_Attachmentfield.Value rstAttachments.Sort = "Filename ASC" Set rstAttachmentsSortiert = rstAttachments.OpenRecordset Me!lstAnlagen.RowSource = "" Do While Not rstAttachments.EOF Me!lstAnlagen.AddItem rstAttachments!FileName rstAttachments.MoveNext Loop End Sub
Liste mit Anlagen füllen
Die Prozedur AnlagenAuflisten füllt das Listenfeld des Formulars, das wir lstAnlagen nennen, mit den Dateinamen der im übergebenen Feld enthaltenen Dateien. Damit wir die AddItem und die RemoveItem-Methoden des Listenfeldes verwenden können, stellen wir die Eigenschaft Herkunftsart dieses Steuerelements auf Wertliste ein. Die Prozedur füllt dann das Listenfeld mit den Namen der im Anlagenfeld gespeicherten Dateien – und zwar in alphabetischer Reihenfolge (s. Listing 3). Das zukünftige Unterformular gestalten wir noch ein wenig übersichtlicher, indem wir die Eigenschaften Navigationsschaltfläche, Datensatzmarkierer und Bildlaufleisten jeweils auf den Wert Nein einstellen.
Listing 5: Auslösen des Hinzufügens einer Anlage aus einer Datei
Private Sub cmdHinzufuegen_Click() Dim objFiles As clsFiles Dim strDateien As String Dim strDateienArray() As String Dim i As Integer Set objFiles = New clsFiles With objFiles .Filter = "Alle Dateien (*.*)" .StartDir = CurrentProject.Path .Title = "Datei(en) auswählen" .MultipleFiles = True strDateien = .OpenFileName End With strDateienArray() = Split(strDateien, vbTab) For i = LBound(strDateienArray) To UBound(strDateienArray) AnlageHinzufuegen strDateienArray(i) Next i AnlagenAuflisten End Sub
Steuerelemente aktivieren und deaktivieren
Bevor wir die Steuerelemente selbst mit Leben füllen, sollen diese zunächst, je nach den angezeigten Daten, aktiviert oder deaktiviert werden. Die Hinzufügen-Schaltfläche etwa ist immer aktiviert. Die Schaltfläche Entfernen hingegen soll nur benutzbar sein, wenn die Liste Dateien anzeigt und mindestens eine davon markiert ist. Das gleiche gilt für die Schaltflächen Öffnen und Speichern unter…. Die Schaltfläche Alle speichern wiederum darf ebenfalls immer aktiviert sein – außer wenn die Liste keinerlei Anlagen anzeigt.
Die Prüfung des Zustands des Listenfeldes und die davon abhängige Aktivierung/Deaktivierung der Schaltflächen nimmt die folgende Prozedur vor, die Sie ebenfalls im Klassenmodul des Formulars anlegen (s. Listing 4).
Listing 4: Aktiviere und Deaktivieren der Schaltflächen
Private Sub SchaltflaechenAktivieren() Dim bolDateiAusgewaehlt As Boolean bolDateiAusgewaehlt = Not Me!lstAnlagen.ItemsSelected.Count = 0 Me!cmdEntfernen.Enabled = bolDateiAusgewaehlt Me!cmdOeffnen.Enabled = bolDateiAusgewaehlt Me!cmdSpeichernUnter.Enabled = bolDateiAusgewaehlt Me!cmdAllesSpeichern.Enabled = Not (Me!lstAnlagen.ListCount = 0) End Sub