Creating VBA macro to save email copy - vba

I use Outlook (MS Exchange) and have an individual as well as two group inboxes (I'm working logged in with the individual profile through which I also have access to the group inboxes).
When I send an email, I chose either my individual or one of the two group email addresses in the From field. When the email is sent, I want a copy saved in the inbox of myIndividualMailbox, groupAMailbox, or groupBMailbox depending on which From email address I used.
Example: If I send an email From groupA#myCompany.com, I want a copy of the email saved in the inbox of the groupAMailbox (and not in my individual inbox).
I have understood that this is not possible by setting up a rule in Outlook but that it could be done with a VBA macro. I don't now how to write the VBA macro and don't know if this is a just a short script or more complicated. In fact I have never written a macro in Outlook so I don't even know how to begin. Can anyone show how to do this?
I started looking for a solution with this question: Outlook send-rule that filter on the 'From' field

I made this for you as far as I can tell, it works. You should put this in the Microsoft Outlook Objects - ThisOutlookSession Module.
Note that the myolApp_ItemSend event will never trigger unless you run enableEvents first. And you will need to make sure it is enabled every time you close an re-open Outlook. This will take some customization, but it should give you the general idea.
Option Explicit
Public WithEvents myolApp As Outlook.Application
Sub enableEvents()
Set myolApp = Outlook.Application
End Sub
Private Sub myolApp_ItemSend(ByVal item As Object, Cancel As Boolean)
Dim items As MailItem
Dim copyFolder As Outlook.Folder
Dim sentWith As String
'Identify sender address
If item.Sender Is Nothing Then
sentWith = item.SendUsingAccount.SmtpAddress
Else
sentWith = item.Sender.Address
End If
'Determin copy folder based on sendAddress
Select Case sentWith
Case "groupA#myCompany.com"
'get groupAMailbox's inbox
Set copyFolder = Application.GetNamespace("MAPI").folders("groupAMailbox").folders("Inbox")
Case "myE-mailAddress"
'get My inbox
Set copyFolder = Application.GetNamespace("MAPI").folders("myE-mailAddress").folders("Inbox")
End Select
'copy the Item
Dim copy As Object
Set copy = item.copy
'move copy to folder
copy.Move copyFolder
End Sub
EDIT: It looks like they've actually built the event functionality into the Application object for Outlook directly now, but it from testing you still have to do what I outlined above.

Outlook stores all sent items in default sent items folders. however you can apply a patch to save sent items in its own folder.
http://support.microsoft.com/kb/2181579

Related

How to determine dragged outlook mailObject attachment

I have a userform with a treeview control MSComctlLib.TreeView. It is used to save files that are dragged on top of it to the drive. My problem is that whenever an email has multiple attachment and one is dragged over, there is no apparent way to tell which one specific attachment out of multiple is selected.
Code below includes an event fired when the file is dragged to the TreeView and then calls a sub based on the DataObject format. When the attachment is dragged, this code parses all of the attachments in the currently selected email (after filtering out embedded images). The ordering of attachments does not change based on which attachment is selected and I could not find a PropertyAccessor property that may be helpful.
Private Sub treeView_OLEDragDrop(Data As MSComctlLib.DataObject, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single)
Select Case True
Case Data.GetFormat(13): 'process Email
Case Data.GetFormat(15): 'process files
Case Else: processAttachments
End Select
End Sub
Private Sub processAttachments()
Dim outlookApp As Object: Set outlookApp = CreateObject("Outlook.Application")
Dim selection As Object: Set selection = outlookApp.activeexplorer.selection
Dim email As Object
Dim attachment As Object
For Each email In selection
For Each attachment In email.Attachments
If Not attachment.PropertyAccessor. _
GetProperty("http://schemas.microsoft.com/mapi/proptag/0x37140003") = 4 _
Then ' filters out embedded images
Debug.Print attachment.DisplayName
End If
Next
Next
End Sub
Is there a method to determine which one of the email attachments is currently selected or is currently being dragged over?
The best what you could do is to track the currently selected attachment in Outlook, so if the drag and drop operation is made you could quickly get the currently selected attachment. Or just use the AttachmentSelection property as explained below to get the selected attachments in Outlook.
The Explorer.AttachmentSelectionChange event is fired when the user selects a different or additional attachment in the active explorer programmatically or by interacting with the user interface.
The Inspector.AttachmentSelectionChange event is fired when the user selects a different or additional attachment of an item in the active inspector programmatically or by interacting with the user interface.
To get the selected attachments you need to use the Explorer.AttachmentSelection or Inspector.AttachmentSelection property which returns an AttachmentSelection object consisting of one or more attachments that are selected in the explorer or inspector respectively.
The AttachmentSelection object contains a read-only collection of attachments that are selected in an item that is in the active inspector or the active explorer.

Outlook startup macro execution results are different from manually initiated copy

Every weekday morning I would like to see the content of a specific subfolder in my personal profile right after starting Outlook.
I have an Outlook macro that when fired manually the folder is activated, content (all mails) is shown.
I copied the macro to ThisOutlookSession and restarted Outlook.
The macro starts and the folder is activated.
Nothing is shown (it is not empty for sure).
Nothing is shown in any folders having run the macro this way. Content of any folder is shown for a second when I switch from one folder to another. The content is there but won't show permanently.
Private Sub Application_Startup()
Activate_SubFolder
End Sub
Sub Activate_SubFolder()
Dim myfolder As Folder
Set myfolder = Session.Folders("myname#mycompany.com").Folders("Subfolder1").Folders("Subfolder2")
Set ActiveExplorer.CurrentFolder = myfolder
Set myfolder = Nothing
End Sub

Macro works on one computer but not the other

Fair warning - the code is not my own, so any ideas will be welcomed on how to change it.
Public Sub ChangeMeeting()
Dim oRequest As MeetingItem
Dim oAppt As AppointmentItem
Set oRequest = Application.ActiveExplorer.Selection.Item(1)
If oRequest.MessageClass = "IPM.Schedule.Meeting.Request" Then
Set oAppt = oRequest.GetAssociatedAppointment(True)
' use this to autoaccept
Dim oResponse
Set oResponse = oAppt.Respond(olMeetingAccepted, True)
oResponse.Send
' set fields on the appt.
With oAppt
' .Categories = "Slipstick"
.BusyStatus = olFree
.Save ' use .Display if you want to see the appt. and set the reminder yourself
End With
End If
'delete the request from the inbox
oRequest.Delete
End Sub
This one's interesting. On my computer, it works just fine. However, on the other one it can be clicked on and clicked on, and nothing will happen. No errors, no popups, no nothing. So, I know that the code works, but is there any reason (rights?) that the exact same code would work on one and not the other?
First of all, make sure that VBA macros are allowed to run. Is the VBA macro run in Outlook at all? Did you try to debug it?
Do you get any errors in the code on another machines?
I'd suggest starting from breaking the chain of property and method calls and declaring them on separate lines of code. Thus, you will be able to find what property or method fails.
The code is based on the selected item in the Explorer:
Application.ActiveExplorer.Selection.Item(1)
Is the selection not empty all the time?
If oRequest.MessageClass = "IPM.Schedule.Meeting.Request"
Does the selection contains the first item with the specified message class?
In general, VBA macros are not designed for distributing on multiple PCs. If you need to get a solution working on multiple machines you need to develop an add-in instead. See Walkthrough: Creating Your First VSTO Add-In for Outlook .
Finally, you may find the Getting Started with VBA in Outlook 2010 article helpful.

Outlook Task Scheduler to Run Access Subs

I have Access Macros that run a series of queries, form a tables, and send those tables to multiple recipients. This works fine, but I'm being increasingly asked to supply an increasing number of reports on a set day of the week.
Rather than use my calendar to remind me to open Access and run these Macros, can I run VBA in Outlook to run an Access macro on a certain day?
Rather than use my calendar to remind me to open Access and run these Macros, can I run VBA in Outlook to run an Access macro on a certain day?
There are ways you can do this with .BAT files and windows task scheduler, but you can also do it with Outlook VBA. I have a few calendar events which have this exact purpose, to execute code and clear the reminder.
First you need to add an event handler to fire when your reminders get set.
Private WithEvents olRemind As Outlook.Reminders
You then need to initialize the WithEvents. I do this everytime a reminder happens because I sometimes break code or hard stop, which loses the event handler.
Private Sub Application_Reminder(ByVal Item As Object)
Set olRemind = Outlook.Reminders
End Sub
Then, you want to process the event on your calendar. The way I have mine setup is I add a specific category for the event I want to fire. This helps make my calendar clearer. You can do this in a variety of ways.
I also then dismiss the reminder so it doesn't show up.
'fire off automatic macros based on recurring reminders
Private Sub olRemind_BeforeReminderShow(Cancel As Boolean)
Dim objRem As Reminder
For Each objRem In olRemind
'get categories
Dim rmdrCategories As String
rmdrCategories = objRem.Item.categories
'call the macro based on category
If InStr(rmdrCategories, "whateverYouWantTheReminder") > 0 Then
'only run if this reminder is visible
If objRem.IsVisible Then
'This code is specific to whatever macro you want to run
Dim mydb As Object
Set mydb = GetObject("...pathToDatabase.mdb")
mydb.Application.Run "YourMacroName"
mydb.Application.Quit
Set mydb = Nothing
objRem.Dismiss
Cancel = True
End If
End If
Next objRem
End Sub

Extracting specific information from Outlook 2003 to Excel using VBA

So firstly, I'm very new to VBA and due to the number of emails I get that follow a certain template, I'm trying to automate the data collation to save myself from all the cutting and pasting that is currently required. I've looked at some previous questions but due to my very little knowledge, the answers aren't specific enough for me to understand.
Each one of these emails is from a particular email address and has a standard format as shown below:
"
dd/mm/yyyy hr.min.sec
xxx xxxxxxx xxxxxxxxxxxxxxxxx xxxx xxxxx "
I would like to export or copy this information to an excel 2003 worksheet so that each separate piece of information is in a new column of a single row, where each email is a new row.
I would like the macro to be able to search through my received emails in a particular folder (as I've already set up some rules in outlook relating to this email address), copy the information from each email matching the template and paste it into a single excel worksheet. Then each time I get a new email, the information will be added to the bottom of the table thats been created.
Hopefully that all makes sense, please let me know if you need anymore information.
Thanks in advance.
I did something exactly like this recently, except that I had it entered into an access database instead of an excel sheet, but the idea is the same. For some reason, I was having trouble getting it to run with rules, but I anyways found that I could control it better from a manually run macro. So use a rule to put everything into a folder, and make an AlreadyProcessed subfolder under that. Here is some code to start from:
Sub process()
Dim i As Integer, folder As Object, item As Object
With Application.GetNamespace("MAPI").GetDefaultFolder(olFolderInbox).Folders("YourFolderName")
For Each item In .Items
processMail item
item.Move .Folders("AlreadyProcessed")
Next
End With
End Sub
Sub processMail(item As Outlook.MailItem)
Dim bitsOfInformation() As String
bitsOfInformation = Split(item.Body, " ")
'Use this information to make an Excel file
End Sub
Making Excel files from VBA are very easy - just read up on opening excel and making new documents from other Office program VBAs - you're looking for Excel.Application. You can even record a macro in Excel, filling the information manually, and basically copy the code into Outlook and replace the hard-coded information with variables. But if you're going to be running this on thousands of e-mails, be warned that recorded macros (that use selection objects) are inefficient.
Start with the following code:
Private WithEvents Items As Outlook.Items
Private Sub Application_Startup()
Set Items = GetItems(GetNS(GetOutlookApp), olFolderInbox)
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
End If
ProgramExit:
Exit Sub
ErrorHandler:
MsgBox Err.Number & " - " & Err.Description
Resume ProgramExit
End Sub
Function GetItems(olNS As Outlook.NameSpace, folder As OlDefaultFolders) As Outlook.Items
Set GetItems = olNS.GetDefaultFolder(folder).Items
End Function
Function GetNS(ByRef app As Outlook.Application) As Outlook.NameSpace
Set GetNS = app.GetNamespace("MAPI")
End Function
Function GetOutlookApp() As Outlook.Application
Set GetOutlookApp = Outlook.Application
End Function
This sets an event listener on your default Inbox. Whenever an email message is received, the code inside the If TypeName statement will be executed. Now it's simply a matter of what code you want to run.
You can check the sender using the .SenderName or .SenderEmailAddress properties to make sure it's the right sender.
If you provide more specific information, I can amend the code.