{"id":55000466,"date":"2025-06-01T00:00:00","date_gmt":"2025-08-27T12:14:47","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=466"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Microsoft_365_EMails_per_AccessFormular_senden","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/Microsoft_365_EMails_per_AccessFormular_senden\/","title":{"rendered":"Microsoft 365- E-Mails per Access-Formular senden"},"content":{"rendered":"<p><b>Im Artikel &#8220;Microsoft 365 E-Mails mit Make per Klasse senden&#8221; (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&ouml;nnen. Dazu haben wir eine Klasse programmiert, mit der wir leicht die notwendigen Daten f&uuml;r die E-Mail &uuml;bergeben k&ouml;nnen. Im vorliegenden Artikel stellen wir nun ein Formular vor, mit dem wir leicht die Daten f&uuml;r eine solche E-Mail eingeben und diese schlie&szlig;lich absenden k&ouml;nnen. Die dazu eingegebenen Daten speichern wir in entsprechenden Tabellen, sodass wir diese sp&auml;ter einsehen k&ouml;nnen.<\/b><\/p>\n<p>Wenn man eine kleine Access-Anwendung zum Versenden von E-Mails programmieren m&ouml;chte, denkt man zun&auml;chst, man w&uuml;rde mit einigen wenigen Tabellen auskommen. Eine zum Speichern von E-Mails und vielleicht noch eine f&uuml;r die Kontakte. Tats&auml;chlich haben wir auch so angefangen, allerdings wuchs das Datenmodell dann schnell an.<\/p>\n<h2>Datenmodell der Beispiell&ouml;sung<\/h2>\n<p>Wir schauen uns das Datenmodell zun&auml;chst in der &Uuml;bersicht an und gehen sp&auml;ter ins Detail (siehe Bild 1). Dass wir eine Haupttabelle zum Verwalten der einzelnen Informationen der E-Mail ben&ouml;tigen, ist logisch (<b>tblEMails<\/b>). Hinzu kommen aber erst einmal zwei Tabellen mit den Werten f&uuml;r den Content-Type (<b>tblContentTypes<\/b>) und f&uuml;r die Priorit&auml;t (<b>tblImportanceLevels<\/b>). Eine weitere Tabelle ben&ouml;tigen wir f&uuml;r die Adressen, die wir als ReplyTo-Adressen angeben (<b>tblReplyToContacts<\/b>).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_466_001.png\" alt=\"Datenmodell der Beispiell&ouml;sung\" width=\"700\" height=\"297,9615\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Datenmodell der Beispiell&ouml;sung<\/span><\/b><\/p>\n<p>Au&szlig;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&auml;hlen k&ouml;nnen. Also schreiben wir diese in die Tabelle <b>tblEMailContacts<\/b>.<\/p>\n<p>Um diese den verschiedenen Empf&auml;ngertypen der E-Mail zuordnen zu k&ouml;nnen, verwenden wir die Tabelle <b>tblEMailsEMailContacts<\/b>. Diese dient als m:n-Verkn&uuml;pfungstabelle zwischen den Tabellen <b>tblEMailContacts <\/b>und <b>tblEMails<\/b>.<\/p>\n<p>Um festzulegen, ob es sich um einen To-, CC- oder BCC-Empf&auml;nger handelt, enth&auml;lt diese Tabelle au&szlig;erdem noch ein Auswahlfeld, dessen Werte aus der Tabelle <b>tblEMailContactTypes <\/b>stammen.<\/p>\n<h2>Die Tabelle tblContentTypes<\/h2>\n<p>Wir starten mit den Lookuptabellen f&uuml;r die Tabelle <b>tblEMails<\/b>. Die erste ist die Tabelle <b>tblContentTypes<\/b>. Sie enth&auml;lt neben dem Prim&auml;rschl&uuml;sselfeld noch ein Textfeld f&uuml;r die anzuzeigende Bezeichnung und eines f&uuml;r interne Zwecke (siehe Bild 2).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_466_002.png\" alt=\"Entwurf der Tabelle tblContentTypes\" width=\"524,6265\" height=\"125,4343\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Entwurf der Tabelle tblContentTypes<\/span><\/b><\/p>\n<p>Dieser Tabelle f&uuml;gen wir die Werte aus Bild 3 hinzu. Mehr ben&ouml;tigen wir hier nicht.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_466_003.png\" alt=\"Werte der Tabelle tblContentTypes\" width=\"424,6267\" height=\"149,9926\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Werte der Tabelle tblContentTypes<\/span><\/b><\/p>\n<h2>Die Tabelle tblImportanceLevels<\/h2>\n<p>Die Tabelle <b>tblImportanceLevels <\/b>ist genauso aufgebaut wie die Tabelle <b>tblContentTypes<\/b>. Sie enth&auml;lt ebenfalls ein Feld f&uuml;r interne Zwecke (<b>ImportanceLevel<\/b>) und eins f&uuml;r die Anzeige (<b>Description<\/b>) &#8211; siehe Bild 4.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_466_004.png\" alt=\"Entwurf der Tabelle tblImportanceLevels\" width=\"524,6265\" height=\"127,7113\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Entwurf der Tabelle tblImportanceLevels<\/span><\/b><\/p>\n<p>Hier finden wir mit <b>Low<\/b>, <b>Normal <\/b>und <b>High <\/b>beziehungsweise <b>Niedrig<\/b>, <b>Normal <\/b>und <b>Hoch <\/b>drei verschiedene Werte vor (siehe Bild 5).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_466_005.png\" alt=\"Werte der Tabelle tblImportanceLevels\" width=\"424,6267\" height=\"175,4326\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Werte der Tabelle tblImportanceLevels<\/span><\/b><\/p>\n<h2>Die Tabelle tblReplyToContacts<\/h2>\n<p>In der Tabelle <b>tblReplyToContacts <\/b>speichern wir die Kontakte, die wir f&uuml;r das Feld <b>ReplyTo <\/b>verwenden wollen, also als alternative Antwortadresse zu der eigentlichen Absenderadresse. Antwort der Empf&auml;nger auf eine E-Mail mit einer Antwortadresse, wird diese entsprechend adressiert.<\/p>\n<p>Die Tabelle aus speichert die E-Mailadresse und den Namen des Kontaktes in zwei getrennten Feldern (siehe Bild 6).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_466_006.png\" alt=\"Entwurf der Tabelle tblReplyContacts\" width=\"499,6267\" height=\"342,7971\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Entwurf der Tabelle tblReplyContacts<\/span><\/b><\/p>\n<p>F&uuml;r das Feld <b>ContactAddress <\/b>haben wir au&szlig;erdem einen eindeutigen Index definiert. Auf diese Weise kann ein Kontakt nicht doppelt angelegt werden, was Redundanzen vermeidet.<\/p>\n<h2>Die Haupttabelle tblEMails<\/h2>\n<p>Damit haben wir den Grundstein f&uuml;r die Beschreibung der Tabelle <b>tblEMails<\/b> gelegt (siehe Bild 7).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_466_007.png\" alt=\"Entwurf der Tabelle tblEMails\" width=\"574,6265\" height=\"443,6191\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Entwurf der Tabelle tblEMails<\/span><\/b><\/p>\n<p>Sie enth&auml;lt die &uuml;blichen Daten f&uuml;r eine E-Mail, also zun&auml;chst einmal den Betreff (<b>Subject<\/b>).<\/p>\n<p>F&uuml;r den Inhalt gibt es zwei Felder, die wir je nach der Einstellung f&uuml;r das Feld <b>ContentTypeID <\/b>beim Versenden heranziehen.<\/p>\n<p>Das Feld <b>BodyPlain <\/b>nimmt den Inhalt f&uuml;r reine Text-E-Mails auf, das Feld <b>BodyHTML <\/b>den f&uuml;r E-Mails mit Markierungen. Damit wir diese Markierungen sp&auml;ter im Formular hinzuf&uuml;gen k&ouml;nnen, haben wir das Feld mit dem Wert <b>Rich-Text <\/b>f&uuml;r die Eigenschaft <b>Textformat <\/b>ausgestattet.<\/p>\n<p>Die &uuml;brigen Felder sind Nachschlagefelder f&uuml;r die Daten aus den Tabellen <b>tblContentTypes<\/b>, <b>tblImportanceLevels <\/b>und <b>tblReplyToContacts<\/b>. Diese haben wir jeweils mit den Nachschlage-Assistenten eingerichtet und Beziehungen mit referenzieller Integrit&auml;t definiert.<\/p>\n<p>Nach dem Anlegen eines Datensatzes sieht die Tabelle wie in Bild 8 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_466_008.png\" alt=\"Beispieldatensatz in der Tabelle tblEMails\" width=\"700\" height=\"212,6096\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 8: Beispieldatensatz in der Tabelle tblEMails<\/span><\/b><\/p>\n<h2>Die Tabelle tblEMailContacts<\/h2>\n<p>Die Tabelle <b>tblEMailContacts <\/b>ist identisch aufgebaut wie <b>tblReplyToContacts<\/b>. Auch f&uuml;r diese Tabelle haben wir f&uuml;r das Feld <b>ContactAddress <\/b>einen eindeutigen Index definiert (siehe Bild 9).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_466_009.png\" alt=\"Entwurf der Tabelle tblEMailContacts\" width=\"499,6267\" height=\"359,7995\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 9: Entwurf der Tabelle tblEMailContacts<\/span><\/b><\/p>\n<p>Somit k&ouml;nnen wir jede E-Mail-Adresse nur einmal in dieser Tabelle speichern. Diese sieht mit einigen Daten wie in Bild 10 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_466_010.png\" alt=\"Werte der Tabelle tblEMailContacts\" width=\"499,6267\" height=\"143,2377\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 10: Werte der Tabelle tblEMailContacts<\/span><\/b><\/p>\n<h2>Die Tabelle tblEMailContactTypes<\/h2>\n<p>Bevor wir uns der Verkn&uuml;pfungstabelle zur Zuordnung von Kontakten zu E-Mails zuwenden, legen wir noch die Tabelle <b>tblEMailContactTypes <\/b>an. Wir wollen sp&auml;ter f&uuml;r jede E-Mail nach den unterschiedlichen Empf&auml;ngertypen filtern k&ouml;nnen, also nach <b>To<\/b>, <b>CC <\/b>und <b>BCC<\/b>.<\/p>\n<p>Diese Typen holen wir wieder aus einer Lookuptabelle, die wir wie in Bild 11 entwerfen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_466_011.png\" alt=\"Entwurf der Tabelle tblEMailContactTypes\" width=\"499,6267\" height=\"95,5526\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 11: Entwurf der Tabelle tblEMailContactTypes<\/span><\/b><\/p>\n<p>Diese enth&auml;lt die drei Werte <b>To-Empf&auml;nger<\/b>, <b>CC-Empf&auml;nger <\/b>und <b>BCC-Empf&auml;nger <\/b>(siehe Bild 12).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_466_012.png\" alt=\"Werte der Tabelle tblEMailContactTypes\" width=\"249,6268\" height=\"146,5046\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 12: Werte der Tabelle tblEMailContactTypes<\/span><\/b><\/p>\n<h2>Die Tabelle tblEMailsEMailContacts<\/h2>\n<p>Damit kommen wir zur letzten Tabelle, welche die Kontakte zu den E-Mails zuordnet und gleichzeitig festlegen, ob es sich um einen <b>To<\/b>-, <b>CC<\/b>&#8211; oder <b>BCC<\/b>-Empf&auml;nger handelt.<\/p>\n<p>Diese Tabelle enth&auml;lt neben dem Prim&auml;rschl&uuml;sselfeld jeweils ein Fremdschl&uuml;sselfeld mit Beziehung zu den Tabellen <b>tblEMails<\/b>, <b>tblEMailContacts <\/b>und <b>tblEMailContactTypes<\/b> (siehe Bild 13).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_466_013.png\" alt=\"Entwurf der Tabelle tblEMailsEMailContacts\" width=\"599,6265\" height=\"368,3308\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 13: Entwurf der Tabelle tblEMailsEMailContacts<\/span><\/b><\/p>\n<p>F&uuml;r diese Tabelle haben wir au&szlig;erdem einen zusammengesetzten, eindeutigen Index hinzugef&uuml;gt, der sicherstellt, dass jeder Kontakt jeder E-Mail nur einmal hinzugef&uuml;gt werden kann. Dieser umfasst daher die Felder <b>EMailID <\/b>und <b>EMailContactID<\/b>.<\/p>\n<p>Wenn wir eine E-Mail angelegt und dieser Kontakte f&uuml;r die drei Kategorien von Empf&auml;ngern hinzugef&uuml;gt haben, liefert die Datenblattansicht der Tabelle die Werte aus Bild 14.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_466_014.png\" alt=\"Werte der Tabelle tblEMailsEMailContacts\" width=\"549,6265\" height=\"170,7032\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 14: Werte der Tabelle tblEMailsEMailContacts<\/span><\/b><\/p>\n<h2>Die Tabelle tblAttachments<\/h2>\n<p>Diese Tabelle speichert die Informationen zu den Dateien, die als Anlage zu einer E-Mail hinzugef&uuml;gt werden sollen (siehe Bild 15). Sie enth&auml;lt ein Feld f&uuml;r den vollst&auml;ndigen Pfad sowie eines f&uuml;r den Dateinamen. Dieses Feld dient allein zur Anzeige im Listenfeld der L&ouml;sung. Den Pfad verwenden wir schlie&szlig;lich zum Hinzuf&uuml;gen der Datei zur E-Mail.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_466_018.png\" alt=\"Entwurf der Tabelle tblAttachments\" width=\"549,6265\" height=\"128,1388\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 15: Entwurf der Tabelle tblAttachments<\/span><\/b><\/p>\n<p>In Bild 16 sehen wir auch noch einige Beispielwerte f&uuml;r diese Tabelle in der Datenblattansicht.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_466_019.png\" alt=\"Werte der Tabelle tblAttachments\" width=\"549,6265\" height=\"144,0688\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 16: Werte der Tabelle tblAttachments<\/span><\/b><\/p>\n<h2>Benutzeroberfl&auml;che zum Eingeben der E-Mail-Daten<\/h2>\n<p>Nun programmieren wir die Formulare, die wir zum Eingeben der Daten einer E-Mail und zum Absenden ben&ouml;tigen. Dazu nutzen wir zwei Formulare.<\/p>\n<p>Wir schauen uns zuerst die Funktionen an, anschlie&szlig;end zeigen wir, wie diese programmiert werden.<\/p>\n<p>Das Hauptformular hei&szlig;t <b>frmEMails<\/b> und ist in Bild 17 zu sehen. Im obersten Textfeld k&ouml;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&auml;hlt ist, wird entweder das Feld <b>Inhalt (Nur Text) <\/b>oder <b>Inhalt (HTML) <\/b>aktiviert und das jeweils andere deaktiviert.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_466_015.png\" alt=\"Formular zur Eingabe der E-Mail-Daten\" width=\"549,6265\" height=\"651,9709\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 17: Formular zur Eingabe der E-Mail-Daten<\/span><\/b><\/p>\n<p>Im Feld <b>Inhalt (HTML) <\/b>k&ouml;nnen wir den aktuell markierten Text mit individuellen Formatierungen versehen.<\/p>\n<p>Darunter stellen wir die Wichtigkeit dieser E-Mail ein und w&auml;hlen dazu einen der Werte <b>Niedrig<\/b>, <b>Normal <\/b>oder <b>Hoch <\/b>aus.<\/p>\n<p>Anschlie&szlig;end folgt der Kontakt, den wir f&uuml;r die Eigenschaft <b>ReplyTo <\/b>hinterlegen wollen. Diesen k&ouml;nnen wir entweder aus den bestehenden Kontakten der Tabelle <b>tblReplyToContacts <\/b>ausw&auml;hlen oder wir klicken auf die <b>Bearbeiten<\/b>-Schaltfl&auml;che, um das Formular <b>frmEditEMailContacts <\/b>zu &ouml;ffnen.<\/p>\n<p>Dieses sieht wie in Bild 18 aus und zeigt alle E-Mails aus der Tabelle <b>tblReplyToContacts <\/b>an. Wir k&ouml;nnen hier eine Adresse ausw&auml;hlen und auf die Schaltfl&auml;che rechts neben der Liste klicken, um diese hinzuzuf&uuml;gen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_466_016.png\" alt=\"Das Formular frmEditEMailContacts\" width=\"424,6267\" height=\"203,1581\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 18: Das Formular frmEditEMailContacts<\/span><\/b><\/p>\n<p>Oder wir geben unten den Namen und die E-Mail-Adresse eines Kontakts ein, den wir der Liste hinzuf&uuml;gen wollen.<\/p>\n<p>Beim Doppelklicken auf einen der Eintr&auml;ge oder beim Bet&auml;tigen der Schaltfl&auml;che rechts neben der Liste wird der aktuelle Eintrag in das Kombinationsfeld &uuml;bernommen und das Formular geschlossen.<\/p>\n<h2>Empf&auml;nger ausw&auml;hlen<\/h2>\n<p>Darunter befinden sich drei Listenfelder, mit denen wir die Empf&auml;nger der drei Kategorien To, CC und BCC verwalten k&ouml;nnen.<\/p>\n<p>Ein Klick auf die Plus-Schaltfl&auml;che &ouml;ffnet den gleichen Dialog wie bei der <b>ReplyTo<\/b>-Adresse, allerdings werden hier nun die Eintr&auml;ge der Tabelle <b>tblEMailContacts <\/b>angezeigt. Hier k&ouml;nnen wir nun einen oder mehrere Eintr&auml;ge ausw&auml;hlen und mit einem Klick auf die Schaltfl&auml;che rechts zum Listenfeld hinzuf&uuml;gen.<\/p>\n<p>Wenn mindestens ein Empf&auml;nger vorhanden ist und wir diesen entfernen wollen, k&ouml;nnen wir diesen markieren und mit einem Klick auf die entsprechende L&ouml;schen-Schaltfl&auml;che l&ouml;schen.<\/p>\n<p>Das Gleiche gilt f&uuml;r die beiden weiteren Listenfelder mit den CC- und den BCC-Empf&auml;ngern.<\/p>\n<h2>Anlagen hinzuf&uuml;gen<\/h2>\n<p>Auch f&uuml;r die Anlagen einer E-Mail gibt es ein Listenfeld. Durch Anklicken der Plus-Schaltfl&auml;che &ouml;ffnen wir einen Dateiauswahl-Dialog, mit dem wir ein oder mehrere Dateien ausw&auml;hlen k&ouml;nnen.<\/p>\n<p>Diese Dateien werden anschlie&szlig;end im Listenfeld angezeigt.<\/p>\n<p>Um eine Anlage zu entfernen, markieren wir die gew&uuml;nschte Anlage und bet&auml;tigen die L&ouml;schen-Schaltfl&auml;che.<\/p>\n<p>Schlie&szlig;lich l&ouml;sen wir mit der <b>Senden<\/b>-Schaltfl&auml;che die bereits im Artikel <b>Microsoft 365 E-Mails mit Make per Klasse senden <\/b>(<b>www.vbentwickler.de\/465<\/b>) vorgestellte Prozedur zum Versenden einer E-Mail aus. <\/p>\n<h2>Programmieren des Formulars frmEMails<\/h2>\n<p>Das Formular <b>frmEMails <\/b>legen wir in der Entwurfsansicht wie in Bild 19 an.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_466_017.png\" alt=\"Das Formular frmEMails in der Entwurfsansicht\" width=\"549,6265\" height=\"679,4885\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 19: Das Formular frmEMails in der Entwurfsansicht<\/span><\/b><\/p>\n<p>Wir gehen nun Schritt f&uuml;r Schritt die f&uuml;r den Einsatz notwendigen Prozeduren durch.<\/p>\n<h2>Laden des Formulars und F&uuml;llen der Listenfelder<\/h2>\n<p>Den Start macht die Ereignisprozedur <b>Beim Anzeigen<\/b>. Sie l&ouml;st diese Prozedur aus:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Current()\r\n     <span style=\"color:blue;\">Call<\/span> RequeryBodyfields\r\n     <span style=\"color:blue;\">Call<\/span> UpdateListboxes\r\n     Me.Subject.SetFocus\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Die erste aufgerufene Prozedur <b>RequeryBodyFields <\/b>aus Listing 2 pr&uuml;ft den Wert des Feldes <b>ContentType<\/b>.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>RequeryBodyfields()\r\n     <span style=\"color:blue;\">If <\/span>Me.ContentTypeID = 1<span style=\"color:blue;\"> Then<\/span>\r\n         Me.BodyPlain.Enabled = <span style=\"color:blue;\">True<\/span>\r\n         Me.BodyHTML.Enabled = <span style=\"color:blue;\">False<\/span>\r\n         Me.BodyPlain.VerticalAnchor = acVerticalAnchorBoth\r\n         Me.BodyHTML.VerticalAnchor = acVerticalAnchorBottom\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         Me.BodyPlain.Enabled = <span style=\"color:blue;\">False<\/span>\r\n         Me.BodyHTML.Enabled = <span style=\"color:blue;\">True<\/span>\r\n         Me.BodyPlain.VerticalAnchor = acVerticalAnchorTop\r\n         Me.BodyHTML.VerticalAnchor = acVerticalAnchorBoth\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Diese Prozedur aktualisiert die Steuerelemente zum Eingeben des Inhalts der E-Mail.<\/span><\/b><\/p>\n<p>Hat dieser den Wert <b>1<\/b>, wird das Textfeld <b>BodyPlain <\/b>f&uuml;r reine Text-E-Mails aktiviert und das Feld <b>BodyHTML <\/b>deaktiviert.<\/p>\n<p>Au&szlig;erdem wird <b>VerticalAnchor <\/b>f&uuml;r <b>BodyPlain <\/b>auf <b>acVerticalAnchorBoth <\/b>eingestellt, was bedeutet, dass dieses Feld nun beim Vergr&ouml;&szlig;ern des Formulars in der H&ouml;he ebenfalls vergr&ouml;&szlig;ert wird. Damit dies beim Feld <b>BodyPlain <\/b>nicht ebenfalls geschieht, stellen wir hier <b>VerticalAnchor <\/b>auf <b>acVerticalAnchorBottom <\/b>ein.<\/p>\n<p>Ist <b>ContentType <\/b>hingegen auf <b>2 <\/b>eingestellt, wird <b>BodyPlain <\/b>deaktiviert und <b>BodyHTML <\/b>aktiviert und <b>BodyHTML <\/b>passt sich nun in der H&ouml;he an das Formular an.<\/p>\n<h2>Listenfelder aktualisieren<\/h2>\n<p>Die zweite in <b>Form_Current <\/b>aufgerufene Funktion <b>UpdateListboxes<\/b> sehen wir in Listing 1.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>UpdateListboxes()\r\n     <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n     strSQL = \"SELECT tblEMailsEMailContacts.EMailEMailContactID, [ContactName] & '' &lt;'' & [ContactAddress] _\r\n         & ''&gt;'' AS Contact FROM tblEMailContacts INNER JOIN (tblEMails INNER JOIN tblEMailsEMailContacts \" _\r\n         &  \"ON tblEMails.EMailID = tblEMailsEMailContacts.EMailID) ON tblEMailContacts.EMailContactID = \" _\r\n         & \"tblEMailsEMailContacts.EMailContactID WHERE tblEMailsEMailContacts.EMailID = \" & Me.EMailID _\r\n         & \" AND tblEMailsEMailContacts.EMailContactTypeID = \"\r\n     Me.lstTo.RowSource = strSQL & \" 1\"\r\n     Me.lstCC.RowSource = strSQL & \" 2\"\r\n     Me.lstBCC.RowSource = strSQL & \" 3\"\r\n     Me.lstAttachments.RowSource = \"SELECT AttachmentID, AttachmentFilename FROM tblAttachments WHERE EMailID = \" _\r\n         & Me.EMailID\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Diese Prozedur aktualisiert die Listenfelder.<\/span><\/b><\/p>\n<p>Sie stellt in <b>strSQL <\/b>eine SQL-Anweisung zusammen, die alle E-Mail-Kontakte liefert, die zu der aktuell angezeigten E-Mail geh&ouml;ren und h&auml;ngt hinten noch ein unvollst&auml;ndiges Kriterium f&uuml;r <b>EMailContactTypeID <\/b>an.<\/p>\n<p>Diesem fehlt noch der Vergleichswert, den wir beim Zuweisen von <b>strSQL <\/b>zur jeweiligen Datensatzherkunft der Listenfelder <b>lstTo<\/b>, <b>lstCC <\/b>und <b>lstBCC <\/b>noch hinzuf&uuml;gen.<\/p>\n<p>Au&szlig;erdem weisen wir hier die Datensatzherkunft f&uuml;r das Listenfeld <b>lstAttachments <\/b>zu, das alle Anlagen aus der Tabelle <b>tblAttachments <\/b>liefert, die zur aktuellen E-Mail geh&ouml;ren.<\/p>\n<h2>Fokus auf das Betreff-Feld setzen<\/h2>\n<p>Die dritte Anweisung in <b>Form_Current <\/b>stellt den Fokus auf das Feld <b>Betreff <\/b>ein, damit der Benutzer hier als Erstes einen Text eintragen kann.<\/p>\n<h2>ContentType aktualisieren<\/h2>\n<p>Wenn der Benutzer einen anderen Eintrag im Feld <b>ContentType <\/b>ausw&auml;hlt, sollen die beiden Felder <b>BodyPlain <\/b>und <b>BodyHTML <\/b>angepasst werden.<\/p>\n<p>Deshalb rufen wir in der Prozedur, die durch das Ereignis <b>Nach Aktualisierung <\/b>aufgerufen wird, erneut die Routine <b>RequeryBodyFields <\/b>auf:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>ContentTypeID_AfterUpdate()\r\n     <span style=\"color:blue;\">Call<\/span> RequeryBodyfields\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Es kann sein, dass der Benutzer das Kombinationsfeld leert. Dies pr&uuml;ft die Ereignisprozedur <b>Vor Aktualisierung <\/b>wie folgt und gibt gegebenenfalls eine Meldung aus, dass ein Contenttyp eingestellt werden muss:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>ContentTypeID_BeforeUpdate(Cancel<span style=\"color:blue;\"> As Integer<\/span>)\r\n     <span style=\"color:blue;\">If <\/span>IsNull(Me.ContentTypeID)<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Bitte einen Contenttype einstellen.\", _\r\n             vbOKOnly + vbExclamation, \"Contenttype fehlt.\"\r\n         Me.ContentTypeID.Undo\r\n         Cancel = <span style=\"color:blue;\">True<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Verhindern, dass keine Wichtigkeit angegeben wird<\/h2>\n<p>Auf &auml;hnliche Weise sorgt die folgende Prozedur, die durch das Ereignis <b>Vor Aktualisierung<\/b> des Feldes <b>ImportanceLevelID<\/b> ausgel&ouml;st wird, daf&uuml;r, dass dieses Feld nicht geleert wird:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>ImportanceLevelID_BeforeUpdate(Cancel _\r\n        <span style=\"color:blue;\"> As Integer<\/span>)\r\n     <span style=\"color:blue;\">If <\/span>IsNull(Me.ImportanceLevelID)<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Bitte eine Wichtigkeit einstellen.\", _\r\n             vbOKOnly + vbExclamation, \"Wichtigkeit fehlt.\"\r\n         Me.ImportanceLevelID.Undo\r\n         Cancel = <span style=\"color:blue;\">True<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>ReplyTo-Kontakt hinzuf&uuml;gen<\/h2>\n<p>Wenn der Benutzer die Schaltfl&auml;che zum Bearbeiten der ReplyTo-Kontakte <b>cmdEditReplyTo <\/b>anklickt, l&ouml;st er die folgende Prozedur aus:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdEditReplyTo_Click()\r\n     <span style=\"color:blue;\">If <\/span>CheckNewRecord = <span style=\"color:blue;\">False<\/span><span style=\"color:blue;\"> Then<\/span> <span style=\"color:blue;\">Exit Sub<\/span>\r\n     DoCmd.OpenForm \"frmEditEMailContacts\", _\r\n         WindowMode:=acDialog, OpenArgs:=\"4|\" & Me.EMailID\r\n     Me.ReplyToID.Requery\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Diese ruft zuerst die Funktion <b>CheckNewRecord <\/b>auf.  War der Aufruf erfolgreich &ouml;ffnet sie das Formular <b>frmEditMailContacts<\/b> und &uuml;bergibt als &Ouml;ffnungsargument eine Zeichenkette bestehend aus der Zahl <b>4<\/b>, einem Pipe-Zeichen (<b>|<\/b>) und der aktuellen <b>EMailID<\/b>.<\/p>\n<p>Dort werden die Kontakte bearbeitet und nach dem Schlie&szlig;en des Formulars wird das Kombinationsfeld <b>ReplyToID <\/b>aktualisiert. Wie das im Detail aussieht, sehen wir weiter unten bei der Beschreibung des Formulars <b>frmEditEMailContacts<\/b>.<\/p>\n<h2>Pr&uuml;fen, ob ein neuer Datensatz vorliegt<\/h2>\n<p>Wenn wir einen neuen Kontakt zu der aktuellen E-Mail hinzuf&uuml;gen wollen, &ouml;ffnen wir dazu das Formular <b>frmEditEMailContacts<\/b>. Hier w&uuml;rden wir im Normalfall mindestens einen Kontakt ausw&auml;hlen, der dann &uuml;ber einen neuen Datensatz in der Tabelle <b>tblEMailsEMailContacts <\/b>der aktuellen E-Mail zugewiesen wird. Das ist jedoch nur m&ouml;glich, wenn im Hauptformular bereits ein gespeicherter Datensatz mit einer E-Mail vorhanden ist.<\/p>\n<p>Deshalb rufen wir gleich zu Beginn die Funktion <b>CheckNewRecord <\/b>auf (siehe Listing 3). Diese pr&uuml;ft als Erstes, ob es sich bei dem aktuellen Datensatz im Formular <b>frmEMails <\/b>um einen neuen, leeren Datensatz handelt.<\/p>\n<pre><span style=\"color:blue;\">Private Function <\/span>CheckNewRecord()<span style=\"color:blue;\"> As Boolean<\/span>\r\n     <span style=\"color:blue;\">If <\/span>Me.NewRecord = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">If <\/span>Me.Dirty = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n             Me.Dirty = <span style=\"color:blue;\">False<\/span>\r\n             CheckNewRecord = <span style=\"color:blue;\">True<\/span>\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             <span style=\"color:blue;\">MsgBox<\/span> \"Bitte erst einen Betreff angeben.\", vbOKOnly + vbExclamation, \"Betreff fehlt\"\r\n             Me.Subject.SetFocus\r\n             CheckNewRecord = <span style=\"color:blue;\">False<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         Me.Dirty = <span style=\"color:blue;\">False<\/span>\r\n         CheckNewRecord = <span style=\"color:blue;\">True<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Pr&uuml;fen, ob ein speicherbarer Datensatz vorliegt<\/span><\/b><\/p>\n<p>Falls ja, folgt eine zweite Pr&uuml;fung, ob dieser bereits in Bearbeitung ist (<b>Me.Dirty = True<\/b>). Ist auch das der Fall, wurde der Datensatz also bereits bearbeitet und wir k&ouml;nnen diesen speichern (mit <b>Me.Dirty = False<\/b>).<\/p>\n<p>In diesem Fall soll <b>CheckNewRecord <\/b>den Wert <b>True <\/b>zur&uuml;ckliefern.<\/p>\n<p>Ist der Datensatz noch nicht bearbeitet, erscheint die Meldung, dass zun&auml;chst ein Betreff angegeben werden muss. Au&szlig;erdem wird der Fokus auf das Textfeld <b>Subject <\/b>gesetzt und <b>CheckNewRecord <\/b>liefert <b>False <\/b>zur&uuml;ck.<\/p>\n<p>Es kann auch sein, dass wir es mit einem bereits gespeicherten Datensatz zu tun haben &#8211; dann speichern wir den Datensatz mit <b>Me.Dirty = False <\/b>und geben <b>CheckNewRecord = True <\/b>zur&uuml;ck.<\/p>\n<h2>To-Empf&auml;nger hinzuf&uuml;gen<\/h2>\n<p>Die <b>Plus<\/b>-Schaltfl&auml;che neben dem Listenfeld <b>lstToRecipients <\/b>ruft zun&auml;chst ebenfalls die <b>CheckNewRecord <\/b>auf.<\/p>\n<p>Liefert diese den Wert <b>True <\/b>zur&uuml;ck, &ouml;ffnet die Prozedur das Formular <b>frmEditEMailContacts <\/b>und &uuml;bergibt diesmal ein &Ouml;ffnungsargument, das als ersten Teil den Wert <b>1 <\/b>und als zweiten die aktuelle <b>EMailID <\/b>enth&auml;lt. Was in diesem Formular geschieht, beschreiben wir ebenfalls weiter unten. Nach dem Hinzuf&uuml;gen der gew&uuml;nschten Kontakte &uuml;ber dieses Formular l&auml;uft die aufrufende Prozedur weiter und aktualisiert die Anzeige im Listenfeld.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdAddTo_Click()\r\n     <span style=\"color:blue;\">If <\/span>CheckNewRecord = <span style=\"color:blue;\">False<\/span><span style=\"color:blue;\"> Then<\/span> <span style=\"color:blue;\">Exit Sub<\/span>\r\n     DoCmd.OpenForm \"frmEditEMailContacts\", WindowMode:=acDialog, OpenArgs:=\"1|\" & Me.EMailID\r\n     Me.lstTo.Requery\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>CC-Empf&auml;nger hinzuf&uuml;gen<\/h2>\n<p>Das Hinzuf&uuml;gen von CC-Empf&auml;ngern funktioniert auf die gleiche Weise. Diesmal &uuml;bergeben wir beim Aufrufen des Formulars <b>frmEditEMailContacts <\/b>allerdings als ersten Wert des &Ouml;ffnungsarguments den Wert <b>2 <\/b>(f&uuml;r <b>CC<\/b>).<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdAddCC_Click()\r\n     <span style=\"color:blue;\">If <\/span>CheckNewRecord = <span style=\"color:blue;\">False<\/span><span style=\"color:blue;\"> Then<\/span> <span style=\"color:blue;\">Exit Sub<\/span>\r\n     DoCmd.OpenForm \"frmEditEMailContacts\", _\r\n         WindowMode:=acDialog, OpenArgs:=\"2|\" & Me.EMailID\r\n     Me.lstCC.Requery\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>BCC-Empf&auml;nger hinzuf&uuml;gen<\/h2>\n<p>Schlie&szlig;lich fehlt noch das Hinzuf&uuml;gen von BCC-Empf&auml;ngern, f&uuml;r die wir das Formular mit der folgenden Prozedur &ouml;ffnen:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdAddBCC_Click()\r\n     <span style=\"color:blue;\">If <\/span>CheckNewRecord = <span style=\"color:blue;\">False<\/span><span style=\"color:blue;\"> Then<\/span> <span style=\"color:blue;\">Exit Sub<\/span>\r\n     DoCmd.OpenForm \"frmEditEMailContacts\", _\r\n         WindowMode:=acDialog, OpenArgs:=\"3|\" & Me.EMailID\r\n     Me.lstBCC.Requery\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Anlagen hinzuf&uuml;gen<\/h2>\n<p>Etwas anders sieht die Prozedur aus, mit der wir Anlagen zur Tabelle <b>tblAttachments <\/b>hinzuf&uuml;gen und damit zum Listenfeld <b>lstAttachments<\/b>.<\/p>\n<p>Diese wird durch die Schaltfl&auml;che <b>cmdAddAttachment<\/b> ausgel&ouml;st und ist in Listing 4 abgebildet. <\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdAddAttachment_Click()\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>objFileDialog<span style=\"color:blue;\"> As <\/span>Office.FileDialog\r\n     <span style=\"color:blue;\">Dim <\/span>strTemp<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strFilename<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>varPath<span style=\"color:blue;\"> As Variant<\/span>\r\n     <span style=\"color:blue;\">If <\/span>CheckNewRecord = <span style=\"color:blue;\">False<\/span><span style=\"color:blue;\"> Then<\/span> <span style=\"color:blue;\">Exit Sub<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> objFileDialog = Application.FileDialog(msoFileDialogFilePicker)\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">With<\/span> objFileDialog\r\n         .Title = \"Anlagen ausw&auml;hlen\"\r\n         .ButtonName = \"Ausw&auml;hlen\"\r\n         .AllowMultiSelect = <span style=\"color:blue;\">True<\/span>\r\n         .InitialFileName = CurrentProject.Path & \"\\\"\r\n         .Filters.Clear\r\n         .Filters.Add \"Alle Dateitypen\", \"*.*\"\r\n         <span style=\"color:blue;\">If <\/span>.Show = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n             For Each varPath In .SelectedItems\r\n                 strFilename = <span style=\"color:blue;\">Mid<\/span>(varPath, <span style=\"color:blue;\">InStrRev<\/span>(varPath, \"\\\") + 1)\r\n                 db.Execute \"INSERT INTO tblAttachments(AttachmentPath, AttachmentFilename, EMailID) VALUES(''\" _\r\n                     & varPath & \"'', ''\" & strFilename & \"'', \" & Me.EMailID & \")\", dbOpenDynaset\r\n             <span style=\"color:blue;\">Next<\/span> varPath\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     End <span style=\"color:blue;\">With<\/span>\r\n     Me.lstAttachments.Requery\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Hinzuf&uuml;gen eines Attachments<\/span><\/b><\/p>\n<p>In dieser Prozedur nutzen wir die Dateidialoge von Office. Dazu m&uuml;ssen wir dem VBA-Projekt noch einen Verweis auf die Bibliothek <b>Microsoft Office 16.0 Object Library <\/b>hinzuf&uuml;gen.<\/p>\n<p>Damit der Benutzer die hinzuzuf&uuml;gende Datei ausw&auml;hlen kann, deklarieren wir eine Variable des Typs <b>Office.FileDialog<\/b>.<\/p>\n<p>Wie auch bei den &uuml;brigen Schaltfl&auml;chen, mit denen wir Datens&auml;tze zu Tabellen hinzuf&uuml;gen, die wir mit dem aktuellen Datensatz der Tabelle <b>tblEMails <\/b>verkn&uuml;pfen wollen, rufen wir auch hier die Funktion <b>CheckNewRecord <\/b>auf, um zu pr&uuml;fen, ob bereits ein Datensatz im Formular <b>frmEMails <\/b>vorliegt.<\/p>\n<p>Dann erstellt die Prozedur ein neues <b>FileDialog<\/b>-Objekt mit dem Typ <b>msoFileDialogPicker<\/b> und weist es <b>objFileDialog <\/b>zu.<\/p>\n<p>F&uuml;r dieses Objekt legen wir den Titel, die Buttonbeschriftung, den initialen Pfad sowie als Filter <b>*.* <\/b>fest. Au&szlig;erdem stellen wir die Eigenschaft <b>AllowMultiSelect <\/b>auf <b>True <\/b>ein, damit der Benutzer mehrere Dateien gleichzeitig ausw&auml;hlen kann.<\/p>\n<p>Mit der <b>Show<\/b>-Methode rufen wir den Dialog auf und verarbeiten nach dem Schlie&szlig;en seine Auflistung <b>SelectedItems<\/b>. Diese durchlaufen wir in einer <b>For Each<\/b>-Schleife und speichern den aktuellen Pfad jeweils in der Variablen <b>varPath<\/b>.<\/p>\n<p>Aus dem Pfad extrahieren wir den Dateinamen und schreiben anschlie&szlig;end den Pfad und den Dateinamen in die Tabelle <b>tblAttachments<\/b>. Au&szlig;erdem tragen wir dort noch die ID des aktuellen E-Mail-Datensatzes ein.<\/p>\n<p>Schlie&szlig;lich aktualisieren wir noch das Listenfeld <b>lstAttachments<\/b>, damit neu hinzugef&uuml;gte Anlagen direkt angezeigt werden.<\/p>\n<h2>Anlagen entfernen<\/h2>\n<p>Zum Entfernen von Anlagen programmieren die Schaltfl&auml;che <b>cmdRemoveAttachment<\/b>. Diese l&ouml;st die Prozedur aus Listing 5 aus.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdRemoveAttachment_Click()\r\n     <span style=\"color:blue;\">Dim <\/span>lngID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     lngID = Nz(Me.lstAttachments, 0)\r\n     db.Execute \"DELETE FROM tblAttachments WHERE AttachmentID = \" & lngID, dbFailOnError\r\n     Me.lstAttachments.Requery\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: Entfernen eines Attachments<\/span><\/b><\/p>\n<p>Hier ermitteln wir zun&auml;chst den aktuell im Anlagefeld markierten Datensatz und entfernen diesen mit einer <b>DELETE<\/b>-Anweisung.<\/p>\n<p>Auch hier folgt anschlie&szlig;end die Aktualisierung des Listenfeldes, damit die entfernten Anlagen auch hier nicht mehr angezeigt werden.<\/p>\n<h2>Entfernen von Empf&auml;ngern<\/h2>\n<p>F&uuml;r die drei Listenfelder <b>lstTo<\/b>, <b>lstCC <\/b>und <b>lstBCC <\/b>haben wir ebenfalls jeweils eine Schaltfl&auml;che zum Entfernen des jeweils markierten Eintrags vorgesehen.<\/p>\n<p>Diese rufen jeweils die Prozedur <b>RemoveRecipients <\/b>auf:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdRemoveTo_Click()\r\n     RemoveRecipient Me.lstTo\r\n<span style=\"color:blue;\">End Sub<\/span>\r\n<span style=\"color:blue;\">Private Sub <\/span>cmdRemoveCC_Click()\r\n     RemoveRecipient Me.lstCC\r\n<span style=\"color:blue;\">End Sub<\/span>\r\n<span style=\"color:blue;\">Private Sub <\/span>cmdRemoveBCC_Click()\r\n     RemoveRecipient Me.lstBCC\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Beim Aufruf wird jeweils der Verweis auf das betroffene Listenfeld an die Prozedur <b>RemoveRecipient <\/b>&uuml;bergeben.<\/p>\n<p>Die Prozedur <b>RemoveRecipients<\/b> sehen wir in Listing 6. Sie nimmt den Verweis auf das Listenfeld entgegen und ermittelt den aktuell markierten Datensatz mit <b>Nz(lst, 0)<\/b>. Die nachfolgende Bedingung ist nur erf&uuml;llt, wenn dabei ein Wert ungleich <b>0 <\/b>ermittelt werden konnte. In diesem Fall rufen wir eine <b>DELETE<\/b>-Anweisung auf, die den entsprechenden Datensatz aus der Tabelle <b>tblEMailsEMailContacts <\/b>l&ouml;scht.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>RemoveRecipient(lst<span style=\"color:blue;\"> As <\/span>ListBox)\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>lngID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     lngID = Nz(lst, 0)\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> lngID = 0<span style=\"color:blue;\"> Then<\/span>\r\n         db.Execute \"DELETE FROM tblEMailsEMailContacts WHERE EMailEMailContactID = \" & lngID, dbFailOnError\r\n         lst.Requery\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 6: Entfernen eines Empf&auml;ngers<\/span><\/b><\/p>\n<p>Warum m&uuml;ssen wir hier nicht gezielt angeben, f&uuml;r welches Listenfeld die Prozedur aufgerufen wurde? Weil die Listenfelder die Daten alle aus der gleichen Tabelle beziehen und wir nur gezielt den Datensatz l&ouml;schen, der im Listenfeld angezeigt wird.<\/p>\n<p>Anschlie&szlig;end aktualisieren wir noch das entsprechende Listenfeld.<\/p>\n<h2>Pr&uuml;fen, ob alle notwendigen Eigenschaften f&uuml;r die E-Mail vorhanden sind<\/h2>\n<p>In der anschlie&szlig;end beschriebenen Prozedur stellen wir die Daten f&uuml;r die E-Mail zusammen und &uuml;bergeben diese an die Klasse <b>clsEMail<\/b>.<\/p>\n<p>In dieser pr&uuml;fen wir vorab, ob alle notwendigen Informationen zum Versenden der E-Mail vorhanden sind. Das erledigen wir mit der Funktion <b>AllEMailPropertiesSet <\/b>aus Listing 7.<\/p>\n<pre><span style=\"color:blue;\">Private Function <\/span>AllEMailPropertiesSet()<span style=\"color:blue;\"> As Boolean<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(Nz(Me.Subject, \"\")) = 0<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Bitte geben Sie einen Betreff ein.\", vbOKOnly + vbExclamation, \"Betreff fehlt\"\r\n         Me.Subject.SetFocus\r\n         AllEMailProperties<span style=\"color:blue;\">Set<\/span> = <span style=\"color:blue;\">False<\/span>\r\n         <span style=\"color:blue;\">Exit Function<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM tblEMailsEMailContacts WHERE EMailID = \" & Me.EMailID _\r\n         & \" AND EMailContactTypeID = 1\", dbOpenSnapshot)\r\n     <span style=\"color:blue;\">If <\/span>rst.RecordCount = 0<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Bitte f&uuml;gen Sie einen To-Empf&auml;nger hinzu.\", vbOKOnly + vbExclamation, \"To-Empf&auml;nger fehlt\"\r\n         Me.lstTo.SetFocus\r\n         AllEMailProperties<span style=\"color:blue;\">Set<\/span> = <span style=\"color:blue;\">False<\/span>\r\n         <span style=\"color:blue;\">Exit Function<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     AllEMailProperties<span style=\"color:blue;\">Set<\/span> = <span style=\"color:blue;\">True<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 7: Pr&uuml;fen, ob alle notwendigen Informationen vorhanden sind<\/span><\/b><\/p>\n<p>Die Funktion pr&uuml;ft als Erstes, ob das Feld <b>Subject <\/b>einen Betreff enth&auml;lt. Falls nicht, erscheint eine Meldung, die auf das Fehlen dieser Information hinweist. Der Fokus wird auf dieses Feld gesetzt, die Funktion <b>AllEMailProperties <\/b>erh&auml;lt den R&uuml;ckgabewert <b>False <\/b>und die Funktion wird verlassen.<\/p>\n<p>Danach &ouml;ffnen wir ein Recordset basierend auf der Tabelle <b>tblEMailsEMailContacts<\/b>, das per Kriterium nur die Datens&auml;tze liefert, die zur aktuellen E-Mail geh&ouml;ren und deren Feld <b>EMailContactTypeID <\/b>den Wert <b>1 <\/b>enth&auml;lt. Das bedeutet, dass wir nur die Empf&auml;nger abfragen, die als <b>To<\/b>-Empf&auml;nger festgelegt sind.<\/p>\n<p>Ist die Anzahl der Datens&auml;tze in diesem Recordset gleich <b>0<\/b>, bedeutet das, dass wir keinen <b>To<\/b>-Empf&auml;nger hinzugef&uuml;gt haben.<\/p>\n<p>In diesem Fall erscheint ebenfalls eine entsprechende Meldung, der Fokus wird auf das Listenfeld eingestellt und die Funktion wird mit dem Ergebnis <b>False <\/b>verlassen.<\/p>\n<p>Mehr Informationen ben&ouml;tigen wir nicht, um eine g&uuml;ltige E-Mail zu erstellen. Sind die oben genannten Bedingungen also nicht erf&uuml;llt, gibt die Prozedur den Wert <b>True <\/b>zur&uuml;ck.<\/p>\n<h2>Zusammenstellen der E-Mail<\/h2>\n<p>Die E-Mail stellen wir in der Prozedur zusammen, die durch das Ereignis <b>Beim Klicken <\/b>der Schaltfl&auml;che <b>cmdSenden<\/b> ausgel&ouml;st wird. Den ersten Teil sehen wir in Listing 8.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdSenden_Click()\r\n     <span style=\"color:blue;\">Dim <\/span>objMail<span style=\"color:blue;\"> As <\/span>clsMail\r\n     <span style=\"color:blue;\">Dim <\/span>strResponse<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>rstTo<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>rstCC<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>rstBCC<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>rstReplyTo<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>rstAttachments<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>strSQLBase<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">If <\/span>AllEMailProperties<span style=\"color:blue;\">Set<\/span> = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n         <span style=\"color:blue;\">Set<\/span> objMail = <span style=\"color:blue;\">New<\/span> clsMail\r\n         <span style=\"color:blue;\">With<\/span> objMail\r\n             .Subject = Me.Subject\r\n             .ContentType = Me.ContentTypeID\r\n             <span style=\"color:blue;\">If <\/span>Me.ContentTypeID = 1<span style=\"color:blue;\"> Then<\/span>\r\n                 .Body = Me.BodyPlain\r\n             <span style=\"color:blue;\">Else<\/span>\r\n                 .Body = Me.BodyHTML\r\n             <span style=\"color:blue;\">End If<\/span>\r\n             strSQLBase = \"SELECT t1.ContactName, t1.ContactAddress FROM tblEMailsEMailContacts AS t2 INNER JOIN \" _\r\n                 & \"tblEMailContacts AS t1 ON t2.EMailContactID = t1.EMailContactID WHERE t2.EMailID = \" _\r\n                 & Me.EMailID & \" AND t2.EMailContactTypeID = \"\r\n             strSQL = strSQLBase & 1\r\n             <span style=\"color:blue;\">Set<\/span> rstTo = db.OpenRecordset(strSQL, dbOpenDynaset)\r\n             <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rstTo.EOF\r\n                 .AddToRecipient rstTo!ContactAddress, rstTo!ContactName\r\n                 rstTo.Move<span style=\"color:blue;\">Next<\/span>\r\n             <span style=\"color:blue;\">Loop<\/span>\r\n             strSQL = strSQLBase & 2\r\n             <span style=\"color:blue;\">Set<\/span> rstCC = db.OpenRecordset(strSQL, dbOpenDynaset)\r\n             <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rstCC.EOF\r\n                 .AddCCRecipient rstCC!ContactAddress, rstCC!ContactName\r\n                 rstCC.Move<span style=\"color:blue;\">Next<\/span>\r\n             <span style=\"color:blue;\">Loop<\/span>\r\n             strSQL = strSQLBase & 3\r\n     ...<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 8: Zusammenstellen der E-Mail, Teil 1<\/span><\/b><\/p>\n<p>Hier rufen wir zun&auml;chst die bereits beschriebene Funktion <b>AllEMailPropertiesSet <\/b>auf.<\/p>\n<p>Liefert diese den Wert <b>True <\/b>zur&uuml;ck, k&ouml;nnen wir mit dem Eintragen der Daten in die Klasse <b>clsMail <\/b>beginnen.<\/p>\n<p>Dazu holen wir uns einen Verweis auf das aktuelle <b>Database<\/b>-Objekt und erstellen ein neues Objekt auf Basis der Klasse <b>clsMail<\/b>, das wir mit der Variablen <b>objMail<\/b> referenzieren.<\/p>\n<p>Hier stellen wir die Eigenschaft <b>Subject <\/b>auf den entsprechenden Wert des Formulars ein, gleiches geschieht mit der Eigenschaft <b>ContentType<\/b>. Hat <b>ContentType <\/b>den Wert <b>1<\/b>, legen wir f&uuml;r die Eigenschaft <b>Body <\/b>den Wert des Feldes <b>BodyPlain <\/b>als Inhalt der E-Mail fest, anderenfalls den Inhalt des Feldes <b>BodyHTML<\/b>.<\/p>\n<p>Danach stellen wir in <b>strSQLBase <\/b>eine Abfrage zusammen, die jeweils den Wert der Felder <b>ContactName <\/b>und <b>ContactAddress <\/b>der Tabelle <b>tblEMailContacts <\/b>liefern soll. Allerdings nicht alle, sondern nur diejenigen, deren Feld <b>EMailID<\/b> aus der verkn&uuml;pften Tabelle <b>tblEMailsEMailContacts <\/b>mit dem Prim&auml;rschl&uuml;sselwert des aktuellen Datensatzes &uuml;bereinstimmt.<\/p>\n<p>Au&szlig;erdem hat die Abfrage noch ein Kriterium, das nicht ganz vollst&auml;ndig ist, n&auml;mlich <b>t3.EMailContactTypeID =<\/b>.<\/p>\n<p>Diesen Wert erg&auml;nzen wir in den n&auml;chsten Schritten. F&uuml;r die Ermittlung der <b>To<\/b>-Empf&auml;nger f&uuml;gen wir beispielsweise den Wert <b>1 <\/b>hinten an und speichern die resultierende Abfrage in <b>strSQL<\/b>. Basierend auf dieser Abfrage &ouml;ffnen wir ein Recordset und durchlaufen alle enthaltenen Datens&auml;tze. F&uuml;r jeden Datensatz &uuml;bergeben wir die E-Mail-Adresse und den Namen der Methode <b>AddToRecipient <\/b>der Klasse <b>clsMail<\/b> und h&auml;ngen diesen Kontakt so als <b>To<\/b>-Empf&auml;nger der E-Mail an.<\/p>\n<p>Diesen Schritt wiederholen wir anschlie&szlig;end noch zwei Mal, wobei wir zuerst den Wert <b>2 <\/b>f&uuml;r die <b>CC<\/b>-Empf&auml;nger und dann den Wert <b>3 <\/b>f&uuml;r die <b>BCC<\/b>-Empf&auml;nger an die SQL-Anweisung anh&auml;ngen.<\/p>\n<p>In Listing 9 pr&uuml;fen wir nach dem Anlegen der <b>BCC<\/b>-Empf&auml;nger, ob das Feld <b>ReplyToID <\/b>des Formulars leer ist. Fall nicht, &ouml;ffnen wir ein weiteres Recordset, das den den Eintrag der Tabelle <b>tblReplyToContacts <\/b>enth&auml;lt, der dieser E-Mail zugeordnet wurde.<\/p>\n<pre>             ...\r\n             <span style=\"color:blue;\">Set<\/span> rstBCC = db.OpenRecordset(strSQL, dbOpenDynaset)\r\n             <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rstBCC.EOF\r\n                 .AddBCCRecipient rstBCC!ContactAddress, rstBCC!ContactName\r\n                 rstBCC.Move<span style=\"color:blue;\">Next<\/span>\r\n             <span style=\"color:blue;\">Loop<\/span>\r\n             <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> IsNull(Me.ReplyToID)<span style=\"color:blue;\"> Then<\/span>\r\n                 <span style=\"color:blue;\">Set<\/span> rstReplyTo = db.OpenRecordset(\"SELECT * FROM tblReplyToContacts WHERE ReplyToContactID = \" _\r\n                     & Me.ReplyToID, dbOpenDynaset)\r\n                 .AddReplyToRecipient rstReplyTo!ContactAddress, rstReplyTo!ContactName\r\n             <span style=\"color:blue;\">End If<\/span>\r\n             <span style=\"color:blue;\">Set<\/span> rstAttachments = db.OpenRecordset(\"SELECT * FROM tblAttachments WHERE EMailID = \" & Me.EMailID, _\r\n                 dbOpenDynaset)\r\n             <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rstAttachments.EOF\r\n                 .AddAttachmentPath rstAttachments!AttachmentPath\r\n                 rstAttachments.Move<span style=\"color:blue;\">Next<\/span>\r\n             <span style=\"color:blue;\">Loop<\/span>\r\n             .Importance = Me.ImportanceLevelID\r\n             <span style=\"color:blue;\">If <\/span>.Send(strResponse) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n                 <span style=\"color:blue;\">MsgBox<\/span> strResponse\r\n             <span style=\"color:blue;\">Else<\/span>\r\n                 <span style=\"color:blue;\">MsgBox<\/span> strResponse\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         End <span style=\"color:blue;\">With<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 9: Zusammenstellen der E-Mail, Teil 2<\/span><\/b><\/p>\n<p>Dessen E-Mail-Adresse und Name weisen wir mit der <b>AddReplyToRecipient<\/b>-Funktion zur Klasse <b>clsMail <\/b>hinzu.<\/p>\n<p>Schlie&szlig;lich folgen die Anlagen. Hier stellen wir ein Recordset namens <b>rstAttachments <\/b>zusammen, das alle Eintr&auml;ge der Tabelle <b>tblAttachments <\/b>enth&auml;lt, deren Fremdschl&uuml;sselfeld <b>EMailID <\/b>mit dem aktuellen Datensatz im Formular verkn&uuml;pft ist. F&uuml;r alle gefundenen Datens&auml;tze f&uuml;gen wir mit der <b>AddAttachmentPath<\/b>-Funktion den Pfad zu der hinzuzuf&uuml;genden Anlage zu <b>clsMail <\/b>hinzu.<\/p>\n<p>Schlie&szlig;lich stellen wir noch die Wichtigkeit ein und rufen die <b>Send<\/b>-Methode auf, um die E-Mail zu versenden. Das Ergebnis des <b>Send<\/b>-Befehls geben wir in einer Meldung aus.<\/p>\n<h2>Formular zum Verwalten der Empf&auml;nger<\/h2>\n<p>Damit fehlt noch das Formular <b>frmEditEMailContacts<\/b>. Dieses gestalten wir in der Entwurfsansicht wie in Bild 20.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_466_020.png\" alt=\"Das Formular frmEditEMailContacts im Entwurf\" width=\"499,6267\" height=\"291,1494\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 20: Das Formular frmEditEMailContacts im Entwurf<\/span><\/b><\/p>\n<p>Im Kopf des Klassenmoduls dieses Formulars deklarieren wir die folgenden beiden Variablen, die wir formularweit ben&ouml;tigen:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>lngContactTypeID<span style=\"color:blue;\"> As Long<\/span>\r\n<span style=\"color:blue;\">Private <\/span>lngEMailID<span style=\"color:blue;\"> As Long<\/span><\/pre>\n<p>Wie bereits erw&auml;hnt, wollen wir nicht nur die Kontakte f&uuml;r die <b>To<\/b>-, <b>CC<\/b>&#8211; und <b>BCC<\/b>-Empf&auml;nger mit diesem Formular verwalten, sondern auch noch die f&uuml;r das <b>ReplyTo<\/b>-Feld.<\/p>\n<p>Deshalb m&uuml;ssen wir gleich beim &Ouml;ffnen des Formulars einige Einstellungen vornehmen, damit die richtigen Daten angezeigt und verarbeitet werden k&ouml;nnen. Dies geschieht im Ereignis <b>Beim &Ouml;ffnen <\/b>des Formulars, f&uuml;r das wir die Ereignisprozedur aus Listing 10 hinterlegen.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Open(Cancel<span style=\"color:blue;\"> As Integer<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>strOpenArgs<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(Nz(Me.OpenArgs, \"\")) = 0<span style=\"color:blue;\"> Then<\/span>\r\n         Cancel = <span style=\"color:blue;\">True<\/span>\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         strOpenArgs = Me.OpenArgs\r\n         lngContactTypeID = <span style=\"color:blue;\">Split<\/span>(strOpenArgs, \"|\")(0)\r\n         lngEMailID = <span style=\"color:blue;\">Split<\/span>(strOpenArgs, \"|\")(1)\r\n         Select Case lngContactTypeID\r\n             <span style=\"color:blue;\">Case <\/span>1, 2, 3\r\n                 Me.lstContacts.RowSource = \"SELECT tblEMailContacts.EMailContactID, [ContactName] & '' &lt;'' _\r\n                     & [ContactAddress] & ''&gt;'' AS Contact FROM tblEMailContacts WHERE EMailContactID NOT IN \" _\r\n                     & \"(SELECT EMailContactID FROM tblEMailsEMailContacts AS t1 WHERE t1.EMailID = \" & lngEMailID _\r\n                     & \") ORDER BY [ContactName]\"\r\n             <span style=\"color:blue;\">Case <\/span>4\r\n                 Me.lstContacts.RowSource = \"SELECT tblReplyToContacts.ReplyToContactID, [ContactName] & '' &lt;'' _\r\n                     & [ContactAddress] & ''&gt;'' AS Contact FROM tblReplyToContacts ORDER BY [ContactName]\"\r\n         <span style=\"color:blue;\">End Select<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 10: Prozedur, die beim &Ouml;ffnen des Formulars ausgel&ouml;st wird<\/span><\/b><\/p>\n<p>Wir erinnern uns, dass wir beispielsweise f&uuml;r die <b>To<\/b>-Adressaten das Formular mit der folgenden Anweisung aufrufen:<\/p>\n<pre>DoCmd.OpenForm \"frmEditEMailContacts\", _\r\n     WindowMode:=acDialog, OpenArgs:=\"1|\" & Me.EMailID<\/pre>\n<p>Wir &uuml;bergeben hier also mit dem &Ouml;ffnungsargument den Wert <b>1<\/b> als Kennzeichen daf&uuml;r, dass wir die <b>To<\/b>-Adressaten bearbeiten wollen und dann, nach einem trennenden Pipe-Zeichen (<b>|<\/b>), den Prim&auml;rschl&uuml;sselwert der zu bearbeitenden E-Mail.<\/p>\n<p>Diese nehmen wir in der <b>Form_Open<\/b>-Prozedur entgegen. Hier pr&uuml;fen wir, ob &uuml;berhaupt ein &Ouml;ffnungsargument &uuml;bergeben wurde. Falls dieses leer ist, stellen wir den Wert <b>Cancel <\/b>auf <b>True <\/b>ein und verlassen die Prozedur. Durch diesen Parameter wird das &Ouml;ffnen des Formulars direkt abgebrochen. Ist <b>OpenArgs <\/b>nicht leer, weisen wir es <b>strOpenArgs <\/b>zu.  Dieses teilen wir nun mit der <b>Split<\/b>-Funktion an der Stelle des Pipe-Zeichens in ein aus zwei Elementen bestehendes Array auf. Den ersten Teil schreiben wir in <b>lngContactTypeID<\/b>, den zweiten in <b>lngEMailID<\/b>.<\/p>\n<p>In der folgenden <b>Select Case<\/b>-Bedingung pr&uuml;fen wir den Wert von <b>lngContactType<\/b>. Die Werte <b>1<\/b>, <b>2 <\/b>und <b>3 <\/b>stehen f&uuml;r die <b>To<\/b>-, <b>CC<\/b>&#8211; und <b>BCC<\/b>-Adressaten, der Wert <b>4 <\/b>f&uuml;r die <b>ReplyTo<\/b>-Adressaten. In den F&auml;llen <b>1<\/b>, <b>2 <\/b>und <b>3 <\/b>legen wir die Datensatzquelle f&uuml;r das enthaltene Listenfeld <b>lstContacts<\/b> auf eine Abfrage fest, die alle Eintr&auml;ge der Tabelle <b>tblEMailContacts <\/b>enth&auml;lt, die noch nicht der aktuellen E-Mail zugewiesen wurden.<\/p>\n<p>Als Vergleichswert des Kriteriums verwenden wir eine Unterabfrage, die alle Datens&auml;tze liefert, die bereits zugeordnet sind. Der Name und die E-Mail-Adresse der Datens&auml;tze werden dabei in folgendem Format zusammengestellt:<\/p>\n<pre>Andr&eacute; Minhorst &lt;info@andreminhorst.de&gt;<\/pre>\n<p>Im Fall des Wertes <b>4 <\/b>stellen wir eine Abfrage als Datensatzherkunft des Listenfeldes zusammen, die alle Datens&auml;tze der Tabelle <b>tblReplyToContacts <\/b>enth&auml;lt. Auch hier formatieren wir Name und Adresse wie zuvor. Damit ist bereits das Listenfeld mit den Daten f&uuml;r den jeweiligen Anwendungszweck gef&uuml;llt.<\/p>\n<h2>Einen neuen Kontakt zur Liste hinzuf&uuml;gen<\/h2>\n<p>Um einen neuen Kontakt zu einer der Listen hinzuzuf&uuml;gen, kann der Benutzer in den beiden Textfeldern unten den Namen und die E-Mail-Adresse des neuen Kontakts eintragen und diesen mit einem Klick auf die <b>Plus<\/b>-Schaltfl&auml;che hinzuf&uuml;gen. Dies l&ouml;st die Prozedur aus Listing 11 aus.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdAddContact_Click()\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(Nz(Me.txtName, \"\")) = 0<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Bitte Name angeben.\", vbOKOnly + vbExclamation, \"Name fehlt\"\r\n         Me.txtName.SetFocus\r\n         <span style=\"color:blue;\">Exit Sub<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(Nz(Me.txtEMail, \"\")) = 0<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Bitte E-Mail angeben.\", vbOKOnly + vbExclamation, \"E-Mail fehlt\"\r\n         Me.txtEMail.SetFocus\r\n         <span style=\"color:blue;\">Exit Sub<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     Select Case lngContactTypeID\r\n         <span style=\"color:blue;\">Case <\/span>1, 2, 3\r\n             db.Execute \"INSERT INTO tblEMailContacts(ContactName, ContactAddress) VALUES(''\" & Me.txtName & \"'', ''\" _\r\n                 & Me.txtEMail & \"'')\", dbFailOnError\r\n         <span style=\"color:blue;\">Case <\/span>4\r\n             db.Execute \"INSERT INTO tblReplyToContacts(ContactName, ContactAddress) VALUES(''\" & Me.txtName & \"'', ''\" _\r\n                 & Me.txtEMail & \"'')\", dbFailOnError\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n     Me.lstContacts.Requery\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 11: Hinzuf&uuml;gen eines neuen Kontakts zur Tabelle tblEMailContacts<\/span><\/b><\/p>\n<p>Die Prozedur pr&uuml;ft zun&auml;chst, ob im Feld <b>txtName <\/b>ein Wert eingegeben wurde. Falls das Textfeld leer ist, erscheint eine entsprechende Meldung, der Fokus wird auf das Textfeld verschoben und die Prozedur wird beendet.<\/p>\n<p>Das Gleiche geschieht, wenn das Feld <b>txtEMail <\/b>nicht gef&uuml;llt wurde.<\/p>\n<p>Danach f&uuml;gen wir den neuen Eintrag zur jeweiligen Tabelle hinzu. Auch hier m&uuml;ssen wir wieder unterscheiden, ob das Formular zum Bearbeiten der <b>To<\/b>-, <b>CC<\/b>&#8211; und <b>BCC<\/b>-Adressaten oder zum Bearbeiten des <b>ReplyTo<\/b>-Kontakts ge&ouml;ffnet wurde.<\/p>\n<p>Im ersten Fall f&uuml;hren wir eine <b>INSERT INTO<\/b>-Anweisung aus, die den neuen Datensatz zur Tabelle <b>tblEMailContacts <\/b>hinzuf&uuml;gt.<\/p>\n<p>Im zweiten Fall landet der neue Kontakt in der Tabelle <b>tblReplyContacts<\/b>.<\/p>\n<p>In beiden F&auml;llen wird das Listenfeld anschlie&szlig;end aktualisiert.<\/p>\n<h2>Hinzuf&uuml;gen eines Kontakts zu einer E-Mail<\/h2>\n<p>Neben dem Listenfeld befindet sich eine Schaltfl&auml;che, die wiederum je nach dem Zweck des Formulars entweder einen oder mehrere Kontakte als <b>To<\/b>-, <b>CC<\/b>&#8211; oder <b>BCC<\/b>-Empf&auml;nger der aktuellen E-Mail-Adresse hinzuf&uuml;gt oder als <b>ReplyTo<\/b>-Adresse (siehe Listing 12).<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdAddContactsToEMail_Click()\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>lngEMailContactID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>var<span style=\"color:blue;\"> As Variant<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     Select Case lngContactTypeID\r\n         <span style=\"color:blue;\">Case <\/span>1, 2, 3\r\n             For Each var In Me.lstContacts.ItemsSelected\r\n                 lngEMailContactID = Me.lstContacts.ItemData(var)\r\n                 On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n                 db.Execute \"INSERT INTO tblEMailsEMailContacts(EMailID, EMailContactID, EMailContactTypeID) VALUES(\" _\r\n                     & lngEMailID & \", \" & lngEMailContactID & \", \" & lngContactTypeID & \")\", dbFailOnError\r\n                 <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n             <span style=\"color:blue;\">Next<\/span> var\r\n         <span style=\"color:blue;\">Case <\/span>4\r\n             var = Me.lstContacts.ListIndex\r\n             lngEMailContactID = Nz(Me.lstContacts.ItemData(var), 0)\r\n             <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> lngEMailContactID = 0<span style=\"color:blue;\"> Then<\/span>\r\n                 db.Execute \"UPDATE tblEMails SET ReplyToID = \" & lngEMailContactID & \" WHERE EMailID = \" _\r\n                     & lngEMailID, dbFailOnError\r\n             <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n     DoCmd.Close acForm, Me.Name\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 12: Hinzuf&uuml;gen eines neuen Kontakts zu einer E-Mail<\/span><\/b><\/p>\n<p>Auch hier pr&uuml;fen wir dies in einer <b>Select Case<\/b>-Bedingung. Im Falle der Werte <b>1<\/b>, <b>2 <\/b>oder <b>3 <\/b>durchlaufen wir alle aktuell markierten Eintr&auml;ge des Listenfeldes, die wir in der Auflistung <b>ItemsSelected <\/b>finden.<\/p>\n<p>Die Laufvariable <b>var <\/b>nimmt dabei jeweils den Index des aktuellen Listeneintrags auf. Mit <b>Me.lstContacts.ItemData(var) <\/b>holen wir uns dazu den Wert der gebundenen Spalte und speichern diesen in der Variablen <b>lngEMailContactID<\/b>.<\/p>\n<p>Diesen tragen wir schlie&szlig;lich per <b>INSERT INTO<\/b>-Abfrage in die Tabelle <b>EMailsEMailContacts <\/b>ein. Dabei &uuml;bergeben den Wert aus <b>lngEMail <\/b>f&uuml;r die aktuelle E-Mail, <b>lngEMailContactID <\/b>f&uuml;r den hinzuzuf&uuml;genden Kontakt und <b>lngContactTypeID <\/b>als Art des Adressaten.<\/p>\n<p>Etwas anders ist die Vorgehensweise, wenn wir eine <b>ReplyTo<\/b>-Adresse zur&uuml;ckgeben wollen. Hier k&ouml;nnen wir nur einen Kontakt zur&uuml;ckgeben.<\/p>\n<p>Was aber, wenn der Benutzer mehr als einen Eintrag markiert hat, was ja m&ouml;glich ist, das das Listenfeld die Mehrfachauswahl erlaubt?<\/p>\n<p>Darum k&uuml;mmern wir uns weiter unten.<\/p>\n<p>Davon ausgehend, dass nur ein Kontakt markiert ist, lesen wir seinen Index aus der Eigenschaft <b>ListIndex <\/b>in die Variable <b>var <\/b>ein und ermitteln daraus den Wert der gebundenen Spalte.<\/p>\n<p>Ist dieser Wert nicht Null, aktualisieren wir das Feld <b>ReplyToID <\/b>der Tabelle <b>tblEMails <\/b>auf die ID des jeweiligen Kontaktes.<\/p>\n<h2>Verhindern, dass bei Auswahl eines ReplyTo-Kontakts mehr als ein Kontakt markiert wird<\/h2>\n<p>Wie oben beschrieben, m&uuml;ssen wir beim &Ouml;ffnen des Formulars <b>frmEditEMailContacts <\/b>zur Auswahl eines <b>ReplyTo<\/b>-Kontakts sicherstellen, dass immer nur ein Eintrag ausgew&auml;hlt werden kann. Das gelingt aber nicht, wenn die Mehrfachauswahl aktiviert ist. Da wir diese nicht zur Laufzeit umstellen k&ouml;nnen, m&uuml;ssen wir uns anderweitig behelfen: Wir sorgen einfach daf&uuml;r, dass beim Ausw&auml;hlen eines anderen Eintrags alle anderen zuvor ausgew&auml;hlten Eintr&auml;ge abgew&auml;hlt werden.<\/p>\n<p>Dazu verwenden wir das Ereignis <b>Nach Aktualisierung <\/b>des Listenfeldes, f&uuml;r das wir die folgende Prozedur hinterlegen.<\/p>\n<p>Diese soll nur etwas tun, wenn <b>lngContactTypeID <\/b>den Wert <b>4 <\/b>aufweist.<\/p>\n<p>In diesem Fall merken wir uns den aktuell angeklickten Eintrag, den wir mit der Eigenschaft <b>ListIndex <\/b>ermitteln, in der Variablen <b>lngListIndex<\/b>.<\/p>\n<p>Danach durchlaufen wir eine Schleife, in der wir alle aktuell ausgew&auml;hlten Eintr&auml;ge abw&auml;hlen, indem wir die Eigenschaft <b>Selected <\/b>f&uuml;r den jeweiligen Index auf <b>False <\/b>einstellen.<\/p>\n<p>Dann wird wieder der zuletzt markierte Eintrag markiert:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>lstContacts_AfterUpdate()\r\n     <span style=\"color:blue;\">Dim <\/span>lngListIndex<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As Long<\/span>\r\n     Select Case lngContactTypeID\r\n         <span style=\"color:blue;\">Case <\/span>1, 2, 3\r\n         <span style=\"color:blue;\">Case <\/span>4\r\n             lngListIndex = Me.lstContacts.ListIndex\r\n             For i = 0 To Me.lstContacts.ListCount - 1\r\n                 Me.lstContacts.Selected(i) = <span style=\"color:blue;\">False<\/span>\r\n             <span style=\"color:blue;\">Next<\/span> i\r\n             Me.lstContacts.Selected(lngListIndex) = <span style=\"color:blue;\">True<\/span>\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Kontakt per Doppelklick hinzuf&uuml;gen<\/h2>\n<p>Schlie&szlig;lich haben wir noch eine Funktion hinzugef&uuml;gt, mit dem wir einen Kontakt per Doppelklick direkt zur aktuellen E-Mail zuweisen k&ouml;nnen (siehe Listing 13). <\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>lstContacts_DblClick(Cancel<span style=\"color:blue;\"> As Integer<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>lngEMailContactID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>var<span style=\"color:blue;\"> As Variant<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     var = Me.lstContacts.ListIndex\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> IsNull(var)<span style=\"color:blue;\"> Then<\/span>\r\n         lngEMailContactID = Me.lstContacts.ItemData(var)\r\n         Select Case lngContactTypeID\r\n             <span style=\"color:blue;\">Case <\/span>1, 2, 3\r\n                 On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n                 db.Execute \"INSERT INTO tblEMailsEMailContacts(EMailID, EMailContactID, EMailContactTypeID) VALUES(\" _\r\n                     & lngEMailID & \", \" & lngEMailContactID & \", \" & lngContactTypeID & \")\", dbFailOnError\r\n                 <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n             <span style=\"color:blue;\">Case <\/span>4\r\n                 On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n                 db.Execute \"UPDATE tblEMails SET ReplyToID = \" & lngEMailContactID & \" WHERE EMailID = \" _\r\n                     & lngEMailID, dbFailOnError\r\n                 <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n         <span style=\"color:blue;\">End Select<\/span>\r\n         DoCmd.Close acForm, Me.Name\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Bitte zur Schnellauswahl doppelt auf einen vorhandenen Datensatz klicken.\", vbOKOnly + _\r\n             vbExclamation, \"Kein Datensatz markiert\"\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 13: &Ouml;ffnen eines Kontakts <\/span><\/b><\/p>\n<p>Hier m&uuml;ssen wir etwas anders vorgehen als sonst, wenn wir den angeklickten Eintrag des Listenfeldes nach einem Doppelklick auswerten wollen.<\/p>\n<p>&Uuml;blicherweise fragen wir dann einfach den Wert des Listenfeldes ab,  hier also beispielsweise mit <b>Me.lstContacts.Value<\/b>.<\/p>\n<p>Das gelingt hier allerdings nicht, denn wir haben f&uuml;r dieses Listenfeld die Eigenschaft <b>Mehrfachauswahl <\/b>auf den Wert <b>Einfach <\/b>eingestellt.<\/p>\n<p>Wenn wir in dieser Konstellation mit <b>Me.lstContacts.Value <\/b>auf einen Eintrag zugreifen wollen, liefert dies den Wert <b>Null <\/b>zur&uuml;ck.<\/p>\n<p>Zum Gl&uuml;ck gibt es mit der Eigenschaft <b>ListIndex <\/b>eine Alternative, denn damit k&ouml;nnen wir auf den angeklickten Eintrag zugreifen. Diesen Wert speichern wir in der Ereignisprozedur f&uuml;r das Ereignis <b>Beim Doppelklicken  <\/b>in der Variablen <b>var<\/b>.<\/p>\n<p>Dann pr&uuml;fen wir in einer <b>If&#8230;Then<\/b>-Bedingung mit <b>IsNull<\/b>, ob var den Wert <b>Null <\/b>enth&auml;lt. In diesem Fall geben wir im zweiten Teil der Bedingung eine entsprechende Meldung aus.<\/p>\n<p>Hat der Benutzer jedoch einen vorhandenen Listeneintrag angeklickt, ermitteln wir mit der <b>ItemData<\/b>-Eigenschaft die ID des angeklickten Kontaktes und speichern diesen in <b>lngEMailContactID<\/b>.<\/p>\n<p>Nun pr&uuml;fen wir wieder, welchen Kontakttyp wir gerade zuweisen. F&uuml;r die Typen <b>1<\/b>, <b>2 <\/b>und <b>3 <\/b>schreiben wir einen Eintrag mit den entsprechenden Daten in die Tabelle <b>tblEMailsEMailContacts<\/b>.<\/p>\n<p>Im Falle des Typs <b>4<\/b>, also der ReplyTo-Adresse, schreiben wir den Prim&auml;rschl&uuml;sselwert des Kontaktes direkt in das Feld <b>ReplyToID <\/b>der Tabelle <b>tblEMails<\/b>.<\/p>\n<p>Damit kann die Prozedur das Formular schlie&szlig;en.<\/p>\n<h2>Suchfunktion f&uuml;r die Kontakte<\/h2>\n<p>Schlie&szlig;lich kann es sein, dass sich schnell viele Kontakte in der Liste sammeln, nach denen man im Listenfeld vermutlich nicht ewig suchen m&ouml;chte. Also f&uuml;gen wir noch ein Textfeld namens <b>txtSearch <\/b>hinzu, in das der Besucher einen Suchtext f&uuml;r Name und E-Mail eingeben kann.<\/p>\n<p>Diese l&ouml;st beim &Auml;ndern die Prozedur aus Listing 14 aus. Hier lesen wir den aktuellen Text des Suchfensters in die Variable <b>strSearch <\/b>ein. Je nach dem Typ des hinzuzuf&uuml;genden Kontacts aus <b>lngContactTypeID <\/b>stellen wir f&uuml;r die Werte <b>1<\/b>, <b>2 <\/b>und <b>3 <\/b>eine Datensatzherkunft basierend auf der Tabelle <b>tblEMailContacts <\/b>mit einer Unterabfrage mit der Tabelle <b>tblEMailsEMailContacts <\/b>zusammen oder im Falle des Wertes <b>4 <\/b>eine Abfrage basierend auf der Tabelle <b>tblReplyTo<\/b>.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>txtSearch_Change()\r\n     <span style=\"color:blue;\">Dim <\/span>strSearch<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n     \r\n     strSearch = Me.txtSearch.Text\r\n     Select Case lngContactTypeID\r\n         <span style=\"color:blue;\">Case <\/span>1, 2, 3\r\n             strSQL = \"SELECT EMailContactID, [ContactName] & '' &lt;'' & [ContactAddress] & ''&gt;'' AS Contact \" _\r\n                 & \"FROM tblEMailContacts WHERE (ContactName LIKE ''*\" & strSearch & \"*'' OR ContactAddress LIKE ''*\" _\r\n                 & strSearch & \"*'') AND EMailContactID NOT IN (SELECT EMailContactID FROM tblEMailsEMailContacts \" _\r\n                 & \"AS t1 WHERE t1.EMailID = \" & lngEMailID & \") ORDER BY ContactName;\"\r\n         <span style=\"color:blue;\">Case <\/span>4\r\n             strSQL = \"SELECT ReplyToContactID, [ContactName] & '' &lt;'' & [ContactAddress] & ''&gt;'' AS Contact \" _\r\n                 & \"FROM tblReplyToContacts WHERE (ContactName LIKE ''*\" & strSearch & \"*'' OR ContactAddress LIKE ''*\" _\r\n                 & strSearch & \"*'') ORDER BY ContactName;\"\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n     Me.lstContacts.RowSource = strSQL\r\n     Me.txtEMail = Null\r\n     Me.txtName = Null\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 14: Suchfunktion f&uuml;r die Kontakte<\/span><\/b><\/p>\n<h2>Zusammenfassung und Ausblick<\/h2>\n<p>Dieser Artikel zeigt, wie man ein Formular zur Eingabe von E-Mail-Informationen programmieren kann. Es erlaubt die Eingabe aller wichtigen Daten und bietet au&szlig;erdem den Komfort eines Auswahlformulars f&uuml;r die Adressaten.<\/p>\n<h2>Downloads zu diesem Beitrag<\/h2>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>Microsoft365EMailsPerFormularVerschicken.accdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/E90B5309-7C0C-4DA5-9A76-B6727911685F\/vbe_466.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Im Artikel &#8220;Microsoft 365 E-Mails mit Make per Klasse senden&#8221; (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&ouml;nnen. Dazu haben wir eine Klasse programmiert, mit der wir leicht die notwendigen Daten f&uuml;r die E-Mail &uuml;bergeben k&ouml;nnen. Im vorliegenden Artikel stellen wir nun ein Formular vor, mit dem wir leicht die Daten f&uuml;r eine solche E-Mail eingeben und diese schlie&szlig;lich absenden k&ouml;nnen. Die dazu eingegebenen Daten speichern wir in entsprechenden Tabellen, sodass wir diese sp&auml;ter einsehen k&ouml;nnen.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[662025,66032025,44000029,44000034,44000025],"tags":[],"yst_prominent_words":[],"class_list":["post-55000466","post","type-post","status-publish","format-standard","hentry","category-662025","category-66032025","category-Access_programmieren","category-COMAddIns_programmieren","category-VBAProgrammierung"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000466","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/comments?post=55000466"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000466\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000466"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000466"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000466"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000466"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}