This question already has answers here:
Using visual basic to access subfolder in Inbox?
(3 answers)
Closed 1 year ago.
My code isn't working because emails are being forwarded to subfolders with a rule.
I cannot remove this rule nor make any rules on this computer.
I realized that newMailEx is probably the answer to my problems. Would there be a way to convert my code to run off of that instead of item_add?
Private WithEvents Items As Outlook.Items
Private Sub Application_Startup()
Dim olApp As Outlook.Application
Dim objNS As Outlook.NameSpace
Set olApp = Outlook.Application
Set objNS = olApp.GetNamespace("MAPI")
Set Items = objNS.Folders.Item("Data").Folders.Item("Inbox").Items
End Sub
Private Sub Items_ItemAdd(ByVal Item As Object)
Dim Msg As Outlook.MailItem
If TypeOf Item Is Outlook.MailItem Then
'''code to check subject lines and do various things to attachments for the various cases
End If
End Sub
If you are creating a VBA macro in Outlook you need to choose the Application in the left drop-down menu and choose the NewMailEx event to generate the event handler in the editor.
After choosing the NewMailEx entry from the drop-down list you will get the following where you can add your code:
Private Sub Application_NewMailEx(ByVal EntryIDCollection As String)
End Sub
So, in the event handler you may use the `` method in the following way:
Private Sub Application_NewMailEx(ByVal EntryIDCollection As String)
Dim mail as Outlook.MailItem
Set mail = Application.Session.GetItemFromID(strEntryId)
MsgBox mai.Subject
End Sub
Please remember that different kind of items can be passed to the event handler. For example, it can be an appointment item (meeting request). You need to check its message class before casting to the MailItem class to make sure you deal with mail items. Otherwise, an exception could be thrown if non-existing method or property is called.
Related
I'm trying to record a specific next-numbering on certain e-mails after I send them. However Application_ItemSend executes the code before it sends the e-mail.
I'm adding a reference number to the Subject, but I don't want to confuse everyone with random numbers appearing in their inbox.
Is there a way to execute code after the send?
I think I got it:
Declare a new type of events-related variable to ensure every time an e-mail is added to the "Received Items" folder an action is executed.
Private WithEvents Rcvditems As Outlook.Items
The method I used to avoid variables being restored to 'nothing' is using the same Application.Item_Send event. This option will ensure I activate my reader every time I send an e-mail.
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
Dim olApp As Outlook.Application
Dim objNS As Outlook.NameSpace
Set olApp = Outlook.Application
Set objNS = olApp.GetNamespace("MAPI")
Set Rcvditems = objNS.GetDefaultFolder(olFolderSentMail).Items
End Sub
... what it is doing is recalculating my variable 'Rcvditems'.
Finally, as Rcvd_Items is an event-related variable, I can assign event 'AddItem' to it.
Private Sub Rcvditems_ItemAdd(ByVal Item As Object)
On Error GoTo EscapeSub
Call MyMacro(Item)
EscapeSub:
End Sub
Like this I'm ensuring that I won't alter the e-mail when prior sending it, but just the e-mail that is added in the Received-Items folder.
By default, the sent items are placed to the Sent Items folder in Outlook. If so, you can hook to the ItemAdd event of the Items class which belongs to the Sent Items folder. It is fired when one or more items are added to the specified collection. This event does not run when a large number of items are added to the folder at once (more than sixteen) - this is a known issue in OOM and exists in all Outlook versions.
Public WithEvents myOlItems As Outlook.Items
Public Sub Initialize_handler()
Set myOlItems = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderSentItems).Items
End Sub
Private Sub myOlItems_ItemAdd(ByVal Item As Object)
MsgBox Item.Subject
End Sub
Note, the MailItem.SaveSentMessageFolder property allows to set a Folder object that represents the folder in which a copy of the email message will be saved after being sent. So, it is not necessary that an Outlook item will be saved to the Sent Items folder if an add-in sets this property in the ItemSend event handler.
This question looks like it should have been answered here:
Outlook VBA Save Copy Sent Item
I am unable to find the referenced "Items.ItemAdd" event amongst the list of events in the VB Editor for Outlook 2016.
Application.ItemSend is located in "ThisOutLookSession". The script I came up with looks 90% similar to the one posted in the original question and I have the same problem. The mail item is saved in it's pre-send condition.
I can't use "MailItem.SaveSentMessageFolder" as I am trying to move the sent mail to a PST.
The Event is explained here:
https://msdn.microsoft.com/en-us/vba/outlook-vba/articles/items-itemadd-event-outlook
In case someone asks "Why not use the AutoArchive Function?", my organization has some terrible group policies set up for both Sent Items and AutoArchive. I can't wade through the mess to get AutoArchive for sent items set up.
Work with Items.ItemAdd Event (Outlook)
Example
Option Explicit
Private WithEvents Items As Outlook.Items
Private Sub Application_Startup()
Dim olNs As Outlook.NameSpace
Dim Inbox As Outlook.MAPIFolder
Set olNs = Application.GetNamespace("MAPI")
Set Inbox = olNs.GetDefaultFolder(olFolderSentMail)
Set Items = Inbox.Items
End Sub
Private Sub Items_ItemAdd(ByVal Item As Object)
If TypeOf Item Is Outlook.mailitem Then
' code to copy the sent Item here
End If
End Sub
I have a rule in Outlook which sends a daily email into a particular folder. I then have a VBA script which upon noticing a new unread message in that folder goes in and saves the attachment to a folder on my hard drive and does a few other formatting type things (on the attachment).
I then just linked up the script to the rule in the Outlook rules wizard so it runs as a package.
The problem is as follows: the script is kicked off BEFORE the message is sorted into the appropriate folder. In reality it should run after the message is sorted (otherwise there is nothing for it to act upon). Any ideas on how to rectify?
The code currently begins as follows:
sub saveattachment()
Should it be this instead?
private sub saveattachment()
or
public sub saveattachment()
Would it be better to have the "rule" embedded in the macro instead and then just run it as a private sub anytime the daily email appears in my Inbox?
If you need to assign a VBA macro sub to the Outlook rule, the VBA sub should look like the following one:
Public Sub Test(mail as MailItem)
' your code goes there
End Sub
An instance of the MailItem class is passed as a parameter and stands for the email arrived to the Inbox.
But in case if you need to be sure that your code is triggered when a mail is moved to a particular folder you need to handle the ItemAdd event of the Items class which comes from that folder. Be aware, the event is not fired when more than 16 items are added to the folder simultaneously.
Public WithEvents myOlItems As Outlook.Items
Public Sub Initialize_handler()
Set myOlItems = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderContacts).Items
End Sub
Private Sub myOlItems_ItemAdd(ByVal Item As Object)
Dim myOlMItem As Outlook.MailItem
Dim myOlAtts As Outlook.Attachments
Set myOlMItem = myOlApp.CreateItem(olMailItem)
myOlMItem.Save
Set myOlAtts = myOlMItem.Attachments
' Add new contact to attachments in mail message
myOlAtts.Add Item, olByValue
myOlMItem.To = "Sales Team"
myOlMItem.Subject = "New contact"
myOlMItem.Send
End Sub
Finally, you may find the Getting Started with VBA in Outlook 2010 article helpful.
I use event handlers in VBA and Outlook frequently. One of them is one which marks any item which is deleted to be marked as read.
Private Sub deletedItems_ItemAdd(ByVal Item As Object)
Application_Startup
On Error Resume Next
Item.UnRead = False
End Sub
Declared via:
Private WithEvents deletedItems As Outlook.Items
and initialized in Application_Startup as:
Dim olNameSpace As Outlook.NameSpace
Set olNameSpace = olApp.GetNamespace("MAPI")
Set deletedItems = olNameSpace.GetDefaultFolder(olFolderDeletedItems).Items
Unfortunately, this does not affect all the items if I delete multiple items at once.
Is there a way I can do something to hijack this process somehow? I looked into using the _beforeDelete event but you have to set the item correctly each time, which if I could do this problem wouldn't exist anyways.
Apparently I wasn't clear - the use case I have is when I delete messages via the delete key from my inbox, drafts, whatever.
You don't have to.
I was curious about your question so I opened up Outlook and wrote this code in ThisOutlookSession:
Private WithEvents items As Outlook.items
Public Sub SetItems()
Set items = Application.GetNamespace("MAPI") _
.GetDefaultFolder(olFolderDeletedItems) _
.items
End Sub
Private Sub items_ItemAdd(ByVal Item As Object)
Dim mail As MailItem
On Error Resume Next
Set mail = Item
Err.Clear
On Error GoTo 0
If Not mail Is Nothing Then
MsgBox mail.Subject
mail.UnRead = False
End If
End Sub
Then I ran SetItems from the immediate pane, went to my inbox and deleted a SMS message - as expected mail was Nothing. Then I deleted a single email, and got the message with the mail's subject.
When I selected two emails and hit Delete, the event was fired once for each selected email, so I saw two message boxes - it just works! :)
The Outlook API doesn't seem to offer an event which would handle all deletions at once.
i have (almost) exactly the same code and it works also for multiple items - only after sleep-mode Outlook seems to forget how to handle deleted items...
Option Explicit
Public WithEvents itDeleted As items
Private Sub Application_Startup()
Set itDeleted = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderDeletedItems).items
End Sub
Private Sub itDeleted_ItemAdd(ByVal Item As Object)
'MsgBox "deleted-sub fired" 'this only for test-purposes
If TypeOf Item Is MailItem Then
Item.UnRead = False
End If
End Sub
I think the difference in the definition of "deletedItems" is the problem; that you are not checking the mailitem-property is also not optimal.
Hope this helps,
Max
This question already has answers here:
How do I trigger a macro to run after a new mail is received in Outlook?
(2 answers)
Closed 5 years ago.
Win 7, Outlook 2013 I use VBA code that takes an action on some of the files that arrive in my inbox. However, I have to click/run button to run this macro.
Is there a way that this code could run automatically when an email arrives?
I have tried an Outlook rule to run the script but not successful.
I tried this, but this works only when once I run the macro
Private Sub Application_NewMail()
Call GetAttachments_From_Inbox (My Macro)
End Sub
I specifically use a script I run as a rule, applied to all messages. This gives you easy and clear access to the mail item you receive. Since you want to run this on each message setting up WithEvents on your inbox is probably your best bet.
For example:
You can create a listeners for an Outlook folder as follows:
Private WithEvents mainInboxItems As Outlook.Items
Public Sub Application_Startup()
Dim olApp As Outlook.Application
Dim objNS As Outlook.NameSpace
Set olApp = Outlook.Application
Set objNS = olApp.GetNamespace("MAPI")
Set mainInboxItems = objNS.Folders("whatever your main mailbox is called").Folders("AssignNumber").Items
'assumes your "AssignNumber" folder is a subfolder of the main inbox
'otherwise you can nest Folders("myArchive").Folders("AssignNumber).items etc
End Sub
You can do this for as many folders as you want, too.
You can then assign the ItemAdd method to each of them like:
Private Sub mainInboxItems_ItemAdd(ByVal item As Object)
'do Stuff to mailitem
Call GetAttachments_From_Inbox (item)
End Sub
All this code can go in ThisOutlookSession.