Create email, based on Outlook template, from a Word menu - vba

This is the code for other Word templates on the menu.
Private Sub "button name_Click()
Unload ####Menu
End Sub
This is code I've seen to create an Outlook item from Word.
Sub CreateFromTemplate()
Dim MyItem As Outlook.MailItem
Set MyItem = Application.CreateItemFromTemplate("C:\statusrep.oft")
MyItem.Display
End Sub
Sub CreateTemplate()
Dim MyItem As Outlook.MailItem
Set MyItem = Application.CreateItem(olMailItem)
MyItem.Subject = "Status Report"
MyItem.To = "Dan Wilson"
MyItem.Display
MyItem.SaveAs "C:\statusrep.oft", OlSaveAsType.olTemplate
End Sub
How do I combine these?

It seems you just need to automate Outlook from Word VBA. To start an Outlook Automation session, you can use either early or late binding. Late binding uses either the Visual Basic GetObject function or the CreateObject function to initialize Outlook. For example, the following code sets an object variable to the Outlook Application object, which is the highest-level object in the Outlook object model. All Automation code must first define an Outlook Application object to be able to access any other Outlook objects.
Dim objOL as Object
Set objOL = CreateObject("Outlook.Application")
To use early binding, you first need to set a reference to the Outlook object library. Use the Reference command on the Visual Basic for Applications (VBA) Tools menu to set a reference to Microsoft Outlook xx.x Object Library, where xx.x represents the version of Outlook that you are working with. You can then use the following syntax to start an Outlook session.
Dim objOL as Outlook.Application
Set objOL = New Outlook.Application
Most programming solutions interact with the data stored in Outlook. Outlook stores all of its information as items in folders. Folders are contained in one or more stores. After you set an object variable to the Outlook Application object, you will commonly set a NameSpace object to refer to MAPI, as shown in the following example.
Set objOL = New Outlook.Application
Set objNS = objOL.GetNameSpace("MAPI")
Set objFolder = objNS.GetDefaultFolder(olFolderContacts)
Once you have set an object variable to reference the folder that contains the items you wish to work with, you use appropriate code to accomplish your task, as shown in the following example.
Sub CreateNewOutlookMail()
Dim objOLApp As Outlook.Application
Dim NewMail As Outlook.MailItem
' Set the Application object
Set objOLApp = New Outlook.Application
' You can only use CreateItem for default items
Set NewMail = objOLApp.CreateItem(olMailItem)
' Display the new mail form so the user can fill it out
NewMail.Display
End Sub
See Automating Outlook from a Visual Basic Application for more information.

Related

Macro used to run on Outlook 2013, now doesn't run on Outlook 2021 on a new computer

A few years ago I had a developer write a macro for me to print the current email as two pages per page rather than on two separate pages.
It used to run successfully on my old computer Win 10/Outlook 2013.
I now have a new computer Win10/Outlook 2021
It now comes up with a compile error "User defined type not defined" for the line
Dim wdApp As Word.Application
I only have a rudimentary grasp of VBA so am unable to solve this one. Any help would be greatly appreciated.
Code is as follows:
Option Explicit
Public Sub print_mail()
Dim objOL As Outlook.Application
Dim objMsg As Outlook.MailItem
Dim objAttachments As Outlook.Attachments
Dim objSelection As Outlook.Selection
Dim i As Long
Dim lngCount As Long
Dim Response As Integer
Dim msg As String
Dim strSubject As String
Dim currentItem As Object
Set objOL = CreateObject("Outlook.Application")
Set objSelection = objOL.ActiveExplorer.Selection
For Each currentItem In objSelection
If currentItem.Class = olMail Then
Set objMsg = currentItem
PrintFirstPage objMsg
End If
Next
Set objAttachments = Nothing
Set objMsg = Nothing
Set objSelection = Nothing
Set objOL = Nothing
End Sub
Public Sub PrintFirstPage(Mail As Outlook.MailItem)
Dim wdApp As Word.Application
Dim wdDoc As Word.Document
Dim olDoc As Word.Document
Set wdApp = CreateObject("Word.Application")
Set wdDoc = wdApp.Documents.Add(Visible:=True)
Set olDoc = Mail.GetInspector.WordEditor
olDoc.Range.Copy
wdDoc.Range.Paste
' With wdDoc
' .PageSetup.Orientation = wdOrientLandscape
' End With
'wdDoc.PrintOut
wdApp.PrintOut FileName:="", Range:=wdPrintRangeOfPages, Item:= _
wdPrintDocumentWithMarkup, Copies:=1, Pages:="1-2", PageType:= _
wdPrintAllPages, Collate:=True, Background:=True, PrintToFile:=False, _
PrintZoomColumn:=2, PrintZoomRow:=1, PrintZoomPaperWidth:=0, _
PrintZoomPaperHeight:=0
wdDoc.Close False
wdApp.Quit
End Sub
Use an untyped variable:
Dim appWD as Object
appWD = CreateObject("Word.Application")
Or try to add the Word object library reference to the project.
Inside the Visual Basic Editor , select Tools then References and scroll down the list until you see Microsoft Word 12.0 Object Library. Check that box and hit Ok.
VBA macros are not designed for distributing on multiple machines. If you need to deploy your code on a wide range of machines you would better consider transforming your solution to Office add-ins - it can be a COM add-in or a web-based one. See Walkthrough: Create your first VSTO Add-in for Outlook for more information.
When you move your VBA code to another machine you need to make sure that all COM references are added as it was on your original machine.
In order to solve your problem, you have to add the Word object library reference to your project.
Inside the Visual Basic Editor, select Tools then References and scroll down the list until you see Microsoft Word XX.0 Object Library. Check that box and hit Ok.
From that moment, you should have the auto complete enabled when you type Word. to confirm the reference was properly set.
Note, you could also use the late binding technology which doesn't require adding COM references:
' No reference to a type library is needed to use late binding.
' As long as the object supports IDispatch, the method can
' be dynamically located and invoked at run-time.
' Declare the object as a late-bound object
Dim oWord As Object
Set oWord = CreateObject("Word.Application")
' The Visible property is called via IDispatch
oWord.Visible = True
So, to start an Word Automation session, you can use either early or late binding. Late binding uses either the Visual Basic GetObject function or the CreateObject function to initialize Word. See Using early binding and late binding in Automation for more information.

How I can run macro automatically with new email arrives in outlook

Am very new to VBScript and macro . I have a vbscript which will create tickets for email's but I need to run this script manually every time .To make it automation I have mapped my macro to the "run a script" script rule in Outlook but when the rule runs it is not fetching the data in the mail which is arrived .It's creating tickets with previous email always .
I have gone through so many VBscripts but none worked to convert the mail that received in to ticket.
If any one faced similar type of issue please let me know the complete solution.
Dim olApp As outlook.Application
Dim objNS As outlook.NameSpace
Dim objSourceFolder As outlook.MAPIFolder
Dim objDestFolder As outlook.MAPIFolder
Dim Msg As outlook.MailItem
Set olApp = outlook.Application
Set objNS = olApp.GetNamespace("MAPI")
Set objSourceFolder = objNS.GetDefaultFolder(olFolderInbox)
Set objDestFolder = objSourceFolder.Folders("Termination")
Set Msg = objDestFolder.Items.GetLast
Set sh = CreateObject("Shell.Application")
Set ie = CreateObject("InternetExplorer.Application")
LocationURL = "Ticket URL” & Msg.EntryID"
ie.Navigate (LocationURL)
ie.Visible = True
With ie.Document
.getElementById("details").Value = Msg.Body
.getElementById("short_description").Value = Msg.Subject
.getElementById("requester_login").Value = "premchand"
End With
When you run a macro from a rule it typically has an argument to which the item triggering the rule gets passed: you do not have to navigate through the Inbox to find the item.
Public Sub DoSomething(Item As Outlook.MailItem)
'code which acts on "Item"
End Sub
There are several ways for handling incoming emails:
The NewMailEx event of the Application class which is fired when a new item is received in the Inbox. This event is not available in Microsoft Visual Basic Scripting Edition (VBScript).
The ItemAdd event of the Items class is fired when one or more items are added to the specified collection. So, you can subscribe to the Inbox folder to see new items. Be aware, this event does not run when a large number of items are added to the folder at once. This event is not available in Microsoft Visual Basic Scripting Edition (VBScript).
Assign a macro VBA sub to the rule in Outlook. In that case the incoming mail item is passed as a parameter to the sub as Tim showed.

How to access certain mailitem properties/methods in a Visual Studio Outlook Add-In?

I'm developing an Outlook (2010) add-in using Visual Studio 2013 (Targeting .NET 4).
Certain Outlook properties/methods seem to be unavailable.
The following code works from Outlook VBA.
Public Sub OutlookTest()
'Dim oApp As New Outlook.Application (NOT NEEDED FOR OUTLOOK VBA)
Dim oExp As Outlook.Explorer
Dim oSel As Outlook.Selection ' You need a selection object for getting the selection.
Dim oItem As Object ' You don't know the type yet.
Set oExp = Application.ActiveExplorer 'Get the ActiveExplorer.
Set oSel = oExp.Selection ' Get the selection.
For i = 1 To oSel.Count ' Loop through all the currently .selected items
Set oItem = oSel.Item(i) ' Get a selected item.
Call DisplayInfo(oItem) ' Display information about it.
Next i
End Sub
Private Sub DisplayInfo(oItem As Object)
Dim strMessageClass As String
Dim oMailItem As Outlook.MailItem
' You need the message class to determine the type.
strMessageClass = oItem.MessageClass
If (strMessageClass = "IPM.Note") Then ' Mail Entry.
Set oMailItem = oItem
MsgBox oMailItem.Subject
MsgBox oMailItem.EntryID
MsgBox oMailItem.HTMLBody
oMailItem.SaveAs "C:\Users\u001tb7\Desktop\New folder\testOL.msg", olMSG
Else
MsgBox "Pick something else"
End If
End Sub
When I try near identical code from Visual Studio in an add-in:
Private Sub butSettings_Click(sender As Object, e As RibbonControlEventArgs) Handles butSettings.Click
Dim oApp As New Outlook.Application
Dim oExp As Outlook.Explorer
Dim oSel As Outlook.Selection ' You need a selection object for getting the selection.
Dim oItem As Object ' You don't know the type yet.
oExp = oApp.ActiveExplorer ' Get the ActiveExplorer.
oSel = oExp.Selection ' Get the selection.
For i = 1 To oSel.Count ' Loop through all the currently .selected items
oItem = oSel.Item(i) ' Get a selected item.
DisplayInfo(oItem) ' Display information about it.
Next i
End Sub
Sub DisplayInfo(oItem As Object)
Dim strMessageClass As String
Dim oMailItem As Outlook.MailItem
' You need the message class to determine the type.
strMessageClass = oItem.MessageClass
If (strMessageClass = "IPM.Note") Then ' Mail Entry.
oMailItem = oItem
MsgBox(oMailItem.Subject)
MsgBox(oMailItem.EntryID)
MsgBox(oMailItem.HTMLBody) '<---FAILS
oMailItem.SaveAs("C:\Users\u001tb7\Desktop\New folder\testVS.msg", Outlook.OlSaveAsType.olMSG) '<---ALSO FAILS
Else
MsgBox("Pick something else")
End If
End Sub
I get an error on MailItem.HTMLBody and MailItem.SaveAs but NOT MailItem.Subject or .EntryID.
This makes me suspect it's something to do with the security, as I think properties like .HTMLBody are 'protected', but .EntryID and .Subject are not.
The error is the generic COM exception not giving me any detail:
An exception of type 'System.Runtime.InteropServices.COMException' occurred in MsgSave.dll but was not handled in user code
Additional information: Operation aborted (Exception from HRESULT: 0x80004004 (E_ABORT))
Is there any way to get Outlook to 'trust' my VS code (for eventual distribution)? Or is there something else amiss?
EDIT: Thanks to both below!
Instead of:
Dim oApp As New Outlook.Application
Use:
Dim oApp as Outlook.Application = Globals.ThisAddIn.Application
Do not use New Outlook.Application in an Outlook addin - you get Outlook.Application object for free when your addin starts up.
certain outlook properties/methods seem to be unavailable
What properties are you talking about? Could you be more specific?
As Dmitry suggested, you need to use the Application property provided by VSTO. In that case you will avoid security prompts or exceptions. Typically you get such issue when you try to automate Outlook from a standalone application. The Application object provided by VSTO is trusted and doesn't generate exceptions for secured properties or methods (for example, MailItem.Send). You can read more about that in the Outlook "Object Model Guard" Security Issues for Developers article.

In Outlook 2013, can a macro open a new custom form?

In Outlook 2013 using Developer tab -> Design a Form, I created a custom form (with no mods yet) from the delivered Message form and placed it in my Personal Forms Library. Outlook tells me that the Message class is: IPM.Note.MyForm
I've created a macro and set up a new ribbon button to run the macro. I would like the macro to open a new instance of my custom form, but I can't get it working.
With the following code I can get the macro to open a new instance of the delivered Message Form:
Set newItem = Application.CreateItem(olMailItem)
newItem.Display
Set newItem = Nothing
I can't get it to open my custom form. I've tried the following as arguments to CreateItem: olMailItem.MyForm and IPM.Note.MyForm.
The macro editor intellisense has about 9 options for arguments to CreateItem, all of them appear to be delivered objects/forms, and it errors if one of these options aren't used.
I've done very little vba and office macros, is there some way to get this macro to open my custom form? Thanks.
See Items.Add http://msdn.microsoft.com/en-us/library/office/ff861028(v=office.15).aspx
Sub AddForm()
Dim myNamespace As outlook.NameSpace
Dim myItems As outlook.Items
Dim myFolder As outlook.Folder
Dim myItem As outlook.MailItem
Set myNamespace = Application.GetNamespace("MAPI")
Set myFolder = myNamespace.GetDefaultFolder(olFolderInbox)
Set myItems = myFolder.Items
Set myItem = myItems.Add("IPM.Note.MyForm")
End Sub

Call Outlook procedure using VBScript

I have a procedure in Outlook that sends all the saved messages in Drafts folder.
Below is the code:
Public Sub SendMail()
Dim olApp As Outlook.Application
Dim olNS As Outlook.NameSpace
Dim olFolder As Outlook.MAPIFolder
Dim olDraft As Outlook.MAPIFolder
Dim strfoldername As String
Dim i As Integer
Set olApp = Outlook.Application
Set olNS = olApp.GetNamespace("MAPI")
Set olFolder = olNS.GetDefaultFolder(olFolderInbox)
strfoldername = olFolder.Parent
Set olDraft = olNS.Folders(strfoldername).Folders("Drafts")
If olDraft.Items.Count <> 0 Then
For i = olDraft.Items.Count To 1 Step -1
olDraft.Items.Item(i).Send
Next
End If
End Sub
Above code works fine.
Question:
I want to use Task Scheduler to fire this procedure as a specified time.
1. Where will I put the procedure in Outlook, Module or ThisOutlookSession?
2. I am not good in vbscript so I also don't know how to code it to call the Outlook Procedure. I've done calling Excel Procedure but Outlook doesn't support .Run property.
So this doesn't work:
Dim olApp
Set olApp = CreateObject("Outlook.Application")
olApp.Run "ProcedureName"
Set olApp = Nothing
I've also read about the Session.Logon like this:
Dim olApp
Set olApp = CreateObject("Outlook.Application")
olApp.Session.Logon
olApp.ProcedureName
Set olApp = Nothing
But it throws up error saying object ProcedureName is not supported.
Hope somebody can shed some light.
SOLUTION:
Ok, I've figured out 2 work around to Avoid or get pass this pop-up.
1st one: is as KazJaw Pointed out.
Assuming you have another program (eg. Excel, VBScript) which includes sending of mail via Outlook in the procedure.
Instead of using .Send, just .Save the mail.
It will be saved in the Outlook's Draft folder.
Then using below code, send the draft which fires using Outlook Task Reminder.
Option Explicit
Private WithEvents my_reminder As Outlook.Reminders
Private Sub Application_Reminder(ByVal Item As Object)
Dim myitem As TaskItem
If Item.Class = olTask Then 'This works the same as the next line but i prefer it since it automatically provides you the different item classes.
'If TypeName(Item) = "TaskItem" Then
Set my_reminder = Outlook.Reminders
Set myitem = Item
If myitem.Subject = "Send Draft" Then
Call SendMail
End If
End If
End Sub
Private Sub my_reminder_BeforeReminderShow(Cancel As Boolean)
Cancel = True
Set my_reminder = Nothing
End Sub
Above code fires when Task Reminder shows with a subject "Send Draft".
But, we don't want it showing since the whole point is just to call the SendMail procedure.
So we added a procedure that Cancels the display of reminder which is of olTask class or TaskItem Type.
This requires that Outlook is running of course.
You can keep it running 24 hours as i did or, create a VBscript that opens it to be scheduled via Task Scheduler.
2nd one: is to use API to programatically click on Allow button when the security pop-up appears.
Credits to SiddarthRout for the help.
Here is the LINK which will help you programmatically click on the Allow button.
Of course you have to tweak it a bit.
Tried & Tested!
Assuming that you have Outlook Application always running (according to comment below your question) you can do what you need in the following steps:
add a new task in Outlook, set subject to: "run macro YourMacroName" and set time (plus cycles) when your macro should start.
go to VBA Editor, open ThisOutlookSession module and add the following code inside (plus see the comments inside the code):
Private Sub Application_Reminder(ByVal Item As Object)
If TypeName(Item) = "TaskItem" Then
Dim myItem As TaskItem
Set myItem = Item
If myItem.Subject = "run macro YourMacroName" Then
Call YourMacroName '...your macro name here
End If
End If
End Sub
Where will I put the procedure in Outlook, Module or ThisOutlookSession?
Neither. Paste the below code in a Text File and save it as a .VBS file. Then call this VBS file from the Task Scheduler as shown HERE
Dim olApp, olNS, olFolder, olDraft, strfoldername, i
Set olApp = GetObject(, "Outlook.Application")
Set olNS = olApp.GetNamespace("MAPI")
Set olFolder = olNS.GetDefaultFolder(6)
strfoldername = olFolder.Parent
Set olDraft = olNS.Folders(strfoldername).Folders("Drafts")
If olDraft.Items.Count <> 0 Then
For i = olDraft.Items.Count To 1 Step -1
olDraft.Items.Item(i).Send
Next
End If
If you are using Outlook 2007 or newer I have found you can easily eliminate the security pop up you mentioned above when running your script by doing the following:
In Outlook 2007 Trust Center, go to Macro Security - Select "No security Check for macros"
In Outlook 2007 Trust Center, go to Programatic Access - Select "Never warn me abous suspicious activity.
Of course that technically leaves you open to the remote possibility for someone to email you some malicious email script or something of that nature I assume. I trust my company has that managed though and this works for me. I can use VBS scripts in Outlook, Access, Excel to send emails with no security pop up.
Another Option:
If you don't want to do that, another option that has worked well for me prior to this is here:
http://www.dimastr.com/redemption/objects.htm
Basically a dll redirect that does not include the popup. It leaves your other default security in place and you write \ call your VBA for it and send mail without the secutity pop-ups.