I'm getting this error:
only valid in object module
when I'm trying to run the script below on VBA outlook 2016.
Private WithEvents myItem As outlook.MailItem
Private Sub myItem_AttachmentRead(ByVal myAttachment As Outlook.Attachment)
If myAttachment.Type = olByValue Then
MsgBox "If you change this file, also save your changes to the original file."
End If
End Sub
Public Sub TestAttachRead()
Dim atts As Outlook.Attachments
Dim myAttachment As Outlook.Attachment
Set myItem = Application.ActiveExplorer.CurrentFolder.Items("Test")
Set atts = myItem.Attachments
myItem.Display
End Sub
The following vba code Must be under ThisOutlookSession module
Private WithEvents myItem As outlook.MailItem
Private Sub myItem_AttachmentRead(ByVal myAttachment As Outlook.Attachment)
If myAttachment.Type = olByValue Then
MsgBox "If you change this file, also save your changes to the original file."
End If
End Sub
And the following vba code could be on regular module
Public Sub TestAttachRead()
Dim atts As Outlook.Attachments
Dim myAttachment As Outlook.Attachment
Set myItem = Application.ActiveExplorer.CurrentFolder.Items("Test")
Set atts = myItem.Attachments
myItem.Display
End Sub
I'm presuming this code is currently on a standard VBA module. You cannot have an WithEvents variable on such modules. It must be either a class module or a document module (e.g. one of Outlook's code-behind for instance) in order to receive events from that mail item.
Related
I'm trying to move the received new mails in shared inbox excluding the (Re: and FWD:) to "In progress folder". When I execute it's not working.
Error popping up in this line olReply.Move fldr
Option Explicit ' Consider this mandatory
' Tools | Options | Editor tab
' Require Variable Declaration
' If desperate declare as Variant
Public WithEvents olItems As Items
Private Sub Application_Startup()
Set olItems = Session.Folders("xxx#xxx.com").Folders("Inbox").Items
End Sub
Private Sub olItems_ItemAdd(ByVal Item As Object)
Dim olReply As MailItem
Dim fldr As Outlook.MAPIFolder
If Item.Class = olMail Then
If Len(Item.ConversationIndex) > 44 Then
Exit Sub
Else
Set fldr = Outlook.Session.Folders("xxx#xxx.com").Folders("In Progress")
olReply.Move fldr
End If
End If
End Sub
I Figured out the code myself and it works perfectly. The below-mentioned code reads through the new mails which hits the shared mailbox and move to another folder if it is a new mail and skips Conversation mails.
Option Explicit ' Consider this mandatory
' Tools | Options | Editor tab
' Require Variable Declaration
' If desperate declare as Variant
Public WithEvents olItems As Items
Private Sub Application_Startup()
Set olItems = Session.Folders("xxxxx#xxxx.com").Folders("Inbox").Items
End Sub
Private Sub olItems_ItemAdd(ByVal Item As Object)
Dim olNameSpace As NameSpace
Set olNameSpace = GetNamespace("MAPI")
Dim olReply As MailItem
Dim olObj As Object
Dim olDestFolder As Folder
If Item.Class = olMail Then
If Len(Item.ConversationIndex) > 44 Then ' Checks if the mail has conversation
Exit Sub
Else
Set olDestFolder = olNameSpace.Folders("xxx#xx.com").Folders("In Progress")'Set destination folder
Item.Move olDestFolder ' move to InProgress folder
End If
End If
End Sub
I have two sets of code. The first code adds a preset BCC address triggered by a button. The second code enables filing of emails, by tagging/categorizing the sent email, copying that sent email and then moving the copy to the folder indicated in pickfolder.
The two codes work separately.
When I paste both codes in ThisOutlookSession, the second one does not work. The error is (loosely translated from Dutch): "compilation error: invalid characteristics in Sub or Function" which relates to all three declarations (Dim WithEvents objInspectors As Inspectors, Dim WithEvents objMyNewMail As MailItem, Dim WithEvents colSentItems As Items)
The full codes:
'button bcc to crm system emailaddress)
Sub AddCRMtoBCC()
Dim objRecip As Recipient
Set oMsg = Application.ActiveInspector.CurrentItem
With oMsg
Set objRecip = oMsg.Recipients.Add("__#__.com")
objRecip.Type = olBCC
objRecip.Resolve
End With
Set oMsg = Nothing
End Sub
'________
'file emails
Dim WithEvents objInspectors As Inspectors
Dim WithEvents objMyNewMail As MailItem
Dim WithEvents colSentItems As Items
Private Sub Application_Startup()
Set objInspectors = Application.Inspectors
Dim NS As Outlook.NameSpace
Set NS = Application.GetNamespace("MAPI")
Set colSentItems = NS.GetDefaultFolder(olFolderSentMail).Items
Set NS = Nothing
End Sub
Private Sub Application_Quit()
Set objInspectors = Nothing
Set objMyNewMail = Nothing
End Sub
Private Sub objInspectors_NewInspector(ByVal Inspector As Inspector)
If Inspector.CurrentItem.Class <> olMail Then Exit Sub
Set objMyNewMail = Inspector.CurrentItem
End Sub
Private Sub objMyNewMail_Send(Cancel As Boolean)
If MsgBox("Are you sure you want to send this message?", vbYesNo + vbQuestion _
, "SEND CONFIRMATION") = vbNo Then
Cancel = True
End If
End Sub
Private Sub colSentItems_ItemAdd(ByVal Item As Object)
If Item.Class = olMail Then
Set Copy = Item.Copy
Set objNS = Application.GetNamespace("MAPI")
Set objFolder = objNS.PickFolder
Copy.Move objFolder
End If
End Sub
When you declare global variables at module level (ThisOutlookSession is a module), all of them should be declared at the top of the module.
thus, move those 3 lines at the top , before the very first sub()
Dim WithEvents objInspectors As Inspectors
Dim WithEvents objMyNewMail As MailItem
Dim WithEvents colSentItems As Items
objMyNewMail_Send() Cancel parameter must be declared ByRef
whenever a new mail arrives in a public folder, I would like a MsgBox to pop up. I solved this for my own inbox using this code:
Private Sub Application_NewMail()
Dim oNS As NameSpace
Dim oFolder As MAPIFolder
Dim oNewMail As MailItem
Set oNS = Application.GetNamespace("MAPI")
Set oFolder = oNS.GetDefaultFolder(olFolderInbox)
Set oNewMail = oFolder.Items.GetFirst
MsgBox oNewMail.subject
End Sub
I also managed to access and retrieve the latest email from the public folder by replacing:
Set oFolder = oNS.GetDefaultFolder(olFolderInbox)
by
Set oFolder = oNS.Folders(2).Folders(2).Folders("XX").Folders("XX")
Howver, this obviously only works, when I manually evalute the code since the code is only executed when a new mail arrives in my inbox. I did some googling and found a potential solution to monitor a public folder:
Private WithEvents TestMail As Items
Public Sub Application_Startup()
Set TestMail = Application.GetNamespace("MAPI").Folders(2).Folders(2).Folders("XX").Folders("XX").Items
End Sub
Private Sub TestMail_ItemAdd(ByVal Item As Object)
MsgBox ("new mails arrived")
End Sub
Edit - The error when compiling: Unknown attribute in sub or function. I am using Outlook 2010 professional.
Try to use the following code:
Private WithEvents NewMail As Items
Public Sub Application_Startup()
Set NewMail = Application.GetNamespace("MAPI").Folders(2).Folders(2).Folders("XX").Folders("XX").Items
End Sub
Private Sub NewMail_ItemAdd(ByVal Item As Object)
MsgBox ("new mails arrived")
End Sub
However, I'd recommend breaking the long chain of calls:
Set NewMail = Application.GetNamespace("MAPI").Folders(2).Folders(2).Folders("XX").Folders("XX").Items
and declare each property or method call on a separate line of code. Thus, you will find the exact ptoperty or method call which generates the error.
You may find the How to get reference to Public Folder Store using Outlook Object Model for Outlook 2010? article helpful.
How do I show a MsgBox or alert upon receiving a message with a specified subject or sender?
I put this procedure in ThisOutlookSession block.
Private Sub olInboxItems_ItemAdd(ByVal Item As Object)
Dim myMail As MailItem
Dim name As String
If TypeOf Item Is MailItem Then
Set myMail = Item
If myMail.Subject Like "*Hello world*" And myMail.Categories = "" Then
MsgBox "Message", vbInformation, "approved"
MailDate = myMail.ReceivedTime
myMail.Categories = "CZEART"
myMail.MarkAsTask (olMarkNoDate)
myMail.Save
End If
End If
End Sub
To test the code, open a mailitem with the required conditions then step through this.
Option Explicit
Private Sub test()
Dim currItem As MailItem
Set currItem = ActiveInspector.currentItem
olInboxItems_ItemAdd currItem
End Sub
Likely though you need this in the ThisOutlookSession module.
Option Explicit
Private WithEvents olInboxItems As Items
Private Sub Application_Startup()
Dim objNS As NameSpace
Set objNS = Application.Session
' instantiate objects declared WithEvents
Set olInboxItems = objNS.GetDefaultFolder(olFolderInbox).Items
Set objNS = Nothing
End Sub
http://www.outlookcode.com/article.aspx?id=62
I have an Outlook macro I wrote that will automatically mark items as read when I move them to a folder. (I hate having unread messages in folders other than my Inbox.) I wrote the macro in Outlook 2010, and it's been functioning well for years.
I recently upgraded to Office 2013, and now my macro doesn't work--I'm getting a type mismatch error on this line (see below for the full code):
Set oMoveHandler.Callback = Me
oMoveHandler.Callback expects an object of type IMessageMoved, which the object implements, so I'm not sure why I'm getting this error. Any ideas?
ThisOutlookSession code:
Option Explicit
Implements IMessageMoved
Private m_oFolderCollection As Collection
Private Sub Application_Quit()
Set m_oFolderCollection = Nothing
End Sub
Private Sub Application_Startup()
Dim oFolder As Outlook.Folder
Set m_oFolderCollection = New Collection
For Each oFolder In Application.GetNamespace("MAPI").Folders
Call AddFolder(oFolder)
Next oFolder
End Sub
Private Sub AddFolder(Folder As Outlook.Folder)
Dim oFolder As Outlook.Folder
Dim oMoveHandler As MoveHandler
If Folder Is Nothing Then
Exit Sub
End If
If Folder.Folders.Count = 0 Then
Exit Sub
End If
For Each oFolder In Folder.Folders
If oFolder.DefaultItemType = olMailItem Then
If oFolder.Name <> "Inbox" And oFolder.Name <> "Outbox" And oFolder.Name <> "ePrescribing Workgroup" Then
Set oMoveHandler = New MoveHandler
Set oMoveHandler.Folder = oFolder.Items
Set oMoveHandler.Callback = Me
Call m_oFolderCollection.Add(oMoveHandler)
Set oMoveHandler = Nothing
End If
Call AddFolder(oFolder)
End If
Next oFolder
End Sub
Private Function IMessageMoved_MessageMoved(Item As Object) As Variant
On Error Resume Next
Item.UnRead = False
On Error GoTo 0
End Function
IMessageMoved:
Public Function MessageMoved(Item As Object)
End Function
MoveHandler:
Private WithEvents m_oFolder As Outlook.Items
Private m_oCallback As IMessageMoved
Public Property Set Folder(Folder As Outlook.Items)
Set m_oFolder = Folder
End Property
Public Property Get Folder() As Outlook.Items
Set Folder = m_oFolder
End Property
Public Property Set Callback(Object As IMessageMoved)
Set m_oCallback = Object
End Property
Private Sub Class_Terminate()
Set m_oFolder = Nothing
Set m_oCallback = Nothing
End Sub
Private Sub m_oFolder_ItemAdd(ByVal Item As Object)
If Not m_oCallback Is Nothing Then
Call m_oCallback.MessageMoved(Item)
End If
End Sub
I suspect I was actually running into a similar issue to the one described in this post describing a similar problem in Excel where binding just wasn't working as expected. To work around it, I ended up moving my interface out of ThisOutlookSession into a separate class which I then just instantiate from ThisOutlookSession.