How to loop through items in a folder? - excel

CONTEXT: I'm trying to first check if mails in a folder ("pending") are read. If the mail is read, move it to another folder ("done").
Then, for the remaining mails in "pending", save the attachments and mark the mail as "read".
PROBLEM: When I try to loop through the items in the folder it drops
Run-time error 438:
The object doesn't support this property or method
CODE:
Sub MoveInbox2Reviewed()
Dim OutlookApp As Outlook.Application
Dim ONameSpace As Object
Dim OItem As Outlook.MailItem
Dim OFolderSrc As Object
Dim OFolderDst As Object
Dim Path As String
Set OutlookApp = New Outlook.Application
Set ONameSpace = OutlookApp.GetNamespace("MAPI")
Set OFolderSrc = ONameSpace.GetDefaultFolder(olFolderInbox).Folders("pending")
Set OFolderDst = ONameSpace.GetDefaultFolder(olFolderInbox).Folders("done")
Path = "C:\Users\..."
For Each OItem In OFolderSrc
If OItem.UnRead = False Then
OItem.Move OFolderDst
End If
Next
For Each OItem In OFolderSrc
OItem.Attachments.SaveAsFile Path & Attachment.DisplayName
OItem.UnRead = False
Next
End Sub

Firstly, you are looping through the folders. not items. You need OFolderSrc.Items.
Secondly, you should never loop through all items in a folder, use Items.Restrict:
For Each OItem In OFolderSrc.Items.Restrict("[Unread] = true")

Related

MailItem.Move method for mail that is read

I'm trying to first check if mails in a specific folder ("pending") are read. If the mail is read, move it to another specific folder ("done").
For the remaining mails in "pending", save the attachments and mark them as "read".
When I try to move each read mail from the "pending" folder to "done" with ".Move", drops
"error 424. An object is required".
The problem is OItem.Move OFolderDst.
Sub MoveInbox2Reviewed()
Dim OutlookApp As Outlook.Application
Dim ONameSpace As Object
Dim OItem As Outlook.MailItem
Dim OFolderSrc As Object
Dim OFolderDst As Object
Dim Path As String
Set OutlookApp = New Outlook.Application
Set ONameSpace = OutlookApp.GetNamespace("MAPI")
Set OFolderSrc = ONameSpace.GetDefaultFolder(olFolderInbox).Folders("pending")
Set OFolderDst = ONameSpace.GetDefaultFolder(olFolderInbox).Folders("done")
Path = "C:\Users\..."
For Each OItem In OFolderSrc.Items.Restrict("[Unread] = False")
OItem.Move OFolderDst 'The problem is here
Next
For Each OItem In OFolderSrc.Items
OItem.Attachments.SaveAsFile Path & Attachment.DisplayName
OItem.UnRead = False
Next
End Sub
Each time the Move call is made the collection is decreased by one item. So, I'd recommend using the reverse for loop instead for moving items from a folder. For example:
for i = Items.Count to 1 step -1
Items(i).Move folder
next
So, in the code you may get all unread items (represented by the Items collection) and then call a reverse loop to move items.

Extract pdf files from an email from a specific contact (sender) and different inbox address in outlook

Good morning friends,
Please, I need your help, I have 2 problems:
1.- I wanted to be able to extract pdf files but an email from a specific contact (sender)
2.- I have several inboxes, how could I set another inbox, but not the one that comes by default - here I tried the following "Set Inbox = olNs.GetDefaultFolder (onothermail#gmail.com)" but it did not work for me
Thank you very much in advance
Option Explicit
Public Sub Example()
'// Declare your Variables
Dim olNs As Outlook.NameSpace
Dim Inbox As Outlook.MAPIFolder
Dim Items As Outlook.Items
Dim Item As Outlook.MailItem
Dim Atmt As Attachment
Dim Filter As String
Dim FilePath As String
Dim AtmtName As String
Dim i As Long
Dim objOwner As Outlook.Recipient
'// Set Inbox Reference
Set olNs = Application.GetNamespace("MAPI")
Set objOwner = olNs.CreateRecipient("secondMail#gmail.com")
Set Inbox = olNs.GetSharedDefaultFolder(objOwner)
FilePath = "C:\Users\Unity\Desktop\adjuntos\"
Filter = "[Unread] = True"
Set Items = Inbox.Items.Restrict(Filter)
'// Loop through backwards
For i = Items.Count To 1 Step -1
Set Item = Items(i)
DoEvents
If Item.Class = olMail Then
If Item.SenderEmailAddress = "senderx#gmail.com" Then
For Each Atmt In Item.Attachments
AtmtName = FilePath & Atmt.FileName
If ((InStr(Atmt.DisplayName, ".jpg") Or InStr(Atmt.DisplayName, ".zip") Or InStr(Atmt.DisplayName, ".PDF") Or InStr(Atmt.DisplayName, ".pdf"))) Then
Atmt.SaveAsFile FilePath & "\" & Atmt.DisplayName
End If
Item.UnRead = False
Next
End If
End If
Next
Set Inbox = Nothing
Set Items = Nothing
Set Item = Nothing
Set Atmt = Nothing
Set olNs = Nothing
End Sub
It seems additionally you need to check the sender's email address of the item. The MailItem.SenderEmailAddress property returns a string that represents the email address of the sender of the Outlook item.
Sub SetFlagIcon()
Dim mpfInbox As Outlook.Folder
Dim obj As Outlook.MailItem
Dim i As Integer
Set mpfInbox = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderInbox).Folders("Test")
' Loop all items in the Inbox\Test Folder
For i = 1 To mpfInbox.Items.Count
If mpfInbox.Items(i).Class = olMail Then
Set obj = mpfInbox.Items.Item(i)
If obj.SenderEmailAddress = "someone#example.com" Then
'Set the yellow flag icon
obj.FlagIcon = olYellowFlagIcon
obj.Save
End If
End If
Next
End Sub
However, iterating over all items in the folder is not really a good idea. Use the Find/FindNext or Restrict methods of the Items class. 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
Also you may use the AdvancedSearch method of the Application class helpful. See Advanced search in Outlook programmatically: C#, VB.NET for more information.
Use the Store.GetDefaultFolder method instead. It returns a Folder object that represents the default folder in the store and that is of the type specified by the FolderType argument. 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.

How to access an Outlook folder from an Excel macro

I have VBA code in Excel to select the main Outlook inbox. I would like to select any folder or subfolder in that inbox.
For example, I would like to select the subfolder ALD in this screenshot of my main inbox:
I have another email address in Outlook with folders and subfolders. I would like to select any folder or subfolder of this other email address. For example, I have another email address called xxxx#yyyy.com and a folder aaaa and inside a subfolder bbbb. How would I select the subfolder bbbb?
Sub OpenOutlookFolder()
Dim xOutlookApp As Outlook.Application
Dim xNameSpace As Outlook.Namespace
Dim xFolder As Outlook.Folder
Dim xFolderType As OlDefaultFolders
On Error Resume Next
Set xOutlookApp = New Outlook.Application
Set xNameSpace = xOutlookApp.Session
Set xFolder = xNameSpace.GetDefaultFolder(olFolderInbox
xFolder.Display
Set xFolder = Nothing
Set xNameSpace = Nothing
Set xOutlookApp = Nothing
Exit Sub
End Sub
Something along the lines of:
Dim ThisNamespace As Outlook.NameSpace: Set ThisNamespace = Application.GetNamespace("MAPI")
Dim Inbox As Outlook.MAPIFolder: Set Inbox = ThisNamespace.GetDefaultFolder(olFolderInbox)
Dim BaseFolder As Outlook.MAPIFolder: Set BaseFolder = Inbox '.Folders("SubFolder1\SubFolder2...")
For direct subfolder access, uncomment within the last line and update the path
If you want to create a folder structure which is searchable/editable then my answer in this question may be of interest: How can one iterate through the subfolders of a subfolder of a shared mail inbox folder?
Finally by checking again the link Get reference to additional Inbox, I managed to modify my macro in order it works and does as I want. Please find the code below:
Sub OpenOutlookFolderworks()
Dim xOutlookApp As Outlook.Application
Dim xNameSpace As Outlook.Namespace
Dim xFolder As Outlook.Folder
Dim vRecipient As Outlook.MAPIFolder
Dim xFolderType As OlDefaultFolders
On Error Resume Next
Set xOutlookApp = New Outlook.Application
Set xNameSpace = xOutlookApp.Session
Set xFolder = xNameSpace.GetDefaultFolder(olFolderInbox)
Set xFolder = xFolder.Folders("payment office")
Set xFolder = xFolder.Folders("JIRA")
xFolder.display
Set xFolder = Nothing
Set xNameSpace = Nothing
Exit Sub
End Sub

Set reference to Outlook 365 folder in Excel VBA

My company is transferring from Outlook 16 to Outlook 365, and the Excel VBA script below now needs to refer to a mailbox in Outlook 365.
It errors on the line
Set oMapi = oApp.GetNamespace("MAPI").Folders(strMail).Folders("inbox")
with the error
The attempted operation failed. An object could not be found.
Is it possible the mailbox needs to be added in a different way? Or is there a different way to do this function in Outlook 365?
I am not seeing much on a different way to do this with Outlook 365.
Sub Import_Email_Preferences()
Const strMail As String = "borrowerservicesshiftbid#glhec.org"
Dim oApp As Outlook.Application
Dim oMapi As Outlook.MAPIFolder
Dim oMail As Outlook.MailItem
Dim strEmailAddress As String
Dim strSenderName As String
Dim strSubject As String
Dim intRow As Integer
Dim i As Long
Dim tbl As ListObject
Dim ltblRow As Long
Set tbl = ThisWorkbook.Worksheets("Preferences").ListObjects(1)
ltblRow = tbl.DataBodyRange.Rows.Count
On Error Resume Next
Set oApp = GetObject(, "OUTLOOK.APPLICATION")
If (oApp Is Nothing) Then Set oApp = CreateObject("OUTLOOK.APPLICATION")
On Error GoTo 0
'Getting Error Here
Set oMapi = oApp.GetNamespace("MAPI").Folders(strMail).Folders("inbox")
For i = oMapi.Items.Count To 1 Step -1
Set oMail = oMapi.Items(i)
If TypeOf oMail Is Outlook.MailItem Then
MsgBox = "Blue"
End If
Next i
Set oApp = Nothing
Set oMapi = Nothing
Set oMail = Nothing
Set oHTML = Nothing
Set oElColl = Nothing
End Sub
Please try to reference the inbox by GetDefaultFolder:
On Error Resume Next
If oApp Is Nothing Then
Set oApp = GetObject(, "Outlook.Application")
If oApp Is Nothing Then
Set oApp = New Outlook.Application
End If
End If
On Error GoTo 0
Set oMapi = oApp.GetNamespace("MAPI").GetDefaultFolder(olFolderInbox)
If the default folder ist not accessible, be aware that folder names are language dependent, e. g. Namespace.Folders("Posteingang") in German.
The trouble with Set oMapi = oApp.GetNamespace("MAPI").Folders(strMail).Folders("inbox") is you are stringing references together. This is fine if it works but you do not know what has failed if it does not.
Set oMapi = oApp.GetNamespace("MAPI") will fail if oApp is not an object.
Set oMapi = oApp.GetNamespace("MAPI").Folders(strMail) will fail if oApp.GetNamespace("MAPI") is not an object.
Set oMapi = oApp.GetNamespace("MAPI").Folders(strMail).Folders("inbox") will fail if oApp.GetNamespace("MAPI").Folders(strMail) is not an object.
I suggest trying the subroutine below to identify which step is failing. This subroutine does everything in single steps. It also tries different ways of achieving the same effect. If one Set fails, comment it out and see if the next one works.
I have suggested some possible causes of failures but I am sure there are other possibilities. Once you know the step that fails, come back if you need further help.
You may wish to try Asger suggestion of GetDefaultFolder as well. It does not work on my system because the default Inbox in not used. I have to name the store containing the Inbox I wish to access.
Sub TestGetInbox()
Dim olApp As Outlook.Application
Dim olInbox1 As Outlook.MAPIFolder
Dim olInbox2 As Outlook.Folder
Dim olInbox3 As Outlook.MAPIFolder
Dim olInbox4 As Outlook.Folder
Dim olNs As Outlook.Namespace
Dim olSession As Outlook.Namespace
Dim olStore1 As Outlook.Folder
Dim olStore2 As Outlook.Folder
' If execution stops her, you have a problem accessing Outlook
Set olApp = CreateObject("Outlook.Application")
' If execution stops here, you have a problem accessing Outlook's namespace
' using this method. Comment out statements down to "Set olSession = olApp.Session"
Set olNs = olApp.GetNamespace("MAPI")
' If execution stops here, look at your folder pane. Is "borrowerservicesshiftbid#glhec.org"
' the name of a store? Case does not seem to matter but a single letter change in the name
' does.
Set olStore1 = olNs.Folders("borrowerservicesshiftbid#glhec.org")
Debug.Print olStore1.Name
Set olInbox1 = olStore1.Folders("Inbox")
Debug.Print olInbox1.Name
Set olInbox2 = olStore1.Folders("Inbox")
Debug.Print olInbox1.Name
' If execution stops her, you have a problem accessing Outlook's namespace
' This is a different methods of accessing Outlook's namespace. The documentation
' says the two method are identical but I once had the olApp.Namespace("MAPI")
' fail so I now always use the olApp.Session method which has never failed for me.
Set olSession = olApp.Session
Set olStore2 = olSession.Folders("borrowerservicesshiftbid#glhec.org")
Debug.Print olStore2.Name
Set olInbox3 = olStore1.Folders("Inbox")
Debug.Print olInbox1.Name
Set olInbox4 = olStore1.Folders("Inbox")
Debug.Print olInbox1.Name
Set olInbox1 = Nothing
Set olInbox2 = Nothing
Set olStore1 = Nothing
Set olNs = Nothing
Set olInbox3 = Nothing
Set olInbox4 = Nothing
Set olStore2 = Nothing
Set olSession = Nothing
Set olApp = Nothing
End Sub

Excel vba code to read outlook email from inbox from bottom

With the help of below coding I am able to retrieve the data from outlook inbox and update the same in excel.
The problem is that I am not able to update the latest response as macro read first come first update basis. If I get the response from abc yesterday and updated response from abc today, the macro is updating the yesterday's response. How can we change the code so that macro should read the emails from bottom of folder and the data that is pulled is updated.
In short, I want to update the latest response in my records.
Dim outlookApp As Outlook.Application, oOutlook As Object
Dim oInbox As Outlook.Folder, oMail As Outlook.MailItem
Dim strAddress As String, strEntryId As String, getSmtpMailAddress As String
Dim objAddressentry As Outlook.AddressEntry, objExchangeUser As Outlook.ExchangeUser
Dim objReply As Outlook.MailItem, objRecipient As Outlook.Recipient
Set outlookApp = New Outlook.Application
Set oOutlook = outlookApp.GetNamespace("MAPI")
Set oInbox = oOutlook.GetDefaultFolder(olFolderInbox)
For Each oMail In oInbox.Items
If oMail.SenderEmailType = "SMTP" Then
strAddress = oMail.SenderEmailAddress
Else
Set objReply = oMail.Reply()
Set objRecipient = objReply.Recipients.Item(1)
strEntryId = objRecipient.EntryID
objReply.Close OlInspectorClose.olDiscard
strEntryId = objRecipient.EntryID
Set objAddressentry = oOutlook.GetAddressEntryFromID(strEntryId)
Set objExchangeUser = objAddressentry.GetExchangeUser()
strAddress = objExchangeUser.PrimarySmtpAddress()
End If
getSmtpMailAddress = strAddress
body = oMail.body
Loop backwards:
For i = oInbox.Count To 1 Step -1
If TypeName(oInbox.item(i)) = "MailItem" Then
Set oMail = oInbox.item(i)
'Do stuff here
Set oMail = Nothing
End If
Next i

Resources