Moving Emails from Previous Weekday Doing Nothing - vba

I am trying to put together Outlook VBA to find all emails in the primary inbox from the previous weekday (Monday-Friday) and move them to a new folder, which I am also creating.
I tried to add in the logic to skip Saturday and Sunday. Since today is Monday, I should be moving all emails from Friday. It successfully creates the new folder with last Friday's date, but it doesn't move any emails. Last I checked, on Friday it did move the Thursday items. I'm struggling to determine why it wont move last Friday's emails today?
My question is, can anyone determine why Friday's emails are not being moved at all?
Below is the code I currently use:
Sub Move_Yesterdays_Emails()
'***Creates a new folder named yesterdays date under the inbox***
Dim myNameSpace As Outlook.NameSpace
Dim myFolder As Outlook.Folder
Dim myNewFolder As Outlook.Folder
Dim xDay As String
Dim XDate As Date
If Weekday(Now()) = vbMonday Then
XDate = Date - 3
Else
XDate = Date - 1
End If
Set myNameSpace = Application.GetNamespace("MAPI")
Set myFolder = myNameSpace.GetDefaultFolder(olFolderInbox)
Set myNewFolder = myFolder.Folders.Add(XDate)
'***Releases memory***
Set myNameSpace = Nothing
Set myFolder = Nothing
Set myNewFolder = Nothing
'***Finds all emails in the inbox from yesterday and moves them to the created folder***
Dim myNameSpace As Outlook.NameSpace
Dim Inbox As Outlook.MAPIFolder
Dim Items As Outlook.Items
Dim Item As Object
Dim Filter As String
Dim i As Long
Filter = "[ReceivedTime] >= '" & _
CStr(XDate) & _
" 12:00AM' AND [ReceivedTime] < '" & _
CStr(XDate) & " 12:00AM'"
Debug.Print Filter
Set myNameSpace = Application.GetNamespace("MAPI")
Set Inbox = myNameSpace.GetDefaultFolder(olFolderInbox)
Set Items = Inbox.Items.Restrict(Filter)
Items.Sort "[ReceivedTime]"
For i = Items.Count To 1 Step -1
DoEvents
If TypeOf Items(i) Is MailItem Then
Debug.Print Items(i)
Set Item = Items(i)
Item.Move Inbox.Folders(XDate)
End If
Next
End Sub
Thank you in advance. I'd like to get this solved today, so I don't have to wait until next Monday to try the situation live again.

There were several issues with your code, I fixed everything and it now runs fine
The main mistake: your filter was
[ReceivedTime] >= '15/06/2018 12:00AM' AND [ReceivedTime] < '15/06/2018 12:00AM'
So basically it searched for nothing as the 2 datetime in between were the same. You should make your filter like this
Filter = "[ReceivedTime] >= '" & _
CStr(XDate) & _
" 12:00AM' AND [ReceivedTime] < '" & _
CStr(XDate + 1) & " 12:00AM'"
You also had issue with the Item.Move. You should specify an Outlook.Folder type of object there
Whole sub becomes
Option Explicit
Sub Move_Yesterdays_Emails()
'***Creates a new folder named yesterdays date under the inbox***
Dim myNameSpace As Outlook.NameSpace
Dim myFolder As Outlook.Folder
Dim myNewFolder As Outlook.Folder
Dim xDay As String
Dim XDate As Date
If Weekday(Now()) = vbMonday Then
XDate = Date - 3
Else
XDate = Date - 1
End If
Set myNameSpace = Application.GetNamespace("MAPI")
Set myFolder = myNameSpace.GetDefaultFolder(olFolderInbox)
Set myNewFolder = myFolder.Folders.Add(XDate)
'***Finds all emails in the inbox from yesterday and moves them to the created folder***
'Dim myNameSpace As Outlook.NameSpace ---> DUPLICATE DECLARATION
Dim Inbox As Outlook.MAPIFolder
Dim Items As Outlook.Items
Dim Item As Object
Dim Filter As String
Dim i As Long
Filter = "[ReceivedTime] >= '" & _
CStr(XDate) & _
" 12:00AM' AND [ReceivedTime] < '" & _
CStr(XDate + 1) & " 12:00AM'"
Debug.Print Filter
Set myNameSpace = Application.GetNamespace("MAPI")
Set Inbox = myNameSpace.GetDefaultFolder(olFolderInbox)
Set Items = Inbox.Items.Restrict(Filter)
Items.Sort "[ReceivedTime]"
For i = Items.Count To 1 Step -1
DoEvents
If TypeOf Items(i) Is MailItem Then
Debug.Print Items(i)
Set Item = Items(i)
Item.Move myNewFolder
End If
Next
End Sub

Related

Find email from ReceivedTime

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

Getting attachment file size in outlook VBA

I receive emails and would like to save size of attachment in Excel sheet.
I can save size of email but I can't get size of attachment.
I looked up attachment.Size Property in MSDN, but it doesn't work. Could you please take a loop my for loop? I've attached my code below. I appreciate it if anyone would help.
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("teammailbox#example.ca")
Set Folder = Session.GetSharedDefaultFolder(olShareName, olFolderInbox).Folders("Subfolder1").Folders("Subfolder2")
Set olItems = Folder.Items
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] = ""jon.doe#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
MsgBox myItem.Attachments.Size
Range("eMail_subject").Offset(i, 0).Value = myItem.Subject
Range("eMail_date").Offset(i, 0).Value = Format(myItem.ReceivedTime, "h:nn")
Range("eMail_size").Offset(i, 0).Value = myItem.Size
i = i + 1
Next myItem
Set Folder = Nothing
Set OutlookNamespace = Nothing
Set OutlookApp = Nothing
End Sub
Sub sbClearCellsOnlyData()
Rows("5:" & Rows.Count).ClearContents
End Sub
The VBEditor has a great built-in tool for debugging. If you press Ctrl+F9, while selecting the myItem text with your mouse cursor you would be able to see it. It is called "Local Window" (or in German - "überwachungsausdrücke")
Long stroy short, give it a try like this in the code:
MsgBox myItem.Attachments.Item(1).Size
Instead of:
MsgBox myItem.Attachments.Size
Before doing this, it is a good idea to see whether the attachment exists:
If myItem.Attachments.Count > 0 Then
Attachment.Size property is not the size of the file blob - it is the size of the attachment record in the message store, which includes the attachment data, file name, and various other MAPI properties.
If you only want the file data, you can either use Extended MAPI (C++ or Delphi) to open the blob (PR_ATTACH_DATA_BIN) as IStream and call IStream::Stat. If you are limited to using the Outlook Object Model only, the only workaround is saving the attachment as file (Attachment.SaveAsFile) and then retrieving the file size.
I got hint from #Vityata and my below code is fixed and it works now.
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")
If myItem.Attachments.Count > 0 Then
Range("eMail_size").Offset(i, 0).Value = myItem.Attachments.Item(1).Size / 1024 'convert to 3 digits (KB)
Else
Range("eMail_size").Offset(i, 0).Value = "No attached file"
End If
i = i + 1
Next myItem

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

Check e-mails in specific time frame

I need to check items in a folder in a specific time frame.
My code goes through all the mails in the specified folder, but the folder has thousands of mails, so it takes forever.
How do I check the mails only from, for example, 3/16/2015 12:00PM to 3/16/2015 2:00PM?
This is what I have:
Sub ExportToExcel()
Dim appExcel As Excel.Application
Dim wkb As Excel.Workbook
Dim wks As Excel.Worksheet
Dim rng As Excel.Range
Dim workbookFile As String
Dim msg As Outlook.MailItem
Dim nms As Outlook.NameSpace
Dim fld As Outlook.MAPIFolder
Dim itm As Object
'Folder path and file name of an existing Excel workbook
workbookFile = "C:\Users\OutlookItems.xls"
'Select export folder
Set nms = Application.GetNamespace("MAPI")
Set fld = nms.PickFolder
'Handle potential errors with Select Folder dialog box.
If fld Is Nothing Then
MsgBox "There are no mail messages to export", vbOKOnly, _
"Error"
Exit Sub
ElseIf fld.DefaultItemType <> olMailItem Then
MsgBox "There are no mail messages to export", vbOKOnly, _
"Error"
Exit Sub
ElseIf fld.Items.Count = 0 Then
MsgBox "There are no mail messages to export", vbOKOnly, _
"Error"
Exit Sub
End If
' Open and activate Excel workbook.
Set appExcel = CreateObject("Excel.Application")
Set wkb = appExcel.Workbooks.Open(workbookFile)
Set wks = wkb.Sheets(1)
wks.Activate
appExcel.Application.Visible = True
Set rng = wks.Range("A1")
'Copy field items in mail folder.
For Each itm In fld.Items
If itm.Class = Outlook.OlObjectClass.olMail Then
Set msg = itm
If InStr(msg.Subject, "Error in WU_Send") > 0 And DateDiff("h", msg.SentOn, Now) <= 2 Then
rng.Offset(0, 4).Value = msg.Body
Set rng = rng.Offset(1, 0)
End If
End If
Next
End Sub
The problem lies in this part:
For Each itm In fld.Items
If itm.Class = Outlook.OlObjectClass.olMail Then
Set msg = itm
If InStr(msg.Subject, "Error in WU_Send") > 0 And DateDiff("h", msg.SentOn, Now) <= 2 Then
How do I look at e-mails between specified hours?
You need to use the Find/FindNext or Restrict methods of the Items class instead of iterating through all items in the folder. For example:
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
See the following articles for more information and sample code:
How To: Use Find and FindNext methods to retrieve Outlook mail items from a folder (C#, VB.NET)
How To: Use Restrict method to retrieve Outlook mail items from a folder
Also you may find the AdvancedSearch method of the Application class helpful. The key benefits of using the AdvancedSearch method are listed below:
The search is performed in another thread. You don’t need to run another thread manually since the AdvancedSearch method runs it automatically in the background.
Possibility to search for any item types: mail, appointment, calendar, notes etc. in any location, i.e. beyond the scope of a certain folder. The Restrict and Find/FindNext methods can be applied to a particular Items collection (see the Items property of the Folder class in Outlook).
Full support for DASL queries (custom properties can be used for searching too). You can read more about this in the Filtering article in MSDN. To improve the search performance, Instant Search keywords can be used if Instant Search is enabled for the store (see the IsInstantSearchEnabled property of the Store class).
You can stop the search process at any moment using the Stop method of the Search class.
You could just change the line to:
If InStr(msg.Subject, "Error in WU_Send") > 0 And msg.SentOn > "03/16/2015 12:00 PM" AND msg.SentOn < "03/16/2015 2:00 PM" Then
This specifies the time period.
Option Explicit
Sub RestrictTimePeriod()
Dim nms As Namespace
Dim fld As folder ' Subsequent to 2003 otherwise MAPIFolder
Dim msg As MailItem
Dim filterCriteria As String
Dim filterItems As Items
Dim i As Long
Dim start
Dim dif
Set nms = Application.GetNamespace("MAPI")
Set fld = nms.PickFolder
If Not fld Is Nothing Then
start = Now
Debug.Print start
' http://www.jpsoftwaretech.com/use-filters-to-speed-up-outlook-macros/
filterCriteria = "[ReceivedTime] > " & QuoteWrap("2015-03-16 12:00 PM") & _
" And [ReceivedTime] < " & QuoteWrap("2015-03-17 2:00 PM")
Set filterItems = fld.Items.Restrict(filterCriteria)
For i = filterItems.count To 1 Step -1
Set msg = filterItems.Item(i)
Debug.Print msg.Subject
Next
End If
ExitRoutine:
Set nms = Nothing
Set msg = Nothing
Set filterItems = Nothing
Debug.Print Now
dif = (Now - start) * 86400
Debug.Print dif
Debug.Print "Done."
End Sub
Function QuoteWrap(stringToWrap As String, _
Optional charToUse As Long = 39) As String
' http://www.jpsoftwaretech.com/use-filters-to-speed-up-outlook-macros/
' use 34 for double quotes, 39 for apostrophe
QuoteWrap = Chr(charToUse) & stringToWrap & Chr(charToUse)
End Function

VBA to delete Outlook messages from a user created folder over certain time period

I'm looking for a VBA code snippet to delete Outlook messages that are six (6) months or older and sit in a user-created folder.
What does that code look like?
Here is a example script
Sub DeleteOlderThan6months()
Dim oFolder As Folder
Dim Date6months As Date
Dim ItemsOverMonths As Outlook.Items
Dim DateToCheck As String
Date6months = DateAdd("d", -182, Now())
Date6months = Format(Date6months, "mm/dd/yyyy")
Set oFolder = Application.Session.PickFolder 'or set your folder
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