Preventing an Outlook mailitem from entering into a conflict - vba

An outlook mailitem is on a network share, and is prone to conflicts especially when modifications are made to it.
The following VBA macro does the following:
Makes changes to a mailitem
Checks if the mailitem is saved and saves it.
Checks the saved mailitem for any conflicts.
How do I modify this code to prevent the mailitem from entering into a conflict in the first place?
Any ideas a welcome.
Sub CheckConflict()
Dim olApp As Outlook.Application
Dim objMail As Outlook.MailItem
Set olApp = Outlook.Application
Set objMail = olApp.ActiveInspector.CurrentItem
objMail.Subject = "Changing subject and saving mail"
If objMail.Saved = False Then
objMail.Save
End if
If objMail.IsConflict = True Then
Msgbox "Conflict detected!"
End If
Set olApp = Nothing
Set objMail = Nothing
End Sub

Minimize the number of times you call Save and do not keep the MailItem object open for any prolonged periods of time.

Related

Outlook has exhausted all shared resources. Why?

With this bit of VBA code in MS Access I'm getting an error if its executed too often. The only way I've found to clear it is reboot my computer. Any idea why and what can I do?
Public Function HasOutlookAcct(strEmail As String) As Boolean
Dim OutMail As Object
Dim OutApp As OutLook.Application
Dim objNs As OutLook.NameSpace
Dim objAcc As Object
'https://stackoverflow.com/questions/67284852/outlook-vba-select-sender-account-when-new-email-is-created
Set OutApp = CreateObject("Outlook.Application")
Set objNs = OutApp.GetNamespace("MAPI")
For Each objAcc In objNs.Accounts
If objAcc.SmtpAddress = strEmail Then
HasOutlookAcct = True
Exit For
End If
Next
OutApp.Quit
Set objAcc = Nothing
Set objNs = Nothing
End Function
The code looks good. The NameSpace.Accounts property returns an Accounts collection object that represents all the Account objects in the current profile. I don't see any extensive or heavy usage of the Outlook object model, but creating a new Outlook Application instance in the method for checking whether a particular account is configured in Outlook or not is not the best way of using Outlook. Instead, I'd recommend running Outlook once at some point and getting all the configured emails for saving for future usage where necessary.
Also it makes sense to disable all COM add-ins to see whether it helps or not. The problem may be related to any specific COM add-in.
Appears the error is addressed by considering the user.
The assumption, based on my results, is Outlook is not cleaned up completely when the user's instance is closed with outApp.Quit.
When Outlook is open, outApp.Quit is not applied and Outlook remains open at the end.
When Outlook is not open, it is opened in the background and later closed with outApp.Quit.
There is zero or one instance of Outlook at any time.
Option Explicit
Public Function HasOutlookAcct(strEmail As String) As Boolean
'Reference Outlook nn.n Object Library
' Consistent early binding
Dim outApp As Outlook.Application
Dim objNs As Outlook.Namespace
Dim objAcc As Outlook.Account
Dim bCreated As Boolean
On Error Resume Next
Set outApp = GetObject(, "Outlook.Application")
On Error GoTo 0
If outApp Is Nothing Then
bCreated = True
Set outApp = CreateObject("Outlook.Application")
End If
Set objNs = outApp.GetNamespace("MAPI")
For Each objAcc In objNs.Accounts
'Debug.Print objAcc.SmtpAddress
If objAcc.SmtpAddress = strEmail Then
HasOutlookAcct = True
Exit For
End If
'Set objAcc = Nothing ' Additional cleanup if needed
Next
If bCreated = True Then ' Outlook object had to be created
outApp.Quit
End If
'Set outApp = Nothing ' Additional cleanup if needed
Set objNs = Nothing
End Function
Private Sub HasOutlookAcct_Test()
Dim x As Boolean
Dim sEmail As String
sEmail = "someone#somewhere.com"
Dim i As Long
For i = 1 To 50
Debug.Print i & ": " & sEmail
x = HasOutlookAcct(sEmail)
Debug.Print " HasOutlookAcct: " & x
DoEvents
Next
Debug.Print "done"
End Sub

Outlook script that runs when email is received works only when I transfer the new mail to myself

I made a code that would take an incomming email in a specific folder (First a rule is created in order to move the mail to the folder and then the script is launched).
The problem is that the rule is working (it moves the mail to the folder), but the script isn't.
The thing is that when I take the new mail and transfer it to myself (My email is also in the receivers in the rules), the script is correctly working.
Here is the beginning of the code that I believe may be wrong.
Sub Script(item As Outlook.MailItem)
Dim strMailID As String
Dim objMail As Outlook.MailItem
Dim objNamespace As Outlook.NameSpace
strMailID = item.EntryID
Set objNamespace = Application.GetNamespace("MAPI")
Set objMail = objNamespace.GetItemFromID(strMailID)
Dim objpf As MAPIFolder
If objMail.MessageClass = "IPM.Note" Then
Any help would be appreciated
You need add an event listener to the default local Inbox, it worked with Outlook 2016.
This code will add an event listener to the default local Inbox. Action will be placed upon incoming emails. You need to add actions you need in the code below:
Private WithEvents Items As Outlook.Items
Private Sub Application_Startup()
Dim olApp As Outlook.Application
Dim objNS As Outlook.NameSpace
Set olApp = Outlook.Application
Set objNS = olApp.GetNamespace("MAPI")
' default local Inbox
Set Items = objNS.GetDefaultFolder(olFolderInbox).Items
End Sub
Private Sub Items_ItemAdd(ByVal item As Object)
On Error Goto ErrorHandler
Dim Msg As Outlook.MailItem
If TypeName(item) = "MailItem" Then
Set Msg = item
' ******************
' do something here
' ******************
End If
ProgramExit:
Exit Sub
ErrorHandler:
MsgBox Err.Number & " - " & Err.Description
Resume ProgramExit
End Sub
After pasting the code in ThisOutlookSession module, you must restart Outlook.

Outlook vba does not find existing folder

My Outlook macro worked at one time, then stopped. When it parses, the macro throws an error "Compile Error: Variable not defined". It seems the macro does not recognize that that folder exists. I cut the code to the bare minimum and it is a repeatable problem. The macro will recognize standard folders such as JUNK and DRAFTS but not PROCESSED_FOLDERS. I have tried renaming Processed_Folders as well as creating a new folder with a different name. No joy.
Folder structure is:
reports#xxx.com
Inbox
Drafts
Sent
Trash
Junk
Processed_Reports
Outbox
Sync Issues1 (This computer only)
SearchFolders
CODE:
Sub testfforfolder()
Dim olApp As Outlook.Application
Dim objNS As Outlook.NameSpace
Dim olFolder As Outlook.MAPIFolder
Dim msg As Outlook.MailItem
Set olApp = Outlook.Application
Set objNS = olApp.GetNamespace("MAPI")
Set olFolder = objNS.GetDefaultFolder(olFolderInbox)
On Error GoTo xyz
Set olFolder = olFolder.Folders("Processed_Reports")
MsgBox "Folder Exists" ' This line works if I use DRAFTS or JUNK
Exit Sub
xyz:
MsgBox ("Cannot find Folder") ' I get here if I use PROCESSED_REPORTS
Exit Sub
End Sub
Thanks to the comment by Tony Dallimore I was able to solve the issue. The link to https://stackoverflow.com/a/12146315/973283 let me solve the problem. With an updated version of Outlook, the default email account was being referenced rather than the account of the selected item. The Processed_Reports folder only existed in a different account folder. The solution, as Tony suggested, was to set the target folder to the full path to the target. I did need one more level as shown in the working solution below.
Sub testfforfolder()
Dim olApp As Outlook.Application
Dim objNS As Outlook.NameSpace
Dim olFolder As Outlook.MAPIFolder
Dim msg As Outlook.MailItem
Set olApp = Outlook.Application
Set objNS = olApp.GetNamespace("MAPI")
Set olFolder = objNS.GetDefaultFolder(olFolderInbox)
On Error GoTo xyz
'OLD INCORRECT
'Set olFolder = olFolder.Folders("Processed_Reports")
'WORKING CORRECTION
Set TgtFolder= _
Session.Folders("reports#xxx.com"). _
Folders("Inbox").Folders("Processed_Reports")
MsgBox "Folder Exists" ' This line works if I use DRAFTS or JUNK
Exit Sub
xyz:
MsgBox ("Cannot find Folder") ' I get here if I use PROCESSED_REPORTS
Exit Sub
End Sub
here is a way to get the session folder without knowing the session name
Sub topFolder()
Dim topFolder As Folder
Set topFolder = Application.Session.GetDefaultFolder(olFolderInbox).Parent
Dim i As Integer
For i = 1 To topFolder.Folders.Count
Debug.Print topFolder.Folders(i).Name
Next i
For i = 1 To topFolder.Folders("inbox").Folders.Count
Debug.Print topFolder.Folders("inbox").Folders(i).Name
Next i
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

Outlook rule not running VBA code

I have VBA code to look for attachments in e-mails in a specific Outlook folder and save them into a location.
I have an Outlook rule that sends the emails to the Outlook folder then fires the macro. The code does not fire on my computer automatically, but it does on another computer. The email comes in and the rule drops it into the folder, but the code does not run. When I run the code manually, through the VB Editor, it saves the attachment in the right place.
I have checked to make sure folder and path names are correct (either way if they were wrong the code would not run properly when I run it manually).
Outlook rule:
Apply this rule after the message arrives
from xxxxxxxxxxxx
and with xxxx in the subject
and on this machine only
move it to the xxxxx folder
and run Project1.ThisOutlookSession.Save
VBA code:
Sub Save(item As Outlook.MailItem)
Dim olApp As Outlook.Application
Dim objNS As Outlook.NameSpace
Dim olFolder As Outlook.MAPIFolder
Dim msg As Outlook.MailItem
Set olApp = Outlook.Application
Set objNS = olApp.GetNamespace("MAPI")
Set olFolder = objNS.GetDefaultFolder(olFolderInbox)
Set olFolder = olFolder.Folders("xxxxxxx")
Set oApp = CreateObject("Shell.Application")
For Each myitem In olFolder.Items
For Each att In myitem.Attachments
att.SaveAsFile "\\.............\" & att.FileName
myitem.Attachments.Remove 1
myitem.Save
Next
Next
End Sub
The incoming mailitem is item in Sub Save(item As Outlook.MailItem). It is not used in the code.
Later when run manually the code still ignores whatever item is passed but all items in olFolder are now processed.
Try this:
Sub Save(item As Outlook.MailItem)
For Each att In item.Attachments
att.SaveAsFile "\\.............\" & att.FileName
item.Attachments.Remove 1
item.Save
Next
End Sub
try deleting the file (save the codes somewhere else first) ... \Documents and Settings\\Application Data\Microsoft\Outlook\VbaProject.OTM