Code in Application_Quit() not Running (Outlook) - vba

I've added some VBA code to my outlook application to run some clean-up when I close the program. Specifically, I delete any notification emails automatically generated by my test environment at work.
Then I try to empty my junk folder, mark emails in a specific folder as read, and then permanently delete all the items from my "Deleted Items" folder. Here is the code:
Private Sub Application_Quit()
On Error Resume Next
Call delete_LV_emails
Call mark_JIRA_read
Call empty_junk
Call empty_deleted
End Sub
The subs that I am calling are in a module named "Cleanup", and I know they all work when I run them on their own. However, only the "delete_LV_emails" sub gets called. That is, when I close/re-open outlook. The only thing that has occurred is that the automatically generated emails are moved to the "Deleted Items" folder. I can't figure out why only one of the subs is being called.
If it matters, the code for each of the subs is below:
Sub delete_LV_emails()
On Error Resume Next
Dim olNS As Outlook.NameSpace
Dim olFolder As Outlook.Folder
Dim olItem As Object
Dim arrKeys(0 To 1) As String
Set olNS = Application.GetNamespace("MAPI")
Set olFolder = olNS.GetDefaultFolder(olFolderInbox)
arrKeys(0) = "LabVIEW Error"
arrKeys(1) = "Test Complete"
iItemCount = olFolder.Items.Count
sDate = Split(Str(Now), " ")(0)
For iItemInd = iItemCount To 1 Step -1
Set olItem = olFolder.Items(iItemInd)
If Not Split(Str(olItem.CreationTime), " ")(0) = sDate Then GoTo NEXTITEM
iKeyInd = 0
While Not iKeyInd > 1
If InStr(olItem.Subject, arrKeys(iKeyInd)) Then olItem.Delete
iKeyInd = iKeyInd + 1
Wend
NEXTITEM:
Next
Set olNS = Nothing
Set olFolder = Nothing
Set olItem = Nothing
End Sub
Sub empty_deleted()
On Error Resume Next
Dim olNS As Outlook.NameSpace
Dim olFolder As Outlook.Folder
Dim olItem As Object
Set olNS = Application.GetNamespace("MAPI")
Set olFolder = olNS.GetDefaultFolder(olFolderDeletedItems)
iItemCount = olFolder.Items.Count
For iItemInd = iItemCount To 1 Step -1
Set olItem = olFolder.Items(iItemInd)
olItem.Delete
Next
Set olNS = Nothing
Set olFolder = Nothing
Set olItem = Nothing
End Sub
Sub empty_junk()
On Error Resume Next
Dim olNS As Outlook.NameSpace
Dim olFolder As Outlook.Folder
Dim olItem As Object
Set olNS = Application.GetNamespace("MAPI")
Set olFolder = olNS.GetDefaultFolder(olFolderJunk)
iItemCount = olFolder.Items.Count
For iItemInd = iItemCount To 1 Step -1
Set olItem = olFolder.Items(iItemInd)
olItem.Delete
Next
Set olNS = Nothing
Set olFolder = Nothing
Set olItem = Nothing
End Sub
Sub mark_JIRA_read()
On Error Resume Next
Dim olNS As Outlook.NameSpace
Dim olFolder As Outlook.Folder
Dim olItem As Object
Set olNS = Application.GetNamespace("MAPI")
Set olFolder = olNS.GetDefaultFolder(olFolderInbox).Folders("Jira")
iItemCount = olFolder.Items.Count
For iItemInd = iItemCount To 1 Step -1
Set olItem = olFolder.Items(iItemInd)
If olItem.UnRead Then olItem.UnRead = False
Next
Set olNS = Nothing
Set olFolder = Nothing
Set olItem = Nothing
End Sub
I realize that this is an extremely long-winded question, but if anyone has any insight I would greatly appreciate it.

Remove On Error Resume Next from your code then run it again
On Error Resume Next you are basically instructing VBA to essentially ignore the error and resume execution on the next line of code.
It is very important to remember that On Error Resume Next does not in any way "fix" the error. It simply instructs VBA to continue as if no error occurred.
See more info on
http://www.cpearson.com/excel/ErrorHandling.htm

The latest versions of Outlook do not call the Quit event handler. They do not pass Go and do not collect $200 - they just quit.
You can watch the Explorer.Close and Inspector.Close events - if there is only one Explorer or Inspector left (as reported by Application.Explorers.Count and Application.Inspectors.Count), Outlook is closing.

Related

How to setup VBscript to run in a specific folder in Outlook [duplicate]

How can I in an Outlook VBA macro iterate all email items in a specific Outlook folder (in this case the folder belongs not to my personal inbux but is a sub-folder to the inbox of a shared mailbox.
Something like this but I've never done an Outlook macro...
For each email item in mailboxX.inbox.mySubfolder.items
// do this
next item
I tried this but the inbox subfolder is not found...
Private Sub Application_Startup()
Dim objNS As Outlook.NameSpace
Dim objFolder As Outlook.MAPIFolder
Set objNS = GetNamespace("MAPI")
Set objFolder = objNS.Folders("myGroupMailbox")
Set objFolder = objFolder.Folders("Inbox\mySubFolder1\mySubFolder2")
On Error GoTo ErrorHandler
Dim Msg As Outlook.MailItem
For Each Item In objFolder.Items
If TypeName(Item) = "MailItem" Then
Set Msg = Item
If new_msg.Subject Like "*myString*" Then
strBody = myItem.Body
Dim filePath As String
filePath = "C:\myFolder\test.txt"
Open filePath For Output As #2
Write #2, strBody
Close #2
End If
End If
ProgramExit:
Exit Sub
ErrorHandler:
MsgBox Err.Number & " - " & Err.Description
Resume ProgramExit
Next Item
End Sub
In my case the following worked:
Sub ListMailsInFolder()
Dim objNS As Outlook.NameSpace
Dim objFolder As Outlook.MAPIFolder
Set objNS = GetNamespace("MAPI")
Set objFolder = objNS.Folders.GetFirst ' folders of your current account
Set objFolder = objFolder.Folders("Foldername").Folders("Subfoldername")
For Each Item In objFolder.Items
If TypeName(Item) = "MailItem" Then
' ... do stuff here ...
Debug.Print Item.ConversationTopic
End If
Next
End Sub
Likewise, you can as well iterate through calender items:
Private Sub ListCalendarItems()
Set olApp = CreateObject("Outlook.Application")
Set olNS = olApp.GetNamespace("MAPI")
Set olRecItems = olNS.GetDefaultFolder(olFolderTasks)
strFilter = "[DueDate] > '1/15/2009'"
Set olFilterRecItems = olRecItems.Items.Restrict(strFilter)
For Each Item In olFilterRecItems
If TypeName(Item) = "TaskItem" Then
Debug.Print Item.ConversationTopic
End If
Next
End Sub
Note that this example is using filtering and also .GetDefaultFolder(olFolderTasks) to get the builtin folder for calendar items. If you want to access the inbox, for example, use olFolderInbox.
The format is:
Set objFolder = objFolder.Folders("Inbox").Folders("mySubFolder1").Folders("mySubFolder2")
As advised in a comment "move the next item line to before the ProgramExit label"
Sub TheSub()
Dim objNS As Outlook.NameSpace
Dim fldrImAfter As Outlook.Folder
Dim Message As Outlook.MailItem
'This gets a handle on your mailbox
Set objNS = GetNamespace("MAPI")
'Calls fldrGetFolder function to return desired folder object
Set fldrImAfter = fldrGetFolder("Folder Name Here", objNS.Folders)
For Each Message In fldrImAfter.Items
MsgBox Message.Subject
Next
End Sub
Recursive function to loop over all folders until the specified folder name is found....
Function fldrGetFolder( _
strFolderName As String _
, objParentFolderCollection As Outlook.Folders _
) As Outlook.Folder
Dim fldrSubFolder As Outlook.Folder
For Each fldrGetFolder In objParentFolderCollection
'MsgBox fldrGetFolder.Name
If fldrGetFolder.Name = strFolderName Then
Exit For
End If
If fldrGetFolder.Folders.Count > 0 Then
Set fldrSubFolder = fldrGetFolder(strFolderName,
fldrGetFolder.Folders)
If Not fldrSubFolder Is Nothing Then
Set fldrGetFolder = fldrSubFolder
Exit For
End If
End If
Next
End Function

Move mail to folder from button on ribbon

I have a macro that will run perfectly using F8 to step through it but will skip the last step, to move an email, when run from a button on the ribbon.
Here is the code.
Sub Reportmail()
'Declare Variables
Dim olApp As Outlook.Application
Dim objNS As Outlook.NameSpace
Dim olFolder As Outlook.MAPIFolder
Dim msg As Outlook.MailItem
Dim objDestFolder As Outlook.MAPIFolder
Dim objItem As Outlook.MailItem
Dim Move As Outlook.MailItem
Dim selEmail As Outlook.MailItem
Dim moveToFolder As Outlook.MAPIFolder
Dim MItem As MailItem
'Append subject & Move
For Each MItem In ActiveExplorer.Selection
MItem.Subject = "Suspicious Email: " & MItem.Subject
Next
Set olApp = Outlook.Application
Set objNS = olApp.GetNamespace("MAPI")
Set olFolder = objNS.GetDefaultFolder(olFolderInbox)
On Error GoTo xyz
Set myNewFolder = olFolder.Folders.Add("Suspicious Items")
xyz:
Set olFolder = olFolder.Folders("Suspicious Items")
Set objNS = Application.GetNamespace("MAPI")
'Set folder to move suspicious email into
Set objDestFolder = objNS.GetDefaultFolder(olFolderInbox).Folders("Suspicious Items")
'SET Task
Set selEmail = ActiveExplorer.Selection.Item(1).Forward
'Set Recipient
selEmail.Recipients.Add "myemail#mydonain.com"
'Send Email
selEmail.Send
'Move email to folder
ActiveExplorer.Selection.Item(1).Move objDestFolder
End Sub
You can debug the problem by adding error trapping and examining the error message and the variables' values at the time of the error by adding:
On Error GoTo oops
{your code}
finish:
On Error GoTo 0
Exit Sub
oops:
Debug.Print Err.Number;Err.Description
Debug.Assert False
Resume finish
End Sub
Figured I'd show what I tried to explain in my comment to your question:
'Set olApp = Outlook.Application
'Set objNS = olApp.GetNamespace("MAPI")
'Set objNS = Outlook.Application.GetNamespace("MAPI")
'****I'd prefer condensing above to the following since olApp, objNS not used again
Set olFolder = Outlook.Application.GetNamespace("MAPI").GetDefaultFolder(olFolderInbox)
On Error Resume Next '<-****my personal preference, part 1
Set olFolder = olFolder.Folders("Suspicious Items")
On Error GoTo 0 '<--- updated per comments
'xyz: <-****my personal preference, part 2. Nothing "wrong" with how you wrote it.
If olFolder.Name = "Inbox" Then Set olFolder = olFolder.Add("Suspicious Items")
'****objNS and olFolder already defined!! No need to set 2 objects to same folder.
'Set objNS = Application.GetNamespace("MAPI")
'Set folder to move suspicious email into
'Set objDestFolder = objNS.GetDefaultFolder(olFolderInbox).Folders("Suspicious Items")
'SET Task
'Append subject & Move
For Each MItem In ActiveExplorer.Selection
MItem.Subject = "Suspicious Email: " & MItem.Subject
Set selEmail = MItem.Forward
'Set Recipient
selEmail.Recipients.Add "myemail#mydonain.com"
'Send Email
selEmail.Send
'Move email to folder
'MItem.Move objDestFolder
MItem.Move olFolder
Next

if there is that folder pass else create it

I would like to create a code if there is a folder in outlook than just pass and run the rest of the code else create the folder than just run the rest of the code
If objFolder Is Nothing Then
objFolder = objNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox)
objFolder = objFolder.Folders.Add("test", Outlook.OlDefaultFolders.olFolderInbox)
End If
https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/object-required-error-424
You're not using Set to assign objFolder
In VBA Set is required when assigning objects to a variable.
See: What does the keyword Set actually do in VBA?
As already mentioned, you need to use the keyword Set to assign an object to a variable. The following code will first check whether the folder already exists. If not, it creates one.
Dim objFolder As Outlook.Folder
Dim objTestFolder As Outlook.Folder
Set objFolder = objNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox)
On Error Resume Next
Set objTestFolder = objFolder.Folders("test")
If objTestFolder Is Nothing Then
Set objTestFolder = objFolder.Folders.Add("test", Outlook.OlDefaultFolders.olFolderInbox)
End If
On Error GoTo 0
Typically you should use the following construction:
If obj Is Nothing Then
' need to initialize obj: '
Set obj = ...
Else
' obj already set / initialized. '
End If
So, use the following code instead:
Sub MoveItems()
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 objApp As Outlook.Application
Dim objFolder As Outlook.Folder
Dim objTestFolder As Outlook.Folder
Set myNameSpace = Application.GetNamespace("MAPI")
Set myInbox = myNameSpace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox)
On Error Resume Next
Set objTestFolder = myInbox.Folders("test")
If objTestFolder Is Nothing Then
Set myDestFolder = myInbox.Folders.Add("test", Outlook.OlDefaultFolders.olFolderInbox)
End If
On Error GoTo 0
Set oDeletedItems = Application.Session.GetDefaultFolder(olFolderDeletedItems)
Set myitems = oDeletedItems.Items
Debug.Print myitems.Count
For I = myitems.Count To 1 Step -1
myitems.Item(I).Move myDestFolder
Next
End Sub

Move Outlook incoming message to folder that starts with the same codes

I am trying to automate moving incoming messages to a designated subfolder in Outlook.
Messages that contain a projectnumber in the format P000.0000 should be moved to the Inbox's subfolder that starts with the same projectnumber.
The subfolders will be pre-created by hand, so the user can decide which projects to round up in a dedicated subfolder.
The folderstructure is Inbox>Actueel>P000.0000
The first bit, where incoming messages are checked works fine, but after that I get lost... Where it starts with For Each Folder In olFolderPrjcts
The error is on this line Set olFolder = objNS.GetDefaultFolder(olFolderInbox)
This is what I came up with so far:
Private WithEvents myOlItems As Outlook.Items
Private Sub Application_Startup()
Dim olApp As Outlook.Application
Dim objNS As Outlook.NameSpace
Dim olFolder As Outlook.MAPIFolder
Set olApp = Outlook.Application
Set objNS = olApp.GetNamespace("MAPI")
Set olFolder = objNS.GetDefaultFolder(olFolderInbox)
Set myOlItems = objNS.GetDefaultFolder(olFolderInbox).Items
End Sub
Private Sub myOlItems_ItemAdd(ByVal item As Object)
Dim Atts As Outlook.Attachments
Dim Props As Outlook.UserProperties
Dim Prop As Outlook.UserProperty
Dim PropName As String
PropName = "NumberAttachments"
Set Atts = item.Attachments
Set Props = item.UserProperties
Set Prop = Props.Find(PropName, True)
If Prop Is Nothing Then
Set Prop = Props.Add(PropName, olText, True)
End If
Dim olFolder As Outlook.MAPIFolder
Set olFolder = objNS.GetDefaultFolder(olFolderInbox)
Dim olFolderPrjcts
Set olFolderPrjcts = olFolder.Folders("actueel")
Prop.Value = Atts.Count
item.Save
Dim Msg As Outlook.MailItem
If TypeName(item) = "MailItem" Then
Set Msg = item
For Each Folder In olFolderPrjcts
If Left(Msg.Subject, 9) = Left(Folder.Name, 9) Then
Msg.Move (Folder)
End If
Next
' DO SOMETHING TO NEWLY ARRIVED MESSAGE
' If Msg.Subject contains like P000.0000 AND
' folder exists that starts with P000.0000
' then move to that folder
End If
End Sub
Without Option Explicit the error is likely Run-time error '424': Object required.
With Option Explicit the error is likely Compile error: Variable not defined.
Option Explicit
' Tools | Options | Editor tab
' Checkbox "Require Variable Declaration"
Private Sub myOlItems_ItemAdd(ByVal Item As Object)
Dim objNS As Namespace ' <--
Dim olFolder As folder
Dim folder As folder
Dim olFolderPrjcts As folder
Dim Msg As MailItem
Set objNS = GetNamespace("MAPI") ' <--
Set olFolder = objNS.GetDefaultFolder(olFolderInbox)
Set olFolderPrjcts = olFolder.Folders("actueel")
If TypeName(Item) = "MailItem" Then
Set Msg = Item
For Each folder In olFolderPrjcts.Folders
If Left(Msg.subject, 9) = Left(folder.name, 9) Then
'Debug.Print Msg.subject
'Debug.Print folder.name
Msg.move folder ' <-- no brackets
Exit For
End If
Next
End If
End Sub

Unable to forward an email due to run-time error '287'

Set myNameSpace = myOlApp.GetNamespace("MAPI")
Set myInbox = myNameSpace.GetDefaultFolder(olFolderInbox)
Set myitems = myInbox.Items
For Each myitem In myitems
If myitem.Class = olMail Then
If InStr(1, myitem.Subject, "Greetings") > 0 Then
senderemail = myitem.Sender.GetExchangeUser.PrimarySmtpAddress
If senderemail = "abc#xyz.com" Then
Set oMail = myitem.Forward
oMail.Recipients.Add "i#me.com"
oMail.HTMLBody = "Hi"
oMail.Display
End If
End If
End If
Next myitem
My code use to run properly a few weeks back. Today I ran again and debugging it I see that once it comes to Set oMail = myitem.Forward I get an outlook window open and an Run-time error saying Application-defined or object-defined error.
How can I get the forward email and error at the same time? First I use to get the outlook window only after the display command. Also due to this I am not able to execute the next lines of code in my forward email.
Edit:
Also now I see that directly displaying the email does not give any error, but once I use .Forward command this is when error comes.
Few Errors in your code, so I clean it up and added more code - Try it and let me know.
Option Explicit
Sub olForward()
Dim olApp As Outlook.Application
Dim olFolder As Outlook.MAPIFolder
Dim olInbox As Outlook.MAPIFolder
Dim olNameSpace As Outlook.NameSpace
Dim olItem As Outlook.MailItem
Dim olSender As String
Set olApp = New Outlook.Application
Set olNameSpace = Application.GetNamespace("MAPI")
Set olInbox = olNameSpace.GetDefaultFolder(olFolderInbox)
'// Require this procedure be called only when a message is selected
If Application.ActiveExplorer.Selection.Count = 0 Then
Exit Sub
End If
For Each olItem In Application.ActiveExplorer.Selection
If olItem.class = olMail Then
If InStr(1, olItem.Subject, "Greetings") > 0 Then
olSender = olItem.SenderEmailAddress
If olSender = "abc#xyz.com" Then
Set olItem = olItem.Forward
olItem.Recipients.Add "Om3r <i#me.com>"
olItem.HTMLBody = "Hi" + olItem.HTMLBody
olItem.Display
End If
End If
End If
Next
End Sub