Extract Outlook UserDefinedProperties field - vba

I add UserDefinedProperties in Outlook with the below code
Sub AddStatusProperties()
Dim objNamespace As NameSpace
Dim objFolder As Folder
Dim objProperty As UserDefinedProperty
Set objNamespace = Application.GetNamespace("MAPI")
Set objFolder = objNamespace.GetDefaultFolder(olFolderInbox)
With objFolder.UserDefinedProperties
Set objProperty = .Add("MyNotes1", olText, 1)
End With
End Sub
The user can add a value to MyNotes1 field in any email.
Public Sub EditField()
Dim obj As Object
Dim objProp As Outlook.UserProperty
Dim strNote As String, strAcct As String, strCurrent As String
Dim propertyAccessor As Outlook.propertyAccessor
Set obj = Application.ActiveExplorer.Selection.Item(1)
On Error Resume Next
Set UserProp = obj.UserProperties.Find("MyNotes1")
If Not UserProp Is Nothing Then
strCurrent = obj.UserProperties("MyNotes1").Value
End If
Dim varArrayList As Variant
Dim varArraySelected As Variant
varArrayList = Array("value1", "value2", "value3")
varArraySelected = SelectionBoxMulti(List:=varArrayList, Prompt:="Select one or more values", _
SelectionType:=fmMultiSelectMulti, Title:="Select multiple")
If Not IsEmpty(varArraySelected) Then 'not cancelled
For i = LBound(varArraySelected) To UBound(varArraySelected)
If strNote = "" Then
strNote = varArraySelected(i)
Else
strNote = strNote & ";" & varArraySelected(i)
End If
Next i
End If
Set objProp = obj.UserProperties.Add("MyNotes1", olText, True)
objProp.Value = strNote
obj.Save
Err.Clear
Set obj = Nothing
End Sub
I need to extract all email properties including the values available under MyNotes field to Excel. How do I recall MyNotes1 values?
This is the Excel code. The part I miss is "myArray(6, i - 1) = item.?????".
Public Sub getEmails()
On Error GoTo errhand:
Dim outlook As Object: Set outlook = CreateObject("Outlook.Application")
Dim ns As Object: Set ns = outlook.GetNamespace("MAPI")
'This option open a new window for you to select which folder you want to work with
Dim olFolder As Object: Set olFolder = ns.PickFolder
Dim emailCount As Long: emailCount = olFolder.Items.Count
Dim i As Long
Dim myArray As Variant
Dim item As Object
ReDim myArray(6, (emailCount - 1))
For i = 1 To emailCount
Set item = olFolder.Items(i)
If item.Class = 43 And item.ConversationID <> vbNullString Then
myArray(0, i - 1) = item.Subject
myArray(1, i - 1) = item.SenderName
myArray(2, i - 1) = item.To
myArray(3, i - 1) = item.CreationTime
myArray(4, i - 1) = item.ConversationID
myArray(5, i - 1) = item.Categories
'myArray(6, i - 1) = item.?????
End If
Next
With ActiveSheet
.Range("A1") = "Subject"
.Range("B1") = "From"
.Range("C1") = "To"
.Range("D1") = "Created"
.Range("E1") = "ConversationID"
.Range("F1") = "Category"
.Range("G1") = "MyNote"
.Range("A2:G" & (emailCount + 1)).Value = TransposeArray(myArray)
End With
Exit Sub
errhand:
Debug.Print Err.Number, Err.Description
End Sub

You already have code that retrieves that property
Set UserProp = item.UserProperties.Find("MyNotes1")
If Not UserProp Is Nothing Then
myArray(6, i - 1) = UserProp.Value
End If

Related

Get attachments file names from emails vba

I have a folder that has emails with attachments and without attachments. i have the code for extracting the attachments names but if an email doesn't have attachments the code will stop. Any help is welcomed, thank you.
by jimmypena
Private Sub CommandButton2_Click()
Dim a As Attachments
Dim myitem As Folder
Dim myitem1 As MailItem
Dim j As Long
Dim i As Integer
Set myitem = Session.GetDefaultFolder(olFolderDrafts)
For i = 1 To myitem.Items.Count
If myitem.Items(i) = test1 Then
Set myitem1 = myitem.Items(i)
Set a = myitem1.Attachments
MsgBox a.Count
' added this code
For j = 1 To myitem1.Attachments.Count
MsgBox myitem1.Attachments.Item(i).DisplayName ' or .Filename
Next j
End If
Next i
End Sub
My code:
Sub EXPORT()
Const FOLDER_PATH = "\\Mailbox\Inbox\emails from them"
Dim olkMsg As Object, _
olkFld As Object, _
excApp As Object, _
excWkb As Object, _
excWks As Object, _
intRow As Integer, _
intCnt As Integer, _
strFileName As String, _
arrCells As Variant
strFileName = "C:\EXPORT"
If strFileName <> "" Then
Set excApp = CreateObject("Excel.Application")
Set excWkb = excApp.Workbooks.Add()
Set excWks = excWkb.ActiveSheet
excApp.DisplayAlerts = False
With excWks
.Cells(1, 1) = "ATTACH NAMES"
.Cells(1, 2) = "SENDER"
.Cells(1, 3) = "NR SUBJECT"
.Cells(1, 4) = "CATEGORIES"
End With
intRow = 2
Set olkFld = OpenOutlookFolder(FOLDER_PATH)
For Each olkMsg In olkFld.Items
If olkMsg.Class = olMail Then
arrCells = Split(GetCells(olkMsg.HTMLBody), Chr(255))
Dim Reg1 As RegExp
Dim M1 As MatchCollection
Dim M As match
Set Reg1 = New RegExp
With Reg1
.Pattern = "\s*[-]+\s*(\w*)\s*(\w*)"
.Global = True
End With
Set M1 = Reg1.Execute(olkMsg.Subject)
For Each M In M1
excWks.Cells(intRow, 3) = M
Next
Dim a As Attachments
Set a = olkMsg.Attachments
If Not a Is Nothing Then
excWks.Cells(intRow, 1) = olkMsg.Attachment.Filename
'excWks.Cells(intRow, 2) = olkMsg.SenderEmailAddress
End If
excWks.Cells(intRow, 2) = olkMsg.sender.GetExchangeUser.PrimarySmtpAddress
excWks.Cells(intRow, 4) = olkMsg.Categories
intRow = intRow + 1
intCnt = intCnt + 1
End If
Next
Set olkMsg = Nothing
excWkb.SaveAs strFileName, 52
excWkb.Close
End If
Set olkFld = Nothing
Set excWks = Nothing
Set excWkb = Nothing
Set excApp = Nothing
MsgBox "Ta dam! "
End Sub
edited
Set a = myitem1.Attachments
MsgBox a.Count
For j = 1 To myitem1.Attachments.Count
MsgBox myitem1.Attachments.Item(j).DisplayName ' or .Filename
Next j
as about your edited question, replace the following snippet
Dim a As Attachments
Set a = olkMsg.Attachments
If Not a Is Nothing Then
excWks.Cells(intRow, 1) = olkMsg.Attachment.Filename
'excWks.Cells(intRow, 2) = olkMsg.SenderEmailAddress
End If
with:
Dim a As Attachment
For Each a In olkMsg.Attachments
excWks.Cells(intRow, 1) = a.FileName
'excWks.Cells(intRow, 2) = a.SenderEmailAddress
Next a
which you must treat appropriately as for the intRow index.
if you are interested in only the first attachment then you could substitute the entire last code with this:
excWks.Cells(intRow, 1) = olkMsg.Attachments.Item(1).FileName
while if you are interested in all attachments then you'll have to rethink about your sheet report structure

Copying Global Address List contacts including "External Contacts"

I have a VBA code to get whole Global Address List from Outlook 2013 and place the values Name and E-mail Address in an Excel sheet.
The problem is it's only returning e-mails/users from my SMTP (I guess).
In this image, we can see the users from the SMTP as mine covered in black and an external user covered in red. My code:
Sub tgr()
Dim appOL As Object
Dim oGAL As Object
Dim oContact As Object
Dim oUser As Object
Dim arrUsers(1 To 75000, 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
So, am I doing something wrong?
According to this documentation, the oContact.AddressEntryUserType value should include olExchangeRemoteUserAddressEntry (5) for External Users.
What's in your code is just to list Exchange Users, so it also skips mail-enabled PublicFolders, Distribution Lists, etc.
EDIT
Found a better way to extract name and email address (if any):
Reference: Obtain the E-mail Address of a Recipient
Option Explicit
Sub tgr()
Const PR_SMTP_ADDRESS = "http://schemas.microsoft.com/mapi/proptag/0x39FE001E"
Dim appOL As Object
Dim oGAL As Object
Dim arrUsers() As String
Dim UserIndex As Long
Dim i As Long
Dim sEmail As String
Set appOL = GetObject(, "Outlook.Application")
If appOL Is Nothing Then Set appOL = CreateObject("Outlook.Application")
Set oGAL = appOL.GetNameSpace("MAPI").AddressLists("Global Address List").AddressEntries
Debug.Print oGAL.Parent.Name & " has " & oGAL.Count & " entries"
ReDim arrUsers(1 To oGAL.Count, 1 To 2)
On Error Resume Next
For i = 1 To oGAL.Count
With oGAL.Item(i)
Application.StatusBar = "Processing GAL entry #" & i & " (" & .Name & ")"
sEmail = "" ' Not all entries has email address
sEmail = .PropertyAccessor.GetProperty(PR_SMTP_ADDRESS)
If Len(sEmail) = 0 Then Debug.Print "No Email address configured for " & .Name & " (#" & i & ")"
UserIndex = UserIndex + 1
arrUsers(UserIndex, 1) = .Name
arrUsers(UserIndex, 2) = sEmail
End With
Next
On Error GoTo 0
Application.StatusBar = False
appOL.Quit
If UserIndex > 0 Then
Range("A2").Resize(UserIndex, UBound(arrUsers, 2)).Value = arrUsers
End If
Set appOL = Nothing
Set oGAL = Nothing
Erase arrUsers
End Sub

vba outlook: get emails and export to excel and save attachments

I have tried to put together a piece of vba code which does the following.
first it looks for all emails in my inbox folder for the account NewSuppliers#Hewden.co.uk where the subject contains certain key words.
Secondly it looks for all emails in my inbox folder CreditChecks#Hewden.co.uk where the subject contains certain keywords.
Then it exports certain data into excel row after row.
This works fine except with my emails which I export from the CreditChecks#Hewden.co.uk inbox, I want to export only the emails which contains a pdf attachment and save this attachment in a directory and place each seperate pdf document in a folder with the same name as the pdf file.
I've tested my save attachment and export emails scripts separate and they work fine but when I put them together I get an error saying
method or object not found
Set objAttachments = Outlook.Attachments
Can someone please help me get my code to do what I need it to do? Thanks in advance
Here is my code:
'On the next line edit the path to the spreadsheet you want to export to
Const WORKBOOK_PATH = "X:\New_Supplier_Set_Ups_&_Audits\NewSupplierSet-Up.xls"
'On the next line edit the name of the sheet you want to export to
Const SHEET_NAME = "Validations"
Const SHEET_NAME2 = "BankSetup"
Const SHEET_NAME3 = "CreditChecks"
Const MACRO_NAME = "Export Messages to Excel (Rev 7)"
Private Sub Application_Startup()
Dim olkMsg As Object, _
olkMsg2 As Object, _
excApp As Object, _
excWkb As Object, _
excWks As Object, _
excWks2 As Object, _
excWks3 As Object, _
intRow As Integer, _
intRow2 As Integer, _
intRow3 As Integer, _
intExp As Integer, _
intVersion As Integer
intVersion = GetOutlookVersion()
Set excApp = CreateObject("Excel.Application")
Set excWkb = excApp.Workbooks.Open(WORKBOOK_PATH)
Set excWks = excWkb.Worksheets(SHEET_NAME)
Set excWks2 = excWkb.Worksheets(SHEET_NAME2)
Set excWks3 = excWkb.Worksheets(SHEET_NAME3)
intRow = excWks.UsedRange.Rows.Count + 1
intRow2 = excWks2.UsedRange.Rows.Count + 1
intRow3 = excWks3.UsedRange.Rows.Count + 1
'Write messages to spreadsheet
Dim ns As Outlook.NameSpace
Dim Items As Outlook.Items
Dim Items2 As Outlook.Items
Dim objAttachments As Outlook.Attachments
Dim objMsg As Outlook.MailItem 'Object
Dim i As Long
Dim lngCount As Long
Dim strFile As String
Dim strFolderPath As String
Dim strDeletedFiles As String
Dim withParts As String
Dim withoutParts As String
' Get the MAPI Namespace
Set ns = Application.GetNamespace("MAPI")
' Get the Items for the Inbox in the specified account
Set Items = ns.Folders("New Suppliers").Folders("Inbox").Items
Set Items2 = ns.Folders("Credit Checks").Folders("Inbox").Items
Set objAttachments = Outlook.Attachments
' Start looping through the items
For Each olkMsg In Items
'Only export messages, not receipts or appointment requests, etc.
If olkMsg.class = olMail Then
If olkMsg.Subject Like "Accept: New Supplier Request*" Or olkMsg.Subject Like "Reject: New Supplier Request*" Then
'Add a row for each field in the message you want to export
excWks.Cells(intRow, 1) = olkMsg.ReceivedTime
Dim LResult As String
LResult = Replace(GetSMTPAddress(olkMsg, intVersion), ".", " ")
LResult = Left(LResult, InStrRev(LResult, "#") - 1)
excWks.Cells(intRow, 2) = LResult
excWks.Cells(intRow, 3) = olkMsg.VotingResponse
Dim s As String
s = olkMsg.Subject
Dim indexOfName As Integer
indexOfName = InStr(1, s, "Reference: ")
Dim finalString As String
finalString = Right(s, Len(s) - indexOfName - 10)
excWks.Cells(intRow, 4) = finalString
intRow = intRow + 1
End If
End If
If olkMsg.class = olMail Then
If olkMsg.Subject Like "Complete: Bank Details Set-Up for New Supplier*" Or olkMsg.Subject Like "Incomplete: Bank Details Set-Up for New Supplier*" Then
'Add a row for each field in the message you want to export
excWks2.Cells(intRow2, 1) = olkMsg.ReceivedTime
Dim LResult2 As String
LResult2 = Replace(GetSMTPAddress(olkMsg, intVersion), ".", " ")
LResult2 = Left(LResult2, InStrRev(LResult2, "#") - 1)
excWks2.Cells(intRow2, 2) = LResult2
excWks2.Cells(intRow2, 3) = olkMsg.VotingResponse
Dim s2 As String
s2 = olkMsg.Subject
Dim indexOfName2 As Integer
indexOfName2 = InStr(1, s2, "Reference: ")
Dim finalString2 As String
finalString2 = Right(s2, Len(s2) - indexOfName2 - 10)
excWks2.Cells(intRow2, 4) = finalString2
intRow2 = intRow2 + 1
End If
End If
Next
strFolderPath = "\\UKSH000-FILE06\Purchasing\New_Supplier_Set_Ups_&_Audits\ATTACHMENTS\"
Set objAttachments = objMsg.Attachments
lngCount = objAttachments.Count
For Each olkMsg2 In Items2
If olkMsg2.class = olMail Then
If olkMsg2.Subject Like "RE: New Supplier Credit*" Then
If lngCount > 0 Then
For i = lngCount To 1 Step -1
strFile = objAttachments.item(i).FileName
If Right(strFile, 3) = "pdf" Then
' Combine with the path to the Temp folder.
withParts = strFile
withoutParts = Replace(withParts, ".pdf", "")
strFile = strFolderPath & withoutParts & "\" & strFile
' Save the attachment as a file.
objAttachments.item(i).SaveAsFile strFile
'Add a row for each field in the message you want to export
excWks3.Cells(intRow3, 1) = olkMsg2.ReceivedTime
Dim LResult3 As String
LResult3 = Replace(GetSMTPAddress(olkMsg2, intVersion), ".", " ")
LResult3 = Left(LResult3, InStrRev(LResult3, "#") - 1)
excWks3.Cells(intRow3, 2) = LResult3
excWks3.Cells(intRow3, 3) = "Complete"
excWks3.Cells(intRow3, 4) = "File Attached"
Dim s3 As String
s3 = olkMsg2.Subject
Dim indexOfName3 As Integer
indexOfName3 = InStr(1, s3, "Reference: ")
Dim finalString3 As String
finalString3 = Right(s3, Len(s3) - indexOfName3 - 10)
excWks3.Cells(intRow3, 5) = finalString3
excWks3.Cells(intRow3, 6) = "File Path"
intRow3 = intRow3 + 1
End If
Next i
End If
End If
End If
Next
Set olkMsg = Nothing
Set olkMsg2 = Nothing
excWkb.Close True
Set excWks = Nothing
Set excWks2 = Nothing
Set excWks3 = Nothing
Set excWkb = Nothing
Set excApp = Nothing
On Error GoTo ErrHandle
ErrHandle:
Resume Next
End Sub
Private Function GetSMTPAddress(item As Outlook.MailItem, intOutlookVersion As Integer) As String
Dim olkSnd As Outlook.AddressEntry, olkEnt As Object
On Error Resume Next
Select Case intOutlookVersion
Case Is < 14
If item.SenderEmailType = "EX" Then
GetSMTPAddress = SMTP2007(item)
Else
GetSMTPAddress = item.SenderEmailAddress
End If
Case Else
Set olkSnd = item.Sender
If olkSnd.AddressEntryUserType = olExchangeUserAddressEntry Then
Set olkEnt = olkSnd.GetExchangeUser
GetSMTPAddress = olkEnt.PrimarySmtpAddress
Else
GetSMTPAddress = item.SenderEmailAddress
End If
End Select
On Error GoTo 0
Set olkPrp = Nothing
Set olkSnd = Nothing
Set olkEnt = Nothing
End Function
Function GetOutlookVersion() As Integer
Dim arrVer As Variant
arrVer = Split(Outlook.Version, ".")
GetOutlookVersion = arrVer(0)
End Function
Function SMTP2007(olkMsg As Outlook.MailItem) As String
Dim olkPA As Outlook.PropertyAccessor
On Error Resume Next
Set olkPA = olkMsg.PropertyAccessor
SMTP2007 = olkPA.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x5D01001E")
On Error GoTo 0
Set olkPA = Nothing
End Function
Set objAttachments = Outlook.Attachments is not the correct syntax.
Just remove the line as you have this later.
Set objAttachments = objMsg.Attachments

Runtime error looping through Outlook items

I am using VBA in Outlook to extract mail information from items in the mainfolder and subfolder. The mainfolder failed to set(capture) the subfolder properties into it and it causes the runtime error.
The runtime error differs whenever I run. For example, sometime I received -970718969 (c6240107) and another time I received -2044460793 (86240107).
When I clicked debug, it points to this line of code:
For Each itm In subFld.Items
Here is the screenshot:
Here is the full code:
Public monthValue As Integer
Public yearValue As String
'Ensure Microsoft Excel 11.0 Object Library is ticked in tools.
Sub ExportToExcel1()
Dim appExcel As Excel.Application
Dim wkb As Excel.Workbook
Dim wks As Excel.Worksheet
Dim rng As Excel.Range
Dim strSheet As String
Dim strPath As String
Dim intRowCounter As Integer
Dim msg As Outlook.MailItem
Dim nms As Outlook.NameSpace
Dim mainFld As Outlook.MAPIFolder
Dim subFld As Outlook.MAPIFolder
Dim itm As Object
Dim offsetRow As Long
Dim emailCount As Long
'Set the path of the excel file.
strSheet = "For fun.xlsx"
strPath = "C:\Users\xxxxxx\Desktop\xxxxx\"
strSheet = strPath & strSheet
Debug.Print strSheet
Set nms = Application.GetNamespace("MAPI")
Set mainFld = nms.PickFolder 'Open the box to select the file.
'Handle potential errors with Select Folder dialog box.
If mainFld Is Nothing Then
MsgBox "Thank you for using this service.", vbOKOnly, "Error"
Set nms = Nothing
Set mainFld = Nothing
Exit Sub
ElseIf mainFld.DefaultItemType <> olMailItem Then
MsgBox "Please select the correct folder.", vbOKOnly, "Error"
Set nms = Nothing
Set mainFld = Nothing
Exit Sub
ElseIf mainFld.Items.Count = 0 Then
MsgBox "There are no mail messages to export", vbOKOnly, "Error"
Set nms = Nothing
Set mainFld = Nothing
Exit Sub
End If
mainForm.Show
'If user clicks cancel, it will exit sub.
If yearValue = "" Then
Set nms = Nothing
Set mainFld = Nothing
Exit Sub
End If
'Open and activate Excel workbook.
Set appExcel = CreateObject("Excel.Application")
appExcel.Workbooks.Open (strSheet)
Set wkb = appExcel.ActiveWorkbook
Set wks = wkb.Sheets(1)
wks.Activate
appExcel.Application.Visible = True 'Show my workbook.
'Check if there are any subfolders.
If mainFld.Folders.Count = 0 Then '1
'No subfolder.
For Each itm In mainFld.Items
If itm.Class <> olMail Then '2
'do nothing
Else
Set msg = itm
'Validate the month and year for the email.
If Month(msg.ReceivedTime) = monthValue And Year(msg.ReceivedTime) = yearValue Then '3
With wks
offsetRow = .Cells(.Rows.Count, 1).End(xlUp).Row
End With
intRowCounter = 1 + offsetRow
Set rng = wks.Cells(intRowCounter, 1)
rng.Value = msg.ReceivedTime
Set rng = wks.Cells(intRowCounter, 2)
rng.Value = msg.SentOn
Set rng = wks.Cells(intRowCounter, 3)
rng.Value = msg.Subject
emailCount = 1 + emailCount 'Track the number of email.
Else
'Do nothing
End If '3
End If '2
Next itm
Else
'With subfolder
For Each itm In mainFld.Items
If itm.Class <> olMail Then '4
'do nothing
Else
Set msg = itm
If Month(msg.ReceivedTime) = monthValue And Year(msg.ReceivedTime) = yearValue Then '5
With wks
offsetRow = .Cells(.Rows.Count, 1).End(xlUp).Row
End With
intRowCounter = 1 + offsetRow
Set rng = wks.Cells(intRowCounter, 1)
rng.Value = msg.ReceivedTime
Set rng = wks.Cells(intRowCounter, 2)
rng.Value = msg.SentOn
Set rng = wks.Cells(intRowCounter, 3)
rng.Value = msg.Subject
emailCount = 1 + emailCount
Else
'Do nothing
End If '5
End If '4
Next itm
For Each subFld In mainFld.Folders
For Each itm In subFld.Items
If itm.Class <> olMail Then '6
'do nothing
Else
Set msg = itm
If Month(msg.ReceivedTime) = monthValue And Year(msg.ReceivedTime) = yearValue Then '7
With wks
offsetRow = .Cells(.Rows.Count, 1).End(xlUp).Row
End With
intRowCounter = 1 + offsetRow
Set rng = wks.Cells(intRowCounter, 1)
rng.Value = msg.ReceivedTime
Set rng = wks.Cells(intRowCounter, 2)
rng.Value = msg.SentOn
Set rng = wks.Cells(intRowCounter, 3)
rng.Value = msg.Subject
emailCount = 1 + emailCount
Else
'Do nothing
End If '7
End If '6
Next itm
Next subFld
End If '1
Set appExcel = Nothing
Set wkb = Nothing
Set wks = Nothing
Set rng = Nothing
Set msg = Nothing
Set nms = Nothing
Set mainFld = Nothing
Set subFld = Nothing
Set itm = Nothing
'Inform the user that there are no email.
If emailCount = 0 Then
MsgBox "No emails associated with this date: " & MonthName(monthValue, True) & " " & yearValue, vbOKOnly, "No Emails"
End If
Exit Sub
Set appExcel = Nothing
Set wkb = Nothing
Set wks = Nothing
Set rng = Nothing
Set msg = Nothing
Set nms = Nothing
Set mainFld = Nothing
Set subFld = Nothing
Set itm = Nothing
End Sub
Do you get that error immediately or only after processing a large number of items? Most likely you are opening too many items and run out of RPC channels. Is this a cached or an online Exchange profile?
Instead of looping through all items, use the Table object (MAPITable.GetTable) - if nothing else, it will be a lot faster.
EDIT: If you are using Exchange, every store object (message, folder, store) opens an RPC channel. Exchange Server limits the number of RPC channels to 255 per client (can be changed on the server). Do not use "for each" loop (it keeps all items referenced until the loop ends) and avoid multiple dot notation (because you will have implicit variables that you cannot explicitly dereference). You will also need to release all Outlook objects as soon as you are done with them.
set fldItems = mainFld.Items
For i = 1 to fldItems.Count do
set itm = fldItems.Item(i)
'do stuff
set itm = Nothing
next
As for the Table object (introduced in Outlook 2007), see http://msdn.microsoft.com/en-us/library/office/ff860769.aspx. If you need to use this in an earlier version of Outlook, you can use the MAPITable object in Redemption (I am its author); it also has a MAPITable.ExecSQL method that takes a standard SQL query and returns the ADODB.Recordset object.

Can I iterate through all Outlook emails in a folder including sub-folders?

I have a folder which contains a number of emails and sub-folders. Within those sub-folders are more emails.
I'd like to write some VBA which will iterate through all emails in a certain folder, including those in any of the sub-folders. The idea is to extract the SenderEmailAddress and SenderName from every email and do something with it.
I've tried just exporting the folder as CSV with only these two fields and whilst this works, it doesn't support exporting emails held in sub-folders. Hence the need to write some VBA.
Before I go re-inventing the wheel, does anyone have any code snippets or links to sites which, given a folder name, shows how to get a MailItem object for every email in that folder and subsequent sub-folders?
Something like this ...
Private Sub processFolder(ByVal oParent As Outlook.MAPIFolder)
Dim oFolder As Outlook.MAPIFolder
Dim oMail As Outlook.MailItem
For Each oMail In oParent.Items
'Get your data here ...
Next
If (oParent.Folders.Count > 0) Then
For Each oFolder In oParent.Folders
processFolder oFolder
Next
End If
End Sub
This has a lot of great code that you are interested in. Go run it in Outlook/VBA as a macro.
Const MACRO_NAME = "OST2XLS"
Dim excApp As Object, _
excWkb As Object, _
excWks As Object, _
intVersion As Integer, _
intMessages As Integer, _
lngRow As Long
Sub ExportMessagesToExcel()
Dim strFilename As String, olkSto As Outlook.Store
strFilename = InputBox("Enter a filename (including path) to save the exported messages to.", MACRO_NAME)
If strFilename <> "" Then
intMessages = 0
intVersion = GetOutlookVersion()
Set excApp = CreateObject("Excel.Application")
Set excWkb = excApp.Workbooks.Add
For Each olkSto In Session.Stores
Set excWks = excWkb.Worksheets.Add()
excWks.Name = "Output1"
'Write Excel Column Headers
With excWks
.Cells(1, 1) = "Folder"
.Cells(1, 2) = "Sender"
.Cells(1, 3) = "Received"
.Cells(1, 4) = "Sent To"
.Cells(1, 5) = "Subject"
End With
lngRow = 2
ProcessFolder olkSto.GetRootFolder()
Next
excWkb.SaveAs strFilename
End If
Set excWks = Nothing
Set excWkb = Nothing
excApp.Quit
Set excApp = Nothing
MsgBox "Process complete. A total of " & intMessages & " messages were exported.", vbInformation + vbOKOnly, "Export messages to Excel"
End Sub
Sub ProcessFolder(olkFld As Outlook.MAPIFolder)
Dim olkMsg As Object, olkSub As Outlook.MAPIFolder
'Write messages to spreadsheet
For Each olkMsg In olkFld.Items
'Only export messages, not receipts or appointment requests, etc.
If olkMsg.Class = olMail Then
'Add a row for each field in the message you want to export
excWks.Cells(lngRow, 1) = olkFld.Name
excWks.Cells(lngRow, 2) = GetSMTPAddress(olkMsg, intVersion)
excWks.Cells(lngRow, 3) = olkMsg.ReceivedTime
excWks.Cells(lngRow, 4) = olkMsg.ReceivedByName
excWks.Cells(lngRow, 5) = olkMsg.Subject
lngRow = lngRow + 1
intMessages = intMessages + 1
End If
Next
Set olkMsg = Nothing
For Each olkSub In olkFld.Folders
ProcessFolder olkSub
Next
Set olkSub = Nothing
End Sub
Private Function GetSMTPAddress(Item As Outlook.MailItem, intOutlookVersion As Integer) As String
Dim olkSnd As Outlook.AddressEntry, olkEnt As Object
On Error Resume Next
Select Case intOutlookVersion
Case Is < 14
If Item.SenderEmailType = "EX" Then
GetSMTPAddress = SMTP2007(Item)
Else
GetSMTPAddress = Item.SenderEmailAddress
End If
Case Else
Set olkSnd = Item.Sender
If olkSnd.AddressEntryUserType = olExchangeUserAddressEntry Then
Set olkEnt = olkSnd.GetExchangeUser
GetSMTPAddress = olkEnt.PrimarySmtpAddress
Else
GetSMTPAddress = Item.SenderEmailAddress
End If
End Select
On Error GoTo 0
Set olkPrp = Nothing
Set olkSnd = Nothing
Set olkEnt = Nothing
End Function
Function GetOutlookVersion() As Integer
Dim arrVer As Variant
arrVer = Split(Outlook.Version, ".")
GetOutlookVersion = arrVer(0)
End Function
Function SMTP2007(olkMsg As Outlook.MailItem) As String
Dim olkPA As Outlook.PropertyAccessor
On Error Resume Next
Set olkPA = olkMsg.PropertyAccessor
SMTP2007 = olkPA.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x5D01001E")
On Error GoTo 0
Set olkPA = Nothing
End Function