dani
Goto Top

VBA Outlook - E-Mails entsprechend filtern

Guten Abend @all,
ich weiß, es ist Freitag Abend aber ich habe noch ein Problem, dass ich bewältigen muss. face-sad

Ich brauche ein VBA-Outlook Makro, dass folgendes macht:
Die E-Mail kommt im Posteingang an. Das Marko durchsucht die E-Mail (Betreff und Mailtext) nach einen oder mehreren Begriffen. Sprich in Laufe der Zeit können die Suchbegriffe auf 10 Stück ansteigen. Die E-Mail soll also nach all den Wörter durchsucht werden und falls eines vorkommt, in ein bestimmtes Verzeichnis verschoben werden.

Es handelt sich hier ausschließlich im Outlook 2003 + Exchange. Sollte es eine komfortablere Lösung geben, bitte ich um Meldung. Einigste Bitte, es soll genau das gleiche passieren.

Das Script sieht im Moment wie folgt aus:
Option Explicit

'Deklarationen  
'zuerst für Outlook selbst und den Namespace... ohne die beiden geht nichts.  
Dim MyOLApp As Application
Dim myNameSpace As NameSpace

Public Sub test()

	'Deklaration  
    Dim FolderInbox As MAPIFolder
    Dim FolderNeu As MAPIFolder
    Dim MailX As MailItem
    
    
    'Outlook als Object erstellen  
    Set MyOLApp = CreateObject("Outlook.Application")  
    Set myNameSpace = MyOLApp.GetNamespace("MAPI")  
    
    
    'Default-Mailbox nehmen.. manche haben nur eine, andere ein Dutzend  
    ' die aktive Mailbox laut Profil ist logischerweise der Parent (neudeutsch für <i>"Vadder"</i> vom "Posteingang"  
    Set FolderInbox = myNameSpace.GetDefaultFolder(olFolderInbox)
    Set FolderNeu= FolderInbox.Parent.Folders("Neu")  


    'Verschiebt die Mails aus dem Posteingang in den Ornder "NEU"  
	'Verschiebt die Mails von "SourceFolder" nach "DestFolder"  
    For Each MailX In FolderInbox.Items
        If StrComp(MailX.Subject, "12345", vbTextCompare) = 0 Then '<<<<<<<<  
            MailX.Move FolderNeu
        End If
    Next
    
	
    'Variablen löschen  
    Set myNameSpace = Nothing
    Set FolderVPN = Nothing
    Set MailX = Nothing
    
End Sub
Soweit funktioniert auch alles. Jetzt bin ich auf der Suche nach einer Möglichkeit, ein Array in VBA abzubilden und die Werte dort dann zu hinterlegen. So dass ich eigentlich nur noch um die vorhandene NEXT-FOR Schleife noch mal eine drum-rum machen müsste. Müsste doch so gehen?!


Schönen Abend / Weekend
Dani

Content-Key: 80868

Url: https://administrator.de/contentid/80868

Printed on: April 19, 2024 at 21:04 o'clock

Member: bastla
bastla Feb 15, 2008 at 19:32:26 (UTC)
Goto Top
Hallo Dani!

Am Anfang Deines Scripts könntest Du mit
WL = "D:\Wortliste.txt"  
WordList = Split(CreateObject("Scripting.FileSystemObject").OpenTextFile(WL, 1).ReadAll, vbCrLF)  
die Liste der Suchbegriffe aus einer Datei (jeder Begriff in einer eigenen Zeile) in ein Array einlesen.

Die zweite Schleife ließe sich dann etwa so realisieren:
For Each MailX In FolderInbox.Items
	For Each Word In WordList
		If StrComp(MailX.Subject, Word, vbTextCompare) = 0 Then '<<<<<<<<  
			MailX.Move FolderNeu
			Exit For
		End If
	Next
Next

Grüße
bastla
Member: Dani
Dani Feb 15, 2008 at 20:00:06 (UTC)
Goto Top
Abend bastla,
vielen Dank..die Idee mit der Textdatei finde ich gut. Somit kann ich einfach immer diese Verteilen. *g*

Als was soll ich die Objekte WL, Word, Wordlist oben definieren? Denn ich hab oben "Option Explicit" gesetzt.

Dann habe ich jetzt noch ein Problem:
Jezt habe ich herausgefunden, dass es am Typ liegt. Sprich es sind auch Lese, Löschbestätigungen dabei.

Des Weitern ist VBCompare wohl der falsche Parameter. Denn er verschiebt die Mail nur, wenn der genauer Betreff (1:1) hinterlegt ist. Jedoch wird das hier nicht oft vorkommen. Was gibt es den sonst noch für Para oder andere Methoden um das Problem zu umgehen?


Grüße
Dani
Member: bastla
bastla Feb 15, 2008 at 20:20:11 (UTC)
Goto Top
Hallo Dani!

Textdatei finde ich gut. Somit kann ich einfach immer diese Verteilen.
... oder gleich von einem UNC-Pfad einlesen.

Variablentypen:
Dim WL As String, WordList() As String, Word As Variant
WordList ist ein String-Array und wird eigentlich implizit durch "Split()" erzeugt.

Des Weitern ist VBCompare wohl der falsche Parameter
Es liegt nicht am Parameter (der sorgt dafür, dass Groß-/Kleinschreibung nicht unterschieden wird, ist also hier sinnvoll), sondern es würde sich hier die Funktion InStr() besser eignen:
If InStr(1, MailX.Subject, Word, vbTextCompare) <> 0 Then

Grüße
bastla
Member: Dani
Dani Feb 15, 2008 at 20:42:51 (UTC)
Goto Top
Hi! face-smile
Also es funktioniert jetzt genauso wie gedacht. Groß- / Kleinschreibung wird schön ignoriert und sauber verschoben.

Das einzigste Problem ist nun noch: Dass immer ein Laufzeitfehler erscheint, wenn es eine Bestätigung (Gelesen, etc..) ist. Sprich ich erhalte im VBA Editor dann folgende Meldung:
Laufzeitfehler '13'  
Typen unverträglich
Hast du vllt. noch eine Idee, wie ich dem Problem aushebeln könnte?


Gruß
Dani
Member: bastla
bastla Feb 15, 2008 at 20:54:49 (UTC)
Goto Top
Hallo Dani!

Das Outlook-Objektmodell ist mir leider nicht so geläufig, aber ich werd' mal schauen ...

Grüße
bastla
Member: Dani
Dani Feb 15, 2008 at 21:02:56 (UTC)
Goto Top
Wunderbar...ich schau natürlich auch, was sich finden lässt. Auf jeden Fall schon mal eine großes, dickes Danke! Du hast mir mal wieder viel Zeit erspart. Im Moment hab ich davon nämlich nicht viel.


Grüße
Dani
Member: bastla
bastla Feb 15, 2008 at 21:06:35 (UTC)
Goto Top
Hallo Dani!

Versuch es einmal mit der Deklaration
Dim MailX As Object

Grüße
bastla
Member: miniversum
miniversum Feb 15, 2008 at 21:47:55 (UTC)
Goto Top
Mal doof gefragt.
Gibts nen Grund das es umbedingt ein makro sein soll?
Die gleiche funktionalität bekomt man doch auch mit ner Regel hin (mal abgesehen von der Sache mit der Datei inder die wörter stehen)?

miniversum
Member: Dani
Dani Feb 15, 2008 at 21:49:18 (UTC)
Goto Top
Hmm...wenn ich es als Object deklariere, habe ich mit den Punktoperator (.) keine Auswahlmöglichkeit (Body, Subject, etc...).


Gruß
Dani
Member: Dani
Dani Feb 15, 2008 at 21:54:13 (UTC)
Goto Top
Abend miniversum,
klar.. darfst du fragen! face-wink

Erstmal hätte ich dann für die einzelnen Dinge wie Subject, Mailtext und Absenderadresse jeweils eine Regel erzeugen müssen, da bei einer Regel alle Faktoren mit "UND" verbunden werden (Outlook eben). Die Filterung hat auch nicht so geklappt wie mit Marko.

Desweitern sollen die Stichwörter kontinuirlich erweitert werden...da tut man sich eben mit der Regel schwer. Das Marko hat eben den Vorteil die Leute können keine Regel sehen und somit kann keiner etwas verstellen, etc... Klar, das Marko kann er finden, aber da muss er erstmal dahintersteigen.


Grüße
Dani
Member: bastla
bastla Feb 15, 2008 at 21:56:57 (UTC)
Goto Top
Hallo Dani!

wenn ich es als Object deklariere, habe ich mit den Punktoperator (.) keine Auswahlmöglichkeit ...
Wenn das Script ansonsten fertig ist, bräuchtest Du die ja eigentlich auch nicht mehr ...

Die Idee stammt übrigens aus der VBA-Hilfe zur "Move"-Methode des "MailItem"-Objekts.

Grüße
bastla
Member: miniversum
miniversum Feb 15, 2008 at 21:59:53 (UTC)
Goto Top
JA ok. Das ist dan klar ein Argument.
Das Makro zu schützen ist ja kein Problem. Kann man ja mit Passwort verschlüsseln.
Member: Dani
Dani Feb 15, 2008 at 22:03:34 (UTC)
Goto Top
Vllt. habe ich mich falsch ausgedrückt.
Nehmen wir an, es liegen 10 Mails und 4 Bestätigungen im Posteingang. Dann läuft das Marko bis zur ersten Bestätigung und bricht dann mit der Fehlernummer oben ab. Das geht eben solange nicht, bis eben alle Bestätigungen aus dem Posteingang verschoben sind.
Ich nenne dir mal Realitätswert: 130 Mails und 69 Bestätigungen...

Ich hoffe, es kommt jetzt verständlicher rüber.


Grüße
Dani
Member: bastla
bastla Feb 15, 2008 at 22:17:48 (UTC)
Goto Top
Hallo Dani!

Ja, schon klar - aber was passiert, wenn Du bei der aktuellen Script-Version die Deklaration als "Object" verwendest?

Und in welcher Zeile genau tritt eigentlich der Fehler auf?

Grüße
bastla
Member: Dani
Dani Feb 15, 2008 at 23:18:28 (UTC)
Goto Top
Abend,
Sry, hätte ich gleich schreiben können, ich habe folgende Zeile geändert:
Dim MailX As MailItem ========> Dim MailX As Object
Somit erhalte ich in dieser Zeile
MailX.Move FolderDest
Fehler: Laufzeitfehler '438':Object unterstützt diese Eigenschaft oder Methode nicht.

Wenn ich im Marko MailX. schreibe und dann eben STRG+Leertaste erscheinen keine weitere Eigenschaften, Methoden, etc...

Wenn ich die Zeile so lasse "Dim MailX As MailItem" tritt der Fehler in dieser Zeile auf:
For Each MailX In FolderInbox.Items
Fehler: Laufzeitfehler '13': Typen unverträglich.


Grüße
Dani
Member: Dani
Dani Feb 16, 2008 at 00:06:05 (UTC)
Goto Top
Ich habe mir eben noch die VBA Hilfe angesehen. Also wenn ich folgenden Ansatz verfolge
Dim Mails As Outlook.Items
Dim Mail As Object
.....
....
Set FolderDest = FolderInbox.Parent.Folders("test")  
    
Set Mails = FolderInbox.Items
Set Mail = Mails.Find("[Subject] = '48 test' ")  

While TypeName(Mail) <> "Nothing"  
        Mail.Move FolderDest
        Set Mail = Mails.FindNext
Wend
....
Das Problem ist eben, das Suchmuster muss 1:1 mit dem Betreff der E-Mail übereinstimmen. Ansonsten wird nichts vom Marko verschoben. Ansonsten wäre das der richtige Weg, da es dort den Laufzeitfehler '13' nicht mehr gibt. face-smile


Grüße
Dani
Member: bastla
bastla Feb 16, 2008 at 00:19:38 (UTC)
Goto Top
Hallo Dani!

Vielleicht lässt sich ein "LIKE" verwenden, etwa:
Set Mail = Mails.Find("[Subject] LIKE '*" & Word & "*' ")  
oder "Find" lässt sich austricksen:
Set Mail = Mails.Find("[Subject]  <> '\-\-\-\-\-\-\-\-\-\-\-\-/-/-/-/-/-/-/-/-/-/-/' ")  
Do While TypeName(Mail) <> "Nothing"  
    For Each Word In WordList
        If InStr(1, Mail.Subject, Word, vbTextCompare) Then
            Mail.Move FolderDest
            Exit For
        End If
    Next
    Set Mail = Mails.FindNext
Loop
Die Idee ist hier, alle Mails (aber eben nur Mails) zu finden, indem als Kriterium ein mit größter Wahrscheinlichkeit nicht vorkommender String gewählt wird, allerdings mit Bedingung "<>", und erst danach den Vergleich mit den Suchwörtern vorzunehmen.

Grüße
bastla

[Edit] Startposition "1" bei InStr() ergänzt. [/Edit]
Member: Dani
Dani Feb 16, 2008 at 09:46:38 (UTC)
Goto Top
Moin bastla,
also ich beide Funktionen getestet und keine funktioniert. face-sad

Diese Zeile
Set Mail = Mails.Find("[Subject] LIKE '*" & Word & "*' ")  
Fehler: Laufzeitfehler '-1975386103 (8a420009)':Die Bedingung ist ungültig.

Die Frage ist eben, gibt es nun "LIKE" als Operator oder nicht. In der Hilfe finde ich dazu nämlich nichts.

Das 2. Konstrukt:
Das mit dem Subject funktioniert prima...er sprich zwar alle Mails an, aber das ist egal.
Jedoch erhalte ich wieder den Laufzeifehler 13 ....

Durch Debuggen habe ich herausgefunden, in welcher Zeile es mal wieder Probleme gibt:
For Each Word In WordList
            'If InStr(Mail.Subject, Word, vbTextCompare) Then  
                MsgBox "hallo", , "test"  
                
                Mail.Move FolderDest
                Exit For
            'End If  
        Next
Betroffen ist die auskommentierte Zeile mit "InStr...".


Grüße
Dani
Member: bastla
bastla Feb 16, 2008 at 12:24:03 (UTC)
Goto Top
Hallo Dani!

Dann fällt mir für's Erste nur mehr eine "On Error"-Variante ein:
Subj = ""  
On Error Resume Next
Subj = Mail.Subject
On Error Goto 0
If Subj <> "" Then  
    For Each Word In WordList
        If InStr(1, Subj, Word, vbTextCompare) Then
            MsgBox "hallo", , "test"  
                
            Mail.Move FolderDest
            Exit For
        End If
    Next
End If
Damit würden zwar Mails ohne Betreff "durchrutschen", aber in solchen kannst Du Deine Schlüsselwörter ja ohnehin nicht finden.

Die Abfrage
If Subj <> "" Then  
ist gar nicht nötig, kann aber durch Überspringen der Überprüfungsschleife die Verarbeitung beschleunigen.

Grüße
bastla

[Edit] Startposition "1" bei InStr() ergänzt. [/Edit]
Member: Dani
Dani Feb 16, 2008 at 13:15:19 (UTC)
Goto Top
Hi bastla,
so ich habe jezt eine Lösung, die mit meinen Testmails/bestätigungen prima funktioniert.

Hier mal der Codeausschnitt:
    Set Mails = FolderInbox.Items
    Set Mail = Mails.Find("[Subject]  <> '\-\-\-\-\-\-\-\-\-\-\-\-/-/-/-/-/-/-/-/-/-/-/' ")  
    Do While TypeName(Mail) <> "Nothing"  
        For Each Word In WordList
        
            If InStr(1, Mail.Body, Word, vbTextCompare) <> 0 Then
               Mail.Move FolderDest
               Exit For
               
            ElseIf InStr(1, Mail.Subject, Word, vbTextCompare) <> 0 Then
                Mail.Move FolderDest
               Exit For
               
            End If
        Next
        
        Set Mail = Mails.FindNext
    Loop
Nächste Woche lass ich es mal auf 2-3 Clients laufen und gebe dir/euch dann am Freitag Rückmeldung. Auf jeden Fall schon mal ein dickes Danke an dich, dass du dir am WE die Zeit nimmst, mir zuhelfen.


Gruß
Dani
Member: bastla
bastla Feb 16, 2008 at 13:35:22 (UTC)
Goto Top
Hallo Dani!

Freut mich, dass es nun zu funktionieren scheint face-smile (wobei ich den genauen Unterschied noch gar nicht gesehen habe).

Allerdings musste ich beim Drüberschauen feststellen, dass ich InStr() zumeist ohne Startposition ("1") geschrieben habe (was wegen des "vbTextCompare" allerdings nötig ist) - ich korrigiere das dann jeweils oben (und hoffe, dass nicht das die Fehler verursacht hat ...).

Grüße
bastla
Member: Dani
Dani Feb 16, 2008 at 14:19:28 (UTC)
Goto Top
Hi Bastla,
face-smile Ich werde dann sowieso eine Final Version posten...sprich, das man unser hin und her nicht lesen muss bzw. nur in Sonderfällen.


Grüße
Dani
Member: Dani
Dani Feb 23, 2008 at 11:38:12 (UTC)
Goto Top
Hi @all,Hi bastla,
wie versprochen, melde ich mich nochmal und gebe Rückmeldung. Also scheint wirklich jetzt astrein zu funktionieren..die Anwender sind damit hochzufrieden und ich bin somit auch glücklich.

Hier nochmal das Marko in der Final-Version:
Option Explicit

'Deklarationen  
'zuerst für Outlook selbst und den Namespace... ohne die beiden geht nichts.  
Dim MyOLApp As Application
Dim myNameSpace As NameSpace

Private Sub Application_NewMail()
    
    'Ruft die Funktion "test" auf  
    test
    
End Sub

Private Sub Application_NewMailEx(ByVal EntryIDCollection As String)

    'Ruft die Funktion "test" auf  
    test

End Sub

Public Sub test()

    'Deklaration  
    Dim FolderInbox As MAPIFolder
    Dim FolderDest As MAPIFolder
    
    Dim Mails As Outlook.Items
    Dim Mail As Object
    
    Dim WordListSrc As String
    Dim WordList() As String
    Dim Word As Variant
   
        
    'Wortdatei laden  
    WordListSrc = "C:\Outlook_filter.txt"  
    
    'Array erzeugen - jede Zeile wird in ein Feld gespeichert  
    WordList = Split(CreateObject("Scripting.FileSystemObject").OpenTextFile(WordListSrc, 1).ReadAll, vbCrLf)  

    
    'Outlook als Object erstellen  
    Set MyOLApp = CreateObject("Outlook.Application")  
    Set myNameSpace = MyOLApp.GetNamespace("MAPI")  
    
    'Default-Mailbox nehmen.. manche haben nur eine, andere ein Dutzend  
    ' die aktive Mailbox laut Profil ist logischerweise der Parent (neudeutsch für <i>"Vadder"</i> vom "Posteingang"  
    Set FolderInbox = myNameSpace.GetDefaultFolder(olFolderInbox)
    Set FolderDest = FolderInbox.Parent.Folders("xyz")  
    
    
    Set Mails = FolderInbox.Items
    Set Mail = Mails.Find("[Subject]  <> '\-\-\-\-\-\-\-\-\-\-\-\-/-/-/-/-/-/-/-/-/-/-/' ")  
    Do While TypeName(Mail) <> "Nothing"  
        For Each Word In WordList
            'Vergleiche Mailtext mit jedem Suchbegriff aus der Wortdatei, bis einer der beiden Bedingungen zutrifft.  
            ''Als gelesen markieren  
            ''In Verzeichnis verschieben  
            ''FOR-Schleife beenden  
            If (InStr(1, Mail.Body, Word, vbTextCompare) Or InStr(1, Mail.Subject, Word, vbTextCompare)) <> 0 Then
               Mail.UnRead = False
               Mail.Move FolderDest
               Exit For
            End If
        Next
        'Makiert die nächste Mail  
        Set Mail = Mails.FindNext
    Loop

    'Variablen löschen  
    Set myNameSpace = Nothing
    Set FolderDest = Nothing
    
    Set Mails = Nothing
    Set Mail = Nothing
    
    Set Word = Nothing
    
End Sub
Wichtig ist, dass in der Textdatei es keine leere Zeile gibt. Denn ansonsten werden alle Mails aus dem Posteingang verschoben!

Ein großes, dickes Danke geht an bastla, der mir tatkräftig zur Seite gestanden ist!


Grüße
Dani