Find email from ReceivedTime - vba

I try to find email from received time but somethings dont want to work. I dont get any error but the msg is not moving to diff folder
Dim myNameSpace As Outlook.NameSpace
Dim myInbox As Outlook.Folder
Dim myDestFolder As Outlook.Folder
Dim myItems As Outlook.Items
Dim myItem As Object
Dim myOlApp As New Outlook.Application
Set myNameSpace = Outlook.Application.GetNamespace("MAPI")
Set myInbox = myNameSpace.Folders(user_email).Folders("RXXX")
Set myDestFolder = myInbox.Folders(fDestination)
Set myItems = myInbox.Items
Set myItem = myItems.Find("[ReceivedTime] = '#" + msg_date + "#'")
While TypeName(myItem) <> "Nothing"
MsgBox 1
MoveItems = MoveItems + 1
myItem.Move myDestFolder
Set myItem = myItems.FindNext
Wend
Set myNameSpace = Nothing
Set myInbox = Nothing
Set myItems = Nothing
Set myDestFolder = Nothing
Set myItem = Nothing

Format seems correct, but single quotes should not be present:
Set myItem = myItems.Find("[ReceivedTime] = #" + msg_date + "#")

You should never use = when working with DateTime properties - the condition will never be satisfied (even if you specify date and time down to the millisecond level) because of the round-off errors. Always use a range
#SQL=(ReceivedTime < '4/17/2020') AND (ReceivedTime > '4/1/2020')

Date format is a major source of problems.
Option Explicit ' Consider this mandatory
' Tools | Options | Editor tab
' Require Variable Declaration
'
' If desperate declare as variant
Sub findByReceivedTime_DateRange()
Dim myNamespace As Outlook.Namespace
Dim mySourceFolder As Outlook.folder
Dim myDestFolder As Outlook.folder
Dim fDestination As String
Dim myItems As Outlook.items
Dim myItem As Object
Dim msg_dateStart As Date
Dim msg_dateEnd As Date
Dim msg_dateStartStr As String
Dim msg_dateEndStr As String
Dim strFilter As String
Set myNamespace = Outlook.Application.GetNamespace("MAPI")
' mySourceFolder under mailbox, not under inbox
Set mySourceFolder = myNamespace.folders(user_email)
Set mySourceFolder = mySourceFolder.folders("RXXX")
' myDestFolder under mySourceFolder
fDestination = "TestDest"
Set myDestFolder = mySourceFolder.folders(fDestination)
Set myItems = mySourceFolder.items
myItems.sort "[ReceivedTime]", True
Debug.Print myItems(1).ReceivedTime & ": " & myItems(1).Subject
Debug.Print
' Test with a number bigger than 12 for the day to verify date format
' Start of the range
msg_dateStart = Format(#3/26/2020#, "yyyy/mm/dd")
Debug.Print "msg_dateStart...: " & msg_dateStart
msg_dateStartStr = CStr(msg_dateStart)
Debug.Print "msg_dateStartStr: " & msg_dateStartStr
' For a single day, end of the range is the beginning of the next day
msg_dateEnd = Format(#3/27/2020#, "yyyy/mm/dd")
Debug.Print "msg_dateEnd.....: " & msg_dateEnd
msg_dateEndStr = CStr(msg_dateEnd)
Debug.Print "msg_dateEndStr..: " & msg_dateEndStr
strFilter = "[ReceivedTime] > '#" & msg_dateStartStr & "#'"
Debug.Print strFilter
strFilter = strFilter & " AND [ReceivedTime] < '#" & msg_dateEndStr & "#'"
Debug.Print strFilter
Set myItem = myItems.Find(strFilter)
While TypeName(myItem) <> "Nothing"
Debug.Print myItem.Subject
myItem.Move myDestFolder
Set myItem = myItems.FindNext
Wend
End Sub

Related

Outlook VBA move sent mail based on SendAs address

I am trying to move sent mail from my regular Sent Items standard folder to two separate folders in Outlook (365). On the left in my Folder Pane I have my email 'main#domain.com', 'Online Archive - main#domain.com' (an Online Archive for more storage similar to a PST I guess) and then a shared mailbox 'secondary#domain.com'.
One of the backup folders is in my Online Archive and the other backup folder is a shared mailbox. Here's the VBA code I have so far. Ideally I would like it to run each time an email is sent/appears in the Sent Items so I think I could use WithEvents somehow but I am okay to run the macro on an as needed basis.
When I run the code none of the mail moves so I think the issue is something with how I am selecting the filtered mail items to move.
Sub MoveItems()
Dim myOlApp As New Outlook.Application
Dim myNameSpace As Outlook.NameSpace
Dim mySource As Outlook.MAPIFolder
Dim myDestFolder As Outlook.MAPIFolder
Dim myItems As Outlook.Items
Dim myItem As Object
Set myNameSpace = myOlApp.GetNamespace("MAPI")
Set mySource = myNameSpace.GetDefaultFolder(olFolderSentMail)
Set myItems = mySource.Items
Set myDestFolder = Outlook.Session.Folders("Online Archive - main#domain.com").Folders("Backup")
Set myItem = myItems.Find("[SenderEmailAddress] = 'main#domain.com'")
While TypeName(myItem) <> "Nothing"
myItem.Move myDestFolder
Set myItem = myItems.FindNext
Wend
Set myItem = myItems.Find("[SenderEmailAddress] = 'secondary#domain.com'")
Set myDestFolder = Outlook.Session.Folders("secondary#domain.com").Folders("SecondaryBackup")
While TypeName(myItem) <> "Nothing"
myItem.Move myDestFolder
Set myItem = myItems.FindNext
Wend
End Sub
Sub MoveItems()
Dim myOlApp As New Outlook.Application
Dim myNameSpace As Outlook.NameSpace
Dim mySource, myDestFolder As Outlook.MAPIFolder
Dim myItems As Outlook.Items
Dim myItem As Object
Dim strFilter As String
Set myNameSpace = myOlApp.GetNamespace("MAPI")
Set mySource = myNameSpace.GetDefaultFolder(olFolderSentMail)
Set myItems = mySource.Items
strFilter = "#SQL=" & Chr(34) & "urn:schemas:httpmail:fromname" & Chr(34) & " like '%Main Display Name%'"
Set myDestFolder = Outlook.Session.Folders("Online Archive - main#domain.com").Folders("Backup")
Set myItem = myItems.Find(strFilter)
While TypeName(myItem) <> "Nothing"
myItem.Move myDestFolder
Set myItem = myItems.FindNext
Wend
strFilter = "#SQL=" & Chr(34) & "urn:schemas:httpmail:fromname" & Chr(34) & " like '%Shared Box Display Name%'"
Set myDestFolder = Outlook.Session.Folders("Shared Box Display Name").Folders("Backup")
Set myItem = myItems.Find(strFilter)
While TypeName(myItem) <> "Nothing"
myItem.Move myDestFolder
Set myItem = myItems.FindNext
Wend
End Sub
You may change to senderName if senderEmailAddress is not in SMTP format.
Sub MoveItems_senderName()
Dim mySource As Folder
Dim myDestFolder As Folder
Dim myItems As Items
Dim myItem As Object
Set mySource = Session.GetDefaultFolder(olFolderSentMail)
'mySource.Display
Set myItems = mySource.Items
Set myDestFolder = Session.Folders("Online Archive - main#domain.com").Folders("Backup")
Debug.Print "senderName: " & senderName
Set myItem = myItems.Find("[SenderName] = 'text from immediate pane'")
While TypeName(myItem) <> "Nothing"
myItem.Move myDestFolder
Set myItem = myItems.FindNext
Wend
End Sub

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

Trouble setting the subfolder

I'm new to Outlook VBA and having a tough time figuring out how to set my subfolder in the code below. I have been trouble shooting this all day. Not sure what I'm missing.
Sub DeleteOlderThan6months()
Dim oFolder As Folder
Dim Date6months As Date
Dim ItemsOverMonths As Outlook.Items
Dim DateToCheck As String
Date6months = DateAdd("d", -1, Now())
Date6months = Format(Date6months, "mm/dd/yyyy")
Set oFolder = oFolder.Folders("My#email.com").Folders("Inbox").Folders("Zip Files")
DateToCheck = "[Received] <= """ & Date6months & """"
Set ItemsOverMonths = oFolder.Items.Restrict(DateToCheck)
For i = ItemsOverMonths.Count To 1 Step -1
ItemsOverMonths.Item(i).Delete
Next
Set ItemsOverMonths = Nothing
Set oFolder = Nothing
End Sub
This should do it, see how i set the subfolder
Option Explicit
Sub DeleteOlderThan6months()
'// Declare variables
Dim oFolder As Folder
Dim Date6months As Date
Dim ItemsOverMonths As Outlook.Items
Dim DateToCheck As String
Dim olNs As Outlook.NameSpace
Dim Inbox As Outlook.MAPIFolder
Dim oItem As Object
Dim i As Long
'// set your inbox and subfolder
Set olNs = Application.GetNamespace("MAPI")
Set Inbox = olNs.GetDefaultFolder(olFolderInbox)
Set oFolder = Inbox.Folders("Zip Files")
Date6months = DateAdd("d", -1, Now())
Date6months = Format(Date6months, "mm/dd/yyyy")
DateToCheck = "[Received] <= """ & Date6months & """"
Set ItemsOverMonths = oFolder.Items.Restrict(DateToCheck)
'// Loop through the Items in the folder backwards
For i = ItemsOverMonths.Count To 1 Step -1
Set oItem = ItemsOverMonths.Item(i)
If TypeOf oItem Is Outlook.MailItem Then
Debug.Print oItem.Subject
oItem.Delete
End If
Next
Set ItemsOverMonths = Nothing
Set oFolder = Nothing
End Sub
set Inbox = Application.Session.GetDefaultFolder(olFolderInbox)
set oFolder = Inbox.Folders.Item("Zip Files")

Having MS Access Search Outlook for e-mails

So I am trying to create a Macro that will search my e-mails based on a piece of information on an access form I know I am close but I cannot seem to figure out the final piece
Private Sub btnEMAIL_Click()
Dim strID As String, strMessages As String
Call Outlook_open 'CHECKS TO SEE IF OUT LOOK IS OPEN
Dim myOlApp As Object
Set myOlApp = CreateObject("Outlook.Application") 'Creates outlook object
strID = PayeeID.Value 'this is a value on the form
Dim myNameSpace As Outlook.Namespace
Dim myInbox As Outlook.MAPIFolder
Dim myitems As Outlook.Items
Dim myitem As Object
Dim blnfound As Boolean
Set myNameSpace = myOlApp.GetNamespace("MAPI")
Set myInbox = myNameSpace.Folders("HQP Field Compensation").Folders("Inbox")
Set myitems = myInbox.Items
Set mySearch = AdvancedSearch(Scope:=myInbox,Filter:="urn:schemas:mailheader:subject= '" & strID & "'")
Set myResults = mySearch.Results
If myResults.Count > 0 Then
For intCounter = 1 To myResults.Count
myResults.Item(intCounter).Display 'Should display the relevant e-mail
Next intCounter
End If
End Sub
AdvancedSearch is asynchronous/ Since you are only searching through the Inbox, use Items.Restrict or Items.Find/FindNext
set myInbox = myNameSpace.GetDefaultFolder(olFolderInbox)
set myItems = myInbox.Items
set myItem = myItems.Find("[Subject]='" & strID & "'")
while Not (myItem Is Nothing)
myItem.Display
set myItem = myItems.FindNext
wend