Error creating Outlook Task Item in Sub-folder of Task folder - vba

I've been using a routine that I discovered on Stack Overflow to automatically create a task item in Outlook in the default Tasks folder. I attempted to modify it to create the task in one of two sub-folders of Tasks named "New FTEs" and "New Consultants".
Running this code results in this message from the error handler.
Error Number: -2147221233
Error Source: AddOlkTask
Error Description: The attempted operation failed. An object could not be found.
The problem code is shown between 'start new code and 'end new code. I've tried many variants of this code, but I can't crack it (no pun intended).
Sub AddOlTask(sSubject, sBody, dtDueDate, dtReminderDate, name, program)
On Error GoTo Error_Handler
Dim noDue, pFolder, reminderSetFlag As String
reminderSetFlag = False
If program <> "Career Path Curriculum" Then
dtDue = dtDueDate
dtReminder = dtReminderDate
reminderSetFlag = True
End If
If program = "Active Consultant" Then
pFolder = "New Consultants"
Else
pFolder = "New FTEs"
End If
Const olTaskItem = 3
Dim olApp As Object
Dim OlTask As Object
Set olApp = CreateObject("Outlook.Application")
Set OlTask = olApp.CreateItem(olTaskItem)
With OlTask
.Subject = name & ": " & sSubject
.Status = 1 '0=not started, 1=in progress, 2=complete, 3=waiting,
'4=deferred
.Importance = 1 '0=low, 1=normal, 2=high
.dueDate = dtDue
.ReminderSet = reminderSetFlag
.ReminderTime = dtReminder
.Categories = "Mandatory SkillSoft Training" 'use any of the predefined Categorys or create your own
.body = sBody
.Display
.Save
End With
'start new code
Dim objNS As Outlook.NameSpace
Dim olFolder As Outlook.MAPIFolder
Dim tsk As Outlook.TaskItem
Set olApp = Outlook.Application
Set objNS = olApp.GetNamespace("MAPI")
Set olFolder = objNS.GetDefaultFolder(olFolderTasks)
Set olFolder = olFolder.Folders(pFolder) 'error raised on this line
'end new code
Error_Handler_Exit:
On Error Resume Next
Set OlTask = Nothing
Set olApp = Nothing
Exit Sub
Error_Handler:
MsgBox "The following error has occured" & vbCrLf & vbCrLf & "Error Number: " & _
Err.Number & vbCrLf & "Error Source: AddOlkTask" & vbCrLf & "Error Description: " & _
Err.Description, vbCritical, "An Error has Occurred!"
Resume Error_Handler_Exit
End Sub

I had a similar problem and perhaps the cause of your problem is the same. I discovered the default Inbox was not in the store into which all my emails were loaded from my ISP. The default Inbox was in fact empty because it had never been used.
Run the macro below to discover what default folders you have and which store contains them.
Sub DsplUsernameOfDefaultStores()
Dim NS As Outlook.NameSpace
Dim DefaultFldr As MAPIFolder
Dim FldrTypeNo() As Variant
Dim FldrTypeName() As Variant
Dim InxFldr As Long
Set NS = CreateObject("Outlook.Application").GetNamespace("MAPI")
FldrTypeNo = VBA.Array(olFolderCalendar, olFolderConflicts, olFolderContacts, _
olFolderDeletedItems, olFolderDrafts, olFolderInbox, _
olFolderJournal, olFolderJunk, olFolderLocalFailures, _
olFolderManagedEmail, olFolderNotes, olFolderOutbox, _
olFolderSentMail, olFolderServerFailures, _
olFolderSuggestedContacts, olFolderSyncIssues, olFolderTasks, _
olPublicFoldersAllPublicFolders, olFolderRssFeeds)
FldrTypeName = VBA.Array("Calendar", "Conflicts", "Contacts", _
"DeletedItems", "Drafts", "Inbox", _
"Journal", "Junk", "LocalFailures", _
"ManagedEmail", "Notes", "Outbox", _
"SentMail", "ServerFailures", _
"SuggestedContacts", "SyncIssues", "Tasks", _
"AllPublicFolders", "RssFeeds")
Debug.Print "Stores containing default folders"
For InxFldr = 0 To UBound(FldrTypeNo)
Set DefaultFldr = Nothing
On Error Resume Next
Set DefaultFldr = NS.GetDefaultFolder(FldrTypeNo(InxFldr))
On Error GoTo 0
If DefaultFldr Is Nothing Then
Debug.Print "No default " & FldrTypeName(InxFldr)
Else
Debug.Print "Default " & FldrTypeName(InxFldr) & " in """ & DefaultFldr.Parent.Name & """"
End If
Next
End Sub
Second attempt at identifying the problem
I have added two sub-folders to my Tasks folders and then used the following macro to successfully display their names.
I have used Session instead of GetNamespace("MAPI"). These are supposed to be equivalent but I have once had Session work when GetNamespace("MAPI") did not. I don't remember the details and I did not investigate since I was happy to use Session.
You will need to amend my Set Fldr ... statement if your Tasks folder is not in the same location as mine. You can use Set Fldr = Session.GetDefaultFolder(olFolderTasks) if you prefer.
I have displayed the names with square brackets round them to highlight any stray spaces within the name.
Sub DsplTaskFolders()
Dim Fldr As Folder
Dim InxTskFldrCrnt
Set Fldr = Session.Folders("Outlook data file").Folders("Tasks")
For InxTskFldrCrnt = 1 To Fldr.Folders.Count
Debug.Print "[" & Fldr.Folders(InxTskFldrCrnt).Name & "]"
Next
End Sub

Thanks again Tony. You're code helped me understand the issue. I was not creating the custom folders in the correct location in Outlook. I created then under Inbox, when I should have created them under Tasks. The difference is not obvious. You basically have to right-click on the object Tasks - username#domain.com and select Create New Folder. If you right-click somewhere else, for instance, on the To-Do List, you'll create the folder under Inbox. It's working now.

Related

Run time error 91, code was working before now it isn't?

My code is supposed to check my inbox for unopened emails that contain csv files. When it encounters one it is supposed to download it with a new name and mark the email as read in a new folder.
Everything was working yesterday and now I am getting a run-time error 91.
Option Explicit
Sub SaveAttachments()
Dim myOlapp As Outlook.Application
Dim myNameSpace As Outlook.NameSpace
Dim myFolder As Outlook.MAPIFolder
Dim myItem As Outlook.MailItem
Dim myAttachment As Outlook.Attachment
Dim avDate() As String
Dim vDate As String
Dim Address As String
Dim i As Long
Dim j As Long
Dim csvCount As Long
Dim myDestFolder As Outlook.MAPIFolder
Const myPath As String = "C:\Saved CSV\"
ReDim Preserve avDate(3)
Set myOlapp = CreateObject("Outlook.Application")
Set myNameSpace = Application.GetNamespace("MAPI")
Set myFolder = myNameSpace.GetDefaultFolder(olFolderInbox)
i = 0
j = 0
Set myDestFolder = myFolder.Parent.Folders("CSV Emails")
For i = myFolder.Items.Count To 1 Step -1
If TypeName(myFolder.Items(i)) = "MailItem" Then
Set myItem = myFolder.Items(i)
End If
csvCount = 0
If myItem.UnRead = True Then 'Run time error Here'
avDate = Split(CStr(myItem.ReceivedTime), "/")
vDate = Mid(avDate(2), 1, 4) & "-" & avDate(1) & "-" & avDate(0)
If myItem.Attachments.Count <> 0 Then
For Each myAttachment In myItem.Attachments
If LCase(Right(myAttachment.FileName, 3)) = "csv" Then
j = j + 1
csvCount = csvCount + 1
Dim recipientsItem As Object
Dim OldMessage As Outlook.MailItem
Set OldMessage = ActiveExplorer.Selection.Item(1)
For Each recipientsItem In OldMessage.Recipients
If OldMessage.SenderEmailType = "EX" Then
Address = OldMessage.Sender.GetExchangeUser.PrimarySmtpAddress
End If
If OldMessage.SenderEmailType = "SMTP" Then
Address = mymessage.SenderEmailAddress
End If
Next recipientsItem
myAttachment.SaveAsFile ((myPath) & "," & Address & "," & vDate & " - " & j & " - " & myAttachment.FileName)
End If
Next myAttachment
If csvCount > 0 Then
myItem.UnRead = False
myItem.Move myDestFolder
End If
End If
End If
Next i
SaveAttachments_exit:
Set myAttachment = Nothing
Set myItem = Nothing
Set myNameSpace = Nothing
Set OldMessage = Nothing
Exit Sub
SaveAttachments_err:
MsgBox "An unexpected error has occurred." _
& vbCrLf & "Please note and report the following information." _
& vbCrLf & "Macro Name: GetAttachments" _
& vbCrLf & "Error Number: " & Err.Number _
& vbCrLf & "Error Description: " & Err.Description _
, vbCritical, "Error!"
Resume SaveAttachments_exit
End Sub
I am getting an error on
If myItem.UnRead = True Then
Didn't have the error yesterday. Any help would be appreciated.
I am assuming that it is because the set statement for myItem is within the for loop and it isn't being set properly.
For anyone wondering why I am putting commas in the file name it is so I can extract the senders email address with a -split statement in powershell.
My suspect is that this line Set myItem = myFolder.Items(i) is never executed, and this will cause your If instruction to fail accessing the object property.
This can be caused by several reason:
Outlook doesn't return any mail (Items.Count = 0)
Your If condition is never satisfied (TypeName(myFolder.Items(i)) is never "MailItem")
Your default mailbox is changed, and doesn't contain any MailBox Item.
Technical problems (i.e Can't instantiate an instance of Outlook, Different version of Office, etc.)
Finding the error
To test which of this problem can be, I suggest you to run the code in debug mode and executing each instruction step-by-step (you can do it by pressing F8).
While still executing the code, check the value of your variables (using your Local Variable Window).
This can help you better understanding what's going on with your code, and can be a great help in finding where is the issue.
Check if the object is Not Null
In any case, it's a good practice to check if the object is initialized, before trying accessing it.
To do that, you can add this instruction:
If Not myItem Is Nothing then
If myItem.UnRead = True Then
'rest of your code...
Hope this helps.

How to Search Items with Attachment and keyword in Subject using Filter

I am working on a code which attachment will be download to folder location in context to subject by using a subject filter.
After a long search on the internet, my code is working but the problem here is that I want to put the keyword in the subject filter so that it will download the attachment as the subject keep changing every day
e.g. Sub: training_24357 on one day and training_24359 on the next day.
Also, I want to run my code after every 5 minutes automatically, any help will be much appreciated,
below is my code.
Sub Attachment()
Dim OutOpened As Boolean
Dim App As Outlook.Application
Dim Ns As Outlook.NameSpace
Dim Folder As Outlook.MAPIFolder
Dim Attach As Outlook.Attachment
Dim Item As Object
Dim MailItem As Outlook.MailItem
Dim subject As String
Dim saveFolder As String
Dim dateFormat As String
saveFolder = "D:\Outlook\POS Visit Report"
If Right(saveFolder, 1) <> "\" Then saveFolder = saveFolder & "\"
subject = """*POS Visit*"""
OutOpened = False
On Error Resume Next
Set App = GetObject(, "Outlook.Application")
If Err.Number <> 0 Then
Set App = New Outlook.Application
OutOpened = True
End If
On Error GoTo 0
If App Is Nothing Then
MsgBox "Cannot Start Outlook Mail", vbExclamation
Exit Sub
End If
Set Ns = App.GetNamespace("MAPI")
Set Folder = Ns.GetDefaultFolder(olFolderInbox)
If Not olFolder Is Nothing Then
For Each Item In olFolder.Items
If Item.Class = Outlook.ObjectClass.olMail Then
Set MailItem = Item
If MailItem.subject = subject Then
Debug.Print MailItem.subject
For Each Attach In MailItem.Attachments
dateFormat = Format(Now(), "yyyy-mm-dd H-mm")
Attach.SaveAsFile saveFolder & "(" & dateFormat & ")" & " " & Attach
Next
End If
End If
Next
End If
If OutOpened Then App.Quit
Set App = Nothing
End Sub
To Search for Items with Attachment and by Subject line you can use Items.Restrict Method to filter Items collection containing all the match from the filter
Filter Example: [Attachment & Subject Like '%training%']
Filter = "#SQL=" & Chr(34) & "urn:schemas:httpmail:subject" & _
Chr(34) & " Like '%training%' AND " & _
Chr(34) & "urn:schemas:httpmail:hasattachment" & _
Chr(34) & "=1"
VBA Example https://stackoverflow.com/a/42547062/4539709 Or https://stackoverflow.com/a/42777485/4539709
Now if your running the code from Outlook then you do not need to GetObject, or Set App = New Outlook.Application Just simply Set Ns = Application.GetNamespace("MAPI")
To run your code when Items are added to you Inbox - Try working with Application.Startup Event (Outlook) And Items_ItemAdd Event (Outlook)
Items.ItemAdd Event Occurs 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.
Code Example:
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(olFolderInbox)
Set Items = Inbox.Items
End Sub
Private Sub Items_ItemAdd(ByVal Item As Object)
If TypeOf Item Is Outlook.MailItem Then
'// call sub here
End If
End Sub

Remove duplicate Outlook items from a folder

issue
Outlook 2016 corrupted while I was moving items from an online archive into a pst file.
The PST file has been recovered .... but many items (~7000) are duplicated 5 times
There are a range of item types, standard messages, meeting requests etc
what I tried
I looked at existing solutions and tools, including:
duplicate removal tools - none of which were free other than a trial option to remove 10 items at a time.
A variety of code solutions including:
Jacob Hilderbrand's effort which runs from Excel
Macro in Outlook to delete duplicate emails-
I decided to go the code route as it was relatively simple and to gain more control over how the duplicates were reported.
I will post my self solution below as it may help others.
I would like to see other potential approaches (perhaps powershell) to fixing this problem which may be better than mine.
The approach below:
Provides users with a prompt to select the folder to process
Checks duplicates on the base of Subject, Sender, CreationTime and Size
Moved (rather than delete) any duplicates into a sub-folder (removed items) of the folder being processed.
Create a CSV file - stored under the path in StrPath to create a external reference to Outlook of the emails that have been moved.
Updated: Checking for size surprisingly missed a number of dupes, even for otherwise identical mail items. I have changed the test to subject and body
Tested on Outlook 2016
Const strPath = "c:\temp\deleted msg.csv"
Sub DeleteDuplicateEmails()
Dim lngCnt As Long
Dim objMail As Object
Dim objFSO As Object
Dim objTF As Object
Dim objDic As Object
Dim objItem As Object
Dim olApp As Outlook.Application
Dim olNS As NameSpace
Dim olFolder As Folder
Dim olFolder2 As Folder
Dim strCheck As String
Set objDic = CreateObject("scripting.dictionary")
Set objFSO = CreateObject("scripting.filesystemobject")
Set objTF = objFSO.CreateTextFile(strPath)
objTF.WriteLine "Subject"
Set olApp = Outlook.Application
Set olNS = olApp.GetNamespace("MAPI")
Set olFolder = olNS.PickFolder
If olFolder Is Nothing Then Exit Sub
On Error Resume Next
Set olFolder2 = olFolder.Folders("removed items")
On Error GoTo 0
If olFolder2 Is Nothing Then Set olFolder2 = olFolder.Folders.Add("removed items")
For lngCnt = olFolder.Items.Count To 1 Step -1
Set objItem = olFolder.Items(lngCnt)
strCheck = objItem.Subject & "," & objItem.Body & ","
strCheck = Replace(strCheck, ", ", Chr(32))
If objDic.Exists(strCheck) Then
objItem.Move olFolder2
objTF.WriteLine Replace(objItem.Subject, ", ", Chr(32))
Else
objDic.Add strCheck, True
End If
Next
If objTF.Line > 2 Then
MsgBox "duplicate items were removed to ""removed items""", vbCritical, "See " & strPath & " for details"
Else
MsgBox "No duplicates found"
End If
End Sub
Here's a script that takes advantage of sorting emails to check for duplicates much more efficiently.
There's no need to maintain a giant dictionary of every email you've seen if you are processing emails in a deterministic order (e.g. received date). Once the date changes, you know you'll never see another email with the prior date, therefore, they won't be duplicates, so you can clear your dictionary on each date change.
This script also takes into account the fact that some items use an HTMLBody for the full message definition, and others don't have that property.
Sub DeleteDuplicateEmails()
Dim allMails As Outlook.Items
Dim objMail As Object, objDic As Object, objLastMail As Object
Dim olFolder As Folder, olDuplicatesFolder As Folder
Dim strCheck As String
Dim received As Date, lastReceived As Date
Set objDic = CreateObject("scripting.dictionary")
With Outlook.Application.GetNamespace("MAPI")
Set olFolder = .PickFolder
End With
If olFolder Is Nothing Then Exit Sub
On Error Resume Next
Set olDuplicatesFolder = olFolder.Folders("Duplicates")
On Error GoTo 0
If olDuplicatesFolder Is Nothing Then Set olDuplicatesFolder = olFolder.Folders.Add("Duplicates")
Debug.Print "Sorting " & olFolder.Name & " by ReceivedTime..."
Set allMails = olFolder.Items
allMails.Sort "[ReceivedTime]", True
Dim totalCount As Long, index As Long
totalCount = allMails.count
Debug.Print totalCount & " Items to Process..."
lastReceived = "1/1/1987"
For index = totalCount - 1 To 1 Step -1
Set objMail = allMails(index)
received = objMail.ReceivedTime
If received < lastReceived Then
Debug.Print "Error: Expected emails to be in order of date recieved. Previous mail was " & lastReceived _
& " current is " & received
Exit Sub
ElseIf received = lastReceived Then
' Might be a duplicate track mail contents until this recieved time changes.
' Add the last mail to the dictionary if it hasn't been tracked yet
If Not objLastMail Is Nothing Then
Debug.Print "Found multiple emais recieved at " & lastReceived & ", checking for duplicates..."
objDic.Add GetMailKey(objLastMail), True
End If
' Now check the current mail item to see if it's a duplicate
strCheck = GetMailKey(objMail)
If objDic.Exists(strCheck) Then
Debug.Print "Found Duplicate: """ & objMail.Subject & " on " & lastReceived
objMail.Move olDuplicatesFolder
DoEvents
Else
objDic.Add strCheck, True
End If
' No need to track the last mail, since we have it in the dictionary
Set objLastMail = Nothing
Else
' This can't be a duplicate, it has a different date, reset our dictionary
objDic.RemoveAll
lastReceived = received
' Keep track of this mail in case we end up needing to build a dictionary
Set objLastMail = objMail
End If
' Progress update
If index Mod 10 = 0 Then
Debug.Print index & " Remaining..."
End If
DoEvents
Next
Debug.Print "Finished moving Duplicate Emails"
End Sub
And the helper function referenced above for "uniquely identifying" an email. Adapt as needed, but I think if the subject and full body are the same, there's no point in checking anything else. Also works for calendar invites, etc.:
Function GetMailKey(ByRef objMail As Object) As String
On Error GoTo NoHTML
GetMailKey = objMail.Subject & objMail.HTMLBody
Exit Function
BodyKey:
On Error GoTo 0
GetMailKey = objMail.Subject & objMail.Body
Exit Function
NoHTML:
Err.Clear
Resume BodyKey
End Function
I've wrote a VBA script called "Outlook Duplicated Items Remover"
The source code is available on GitHub
It will find all duplicated items in a folder and its subfolders and move them to a dedicated folder
I simplified the duplicate search as in my case I imported multiple duplicates from PST files but the full mail body didn't match. I don't know why, as I am sure those mail are true duplicates.
My simplification is to match ONLY the receive TIME STAMP and the SUBJECT.
I added an error exception for an error I got some times on the function: Set olDuplicatesFolder = olFolder.Folders("Duplicates").
I did a different format for the debug.print messages.
Attribute VB_Name = "DelDupEmails_DATE_SUBJECT"
Sub DeleteDuplicateEmails_DATE_SUBJECT()
Dim allMails As Outlook.Items
Dim objMail As Object, objDic As Object, objLastMail As Object
Dim olFolder As Folder, olDuplicatesFolder As Folder
Dim strCheck As String
Dim received As Date, lastReceived As Date
Set objDic = CreateObject("scripting.dictionary")
With Outlook.Application.GetNamespace("MAPI")
Set olFolder = .PickFolder
End With
If olFolder Is Nothing Then Exit Sub
On Error Resume Next
Set olDuplicatesFolder = olFolder.Folders("Duplicates")
On Error GoTo 0
If olDuplicatesFolder Is Nothing Then Set olDuplicatesFolder = olFolder.Folders.Add("Duplicates")
Debug.Print "Sorting " & olFolder.Name & " by ReceivedTime..."
Set allMails = olFolder.Items
allMails.Sort "[ReceivedTime]", True
Dim totalCount As Long, index As Long
totalCount = allMails.Count
Debug.Print totalCount & " Items to Process..."
'MsgBox totalCount & " Items to Process..."
lastReceived = "1/1/1987"
For index = totalCount - 1 To 1 Step -1
Set objMail = allMails(index)
On Error Resume Next
received = objMail.ReceivedTime
On Error GoTo 0
If received < lastReceived Then
Debug.Print "Error: Expected emails to be in order of date recieved. Previous mail was " & lastReceived _
& " current is " & received
Exit Sub
ElseIf received = lastReceived Then
' Might be a duplicate track mail contents until this recieved time changes.
' Add the last mail to the dictionary if it hasn't been tracked yet
If Not objLastMail Is Nothing Then
Debug.Print olFolder & " : Found multiple emails recieved at " & lastReceived & ", checking for duplicates..."
'MsgBox "Found multiple emails recieved at " & lastReceived & ", checking for duplicates..."
objDic.Add GetMailKey(objLastMail), True
End If
' Now check the current mail item to see if it's a duplicate
strCheck = GetMailKey(objMail)
If objDic.Exists(strCheck) Then
Debug.Print "#" & index & " - Duplicate: " & lastReceived & " " & objMail.Subject
'Debug.Print "Found Duplicate: """ & objMail.Subject & " on " & lastReceived
'MsgBox "Found Duplicate: """ & objMail.Subject & " on " & lastReceived
objMail.Move olDuplicatesFolder
DoEvents
Else
objDic.Add strCheck, True
End If
' No need to track the last mail, since we have it in the dictionary
Set objLastMail = Nothing
Else
' This can't be a duplicate, it has a different date, reset our dictionary
objDic.RemoveAll
lastReceived = received
' Keep track of this mail in case we end up needing to build a dictionary
Set objLastMail = objMail
End If
' Progress update
If index Mod 100 = 0 Then
Debug.Print index & " Remaining... from " & olFolder
'MsgBox index & " Remaining..."
End If
DoEvents
Next
Debug.Print "Finished moving Duplicate Emails"
MsgBox "Finished moving Duplicate Emails"
End Sub
Function GetMailKey(ByRef objMail As Object) As String
On Error GoTo NoHTML
'GetMailKey = objMail.Subject & objMail.HTMLBody
GetMailKey = objMail.Subject ' & objMail.HTMLBody
Exit Function
BodyKey:
On Error GoTo 0
'GetMailKey = objMail.Subject & objMail.Body
GetMailKey = objMail.Subject ' & objMail.Body
Exit Function
NoHTML:
Err.Clear
Resume BodyKey
End Function

Refer to inbox of second account

I'm trying to look through a specific inbox for unread e-mails with .pdf files attached to them, and then save them into a specific folder.
I need to look through the inbox of certain account profile. My code only works if there is just one Inbox folder and one account profile.
Let's say I have two profiles;
One is xxxx#hotmail.com
The second zzzz#hotmail.com
How do I run the code on the Inbox of the second account?
(zzzz#hotmail.com)
The following is the code that I have so far;
Sub GetAttachments()
On Error GoTo GetAttachments_err
Dim ns As NameSpace
Dim Inbox As MAPIFolder
Dim Item As Object
Dim Atmt As Attachment
Dim FileName As String
Dim varResponse As VbMsgBoxResult
Set ns = GetNamespace("MAPI")
Set Inbox = ns.GetDefaultFolder(olFolderInbox)
i = 0
' Checks inbox for messages.
If Inbox.Items.Count = 0 Then
MsgBox "There are no messages in your Inbox.", vbInformation, _
"Nothing found"
Exit Sub
End If
' Checks inbox for unread messages.
If Inbox.UnReadItemCount = 0 Then
"Nothing found"
Exit Sub
End If
' Checks for unread messages with .pdf files attached to them, if yes then saves it to specific folder. _
Puts date and time from when the mail was created infront of the filename.
For Each Item In Inbox.Items
For Each Atmt In Item.Attachments
If Item.UnRead = True Then
If Right(Atmt.FileName, 3) = "pdf" Then
FileName = "C:\Users\XXX\Documents\Office Macro\" & _
Format(Item.CreationTime, "yyyymmdd_hhnnss_") & Atmt.FileName
Atmt.SaveAsFile FileName
i = i + 1
End If
End If
Next Atmt
Next Item
' Shows how many attached files there are if any are found.
If i > 0 Then
& vbCrLf & "Jag har sparat dem till C:\Users\XXX\Documents\Office Macro folder." _
& vbCrLf & vbCrLf & "Would you like to see your files?" _
vbQuestion + vbYesNo, "Finished!")
If varResponse = vbYes Then
Shell "Explorer.exe /e,C:\Users\XXX\Documents\Office Macro\", vbNormalFocus
End If
Else
MsgBox "No attached files could be found.", vbInformation, _
"Finished!"
End If
GetAttachments_exit:
Set Atmt = Nothing
Set Item = Nothing
Set ns = Nothing
Exit Sub
GetAttachments_err:
MsgBox "An unkown ghost spooked the program." _
& vbCrLf & "Please note and report the following information." _
& vbCrLf & "Macro Name: GetAttachments" _
& vbCrLf & "Error Number: " & Err.Number _
& vbCrLf & "Error Description: " & Err.Description _
, vbCritical, "Error!"
Resume GetAttachments_exit
Exit Sub
End Sub
After further inspection of the mailboxes I see that there are some differences:
xxxx#hotmail.com is of the type "IMAP/SMTP"
zzzz#hotmail.com is of the type "Exchange ActiveSync"
I've also noticed that that the account ID I would need to use is 4, as seen in this code when sending a new message with a test-macro specifying what profile you want to send the mail from by assigning profile ID in the script:
Sub Mail_small_Text_Change_Account()
'Only working in Office 2007-2013
'Don't forget to set a reference to Outlook in the VBA editor
Dim OutApp As Outlook.Application
Dim OutMail As Outlook.MailItem
Dim strbody As String
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(olMailItem)
strbody = "Hi there" & vbNewLine & vbNewLine & _
"This is line 1" & vbNewLine & _
"This is line 2" & vbNewLine & _
"This is line 3" & vbNewLine & _
"This is line 4"
On Error Resume Next
With OutMail
.To = "blabla#blabla.nl"
.CC = ""
.BCC = ""
.Subject = "This is the Subject line"
.Body = strbody
'SendUsingAccount is new in Office 2007
'Change Item(1)to the account number that you want to use
.SendUsingAccount = OutApp.Session.Accounts.Item(4) <<<< ACCOUNT ID
.Send 'or use .Display
End With
On Error GoTo 0
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
Set Inbox = ns.GetDefaultFolder(olFolderInbox)
You get only the delivery store's inbox folder to find the items.
The Stores property of the Namespace class returns a Stores collection object that represents all the Store objects in the current profile. You can find the required store and then use the GetDefaultFolder method of the Store class instead. This method is similar to the GetDefaultFolder method of the NameSpace object. The difference is that this method gets the default folder on the delivery store that is associated with the account, whereas NameSpace.GetDefaultFolder returns the default folder on the default store for the current profile.
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(olMailItem)
There is no need to create a new Outlook Application instance in Outlook VBA.
The Outlook object model provides the Find/FindNext or Restrict methods of the Items class. Also you may find the AdvancedSearch method of the Application class helpful.

Outlook VBA - Error 424 Object Required error - but I can't work out why

We get hundreds of invoices emailed in per day - all are PDF format, and for most members of my dept, they're doing nothing more than marking them as read and moving them to a folder. My folder is called "invoices" and is a subfolder to my Inbox. I have written the following code, it throws an error 424 on the lines:
Set myInbox = myNameSpace.GetDefaultFolder(olFolderInbox)
All I'm trying to do is check if an email is unread and has a pdf attachment, then move it to my "invoices" folder. Code follows:
Sub Lazy()
On Error GoTo Lazy_err
' Declare the variables
Dim ns As NameSpace
Dim myInbox As Outlook.Folder
Dim myDestFolder As Outlook.Folder
Dim Item As Object
Dim Atmt As Attachment
Dim i As Integer
' Set variables
Set ns = GetNamespace("MAPI")
Set myInbox = myNameSpace.GetDefaultFolder(olFolderInbox)
Set myDestFolder = myInbox.Folders("invoices")
i = 0
' If statement to check if there's any unread emails in the box
If Inbox.UnReadItemCount = 0 Then
MsgBox "There are no unread messages in your Inbox.", vbInformation, _
"Nothing Found"
Exit Sub
End If
For Each Item In Inbox.Items
If Item.UnRead = True Then
For Each Atmt In Item.Attachments
If Right(Atmt.FileName, 3) = "pdf" Then
myItem.Move myDestFolder
Item.UnRead = False
i = i + 1
End If
Next Atmt
' close off If statements, then move to next item and start again
End If
Next Item
' Display a summary message!
If i > 0 Then
MsgBox "I found " & i & " emails." _
& vbCrLf & "I have moved them into the correct folder." _
& vbCrLf & vbCrLf & "Maybe double check to make sure nothing else has been moved?", vbInformation, "Finished!"
Else
MsgBox "There's nothing to find", vbInformation, _
"Finished!"
End If
' Housekeeping - reset everything for next time macro is run
Lazy_exit:
Set Atmt = Nothing
Set Item = Nothing
Set ns = Nothing
' Exit the macro :)
Exit Sub
' Error Handler - goes at very end of script, even after "exit sub"
Lazy_err:
MsgBox "An unexpected error has occurred." _
& vbCrLf & "Please note and report the following information." _
& vbCrLf & "Macro Name: SaveAttachments" _
& vbCrLf & "Error Number: " & Err.Number _
& vbCrLf & "Error Description: " & Err.Description _
, vbCritical, "Error!"
Resume Lazy_exit
End Sub
First of all, you need to correct the namespace variable name as Paul suggested:
' Set variables
Set ns = GetNamespace("MAPI")
Set myInbox = ns.GetDefaultFolder(olFolderInbox)
Then I have noticed the following lines of code:
For Each Item In Inbox.Items
If Item.UnRead = True Then
Don't iterate over all items in the folder. It will take a lot of time and may cause issues related to not releasing objects in time. Use the Find/FindNext or Restrict methods of the Items class instead. You can read more about these methods in the following articles:
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
You have created/initialized a Namespace Object variable ns, but not myNameSpace. Make sure you modify your code to reference appropriate objects.
Sub Lazy()
On Error GoTo Lazy_err
' Declare the variables
Dim ns As NameSpace
Dim myInbox As Outlook.Folder
Dim myDestFolder As Outlook.Folder
Dim Item As Object
Dim Atmt As Attachment
Dim i As Integer
' Set variables
Set ns = GetNamespace("MAPI")
Set myInbox = ns.GetDefaultFolder(olFolderInbox)
'Code continues...