Skip already categorized mails - vba

Current Code:
Dim outlookapp
Dim olns As Outlook.Namespace
Dim Fldr As Outlook.MAPIFolder
Dim olMail As Object
'Dim olMail As Outlook.MailItem
Dim myTasks
Dim projIDsearch As String
Dim myrecipient As Outlook.Recipient
Dim daysAgo As Long
Set outlookapp = CreateObject("Outlook.Application")
Set olns = outlookapp.GetNamespace("MAPI")
Set myrecipient = olns.CreateRecipient("Ccbcphelpdesk")
myrecipient.Resolve
'Set Fldr = olNs.GetDefaultFolder(olFolderInbox).Folders("ExemptionReview")
Set Fldr = olns.GetSharedDefaultFolder(myrecipient, olFolderInbox)
' Restrict search to daysAgo
daysAgo = 0
Set myTasks = Fldr.Items.Restrict("[ReceivedTime]>'" & Format(Date - daysAgo, "DDDDD HH:NN") & "'")
projIDsearch = ActiveCell.Cells(1, 4)
For Each olMail In myTasks
If (InStr(1, olMail.Subject, projIDsearch, vbTextCompare) > 0) Then
olMail.Categories = "ESP"
olMail.Save
End If
Next
end sub
This looks up emails pertaining to a search string in the subject then tags them as ESP. I need to skip emails that are already categorized.
I have tried:
If (InStr(1, olMail.Subject, projIDsearch, vbTextCompare) > 0) Then
If olmail.categories Is nothing then 'line returns and error 424
olMail.Categories = "ESP"
olMail.Save
End If
End If
How can I skip Emails that are already categorized and only categorize emails with no category?

https://msdn.microsoft.com/en-us/library/office/ff860423.aspx
Categories is a String-type property, so test with something like:
If Len(olmail.Categories) = 0 Then

Use Logical Operators And Not on your Restrict method
Set myTasks = Fldr.Items.Restrict("[ReceivedTime]>'" & Format(Date - daysAgo, "DDDDD HH:NN") & "' And Not [Categories] = 'ESP'")
and remove your If olmail.categories Is nothing that way your not checking every olmail- and it should speedup your loop

Related

How to filter by subject and age?

I'm trying to delete sent items that contain "invoice" in the subject that are more than 30 days old.
It works for emails older than 30 days but doesn't applying the filter on the subject.
The code I'm currently using
Sub MoveAgedMail()
Dim objOutlook As Outlook.Application
Dim objNamespace As Outlook.NameSpace
Dim objSourceFolder As Outlook.MAPIFolder
Dim objDestFolder As Outlook.MAPIFolder
Dim objVariant As Variant
Dim lngMovedItems As Long
Dim intCount As Integer
Dim Items As Outlook.Items
Dim Filter As String
Dim intDateDiff As Integer
Dim strDestFolder As String
Set objOutlook = Application
Set objNamespace = objOutlook.GetNamespace("MAPI")
Set objSourceFolder = objNamespace.GetDefaultFolder(olFolderSentMail)
Set objDestFolder = objNamespace.GetDefaultFolder(olFolderDeletedItems)
Filter = "[Subject] = '%" & "invoice" & "%' And [SenderEmailAddress] = _
'abc #hotmail.com'"
Set Items = objSourceFolder.Items.Restrict(Filter)
For intCount = objSourceFolder.Items.Count To 1 Step -1
Set objVariant = objSourceFolder.Items.Item(intCount)
DoEvents
If objVariant.Class = olMail Then
intDateDiff = DateDiff("d", objVariant.SentOn, Now)
If intDateDiff > 30 Then
objVariant.Move objDestFolder
'count the # of items moved
lngMovedItems = lngMovedItems + 1
End If
End If
Next
MsgBox "Moved " & lngMovedItems & " messages(s)."
Set objDestFolder = Nothing
End Sub
You must work with a restricted set of items instead of getting a new items collection, for example:
For intCount = objSourceFolder.Items.Count To 1 Step -1
Set objVariant = objSourceFolder.Items.Item(intCount)
It should be rewritten as the following:
For intCount = Items.Count To 1 Step -1
Set objVariant = Items.Item(intCount)
You may find the following articles helpful:
How To: Use Restrict method to retrieve Outlook mail items from a folder
How To: Use Find and FindNext methods to retrieve Outlook mail items from a folder (C#, VB.NET)
Do not use Items as a variable.
Sub MoveAgedMail()
'Dim objOutlook As Outlook.Application
'Dim objNamespace As Outlook.NameSpace
Dim objNamespace As NameSpace
'Dim objSourceFolder As Outlook.MAPIFolder
Dim objSourceFolder As Folder
'Dim objDestFolder As Outlook.MAPIFolder
Dim objDestFolder As Folder
Dim objVariant As Variant
Dim lngMovedItems As Long
Dim intCount As Integer
'Dim Items As Outlook.Items ' Do not use Items as a variable
Dim resItems As Items
Dim Filter As String
Dim intDateDiff As Integer
Dim strDestFolder As String
'Set objOutlook = Application ' not necessary
'Set objNamespace = objOutlook.GetNamespace("MAPI")
Set objNamespace = GetNamespace("MAPI")
Set objSourceFolder = objNamespace.GetDefaultFolder(olFolderSentMail)
Debug.Print "objSourceFolder.Items.Count: " & objSourceFolder.Items.Count
Set objDestFolder = objNamespace.GetDefaultFolder(olFolderDeletedItems)
' ?
Filter = "[Subject] = '%" & "invoice" & "%' And [SenderEmailAddress] =" 'abc #hotmail.com'"
Debug.Print Filter
Filter = "[Subject] = '%" & "invoice" & "%'"
Debug.Print Filter
Set resItems = objSourceFolder.Items.Restrict(Filter)
Debug.Print "objSourceFolder.Items.Count: " & objSourceFolder.Items.Count
Debug.Print "resItems.Count: " & resItems.Count
'For intCount = objSourceFolder.Items.Count To 1 Step -1
For intCount = resItems.Count To 1 Step -1
Set objVariant = resItems.Item(intCount)
DoEvents
If objVariant.Class = olMail Then
intDateDiff = DateDiff("d", objVariant.SentOn, Now)
If intDateDiff > 30 Then
objVariant.Move objDestFolder
'count the # of items moved
lngMovedItems = lngMovedItems + 1
End If
End If
Next
MsgBox "Moved " & lngMovedItems & " messages(s)."
Set objDestFolder = Nothing
End Sub

Excel VBA Logic idea

My script is for tracking emails with subject and received time.
I receive 4 emails daily and I need to make reports about when email receiving.
My question is I create check box that allow which emails I want to track, but I don't know how can I make logically. First I tried , I created 15 if statements. I know it's not good so I am looking for new logic. I have attached my code below.
Please share your knowledge.
Plus, restrict method is for specified date and sender.
Sub GetFromOutlook()
Dim OutlookApp As Outlook.Application
Dim OutlookNamespace As Namespace
Dim OutlookMail As Variant
Dim Folder As MAPIFolder
Dim olItems As Outlook.Items
Dim myItems As Outlook.Items
Dim olShareName As Outlook.Recipient
Dim dStart As Date
Dim dEnd As Date
Dim i As Integer
Dim sFilter As String
Dim sFilterLower As String
Dim sFilterUpper As String
Dim sFilterSender As String
'========================================================
'access to shared mailbox to get items
'========================================================
Set OutlookApp = New Outlook.Application
Set OutlookNamespace = OutlookApp.GetNamespace("MAPI")
Set olShareName = OutlookNamespace.CreateRecipient("Mailbox.teamshared#example.ca")
Set Folder = Session.GetSharedDefaultFolder(olShareName, olFolderInbox).Folders("subfolder1").Folders("subfolder2")
Set olItems = Folder.Items
'========================================================
'If check box is checked
'========================================================
dStart = Range("From_Date").Value
dEnd = Range("To_Date").Value
'========================================================
'Conditions for restrict to get items specificed date
'========================================================
sFilterLower = "[ReceivedTime] > '" & Format(dStart, "ddddd h:nn AMPM") & "'"
sFilterUpper = "[ReceivedTime] < '" & Format(dEnd, "ddddd h:nn AMPM") & "'"
sFilterSender = "[SenderName] = ""no-reply#example.com"""
'========================================================
'Restrict emails followed by above conditions
'========================================================
Set myItems = olItems.Restrict(sFilterLower)
Set myItems = myItems.Restrict(sFilterUpper)
Set myItems = myItems.Restrict(sFilterSender)
'========================================================
'items(emails) display in worksheets
'========================================================
i = 1
For Each myItem In myItems
Range("eMail_subject").Offset(i, 0).Value = myItem.Subject
Range("eMail_date").Offset(i, 0).Value = Format(myItem.ReceivedTime, "h:nn")
'Convert size KB
If myItem.Attachments.Count > 0 Then
Range("eMail_size").Offset(i, 0).Value = myItem.Attachments.Item(1).Size / 1024
Else
Range("eMail_size").Offset(i, 0).Value = "No attached file"
End If
i = i + 1
Next myItem
Set Folder = Nothing
Set OutlookNamespace = Nothing
Set OutlookApp = Nothing
Else
MsgBox "You have check at least one"
End If
End Sub

Excel VBA Outlook search Multiple Criteria (ID and Date)

This code was derived from Excel VBA for searching in mails of Outlook.
I made adjustments to make it search a SharedMailbox which does work but the issue is that the mailbox is receiving hundreds of emails a day which makes searching time a bit longer for my liking (we have emails from early last year even). I would like to impose a 2nd search criteria, this time a date limit, like only search emails that are 2 to 3 days old.
Here is what I got:
Dim outlookapp
Dim olNs As Outlook.Namespace
Dim Fldr As Outlook.MAPIFolder
Dim olMail As Variant
Dim myTasks
Dim projIDsearch As String
Dim myRecipient As Outlook.Recipient
Dim days2ago As Date
Set outlookapp = CreateObject("Outlook.Application")
Set olNs = outlookapp.GetNamespace("MAPI")
Set myRecipient = olNs.CreateRecipient("SharedMailboxName")
myRecipient.Resolve
'Set Fldr = olNs.GetDefaultFolder(olFolderInbox).Folders("x")
Set Fldr = olNs.GetSharedDefaultFolder(myRecipient, olFolderInbox)
Set myTasks = Fldr.Items
projIDsearch = ActiveCell.Cells(1, 4)
days2ago = DateTime.Now - 3
For Each olMail In myTasks
'If olMail.ReceivedTime > days2ago Then
If (InStr(1, olMail.Subject, projIDsearch, vbTextCompare) > 0) Then
olMail.Display
'Exit For
End If
Next
I've looked around and found the .ReceivedTime property, which sounds like the thing that I need but I'm having a struggle on how to incorporate it into the code.
Actually I don't even know how a Variant(olMail) is able to accept the .display method and .subject property.
These are the codes that I've added but they don't seem to work:
days2ago = DateTime.Now - 3
and
If olMail.ReceivedTime > days2ago Then
You can Restrict the number of items in the loop. https://msdn.microsoft.com/en-us/library/office/ff869597.aspx
Sub test()
Dim outlookapp As Object
Dim olNs As Outlook.Namespace
Dim myFldr As Outlook.Folder
Dim objMail As Object
Dim myTasks As Outlook.Items
Dim daysAgo As Long
Dim projIDsearch As String
Dim myRecipient As Outlook.Recipient
Set outlookapp = CreateObject("Outlook.Application")
Set olNs = outlookapp.GetNamespace("MAPI")
Set myRecipient = olNs.CreateRecipient("SharedMailboxName")
myRecipient.Resolve
Set myFldr = olNs.GetSharedDefaultFolder(myRecipient, olFolderInbox)
projIDsearch = ActiveCell.Cells(1, 4)
' Restrict search to daysAgo
daysAgo = 3
Set myTasks = myFldr.Items.Restrict("[ReceivedTime]>'" & Format(Date - daysAgo, "DDDDD HH:NN") & "'")
For Each objMail In myTasks
If (InStr(1, objMail.Subject, projIDsearch, vbTextCompare) > 0) Then
objMail.Display
End If
Next
End Sub

Outlook scan through the Inbox for a specific string in the subject

I'm working on a project were I need a macro in outlook that will scan through the inbox for an e-mail with a "reference number" contained with-in the subject field. If no e-mail was detected, the system can then move on to the next reference from an excel spreadsheet.
If an e-mail was detected, it gets extracted as an "MSG" file and the actual e-mail moved into a subfolder. So far I have a code for extracting the e-mails as "MSG" files but I cant get it to identify the specific string (reference No) in the subject field. I got the below EXCEL Macro code so far from this site.
Sub Work_with_Outlook()
Set outlookApp = CreateObject("Outlook.Application")
Dim olNs As Outlook.NameSpace
Dim Fldr As Outlook.MAPIFolder
Dim olMail As Variant
Dim sir() As String
Set outlookApp = New Outlook.Application
Set olNs = outlookApp.GetNamespace("MAPI")
Set Fldr = olNs.GetDefaultFolder(olFolderInbox)
Set myTasks = Fldr.Items
Set olMail = myTasks.Find("[Subject] = ""Macro""")
If Not (olMail Is Nothing) Then
olMail.Display
End If
End Sub
Try below code:
Sub SaveAttachments()
Dim myOlapp As Outlook.Application
Dim myNameSpace As Outlook.Namespace
Dim myFolder, destFolder As Outlook.MAPIFolder
Dim i, lr As Long
'last used row in excel
lr = Cells(Rows.Count, "A").End(xlUp).Row
Set myOlapp = GetObject(, "Outlook.application")
Set myNameSpace = myOlapp.GetNamespace("MAPI")
Set myFolder = myNameSpace.GetDefaultFolder(olFolderInbox)
Set destFolder = myFolder.Folders("provide subFolderName here")
Set mytask = myFolder.Items
'Download and move attachment if found
For i = 1 To lr
'The below line of code will not work if you are using wild card or partial string
Set ref = mytask.Find("[Subject] =" & Range("a" & i).Value)
If Not (ref Is Nothing) Then
ref.Attachments.Item(1).SaveAsFile "C:\" & Range("a" & i).Value & ".msg"
ref.Move destFolder
End If
Set ref = Nothing
'The workaround code goes as below
For Each myItem In mytask
If myItem.Class = olMail Then
If InStr(1, myItem.Subject, Range("a" & i).Value) > 0 Then
myItem.Attachments.Item(1).SaveAsFile "C:\" & Range("a" & i).Value & ".msg"
myItem.Move destFolder
End If
End If
Next myItem
Next i
Set myOlapp = Nothing
Set myNameSpace = Nothing
Set myFolder = Nothing
Set destFolder = Nothing
Set mytask = Nothing
End Sub
Note: Assuming reference number is in "A" Column

Searching for newest email with a certain subject

I have the below code which works.
I now need to find the newest email with that subject line and open it.
Once the email is opened, I'd like to save the attachment to my desktop and close out of the opened email.
Sub SearchOL()
Dim olApp As Outlook.Application
Dim olNs As NameSpace
Dim Fldr As MAPIFolder
Dim olMail As Variant
Dim i As Integer
Set olApp = New Outlook.Application
Set olNs = olApp.GetNamespace("MAPI")
Set Fldr = olNs.GetDefaultFolder(olFolderInbox)
i = 1
For Each olMail In Fldr.Items
If InStr(olMail.Subject, "DNP Warn and Pend Event") <> 0 Then
olMail.Display
i = i + 1
End If
Next olMail
End Sub
I'd suggest starting from the Getting Started with VBA in Outlook 2010 article in MSDN.
Use the Find/FindNext or Restrict methods of the Items class to find the emails with a particular subject line instead of iterating through each email and checking the subject line.
Sub DemoFindNext()
Dim myNameSpace As Outlook.NameSpace
Dim tdystart As Date
Dim tdyend As Date
Dim myAppointments As Outlook.Items
Dim currentAppointment As Outlook.AppointmentItem
Set myNameSpace = Application.GetNamespace("MAPI")
tdystart = VBA.Format(Now, "Short Date")
tdyend = VBA.Format(Now + 1, "Short Date")
Set myAppointments = myNameSpace.GetDefaultFolder(olFolderCalendar).Items
Set currentAppointment = myAppointments.Find("[Start] >= """ & tdystart & """ and [Start] <= """ & tdyend & """")
While TypeName(currentAppointment) <> "Nothing"
MsgBox currentAppointment.Subject
Set currentAppointment = myAppointments.FindNext
Wend
End Sub