Im Beitrag “Serienmails versenden mit CDO” haben wir einige Prozeduren und Funktionen vorgestellt, mit denen Sie Serien-E-Mails über die CDO-Bibliothek von Windows versenden können. Das macht natürlich nur halb soviel Spaß, wenn nur die nackten Routinen vorliegen. Also zeigen wir im vorliegenden Beitrag auch noch, wie Sie eine praktische Benutzeroberfläche zum Verwalten der für den Versand einer Serienmail benötigten Daten programmieren.
Datenmodell der Anwendung
Die Anwendung zum Versenden von Serienmails enthält einige Tabellen, die wie im Folgenden vorstellen.
Im Beziehungen-Fenster aus Bild 1 sehen Sie die benötigten Tabellen. Die ersten beiden heißen tblKunden sowie tblAnreden. Die Tabelle tblConfigurations enthält die Daten für die Konfiguration des Mailservers und die Tabelle tblMailings die Daten zum Mailing selbst, also eine Bezeichnung, die Absenderadresse, den Betreff, den Inhalt und die Anlagen. Der Tabelle tblMailings haben wir ein Fremdschlüsselfeld namens ConfigurationID hinzugefügt, mit dem wir die für das jeweilige Mailing verwendete Konfiguration speichern können. Außerdem enthält die Tabelle tblMailings zwei Felder, mit denen die Adressaten des Mailings definiert werden. SQLSource nimmt den SQL-Ausdruck auf, der die Empfängeradressen liefert und Mailfield den Namen des Feldes aus diesem Ausdruck, der festlegt, welches Feld die Mailadresse enthält.
Bild 1: Datenmodell der Anwendung
Zu erstellende Formulare
Wir wollen der Lösung einige Formulare hinzufügen, mit der Sie diese komfortabel steuern können. Dazu gehören die folgenden:
- Formular zum Verwalten der Konfigurationen
- Formular zum Verwalten der Mailings
- Formular zum Auswählen der Empfänger des Mailings
Formular zum Verwalten der Konfigurationen
Wir beginnen mit dem Formular frmConfigurations. Das Formular verwendet die Tabelle tblConfigurations als Datensatzquelle. Ziehen Sie alle Felder aus der Feldliste in das Formular und ordnen Sie diese so an wie in Bild 2. Dann fügen Sie noch einige weitere Steuerelemente hinzu:
Bild 2: Entwurf des Formulars frmConfigurations
- Kombinationsfeld cboSchnellauswahl (in den Formularkopf)
- Schaltfläche cmdOK (mit den anderen Schaltflächen in den Formularfuß)
- Schaltfläche cmdNeu
- Schaltfläche cmdLoeschen
Außerdem passen wir den Namen des Kontrollkästchens für das Feld Standard auf chkDefault an.
Schnellauswahl für die Konfiguration
Das Kombinationsfeld cboSchnellauswahl verwendet eine Abfrage auf Basis der Tabelle tblConfigurations als Datensatzherkunft. Dabei verwenden wir nur die ersten beiden Felder ConfigurationID und ConfigurationName, wobei wir diese nach dem Feld ConfigurationName sortieren wollen:
SELECT ConfigurationID, ConfigurationName FROM tblConfigurations ORDER BY ConfigurationName;
Damit das Kombinationsfeld nur die Bezeichnung der Konfiguration anzeigt, aber nicht den Inhalt des Autowertfeldes, stellen wir die Eigenschaft Spaltenanzahl auf 2 und Spaltenbreiten auf 0cm ein. Damit das Kombinationsfeld nach dem Wechsel zu einem anderen Datensatz im Formular den Namen der aktuellen Konfiguration anzeigt, fügen wir die folgende Prozedur hinzu, die durch das Ereignis Beim Anzeigen ausgelöst wird:
Private Sub Form_Current() Me!cboSchnellauswahl = Me!ConfigurationID End Sub
Gegebenenfalls ändert der Benutzer die Bezeichnung der Konfiguration. Damit sich dies direkt im Kombinationsfeld zur Schnellauswahl wiederspiegelt, aktualisieren wir dieses, wenn der Benutzer Daten im Formular aktualisiert und gespeichert hat:
Private Sub Form_AfterUpdate() Me!cboSchnellauswahl.Requery End Sub
Aktionen beim Laden des Formulars
Beim Öffnen des Formulars soll dieses den ersten Datensatz anzeigen, der im Feld Default den Wert True enthält – der also als Standardkonfiguration definiert ist. Damit dies geschieht, suchen wir direkt in der Prozedur, die durch das Ereignis Beim Laden ausgelöst wird, mit der FindFirst-Methode des Recordsets des Formulars nach diesem Datensatz. Unabhängig davon, ob dies einen Datensatz findet, soll das Kombinationsfeld cboSchnellauswahl auf den gleichen Datensatz eingestellt werden, den auch das Formular anzeigt. Dafür stellen wir den Wert von Me!cboSchnellauswahl anschließend auf Me!ConfigurationID ein:
Private Sub Form_Load() Me.Recordset.FindFirst "Default = True" Me!cboSchnellauswahl = Me!ConfigurationID End Sub
Auswahl einer anderen Konfiguration per Kombinationsfeld
Damit das Formular nach der Auswahl eines anderen Datensatzes über das Kombinationsfeld cboSchnellauswahl den gewünschte Datensatz anzeigt, fügen wir dem Kombinationsfeld eine Prozedur für das Ereignis Nach Aktualisierung hinzu. Diese sieht wie folgt aus und prüft zunächst, ob im Kombinationsfeld überhaupt ein Datensatz ausgewählt ist. Falls ja, sucht die Prozedur mit der FindFirst-Methode des Recordsets des Formulars nach dem betroffenen Datensatz und stellt diesen ein:
Private Sub cboSchnellauswahl_AfterUpdate() If Not Nz(Me!cboSchnellauswahl, 0) = 0 Then Me.Recordset.FindFirst "ConfigurationID = " & Me!cboSchnellauswahl End If End Sub
Einstellen der Standardkonfiguration
Das Feld Default der Tabelle tblConfigurations legt fest, welche Konfiguration standardmäßig verwendet werden soll. Das bedeutet schlicht und einfach, dass diese Konfiguration beim Anlegen neuer Mailings für das Fremdschlüsselfeld ConfigurationID der Tabelle tblMailings festgelegt wird. Außerdem soll diese Konfiguration beim Öffnen des Formulars frmConfigurations standardmäßig angezeigt werden, was wir weiter oben bereits realisiert haben.
Mit dem Kontrollkästchen wollen wir dem Benutzer die Möglichkeit bieten, eine andere Konfiguration als Standardkonfiguration festzulegen. Dabei nutzen wir als Erstes die Prozedur, die durch das Ereignis Vor Aktualisierung des Kontrollkästchens chkDefault ausgelöst wird. Diese prüft, ob der Benutzer soeben den Haken aus dem Kontrollkästchen entfernt hat. Falls ja, soll eine Meldung erscheinen, die den Benutzer darauf hinweist, dass er zum Ändern der Standardkonfiguration erst zu der gewünschten Standardkonfiguration wechseln muss und diese dann mit einem Klick auf das Kontrollkästchen mit dem Text Standard festlegen kann. Das Ereignis Vor Aktualisierung nutzen wir deshalb, weil wir hier mit dem Cancel-Parameter einstellen können, dass die Änderung rückgängig gemacht wird, wenn der Benutzer das Kontrollkästchen deaktiviert hat:
Private Sub chkDefault_BeforeUpdate(Cancel As Integer) If Not Me!chkDefault Then MsgBox "Um eine andere Konfiguration zur Standardkonfiguration zu machen, aktivieren Sie diese Option für die gewünschte Konfiguration." Cancel = True End If End Sub
Wenn der Benutzer hingegen das Kontrollkästchen chkDefault aktiviert hat, soll die aktuell angezeigte Konfiguration als Standardkonfiguration eingestellt werden. In diesem Fall feuert auch noch das Ereignis Nach Aktualisierung des Kontrollkästchens, was die folgende Prozedur auslöst:
Private Sub chkDefault_AfterUpdate() Dim db As DAO.Database If Me!chkDefault Then Set db = CurrentDb db.Execute "UPDATE tblConfigurations SET Default = 0 WHERE NOT ConfigurationID = " & Me!ConfigurationID, dbFailOnError End If End Sub
Diese Prozedur prüft, ob chkDefault den Wert True hat, also ob der Benutzer das Kontrollkästchen für diesen Datensatz aktiviert hat. Falls ja, führt die Prozedur mit der Execute-Methode des Database-Objekts eine Abfrage aus, die den Wert des Feldes Default für alle anderen Datensätze der Tabelle tblConfigurations auf 0 einstellt. Damit ist sichergestellt, dass das Feld Default nur für den aktuell angezeigten Datensatz den Wert True aufweist.
Löschen einer Konfiguration
Mit einem Klick auf die Schaltfläche cmdLoeschen kann der Benutzer die aktuelle Konfiguration löschen. Dazu löst die Schaltfläche die folgende Prozedur aus. Diese löscht den aktuellen Datensatz und versucht danach, den Datensatzzeiger auf den ersten Datensatz einzustellen, dessen Feld Default den Wert True aufweist:
Private Sub cmdLoeschen_Click() RunCommand acCmdDeleteRecord Me.Recordset.FindFirst "Default = True" End Sub
Anlegen einer neuen Konfiguration
Um eine neue Konfiguration anzulegen, muss der Benutzer nur auf die Schaltfläche cmdNeu klicken. Diese springt dann zu einem neuen, leeren Datensatz:
Private Sub cmdNeu_Click() DoCmd.GoToRecord Record:=acNewRec End Sub
Schließen des Formulars
Ein Klick auf die Schaltfläche cmdOK ruft die DoCmd.Close-Methode auf und schließt das aktuelle Formular:
Private Sub cmdOK_Click() DoCmd.Close acForm, Me.Name End Sub
Wenn Sie in die Formularansicht wechseln und einen Datensatz eingegeben haben, sieht dieses wie in Bild 3 aus.
Bild 3: Das Formular frmConfigurations in der Formularansicht
Kennwort verbergen
Damit das Textfeld Password das Kennwort nicht direkt anzeigt, sondern Sternchen als Platzhalter verwendet, stellen wir die Eigenschaft Eingabeformat auf Kennwort ein.
Formular zum Verwalten der Mailings
Das Formular frmMailings dient zum Verwalten der Mailings. Es verwendet die Tabelle tblMailings als Datensatzquelle. Aus dieser Tabelle haben wir alle Felder in den Detailbereich der Entwurfsansicht gezogen.
Für die in Bild 4 markierten Felder stellen wir die Eigenschaft Horizontaler Anker auf den Wert Beide ein. So können wir die Felder vergrößern, indem wir die Breite des Formulars vergrößern. Anschließend müssen Sie die Bezeichnungsfelder dieser Steuerelemente markieren und für diese die Eigenschaft Horizontaler Anker auf Links einstellen, da diese durch die vorherige Einstellung auf Rechts festgelegt wurde.
Bild 4: Das Formulars frmMailings in der Entwurfsansicht
Eines der Felder können wir außerdem in der Höhe anpassbar machen. Das ist für das Feld TextBody am sinnvollsten. Daher stellen wir seine Eigenschaft Vertikaler Anker auf Beide ein. Auch hier müssen wir die Eigenschaft Vertikaler Anker für das entsprechende Bezeichnungsfeld wieder auf Oben festlegen. Außerdem müssen wir die Eigenschaft Vertikaler Anker für alle Felder, die sich unterhalb des Textfeldes TextBody befinden, auf Unten einstellen, da diese sonst beim Vergrößern der Höhe des Formulars vom Textfeld TextBody überlappt werden.
Die Beschriftungen der Bezeichnungsfelder wurden bisher von den Feldnamen übernommen, diese passen wir jedoch auch noch an (noch nicht im Screenshot sichtbar).
Listenfeld für die Anhänge
Sie sehen die geänderten Bezeichnungen in Bild 5. Hier sehen Sie auch, wie Sie das Textfeld für die Anzeige der Daten des Feldes Attachments in ein Listenfeld umwandeln können – und zwar über das Kontextmenü. Anschließend ändern Sie noch den Namen des Listenfeldes in lstAttachments. Leider können wir die Bindung des Listenfeldes an das Feld Attachments danach nicht mehr nutzen, denn ein Listenfeld bindet man in der Regel an eine Datensatzherkunft wie eine Tabelle oder Abfrage. Deshalb bauen wir das Listenfeld ein wenig um. Als Erstes entfernen Sie den Inhalt der Eigenschaft Steuerelementinhalt. Dann stellen Sie die Eigenschaft Herkunftstyp auf Wertliste ein. Schließlich sorgen wir dafür, dass beim Wechseln des Datensatzes im Formular der Inhalt des Feldes Attachments als Wert des Listenfeldes eingestellt wird.
Bild 5: Ändern des Textfeldes für die Anhänge in ein Listenfeld
Dazu legen wir die Prozedur Form_Current mit der folgenden Anweisung an:
Private Sub Form_Current() Me!lstAttachments.RowSource = Me!Attachments End Sub
Damit zeigt das Listenfeld bei jedem Datensatzwechsel automatisch die enthaltenen Attachments an.
Attachments hinzufügen
Dem Listenfeld lstAttachments stellen wir eine Schaltfläche namens cmdHinzufuegen zur Seite, welche die Ereignisprozedur aus Listing 1 auslöst. Diese stellen wir in ähnlicher Form im Beitrag E-Mails mit Anlagen mit Outlook versenden (www.access-im-unternehmen.de/1357) vor. Wir mussten allerdings einige Anpassungen vornehmen, da unser Listenfeld wie oben beschrieben nicht die Daten einer eigenen Tabelle oder Abfrage anzeigt, sondern den Inhalt des Feldes Attachment als Wertliste. Deshalb arbeiten wir beim Hinzufügen nicht mit der AddItem-Methode des Listenfeldes, sondern fügen die im Dateiauswahl-Dialog selektierten Daten dem Text aus dem Feld Attachments der Tabelle tblMailings hinzu, sofern die jeweilige Datei dort noch nicht enthalten ist. Für die Nutzung des Dateiauswahl-Dialogs fügen Sie dem VBA-Projekt noch einen Verweis auf die Bibliothek Microsoft Office x.0 Object Library hinzu.
Private Sub cmdHinzufuegen_Click() Dim objFileDialog As FileDialog Dim l As Long, Dim m As Long Dim bolVorhanden As Boolean Dim strAttachments As String Dim varAttachment As Variant strAttachments = Me!lstAttachments.RowSource Set objFileDialog = FileDialog(msoFileDialogFilePicker) With objFileDialog .AllowMultiSelect = True .Title = "Anlagen auswählen" .Filters.Clear .Filters.Add "Alle Dateien", "*.*" .ButtonName = "Hinzufügen" If .Show = True Then For l = 1 To .SelectedItems.Count If Not Len(Me!lstAttachments.RowSource + .SelectedItems(l)) > 32750 Then bolVorhanden = False For Each varAttachment In Split(strAttachments, ";") If varAttachment = .SelectedItems(l) Then bolVorhanden = True Exit For End If Next varAttachment If Not bolVorhanden Then strAttachments = strAttachments & ";" & .SelectedItems(l) End If If Left(strAttachments, 1) = ";" Then strAttachments = Mid(strAttachments, 2) End If Else MsgBox "Es können keine weiteren Dateien hinzugefügt werden." Exit Sub End If Next l End If End With Me!lstAttachments.RowSource = strAttachments Me!Attachments = strAttachments End Sub