Extract email address from outlook for a list of employee ids - vba

I am almost done with the code, however I'm only able to pull a single employee ID id. Refer to the code below:
Private Sub CommandButton24_Click()
Dim outApp As Object 'Application
Dim outTI As Object 'TaskItem
Dim outRec As Object 'Recipient
Dim outAL As Object 'AddressList
Set outApp = GetObject(, "Outlook.Application")
Set outAL = outApp.Session.AddressLists.Item("Global Address List")
Set outTI = outApp.CreateItem(3)
outTI.Assign
Set outRec = outTI.Recipients.Add(Range("A2").Value)
outRec.Resolve
If outRec.Resolved Then
Range("B2").Value = outAL.AddressEntries(outRec.AddressEntry.Name).GetExchangeUser.PrimarySmtpAddress
Else
MsgBox "Couldn't find Employee"
End If
End Sub
Looks like some changes need to be made in this code so that I can extract email address from the list.
Set outRec = outTI.Recipients.Add(Range("A2").Value)

If your list is on Column A then Try looping through column
Example
Option Explicit
Private Sub CommandButton24_Click()
Dim olApp As Object 'Application
Dim olTaskItem As Object 'TaskItem
Dim olRecip As Object 'Recipient
Dim olAddList As Object 'AddressList
Set olApp = GetObject(, "Outlook.Application")
Set olAddList = olApp.Session.AddressLists.Item("Global Address List")
Set olTaskItem = olApp.CreateItem(3)
Dim i As Long
For i = 1 To Range("A" & Rows.Count).End(xlUp).Row
olTaskItem.Assign
Set olRecip = olTaskItem.Recipients.Add(Cells(i, 1).Value)
olRecip.Resolve
If olRecip.Resolved Then
Cells(i, 2).Value = olAddList.AddressEntries(olRecip.AddressEntry.Name).GetExchangeUser.PrimarySmtpAddress
Else
MsgBox "Couldn't find Employee"
End If
Next i
End Sub

Related

How to identify emails where sender is also a recipient?

I'm trying to export sender email address and recipient email addresses (to and cc) to Excel. I adapted code I found online. It does most of what I need but there are two problems:
It only works with a single recipient. If there are two or more recipients, it provides names (e.g. Jo Bloggs) instead of email addresses.
It only includes people in the 'To' field, not those in the 'CC' field.
I think the bit that needs fixing is:
'trying to get recipient email address
Dim olEU2 As Outlook.ExchangeUser
Dim oEDL2 As Outlook.ExchangeDistributionList
Dim recip2 As Outlook.Recipient
Set recip2 = Application.Session.CreateRecipient(strColE)
Select Case recip2.AddressEntry.AddressEntryUserType
Case OlAddressEntryUserType.olExchangeUserAddressEntry
Set olEU2 = recip.AddressEntry.GetExchangeUser
If Not (olEU2 Is Nothing) Then
strColE = olEU2.PrimarySmtpAddress
End If
Case OlAddressEntryUserType.olOutlookContactAddressEntry
Set olEU2 = recip.AddressEntry.GetExchangeUser
If Not (olEU2 Is Nothing) Then
strColE = olEU2.PrimarySmtpAddress
End If
Case OlAddressEntryUserType.olExchangeDistributionListAddressEntry
Set oEDL2 = recip.AddressEntry.GetExchangeDistributionList
If Not (oEDL2 Is Nothing) Then
strColE = olEU2.PrimarySmtpAddress
End If
End Select
Full code:
Option Explicit
Sub CopyToExcel()
Dim xlApp As Object
Dim xlWB As Object
Dim xlSheet As Object
Dim rCount As Long
Dim bXStarted As Boolean
Dim enviro As String
Dim strPath As String
Dim objOL As Outlook.Application
Dim objFolder As Outlook.MAPIFolder
Dim objItems As Outlook.Items
Dim obj As Object
Dim olItem 'As Outlook.MailItem
Dim strColA, strColB, strColC, strColD, strColE, strColF As String
' Get Excel set up
enviro = CStr(Environ("USERPROFILE"))
'the path of the workbook
strPath = enviro & "\Documents\Book1.xlsx"
On Error Resume Next
Set xlApp = GetObject(, "Excel.Application")
If Err <> 0 Then
Application.StatusBar = "Please wait while Excel source is opened ... "
Set xlApp = CreateObject("Excel.Application")
bXStarted = True
End If
On Error GoTo 0
On Error Resume Next
' Open the workbook to input the data
' Create workbook if doesn't exist
Set xlWB = xlApp.Workbooks.Open(strPath)
If Err <> 0 Then
Set xlWB = xlApp.Workbooks.Add
xlWB.SaveAs FileName:=strPath
End If
On Error GoTo 0
Set xlSheet = xlWB.Sheets("Sheet1")
On Error Resume Next
' add the headers if not present
If xlSheet.Range("A1") = "" Then
xlSheet.Range("A1") = "Sender Name"
xlSheet.Range("B1") = "Sender Email"
xlSheet.Range("C1") = "Subject"
xlSheet.Range("D1") = "Body"
xlSheet.Range("E1") = "Sent To"
xlSheet.Range("F1") = "Date"
End If
'Find the next empty line of the worksheet
rCount = xlSheet.Range("B" & xlSheet.Rows.Count).End(-4162).Row
'needed for Exchange 2016. Remove if causing blank lines.
rCount = rCount + 1
' get the values from outlook
Set objOL = Outlook.Application
Set objFolder = objOL.ActiveExplorer.CurrentFolder
Set objItems = objFolder.Items
For Each obj In objItems
Set olItem = obj
'collect the fields
strColA = olItem.SenderName
strColB = olItem.SenderEmailAddress
strColC = olItem.Subject
strColD = olItem.Body
strColE = olItem.To
strColF = olItem.ReceivedTime
' Get the Exchange address
' if not using Exchange, this block can be removed
Dim olEU As Outlook.ExchangeUser
Dim oEDL As Outlook.ExchangeDistributionList
Dim recip As Outlook.Recipient
Set recip = Application.Session.CreateRecipient(strColB)
If InStr(1, strColB, "/") > 0 Then
' if exchange, get smtp address
Select Case recip.AddressEntry.AddressEntryUserType
Case OlAddressEntryUserType.olExchangeUserAddressEntry
Set olEU = recip.AddressEntry.GetExchangeUser
If Not (olEU Is Nothing) Then
strColB = olEU.PrimarySmtpAddress
End If
Case OlAddressEntryUserType.olOutlookContactAddressEntry
Set olEU = recip.AddressEntry.GetExchangeUser
If Not (olEU Is Nothing) Then
strColB = olEU.PrimarySmtpAddress
End If
Case OlAddressEntryUserType.olExchangeDistributionListAddressEntry
Set oEDL = recip.AddressEntry.GetExchangeDistributionList
If Not (oEDL Is Nothing) Then
strColB = olEU.PrimarySmtpAddress
End If
End Select
End If
' End Exchange section
'trying to get recipient email address
Dim olEU2 As Outlook.ExchangeUser
Dim oEDL2 As Outlook.ExchangeDistributionList
Dim recip2 As Outlook.Recipient
Set recip2 = Application.Session.CreateRecipient(strColE)
Select Case recip2.AddressEntry.AddressEntryUserType
Case OlAddressEntryUserType.olExchangeUserAddressEntry
Set olEU2 = recip.AddressEntry.GetExchangeUser
If Not (olEU2 Is Nothing) Then
strColE = olEU2.PrimarySmtpAddress
End If
Case OlAddressEntryUserType.olOutlookContactAddressEntry
Set olEU2 = recip.AddressEntry.GetExchangeUser
If Not (olEU2 Is Nothing) Then
strColE = olEU2.PrimarySmtpAddress
End If
Case OlAddressEntryUserType.olExchangeDistributionListAddressEntry
Set oEDL2 = recip.AddressEntry.GetExchangeDistributionList
If Not (oEDL2 Is Nothing) Then
strColE = olEU2.PrimarySmtpAddress
End If
End Select
'write them in the excel sheet
xlSheet.Range("A" & rCount) = strColA
xlSheet.Range("B" & rCount) = strColB
xlSheet.Range("c" & rCount) = strColC
xlSheet.Range("d" & rCount) = strColD
xlSheet.Range("e" & rCount) = strColE
xlSheet.Range("f" & rCount) = strColF
'Next row
rCount = rCount + 1
xlWB.Save
Next
' don't wrap lines
xlSheet.Rows.WrapText = False
xlWB.Save
xlWB.Close 1
If bXStarted Then
xlApp.Quit
End If
Set olItem = Nothing
Set obj = Nothing
Set xlApp = Nothing
Set xlWB = Nothing
Set xlSheet = Nothing
End Sub
Iterating through all items in the folder is not really a good idea. I'd recommend starting from the Find/FindNext or Restrict methods instead. Please note that there are some item properties that you can’t use for the filter. You can read more about the properties not allowed in the filter string and string formats used for the search criterion on MSDN.
The following example uses the Restrict method to get all Inbox items of Business category and moves them to the Business folder. To run this example, create or make sure a subfolder called 'Business' exists under Inbox:
Sub MoveItems()
Dim myNamespace As Outlook.NameSpace
Dim myFolder As Outlook.Folder
Dim myItems As Outlook.Items
Dim myRestrictItems As Outlook.Items
Dim myItem As Outlook.MailItem
Set myNamespace = Application.GetNamespace("MAPI")
Set myFolder = _
myNamespace.GetDefaultFolder(olFolderInbox)
Set myItems = myFolder.Items
Set myRestrictItems = myItems.Restrict("[Categories] = 'Business'")
For i = myRestrictItems.Count To 1 Step -1
myRestrictItems(i).Move myFolder.Folders("Business")
Next
End Sub
Also, you may find the AdvancedSearch method of the Application class helpful. The key benefits of using the AdvancedSearch method in Outlook are:
The search is performed in another thread. You don’t need to run another thread manually since the AdvancedSearch method runs it automatically in the background.
Possibility to search for any item types: mail, appointment, calendar, notes etc. in any location, i.e. beyond the scope of a certain folder. The Restrict and Find/FindNext methods can be applied to a particular Items collection (see the Items property of the Folder class in Outlook).
Full support for DASL queries (custom properties can be used for searching too). You can read more about this in the Filtering article in MSDN. To improve the search performance, Instant Search keywords can be used if Instant Search is enabled for the store (see the IsInstantSearchEnabled property of the Store class).
You can stop the search process at any moment using the Stop method of the Search class.
Please remember that you can set a suitable filter (View | View Settings |filter) on a folder and study the filter string on the SQL tab of the Filter dialog. Then you can construct any required filter string in the code.
If woudl be nice to use Items.Find/FindNext or Items.Restrict, but I cannot think of a query that would let you do what you want. If it is a one time thing, you have no choice but to loop through all items in a folder and for each item loop through all recipients and compare each recipient's entry id (Recipient.EntryID) with the sender entry id (MailItem.Sender.EntryId).

MS-Word 2010 - Macro to export table to Outlook Tasks

I'm trying to create a macro in MS-Word VBA to take the contents of a MS-Word table (with a bookmarked name), iterate through the rows of the table and create tasks in MS-Outlook (1 row=1 task).
I have Googled and think I will need to try and mix together the following two scripts I have found:
Script 1 - (For making calendar entries - not wanted, but iteration through rows - wanted)
Sub AddAppntmnt()
'Adds a list of events contained in a three column Word table
'with a header row, to Outlook Calendar
Dim olApp As Object
Dim olItem As Object
Dim oTable As Table
Dim i As Long
Dim bStarted As Boolean
Dim strStartDate As Range
Dim strEndDate As Range
Dim strSubject As Range
On Error Resume Next
Set olApp = GetObject(, "Outlook.Application")
If Err <> 0 Then
Set olApp = CreateObject("Outlook.Application")
bStarted = True
End If
Set oTable = ActiveDocument.Tables(1)
'Ignore the first (header) row of the table
For i = 2 To oTable.Rows.Count
Set strStartDate = oTable.Cell(i, 1).Range
strStartDate.End = strStartDate.End - 1
Set strEndDate = oTable.Cell(i, 2).Range
strEndDate.End = strEndDate.End - 1
Set strSubject = oTable.Cell(i, 3).Range
strSubject.End = strSubject.End - 1
Set olItem = olApp.CreateItem(1)
olItem.Start = strStartDate
olItem.End = strEndDate
olItem.ReminderSet = False
olItem.AllDayEvent = True
olItem.Subject = strSubject
olItem.Categories = "Events"
olItem.BusyStatus = 0
olItem.Save
Next i
If bStarted Then olApp.Quit
Set olApp = Nothing
Set olItem = Nothing
Set oTable = Nothing
End Sub
Script 2 - has the actual task creation bit I think I need although this one is about setting task to remind user to do something in 2 weeks or something:
Sub AddOutlookTask()
Dim olApp As Object
Dim olItem As Object
Dim bStarted As Boolean
Dim fName As String
Dim flName As String
On Error Resume Next
If ActiveDocument.Saved = False Then
ActiveDocument.Save
If Err.Number = 4198 Then
MsgBox "Process ending - document not saved!"
GoTo UserCancelled:
End If
End If
Set olApp = GetObject(, "Outlook.Application")
If Err <> 0 Then
'Outlook wasn't running, start it from code
Set olApp = CreateObject("Outlook.Application")
bStarted = True
End If
Set olItem = olApp.CreateItem(3) 'Task Item
fName = ActiveDocument.name
flName = ActiveDocument.FullName
olItem.Subject = "Follow up " & fName
olItem.Body = "If no reply to" & vbCr & _
flName & vbCr & "further action required"
olItem.StartDate = Date + 10 '10 days from today
olItem.DueDate = Date + 14 '14 days from today
olItem.Importance = 2 'High
olItem.Categories = InputBox("Category?", "Categories")
olItem.Save
UserCancelled:
If bStarted Then olApp.Quit
Set olApp = Nothing
Set olItem = Nothing
End Sub
How do I reference a particular table in MS-Word in code? I have bookmarked it so it has a "name" if that helps!
With Davids help (above) I have got the following solution to my problem. I post here for others if they come across a similar issue:
Sub CreateTasks()
'
' CreateTasks Macro
'
'
'
'Exports the contents of the ACtoins table to MS-Outlook Tasks
' Set Variables
Dim olApp As Object
Dim olItem As Object
Dim oTable As Table
Dim i As Long
Dim strSubject As Range
Dim strDueDate As Range
Dim strBody As Range
Dim strSummary As String
Dim bStarted As Boolean
'Dim strPupil As WdBookmark
Dim strPerson As Range
'Link to Outlook
On Error Resume Next
Set olApp = GetObject(, "Outlook.Application")
If Err <> 0 Then
Set olApp = CreateObject("Outlook.Application")
bStarted = True
End If
'Set table variable to the bookmarked table
Set oTable = ActiveDocument.Bookmarks("Actions").Range.Tables(1)
'Ignore the first (header) row of the table
For i = 3 To oTable.Rows.Count
Set strSubject = oTable.Cell(i, 3).Range
strSubject.End = strSubject.End - 1
Set strBody = oTable.Cell(i, 4).Range
strBody.End = strBody.End - 1
Set strDueDate = oTable.Cell(i, 5).Range
strDueDate.End = strDueDate.End - 1
'next line not working below
'Set strPupil = WdBookmark.Name
'Create the task
Set olItem = olApp.CreateItem(3) 'Task Item
strSummary = Left(strSubject, 30)
olItem.Subject = "CYPP Action for" & " " & strBody & "-" & strSummary & "..."
olItem.Body = strBody & vbNewLine & olItem.Body & vbNewLine & strSubject
olItem.DueDate = strDueDate & olItem.DueDate
olItem.Categories = "CYPP"
olItem.Save
Next i
If bStarted Then olApp.Quit
Set olApp = Nothing
Set olItem = Nothing
Set oTable = Nothing
End Sub
I will be adding to this to deal with empty rows but I am pleased with the functionality so far. The DateDue is not working yet but I think that is a formatting issue.
Thanks again David,
Richard.

Choose email subject from dropdown list of excel column

I have code for emails and I want to connect to a column in an excel. When the macro is triggered, a dropdown should appear so I can choose to how to send the email depending on a list in an excel. The list is generated from other excels, it could have 2 full names or 40 full names. The list is in Sheet4 and the names are in column L, the email address is in column Q and the text in column P. If I choose from the dropdown, the name in L2, it should take the email address from Q2, the name from L2 and the text from P2. Here is what I have until now:
Sub email_to_one_person_from_the_list()
Dim OutApp As Object
Dim OutMail As Object
Dim xlApp As Object
Dim sourceWB As Object
Dim sourceWS As Object
Set xlApp = CreateObject("Excel.Application")
strFile = "C:\persons.xlsm"
Set sourceWB = xlApp.Workbooks.Open(strFile, , False, , , , , , , True)
Set sourceWH = sourceWB.Worksheets("Sheet4")
sourceWB.Activate
sourceWH.Application.Run "Module2.FetchData3"
On Error Resume Next
Set OutApp = GetObject(, "Outlook.Application")
If Err <> 0 Then Set OutApp = CreateObject("Outlook.Application")
On Error GoTo 0
Set OutMail = OutApp.CreateItem(0)
With OutMail
.To = sourceWH.Range("Q2").Value
.CC = ""
.BCC = ""
.Subject = "Dear " & sourceWH.Range("L2").Value
.Display
OutMail.HTMLBody = sourceWH.Range("P2").Value
sourceWB.Close SaveChanges:=False
xlApp.Quit
Set OutMail = Nothing
Set OutApp = Nothing
End Sub
and the combobox:
Private Sub CancelButton_Click()
Unload Me
End
End Sub
Private Sub OKButton_Click()
thelist1 = ComboBox1.ListIndex
Unload Me
End Sub
Private Sub UserForm_Initialize()
With ComboBox1
' the excel list here
End With
End Sub
edited after OP's usage of my original code and further clarifications
here follows a complete refactoring code as per the following "rules"
Option Explicitstatement
this forces you to declare all variables
but this little extra work but earns you back with much more control over what your writing and less debugging and/or maintenance efforts
main "mega" code splitting into many single Sub/Funcs
this helps in
have more readable and maintainable code
keeping Userforms and Applications loading and unloading calls away from any UserForm code, which must only take care of its real work: gather information
place this in your Outlook Module:
Option Explicit
Sub email_DP2()
Dim mailData As Variant
mailData = GetMailDataFromExcel("C:\persons.xlsm", _
"Module2.FetchData3", _
"Sheet4", _
"L")
If mailData = Empty Then Exit Sub
With CreateItem(0)
.SentOnBehalfOfName = ""
.Importance = olImportanceHigh
.To = mailData(1)
.Subject = mailData(0)
.GetInspector.WordEditor.Range.collapse 1
.Display
.HTMLBody = mailData(2)
'.Paste 'what are you pasting from?
End With
End Sub
'-------------------------------------------------------
' Excel handling Subs and Funcs
'-------------------------------------------
Function GetMailDataFromExcel(strFile As String, fetchingModule As String, strSheet As String, colStrng As String) As Variant
Dim xlApp As Excel.Application
Dim closeExcel As Boolean
Dim namesRng As Excel.Range
Set xlApp = GetExcel(closeExcel)
If Not xlApp Is Nothing Then
Set namesRng = GetExcelRange(xlApp, strFile, fetchingModule, strSheet, colStrng) 'this will get the names range from given column of given worksheet of given workbook
With UserForm14
If namesRng.Count = 1 Then
.ComboBox1.AddItem namesRng.Value
Else
.ComboBox1.List = xlApp.Transpose(namesRng)
End If
.Show
With .ComboBox1
If .ListIndex > -1 Then GetMailDataFromExcel = Array(.Value, _
namesRng.Offset(, 5).Cells(.ListIndex + 1, 1).Value, _
namesRng.Offset(, 6).Cells(.ListIndex + 1, 1).Value)
End With
End With
Unload UserForm14
Set namesRng = Nothing
ReleaseExcel xlApp, closeExcel
End If
End Function
Function GetExcelRange(xlApp As Excel.Application, strFile As String, fetchingModule As String, strSheet As String, colStrng As String) As Excel.Range
With xlApp.Workbooks.Open(strFile, , False, , , , , , , True)
xlApp.Run fetchingModule
With .Worksheets(strSheet)
Set GetExcelRange = .Columns(colStrng).Resize(.Cells(.Rows.Count, colStrng).End(xlUp).Row)
End With
End With
End Function
Function GetExcel(closeExcel As Boolean) As Excel.Application
On Error Resume Next
Set GetExcel = GetObject(, "Excel.Application")
If GetExcel Is Nothing Then
Set GetExcel = CreateObject("Excel.Application")
closeExcel = True
End If
If GetExcel Is Nothing Then
MsgBox "Couldn't instantiate Excel!", vbCritical
End If
End Function
Sub ReleaseExcel(xlApp As Excel.Application, closeExcel As Boolean)
If closeExcel Then xlApp.Quit
Set xlApp = Nothing
End Sub
'-------------------------------------------------------
place this in your UserForm14 code pane
Option Explicit
Private Sub btnOK_Click()
Me.Hide
End Sub
Private Sub CancelButton_Click()
Me.Hide
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = vbFormControlMenu Then
Cancel = True
Me.Hide
End If
End Sub
in this latter I
added Option Explicit statement
although not strictly necessary (there is no variables usage but "built in" ones), it builds on a good habit
added a UserForm_QueryCloseevent handler
that handles the possible user's clicking the UserForm "Close" button
erased the End statement
I always learned it's a bad habit to use it and better stick to Exit Sub/Exit Function ones (possibly with proper mix of If.. Then.. Else blocks) to achieve the same effect without any harm
To connect your Outlook to Excel, you first have to add a reference to "Microsoft Excel XX Object Library" where XX is some version number (Extras->References)
Then create a userform, mine looks like this:
Note that my combobox has 2 columns (first one has a width of 0 so it's invisible)
Then, when you are loading the Form, add code to open an Excel instance and load the combobox with values to select from:
Private Sub UserForm_Initialize()
'Define Excel-Variables
Dim xlApp As Excel.Application
Dim xlWB As Excel.Workbook
Dim xlSheet As Excel.Worksheet
'Create Excel Instance
Set xlApp = New Excel.Application
'Make it invisible
xlApp.Visible = False
'Open Workbook with Values
Set xlWB = xlApp.Workbooks.Open("PATH TO YOUR EXCEL FILE")
'Select the Sheet with Values
Set xlSheet = xlWB.Worksheets("sheet1")
Dim i As Integer
'Loop through the Values
For i = 1 To 30 Step 1
'This Combobox has 2 Columns where 1 is the bound one
'Add RowIndex to the first column(will be used to find the values later)
Me.cboTest.AddItem i
'Add the Name to the second Column
Me.cboTest.List(Me.cboTest.ListCount - 1, 1) = xlSheet.Cells(i, 1).Value
Next i
'Clean up and close Excel
Set xlSheet = Nothing
xlWB.Close False
xlApp.Quit
Set xlWB = Nothing
Set xlApp = Nothing
End Sub
Then you need to add some code to the button:
Private Sub cmdSend_Click()
'variables for the values we are getting now
Dim name As String, email As String, text As String
'more excel variables
Dim xlApp As Excel.Application
Dim xlWB As Excel.Workbook
Dim xlSheet As Excel.Worksheet
Set xlApp = New Excel.Application
xlApp.Visible = False
Set xlWB = xlApp.Workbooks.Open("PATH TO EXCEL FILE")
Set xlSheet = xlWB.Worksheets("sheet1")
'access the rowindex from the first column of the combobox
'use it for the Cells() as row
'column may be edited as needed
name = xlSheet.Cells(Me.cboTest.List(Me.cboTest.ListIndex, 0), 1).Value
email = xlSheet.Cells(Me.cboTest.List(Me.cboTest.ListIndex, 0), 2).Value
text = xlSheet.Cells(Me.cboTest.List(Me.cboTest.ListIndex, 0), 3).Value
'excel cleanup
Set xlSheet = Nothing
xlWB.Close False
xlApp.Quit
Set xlWB = Nothing
Set xlApp = Nothing
'print output to console
'instead of this, write your email
Debug.Print "mailto:" & email & " name:" & name & " text: " & text
End Sub
Then, if we open the form, we can select from the values:
If we then click the button, it will open excel and get the relevant values of the item we have selected.
Output for Name5 looks like this:
By the way, my excel example list looks like this:
#user3598756
I made the config with your code:
userform14 code:"
Private Sub btnOK_Click()
Me.Hide
End Sub
Private Sub CancelButton_Click()
Me.Hide
End
End Sub
Private Sub UserForm_Click()
End Sub
and the function code:
Sub email_DP2()
Dim name As String, email As String, text As String
Dim OutApp As Object
Dim OutMail As Object
Dim olInsp As Object
Dim oRng As Object
Dim StrBdB As String
Dim xlApp As Object
Dim sourceWB As Object
Dim sourceWS As Object
Set xlApp = CreateObject("Excel.Application")
strFile = "C:\persons.xlsm"
Set sourceWB = xlApp.Workbooks.Open(strFile, , False, , , , , , , True)
Set sourceWH = sourceWB.Worksheets("Sheet4")
sourceWH.Application.Run "Module2.FetchData3"
Dim pickedName As String, emailAddress As String, emailText As String
Dim namesRng As Range
With sourceWH '<== change "myWorkbookName" and "Sheet4" to your needs
Set namesRng = .Range("L1:L" & .Cells(.Rows.Count, "L").End(xlUp).Row)
End With
With UserForm14 ' change it to whatever name your actual UserForm has
.ComboBox1.List = xlApp.Transpose(namesRng)
.Show
With ComboBox1
pickedName = .Value
emailAddress = namesRng.Offset(, 5).Cells(.ListIndex + 1, 1).Value
emailText = namesRng.Offset(, 6).Cells(.ListIndex + 1, 1).Value
End With
End With
Unload UserForm14
On Error Resume Next
Set OutApp = GetObject(, "Outlook.Application")
If Err <> 0 Then Set OutApp = CreateObject("Outlook.Application")
On Error GoTo 0
Set OutMail = OutApp.CreateItem(0)
With OutMail
OutMail.SentOnBehalfOfName = ""
.Importance = olImportanceHigh
.To = emailAddress
.Subject = pickedName
Set olInsp = .GetInspector
Set wdDoc = olInsp.WordEditor
Set oRng = wdDoc.Range
oRng.collapse 1
.Display
OutMail.HTMLBody = emailText
oRng.Paste
End With
Set OutMail = Nothing
Set OutApp = Nothing
Set olInsp = Nothing
Set wdDoc = Nothing
Set oRng = Nothing
End Sub
It gives object required on line pickedName = .Value - if i eliminate the line it will give the same at line emailAddress = namesRng.Offset ... I thing is a problem with With ComboBox1 - if i eliminate with , it will generate an email but without the to, subject and text added to it.

parse the body of an eml file in vba excel

My ultimate goal is to open an eml file in Excel vba and end up with the body of the message in a string that I can then use to search for different parameters. I've found a solution using MailItem and an Outlook application, however the machine I'm working on errors out when running this code:
Set MyOutlook = New Outlook.Application
Set x = MyOutlook.GetNamespace("MAPI")
Outlook 2013 opens, but then gives me an error message saying OLMAPI32.dll and then crashes. Eventually, I receive error 429 "ActiveX component can't create object."
I would like either a solution to this error or a workaround way to get the body of an eml file into a string. I've been successful at getting the subject of the email by using this code:
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objRegEx = CreateObject("VBScript.RegExp")
objRegEx.Pattern = "^Subject:"
Do Until objFile.AtEndOfStream
strSearchString = objFile.ReadLine
Set colMatches = objRegEx.Execute(strSearchString)
If colMatches.Count > 0 Then
Cells(i, n) = strSearchString
i = i + 1
Exit Do
End If
Loop
However, from examining a few random eml files, it doesn't appear like there is a way to flag the body of the text like I can with the subject.
Disregard the i and n, its not really relevant for this question. I'm just placing the subject in a cell determined elsewhere.
Any help is appreciated. Thanks!
Have you tried using the .Body function? This article may help.
Note that this code is performed inside of Outlook, not Excel.
Sub ExportToExcel(MyMail As MailItem) Dim strID As String, olNS As Outlook.Namespace Dim olMail As Outlook.MailItem Dim strFileName As String
'~~> Excel Variables
Dim oXLApp As Object, oXLwb As Object, oXLws As Object
Dim lRow As Long
strID = MyMail.EntryID
Set olNS = Application.GetNamespace("MAPI")
Set olMail = olNS.GetItemFromID(strID)
'~~> Establish an EXCEL application object
On Error Resume Next
Set oXLApp = GetObject(, "Excel.Application")
'~~> If not found then create new instance
If Err.Number <> 0 Then
Set oXLApp = CreateObject("Excel.Application")
End If
Err.Clear
On Error GoTo 0
'~~> Show Excel
oXLApp.Visible = True
'~~> Open the relevant file
Set oXLwb = oXLApp.Workbooks.Open("C:\Sample.xls")
'~~> Set the relevant output sheet. Change as applicable
Set oXLws = oXLwb.Sheets("Sheet1")
lRow = oXLws.Range("A" & oXLApp.Rows.Count).End(xlUp).Row + 1
'~~> Write to outlook
With oXLws
'
'~~> Code here to output data from email to Excel File
'~~> For example
'
.Range("A" & lRow).Value = olMail.Subject
.Range("B" & lRow).Value = olMail.SenderName
.Range("C" & lRow).Value = olMail.Body
'.Range("C" & lRow).Value = olMail.HTMLBody
'
End With
'~~> Close and Clean up Excel
oXLwb.Close (True)
oXLApp.Quit
Set oXLws = Nothing
Set oXLwb = Nothing
Set oXLApp = Nothing
Set olMail = Nothing
Set olNS = Nothing
End Sub

Outlook 2010 GAL with Excel VBA

I have the following code to get contacts out of Outlook from Excel:
Public Sub GetGAL()
Dim olApp As Outlook.Application
Dim olNs As Outlook.Namespace
Dim olFldr As Outlook.Items
Dim olContact As Outlook.ContactItem
Set olApp = CreateObject("Outlook.Application.14")
Set olNs = olApp.GetNamespace("MAPI")
Set olFldr = olNs.GetDefaultFolder(olFolderContacts).Items
For Each olContact In olFldr
Debug.Print olContact.FullName
Next olContact
End
End Sub
It is failing on this line saying there is a type mismatch:
For Each olContact In olFldr
Does anyone know why this is?
Also, how do I access the GAL as opposed to just my own contacts?
Thanks for any help.
Edit: Here's my new code to access the addressEntry and ExchangeUser, however, not the country field yet:
Option Explicit
Public Sub GetGAL()
Application.ScreenUpdating = False
Dim olApp As Outlook.Application
Dim olNs As Outlook.Namespace
Dim olGAL As Outlook.addressEntries
Dim olAddressEntry As Outlook.addressEntry
Dim olUser As Outlook.ExchangeUser
Dim i As Long
'Dim sTemp As String
'Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets(1)
Set olApp = CreateObject("Outlook.Application.14")
Set olNs = olApp.GetNamespace("MAPI")
Set olGAL = olNs.addressLists("Global Address List").addressEntries
'On Error Resume Next
For i = 1 To olGAL.Count
Set olAddressEntry = olGAL.Item(i)
If olAddressEntry.DisplayType = olRemoteUser Then
Set olUser = olAddressEntry.GetExchangeUser
'Debug.Print olUser.Name & ";" & olUser.StateOrProvince
'Debug.Print sTemp
'ws.Cells(i, 1) = olUser.Name
'ws.Cells(i, 2) = olUser.StateOrProvince
End If
Next i
End
Application.ScreenUpdating = True
End Sub
Give this a try. Although if you have tons and tons of entries in your GAL, it will take awhile to complete, and you may have to increase the 65000.
Sub tgr()
Dim appOL As Object
Dim oGAL As Object
Dim oContact As Object
Dim oUser As Object
Dim arrUsers(1 To 65000, 1 To 2) As String
Dim UserIndex As Long
Dim i As Long
Set appOL = CreateObject("Outlook.Application")
Set oGAL = appOL.GetNameSpace("MAPI").AddressLists("Global Address List").AddressEntries
For i = 1 To oGAL.Count
Set oContact = oGAL.Item(i)
If oContact.AddressEntryUserType = 0 Then
Set oUser = oContact.GetExchangeUser
If Len(oUser.lastname) > 0 Then
UserIndex = UserIndex + 1
arrUsers(UserIndex, 1) = oUser.Name
arrUsers(UserIndex, 2) = oUser.PrimarySMTPAddress
End If
End If
Next i
appOL.Quit
If UserIndex > 0 Then
Range("A2").Resize(UserIndex, UBound(arrUsers, 2)).Value = arrUsers
End If
Set appOL = Nothing
Set oGAL = Nothing
Set oContact = Nothing
Set oUser = Nothing
Erase arrUsers
End Sub
Your code assumes that you can only have ContactItem objects in the folder. It will break if you encounter an object of type DistListItem.
Declare the item variable as a generic Object, then check the Class property (exposed by all Outlook objects) or use TypeName function to figure out the exact item type.
EDIT: PR_BUSINESS_ADDRESS_COUNTRY DASL name is "http://schemas.microsoft.com/mapi/proptag/0x3A26001F"
For address entries you can see the DASS property names in OutlookSpy (I am its author). For example, you can click IMAPISession button, click QueryIdentity, select a property, look at the DASL edit box.