I found the code below (here) to get outlook VBA to save sent email to a specified folder.
The code works well, however, any time that it runs on a sent meeting request or meeting reply, it errors.
I have been able to identify line 9 as the line where the error occurs:
Set Item.SaveSentMessageFolder = objFolder
My assumption, then, is that the Item.SaveSentMessageFolder code is incompatible with meeting-type objects. However, I am uncertain as to what the equivalent coding would be for meeting-type objects.
Can this code be modified to handle meeting-type objects in the same fashion that message-type objects are handled?
Private Sub Application_ItemSend(ByVal Item As Object, _
Cancel As Boolean)
Dim objNS As NameSpace
Dim objFolder As MAPIFolder
Set objNS = Application.GetNamespace("MAPI")
Set objFolder = objNS.PickFolder
If TypeName(objFolder) <> "Nothing" And _
IsInDefaultStore(objFolder) Then
Set Item.SaveSentMessageFolder = objFolder
End If
Set objFolder = Nothing
Set objNS = Nothing
End Sub
Public Function IsInDefaultStore(objOL As Object) As Boolean
Dim objApp As Outlook.Application
Dim objNS As Outlook.NameSpace
Dim objInbox As Outlook.MAPIFolder
On Error Resume Next
Set objApp = CreateObject("Outlook.Application")
Set objNS = objApp.GetNamespace("MAPI")
Set objInbox = objNS.GetDefaultFolder(olFolderInbox)
Select Case objOL.Class
Case olFolder
If objOL.StoreID = objInbox.StoreID Then
IsInDefaultStore = True
End If
Case olAppointment, olContact, olDistributionList, _
olJournal, olMail, olNote, olPost, olTask
If objOL.Parent.StoreID = objInbox.StoreID Then
IsInDefaultStore = True
End If
Case Else
MsgBox "This function isn't designed to work " & _
"with " & TypeName(objOL) & _
" items and will return False.", _
, "IsInDefaultStore"
End Select
Set objApp = Nothing
Set objNS = Nothing
Set objInbox = Nothing
End Function
At least one other person has found the property to be ineffective for meeting items.
https://msdn.microsoft.com/en-us/vba/outlook-vba/articles/meetingitem-savesentmessagefolder-property-outlook
"Setting or getting this property has no noticeable effect. Do not use this property."
Try monitoring the Sent Items folder.
Place this code in the ThisOutlookSession module.
Private WithEvents sentMailItems As items
Private Sub Application_Startup()
Set sentMailItems = Session.GetDefaultFolder(olFolderSentMail).items
End Sub
Private Sub sentMailItems_ItemAdd(ByVal Item As Object)
Dim objFolder As Folder
If TypeOf Item Is MeetingItem Then
Set objFolder = Session.PickFolder
If TypeName(objFolder) <> "Nothing" Then
Item.Move objFolder
End If
End If
Set objFolder = Nothing
End Sub
Related
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
If only one email is sent at a time then my code works fine, otherwise, if multiple items come in at the same time then only one of the emails is processed and moved. Basically, my code is processing items as they come into outlook. And if the email is received as a distribution list then the email is sent to a sub folder based on the distribution list name and time of day.
Here's my code:
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.GetDefaultFolder(olFolderInbox).Items
End Sub
Private Sub Items_ItemAdd(ByVal cusItem As Object)
Dim olApp As Outlook.Application
Dim objNS As Outlook.NameSpace
Set olApp = Outlook.Application
Set objNS = olApp.GetNamespace("MAPI")
Set Items = objNS.GetDefaultFolder(olFolderInbox).Items
Dim strEntryID As String
Dim objAddressentry As Outlook.AddressEntry
Dim objRecipient As Outlook.Recipient
Dim objDestFolder As Outlook.MAPIFolder
Dim objRecs As Outlook.Recipients
Dim i As Integer
If TypeName(cusItem) = "MailItem" Then
On Error GoTo ErrorHandler
Set objRecs = cusItem.Recipients
For i = 1 To objRecs.Count
Set objRecipient = objRecs.Item(i)
strEntryID = objRecipient.EntryID
Set objAddressentry = objNS.GetAddressEntryFromID(strEntryID)
If objAddressentry = "amazonselling" And TimeValue(Now()) >= TimeValue("08:00:00 AM") And TimeValue(Now()) <= TimeValue("05:00:00 PM") Then
Set objDestFolder = objNS.GetDefaultFolder(olFolderInbox).Folders("ryule")
cusItem.Move objDestFolder
Exit For
End If
Next
End If
ProgramExit:
Exit Sub
ErrorHandler:
MsgBox Err.Number & " - " & Err.Description & vbCrLf & "Click Ok to continue operations"
Resume ProgramExit
End Sub
Also, if I don't declare and set those variables twice then my code doesn't work as intended. Why is that and how could that be fixed?
The ItemAdd event is not fired when a large number of items are added to the folder at once (more than sixteen). This is a known issue when dealing with the Outlook object model. Instead, I'd suggest considering the NewMailEx event which is fired when a new message arrives in the Inbox and before client rule processing occurs. You can use the Entry ID returned in the EntryIDCollection array to call the NameSpace.GetItemFromID method and process the item.
Anyway, it seems the problem is in your code, try to remove additional declarations from both methods:
Private WithEvents Items As Outlook.Items
Private objNS As Outlook.NameSpace
Private Sub Application_Startup()
Set objNS = Application.GetNamespace("MAPI")
Set Items = objNS.GetDefaultFolder(olFolderInbox).Items
End Sub
Private Sub Items_ItemAdd(ByVal cusItem As Object)
Dim strEntryID As String
Dim objAddressentry As Outlook.AddressEntry
Dim objRecipient As Outlook.Recipient
Dim objDestFolder As Outlook.MAPIFolder
Dim objRecs As Outlook.Recipients
Dim i As Integer
If TypeName(cusItem) = "MailItem" Then
On Error GoTo ErrorHandler
Set objRecs = cusItem.Recipients
For i = 1 To objRecs.Count
Set objRecipient = objRecs.Item(i)
strEntryID = objRecipient.EntryID
Set objAddressentry = objNS.GetAddressEntryFromID(strEntryID)
If objAddressentry = "amazonselling" And TimeValue(Now()) >= TimeValue("08:00:00 AM") And TimeValue(Now()) <= TimeValue("05:00:00 PM") Then
Set objDestFolder = objNS.GetDefaultFolder(olFolderInbox).Folders("ryule")
cusItem.Move objDestFolder
Exit For
End If
Next
End If
ProgramExit:
Exit Sub
ErrorHandler:
MsgBox Err.Number & " - " & Err.Description & vbCrLf & "Click Ok to continue operations"
Resume ProgramExit
End Sub
When I run this code I get the error:
Run-Time error '-2147221233 (8004010f)':
The attempted operation failed. An object could not be found.
Everything is working despite the error.
The error disappears if I change the line
'MsgBox "Awesome"
to
MsgBox "Awesome"
A few tests showed that the error does occur if item.Sendername is used with the copy part. If I do just move the mail it works perfectly.
If I try to use the code separately it works without errors.
Private WithEvents snItems As Items
Private Sub Application_Startup()
Set snItems = Session.GetDefaultFolder(olFolderSentMail).Items
End Sub
Private Sub snItems_ItemAdd(ByVal item As Object)
Dim CopiedItem As MailItem
Dim ShareInbox As Outlook.MAPIFolder
Dim MapiNameSpace As Outlook.NameSpace
If TypeName(item) = "MailItem" Then
Set MapiNameSpace = Application.GetNamespace("MAPI")
Set ShareInbox = MapiNameSpace.Folders("Support").Folders("Send Mails")
If item.SenderName = "Support" Then
Set CopiedItem = item.Copy
CopiedItem.UnRead = True
CopiedItem.Move ShareInbox
End If
End If
'MsgBox "Awesome"
ExitRoutine:
Set ShareInbox = Nothing
Set CopiedItem = Nothing
Set MapiNameSpace = Nothing
End Sub
There is no error if not copied.
It is ok with the following Code
Set MapiNameSpace = Application.GetNamespace("MAPI")
Set ShareInbox = MapiNameSpace.Folders("Support").Folders("Gesendete Elemente")
If item.SenderName = "Support" Then
item.Move ShareInbox
End If
Copying the item adds an item to the Sent Items folder, triggering the ItemAdd code.
Disable the ItemAdd event temporarily.
Private Sub snItems_ItemAdd(ByVal item As Object)
Dim CopiedItem As MailItem
Dim ShareInbox As Outlook.MAPIFolder
Dim MapiNameSpace As Outlook.NameSpace
If TypeName(item) = "MailItem" Then
Set MapiNameSpace = Application.GetNamespace("MAPI")
Set ShareInbox = MapiNameSpace.Folders("Support").Folders("Send Mails")
If item.SenderName = "Support" Then
' Turn off event handling
Set snItems = Nothing
Set CopiedItem = item.Copy
CopiedItem.UnRead = True
CopiedItem.Move ShareInbox
' Turn on event handling
Set snItems = Session.GetDefaultFolder(olFolderSentMail).Items
End If
End If
ExitRoutine:
Set ShareInbox = Nothing
Set CopiedItem = Nothing
Set MapiNameSpace = Nothing
End Sub
A user has some VBA code that pops up with a folder view to choose where to save a copy of "Sent Items" to when "Send" is pressed.
The issue is, it only works with the main mailbox, and not PST's
Is there a way to allow this code to copy to PST folders too?
Private Sub Application_ItemSend(ByVal Item As Object, _
Cancel As Boolean)
Dim objNS As NameSpace
Dim objFolder As MAPIFolder
On Error Resume Next
Set objNS = Application.Session
If Item.Class = olMail Then
Set objFolder = objNS.PickFolder
If Not objFolder Is Nothing And _
IsInDefaultStore(objFolder) And _
objFolder.DefaultItemType = olMailItem Then
Set Item.SaveSentMessageFolder = objFolder
Set msg = MailItem.Copy
msg.UnRead = False
msg.Save
msg.Move objNS.GetDefaultFolder(olFolderSentMail)
Else
Set objFolder = _
objNS.GetDefaultFolder(olFolderSentMail)
Set Item.SaveSentMessageFolder = objFolder
Set msg = MailItem.Copy
msg.UnRead = False
msg.Save
msg.Move objNS.GetDefaultFolder(olFolderSentMail)
End If
End If
Set objFolder = Nothing
Set objNS = Nothing
End Sub
Public Function IsInDefaultStore(objOL As Object) As Boolean
Dim objApp As Outlook.Application
Dim objNS As Outlook.NameSpace
Dim objInbox As Outlook.MAPIFolder
Dim blnBadObject As Boolean
On Error Resume Next
Set objApp = objOL.Application
If Err = 0 Then
Set objNS = objApp.Session
Set objInbox = objNS.GetDefaultFolder(olFolderInbox)
Select Case objOL.Class
Case olFolder
If objOL.StoreID = objInbox.StoreID Then
IsInDefaultStore = True
Else
IsInDefaultStore = False
End If
Case olAppointment, olContact, olDistributionList, _
olJournal, olMail, olNote, olPost, olTask
If objOL.Parent.StoreID = objInbox.StoreID Then
IsInDefaultStore = True
Else
IsInDefaultStore = False
End If
Case Else
blnBadObject = True
End Select
Else
blnBadObject = True
End If
If blnBadObject Then
MsgBox "This function isn't designed to work " & _
"with " & TypeName(objOL) & _
" objects and will return False.", _
, "IsInDefaultStore"
IsInDefaultStore = False
End If
Set objApp = Nothing
Set objNS = Nothing
Set objInbox = Nothing
End Function
Do you mean you want the messages moved to somewhere other than the default Sent Items folder? If so, you either need to ask the user to pick it or get a Folder object via NameSpace.GetFolderFromID if you have saved the Folder.EntryID value for the destination folder somewhere. Otherwise, you'll have to find the folder by name by looping through Store.Folders for every Store in NameSpace.Stores, which could get nasty.
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