Is there an event like BeforeFolderMove for copying folders? - vba

I'm looking for events in VBA Outlook, triggered when I copy a folder to another folder.
When I move the folder with a right mouse-click, I get the event BeforeFolderMove.
When I copy the folder, there is no event triggered.
Is there an event like BeforeFolderMove?
Private Sub myFolderSelected_BeforeFolderMove(ByVal MoveToFolder As Outlook.Folder, ByRef Cancel As Boolean) Handles myFolderSelected.BeforeFolderMove
If I move a folder in Outlook only with the mouse via drag and drop, there's no event fired like BeforeFolderMove fired in VBA I can react on.
Any events I can look for?

You can handle the Folders.FolderAdd event which is fired when a folder is added to the specified Folders collection (copied and pasted).
Public WithEvents myOlFolders As Outlook.Folders
Public Sub Initialize_handler()
Set myOlFolders = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderInbox).Folders
End Sub
Private Sub myOlFolders_FolderAdd(ByVal Folder As Outlook.Folder)
Folder.Display
End Sub

Related

When new Reference is added, excel stops firing events

I have this code in ThisWorkbook:
Public WithEvents App As Application
Private Sub Workbook_Open()
Application.EnableEvents = True
' it is a simple control RefEdit, but it could be anything:
ThisWorkbook.VBProject.References.AddFromGuid{00024517-0000-0000-C000-000000000046},0,0
Set App = Application
End Sub
Private Sub App_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
Debug.Print "Selection changed"
End Sub
This code adds new Reference on Workbook open event. When the line which adds reference from GUID is executed, excel stops firing SheetSelectionChange events. As well as other events. If I comment that line, excel fires all events successfully. Could you tell me what I am doing wrong? Is it good place to invoke functions to add new references in a project?
Obviously Events and adding a new references do not love each other - reference.
This is the way around it, proposed there:
Private Sub Workbook_Open()
' 'Must have reference to the VBE IDE to access reference information
' ' Hardcode adding the GUID for the VBE IDE...
ThisWorkbook.VBProject.References.AddFromguid "{00-000000000046}", 0, 0
Application.OnTime Now() + TimeValue("00:00:01"), "SetupApplicationEvents"
End Sub
In a module:
Sub SetupApplicationEvents
Set App = Application
End Sub

Open email after sending

Why am I facing the below problem?
I have written a code to open sent email after sending email. The VBA code doesn't open the latest sent email but the previous one.
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
Dim myItem As MailItem
Dim myNamespace As NameSpace
Dim myFolder As Folder
Set myNamespace = Application.GetNamespace("MAPI")
Set myFolder = myNamespace.GetDefaultFolder(olFolderSentMail)
Set myItem = myFolder.Items(myFolder.Items.Count)
myItem.Display
End Sub
This is the answer why this won't work with the Application_ItemSend event:
Application_ItemSend is called before the email is sent. You can see that because it has a Cancel parameter. This means the email only gets sent if Cancel = False else the email is dropped.
So you just cannot display the email because it isn't sent at this time in the Application_ItemSend event. It gets sent after the Application_ItemSend is finished.
Note: If you put a break point within the Application_ItemSend you will see that the "New Email" window remains open/visible until the ItemSend event is finished. Therefore you cannot open that email within that event.
Workaround
You might try the following code. This creates an event for the default folder of sent items which is called when an item is added to this folder.
A restart of Outlook might be needed after adding the code (or at least running the Application_Startup procedure once).
Option Explicit
Public WithEvents myOlItems As Outlook.Items
Private Sub Application_Startup()
Set myOlItems = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderSentMail).Items
End Sub
Private Sub myOlItems_ItemAdd(ByVal Item As Object)
Item.Display
End Sub
If the folder where your sent items are moved to is not the default Outlook sent mail folder then you need to find the right folder to set it in Application_Startup.

Determine a Folder for Sent Items in Outlook and remember last selected folder

I'm trying to create a send-and-file option for Outlook 2016 and luckily I found this Site. However, because we have a lot of shared mailboxes my dialog box opens and defaults to the main account's inbox.
So far I couldn't find a way to make it remember the last selected folder in the folder picker. From the site I mentioned, we can only use to pick the folder manually because shared mailboxes are not read as an account by Outlook.
How do I add a script in VB to make it remember the last selected folder. If not then what another option we can accept is make the treeview expanded or just set another default folder. Thanks much.
Here's the code btw:
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
If TypeOf Item Is Outlook.MailItem Then
Cancel = Not SaveSentMail(Item)
End If
End Sub
Private Function SaveSentMail(Item As Outlook.MailItem) As Boolean
Dim F As Outlook.MAPIFolder
If Item.DeleteAfterSubmit = False Then
Set F = Application.Session.PickFolder
If Not F Is Nothing Then
Set Item.SaveSentMessageFolder = F
SaveSentMail = True
End If
End If
End Function
The PickFolder method and the dialog that is displayed has no options and cannot be customized. The only other option is to use Redemption, which offers many customizations for selecting a folder. See http://www.dimastr.com/redemption/RDOSelectFoldersDialog.htm.

Outlook VBA - Detect when inbox is empty? Run Macro when inbox is empty?

I have some outlook VBA code for work that will automatically allocate my team members one email at a time to respond to from our customers, and as it does this it also scans for and gives them any emails that have come in later from the same email address, so the customer can be dealt with in one go.
I want this to run when their own folder becomes empty (i.e. they've dealt with one client, and it automatically runs the above to allocate them another when they move the current mail to an archive, leaving their main inbox folder empty).
Is there any way to do this? I know I can set the macro to check for it every 5 mins, but this will slow Outlook down massively. Any way to trigger the macro only when the user's folder is emptied?
Cheers
Chris
Events are perfect for this.
Events are triggered by the application, when key changes are made. This allows you to avoid using a timed loop.
You can use the WithEvents statement to create a variable that can handle event calls.
In this example the variable f points to the inbox. Whenever an item is deleted from this folder the f_BeforeItemMove procedure is called. It displays the number of items left, minus one. We subtract one because the event is fired before the deletion (this gives you a chance to cancel it, should you wish).
Because we are using an object variable we need to create and destroy it. This occurs when the app is started & exited.
Private WithEvents f As Folder ' Inbox folder, used to monitor events.
Private Sub Application_Startup()
' Register for events.
Set f = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderInbox)
End Sub
Private Sub Application_Quit()
' Unregister.
Set f = Nothing
End Sub
Private Sub f_BeforeItemMove(ByVal Item As Object, ByVal MoveTo As MAPIFolder, Cancel As Boolean)
' Called when an item is moved out of the inbox.
' Display the number of items left, after delete.
MsgBox (f.Items.Count - 1)
End Sub
This code must be added to the ThisOutlookSession class. The startup and quit events will not fire if pasted into another module.
EDIT
The original solution, above, was trigger just before an item was deleted from the inbox. The OP wanted code that fired just after. This new solution does that.
Private WithEvents f As Folder ' Inbox folder, used to monitor events.
Private WithEvents i As Items ' Items within folder above
Private Sub Application_Startup()
' Register for events.
Set f = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderInbox)
Set i = f.Items
End Sub
Private Sub Application_Quit()
' Unregister.
Set i = Nothing
Set f = Nothing
End Sub
Private Sub i_ItemRemove()
' Called each time an item is moved out of the inbox.
' This can be triggered by moving an item to another folder
' or deleting it.
' Display the new inbox item count.
MsgBox i.Count
End Sub
As before; this code should be placed inside ThisOutlookSession. You will need to restart Outlook, or manually execute Application_Startup.
You can trap the Items.ItemRemove event to monitor for when the Items.Count property evaluates to 0. Call the Initialize_handler() method during the Application_Startup() event:
Public WithEvents myOlItems As Outlook.Items
Public Sub Initialize_handler()
Set myOlItems = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderInbox).Items
End Sub
Private Sub myOlItems_ItemRemove()
If myOlItems.Count = 0 Then
'Inbox is empty!
End If
End Sub

Error with Outlook VBA script applied to rule

I have a rule in Outlook which sends a daily email into a particular folder. I then have a VBA script which upon noticing a new unread message in that folder goes in and saves the attachment to a folder on my hard drive and does a few other formatting type things (on the attachment).
I then just linked up the script to the rule in the Outlook rules wizard so it runs as a package.
The problem is as follows: the script is kicked off BEFORE the message is sorted into the appropriate folder. In reality it should run after the message is sorted (otherwise there is nothing for it to act upon). Any ideas on how to rectify?
The code currently begins as follows:
sub saveattachment()
Should it be this instead?
private sub saveattachment()
or
public sub saveattachment()
Would it be better to have the "rule" embedded in the macro instead and then just run it as a private sub anytime the daily email appears in my Inbox?
If you need to assign a VBA macro sub to the Outlook rule, the VBA sub should look like the following one:
Public Sub Test(mail as MailItem)
' your code goes there
End Sub
An instance of the MailItem class is passed as a parameter and stands for the email arrived to the Inbox.
But in case if you need to be sure that your code is triggered when a mail is moved to a particular folder you need to handle the ItemAdd event of the Items class which comes from that folder. Be aware, the event is not fired when more than 16 items are added to the folder simultaneously.
Public WithEvents myOlItems As Outlook.Items
Public Sub Initialize_handler()
Set myOlItems = Application.GetNamespace("MAPI").GetDefaultFolder(olFolderContacts).Items
End Sub
Private Sub myOlItems_ItemAdd(ByVal Item As Object)
Dim myOlMItem As Outlook.MailItem
Dim myOlAtts As Outlook.Attachments
Set myOlMItem = myOlApp.CreateItem(olMailItem)
myOlMItem.Save
Set myOlAtts = myOlMItem.Attachments
' Add new contact to attachments in mail message
myOlAtts.Add Item, olByValue
myOlMItem.To = "Sales Team"
myOlMItem.Subject = "New contact"
myOlMItem.Send
End Sub
Finally, you may find the Getting Started with VBA in Outlook 2010 article helpful.