Excel VBA Logic idea - vba

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

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

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

Moving Emails from Previous Weekday Doing Nothing

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

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

Skip already categorized mails

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