How to run a macro that requires an argument "myitem As Outlook.mailItem"? - vba

I have this:
Public Sub MoveMails (myitem As Outlook.mailItem)
...
End Sub
Runs automatically from a rule when I receive a new email.
I want launch this when I want. I tried with Call MoveMails but I don't know the argument for myitem As Outlook.mailItem.
I receive several mails. My idea is to move all. I have several conditions: filter by subject, body... and I move them to different folders.

Now that I know you wish to run this on multiple items at once.
Remove the parameter (myitem As Outlook.MailItem) from the sub to run on all items in the folder, or in a selection.
Copied from the code you posted (I've changed the formatting a bit too);
Public Sub Corrected()
'==========================================
'Declare variables:
Dim myNameSpace As Outlook.NameSpace
Dim myInbox As Outlook.Folder
Dim myDestFolder As Outlook.Folder
'Set variables:
Set myNameSpace = Application.GetNamespace("MAPI")
Set myInbox = myNameSpace.GetDefaultFolder(olFolderInbox)
Set myDestFolder = myInbox.Folders("CHECK")
'===========================================
'Declare the variable MyItem but don't set it:
Dim MyItem As Outlook.MailItem
'Create a loop for all items in a certain folder:
For Each MyItem In myInbox 'Or for a subfolder use '...In MyInbox.Folders("FolderName")'
'Or to check selected items you could use the below:
'For Each MyItem in Application.ActiveExplorer.Selection
'if body contains alarm then move
If InStr(MyItem.Body, "alarm") > 0 Then
MyItem.Move myDestFolder
End If
'if subject contains Urgent move
If InStr(MyItem.Subject, "Urgent") > 0 Then
MyItem.Move myDestFolder
End If
'if body contains MASTER then categorize
If InStr(MyItem.Body, "MASTER") > 0 Then
MyItem.Categories = "Boss"
MyItem.Save
End If
Next MyItem 'This loops onto the next item in the selection or folder,
'so it checks them all automatically.
End Sub

I found a sub for selecting the current item here - it has options for whether the item is open in it's own window (inspector) or in the main Outlook window (explorer).
I recommend you add the custom function GetCurrentItem() from that page to your module and use that as your myitem parameter.
So to call the MoveMails sub Call Movemails(GetCurrentItem()).
Function GetCurrentItem() As Object
Dim objApp As Outlook.Application
Set objApp = Application
On Error Resume Next
Select Case TypeName(objApp.ActiveWindow)
Case "Explorer"
Set GetCurrentItem = objApp.ActiveExplorer.Selection.Item(1)
Case "Inspector"
Set GetCurrentItem = objApp.ActiveInspector.CurrentItem
End Select
Set objApp = Nothing
End Function

Related

Getting an EntryID after an object is moved

Summary
I'm trying to add hyperlinks to tasks created from emails that I have moved to another folder.
The goal is to have the task contain a hyperlink to the Outlook item that was moved to a "Processed Email" folder".
Problem
I don't understand how to move a MailItem and then get its new EntryID after it moves.
The "naive" way doesn't work. After using the Move method to move a MailItem object, the EntryID property does not reflect a change in ID.
Details
Creating a hyperlink to an Outlook item using the format outlook:<EntryID> is easy enough if the Outlook item remains in the Inbox, since I can just get the EntryID of the object that I am linking to. However, Outlook changes the EntryID when an object is moved.
I want to understand how to get the updated ID so that I can construct an accurate link.
Example
The message boxes show the EntryID property of objMail returns the same value despite the fact that the object has moved. However, running a separate macro on the mail in the destination folder confirms that the EntryID has changed with the move.
Sub MoveObject(objItem As Object)
Select Case objItem.Class
Case olMail
Dim objMail As MailItem
Set objMail = objItem
MsgBox (objMail.EntryID)
Dim inBox As Outlook.MAPIFolder
Set inBox = Application.ActiveExplorer().Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox)
Dim destFolder As Outlook.MAPIFolder
Set destFolder = inBox.Folders("Processed Email")
If (Application.ActiveExplorer().CurrentFolder.Name <> destFolder.Name) Then
objMail.Move destFolder
End If
MsgBox (objMail.EntryID)
End Select
End Sub
The Move method of the MailItem class returns an object that represents the item which has been moved to the designated folder. You need to check out the EntryID value of the returned object, not the source one.
Anyway, you may consider handling the ItemAdd event of the target folder to make sure that an updated entry ID value is used all the time.
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
Set myNameSpace = Application.GetNamespace("MAPI")
Set myInbox = myNameSpace.GetDefaultFolder(olFolderInbox)
Set myItems = myInbox.Items
Set myDestFolder = myInbox.Folders("Personal Mail")
Set myItem = myItems.Find("[SenderName] = 'Eugene Astafiev'")
While TypeName(myItem) <> "Nothing"
myItem.Move myDestFolder
Set myItem = myItems.FindNext
Wend
End Sub
Hello can you please elaborate your answer I am not able to understand it.
Anyway, you may consider handling the ItemAdd event of the target folder to make sure that an updated entry ID value is used all the time.
Here is my code and I need EntryID after moving.
Sub Movetest1()
Dim olApp As Outlook.Application
Dim olns As Outlook.NameSpace
Dim Fld As Folder
Dim ofSubO As Outlook.MAPIFolder
Dim myDestFolder As Outlook.Folder
Dim ofolders As Outlook.Folders
Dim objItems As Outlook.Items
Dim myRestrictItems As Outlook.Items
Dim i As Long
Dim myitem As Object
' Dim MailItem As Microsoft.Office.Interop.Outlook.MailItem
Dim MailItem, moveditem As Outlook.MailItem
Dim eid As String
Dim sid As Variant
Dim newEID As String
'---------------------------------------------------------------------------------------------------------
Set olApp = New Outlook.Application
Set olns = olApp.GetNamespace("MAPI")
For Each Fld In olns.Folders
If Fld.Name = "GSS Payables" Then
'
' MsgBox Fld.Name
' Debug.Print " - "; Fld.EntryID
Set Fld = olns.GetFolderFromID("000000009DA6D76FBE7A58489450CDF6094F592A0100A2457DC435B22448A832DB721D8185B1000000B6207D0000").Folders("Inbox")
Exit For
End If
Next
Set objItems = Fld.Items
eid = "000000009DA6D76FBE7A58489450CDF6094F592A0700A2457DC435B22448A832DB721D8185B1000000B620800000A2457DC435B22448A832DB721D8185B100007FF773270000"
sid = "000000009DA6D76FBE7A58489450CDF6094F592A0100A2457DC435B22448A832DB721D8185B1000000B6207D0000"
Set myDestFolder = Fld.Folders("Bhagyashri")
'Set myitem = objItems.Find("[SenderName]='Microsoft Outlook '")
Set MailItem = olns.GetItemFromID(eid)
Set moveditem = MailItem.Move(myDestFolder)
"giving error here
newID = moveditem.entryid
Debug.Print "newID -"; newID
' get mailitem.parent.storeid
MsgBox "done"
End
Use the following syntax:
Dim MoveToFolder As outlook.MAPIFolder
Dim MyItem As outlook.MailItem
Dim NewEntryID As String
NewEntryID = MyItem.Move(MoveToFolder).ENTRYID
After MyItem.Move is executed the new ENTRYID will be returned to the NewEntryID variable.

Outlook VBA - Move to folder - Body text

I tried to create a script which searches the body text and sender name from an incoming email and if true move the email to a subfolder.
I tried to add this code to ThisOutlookSession but it is not working.
Public Sub MailtoFolder(Item As Outlook.MailItem)
Dim myNameSpace As Outlook.NameSpace
Dim myInbox As Outlook.MAPIFolder
Dim myDestFolder As Outlook.MAPIFolder
Set myNameSpace = Application.GetNamespace("MAPI")
Set myInbox = myNameSpace.GetDefaultFolder(olFolderInbox)
Set myDestFolder = myInbox.Folders("xTest")
If InStr(Item.Body, "Test123") > 0 And Item.SenderName = "Jon" Then
Item.Move myDestFolder
End If
Set myDestFolder = Nothing
Set myInbox = Nothing
Set myNameSpace = Nothing
End Sub
Any ideas where I made a fault?
Your "Item" so far is not set.
If you wish to apply this to the currently opened e-mail, this would be e.g.
Set Item=Application.ActiveExplorer.Selection.Item(1)
If you wish to loop through all mails in your folder, you need to do exactly that:
Set myDestFolder = myInbox.Folders("xTest")
For Each mailItem in myDestFolder.Items
' ... do your magic
Next mailItem

Move selected items to folder

I am using the below function to move selected emails to another folder.
The error says "An object could not be found."
It works the first time, but any subsequent attempts fail on the line:
Set TestFolder = SubFolders.Item(FoldersArray(i))
When the following line executes, when I expand folders in the watch window, no subfolders appear:
Set TestFolder = Application.Session.Folders.Item(FoldersArray(0))
I am calling the function from a sub:
Option Explicit
Private Item As Object, olkItem As Object
Private AutoReply As String
Private myDestFolder As Outlook.Folder, myInbox As Outlook.Folder
Private myNameSpace As Outlook.NameSpace
Sub ReplywithNote2()
Set myNameSpace = Application.GetNamespace("MAPI")
Set myInbox = myNameSpace.GetDefaultFolder(olFolderInbox)
Set myDestFolder = GetFolder("\\PO_Queries\Inbox\Completed")
For Each olkItem In Application.ActiveExplorer.Selection
With olkItem
If .Class = olMail Then
'.Move myDestFolder
End If
End With
Next
End Sub
Function:
Function GetFolder(ByVal FolderPath As String) As Outlook.Folder
Set GetFolder = Nothing
Dim TestFolder As Outlook.Folder
Dim FoldersArray As Variant
Dim i As Integer
'On Error GoTo GetFolder_Error
If Left(FolderPath, 2) = "\\" Then
FolderPath = Right(FolderPath, Len(FolderPath) - 2)
End If
'Convert folderpath to array
FoldersArray = Split(FolderPath, "\")
Set TestFolder = Application.Session.Folders.Item(FoldersArray(0))
If Not TestFolder Is Nothing Then
For i = 1 To UBound(FoldersArray, 1)
Dim SubFolders As Outlook.Folders
Set SubFolders = TestFolder.Folders
Set TestFolder = SubFolders.Item(FoldersArray(i))
If TestFolder Is Nothing Then
Set GetFolder = Nothing
End If
Next
End If
'Return the TestFolder
Set GetFolder = TestFolder
On Error GoTo 0
Exit Function
GetFolder_Error:
Set GetFolder = Nothing
Exit Function
End Function
When I restart Outlook it works. I tried setting several variables to Nothing, executing 'End' in the hope of resetting the relevant variable. What is reset when I restart Outlook?
Edit - I've narrowed it down to the move line. The problem occurs when running the sub after having moved the item.
For Each does not work correctly when moving or deleting.
You either process item one until there are no items left or loop backwards.
For i = Application.ActiveExplorer.Selection.Count to 1 step -1
https://msdn.microsoft.com/en-us/library/office/ff863343%28v=office.15%29.aspx
"To delete all items in the Items collection of a folder, you must delete each item starting with the last item in the folder. For example, in the items collection of a folder, AllItems, if there are n number of items in the folder, start deleting the item at AllItems.Item(n), decrementing the index each time until you delete AllItems.Item(1)."
Edit: 2015 06 16
Unless there is a reason for using GetFolder try this:
Set myDestFolder = myNameSpace.Folders("PO_Queries").Folders("Inbox").Folders("Completed")
Many thanks to niton, I amended my sub to the following, which works:
Sub ReplywithNote2()
Set myNameSpace = Application.GetNamespace("MAPI")
Set myInbox = myNameSpace.GetDefaultFolder(olFolderInbox)
Set myDestFolder = GetFolder("\\PO_Queries\Inbox\Completed")
For i = Application.ActiveExplorer.Selection.Count To 1 Step -1
With Application.ActiveExplorer.Selection.Item(i)
If .Class = olMail Then
.Move myDestFolder
End If
End With
Next
End Sub
The issue still occurs if I move the email back into the original folder manually and try again, but I can live with that!
Thanks again, most grateful.
Sub myMove()
Set myNameSpace = Application.GetNamespace("MAPI")
Set myInbox = myNameSpace.GetDefaultFolder(olFolderInbox)
Set myDestFolder = GetFolder("\\xxx\folder1\folder2\folder3")
Dim i As Long
For Each olkItem In Application.ActiveExplorer.Selection
i = MsgBox("Do you want to move selected emails to folder folder3?", vbYesNo + vbQuestion + vbSystemModal + vbMsgBoxSetForeground, "Confirm Move")
If i = vbNo Then
Cancel = True
End
Else
'Continue moving message
For i = Application.ActiveExplorer.Selection.Count To 1 Step -1
With Application.ActiveExplorer.Selection.Item(i)
If .Class = olMail Then
.Move myDestFolder
End If
End With
Next
End
End If
Next
End:
End Sub

Get email from non default inbox?

I am using the following vba code to get emails from my inbox folder and move them to a sub folder called suppliers. At the moment the emails are moved from my default email inbox, but I have an account called purcashing#hewden.co.uk and I want it to get the emails from this inbox and move it to the subfolder called Suppliers in this account.
can someone show me how I would alter GetDefaultFolder to make this happen. thanks
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
Set myNameSpace = Application.GetNamespace("MAPI")
Set myInbox = myNameSpace.GetDefaultFolder(olFolderInbox)
Set myItems = myInbox.Items
Set myDestFolder = myInbox.Folders("Supplier")
Set myItem = myItems.Find("[Subject] = 'Introduction'")
While TypeName(myItem) <> "Nothing"
myItem.Move myDestFolder
Set myItem = myItems.FindNext
Wend
End Sub
Instead of using Namespace.GetDefaultFolder, retrieve the appropriate store from the Namespace.Stores collection and use Store.GetDefaultFolder.
I just used Dmitry's suggestion and it works like a charm.
Hope it helps \o/
Sub GetEmailFromNonDefaultInbox()
Dim myOlApp As New Outlook.Application
Dim myNameSpace As Outlook.Namespace
Dim myInbox As Outlook.MAPIFolder
Dim myitems As Outlook.Items
Dim strFilter As String
' let the user choose which account to use
Set myAccounts = myOlApp.GetNamespace("MAPI").Stores
For i = 1 To myAccounts.count
res = MsgBox(myAccounts.Item(i).DisplayName & "?", vbYesNo)
If res = vbYes Then
Set myInbox = myAccounts.Item(i).GetDefaultFolder(olFolderInbox)
Exit For
End If
Next
If myInbox Is Nothing Then Exit Sub ' avoid error if no account is chosen
' query emails by subject
strFilter = "#SQL=""urn:schemas:httpmail:subject"" like '%YOUR SUBJECT%'"
Set myitems = myInbox.Items.Restrict(strFilter)
' show some feedback if no email is found
If myitems.count = 0 Then
MsgBox "Nothing found. Try another account."
Exit Sub
End If
' get the most recent email
myitems.Sort "ReceivedTime", True
Set myitem = myitems.GetFirst
If myitem.Class = olMail Then
' and now you can do whatever you want
MsgBox (myitem.Subject)
End If
End Sub

In Outlook, is it possible to run a macro on an email I select manually?

Is it possible to run a macro on an email that I manually select in my inbox. For instance, right click on the email and select "Send to >> Macro >> (show list of subroutines accepting Outlook.MailItem as a parameter)?
I think you will have to add a Button to the mail-ribbon. This Button can call an Routine.
In this Routine you use the active selection:
Sub example()
Dim myOlApp As Outlook.Application
Dim myNameSpace As Outlook.NameSpace
Set myOlApp = CreateObject("Outlook.Application")
Set myNameSpace = myOlApp.GetNamespace("MAPI")
Dim olExplorer As Explorer
Dim olfolder As MAPIFolder
Dim olSelection As Selection
Dim olitem As mailitem
Set olExplorer = Application.ActiveExplorer
Set olfolder = Application.ActiveExplorer.CurrentFolder
If olfolder.DefaultItemType = olMailItem Then
Set olSelection = olExplorer.Selection
end if
For Each olitem In olSelection
'do something
Next olitem
end sub
I hope you get this working...
Max
So, I was able to simplify Max's answer a bit, but he certainly pointed me in the right direction. Below is basically what I'm going with. After selecting an email in my inbox, I should be able to run this macro and proceed to work on it.
Sub example()
Dim x, mailItem As Outlook.mailItem
For Each x In Application.ActiveExplorer.Selection
If TypeName(x) = "MailItem" Then
Set mailItem = x
call fooMail(mailItem)
End If
Next
End Sub
Sub fooMail(ByRef mItem as Outlook.MailItem)
Debug.print mItem.Subject
End Sub