i have a very simple small app in mind which will help me save time from alt tabbing from excel to outlook. i want to create a small userform that will have a textbox for a exchange user alias and return the exchange user's full name. now the issue i have here is that the guide in msdn is a little vague for a userform: https://msdn.microsoft.com/en-us/library/office/ff869721.aspx and i'm getting some error messages, some got fixed by activating some references. and the code is quite complicated.
so basically i have 2 textboxes and a button. textbox1 will accept the alias, textbox2 will return the username after clicking the button.
there are several examples but most of them will result in dumping the GAL to an excel file which i don't need.
thanks in advanced
This will give you what you want.
Private Function GetFullName(inAlias As String) As String
Dim olApp As Outlook.Application
Dim olNS As Outlook.Namespace
Dim olAdd As Outlook.AddressEntries
Dim olMem As Outlook.AddressEntry
Dim olLst As Outlook.AddressList
Dim olAlias As String
On Error Resume Next
Set olApp = New Outlook.Application
On Error GoTo 0
If olApp Is Nothing Then
GetFullName = "Source not available"
Exit Function
End If
Set olNS = olApp.GetNamespace("MAPI")
Set olLst = olNS.GetGlobalAddressList
Set olAdd = olLst.AddressEntries
For Each olMem In olAdd
On Error Resume Next
olAlias = olMem.GetExchangeUser.Alias
On Error GoTo 0
If olAlias = inAlias Then
GetFullName = olMem.GetExchangeUser.Name
Exit For
Else
GetFullName = "Invalid Alias"
End If
Next
Set olApp = Nothing: Set olNS = Nothing: Set olAdd = Nothing
End Function
The draw back is this may take a while if your GAL is quite large.
I'll check if I can dump the list to an array first and then manipulate from there.
Or if there is another way to get to the name via alias using other method.
But for now, try learning from this first.
This is a function, so to get it to your textbox, you can simply:
TextBox2 = GetFullname(TextBox1)
Note:
I intentionally declared all the objects, you need to know what type of object you're working on. Also I used On Error Resume Next because there are AddressEntry without Alias and that gives error. That's the easiest work around I can think of for now.
Requirement:
You need to reference Microsoft Outlook xx.x Object Library.
xx.x vary depending on the Outlook version installed in your machine.
Related
So i have been struggling with this issue for about a week now. The below code is the opening portion of a project I'm working on.
The goal here is to open up the address-book pop-up for the Global Address List in outlook. I gathered most of this code from another question or two here on stacked overflow. The issue is, when I get to the final line
Set Dialog = outlookApp.Session.GetSelectNamesDialog
I get a "Run-time error '287': Application-defined or object-defined error"
Yes, Outlook 16.0 reference library is checked off.
I was curious about object security blocking.
I recently updated to GetGlobalAddressList to fix a similair issue.
Sub AddTestConductor() 'inserts information for a new TC from GAL
Dim OutlookApp As Outlook.Application
Dim OutlookNameSpace As Outlook.Namespace
Dim Dialog As Outlook.SelectNamesDialog
Dim GAL As Outlook.AddressList
Dim TCEntry As Outlook.AddressEntry
Dim User As Outlook.ExchangeUser
Dim Alias As String
Dim FirstName As String
Dim LastName As String
Dim Email As String
Dim where As String
Set OutlookApp = GetObject(, "Outlook.Application") 'grabs outlook for use
Set OutlookNameSpace = OutlookApp.GetNamespace("MAPI")
OutlookNameSpace.Logon , , True, False
Set GAL = OutlookApp.Session.GetGlobalAddressList
Set Dialog = OutlookApp.Session.GetSelectNamesDialog
With Dialog
.AllowMultipleSelection = False
.InitialAddressList = GAL
.ShowOnlyInitialAddressList = True
If .Display Then
Alias = Dialog.Recipients.Item(1).Name
Set TCEntry = GAL.AddressEntries(Alias)
Set User = TCEntry.GetExchangeUser
If Not User Is Nothing Then 'populate variable for name and e-mail0
FirstName = User.FirstName
LastName = User.LastName
Email = User.PrimarySmtAddress
End If
End If
End With
Set OutlookApp = Nothing 'Empty objects for next use
Set Dialog = Nothing
Set GAL = Nothing
Set TCEntry = Nothing
Set User = Nothing
In addition to the above, I would like to specify a sub folder withing th GAL, to wean the list down.
Info grabbed from the GAL with be inserted into a spreadsheet, then I will need to create links to calendar dates from their information as well. I haven't gotten that far yet.
I'm currently just trying to gather info about a user as baby step number one.
I’m currently working on an access Vba program in order to automatically write mails to people. However we chose to still press ‘Send’ in Outlook manually (in case there are possible issues, so we can control the mail beforehand).
Is there a way to have a link in the other direction, as in, when pressing the Send button in Outlook, getting the email address of the person back in excel? (The goal would be to make a ‘history’ sheet in order to keep track of which mails were actually sent and to whom)
Thank you!
Yes. A simple case is shown below. This is bare bones demonstrating the actions you requested.
Public variable, addressSent, holds the To address. A boolean test on mail sent (by #Rory) tests for the mail item having been sent and calls a function, by #Dwipayan Das, that opens a specified Excel file, and writes the addressSent to cell A1 in sheet1.
You can tinker with this to fit your purposes. E.g. Adapt the function to accept a file name as parameter.....
Taking a note from #ashleedawg's book: remember to include a xlApp.Quit line so Excel is not left hanging.
I believe your question wanted to go from Outlook to Excel so this is the application that you will have created that needs closing.
So in Outlook goes the following code:
Put this in a standard module:
Option Explicit
Public addressSent As String
Dim itmevt As New CMailItemEvents
Public Sub CreateNewMessage()
Dim objMsg As MailItem
Set objMsg = Application.CreateItem(olMailItem)
Set itmevt.itm = objMsg
With objMsg
.Display
.To = "somebody#mail.com"
.Subject = "Blah"
addressSent = .To
.Send
End With
End Sub
Public Function openExcel() As Boolean 'Adapted from #Dwipayan Das
Dim xlApp As Object
Dim sourceWB As Object
Dim sourceWS As Object
Set xlApp = CreateObject("Excel.Application")
With xlApp
.Visible = True
.EnableEvents = False
End With
Dim strFile As String
strFile = "C:\Users\User\Desktop\Delete.xlsb" 'Put your file path.
Set sourceWB = xlApp.Workbooks.Open(strFile, , False, , , , , , , True)
sourceWB.Activate
sourceWB.Worksheets(1).Range("A1") = addressSent
End Function
Then in a class module called CMailItemEvents, code from #Rory, put the following:
Option Explicit
Public WithEvents itm As Outlook.MailItem
Private Sub itm_Close(Cancel As Boolean)
Dim blnSent As Boolean
On Error Resume Next
blnSent = itm.Sent
If Err.Number = 0 Then
Debug.Print "not sent"
Else
openExcel
End If
End Sub
References:
Check to see if an Outlook Email was sent from Excel VBA
How can I use Outlook to send email to multiple recipients in Excel VBA
How to open an excel file in Outlook vba code
Create a new Outlook message using VBA
Run code after item sent
Just a quick 'n dirty function that will run in Excel/Access/Word and returns the email address from the most recent item in the Sent Items folder (no error handling, etc):
Function LastSentEmailAddress() As String
'Requires reference: "Microsoft Outlook xx.x Object Library"
Dim olApp As Outlook.Application, olMail As Object
Set olApp = New Outlook.Application 'create Outlook object
Set olMail = olApp.GetNamespace("MAPI").GetDefaultFolder(olFolderSentMail).Items.GetLast
LastSentEmailAddress = olMail.Recipients(1).PropertyAccessor.GetProperty( _
"http://schemas.microsoft.com/mapi/proptag/0x39FE001E") 'get email addy
olApp.Quit 'close Outlook
End Function
A Note about working with Outlook objects from Excel:
When working with applications such as Excel it's important to make sure the application object is properly .Quit / .Close'd when finished with them, (and to Set all objects to Nothing), otherwise there's a risk of inadvertently having multiple instances running, which can lead to memory leaks, which leads to crashes and potential data loss.
To check if there is an existing instance of Outlook, use this function:
Function IsOutlookOpen()
'returns TRUE if Outlook is running
Dim olApp As Outlook.Application
On Error Resume Next
Set olApp = GetObject(, "Outlook.Application")
On Error GoTo 0
If olApp Is Nothing Then
IsOutlookOpen= False
Else
IsOutlookOpen= True
End If
End Function
(Source: Rob de Bruin)
More Information:
MSDN : Items.GetLast Method (Outlook)
MSDN : Items Object (Outlook)
MSDN : Obtain the E-mail Address of a Recipient
Office.com : How to disable warnings about programmatic access to Outlook
MSDN : Chapter 17: Working with Item Bodies (Book Excerpt)
MSDN : Check or Add an Object Library Reference
Stack Overflow : VBA to search an Outlook 2010 mail in Sent Items from Excel
I am trying to update a shared calendar from an Excel sheet. The code works for the owner of this shared calendar, but it fails for me. The calendar was shared to me and I have full owner permissions.
I can edit the calendar manually, but the idea is that anyone will be able run the macro from this Excel sheet to update the shared calendar.
The relevant code, up to the failure point:
Sub UpdateSched()
Dim olApp As Outlook.Application
Dim olNameSpace As Outlook.Namespace
Dim olFolder As Outlook.MAPIFolder
Dim olFldrOwner As Outlook.Recipient
On Error Resume Next
' check if Outlook is running
Set olApp = GetObject("Outlook.Application")
If Err <> 0 Then
'if not running, start it
Set olApp = CreateObject("Outlook.Application")
End If
On Error GoTo 0
Set olNameSpace = olApp.GetNamespace("MAPI")
Set olFldrOwner = olNameSpace.CreateRecipient("ownrAlias")
olFldrOwner.Resolve
Set olFolder = Nothing
If olFldrOwner.Resolved Then
Set olFolder = olNameSpace.GetSharedDefaultFolder(olFldrOwner, olFolderCalendar)
' If olFolder Is Nothing Then
' Debug.Print "Nothing"
' Else
' Debug.Print olFolder.Name '<-Error here if the if-block is run
' End If
'******************************
Set olFolder = olFolder.Folders("Transport Sched") '<-Object Not Found Error
'******************************
End If
'Code below updates appointments on the shared calendar
The full error
'The attempted operation failed. An object could not be found'
For testing, I added the commented out block. This made me think that the error might be in the previous line. When this block is un-commented then the code errors out on the line after Else (same error). So the olFolder object is not nothing, but it can't be found.
It's under "Shared Calendars" I get the error. It updates a calendar I created, that's under "My Calendars."
Is it a problem with finding the correct folder for the shared calendar?
The path to the folder shouldn't change, so I could hard-code it so it works for everyone, is that possible?
I came up with a solution to my problem but in a completely different way than I was trying with the code listed in the question. In case anyone else needs it, here is the solution:
Sub ListCalendars()
Dim olApp As Outlook.Application
Dim olPane As Outlook.NavigationPane
Dim olModule As Outlook.CalendarModule
Dim olGroup As Outlook.NavigationGroup
Dim olNavFolder As Outlook.NavigationFolder
Dim olFolder As Folder
Dim i As Integer, j As Integer
On Error Resume Next
' check if Outlook is running
Set olApp = GetObject("Outlook.Application")
If Err <> 0 Then
'if not running, start it
Set olApp = CreateObject("Outlook.Application")
End If
On Error GoTo 0
Set olPane = olApp.ActiveExplorer.NavigationPane
Set olModule = olPane.Modules.GetNavigationModule(olModuleCalendar)
Set olGroup = olModule.NavigationGroups.GetDefaultNavigationGroup(olMyFoldersGroup)
'Dummy Do loop allows exit from within nested For-Next loops
Do
For i = 1 To olModule.NavigationGroups.Count 'Cycle through all Nav Groups
Set olGroup = olModule.NavigationGroups.Item(i)
Debug.Print olGroup.Name
For j = 1 To olGroup.NavigationFolders.Count 'Cycle through all calendars in group
Set olNavFolder = olGroup.NavigationFolders.Item(j)
Debug.Print " - " & olNavFolder.DisplayName
'Un-comment If-block below if searching for a particular calendar:
'CalendarName is the name of the calendar,as listed in your navigation pane
' If olNavFolder.DisplayName = "CalendarName" Then
' Debug.Print "Found it!"
' Set olFolder = olNavFolder.Folder 'To get folder object from NavigationFolder
' Exit Do
' End If
Next
Next
Exit Do 'To prevent endless loop
Loop While True
'If-block below displays results if looking for matching calendar name
'If olFolder Is Nothing Then
' Debug.Print vbNewLine & "No match found"
'Else
' Debug.Print vbNewLine & "Matching calendar found: " & olFolder.Name
'End If
End Sub
This code was modified from this page here. Basically, accessing someone else's calendar folder object directly gave me issues, even if the calendar had been shared. By using the various navigation objects though, I was able to cycle through all the calendars listed in my navigation pane, including all the shared calendars.
As provided this routine merely lists the main folders and one level of subfolders. If the two if-blocks are uncommented then the routine will search for the calendar with a given name(just replace CalendarName) and will display whether or not a match was found.
The dummy Do loop was one way to break out of nested loops. There's multiple other ways to accomplish this listed in this SO question.
One other tricky thing is that NavigationFolder objects are NOT the same as Folder objects. This seemingly inconsequential line:
Set olFolder = olNavFolder.Folder
is actually very important if you want to make changes to the calendar folder, since these two object types have different properties and methods.
The code below deletes appointments in a subfolder of the Outlook default calendar. I have commented out the line giving the run-time error 462: "The remote server machine does not exist or is unavailable".
Is there a change I could make to this code to solve this error? Thanks for any guidance.
Public Sub DeleteAppt()
Dim olApp As Object 'Outlook.Application
Dim olNS As Object 'Outlook.Namespace
Dim olAptItemFolder As Object 'Outlook.Folder
Dim olAptItem As Object 'Outlook.AppointmentItem
Dim i As Long
Set olApp = CreateObject("Outlook.Application")
Set olNS = olApp.Session
Set olAptItemFolder = olNS.GetDefaultFolder(olFolderCalendar).Folders("TestCal")
''''For i = olAptItemFolder.Count To 1 Step -1
Set olAptItem = olAptItemFolder.Items(i)
If olAptItem.Subject Like "***" Then
olAptItem.Delete
End If
Next i
Set olAptItem = Nothing
Set olAptItemFolder = Nothing
Set olApp = Nothing
End Sub
olAptItemFolder has no Count property. olAptItemFolder.Items does. Apart from the issues others noted in comments above, try
For i = olAptItemFolder.Items.Count To 1 Step -1
Edited to add: if you are not setting a reference to something's object lirary, you can't use its enums unless you fully qualify each use. It's generally simpler, easier and quicker to find out the numerical value of the enum and use that instead. Then add a comment on the end of the line to remind yoursef, six months from now, that '9 = olFolderCalendar
I'm really new at VBA but I have this same code in another database, and now I've just copied the code and paste in another database but I get this Object Required error in the last line.
The code is bigger but I've just stopped on the line where I get the error.
Dim frm As Form, ctl As Control
Dim varItm As Variant
Dim stgMO, stgPID, stMail, stgMailCC As String
Dim Question As Long
Dim OutApp, OutMail As Object
Set frm = Forms!Overview
Set ctl = frm!cl_onboarding
stgMO = ctl.Column(7)
stgPID = ctl.Column(2)
stgMail = ctl.Column(8)
stgMailCC = ctl.Column(9)
Question = MsgBox("Do you want to send an e-mail containing the codes for this Agent?", vbYesNo, "Send e-mail")
If Question = vbYes Then
Set OutApp = Outlook.Application
you have dim stMail as a variable but then you use stgMail. just check your spelling.
You also use dim question as long, this confuses me a bit because I thought long meant an integer (there are min and max values but I cant remember).
You need to set a Reference in VBA to Outlook.
VBA editor -> menu Tools -> References
Select and check Microsoft Outlook 14.0 Object Library
Edit: while the above is true, you would probably get a different error if the reference was missing.
The problem may be in this line:
Dim OutApp, OutMail As Object
which actually gets evaluated as
Dim OutApp As Variant, OutMail As Object
and should read
Dim OutApp As Object, OutMail As Object
But a Variant can hold an object too, so this may also not be the cause of the error.