The problem: a user needs to file messages from clients in a specific folder, which is the clients accounts number. Moving the messages manually is time consuming but using a macro makes it easy.
This macro, as written, watches the Inbox and Sent folder and moves all messages containing the client id to a folder of the same name (as written, the client folders are at the same level as the Inbox).

To use a different folder, change this line:
Set Folder = Session.GetDefaultFolder(olFolderInbox).Parent.Folders("Clients")For a path under public folder, use this format:
Set Folder = Session.GetDefaultFolder(olPublicFoldersAllPublicFolders).Folders("Shared Folders").Folders("Clients")If the folder does not exist, the macro won't move the message.
Option Explicit
Private objNS As Outlook.NameSpace
Private WithEvents objItems As Outlook.Items
Private WithEvents objSentItems As Outlook.Items
Dim strCode As String
Dim Code As String
Private m_Folder As Outlook.MAPIFolder
Private m_Find As String
' False is slower but does not lock outlook up
' True is faster but outlook may not respond
Private Const SpeedUp As Boolean = False
Private Sub Application_Startup()
Dim objInboxFolder As Outlook.Folder
Dim objSentFolder As Outlook.Folder
Set objNS = Application.GetNamespace("MAPI")
'Set the folder and items to watch:
Set objInboxFolder = objNS.GetDefaultFolder(olFolderInbox)
Set objItems = objInboxFolder.Items
Set objSentFolder = objNS.GetDefaultFolder(olFolderSentMail)
Set objSentItems = objSentFolder.Items
Set objSentFolder = Nothing
Set objInboxFolder = Nothing
End Sub
Private Sub objItems_ItemAdd(ByVal Item As Object)
If Item.Class = olMail Then
MoveMessages Item
End If
End Sub
Private Sub objSentItems_ItemAdd(ByVal Item As Object)
If Item.Class = olMail Then
MoveMessages Item
End If
End Sub
Public Sub MoveMessages(ByVal Item As MailItem)
Dim strText As String
'' find the code
strText = Item.Subject & vbCrLf & Item.Body
strCode = ExtractText(strText)
If strCode = "" Then
Exit Sub
End If
' if the code is in the message, find the folder
' move message
FindFolder
On Error Resume Next
Item.Move m_Folder
If m_Folder Is Nothing Then
Exit Sub
End If
Err.Clear
End Sub
Function ExtractText(Str As String) ' As String
Dim regEx As New RegExp
Dim NumMatches As MatchCollection
Dim M As Match
'this pattern looks for 6 digits in the subject
With regEx
.Pattern = "(AB[0-9]{6})"
.IgnoreCase = True
.Global = False
End With
Set NumMatches = regEx.Execute(Str)
If NumMatches.Count = 0 Then
ExtractText = ""
Else
Set M = NumMatches(0)
ExtractText = M.SubMatches(0)
End If
Code = ExtractText
End Function
' Borrowing Michael's code from
' http://vboffice.net/en/developers/find-folder-by-name
Public Sub FindFolder()
Dim Name$
Dim Folders As Outlook.Folders
Dim Folder As Outlook.MAPIFolder
Set m_Folder = Nothing
m_Find = ""
Name = "*" & strCode
If Len(Trim$(Name)) = 0 Then Exit Sub
m_Find = Name
m_Find = LCase$(m_Find)
Set Folder = Session.GetDefaultFolder(olFolderInbox).Parent.Folders("Clients")
LoopFolders Folder.Folders
End Sub
Private Sub LoopFolders(Folders As Outlook.Folders)
Dim Folder As Outlook.MAPIFolder
Dim F As Outlook.MAPIFolder
Dim Found As Boolean
If SpeedUp = False Then DoEvents
For Each F In Folders
Found = (LCase$(F.Name) Like m_Find)
If Found Then
Set m_Folder = F
Exit For
Else
LoopFolders F.Folders
If Not m_Folder Is Nothing Then Exit For
End If
Next
End Sub
Moving a copy
Moving a copy is difficult when you are using an ItemAdd macro as any new item added to the folder is processed by the macro and making a copy is a new item. The macro goes into a loop and hangs.
We can use an If statement to look for a value, or compare a field to a value, which we set before making the copy. If the value is set, Outlook will skip it. Comparing the subject to the previous message subject, adding categories, marking the message as read, setting a flag or another value will work.
In the first example, I'm checking the subject to see if it matches the last subject. If so, the message is not processed. The advantage is that the message isn't edited in any way. The disadvantage is that if you receive two messages back to back with the same subject, only the first will be processed.
To use this method, you'll change the ItemAdd macros to check for the subject and add the copy code to the move messages macro.
Private Sub objItems_ItemAdd(ByVal Item As Object)
If Not Not Item.Class = olMail And Item.Subject <> strSubject Then
strSubject = Item.Subject
MoveMessages Item
End If
End Sub
Replace the If block the MoveMessages macro with the following:
If m_Folder Is Nothing Then Exit Sub Else Dim objCopy Set objCopy = Item.Copy Item.Move m_Folder End If
In this example, I'm setting a flag on new messages before creating a copy. In the ItemAdd macro, we check to see if there is a flag set. If not, a flag is set, the message is copied and moved.
While this will work when multiple messages with the same subject arrive in quick succession, both copies will be flagged or tagged.
Private Sub objItems_ItemAdd(ByVal Item As Object)
If Not Not Item.Class = olMail And Not Item.IsMarkedAsTask Then
MoveMessages Item
End If
End Sub
Replace the If block the MoveMessages macro with the following:
Item.MarkAsTask olMarkThisWeek
If m_Folder Is Nothing Then
Exit Sub
Else
Dim objCopy
Set objCopy = Item.Copy
Item.Move m_Folder
End If
How to use the macros on this page
First: You need to have macro security set to the lowest setting, Enable all macros during testing. The macros will not work with the top two options that disable all macros or unsigned macros. You could choose the option Notification for all macros, then accept it each time you restart Outlook, however, because it's somewhat hard to sneak macros into Outlook (unlike in Word and Excel), allowing all macros is safe, especially during the testing phase. You can sign the macro when it is finished and change the macro security to notify.
To check your macro security in Outlook 2010 and newer, go to File, Options, Trust Center and open Trust Center Settings, and change the Macro Settings. In Outlook 2007 and older, look at Tools, Macro Security.
After you test the macro and see that it works, you can either leave macro security set to low or sign the macro.
Macros that run when Outlook starts or automatically need to be in ThisOutlookSession, all other macros should be put in a module, but most will also work if placed in ThisOutlookSession. (It's generally recommended to keep only the automatic macros in ThisOutlookSession and use modules for all other macros.) The instructions are below.
The macros on this page need to go into ThisOutlookSession.
Open the VBA Editor by pressing Alt+F11 on your keyboard.
To put the macro code in ThisOutlookSession:
- Expand Project1 and double click on ThisOutlookSession.
- Copy then paste the macro into ThisOutlookSession. (Click within the code, Select All using Ctrl+A, Ctrl+C to copy, Ctrl+V to paste.)
Set a reference to other Object Libraries
If you receive a "User-defined type not defined" error, you need to set a reference to another object library. For this macro, it is the VBScript Regular Expression library.
- Go to Tools, References menu.
- Locate the object library in the list and add a check mark to it.

More information as well as screenshots are at How to use the VBA Editor

Hi Diane
Im getting a compile error on submatches please see attached pic.
Could you please advise solution. l am using Outlook 2019
I am also getting the same error on the same line when I run a debug. Wondering what I may have done wrong haha. Completely new to VBA