Exporting "To" addresses of incoming Outlook email - excel

I've been trying to export details about my incoming emails to an Excel spreadsheet. The code works as it should except for returning display names for the recipients in the "To" and "CC" fields.
I tried several variations.
I'm using the below code that I found online:
Public WithEvents objMails As Outlook.Items
Private Sub Application_Startup()
Set objMails = Outlook.Application.Session.GetDefaultFolder(olFolderInbox).Items
End Sub
Private Sub objMails_ItemAdd(ByVal Item As Object)
Dim objMail As Outlook.MailItem
Dim Recipient As Outlook.Recipient
Dim strExcelFile As String
Dim objExcelApp As Excel.Application
Dim objExcelWorkBook As Excel.Workbook
Dim objExcelWorkSheet As Excel.Worksheet
Dim nNextEmptyRow As Integer
Dim strColumnB As String
Dim strColumnC As String
Dim strColumnD As String
Dim strColumnE As String
Dim strColumnF As String
Dim strColumnG As String
If Item.Class = olMail Then
Set objMail = Item
End If
'Specify the Excel file which you want to auto export the email list
'You can change it as per your case
strExcelFile = "C:\Users\yakir.machluf\Documents\Outlook automation test.xlsx"
'Get Access to the Excel file
On Error Resume Next
Set objExcelApp = GetObject(, "Excel.Application")
If Error <> 0 Then
Set objExcelApp = CreateObject("Excel.Application")
End If
Set objExcelWorkBook = objExcelApp.Workbooks.Open(strExcelFile)
Set objExcelWorkSheet = objExcelWorkBook.Sheets("Sheet1")
'Get the next empty row in the Excel worksheet
nNextEmptyRow = objExcelWorkSheet.Range("B" & objExcelWorkSheet.Rows.Count).End(xlUp).Row + 1
'Specify the corresponding values in the different columns
strColumnB = objMail.SenderName
strColumnC = objMail.SenderEmailAddress
strColumnD = objMail.Subject
strColumnE = objMail.ReceivedTime
strColumnF = objMail.To
strColumnG = objMail.CC
'Add the vaules into the columns
objExcelWorkSheet.Range("A" & nNextEmptyRow) = nNextEmptyRow - 1
objExcelWorkSheet.Range("B" & nNextEmptyRow) = strColumnB
objExcelWorkSheet.Range("C" & nNextEmptyRow) = strColumnC
objExcelWorkSheet.Range("D" & nNextEmptyRow) = strColumnD
objExcelWorkSheet.Range("E" & nNextEmptyRow) = strColumnE
objExcelWorkSheet.Range("F" & nNextEmptyRow) = strColumnF
objExcelWorkSheet.Range("G" & nNextEmptyRow) = strColumnG
'Fit the columns from A to G
objExcelWorkSheet.Columns("A:G").AutoFit
'Save the changes and close the Excel file
objExcelWorkBook.Close SaveChanges:=True
End Sub

.Recipient has an .Address property.
Recipient.Address property (Outlook) https://learn.microsoft.com/en-us/office/vba/api/outlook.recipient.address
Option Explicit
Public WithEvents objMails As Items
Private Sub Application_Startup()
Set objMails = Session.GetDefaultFolder(olFolderInbox).Items
End Sub
Private Sub objMails_ItemAdd(ByVal Item As Object)
Dim objMail As MailItem
Dim i As Long
Dim recipAddresses As String
If Item.Class = olMail Then
Set objMail = Item
For i = 1 To objMail.Recipients.Count
recipAddresses = recipAddresses & objMail.Recipients(i).Address & " "
Next
Debug.Print Trim(recipAddresses)
End If
End Sub
Private Sub test_objMails_ItemAdd()
objMails_ItemAdd ActiveInspector.CurrentItem
End Sub
Code in detail:
Option Explicit
Private Sub objMails_ItemAdd(ByVal Item As Object)
Dim objMail As MailItem
Dim recip As Recipient
Dim recipAddressesTo As String
Dim recipAddressesCC As String
Dim i As Long
Dim strExcelFile As String
' Early binding - Set reference to Excel XX.X Object Library
Dim objExcelApp As Excel.Application
Dim objExcelWorkBook As Excel.Workbook
Dim objExcelWorkSheet As Excel.Worksheet
Dim nNextEmptyRow As Long
If Item.Class = olMail Then
Set objMail = Item
'Specify the Excel file
strExcelFile = "C:\Users\yakir.machluf\Documents\Outlook automation test.xlsx"
'Get the Excel file
' Bypass normal error handling
On Error Resume Next ' To be used for a specific purpose
Set objExcelApp = GetObject(, "Excel.Application")
' ?
Debug.Print " Error: " & Error
'If Error <> 0 Then
Debug.Print " Err..: " & Err
If Err <> 0 Then
Set objExcelApp = CreateObject("Excel.Application")
End If
' Return to normal error handling
On Error GoTo 0 ' Consider mandatory after On Error Resume Next
Set objExcelWorkBook = objExcelApp.Workbooks.Open(strExcelFile)
Set objExcelWorkSheet = objExcelWorkBook.Sheets("Sheet1")
With objExcelWorkSheet
'Get the next empty row in the Excel worksheet
nNextEmptyRow = .Range("B" & .Rows.Count).End(xlUp).Row + 1
'Specify the corresponding values in the different columns
.Range("A" & nNextEmptyRow) = nNextEmptyRow - 1
.Range("B" & nNextEmptyRow) = objMail.senderName
.Range("C" & nNextEmptyRow) = objMail.SenderEmailAddress
.Range("D" & nNextEmptyRow) = objMail.Subject
.Range("E" & nNextEmptyRow) = objMail.ReceivedTime
For i = 1 To objMail.Recipients.Count
Set recip = objMail.Recipients(i)
If recip.Type = olTo Then
recipAddressesTo = recipAddressesTo & recip.Address & " "
ElseIf recip.Type = olCC Then
recipAddressesCC = recipAddressesCC & recip.Address & " "
End If
Next
' Trim the space character at the end
objExcelWorkSheet.Range("F" & nNextEmptyRow) = Trim(recipAddressesTo)
objExcelWorkSheet.Range("G" & nNextEmptyRow) = Trim(recipAddressesCC)
'Fit the columns from A to G
objExcelWorkSheet.Columns("A:G").AutoFit
End With
'Save the changes and close the Excel file
objExcelWorkBook.Close SaveChanges:=True
End If
End Sub

Thanks to niton, I ended up tweaking the code and using the following.
The new problem I'm facing is trying to get the exchange addresses to appear as regular email addresses.
Any hints?
Public WithEvents objMails As Outlook.Items
Private Sub Application_Startup()
Set objMails = Outlook.Application.Session.GetDefaultFolder(olFolderInbox).Items
End Sub
Private Sub objMails_ItemAdd(ByVal Item As Object)
Dim objMail As Outlook.MailItem
Dim Recipient As Outlook.Recipient
Dim recipAddressesTo As String
Dim recipAddressesCC As String
Dim i As Long
Dim strExcelFile As String
Dim objExcelApp As Excel.Application
Dim objExcelWorkBook As Excel.Workbook
Dim objExcelWorkSheet As Excel.Worksheet
Dim nNextEmptyRow As Integer
Dim strColumnB As String
Dim strColumnC As String
Dim strColumnD As String
Dim strColumnE As String
Dim strColumnF As String
Dim strColumnG As String
If Item.Class = olMail Then
Set objMail = Item
End If
'Specify the Excel file which you want to auto export the email list
'You can change it as per your case
strExcelFile = "C:\Users\yakir.machluf\Documents\Outlook automation test.xlsx"
'Get Access to the Excel file
On Error Resume Next
Set objExcelApp = GetObject(, "Excel.Application")
If Error <> 0 Then
Set objExcelApp = CreateObject("Excel.Application")
End If
Set objExcelWorkBook = objExcelApp.Workbooks.Open(strExcelFile)
Set objExcelWorkSheet = objExcelWorkBook.Sheets("Sheet1")
'Get the next empty row in the Excel worksheet
nNextEmptyRow = objExcelWorkSheet.Range("B" & objExcelWorkSheet.Rows.Count).End(xlUp).Row + 1
'Add the vaules into the columns
objExcelWorkSheet.Range("A" & nNextEmptyRow) = nNextEmptyRow - 1
objExcelWorkSheet.Range("B" & nNextEmptyRow) = objMail.SenderName
objExcelWorkSheet.Range("C" & nNextEmptyRow) = objMail.SenderEmailAddress
objExcelWorkSheet.Range("D" & nNextEmptyRow) = objMail.Subject
objExcelWorkSheet.Range("E" & nNextEmptyRow) = objMail.ReceivedTime
For i = 1 To objMail.Recipients.Count
Set recip = objMail.Recipients(i)
If recip.Type = olTo Then
recipAddressesTo = recipAddressesTo & recip.Address & " "
ElseIf recip.Type = olCC Then
recipAddressesCC = recipAddressesCC & recip.Address & " "
End If
Next
' Trim the space character at the end
objExcelWorkSheet.Range("F" & nNextEmptyRow) = Trim(recipAddressesTo)
objExcelWorkSheet.Range("G" & nNextEmptyRow) = Trim(recipAddressesCC)
'Fit the columns from A to G
objExcelWorkSheet.Columns("A:G").AutoFit
'Save the changes and close the Excel file
objExcelWorkBook.Close SaveChanges:=True
End Sub

Related

Extract Hyperlinks from selected Outlook emails to a Excel Spreadsheet

I found this VBA Outlook code that meets my purpose in theory. objHyperlink seems to return Nothing when I debug.
The outputs are always empty and during debug I get
Runtime error: "13" and Type mismatch
at the line - For Each objHyperlink In objMailDocument.Hyperlinks
Dim objExcelApp As Excel.Application
Dim objExcelWorkbook As Excel.Workbook
Dim objExcelWorksheet As Excel.Worksheet
Sub ExportAllHyperlinksInMultipleEmailsToExcel()
Dim objSelection As Selection
Dim objMail As MailItem
Dim objMailDocument As Document
Dim objHyperlink As Hyperlink
Dim i As Long
Set objSelection = Outlook.Application.ActiveExplorer.Selection
If Not (objSelection Is Nothing) Then
Set objExcelApp = CreateObject("Excel.Application")
Set objExcelWorkbook = objExcelApp.Workbooks.Add
Set objExcelWorksheet = objExcelWorkbook.Sheets(1)
objExcelApp.Visible = True
objExcelWorkbook.Activate
With objExcelWorksheet
.Cells(1, 1) = "Email"
.Cells(1, 2) = "Text"
.Cells(1, 3) = "Link"
.Cells(1, 4) = "Source"
End With
i = 0
For Each objMail In objSelection
Set objMailDocument = objMail.GetInspector.WordEditor
If objMailDocument.Hyperlinks.Count > 0 Then <- Correct # of links shown here
For Each objHyperlink In objMailDocument.Hyperlinks <- Debug highlights this
If InStr(objHyperlink.Address, "www.") > 0 Then
i = i + 1
Call ExportToExcel(i, objMail, objHyperlink)
End If
Next
End If
objMail.Close olDiscard
Next
objExcelWorksheet.Columns("A:D").AutoFit
End If
End Sub
Sub ExportToExcel(n As Long, objCurrentMail As MailItem, objCurrentHyperlink As Hyperlink)
Dim nLastRow As Integer
nLastRow = objExcelWorksheet.Range("A" & objExcelWorksheet.Rows.Count).End(xlUp).Row + 1
objExcelWorksheet.Range("A" & nLastRow) = n
objExcelWorksheet.Range("B" & nLastRow) = objCurrentHyperlink.TextToDisplay
objExcelWorksheet.Range("C" & nLastRow) = objCurrentHyperlink.Address
objExcelWorksheet.Range("D" & nLastRow) = objCurrentMail.Subject
End Sub
Thanks to #CDP1802 for pointing out a couple of changes to try. This does work with the following code:
Dim objExcelApp As Excel.Application
Dim objExcelWorkbook As Excel.Workbook
Dim objExcelWorksheet As Excel.Worksheet
Sub ExportAllHyperlinksInMultipleEmailsToExcel()
Dim objSelection As Selection
Dim objMail As MailItem
Dim objMailDocument As Word.Document << Added Word. here
Dim objHyperlink As Word.Hyperlink << Added Word. here
Dim i As Long
Set objSelection = Outlook.Application.ActiveExplorer.Selection
If Not (objSelection Is Nothing) Then
Set objExcelApp = CreateObject("Excel.Application")
Set objExcelWorkbook = objExcelApp.Workbooks.Add
Set objExcelWorksheet = objExcelWorkbook.Sheets(1)
objExcelApp.Visible = True
objExcelWorkbook.Activate
With objExcelWorksheet
.Cells(1, 1) = "Email"
.Cells(1, 2) = "Text"
.Cells(1, 3) = "Link"
.Cells(1, 4) = "Source"
End With
i = 0
For Each objMail In objSelection
Set objMailDocument = objMail.GetInspector.WordEditor
If objMailDocument.Hyperlinks.Count > 0 Then
For Each objHyperlink In objMailDocument.Hyperlinks
If InStr(objHyperlink.Address, "www.") > 0 Then
i = i + 1
Call ExportToExcel(i, objMail, objHyperlink)
End If
Next
End If
objMail.Close olDiscard
Next
objExcelWorksheet.Columns("A:D").AutoFit
End If
End Sub
Sub ExportToExcel(n As Long, objCurrentMail As MailItem, objCurrentHyperlink As Word.Hyperlink) << Added Word. here
Dim nLastRow As Integer
nLastRow = objExcelWorksheet.Range("A" & objExcelWorksheet.Rows.Count).End(xlUp).Row + 1
objExcelWorksheet.Range("A" & nLastRow) = n
objExcelWorksheet.Range("B" & nLastRow) = objCurrentHyperlink.TextToDisplay
objExcelWorksheet.Range("C" & nLastRow) = objCurrentHyperlink.Address
objExcelWorksheet.Range("D" & nLastRow) = objCurrentMail.Subject
End Sub

Implementing an outlook macro in excel

I have the following macro in Outlook, and would like to use it frm Excel, how can I rewrite it that it will work from excel without an outlook macro being included?
Dim objExcelApp As Excel.Application
Dim objExcelWorkbook As Excel.Workbook
Dim objExcelWorksheet As Excel.Worksheet
Public Sub ExportAllFlaggedEmailsToExcel()
Dim objOutlookFile As Outlook.Folder
Dim objFolder As Outlook.Folder
Dim objNameSpace As NameSpace
Dim mailboxowner As Outlook.Recipient
Dim Shared_email_address As Folder
Dim outlookAPP As Outlook.Application
Set outlookAPP = Outlook.Application
Set objOutlookFile = Outlook.Application.Session.PickFolder
Set objNameSpace = Application.GetNamespace("MAPI")
'If Not (objOutlookFile Is Nothing) Then
'Create a new Excel file
Set objExcelApp = CreateObject("Excel.Application")
Set objExcelWorkbook = objExcelApp.Workbooks.Add
Set objExcelWorksheet = objExcelWorkbook.Sheets("sheet1")
objExcelApp.Visible = True
'Name_of_the_excel_file_created_by_the_vba = ActiveWorkbook.Name
'Name_of_the_excel_file_created_by_the_vba.Select
With objExcelWorksheet
.Cells(1, 1) = "Subject"
.Cells(1, 1).Font.Bold = True
.Cells(1, 2) = "Email was sent On"
.Cells(1, 2).Font.Bold = True
.Cells(1, 3) = "From"
.Cells(1, 3).Font.Bold = True
.Cells(1, 4) = "To"
.Cells(1, 4).Font.Bold = True
.Cells(1, 5) = "Categroy"
.Cells(1, 5).Font.Bold = True
End With
For Each objFolder In objOutlookFile.Folders
If objFolder.DefaultItemType = olMailItem Then
Call ProcessMailFolders(objFolder)
End If
Next
objExcelWorksheet.Columns("A:F").AutoFit
MsgBox "Completed!", vbInformation + vbOKOnly, "Export Emails"
'End If
End Sub
Public Sub ProcessMailFolders(ByVal objCurrentFolder As Outlook.Folder)
Dim i As Long
Dim objMail As Outlook.MailItem
Dim objFlaggedMail As Outlook.MailItem
Dim nLastRow As Integer
Dim objSubfolder As Outlook.Folder
'***********************
'Outlook to export categorised emails to excel
'***********************
amount_of_emails = objCurrentFolder.Items.Count
For i = 1 To objCurrentFolder.Items.Count
If objCurrentFolder.Items(i).Class = olMail Then
'Export the information of each flagged email to Excel
Set objMail = objCurrentFolder.Items(i)
On Error Resume Next
If objMail.Categories = "Category_Name" Then
Set objFlaggedMail = objMail
With objExcelWorksheet
nLastRow = .Range("A" & .Rows.Count).End(xlUp).Row + 1
.Range("A" & nLastRow) = objFlaggedMail.Subject
.Range("B" & nLastRow) = objFlaggedMail.SentOn
'.Range("C" & nLastRow) = objFlaggedMail.ReceivedTime
.Range("C" & nLastRow) = objFlaggedMail.SenderName
.Range("D" & nLastRow) = objFlaggedMail.To
.Range("E" & nLastRow) = "Category_Name"
End With
End If
End If
Next i
If objCurrentFolder.Folders.Count > 0 Then
For Each objSubfolder In objCurrentFolder.Folders
Call ProcessMailFolders(objSubfolder)
Next
End If
end sub
I know that it is not supported to call an outlook function/macro from excel, so therefore I would like to implement this on excel level, how could I start it?
See if you can modify this to do what you want (run from Excel).
Option Explicit On
Const fPath As String = "C:\Users\your_path_here\" 'The path to save the messages
Sub Download_Outlook_Mail_To_Excel()
Dim olApp As Object
Dim olFolder As Object
Dim olNS As Object
Dim xlBook As Workbook
Dim xlSheet As Worksheet
Dim NextRow As Long
Dim i As Long
Dim olItem As Object
Set xlBook = Workbooks.Add
Set xlSheet = xlBook.Sheets(1)
On Error Resume Next
Set olApp = GetObject(, "Outlook.Application")
If Err() <> 0 Then
Set olApp = CreateObject("Outlook.Application")
End If
On Error GoTo 0
With xlSheet
.Cells(1, 1) = "Sender"
.Cells(1, 2) = "Subject"
.Cells(1, 3) = "Date"
.Cells(1, 4) = "Size"
.Cells(1, 5) = "EmailID"
.Cells(1, 6) = "Body"
CreateFolders fPath
Set olNS = olApp.GetNamespace("MAPI")
Set olFolder = olNS.PickFolder
For Each olItem In olFolder.Items
NextRow = .Cells(.Rows.Count, "A").End(xlUp).Row + 1
If olItem.Class = 43 Then
.Cells(NextRow, 1) = olItem.Sender
.Cells(NextRow, 2) = olItem.Subject
.Cells(NextRow, 3) = olItem.SentOn
'.Cells(NextRow, 4) =
.Cells(NextRow, 5) = SaveMessage(olItem)
'.Cells(NextRow, 6) = olItem.Body 'Are you sure?
End If
Next olItem
End With
MsgBox "Outlook Mails Extracted to Excel"
lbl_Exit:
Set olApp = Nothing
Set olFolder = Nothing
Set olItem = Nothing
Set xlBook = Nothing
Set xlSheet = Nothing
Exit Sub
End Sub
Function SaveMessage(olItem As Object) As String
Dim Fname As String
Fname = Format(olItem.ReceivedTime, "yyyymmdd") & Chr(32) &
Format(olItem.ReceivedTime, "HH.MM") & Chr(32) & olItem.sendername & " - " & olItem.Subject
Fname = Replace(Fname, Chr(58) & Chr(41), "")
Fname = Replace(Fname, Chr(58) & Chr(40), "")
Fname = Replace(Fname, Chr(34), "-")
Fname = Replace(Fname, Chr(42), "-")
Fname = Replace(Fname, Chr(47), "-")
Fname = Replace(Fname, Chr(58), "-")
Fname = Replace(Fname, Chr(60), "-")
Fname = Replace(Fname, Chr(62), "-")
Fname = Replace(Fname, Chr(63), "-")
Fname = Replace(Fname, Chr(124), "-")
SaveMessage = SaveUnique(olItem, fPath, Fname)
lbl_Exit:
Exit Function
End Function
Private Function SaveUnique(oItem As Object,
strPath As String,
strFileName As String) As String
Dim lngF As Long
Dim lngName As Long
lngF = 1
lngName = Len(strFileName)
Do While FileExists(strPath & strFileName & ".msg") = True
strFileName = Left(strFileName, lngName) & "(" & lngF & ")"
lngF = lngF + 1
Loop
oItem.SaveAs strPath & strFileName & ".msg"
SaveUnique = strPath & strFileName & ".msg"
lbl_Exit:
Exit Function
End Function
Private Sub CreateFolders(strPath As String)
Dim strTempPath As String
Dim iPath As Long
Dim vPath As Variant
vPath = Split(strPath, "\")
strPath = vPath(0) & "\"
For iPath = 1 To UBound(vPath)
strPath = strPath & vPath(iPath) & "\"
If Not FolderExists(strPath) Then MkDir strPath
Next iPath
End Sub
Private Function FolderExists(ByVal PathName As String) As Boolean
Dim nAttr As Long
On Error GoTo NoFolder
nAttr = GetAttr(PathName)
If (nAttr And vbDirectory) = vbDirectory Then
FolderExists = True
End If
NoFolder:
End Function
Private Function FileExists(filespec) As Boolean
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists(filespec) Then
FileExists = True
Else
FileExists = False
End If
lbl_Exit:
Exit Function
End Function

Auto export e-mails from Outlook to Excel

I've found in the internet and modified a bit a piece of code:
Public WithEvents objMails As Outlook.Items
Private Sub Application_Startup()
Const pierwszy = "pierwszy#gmail.com"
Const drugi = "drugi#gmail.com"
Dim OutAcc As Account
Debug.Print "Startup"
For Each OutAcc In Outlook.Application.Session.Accounts
If (OutAcc.DisplayName = pierwszy) Then
Set objMails = OutAcc.DeliveryStore.GetDefaultFolder(olFolderInbox).Items
Exit For
End If
If (OutAcc.DisplayName = drugi) Then
Set objMails = OutAcc.DeliveryStore.GetDefaultFolder(olFolderInbox).Items
Exit For
End If
Next
End Sub
Private Sub objMails_ItemAdd(ByVal Item As Object)
Dim objMail As Outlook.MailItem
Dim strExcelFile As String
Dim objExcelApp As Excel.Application
Dim objExcelWorkBook As Excel.Workbook
Dim objExcelWorkSheet As Excel.Worksheet
Dim nNextEmptyRow As Integer
Dim strColumnB As String
Dim strColumnC As String
Dim strColumnD As String
Dim strColumnE As String
If Item.Class = olMail Then
Set objMail = Item
End If
'Specify the Excel file which you want to auto export the email list
'You can change it as per your case
strExcelFile = "C:\Users\karol\Documents\test.xlsx"
'Get Access to the Excel file
On Error Resume Next
Set objExcelApp = GetObject(, "Excel.Application")
If Error <> 0 Then
Set objExcelApp = CreateObject("Excel.Application")
End If
Set objExcelWorkBook = objExcelApp.Workbooks.Open(strExcelFile)
Set objExcelWorkSheet = objExcelWorkBook.Sheets("Arkusz1")
'Get the next empty row in the Excel worksheet
nNextEmptyRow = objExcelWorkSheet.Range("B" & objExcelWorkSheet.Rows.Count).End(xlUp).Row + 1
'Specify the corresponding values in the different columns
strColumnB = objMail.SenderName
strColumnC = objMail.SenderEmailAddress
strColumnD = objMail.Subject
strColumnE = objMail.ReceivedTime
strColumnF = objMail.Body
strColumnG = objMail.To
'Add the vaules into the columns
objExcelWorkSheet.Range("A" & nNextEmptyRow) = nNextEmptyRow - 1
objExcelWorkSheet.Range("B" & nNextEmptyRow) = strColumnB
objExcelWorkSheet.Range("C" & nNextEmptyRow) = strColumnC
objExcelWorkSheet.Range("D" & nNextEmptyRow) = strColumnD
objExcelWorkSheet.Range("E" & nNextEmptyRow) = strColumnE
objExcelWorkSheet.Range("F" & nNextEmptyRow) = strColumnF
objExcelWorkSheet.Range("G" & nNextEmptyRow) = strColumnG
'Fit the columns from A to E
objExcelWorkSheet.Columns("A:G").AutoFit
'Save the changes and close the Excel file
objExcelWorkBook.Close SaveChanges:=True
End Sub
This code works fine, when in Outlook application I am logged in at one mailbox (one e-mail). I've faced a problem when I am trying to automatically export emails from two mailboxes (two accounts with different email addresses on which I am logged in to the Outlook application) - look at the picture:
https://ibb.co/mXWZJsw
I tried to solve this problem by using If statements in the Application_Startup () procedure (as seen in the code above). This approach, unfortunately, does not work. I also noticed that, for example, when the first email arrives at the account "pierwszy#gmail.com", then until the application is closed, emails will be exported to Excel only from this account "pierwszy#gmail.com" and not exported from the account "drugi#gmail.com". However, when the first e-mail arrives at the account "drugi#gmail.com", then emails will be exported from the seccond e-mail "drugi#gmail.com" until application is closed.
Let me preface this by saying - not sure how rules work for multiple accounts. You may need to create the rule for BOTH accounts but they can both reference the same script.
I've updated your code to be a public Sub vs Private Sub and placed it in a module so that it can be referenced by the rules engine.
Now, once we have the code in place (scripts run by Rules engine typically inherently pass the email as a MailItem to the sub and ByVal was causing issues with recognizing the script as one to be run from a MailItem so i updated it to Item as MailItem).
We next create a new rule using the rules engine. If you see this simplistic interface, click on Advanced Options. That will allow us to apply to rule to all emails. In the advanced options window, do not check any box for Which conditions do you want to check? simply click Next. It will confirm you want to add this rule for ALL EMAILS which we do.
After selecting run a script we can click on a script to indicate which script we want to run. I set it to the exportToExcel script in Module(Project)1
Click Finish and test it out.
Sub exportToExcel(item As MailItem)
Dim objMail As Outlook.MailItem
Dim strExcelFile As String
Dim objExcelApp As Excel.Application
Dim objExcelWorkBook As Excel.Workbook
Dim objExcelWorkSheet As Excel.Worksheet
Dim nNextEmptyRow As Integer
Dim strColumnB As String
Dim strColumnC As String
Dim strColumnD As String
Dim strColumnE As String
If item.Class = olMail Then
Set objMail = item
End If
'Specify the Excel file which you want to auto export the email list
'You can change it as per your case
strExcelFile = "C:\Users\karol\Documents\test.xlsx"
'Get Access to the Excel file
On Error Resume Next
Set objExcelApp = GetObject(, "Excel.Application")
If Error <> 0 Then
Set objExcelApp = CreateObject("Excel.Application")
End If
Set objExcelWorkBook = objExcelApp.Workbooks.Open(strExcelFile)
Set objExcelWorkSheet = objExcelWorkBook.Sheets("Arkusz1")
'Get the next empty row in the Excel worksheet
nNextEmptyRow = objExcelWorkSheet.Range("B" & objExcelWorkSheet.Rows.count).End(xlUp).Row + 1
'Specify the corresponding values in the different columns
strColumnB = objMail.SenderName
strColumnC = objMail.SenderEmailAddress
strColumnD = objMail.Subject
strColumnE = objMail.ReceivedTime
strColumnF = objMail.Body
strColumnG = objMail.To
'Add the vaules into the columns
objExcelWorkSheet.Range("A" & nNextEmptyRow) = nNextEmptyRow - 1
objExcelWorkSheet.Range("B" & nNextEmptyRow) = strColumnB
objExcelWorkSheet.Range("C" & nNextEmptyRow) = strColumnC
objExcelWorkSheet.Range("D" & nNextEmptyRow) = strColumnD
objExcelWorkSheet.Range("E" & nNextEmptyRow) = strColumnE
objExcelWorkSheet.Range("F" & nNextEmptyRow) = strColumnF
objExcelWorkSheet.Range("G" & nNextEmptyRow) = strColumnG
'Fit the columns from A to E
objExcelWorkSheet.Columns("A:G").AutoFit
'Save the changes and close the Excel file
objExcelWorkBook.Close SaveChanges:=True
End Sub
You can monitor multiple folders with ItemAdd.
Option Explicit
Public WithEvents objMailspierwszy As Items
Public WithEvents objMailsdrugi As Items
Private Sub Application_Startup()
Const pierwszy = "pierwszy#somewhere.com"
Const drugi = "drugi#somewhere.com"
Dim OutAcc As Account
For Each OutAcc In Session.Accounts
Debug.Print "OutAcc.DisplayName: " & OutAcc.DisplayName
Debug.Print "OutAcc.DeliveryStore: " & OutAcc.DeliveryStore
If OutAcc.DisplayName = pierwszy Then
Debug.Print "OutAcc.DisplayName: " & OutAcc.DisplayName
Set objMailspierwszy = OutAcc.DeliveryStore.GetDefaultFolder(olFolderInbox).Items
Debug.Print "Listener on " & objMailspierwszy.Parent & " of DeliveryStore " & OutAcc.DeliveryStore
End If
If OutAcc.DisplayName = drugi Then
Debug.Print "OutAcc.DisplayName: " & OutAcc.DisplayName
Set objMailsdrugi = OutAcc.DeliveryStore.GetDefaultFolder(olFolderInbox).Items
Debug.Print "Listener on " & objMailspierwszy.Parent & " of DeliveryStore " & OutAcc.DeliveryStore
End If
Next
End Sub
Private Sub objMailspierwszy_ItemAdd(ByVal Item As Object)
'...
End Sub
Private Sub objMailsdrug_ItemAdd(ByVal Item As Object)
'...
End Sub

How to fix Compile Error: User-defined type not defined when using Excel VBA from Outlook?

I'm setting up an automatic solution to export incoming mails from Outlook into an Excel file.
I found several solutions online but I get a compile error.
I'm using Outlook 2016 and Windows 8.1.
I thought it's a reference problem, but I found the FM20.DLL and it's still not working.
The error I get:
Compile error: User-defined type not defined
at line Dim objExcelApp As Excel.Application
Public WithEvents objMails As Outlook.Items
Private Sub Application_Startup()
Set objMails =
Outlook.Application.Session.GetDefaultFolder(olFolderInbox).Items
End Sub
Private Sub objMails_ItemAdd(ByVal Item As Object)
Dim objMail As Outlook.MailItem
Dim strExcelFile As String
Dim objExcelApp As Excel.Application
Dim objExcelWorkBook As Excel.Workbook
Dim objExcelWorkSheet As Excel.Worksheet
Dim nNextEmptyRow As Integer
Dim strColumnB As String
Dim strColumnC As String
Dim strColumnD As String
Dim strColumnE As String
If Item.Class = olMail Then
Set objMail = Item
End If
'Specify the Excel file which you want to auto export the email list
'You can change it as per your case
strExcelFile = "H:\SF_Mail\Emails.xlsx"
'Get Access to the Excel file
On Error Resume Next
Set objExcelApp = GetObject(, "Excel.Application")
If Error <> 0 Then
Set objExcelApp = CreateObject("Excel.Application")
End If
Set objExcelWorkBook = objExcelApp.Workbooks.Open(strExcelFile)
Set objExcelWorkSheet = objExcelWorkBook.Sheets("Sheet1")
'Get the next empty row in the Excel worksheet
nNextEmptyRow = objExcelWorkSheet.Range("B" & objExcelWorkSheet.Rows.Count).End(xlUp).Row + 1
'Specify the corresponding values in the different columns
strColumnB = objMail.SenderName
strColumnC = objMail.SenderEmailAddress
strColumnD = objMail.Subject
strColumnE = objMail.ReceivedTime
'Add the vaules into the columns
objExcelWorkSheet.Range("A" & nNextEmptyRow) = nNextEmptyRow - 1
objExcelWorkSheet.Range("B" & nNextEmptyRow) = strColumnB
objExcelWorkSheet.Range("C" & nNextEmptyRow) = strColumnC
objExcelWorkSheet.Range("D" & nNextEmptyRow) = strColumnD
objExcelWorkSheet.Range("E" & nNextEmptyRow) = strColumnE
'Fit the columns from A to E
objExcelWorkSheet.Columns("A:E").AutoFit
'Save the changes and close the Excel file
objExcelWorkBook.Close SaveChanges:=True
End Sub
References
It's an error that appears when a reference is missing.
Try to add in Tools-> References:
Microsoft Excel [Your Version] Object Library
Microsoft Outlook [Your Version] Object Library
Code
Try to change how the Excel App is initialized, using this:
Dim objExcelApp As New Excel.Application
Instead of:
Dim objExcelApp As Excel.Application
So your code will look like this:
Private Sub objMails_ItemAdd(ByVal Item As Object)
Dim objMail As Outlook.MailItem
Dim strExcelFile As String
Dim objExcelApp As New Excel.Application
Dim objExcelWorkBook As Excel.Workbook
Dim objExcelWorkSheet As Excel.Worksheet
Dim nNextEmptyRow As Integer
Dim strColumnB As String
Dim strColumnC As String
Dim strColumnD As String
Dim strColumnE As String
If Item.Class = olMail Then
Set objMail = Item
End If
'Specify the Excel file which you want to auto export the email list
'You can change it as per your case
strExcelFile = "H:\SF_Mail\Emails.xlsx"
'Get Access to the Excel file
Set objExcelWorkBook = objExcelApp.Workbooks.Open(strExcelFile)
Set objExcelWorkSheet = objExcelWorkBook.Sheets("Sheet1")
'Get the next empty row in the Excel worksheet
nNextEmptyRow = objExcelWorkSheet.Range("B" & objExcelWorkSheet.Rows.Count).End(xlUp).Row + 1
'Specify the corresponding values in the different columns
strColumnB = objMail.SenderName
strColumnC = objMail.SenderEmailAddress
strColumnD = objMail.Subject
strColumnE = objMail.ReceivedTime
'Add the vaules into the columns
objExcelWorkSheet.Range("A" & nNextEmptyRow) = nNextEmptyRow - 1
objExcelWorkSheet.Range("B" & nNextEmptyRow) = strColumnB
objExcelWorkSheet.Range("C" & nNextEmptyRow) = strColumnC
objExcelWorkSheet.Range("D" & nNextEmptyRow) = strColumnD
objExcelWorkSheet.Range("E" & nNextEmptyRow) = strColumnE
'Fit the columns from A to E
objExcelWorkSheet.Columns("A:E").AutoFit
'Save the changes and close the Excel file
objExcelWorkBook.Close SaveChanges:=True
objExcelApp.Quit 'Quit Excel application
End Sub
Notes
Usually it's a bad idea to use the instruction On Error Resume Next, because it suppresses every error you get on runtime execution. However, there're some exceptions to the rule and you can check #FunThomas answer for clarification.
This is not really an answer but too long for a comment to the answer of #Louis and the following discussion.
On Error Resume Next usually is evil, but sometimes it is the best way to deal with a statement that might fail. In this case, the command Set objExcelApp = GetObject(, "Excel.Application") will assign a running instance of Excel to the variable objExcelApp, but will fail (and throw an error) if Excel is currently not active. The following If Error <> 0 Then checks if an error occurred and if yes, it will open a new Excel instance and assign it to objExcelApp.
At that point, Excel should be available to the Macro, either an existing or a new Instance. An exception could only be if Excel is not available at all (not installed) or cannot be started (out of memory). However, the On Error Resume Next is still active and will continue to ignore all runtime errors, and that is bad. So, after the the assignment of the variable, revert to the standard error handling and see what fails:
'Get Access to the Excel file
On Error Resume Next
Set objExcelApp = GetObject(, "Excel.Application")
If Error <> 0 Then
Set objExcelApp = CreateObject("Excel.Application")
End If
On Error Goto 0

Get the date of the oldest mail per category

I have a macro to get the count of mails category-wise in Outlook.
Along with that I want the oldest mail date in a particular category. e.g. in the Red category there are 20 mails, so what is the date of the oldest mail in the Red category?
Sub CategoriesEmails()
Dim oFolder As MAPIFolder
Dim oDict As Object
Dim sStartDate As String
Dim sEndDate As String
Dim oItems As Outlook.Items
Dim sStr As String
Dim sMsg As String
Dim strFldr As String
Dim OutMail As Object
Dim xlApp As Object
On Error Resume Next
Set oFolder = Application.ActiveExplorer.CurrentFolder
Set oDict = CreateObject("Scripting.Dictionary")
sStartDate = Date - 365
sEndDate = Date
Set oItems = oFolder.Items.Restrict("[Received] >= '" & sStartDate & "' And [Received] <= '" & sEndDate & "'")
oItems.SetColumns ("Categories")
For Each aItem In oItems
sStr = aItem.Categories
If Not oDict.Exists(sStr) Then
oDict(sStr) = 0
End If
oDict(sStr) = CLng(oDict(sStr)) + 1
Next aItem
sMsg = ""
i = 0
strFldr = "C:\Users\singhab\Desktop\Macro\"
Set xlApp = CreateObject("Excel.Application")
xlApp.Application.Visible = True
xlApp.Workbooks.Open strFldr & "Test.xlsx"
xlApp.Sheets("Sheet1").Select
For Each aKey In oDict.Keys
xlApp.Range("a1").Offset(i, 0).Value = sMsg & aKey
xlApp.Range("B1").Offset(i, 0).Value = oDict(aKey) & vbCrLf
i = i + 1
Next
xlApp.Save
Set oFolder = Nothing
End Sub
I get the output
What I want is
Work with Items.GetFirst Method (Outlook) which Returns An Object value that represents the first object contained by the collection
Code Example
Option Explicit
Public Sub Example()
Dim olNs As Outlook.NameSpace
Set olNs = Application.GetNamespace("MAPI")
Dim Inbox As Outlook.MAPIFolder
Set Inbox = olNs.GetDefaultFolder(olFolderInbox)
Dim Items As Outlook.Items
Set Items = Inbox.Items.Restrict("[Categories] = 'Red Category'")
Dim Item As Object
Set Item = Items.GetFirst
Debug.Print Item.Subject & " " & Item.ReceivedTime
End Sub

Resources