Möchtest Du den gesamten Artikel lesen? Und vielleicht sogar den Artikel im PDF-Format und die Beispieldateien herunterladen? Dann hole Dir den Artikel gleich hier - völlig kostenlos!
Im Artikel “Microsoft 365 E-Mails mit Make per Klasse senden” (www.vbentwickler.de/465) und den dort referenzierten Artikeln haben wir am Beispiel von Microsoft 365 und Make.com gezeigt, wie wir per VBA E-Mails versenden können. Dazu haben wir eine Klasse programmiert, mit der wir leicht die notwendigen Daten für die E-Mail übergeben können. Im vorliegenden Artikel stellen wir nun ein Formular vor, mit dem wir leicht die Daten für eine solche E-Mail eingeben und diese schließlich absenden können. Die dazu eingegebenen Daten speichern wir in entsprechenden Tabellen, sodass wir diese später einsehen können.
Wenn man eine kleine Access-Anwendung zum Versenden von E-Mails programmieren möchte, denkt man zunächst, man würde mit einigen wenigen Tabellen auskommen. Eine zum Speichern von E-Mails und vielleicht noch eine für die Kontakte. Tatsächlich haben wir auch so angefangen, allerdings wuchs das Datenmodell dann schnell an.
Datenmodell der Beispiellösung
Wir schauen uns das Datenmodell zunächst in der Übersicht an und gehen später ins Detail (siehe Bild 1). Dass wir eine Haupttabelle zum Verwalten der einzelnen Informationen der E-Mail benötigen, ist logisch (tblEMails). Hinzu kommen aber erst einmal zwei Tabellen mit den Werten für den Content-Type (tblContentTypes) und für die Priorität (tblImportanceLevels). Eine weitere Tabelle benötigen wir für die Adressen, die wir als ReplyTo-Adressen angeben (tblReplyToContacts).
Bild 1: Datenmodell der Beispiellösung
Außerdem kann jede E-Mail einen oder mehrere To-Adressaten aufweisen und keinen, einen oder mehrere CC- oder BCC-Adressaten. Diese wollen wir komfortabel auswählen können. Also schreiben wir diese in die Tabelle tblEMailContacts.
Um diese den verschiedenen Empfängertypen der E-Mail zuordnen zu können, verwenden wir die Tabelle tblEMailsEMailContacts. Diese dient als m:n-Verknüpfungstabelle zwischen den Tabellen tblEMailContacts und tblEMails.
Um festzulegen, ob es sich um einen To-, CC- oder BCC-Empfänger handelt, enthält diese Tabelle außerdem noch ein Auswahlfeld, dessen Werte aus der Tabelle tblEMailContactTypes stammen.
Die Tabelle tblContentTypes
Wir starten mit den Lookuptabellen für die Tabelle tblEMails. Die erste ist die Tabelle tblContentTypes. Sie enthält neben dem Primärschlüsselfeld noch ein Textfeld für die anzuzeigende Bezeichnung und eines für interne Zwecke (siehe Bild 2).
Bild 2: Entwurf der Tabelle tblContentTypes
Dieser Tabelle fügen wir die Werte aus Bild 3 hinzu. Mehr benötigen wir hier nicht.
Bild 3: Werte der Tabelle tblContentTypes
Die Tabelle tblImportanceLevels
Die Tabelle tblImportanceLevels ist genauso aufgebaut wie die Tabelle tblContentTypes. Sie enthält ebenfalls ein Feld für interne Zwecke (ImportanceLevel) und eins für die Anzeige (Description) – siehe Bild 4.
Bild 4: Entwurf der Tabelle tblImportanceLevels
Hier finden wir mit Low, Normal und High beziehungsweise Niedrig, Normal und Hoch drei verschiedene Werte vor (siehe Bild 5).
Bild 5: Werte der Tabelle tblImportanceLevels
Die Tabelle tblReplyToContacts
In der Tabelle tblReplyToContacts speichern wir die Kontakte, die wir für das Feld ReplyTo verwenden wollen, also als alternative Antwortadresse zu der eigentlichen Absenderadresse. Antwort der Empfänger auf eine E-Mail mit einer Antwortadresse, wird diese entsprechend adressiert.
Die Tabelle aus speichert die E-Mailadresse und den Namen des Kontaktes in zwei getrennten Feldern (siehe Bild 6).
Bild 6: Entwurf der Tabelle tblReplyContacts
Für das Feld ContactAddress haben wir außerdem einen eindeutigen Index definiert. Auf diese Weise kann ein Kontakt nicht doppelt angelegt werden, was Redundanzen vermeidet.
Die Haupttabelle tblEMails
Damit haben wir den Grundstein für die Beschreibung der Tabelle tblEMails gelegt (siehe Bild 7).
Bild 7: Entwurf der Tabelle tblEMails
Sie enthält die üblichen Daten für eine E-Mail, also zunächst einmal den Betreff (Subject).
Für den Inhalt gibt es zwei Felder, die wir je nach der Einstellung für das Feld ContentTypeID beim Versenden heranziehen.
Das Feld BodyPlain nimmt den Inhalt für reine Text-E-Mails auf, das Feld BodyHTML den für E-Mails mit Markierungen. Damit wir diese Markierungen später im Formular hinzufügen können, haben wir das Feld mit dem Wert Rich-Text für die Eigenschaft Textformat ausgestattet.
Die übrigen Felder sind Nachschlagefelder für die Daten aus den Tabellen tblContentTypes, tblImportanceLevels und tblReplyToContacts. Diese haben wir jeweils mit den Nachschlage-Assistenten eingerichtet und Beziehungen mit referenzieller Integrität definiert.
Nach dem Anlegen eines Datensatzes sieht die Tabelle wie in Bild 8 aus.
Bild 8: Beispieldatensatz in der Tabelle tblEMails
Die Tabelle tblEMailContacts
Die Tabelle tblEMailContacts ist identisch aufgebaut wie tblReplyToContacts. Auch für diese Tabelle haben wir für das Feld ContactAddress einen eindeutigen Index definiert (siehe Bild 9).
Bild 9: Entwurf der Tabelle tblEMailContacts
Somit können wir jede E-Mail-Adresse nur einmal in dieser Tabelle speichern. Diese sieht mit einigen Daten wie in Bild 10 aus.
Bild 10: Werte der Tabelle tblEMailContacts
Die Tabelle tblEMailContactTypes
Bevor wir uns der Verknüpfungstabelle zur Zuordnung von Kontakten zu E-Mails zuwenden, legen wir noch die Tabelle tblEMailContactTypes an. Wir wollen später für jede E-Mail nach den unterschiedlichen Empfängertypen filtern können, also nach To, CC und BCC.
Diese Typen holen wir wieder aus einer Lookuptabelle, die wir wie in Bild 11 entwerfen.
Bild 11: Entwurf der Tabelle tblEMailContactTypes
Diese enthält die drei Werte To-Empfänger, CC-Empfänger und BCC-Empfänger (siehe Bild 12).
Bild 12: Werte der Tabelle tblEMailContactTypes
Die Tabelle tblEMailsEMailContacts
Damit kommen wir zur letzten Tabelle, welche die Kontakte zu den E-Mails zuordnet und gleichzeitig festlegen, ob es sich um einen To-, CC– oder BCC-Empfänger handelt.
Diese Tabelle enthält neben dem Primärschlüsselfeld jeweils ein Fremdschlüsselfeld mit Beziehung zu den Tabellen tblEMails, tblEMailContacts und tblEMailContactTypes (siehe Bild 13).
Bild 13: Entwurf der Tabelle tblEMailsEMailContacts
Für diese Tabelle haben wir außerdem einen zusammengesetzten, eindeutigen Index hinzugefügt, der sicherstellt, dass jeder Kontakt jeder E-Mail nur einmal hinzugefügt werden kann. Dieser umfasst daher die Felder EMailID und EMailContactID.
Wenn wir eine E-Mail angelegt und dieser Kontakte für die drei Kategorien von Empfängern hinzugefügt haben, liefert die Datenblattansicht der Tabelle die Werte aus Bild 14.
Bild 14: Werte der Tabelle tblEMailsEMailContacts
Die Tabelle tblAttachments
Diese Tabelle speichert die Informationen zu den Dateien, die als Anlage zu einer E-Mail hinzugefügt werden sollen (siehe Bild 15). Sie enthält ein Feld für den vollständigen Pfad sowie eines für den Dateinamen. Dieses Feld dient allein zur Anzeige im Listenfeld der Lösung. Den Pfad verwenden wir schließlich zum Hinzufügen der Datei zur E-Mail.
Bild 15: Entwurf der Tabelle tblAttachments
In Bild 16 sehen wir auch noch einige Beispielwerte für diese Tabelle in der Datenblattansicht.
Bild 16: Werte der Tabelle tblAttachments
Benutzeroberfläche zum Eingeben der E-Mail-Daten
Nun programmieren wir die Formulare, die wir zum Eingeben der Daten einer E-Mail und zum Absenden benötigen. Dazu nutzen wir zwei Formulare.
Wir schauen uns zuerst die Funktionen an, anschließend zeigen wir, wie diese programmiert werden.
Das Hauptformular heißt frmEMails und ist in Bild 17 zu sehen. Im obersten Textfeld können wir den Betreff eingeben. Darunter finden wir die Auswahl, ob wir eine reine Text-E-Mail schreiben wollen oder eine HTML-E-Mail. Je nachdem, welcher Eintrag gewählt ist, wird entweder das Feld Inhalt (Nur Text) oder Inhalt (HTML) aktiviert und das jeweils andere deaktiviert.
Bild 17: Formular zur Eingabe der E-Mail-Daten
Im Feld Inhalt (HTML) können wir den aktuell markierten Text mit individuellen Formatierungen versehen.
Darunter stellen wir die Wichtigkeit dieser E-Mail ein und wählen dazu einen der Werte Niedrig, Normal oder Hoch aus.
Anschließend folgt der Kontakt, den wir für die Eigenschaft ReplyTo hinterlegen wollen. Diesen können wir entweder aus den bestehenden Kontakten der Tabelle tblReplyToContacts auswählen oder wir klicken auf die Bearbeiten-Schaltfläche, um das Formular frmEditEMailContacts zu öffnen.
Dieses sieht wie in Bild 18 aus und zeigt alle E-Mails aus der Tabelle tblReplyToContacts an. Wir können hier eine Adresse auswählen und auf die Schaltfläche rechts neben der Liste klicken, um diese hinzuzufügen.
Bild 18: Das Formular frmEditEMailContacts
Oder wir geben unten den Namen und die E-Mail-Adresse eines Kontakts ein, den wir der Liste hinzufügen wollen.
Beim Doppelklicken auf einen der Einträge oder beim Betätigen der Schaltfläche rechts neben der Liste wird der aktuelle Eintrag in das Kombinationsfeld übernommen und das Formular geschlossen.
Empfänger auswählen
Darunter befinden sich drei Listenfelder, mit denen wir die Empfänger der drei Kategorien To, CC und BCC verwalten können.
Ein Klick auf die Plus-Schaltfläche öffnet den gleichen Dialog wie bei der ReplyTo-Adresse, allerdings werden hier nun die Einträge der Tabelle tblEMailContacts angezeigt. Hier können wir nun einen oder mehrere Einträge auswählen und mit einem Klick auf die Schaltfläche rechts zum Listenfeld hinzufügen.
Wenn mindestens ein Empfänger vorhanden ist und wir diesen entfernen wollen, können wir diesen markieren und mit einem Klick auf die entsprechende Löschen-Schaltfläche löschen.
Das Gleiche gilt für die beiden weiteren Listenfelder mit den CC- und den BCC-Empfängern.
Anlagen hinzufügen
Auch für die Anlagen einer E-Mail gibt es ein Listenfeld. Durch Anklicken der Plus-Schaltfläche öffnen wir einen Dateiauswahl-Dialog, mit dem wir ein oder mehrere Dateien auswählen können.
Diese Dateien werden anschließend im Listenfeld angezeigt.
Um eine Anlage zu entfernen, markieren wir die gewünschte Anlage und betätigen die Löschen-Schaltfläche.
Schließlich lösen wir mit der Senden-Schaltfläche die bereits im Artikel Microsoft 365 E-Mails mit Make per Klasse senden (www.vbentwickler.de/465) vorgestellte Prozedur zum Versenden einer E-Mail aus.
Programmieren des Formulars frmEMails
Das Formular frmEMails legen wir in der Entwurfsansicht wie in Bild 19 an.
Bild 19: Das Formular frmEMails in der Entwurfsansicht
Wir gehen nun Schritt für Schritt die für den Einsatz notwendigen Prozeduren durch.
Laden des Formulars und Füllen der Listenfelder
Den Start macht die Ereignisprozedur Beim Anzeigen. Sie löst diese Prozedur aus:
Private Sub Form_Current() Call RequeryBodyfields Call UpdateListboxes Me.Subject.SetFocus End Sub
Die erste aufgerufene Prozedur RequeryBodyFields aus Listing 2 prüft den Wert des Feldes ContentType.
Private Sub RequeryBodyfields() If Me.ContentTypeID = 1 Then Me.BodyPlain.Enabled = True Me.BodyHTML.Enabled = False Me.BodyPlain.VerticalAnchor = acVerticalAnchorBoth Me.BodyHTML.VerticalAnchor = acVerticalAnchorBottom Else Me.BodyPlain.Enabled = False Me.BodyHTML.Enabled = True Me.BodyPlain.VerticalAnchor = acVerticalAnchorTop Me.BodyHTML.VerticalAnchor = acVerticalAnchorBoth End If End Sub
Listing 1: Diese Prozedur aktualisiert die Steuerelemente zum Eingeben des Inhalts der E-Mail.
Hat dieser den Wert 1, wird das Textfeld BodyPlain für reine Text-E-Mails aktiviert und das Feld BodyHTML deaktiviert.
Außerdem wird VerticalAnchor für BodyPlain auf acVerticalAnchorBoth eingestellt, was bedeutet, dass dieses Feld nun beim Vergrößern des Formulars in der Höhe ebenfalls vergrößert wird. Damit dies beim Feld BodyPlain nicht ebenfalls geschieht, stellen wir hier VerticalAnchor auf acVerticalAnchorBottom ein.
Ist ContentType hingegen auf 2 eingestellt, wird BodyPlain deaktiviert und BodyHTML aktiviert und BodyHTML passt sich nun in der Höhe an das Formular an.
Listenfelder aktualisieren
Die zweite in Form_Current aufgerufene Funktion UpdateListboxes sehen wir in Listing 1.
Private Sub UpdateListboxes() Dim strSQL As String strSQL = "SELECT tblEMailsEMailContacts.EMailEMailContactID, [ContactName] & '' <'' & [ContactAddress] _ & ''>'' AS Contact FROM tblEMailContacts INNER JOIN (tblEMails INNER JOIN tblEMailsEMailContacts " _ & "ON tblEMails.EMailID = tblEMailsEMailContacts.EMailID) ON tblEMailContacts.EMailContactID = " _ & "tblEMailsEMailContacts.EMailContactID WHERE tblEMailsEMailContacts.EMailID = " & Me.EMailID _ & " AND tblEMailsEMailContacts.EMailContactTypeID = " Me.lstTo.RowSource = strSQL & " 1" Me.lstCC.RowSource = strSQL & " 2" Me.lstBCC.RowSource = strSQL & " 3" Me.lstAttachments.RowSource = "SELECT AttachmentID, AttachmentFilename FROM tblAttachments WHERE EMailID = " _ & Me.EMailID End Sub
Listing 2: Diese Prozedur aktualisiert die Listenfelder.
Sie stellt in strSQL eine SQL-Anweisung zusammen, die alle E-Mail-Kontakte liefert, die zu der aktuell angezeigten E-Mail gehören und hängt hinten noch ein unvollständiges Kriterium für EMailContactTypeID an.
Diesem fehlt noch der Vergleichswert, den wir beim Zuweisen von strSQL zur jeweiligen Datensatzherkunft der Listenfelder lstTo, lstCC und lstBCC noch hinzufügen.
Außerdem weisen wir hier die Datensatzherkunft für das Listenfeld lstAttachments zu, das alle Anlagen aus der Tabelle tblAttachments liefert, die zur aktuellen E-Mail gehören.
Fokus auf das Betreff-Feld setzen
Die dritte Anweisung in Form_Current stellt den Fokus auf das Feld Betreff ein, damit der Benutzer hier als Erstes einen Text eintragen kann.
ContentType aktualisieren
Wenn der Benutzer einen anderen Eintrag im Feld ContentType auswählt, sollen die beiden Felder BodyPlain und BodyHTML angepasst werden.
Deshalb rufen wir in der Prozedur, die durch das Ereignis Nach Aktualisierung aufgerufen wird, erneut die Routine RequeryBodyFields auf:
Private Sub ContentTypeID_AfterUpdate() Call RequeryBodyfields End Sub
Es kann sein, dass der Benutzer das Kombinationsfeld leert. Dies prüft die Ereignisprozedur Vor Aktualisierung wie folgt und gibt gegebenenfalls eine Meldung aus, dass ein Contenttyp eingestellt werden muss:
Private Sub ContentTypeID_BeforeUpdate(Cancel As Integer) If IsNull(Me.ContentTypeID) Then MsgBox "Bitte einen Contenttype einstellen.", _ vbOKOnly + vbExclamation, "Contenttype fehlt." Me.ContentTypeID.Undo Cancel = True End If End Sub
Verhindern, dass keine Wichtigkeit angegeben wird
Auf ähnliche Weise sorgt die folgende Prozedur, die durch das Ereignis Vor Aktualisierung des Feldes ImportanceLevelID ausgelöst wird, dafür, dass dieses Feld nicht geleert wird:
Private Sub ImportanceLevelID_BeforeUpdate(Cancel _ As Integer) If IsNull(Me.ImportanceLevelID) Then MsgBox "Bitte eine Wichtigkeit einstellen.", _ vbOKOnly + vbExclamation, "Wichtigkeit fehlt." Me.ImportanceLevelID.Undo Cancel = True End If End Sub
ReplyTo-Kontakt hinzufügen
Wenn der Benutzer die Schaltfläche zum Bearbeiten der ReplyTo-Kontakte cmdEditReplyTo anklickt, löst er die folgende Prozedur aus:
Private Sub cmdEditReplyTo_Click() If CheckNewRecord = False Then Exit Sub DoCmd.OpenForm "frmEditEMailContacts", _ WindowMode:=acDialog, OpenArgs:="4|" & Me.EMailID Me.ReplyToID.Requery End Sub
Diese ruft zuerst die Funktion CheckNewRecord auf. War der Aufruf erfolgreich öffnet sie das Formular frmEditMailContacts und übergibt als Öffnungsargument eine Zeichenkette bestehend aus der Zahl 4, einem Pipe-Zeichen (|) und der aktuellen EMailID.
Dort werden die Kontakte bearbeitet und nach dem Schließen des Formulars wird das Kombinationsfeld ReplyToID aktualisiert. Wie das im Detail aussieht, sehen wir weiter unten bei der Beschreibung des Formulars frmEditEMailContacts.
Prüfen, ob ein neuer Datensatz vorliegt
Wenn wir einen neuen Kontakt zu der aktuellen E-Mail hinzufügen wollen, öffnen wir dazu das Formular frmEditEMailContacts. Hier würden wir im Normalfall mindestens einen Kontakt auswählen, der dann über einen neuen Datensatz in der Tabelle tblEMailsEMailContacts der aktuellen E-Mail zugewiesen wird. Das ist jedoch nur möglich, wenn im Hauptformular bereits ein gespeicherter Datensatz mit einer E-Mail vorhanden ist.
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