{"id":55000440,"date":"2024-10-01T00:00:00","date_gmt":"2024-11-05T20:33:21","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=440"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Outlook_Mails_nach_dem_Senden_per_VBA_verschieben","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/Outlook_Mails_nach_dem_Senden_per_VBA_verschieben\/","title":{"rendered":"Outlook: Mails nach dem Senden per VBA verschieben"},"content":{"rendered":"<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_05\/pic_440_001.png\" alt=\"Anlegen einer neuen Regel f&uuml;r eingehende Nachrichten\" width=\"700\" height=\"401,4599\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Anlegen einer neuen Regel f&uuml;r eingehende Nachrichten<\/span><\/b><\/p>\n<p><b>F&uuml;r eingehende E-Mails gibt es unter Outlook die Regel-Funktion, mit der man einstellen kann, unter welchen Umst&auml;nden eine E-Mail, die im Posteingang landet, in einen anderen Ordner verschoben werden soll. Das kann man beispielsweise nutzen, um immer wiederkehrende Rechnungen direkt in den entsprechenden Ordner zu verschieben. W&uuml;nschenswert w&auml;re, wenn es eine solche Funktion auch f&uuml;r versendete E-Mails g&auml;be. Da Outlook hier aber keine eingebaute Funktion bereitstellt, schauen wir uns das Thema einmal genauer an und entwickeln VBA-Code, mit dem wir diese Aufgabe selbst steuern k&ouml;nnen. Dabei wollen wir sowohl &uuml;ber die Benutzeroberfl&auml;che gesendete E-Mails erfassen als auch E-Mails, die wir per VBA absenden.<\/b><\/p>\n<p>Wenn wir in Outlook mit der rechten Maustaste auf eine E-Mail in einem beliebigen Ordner klicken, erscheint das Kontextmen&uuml; und offeriert uns den Eintrag <b>Regeln|Regel erstellen &#8230;<\/b> (siehe Bild 1).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_05\/pic_440_001.png\" alt=\"Anlegen einer neuen Regel f&uuml;r eingehende Nachrichten\" width=\"700\" height=\"401,4599\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Anlegen einer neuen Regel f&uuml;r eingehende Nachrichten<\/span><\/b><\/p>\n<p>Damit &ouml;ffnen wir einen Dialog namens Regel erstellen, mit dem wir genauer festlegen k&ouml;nnen, wann die Regel ausgel&ouml;st werden soll und was wir damit bewirken wollen (siehe Bild 2). Wir k&ouml;nnen hier zum Beispiel angeben, dass nur E-Mails mit einem bestimmten Betreff, f&uuml;r einen bestimmten Empf&auml;nger oder von einem bestimmten Absender verarbeitet werden sollen. Au&szlig;erdem geben wir an, was mit der E-Mail geschehen soll. Hier reichen die M&ouml;glichkeiten von einer Benachrichtigung &uuml;ber die Ausgabe eines Sounds bis hin zum Verschieben in einen bestimmten Ordner.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_05\/pic_440_002.png\" alt=\"Dialog zum Erstellen einer Regel\" width=\"499,6267\" height=\"280,7903\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Dialog zum Erstellen einer Regel<\/span><\/b><\/p>\n<p>Diese Regel gelten jedoch nur f&uuml;r Elemente, die frisch im Posteingang gelandet sind. Wenn wir also eine E-Mail erstellen und diese versenden, wird die Regel nicht ausgel&ouml;st. Genau diese fehlende Funktion wollen wir im vorliegenden Artikel nachreichen. Dabei gibt es zwei Ans&auml;tze:<\/p>\n<ul>\n<li>Wir erstellen eine E-Mail automatisiert per VBA, beispielsweise von einer Datenbankanwendung aus, und wollen daf&uuml;r sorgen, dass diese direkt aus dem Ordner Gesendete Elemente in einen vordefinierten Ordner verschoben wird.<\/li>\n<li>Oder wir erstellen eine E-Mail auf herk&ouml;mmliche Art &uuml;ber die Benutzeroberfl&auml;che von Outlook und versenden diese. Auch hier wollen wir, dass diese E-Mails nach vorgegebenen Regeln in andere Ordner verschoben werden.<\/li>\n<\/ul>\n<p>Da die erste L&ouml;sung wesentlich einfacher zu programmieren ist, starten wir mit dieser. Die Programmierung erledigen wir der Einfachheit halber innerhalb des VBA-Projekts von Outlook. Wir verwenden jedoch die volle Referenzierung der Klassen, damit diese auch in anderen Anwendungen eingesetzt werden k&ouml;nnen. Dort m&uuml;ssen wir lediglich noch einen Verweis auf die Bibliothek <b>Microsoft Outlook 16.0 Object Library <\/b>hinzuf&uuml;gen. Diesen Verweis legen wir im <b>Verweise<\/b>-Dialog an, den wir im VBA-Editor der jeweiligen Anwendung mit dem Men&uuml;befehl <b>Extras|Verweise <\/b>&ouml;ffnen.<\/p>\n<h2>Per VBA gesendete E-Mails in anderen Ordner verschieben<\/h2>\n<p>Das Versenden eine E-Mail per VBA ist keine Raketentechnik. Und spannenderweise ben&ouml;tigen wir nur noch eine kleine &Auml;nderung, damit die gesendete E-Mail nicht im Ordner <b>Gesendete Elemente <\/b>landet, sondern in einem beliebigen anderen Ordner Deiner Wahl.<\/p>\n<p>Dann verwenden wir die Prozedur aus Listing 1. Die Prozedur deklariert zun&auml;chst die ben&ouml;tigen Objektvariablen. <b>objOutlook <\/b>f&uuml;llen wir hier mit einem Verweis auf eine neue Instanz von Outlook, die bei Vorhandensein einer Instanz jedoch mit der bestehenden Instanz gef&uuml;llt wird. Mit <b>objMAPI <\/b>referenzieren wir den MAPI-Namespace von Outlook.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>EMailSendenUndVerschieben()\r\n     <span style=\"color:blue;\">Dim <\/span>objOutlook<span style=\"color:blue;\"> As <\/span>Outlook.Application\r\n     <span style=\"color:blue;\">Dim <\/span>objMAPI<span style=\"color:blue;\"> As <\/span>Outlook.NameSpace\r\n     <span style=\"color:blue;\">Dim <\/span>objMailItem<span style=\"color:blue;\"> As <\/span>Outlook.MailItem\r\n     <span style=\"color:blue;\">Dim <\/span>objFolder<span style=\"color:blue;\"> As <\/span>Outlook.Folder\r\n         \r\n     <span style=\"color:blue;\">Set<\/span> objOutlook = <span style=\"color:blue;\">New<\/span> Outlook.Application\r\n     <span style=\"color:blue;\">Set<\/span> objMAPI = objOutlook.GetNamespace(\"MAPI\")\r\n     <span style=\"color:blue;\">Set<\/span> objFolder = objMAPI.PickFolder\r\n         \r\n     <span style=\"color:blue;\">Set<\/span> objMailItem = Application.CreateItem(olMailItem)\r\n     <span style=\"color:blue;\">With<\/span> objMailItem\r\n         .To = \"Info@amvshop.de\"\r\n         .Subject = \"Betreff der E-Mail\"\r\n         .Body = \"Dies ist der Inhalt der E-Mail.\"\r\n         <span style=\"color:blue;\">Set<\/span> .SaveSentMessageFolder = objFolder\r\n         .Send\r\n     End <span style=\"color:blue;\">With<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Senden einer neuen E-Mail und Verschieben in einen zuvor gew&auml;hlten Ordner<\/span><\/b><\/p>\n<p>Dieser wiederum erlaubt uns, die <b>PickFolder<\/b>-Funktion zu nutzen, um den Dialog aus aufzurufen, der uns die Auswahl eines beliebigen Ordners erlaubt. Hier w&auml;hlen wir den Ordner <b>Posteingang <\/b>aus (siehe Bild 3), der nun mit der Variablen <b>objFolder <\/b>referenziert wird.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_05\/pic_440_003.png\" alt=\"Auswahl des Zielordners\" width=\"424,6267\" height=\"359,1129\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Auswahl des Zielordners<\/span><\/b><\/p>\n<p>Anschlie&szlig;end erstellen wir ein neues <b>MailItem<\/b>-Objekt mit der <b>CreateItem<\/b>-Methode und dem Parameter <b>olMailItem<\/b>. F&uuml;r diese legen wir die &uuml;blichen Eigenschaften <b>To<\/b>, <b>Subject <\/b>und <b>Body <\/b>fest. Au&szlig;erdem stellen wir mit der Eigenschaft <b>SaveSendMessageFolder <\/b>auf den zuvor ausgew&auml;hlten und mit <b>objFolder <\/b>referenzierten Ordner ein. Schlie&szlig;lich rufen wir die <b>Send<\/b>-Methode auf und senden die E-Mail somit.<\/p>\n<p>Sofern wir gerade den Posteingang angezeigt haben, erscheint dort umgehend die gesendete E-Mail (au&szlig;er, es dauert in Deinem System etwas l&auml;nger, bis E-Mails den Postausgang verlassen).<\/p>\n<h2>Zielordner ohne Auswahldialog festlegen<\/h2>\n<p>Normalerweise m&ouml;chtest Du nicht immer erneut den Zielordner ausw&auml;hlen. Daher kannst Du diesen auch direkt angeben. Dazu sind zwei Schritte n&ouml;tig:<\/p>\n<ul>\n<li>Du musst einmalig den Pfad des Zielordners ermitteln, beispielsweise in der Form <b>\\\\Outlook\\Posteingang<\/b>.<\/li>\n<li>Dann ben&ouml;tigen wir eine Funktion, die auf Basis dieser Pfadangabe den zugrunde liegenden Ordner in Form eines <b>Folder<\/b>-Objekts ermittelt und zur&uuml;ckgibt.<\/li>\n<\/ul>\n<p>Die erste Aufgabe k&ouml;nnen wir leicht mit der folgenden Prozedur erledigen:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>GetPickFolderPath()<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>objOutlook<span style=\"color:blue;\"> As <\/span>Outlook.Application\r\n     <span style=\"color:blue;\">Dim <\/span>objMAPI<span style=\"color:blue;\"> As <\/span>Outlook.NameSpace\r\n     <span style=\"color:blue;\">Dim <\/span>objFolder<span style=\"color:blue;\"> As <\/span>Outlook.Folder\r\n     <span style=\"color:blue;\">Set<\/span> objOutlook = <span style=\"color:blue;\">New<\/span> Outlook.Application\r\n     <span style=\"color:blue;\">Set<\/span> objMAPI = objOutlook.GetNamespace(\"MAPI\")\r\n     <span style=\"color:blue;\">Set<\/span> objFolder = objMAPI.PickFolder\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> objFolder Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n         GetPickFolderPath = objFolder.FolderPath\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p>Diese &ouml;ffnet den bereits weiter oben vorgestellten Dialog zur Auswahl eines Ordners und gibt den Pfad zu dem gefundenen Order als Zeichenkette zur&uuml;ck. Falls der Benutzer die Auswahl durch Anklicken der <b>Abbrechen<\/b>-Schaltfl&auml;che abbricht, wird eine leere Zeichenkette zur&uuml;ckgegeben.<\/p>\n<p>Mit diesem Ausdruck, zum Beispiel <b>\\\\Outlook\\Posteingang<\/b>, k&ouml;nnen wir mit der Funktion <b>GetFolderFromPath <\/b>aus Listing 2 ein <b>Folder<\/b>-Objekt ermitteln. Leider gibt es keine direkte Funktion etwa des <b>NameSpace<\/b>-Objekts, um auf Basis eines Pfades ein <b>Folder<\/b>-Objekt zur&uuml;ckzuliefern. Deshalb holen wir es uns mit einer selbst entwickelten Funktion.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>GetFolderFromPath(strPath<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As <\/span>Outlook.Folder\r\n     <span style=\"color:blue;\">Dim <\/span>objOutlook<span style=\"color:blue;\"> As <\/span>Outlook.Application\r\n     <span style=\"color:blue;\">Dim <\/span>objMAPI<span style=\"color:blue;\"> As <\/span>Outlook.NameSpace\r\n     <span style=\"color:blue;\">Dim <\/span>objFolder<span style=\"color:blue;\"> As <\/span>Outlook.Folder\r\n     <span style=\"color:blue;\">Dim <\/span>strFolders()<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strFolderNames()<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>j<span style=\"color:blue;\"> As Integer<\/span>\r\n     strFolders = <span style=\"color:blue;\">Split<\/span>(strPath, \"\\\")\r\n     For i = <span style=\"color:blue;\">LBound<\/span>(strFolders) To <span style=\"color:blue;\">UBound<\/span>(strFolders)\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">Len<\/span>(strFolders(i)) = 0<span style=\"color:blue;\"> Then<\/span>\r\n             ReDim Preserve strFolderNames(j)\r\n             strFolderNames(j) = strFolders(i)\r\n             j = j + 1\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> i\r\n     <span style=\"color:blue;\">Set<\/span> objOutlook = <span style=\"color:blue;\">New<\/span> Outlook.Application\r\n     <span style=\"color:blue;\">Set<\/span> objMAPI = objOutlook.GetNamespace(\"MAPI\")\r\n     <span style=\"color:blue;\">Set<\/span> objFolder = objMAPI.Folders(strFolderNames(0))\r\n     For j = <span style=\"color:blue;\">LBound<\/span>(strFolderNames) + 1 To <span style=\"color:blue;\">UBound<\/span>(strFolderNames)\r\n         <span style=\"color:blue;\">Set<\/span> objFolder = objFolder.Folders(strFolderNames(j))\r\n     <span style=\"color:blue;\">Next<\/span> j\r\n     <span style=\"color:blue;\">Set<\/span> GetFolderFromPath = objFolder\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Ermitteln eines Folder-Objekts auf Basis des Pfades<\/span><\/b><\/p>\n<p>Wir &uuml;bergeben dieser den Pfad zum gew&uuml;nschten Ordner. Die Funktion deklariert zwei Arrays. Das erste Array ben&ouml;tigen wir f&uuml;r das Ergebnis der <b>Split<\/b>-Funktion, die wir mit dem Trennzeichen <b>\\ <\/b>auf den mit <b>strPath <\/b>gelieferten Pfad anwenden. Damit erzeugen wir ein Array, dass die an den Backslash-Zeichen aufgesplittete Zeichenketten aus <b>strPath <\/b>erh&auml;lt. Bei <b>\\\\Outlook\\Posteingang <\/b>ist das Element mit dem Index <b>0 <\/b>eine leere Zeichenkette, das mit dem Index <b>1 <\/b>auch, der Index <b>2 <\/b>enth&auml;lt <b>Outlook <\/b>und der Index <b>3 <\/b>enth&auml;lt <b>Posteingang<\/b>.<\/p>\n<p>Das zweite Array soll alle Elemente des ersten Arrays erhalten, die keine leere Zeichenkette enthalten. Dazu durchlaufen wir eine <b>For&#8230;Next<\/b>-Schleife &uuml;ber alle Elemente aus <b>strFolders <\/b>und pr&uuml;fen, ob das aktuelle Element eine leere Zeichenkette enth&auml;lt. Falls nicht, dimensionieren wir das Array <b>strFolderNames <\/b>in der entsprechenden Gr&ouml;&szlig;e und h&auml;ngen das aktuelle Element des ersten Arrays hinten an.<\/p>\n<p>Nun k&ouml;nnen wir auf Outlook zugreifen, uns das MAPI-Namespace holen und erst einmal den Ordner referenzieren, der den Namen aus dem ersten Element von <b>strFolderNames <\/b>enth&auml;lt. Danach durchlaufen wir die &uuml;brigen Elemente des Arrays <b>strFolderNames <\/b>und  ermitteln das jeweils n&auml;chste untergeordnete Element aus der <b>Folders<\/b>-Auflistung. Dieses weisen wir wieder der Variablen <b>objFolder <\/b>zu. Auf diese Weise arbeiten wir uns bis zum untersten <b>Folder<\/b>-Element durch und geben dieses schlie&szlig;lich als Funktionsergebnis zur&uuml;ck.<\/p>\n<p>Damit ausgestattet k&ouml;nnen wir die eingangs beschriebene Prozedur wie folgt anpassen, wenn wir wollen, dass die versendete E-Mail direkt im Posteingang landet:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>EMailSendenUndVerschiebenNachPfad()\r\n     ...\r\n     <span style=\"color:blue;\">Set<\/span> objFolder = _\r\n         GetFolderFromPath(\"<\/font>Outlook\\Posteingang\\\")\r\n     ...\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Statt dem Posteingangsordner k&ouml;nnen wir hier auch jeden anderen Ordner angeben.<\/p>\n<p>Damit haben wir das Verschieben von per VBA erstellten E-Mails in den gew&uuml;nschten Ordner bereits programmiert und k&ouml;nnen uns nun einer anspruchsvolleren Aufgabe zuwenden &#8211; dem Verschieben E-Mails, die wir &uuml;ber die Benutzeroberfl&auml;che von Outlook gesendet haben.<\/p>\n<h2>Per Outlook gesendete E-Mails in anderen Ordner verschieben<\/h2>\n<p>Warum ist das anspruchsvoller? Weil es nicht ausreicht, sich einfach nur in den Prozess reinzuh&auml;ngen, mit dem die E-Mail verschickt wird. Sondern wir m&uuml;ssen irgendwie ein Ereignis abfangen, das ausgel&ouml;st wird, wenn der Benutzer die E-Mail versendet hat. Welches nutzen wir hier optimalerweise? Woran erkennen wir, dass eine E-Mail versendet wurde?<\/p>\n<p>Offensichtlich ist eine E-Mail erst dann erfolgreich versendet worden, wenn sie im Ordner <b>Gesendete Objekte <\/b>gelandet ist. Wir m&uuml;ssen also ein Ereignis definieren, das ausgel&ouml;st wird, wenn ein Element zu diesem Ordner hinzugef&uuml;gt wird. Dann brauchen wir noch eine M&ouml;glichkeit, die Regeln festzulegen, nach denen wir bestimmte E-Mails vom Ordner <b>Gesendete Objekte <\/b>in den gew&uuml;nschten Ordner &uuml;bertragen.<\/p>\n<p>Wir schauen uns zun&auml;chst einmal die Basisversion ohne Regeln an. W&auml;hrend es beim ersten Beispiel keine Rolle spielte, ob wir den Code in einem Standardmodul oder einen Klassenmodul wie <b>ThisOutlookSession <\/b>angelegt haben, kommt dies nun zum Tragen. Wir wollen eine Objektvariable mit dem Schl&uuml;sselwort <b>WithEvents <\/b>deklarieren, damit wir seine Ereignisse implementieren wollen.<\/p>\n<p>Deshalb f&uuml;gen wir den Code in das Modul <b>ThisOutlookSession <\/b>im VBA-Projekt von Outlook ein. Wenn Du diesen Code im VBA-Projekt einer anderen Anwendung nutzen m&ouml;chtest, musst Du die folgenden Elemente in ein Klassenmodul einf&uuml;gen, das Du dann initialisierst &#8211; wir zeigen sp&auml;ter, wie das gelingt.<\/p>\n<p>Wir deklarieren erst einmal die Objektvariable f&uuml;r eine <b>Items<\/b>-Auflistung, &uuml;ber die wir die im Ordner <b>Gesendete Elemente <\/b>enthaltenen Elemente referenzieren:<\/p>\n<pre><span style=\"color:blue;\">Public <\/span>WithEvents objItems<span style=\"color:blue;\"> As <\/span>Outlook.Items<\/pre>\n<p>Dann rufen wir eine Prozedur namens Aktivieren auf. Diese referenziert die aktuelle Outlook-Instanz und dar&uuml;ber den MAPI-Namespace und den Ordner <b>Gesendete Elemente<\/b>, den wir mit der Funktion <b>GetDefaultFolder <\/b>mit dem Parameter <b>olFolderSentMail <\/b>holen. Dessen <b>Items<\/b>-Auflistung weisen wir schlie&szlig;lich der oben definierten Variablen <b>objItems <\/b>zu:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>Aktivieren()\r\n     <span style=\"color:blue;\">Dim <\/span>objOutlook<span style=\"color:blue;\"> As <\/span>Outlook.Application\r\n     <span style=\"color:blue;\">Dim <\/span>objMAPI<span style=\"color:blue;\"> As <\/span>Outlook.NameSpace\r\n     <span style=\"color:blue;\">Dim <\/span>objFolder<span style=\"color:blue;\"> As <\/span>Outlook.Folder\r\n     <span style=\"color:blue;\">Set<\/span> objOutlook = Application ''<span style=\"color:blue;\">New<\/span> Outlook.Application\r\n     <span style=\"color:blue;\">Set<\/span> objMAPI = objOutlook.GetNamespace(\"MAPI\")\r\n     <span style=\"color:blue;\">Set<\/span> objFolder = _\r\n         objMAPI.GetDefaultFolder(olFolderSentMail)\r\n     <span style=\"color:blue;\">Set<\/span> objItems = objFolder.Items\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Schlie&szlig;lich implementieren wir das Ereignis <b>ItemAdd <\/b>der Objektvariablen <b>objItems<\/b>. Dazu w&auml;hlen wir <b>objItems <\/b>im linken Listenfeld des VBA-Fensters aus und erhalten so automatisch eine neue, leere Ereignisprozedur f&uuml;r das Standardereignis <b>ItemAdd <\/b>dieser Klasse. Diese f&uuml;llen wir wie folgt:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>objItems_ItemAdd(ByVal Item<span style=\"color:blue;\"> As Object<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>objMailitem<span style=\"color:blue;\"> As <\/span>Outlook.MailItem\r\n     <span style=\"color:blue;\">Dim <\/span>objFolder<span style=\"color:blue;\"> As <\/span>Outlook.Folder\r\n     Select Case TypeName(Item)\r\n         <span style=\"color:blue;\">Case <\/span>\"MailItem\"\r\n             <span style=\"color:blue;\">Set<\/span> objMailitem = Item\r\n             <span style=\"color:blue;\">Set<\/span> objFolder = _\r\n                 GetFolderFromPath(\"<\/font>Outlook\\Posteingang\")\r\n             objMailitem.Move objFolder\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Diese Ereignisprozedur liefert mit dem Parameter <b>Item<\/b> einen Verweis auf das zum Ordner <b>Gesendete Elemente <\/b>hinzugef&uuml;gten Elements. Wir pr&uuml;fen, ob es sich dabei um ein Element des Typs <b>MailItem <\/b>handelt. Falls ja, referenzieren wir es mit der Variablen <b>objMailItem <\/b>und ermitteln f&uuml;r <b>objFolder <\/b>den Zielordner, in diesem Fall <b>\\\\Outlook\\Posteingang <\/b>(nicht, dass dieser Zielordner sinnvoll w&auml;re, aber wie sehen diesen beim Experimentieren direkt).<\/p>\n<p>Dann rufen wir die Methode <b>Move <\/b>auf und &uuml;bergeben als Parameter den Verweis auf den Ordner, in den die E-Mail verschoben werden soll.<\/p>\n<p>Wenn wir nun eine E-Mail senden, wird diese automatisch direkt in den Posteingang verschoben.<\/p>\n<h2>Beim Start automatisch aktivieren<\/h2>\n<p>Nun wird die Objektvariable <b>objItems <\/b>beim Beenden von Outlook automatisch geleert und beim Neustart nicht automatisch wieder gef&uuml;llt. Das k&ouml;nnen wir jedoch erreichen, indem wir die Funktion <b>Aktivieren <\/b>automatisch beim Start von Outlook aufrufen. Das erledigen wir, indem wir den Aufruf einfach in die folgende Prozedur eintragen:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Application_Startup()\r\n     <span style=\"color:blue;\">Call<\/span> Aktivieren\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Diese Prozedur wird, wenn sie in der Klasse <b>ThisOutlookSession <\/b>platziert ist, beim Start von Outlook gestartet.<\/p>\n<p>Damit fehlt uns noch die M&ouml;glichkeit, verschiedene Bedingungen hinzuzuf&uuml;gen und festzulegen, in welchen Ordner die E-Mails je nach Bedingung landen sollen. <\/p>\n<p>Hier m&uuml;ssen wir uns erst einmal &uuml;berlegen, welche Bedingungen wir nutzen wollen. Typischerweise ist oft der Adressat der E-Mail interessant f&uuml;r eine solche Bedingung. Manche Adressaten sind mit speziellen Rollen verkn&uuml;pft, in deren Kontext es oft entsprechende Ordner in Outlook gibt. Ein Beispiel: E-Mails an die Steuerberaterin sollen im Ordner <b>Buchhaltung <\/b>landen. Oder E-Mails an Partner oder Partnerin in einem Ordner namens <b>Privat<\/b>. Manchmal gibt es auch Ordner f&uuml;r den E-Mail-Austausch mit bestimmten Dienstleistern &#8211; auch hier ist es sinnvoll, diese E-Mails am Empf&auml;nger zu identifizieren und sie gleich in den entsprechenden Ordner zu verschieben.<\/p>\n<h2>E-Mail des Adressaten auslesen<\/h2>\n<p>Auch wenn wir die E-Mail-Adresse des Adressaten einer E-Mail mit der <b>To<\/b>-Eigenschaft angegeben haben, k&ouml;nnen wir diese noch l&auml;ngst nicht &uuml;ber diese Eigenschaft auslesen. <\/p>\n<p>Wenn wir die E-Mail-Adresse des Empf&auml;ngers in die E-Mail eingeben, erscheinen in der Regel Vorschl&auml;ge f&uuml;r dem Empf&auml;nger. Hier wird neben der E-Mail-Adresse manchmal auch noch eine weitere Information angezeigt (siehe Bild 4). Wenn wir diese ausw&auml;hlen oder die dort verwendete E-Mail-Adresse eingeben, stellt Outlook den Wert f&uuml;r <b>To <\/b>automatisch auf den oben angezeigten Wert ein. Wir sollten die Bedingung also nicht so gestalten, dass wir das <b>To<\/b>-Feld nach einer E-Mail durchsuchen. Tats&auml;chlich kann <b>To <\/b>sogar mehrere E-Mail-Adressen aufnehmen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_05\/pic_440_004.png\" alt=\"Ein Alias f&uuml;r die E-Mail-Adresse\" width=\"624,6265\" height=\"331,8628\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Ein Alias f&uuml;r die E-Mail-Adresse<\/span><\/b><\/p>\n<p>Um an die tats&auml;chlich hinter der Adresse steckende E-Mail-Adresse zu kommen, verwenden wir die <b>Recipients<\/b>-Auflistung des <b>MailItem<\/b>-Objekts. Wenn wir f&uuml;r <b>To<\/b>\/<b>An <\/b>mehrere Empf&auml;nger eingegeben haben, enth&auml;lt die <b>Recipients<\/b>-Auflistung entsprechend viele Eintr&auml;ge. Wir m&uuml;ssten also eigentlich alle Eintr&auml;ge durchlaufen und dann pr&uuml;fen, ob die gesuchte E-Mail-Adresse in der Auflistung enthalten ist. Das lassen wir an dieser Stelle aus und pr&uuml;fen stattdessen nur die erste darin enthaltene E-Mail-Adresse. Das sollte f&uuml;r unseren Fall ausreichen, denn die meisten E-Mails in Zusammen mit Buchhaltung oder bestimmten Gesch&auml;ftspartnern werden meist an einen Ansprechpartner geschickt. Sollen noch weitere Personen informiert werden, nutzt man normalerweise das Feld Cc.<\/p>\n<p>Betrachten wir nur diesen Fall, k&ouml;nnen wir die Version der Prozedur <b>objItems_ItemAdd<\/b> aus Listing 3 verwenden. Hier untersuchen wir die verschiedenen Bedingungen in einer <b>Select Case<\/b>-Bedingung. Da wir als Vergleichskriterium den Wert <b>True <\/b>angegeben haben, k&ouml;nnen wir in die <b>Case<\/b>-Zweige Bedingungen wie die folgende einf&uuml;gen:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>objItems_ItemAdd(ByVal Item<span style=\"color:blue;\"> As Object<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>objMailitem<span style=\"color:blue;\"> As <\/span>Outlook.MailItem\r\n     <span style=\"color:blue;\">Dim <\/span>objFolder<span style=\"color:blue;\"> As <\/span>Outlook.Folder\r\n     Select Case TypeName(Item)\r\n         <span style=\"color:blue;\">Case <\/span>\"MailItem\"\r\n             <span style=\"color:blue;\">Set<\/span> objMailitem = Item\r\n             Select Case <span style=\"color:blue;\">True<\/span>\r\n                 <span style=\"color:blue;\">Case <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">InStr<\/span>(1, objMailitem.Recipients(1).Address, \"info@amvshop.de\") = 0\r\n                     <span style=\"color:blue;\">Set<\/span> objFolder = GetFolderFromPath(\"<\/font>Outlook\\Posteingang\\Bestellungen\")\r\n                 <span style=\"color:blue;\">Case <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">InStr<\/span>(1, objMailitem.Recipients(1).Address, \"andre@minhorst.com\") = 0\r\n                     <span style=\"color:blue;\">Set<\/span> objFolder = GetFolderFromPath(\"<\/font>Outlook\\Posteingang\\Buchhaltung\")\r\n             <span style=\"color:blue;\">End Select<\/span>\r\n             <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> objFolder Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n                 objMailitem.Move objFolder\r\n             <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Verschieben von E-Mails mit verschiedenen Bedingungen<\/span><\/b><\/p>\n<pre><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">InStr<\/span>(1, objMailitem.Recipients(1).Address, _\r\n     \"info@amvshop.de\") = 0<\/pre>\n<p>Wir pr&uuml;fen hier zum Beispiel, ob innerhalb der Adresse des ersten angegebenen Empf&auml;ngers die E-Mail-Adresse <b>info@amvshop.de <\/b>befindet. Ist das der Fall, f&uuml;llen wir die <b>objFolder<\/b>-Variable mit dem Ordner, in den E-Mails mit dieser Empf&auml;ngeradresse landen sollen.<\/p>\n<p>Nach der <b>Select Case<\/b>-Bedingung pr&uuml;ft die Prozedur, ob <b>objFolder <\/b>einen Verweis auf einen Ordner enth&auml;lt und verschiebt die E-Mail in diesen Ordner.<\/p>\n<p>Auf die gleiche Weise haben wir noch einen <b>Case<\/b>-Zweig f&uuml;r die E-Mail-Adresse <b>andre@minhorst<\/b>.com hinzugef&uuml;gt. Mails an diese Adresse sollen in den Ordner <b>\\\\Outlook\\Posteingang\\Buchhaltung <\/b>verschoben werden.<\/p>\n<p>Nun k&ouml;nnen wir sicher f&uuml;r unsere eigenen Zwecke die Bedingungen zum Verschieben versendeter E-Mails wie hier geschehen direkt im Quellcode verwalten. Unseren Benutzern sollten wir das aber nicht zumuten. Daher suchen wir nun nach einem Weg, um die Bedingungen anderweitig zu verwalten. Optimal w&auml;re ein Formular, in das wir in einer Liste jeweils links die Empf&auml;nger-E-Mail-Adresse speichern k&ouml;nnten und rechts den Ordner, in den diese E-Mails nach dem Senden verschoben werden sollen.<\/p>\n<p>Allerdings bietet Outlook keine einfache M&ouml;glichkeit, dies zu erledigen. Ein Kompromiss k&ouml;nnte eine Textdatei sein, in die der Benutzer die verschiedenen Kombinationen aus Empf&auml;ngeradressen und Ordnern eintragen kann &#8211; getrennt durch ein Zeichen wie beispielsweise das Pipe-Zeichen (<b>|<\/b>).<\/p>\n<p>Diese Textdatei soll beispielsweise wie in Bild 5 aussehen. Nun ben&ouml;tigen wir noch zwei Dinge:<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_05\/pic_440_005.png\" alt=\"Textdatei mit den Zuordnungen der E-Mails zu den Ordnern\" width=\"524,6265\" height=\"252,0169\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Textdatei mit den Zuordnungen der E-Mails zu den Ordnern<\/span><\/b><\/p>\n<ul>\n<li>Eine M&ouml;glichkeit, wo wir die Textdatei speichern beziehungsweise wo der Benutzer diese schnell finden und &ouml;ffnen kann und<\/li>\n<li>eine Prozedur, welche die Daten aus der Textdatei einliest und diese nutzt, um sp&auml;ter die gesendeten E-Mails den entsprechenden Ordnern zuzuordnen.<\/li>\n<\/ul>\n<p>Wo wir diese Datei speichern, k&ouml;nnen wir dem Benutzer &uuml;berlassen &#8211; er muss dann einmalig im Code in einer Konstanten den Speicherort festlegen. Diesen kann er dann nach Bedarf anpassen.<\/p>\n<h2>Konfigurationsdatei schnell verf&uuml;gbar machen<\/h2>\n<p>Damit haben wir allerdings noch keine L&ouml;sung daf&uuml;r, wie der Benutzer diese Datei schnell &ouml;ffnen kann. Dazu bieten wir am besten einen Ribbonbefehl an.<\/p>\n<p>Wenn der Benutzer diesen anklickt, soll die Datei automatisch im jeweiligen Texteditor ge&ouml;ffnet werden. Um eine solche Schaltfl&auml;che hinzuzuf&uuml;gen, gibt es zwei M&ouml;glichkeiten:<\/p>\n<ul>\n<li>Wir passen die eingebauten Ribbondefinitionen &uuml;ber die Benutzeroberfl&auml;che an. Hier k&ouml;nnen wir eine Schaltfl&auml;che hinzuf&uuml;gen, die eine im VBA-Projekt von Outlook enthaltene Prozedur aufruft.<\/li>\n<li>Oder wir erstellen direkt ein COM-Add-In, das einen individuellen Ribbonbutton bereitstellt und die auch direkt die &uuml;brigen Elemente der hier programmierten L&ouml;sung aufnimmt. So haben wir die L&ouml;sung kompakt in eine DLL verpackt und k&ouml;nnen diese leicht mit einem kleinen Setup weitergeben oder mit einer Anleitung, wie diese manuell registriert werden kann.<\/li>\n<\/ul>\n<p>Die erste Idee schauen wir uns gleich in diesem Artikel an, die zweite betrachten wir in einem eigenen Artikel namens <b>Outlook: Gesendete Mails per COM-Add-In verschieben <\/b>(<b>www.vbentwickler.de\/441<\/b>).<\/p>\n<h2>Prozedur zum &Ouml;ffnen der Konfigurationsdatei<\/h2>\n<p>Wir legen eine Konstante zum Speichern des Pfades zur Konfigurationsdatei an:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>Const cStrPath<span style=\"color:blue;\"> As String<\/span> = _\r\n     \"C:\\...\\SentMailFolders.txt\"<\/pre>\n<p>Au&szlig;erdem hinterlegen wir eine Prozedur, mit der wir diese Datei &ouml;ffnen k&ouml;nnen:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>OpenConfigurationFile()\r\n     ShellExecuteA 0, \"Open\", cStrPath, vbNullString, vbNullString, SW_NORMAL\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Die hier verwendete API-Funktion hinterlegen wir gleich in zwei Versionen f&uuml;r die 64-Bit und die 32-Bit-Variante:<\/p>\n<pre>#If Win64 Then\r\n     <span style=\"color:blue;\">Public <\/span>Declare PtrSafe Function ShellExecuteA Lib _\r\n        \"Shell32\" (ByVal hWnd<span style=\"color:blue;\"> As Long<\/span>Ptr, ByVal _\r\n        lpOperation<span style=\"color:blue;\"> As String<\/span>, ByVal lpFile<span style=\"color:blue;\"> As String<\/span>, _\r\n        ByVal lpParameters<span style=\"color:blue;\"> As String<\/span>, ByVal lpDirectory _\r\n       <span style=\"color:blue;\"> As String<\/span>, ByVal nCmdShow<span style=\"color:blue;\"> As Long<\/span>)<span style=\"color:blue;\"> As Long<\/span>\r\n#Else\r\n     <span style=\"color:blue;\">Public <\/span>Declare Function ShellExecuteA Lib \"Shell32\" _\r\n         (ByVal hWnd<span style=\"color:blue;\"> As Long<\/span>, ByVal lpOperation<span style=\"color:blue;\"> As <\/span>_\r\n         String, ByVal lpFile<span style=\"color:blue;\"> As String<\/span>, ByVal _\r\n         lpParameters<span style=\"color:blue;\"> As String<\/span>, ByVal lpDirectory<span style=\"color:blue;\"> As <\/span>_\r\n         String, ByVal nCmdShow<span style=\"color:blue;\"> As Long<\/span>)<span style=\"color:blue;\"> As Long<\/span>\r\n#End If<\/pre>\n<p>Au&szlig;erdem ben&ouml;tigen wir die folgende Konstante:<\/p>\n<pre><span style=\"color:blue;\">Public <\/span>Const SW_NORMAL = 1<\/pre>\n<p>Dies alles legen wir in einem Standardmodul an. Rufen wir nun die Prozedur <b>OpenConfigurationFile <\/b>auf, erscheint die Textdatei im Texteditor.<\/p>\n<h2>Ribbon um Schaltfl&auml;che zum &Ouml;ffnen der Textdatei erweitern<\/h2>\n<p>Nun wollen wir diese Prozedur &uuml;ber das Ribbon verf&uuml;gbar machen.<\/p>\n<p>Dazu wechseln wir zum Hauptfenster von Outlook und klicken oben im Ribbon auf die Schaltfl&auml;che mit dem nach unten zeigenden Pfeil und w&auml;hlen danach den Eintrag <b>Weitere Befehle&#8230; <\/b>aus (siehe Bild 6).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_05\/pic_440_007.png\" alt=\"Anzeigen der Ribbon-Optionen\" width=\"424,6267\" height=\"534,3615\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Anzeigen der Ribbon-Optionen<\/span><\/b><\/p>\n<p>Im nun erscheinenden Dialog <b>Outlook-Optionen <\/b>wechseln wir zun&auml;chst zum Bereich <b>Men&uuml;band anpassen<\/b>. Dann w&auml;hlen wir unter Befehle ausw&auml;hlen den Eintrag <b>Makros <\/b>aus (siehe Bild 7).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_05\/pic_440_006.png\" alt=\"Erweitern des Ribbons um einen benutzerdefinierten Makroaufruf\" width=\"549,6265\" height=\"340,9339\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Erweitern des Ribbons um einen benutzerdefinierten Makroaufruf<\/span><\/b><\/p>\n<p>In der Liste unter dem Auswahlfeld finden wir nun auch den Eintrag <b>Project1.ThisOutlookSession.OpenConfigurationFile <\/b>vor (siehe Bild 8).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_05\/pic_440_008.png\" alt=\"Die soeben erstellte Prozedur\" width=\"599,6265\" height=\"335,3845\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 8: Die soeben erstellte Prozedur<\/span><\/b><\/p>\n<p>Um diesen zum Ribbon hinzuzuf&uuml;gen, wollen wir zuvor noch einen guten Ort daf&uuml;r finden. Da sich die hier programmierte Aktion auf die Ordner bezieht, halten wir das Tab <b>Ordner <\/b>f&uuml;r einen guten Ort &#8211; am Besten im Bereich <b>Eigenschaften<\/b> (siehe Bild 9). Allerdings k&ouml;nnen wir bestehenden Gruppen keine Elemente zuweisen. Wir haben an dieser Stelle zwei M&ouml;glichkeiten:<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_05\/pic_440_009.png\" alt=\"Hier wollen wir unsere Schaltfl&auml;che einf&uuml;gen.\" width=\"700\" height=\"146,728\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 9: Hier wollen wir unsere Schaltfl&auml;che einf&uuml;gen.<\/span><\/b><\/p>\n<ul>\n<li>Wir erstellen eine eigene Gruppe f&uuml;r unseren Befehl oder<\/li>\n<li>wir bauen die Gruppe <b>Eigenschaften <\/b>nach und f&uuml;gen unseren Befehl noch hinzu. Die eingebaute Gruppe k&ouml;nnen wir dann entfernen. Und keine Sorge &#8211; Du kannst den Originalzustand jederzeit wiederherstellen.<\/li>\n<\/ul>\n<p>Wir haben nur die drei Elemente hinzugef&uuml;gt, die wir auch im Ribbon sehen, und unseren benutzerdefinierten Befehl.<\/p>\n<p>Diesen haben wir noch umbenannt, denn wir wollen dort nicht den Text <b>Project1.ThisOutlookSession.OpenConfigurationFile<\/b> sehen, sondern beispielsweise <b>Konfiguration f&uuml;r gesendete Elemente<\/b> (siehe Bild 10). Hier w&auml;hlen wir au&szlig;erdem aus den wenigen verf&uuml;gbaren Icons das am sinnvollsten erscheinende aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_05\/pic_440_010.png\" alt=\"Hinzuf&uuml;gen einer eigenen Gruppe\" width=\"649,627\" height=\"441,8972\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 10: Hinzuf&uuml;gen einer eigenen Gruppe<\/span><\/b><\/p>\n<p>Nun klicken wir noch mit der rechten Maustaste auf die eingebaute Gruppe <b>Eigenschaften <\/b>und w&auml;hlen f&uuml;r diese den Befehl <b>Entfernen<\/b> aus (siehe Bild 11).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_05\/pic_440_011.png\" alt=\"Entfernen der eingebauten Gruppe\" width=\"424,6267\" height=\"352,5621\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 11: Entfernen der eingebauten Gruppe<\/span><\/b><\/p>\n<p>Nun schlie&szlig;en wir den Dialog <b>Outlook-Optionen <\/b>und schauen uns das Ribbon im Bereich <b>Ordner <\/b>an. Hier finden wir in der Gruppe <b>Eigenschaften <\/b>nun den Eintrag <b>Konfiguration <\/b>f&uuml;r gesendete Elemente vor (siehe Bild 12).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_05\/pic_440_012.png\" alt=\"Der neue Ribboneintrag\" width=\"599,6265\" height=\"189,633\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 12: Der neue Ribboneintrag<\/span><\/b><\/p>\n<p>Klicken wir diesen an, wird die Prozedur <b>OpenConfigurationFile <\/b>ausgel&ouml;st, was die Konfigurationsdatei &ouml;ffnet.<\/p>\n<h2>Textdatei neu erstellen, falls diese nicht vorhanden ist<\/h2>\n<p>Wenn der Benutzer diese Funktion zum ersten Mal benutzt, ist die Textdatei unter Umst&auml;nden noch nicht vorhanden. Damit diese nicht zu einem Fehler f&uuml;hrt, f&uuml;gen wir noch Code hinzu, der diese initial einmal erstellt und mit einem Beispieldatensatz f&uuml;llt. Diese hei&szlig;t <b>CreateTextFile <\/b>und erwartet den Pfad zu der zu erstellenden Datei als Parameter.<\/p>\n<p>Sie verwendet das <b>FileStream<\/b>-Objekt, um mit der Methode <b>CreateTextFile <\/b>eine neue Textdatei f&uuml;r den angegebenen Pfad zu erstellen. Dann schreibt sie mit der <b>WriteLine<\/b>-Methode direkt eine Beispielzeile mit einer Zuweisung einer E-Mail-Adresse zu einem Ordner hinzu. Schlie&szlig;lich schlie&szlig;t sie die Datei (siehe Listing 4).<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>CreateTextFile(strPath<span style=\"color:blue;\"> As String<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>objFSO<span style=\"color:blue;\"> As Object<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>objFileStream<span style=\"color:blue;\"> As Object<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> objFSO = CreateObject(\"Scripting.FileSystemObject\")\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> objFSO.FileExists(strPath)<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> objFileStream = objFSO.CreateTextFile(strPath, <span style=\"color:blue;\">True<\/span>)\r\n         objFileStream.WriteLine \"test@test.de|<\/font>Outlook\\Posteingang\"\r\n         objFileStream.Close\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> objFileStream = Nothing\r\n     <span style=\"color:blue;\">Set<\/span> objFSO = Nothing\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Prozedur zum Erstellen einer Textdatei<\/span><\/b><\/p>\n<p>Unserer Prozedur f&uuml;gen wir noch eine Abfrage hinzu, die pr&uuml;ft, ob die Textdatei aus der Konstanten <b>cStrPath <\/b>bereits vorhanden ist. Ist das nicht der Fall, rufen wir die Prozedur <b>CreateTextFile <\/b>auf und &uuml;bergeben dieser den Pfad zu der zu erstellenden Textdatei. Danach &ouml;ffnen wir diese dann mit der <b>ShellExecuteA<\/b>-Anweisung:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>OpenConfigurationFile()\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(Dir(cStrPath)) = 0<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Call<\/span> CreateTextFile(cStrPath)\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     ShellExecuteA 0, \"Open\", cStrPath, vbNullString, _\r\n         vbNullString, SW_NORMAL\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Prozedur objItems_ItemAdd auf Textdatei anpassen<\/h2>\n<p>Die oben programmierte Version der Prozedur <b>objItems_ItemAdd<\/b>, die beim Hinzuf&uuml;gen eines Elements zum Ordner <b>Gesendete Elemente <\/b>ausgel&ouml;st wird, untersucht die eingehenden Elemente bisher auf die beiden fest im Code verdrahteten E-Mail-Adressen. Wir wollen diese aber auf die E-Mail-Adressen untersuchen, die wir in der Textdatei <b>SentMailFolders<\/b>.txt gespeichert haben, und die betroffenen E-Mails in die dort angegebenen Ordner &uuml;bertragen.<\/p>\n<p>Dazu m&uuml;ssen wir die Ereignisprozedur erheblich anpassen (siehe Listing 5). Wir f&uuml;gen drei Variablen hinzu. Die Variable <b>dic <\/b>nimmt die Elemente aus der Textdatei als Dictionary auf. Die beiden Variablen <b>strMail <\/b>und <b>strFolder <\/b>werden mit den jeweils zu pr&uuml;fenden Daten gef&uuml;llt. <b>key <\/b>ist schlie&szlig;lich noch eine Variable, um die Elemente des Dictionarys zu durchlaufen.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>objItems_ItemAdd(ByVal Item<span style=\"color:blue;\"> As Object<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>objMailitem<span style=\"color:blue;\"> As <\/span>Outlook.MailItem\r\n     <span style=\"color:blue;\">Dim <\/span>objFolder<span style=\"color:blue;\"> As <\/span>Outlook.Folder\r\n     <span style=\"color:blue;\">Dim <\/span>dic<span style=\"color:blue;\"> As Object<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strEMail<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strFolder<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>key<span style=\"color:blue;\"> As Variant<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> dic = ReadTextFileToDictionary(cStrPath)\r\n     For Each key In dic.Keys\r\n         strFolder = dic(key)\r\n         strEMail = key\r\n         Select Case TypeName(Item)\r\n             <span style=\"color:blue;\">Case <\/span>\"MailItem\"\r\n                 <span style=\"color:blue;\">Set<\/span> objMailitem = Item\r\n                 <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">InStr<\/span>(1, objMailitem.Recipients(1).Address, strEMail) = 0<span style=\"color:blue;\"> Then<\/span>\r\n                     <span style=\"color:blue;\">Set<\/span> objFolder = GetFolderFromPath(strFolder)\r\n                     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> objFolder Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n                         objMailitem.Move objFolder\r\n                     <span style=\"color:blue;\">End If<\/span>\r\n                 <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">End Select<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> key\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: Prozedur zum Verschieben der E-Mails, neue Version<\/span><\/b><\/p>\n<p>Das Dictionary f&uuml;llen wir mit der Funktion <b>ReadTextFileToDictionary<\/b>, der wir den Pfad der einzulesenden Textdatei &uuml;bergeben (siehe weiter unten). Dann durchlaufen wir alle <b>Key<\/b>-Elemente des Dictionarys und referenzieren diese mit der <b>key<\/b>-Variablen. In der dazu verwendeten <b>For Each<\/b>-Schleife weisen wir der Variablen <b>strFolder <\/b>den Inhalt des aktuellen Elements zu, der Variablen <b>strEMail <\/b>den Wert von <b>key<\/b>.<\/p>\n<p>Dann untersuchen wir den Typ des im Ordner <b>Gesendete Elemente <\/b>gelandeten Elements. Im Falle einer E-Mail weisen wir das Element der Variablen <b>objMailitem zu<\/b>. Sollte die E-Mail-Adresse aus <b>strEMail <\/b>im ersten Empf&auml;nger der E-Mail enthalten sein, werden die Anweisungen innerhalb der <b>If&#8230;Then<\/b>-Bedingung ausgef&uuml;hrt. Hier ermitteln wir den Zielordner mit <b>GetFolderFromPath <\/b>f&uuml;r den Ordner aus <b>strFolder<\/b>. Handelt es sich dabei um einen g&uuml;ltigen Ordner, verschieben wir die E-Mail mit der <b>Move<\/b>-Methode in diesen. Auf diese Weise verfahren wir mit allen in der Textdatei gespeicherten E-Mail-Adressen.<\/p>\n<h2>Prozedur zum Einlesen der Textdatei in ein Dictionary<\/h2>\n<p>Damit kommen wir zu der Funktion <b>ReadTextFileToDictionary<\/b>, die den Pfad der einzulesenden Textdatei als Parameter erwartet (siehe Listing 6).<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>ReadTextFileToDictionary(strPath<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Object<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>fileNumber<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strLine<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strEMail<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strFolder<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>dic<span style=\"color:blue;\"> As Object<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>key<span style=\"color:blue;\"> As Variant<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> dic = CreateObject(\"Scripting.Dictionary\")\r\n     fileNumber = FreeFile\r\n     Open strPath For Input<span style=\"color:blue;\"> As <\/span>#fileNumber\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> EOF(fileNumber)\r\n         Line Input #fileNumber, strLine\r\n         strEMail = <span style=\"color:blue;\">Split<\/span>(strLine, \"|\")(0)\r\n         strFolder = <span style=\"color:blue;\">Split<\/span>(strLine, \"|\")(1)\r\n         dic(strEMail) = strFolder\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n     Close #fileNumber\r\n     <span style=\"color:blue;\">Set<\/span> ReadTextFileToDictionary = dic\r\n     <span style=\"color:blue;\">Set<\/span> dic = Nothing\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 6: Prozedur zum Einlesen von E-Mails und Ordnern aus der Textdatei in ein Dictionary<\/span><\/b><\/p>\n<p>Die Prozedur erstellt ebenfalls ein <b>Dictionary<\/b>-Objekt namens <b>dic<\/b>. Wir haben dieses der Einfachheit halber mit Late Binding initialisiert, damit wir keinen Verweis auf die Bibliothek <b>Microsoft Scripting Runtime <\/b>zum VBA-Projekt von Outlook hinzuf&uuml;gen m&uuml;ssen. Wir ermitteln eine Filenummer f&uuml;r den lesenden Zugriff auf die einzulesende Textdatei. Diese lesen wir in einer <b>Do While<\/b>-Schleife zeilenweise ein.<\/p>\n<p>Dabei teilen wir die Zeilen mit der <b>Split<\/b>-Funktion jeweils an der Stelle, an der sich das Pipe-Zeichen (<b>|<\/b>) befindet, auf. Den Teil davor lesen wir in die Variable <b>strEMail <\/b>ein, den Teil dahinter in die Variable <b>strFolder<\/b>.<\/p>\n<p>Wir legen jeweils ein neues Element in der Dictionary an, wobei <b>strEMail<\/b> der <b>Key <\/b>ist und der Ordner aus <b>strFolder <\/b>der Wert. Nachdem wir alle Zeilen der Datei durchlaufen haben, schlie&szlig;en wir die Textdatei und geben das gef&uuml;llte <b>Dictionary<\/b>-Element als Funktionsergebnis zur&uuml;ck.<\/p>\n<h2>Einbau in ein anderes Outlook-VBA-Projekt<\/h2>\n<p>Nachfolgend beschreiben wir noch den Einbau der Elemente des Downloads zu diesem Artikel in das VBA-Projekt von Outlook. Ein neues, leeres Outlook-Projekt enth&auml;lt lediglich eine Klasse namens <b>ThisOutlookSession<\/b>.<\/p>\n<p>Damit Du den Code einfach in Dein VBA-Projekt importieren kannst, haben wir diese auf nur zwei Module aufgeteilt:<\/p>\n<ul>\n<li>Das Modul <b>ThisOutlookSession <\/b>enth&auml;lt den &uuml;berwiegenden Teil des Codes.<\/li>\n<li>Das Modul <b>mdlAPI <\/b>enth&auml;lt die ben&ouml;tigten API-Deklarationen und dazugeh&ouml;rige Konstanten.<\/li>\n<\/ul>\n<p>Den Inhalt der Datei <b>ThisOutlookSession.cls <\/b>kopieren wir fast komplett in die vorhandene Klasse <b>ThisOutlookSession.cls <\/b>&#8211; bis auf den markierten Teil aus Bild 13. Das Modul <b>mdlAPI <\/b>k&ouml;nnen wir direkt mit dem Befehl <b>Datei|Datei importieren&#8230; <\/b>des VBA-Editors von Outlook importieren.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2024_05\/pic_440_013.png\" alt=\"Den Rest kopieren wir in das Modul ThisOutlookSession\" width=\"649,627\" height=\"389,4121\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 13: Den Rest kopieren wir in das Modul ThisOutlookSession<\/span><\/b><\/p>\n<p>Die Prozedur <b>Aktivieren <\/b>enth&auml;lt noch ein Meldungsfenster, das angezeigt wird, wenn die Elemente beim Start von Outlook korrekt geladen worden sind und die Funktionen einsatzbereit sind. Wenn das nicht geschieht, ist das der erste Ansatzpunkt f&uuml;r eine ausbleibende Funktion.<\/p>\n<p>Neben diesen Schritten musst Du noch den Ribboneintrag zum Aufrufen der Konfigurationsdatei wie oben beschreiben hinzuf&uuml;gen.<\/p>\n<h2>Zusammenfassung und Ausblick<\/h2>\n<p>Die hier vorliegende L&ouml;sung kann man bereits prima einsetzen. Man muss nur sicherstellen, dass die beim Start von Outlook automatisch ausgel&ouml;ste Prozedur <b>Application_Startup <\/b>alle f&uuml;r die Funktion notwendigen Schritte einmal durchgef&uuml;hrt hat.<\/p>\n<p>Um den Einbau dieser Funktionen noch ein wenig einfacher zu gestalten, zeigen wir in einem weiteren Artikel namens <b>Outlook: Gesendete Mails per COM-Add-In verschieben <\/b>(<b>www.vbentwickler.de\/441<\/b>) noch, wie wir diese in einem COM-Add-In verf&uuml;gbar machen k&ouml;nnen.<\/p>\n<p>Damit braucht man dann nur noch ein kleines Setup auszuf&uuml;hren und die Funktionen stehen bereit.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>F&uuml;r eingehende E-Mails gibt es unter Outlook die Regel-Funktion, mit der man einstellen kann, unter welchen Umst&auml;nden eine E-Mail, die im Posteingang landet, in einen anderen Ordner verschoben werden soll. Das kann man beispielsweise nutzen, um immer wiederkehrende Rechnungen direkt in den entsprechenden Ordner zu verschieben. W&uuml;nschenswert w&auml;re, wenn es eine solche Funktion auch f&uuml;r versendete E-Mails g&auml;be. Da Outlook hier aber keine eingebaute Funktion bereitstellt, schauen wir uns das Thema einmal genauer an und entwickeln VBA-Code, mit dem wir diese Aufgabe selbst steuern k&ouml;nnen. Dabei wollen wir sowohl &uuml;ber die Benutzeroberfl&auml;che gesendete E-Mails erfassen als auch E-Mails, die wir per VBA absenden.<\/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":[662024,66052024,44000027,44000026,44000036],"tags":[],"yst_prominent_words":[],"class_list":["post-55000440","post","type-post","status-publish","format-standard","hentry","category-662024","category-66052024","category-Excel_programmieren","category-Outlook_programmieren","category-Ribbon_programmieren"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000440","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=55000440"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000440\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000440"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000440"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000440"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000440"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}