I am trying to download a specific attachment from an outlook folder, and it works when I sort the mailbox in ascending order. When I sort it in descending order, I suddenly get an Automation Error.
Option Explicit
Sub Taxinfo()
Dim folder As Outlook.MAPIFolder
Dim olApp As Outlook.Application
Dim olNS As Outlook.Namespace
Dim olfldr As Outlook.MAPIFolder
Dim sharedemail As Outlook.Recipient
Dim olMail As Variant
Dim myTasks As Outlook.Items
Dim itm As Outlook.MailItem
Dim objAtt As Outlook.Attachment
Dim y As Workbook
'Dim BodyText
Set y = Workbooks.Open("Current working spreadsheet here")
'Dim daysAgo As Long
Dim priorSaveFolder As Object
Set priorSaveFolder = y.Sheets("VBA Inputs").Range("B10") 'this is just the intended save location
'daysAgo = 3 'not currently being used
'Find Mailbox to search
Set olApp = New Outlook.Application
Set olNS = olApp.GetNamespace("MAPI")
Set sharedemail = olNS.CreateRecipient("mailbox i'm using")
Set olfldr = olNS.GetSharedDefaultFolder(sharedemail, olFolderInbox)
Set folder = olfldr
Set myTasks = folder.Items
Set myTasks = folder.Items.Restrict("[Subject]='Email Subject'")
myTasks.Sort "[ReceivedTime]", False
'if I change this to True, I get "Run-time error '440': Automation Error
For Each olMail In myTasks
If olMail.Attachments.Count > 0 Then
While olMail.Attachments.Count > 0
'This times out or doesn't work for some reason
' For Each objAtt In olMail.Attachments
' If InStr(objAtt.Filename, "MTTAX") Or InStr(objAtt.Filename, "mttax") Then
' olMail.Attachments(1).SaveAsFile priorSaveFolder & "MTTAX.html"
' Exit For
' End If
' Next objAtt
If (Left$(olMail.Attachments(1).Filename, 5) = "mttax" Or Left$(olMail.Attachments(1).Filename, 5) = "MTTAX") Then
olMail.Attachments(1).SaveAsFile priorSaveFolder & "MTTAX.html"
End If
If (Left$(olMail.Attachments(1).Filename, 5) = "mttax" Or Left$(olMail.Attachments(1).Filename, 5) = "MTTAX") Then
Exit For
End If
If (Left$(olMail.Attachments(2).Filename, 5) = "mttax" Or Left$(olMail.Attachments(2).Filename, 5) = "MTTAX") Then
olMail.Attachments(2).SaveAsFile priorSaveFolder & "MTTAX.html"
End If
If (Left$(olMail.Attachments(2).Filename, 5) = "mttax" Or Left$(olMail.Attachments(2).Filename, 5) = "MTTAX") Then
Exit For
End If
If (Left$(olMail.Attachments(3).Filename, 5) = "mttax" Or Left$(olMail.Attachments(3).Filename, 5) = "MTTAX") Then
olMail.Attachments(3).SaveAsFile priorSaveFolder & "MTTAX.html"
End If
If (Left$(olMail.Attachments(3).Filename, 5) = "mttax" Or Left$(olMail.Attachments(3).Filename, 5) = "MTTAX") Then
Exit For
End If
If (Left$(olMail.Attachments(4).Filename, 5) = "mttax" Or Left$(olMail.Attachments(4).Filename, 5) = "MTTAX") Then
olMail.Attachments(4).SaveAsFile priorSaveFolder & "MTTAX.html"
End If
If (Left$(olMail.Attachments(4).Filename, 5) = "mttax" Or Left$(olMail.Attachments(4).Filename, 5) = "MTTAX") Then
Exit For
End If
If (Left$(olMail.Attachments(5).Filename, 5) = "mttax" Or Left$(olMail.Attachments(5).Filename, 5) = "MTTAX") Then
olMail.Attachments(5).SaveAsFile priorSaveFolder & "MTTAX.html"
End If
If (Left$(olMail.Attachments(5).Filename, 5) = "mttax" Or Left$(olMail.Attachments(5).Filename, 5) = "MTTAX") Then
Exit For
End If
If (Left$(olMail.Attachments(6).Filename, 5) = "mttax" Or Left$(olMail.Attachments(6).Filename, 5) = "MTTAX") Then
olMail.Attachments(6).SaveAsFile priorSaveFolder & "MTTAX.html"
End If
If (Left$(olMail.Attachments(6).Filename, 5) = "mttax" Or Left$(olMail.Attachments(6).Filename, 5) = "MTTAX") Then
Exit For
End If
If (Left$(olMail.Attachments(7).Filename, 5) = "mttax" Or Left$(olMail.Attachments(7).Filename, 5) = "MTTAX") Then
olMail.Attachments(7).SaveAsFile priorSaveFolder & "MTTAX.html"
End If
If (Left$(olMail.Attachments(7).Filename, 5) = "mttax" Or Left$(olMail.Attachments(7).Filename, 5) = "MTTAX") Then
Exit For
End If
Wend
End If
Next olMail
Dim IE As InternetExplorer
Dim url As String
url = priorSaveFolder & "MTTAX.html"
Set IE = New InternetExplorerMedium
With IE
.Visible = True
.navigate url
Do Until .readyState = 4: DoEvents: Loop
End With
IE.ExecWB 17, 0 '// SelectAll
IE.ExecWB 12, 2 '// Copy selection
y.Sheets("Tax").Range("A1").PasteSpecial
IE.Quit
End Sub
The code works perfectly when myTasks.sort "[ReceivedTime]", False, except it's pulling an attachment from an email from 2019. If I try to sort the other direction, then it errors out. How do I pull the most recent email?
The issue ended up being in the script to filter through the attachments. Deleting those lines out and replacing them with the following solved my issue:
For Each olMail In myTasks
If olMail.Attachments.Count > 0 Then
For Each objAtt In olMail.Attachments
If InStr(objAtt.Filename, "MTTAX") Or InStr(objAtt.Filename, "mttax") Then
objAtt.SaveAsFile priorSaveFolder & "MTTAX.html"
Exit For
End If
Next objAtt
End If
Next olMail
Related
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
I have code that searches through a particular folder path for excel files and pulls back results. What I can't figure out, is how to select an entire directory and open/search every folder it encounters.
The best solution would be an IF statement that opens the folder If it is available, but I am stumped.
Thank You in advance.
If I need to be more descriptive let me know!
Try
excelapp = New Application
excelapp.Visible = False
strPath = TextBox2.Text
'strPath = "C:\Users\asside\Documents\Test Program"
strSearch = TextBox1.Text
'strSearch = "soup"
If TextBox1.Text = "" Then
Form3.ShowDialog()
Exit Sub
End If
itms(0, 0) = "Workbook"
itms(1, 0) = "Worksheet"
itms(2, 0) = "Cell"
itms(3, 0) = "Text in Cell"
fso = CreateObject("Scripting.FileSystemObject")
fld = fso.GetFolder(strPath)
strFile = Dir(strPath & "\*.xls*")
Do While strFile <> ""
wbk = excelapp.Workbooks.Open(
Filename:=strPath & "\" & strFile,
UpdateLinks:=0,
ReadOnly:=True,
AddToMru:=False)
For Each wks In wbk.Worksheets
rFound = wks.UsedRange.Find(strSearch)
If Not rFound Is Nothing Then
strFirstAddress = rFound.Address
End If
Do
If rFound Is Nothing Then
Exit Do
Else
itmcnt += 1
ReDim Preserve itms(3, itmcnt)
itms(0, itmcnt) = wbk.Name
itms(1, itmcnt) = wks.Name
itms(2, itmcnt) = rFound.Address
itms(3, itmcnt) = rFound.Value
End If
rFound = wks.Cells.FindNext(After:=rFound)
Loop While strFirstAddress <> rFound.Address
Next
wbk.Close(False)
strFile = Dir()
Loop
Catch ex As Exception
MsgBox(ex.Message, vbExclamation, "")
End Try
wOut = Nothing
wks = Nothing
wbk = Nothing
fld = Nothing
fso = Nothing
excelapp.Visible = False
excelapp = Nothing
Dim savefilePath As String
savefilePath = Form5.TextBox1.Text
If savefilePath = "" Then
savefilePath = "Z:\Eric Application\SoupSearch\Program Files\OutputFolder\OutputSearch.CSV"
End If"
Use System.IO.Directory.GetFiles(string, string, SearchOption) using search option: System.IO.SearchOption.AllDirectories
Dim paths = IO.Directory.GetFiles("path", "*.xls*", IO.SearchOption.AllDirectories)
In your example
Try
excelapp = New Application
excelapp.Visible = False
strPath = TextBox2.Text
'strPath = "C:\Users\asside\Documents\Test Program"
strSearch = TextBox1.Text
'strSearch = "soup"
If TextBox1.Text = "" Then
Form3.ShowDialog()
Exit Sub
End If
itms(0, 0) = "Workbook"
itms(1, 0) = "Worksheet"
itms(2, 0) = "Cell"
itms(3, 0) = "Text in Cell"
fso = CreateObject("Scripting.FileSystemObject")
fld = fso.GetFolder(strPath)
For Each strfile In IO.Directory.GetFiles(strPath, "*.xls*", IO.SearchOption.AllDirectories)
wbk = excelapp.Workbooks.Open(
Filename:=strfile,
UpdateLinks:=0,
ReadOnly:=True,
AddToMru:=False)
For Each wks In wbk.Worksheets
rFound = wks.UsedRange.Find(strSearch)
If Not rFound Is Nothing Then
strFirstAddress = rFound.Address
End If
Do
If rFound Is Nothing Then
Exit Do
Else
itmcnt += 1
ReDim Preserve itms(3, itmcnt)
itms(0, itmcnt) = wbk.Name
itms(1, itmcnt) = wks.Name
itms(2, itmcnt) = rFound.Address
itms(3, itmcnt) = rFound.Value
End If
rFound = wks.Cells.FindNext(After:=rFound)
Loop While strFirstAddress <> rFound.Address
Next
wbk.Close(False)
Next
Catch ex As Exception
MsgBox(ex.Message, vbExclamation, "")
End Try
Use the method IO.Directory.GetFiles and set the searchOption-argument to AllDirectories.
For Each f As String In IO.Directory.GetFiles("C:\", "*.xls", IO.SearchOption.AllDirectories)
' Your method to pull back results
Next
I have the below code that I am trying to modify to split a subject line into to six columns to view in Excel.
Sub subject2excel()
On Error Resume Next
Set myOlApp = Outlook.Application
Set mynamespace = myOlApp.GetNamespace("mapi")
Set myfolder = myOlApp.ActiveExplorer.CurrentFolder
Set xlobj = CreateObject("excel.application.14")
xlobj.Visible = True
xlobj.Workbooks.Add
'Set Heading
xlobj.Range("a" & 1).Value = "From"
xlobj.Range("b" & 1).Value = "Subject"
For i = 1 To myfolder.Items.Count
Set myitem = myfolder.Items(i)
msgtext = myitem.Body
xlobj.Range("a" & i + 1).Value = myitem.Sender
xlobj.Range("b" & i + 1).Value = myitem.Subject
Next
End Sub
My data is in the below format
SLWP Moncton | Cable Service Eng. | 21-Jul-15 | Shift End: 0:00 | Leave Time: entire day | SLWP (Unpaid)
So in total 7 columns I plan to leave is below.
Sender
Location
LOB
Date
Shift End Time
Shift Leave Time
Leave Type
In it's current state as you can see it only produces two columns and I do not know how to break the subject line apart.
Any help will be most appreciated.
Thanks
Use Split.
Sub subject2excel()
Dim myOlApp As Outlook.Application
Dim myFolder As folder
Dim xlobj As Object
Dim i As Long
Dim j As Long
Dim myitem As Object
Dim Words() As String
'On Error Resume Next
Set myOlApp = Outlook.Application
'Set myNameSpace = myOlApp.GetNamespace("mapi")
Set myFolder = myOlApp.ActiveExplorer.currentFolder
Set xlobj = CreateObject("excel.application.14")
xlobj.Visible = True
xlobj.Workbooks.Add
'Set Heading
xlobj.Range("a" & 1).Value = "From"
xlobj.Range("b" & 1).Value = "Subject"
For i = 1 To myFolder.Items.count
Set myitem = myFolder.Items(i)
If TypeOf myitem Is MailItem Then
'msgText = myitem.body
xlobj.Range("a" & i + 1).Value = myitem.Sender
'xlobj.Range("b" & i + 1).Value = myitem.Subject
Words = Split(myitem.Subject, " | ")
For j = 0 To UBound(Words)
Debug.Print Words(j)
Next j
End If
Next i
exitRoutine:
Set myOlApp = Nothing
Set myFolder = Nothing
Set xlobj = Nothing
Set myitem = Nothing
End Sub
I was able to solve the issue
Sub subject2excel()
Dim olFolder As Outlook.Folder
Dim olItem As Outlook.MailItem
Dim olNS As Outlook.NameSpace
Dim xlApp As Object
Dim xlWB As Object
Dim i As Long
Dim j As Long
Dim vSubject As Variant
On Error Resume Next
Set xlApp = GetObject(, "Excel.Application")
If Err <> 0 Then
Set xlApp = CreateObject("Excel.Application")
End If
On Error GoTo 0 'err_Handler
xlApp.Visible = True
Set xlWB = xlApp.Workbooks.Add
'Set Heading
With xlWB.Sheets(1)
.Range("A" & 1).Value = "Sender"
.Range("B" & 1).Value = "Location"
.Range("C" & 1).Value = "LOB"
.Range("D" & 1).Value = "Date"
.Range("E" & 1).Value = "Shift End Time"
.Range("F" & 1).Value = "Requested Leave Time"
.Range("G" & 1).Value = "Paid/Unpaid"
End With
'Fill sheet
Set olNS = GetNamespace("MAPI")
Set olFolder = olNS.PickFolder
For i = 1 To olFolder.Items.Count
Set olItem = olFolder.Items(i)
If InStr(1, olItem.Subject, "|") > 0 Then
vSubject = Split(olItem.Subject, "|")
With xlWB.Sheets(1)
.Range("A" & i + 1).Value = olItem.Sender
.Range("B" & i + 1).Value = vSubject(0)
.Range("C" & i + 1).Value = vSubject(1)
.Range("D" & i + 1).Value = vSubject(2)
.Range("E" & i + 1).Value = Trim(Mid(vSubject(3), InStr(1, vSubject(3), Chr(58)) + 1))
.Range("F" & i + 1).Value = Trim(Mid(vSubject(4), InStr(1, vSubject(4), Chr(58)) + 1))
.Range("F" & i + 1).HorizontalAlignment = -4152 'align right
.Range("G" & i + 1).Value = Replace(Trim(Mid(vSubject(5), InStrRev(vSubject(5), Chr(40)) + 1)), Chr(41), "")
End With
End If
Next i
xlWB.Sheets(1).UsedRange.Columns.Autofit
exitRoutine:
Set olFolder = Nothing
Set xlApp = Nothing
Set xlWB = Nothing
Set olItem = Nothing
lbl_Exit:
Exit Sub
err_Handler:
GoTo lbl_Exit
End Sub
I usually get Employee announcement in emails and I need to compile excel sheet from all these emails to know change in status of employee from previous line to current line .
Dear Concerned,
The change in status of the following employee has been carried out as per following details:
New Status
Change in Job
Effective Date
01-Feb-2015
Employee Name
Ricky ponting
Employee Code
4982
Designation
Sourcing Executive (Secondment)
Job Group
1A
Department
Sourcing & Supply Chain
Unit
Technology Sourcing
Division
Finance
Location
Islamabad
Reporting Line
Mr Micheal king
Note: Ricky Ponting was previously working as Tariff Implementation Support Officer in the org Communication dept and was reporting to Mr Robin Sing.
I need working code that export about HTML table data as well last Note : full line so that I can have an excel file of 2000 Employees whoes status have been changed and I can easily sort out from which previous line they were reporting to new line and I can get in touch with the new line for any Access rights re-authorization exercise on later stage .
Currently i am using following code thats working fine with the table extraction but NOTE: line is not being fetched with the following code based on following URL
https://techniclee.wordpress.com/2011/10/29/exporting-outlook-messages-to-excel/
Const MACRO_NAME = "Export Messages to Excel (Rev Sajjad)"
Private Sub ExportMessagesToExcel()
Dim olkFld As Outlook.MAPIFolder, _
olkMsg As Outlook.MailItem, _
excApp As Object, _
excWkb As Object, _
excWks As Object, _
arrCel As Variant, _
varCel As Variant, _
lngRow As Long, _
intPtr As Integer, _
intVer As Integer
Set olkFld = Session.PickFolder
If TypeName(olkFld) = "Nothing" Then
MsgBox "You did not select a folder. Operation cancelled.", vbCritical + vbOKOnly, MACRO_NAME
Else
intVer = GetOutlookVersion()
Set excApp = CreateObject("Excel.Application")
Set excWkb = excApp.Workbooks.Add
Set excWks = excWkb.Worksheets(1)
excApp.Visible = True
With excWks
.Cells(1, 1) = "Subject"
.Cells(1, 2) = "Received"
.Cells(1, 3) = "Sender"
.Cells(1, 4) = "New Status"
.Cells(1, 5) = "Effective Date"
.Cells(1, 6) = "Employee Name"
.Cells(1, 7) = "Employee Code"
.Cells(1, 8) = "Designation"
.Cells(1, 9) = "Job Group"
.Cells(1, 10) = "Department"
.Cells(1, 11) = "Unit"
.Cells(1, 12) = "Division"
.Cells(1, 13) = "Location"
.Cells(1, 14) = "Reporting Line"
.Cells(1, 15) = "Note:"
End With
lngRow = 2
For Each olkMsg In olkFld.Items
excWks.Cells(lngRow, 1) = olkMsg.Subject
excWks.Cells(lngRow, 2) = olkMsg.ReceivedTime
excWks.Cells(lngRow, 3) = GetSMTPAddress(olkMsg, intVer)
arrCel = Split(GetCells(olkMsg.HTMLBody), Chr(255))
For intPtr = LBound(arrCel) To UBound(arrCel)
Select Case Trim(arrCel(intPtr))
Case "New Status"
excWks.Cells(lngRow, 4) = arrCel(intPtr + 1)
Case "Effective Date"
excWks.Cells(lngRow, 5) = arrCel(intPtr + 1)
Case "Employee Name"
excWks.Cells(lngRow, 6) = arrCel(intPtr + 1)
Case "Employee Code"
excWks.Cells(lngRow, 7) = arrCel(intPtr + 1)
Case "Designation"
excWks.Cells(lngRow, 8) = arrCel(intPtr + 1)
Case "Job Group"
excWks.Cells(lngRow, 9) = arrCel(intPtr + 1)
Case "Department"
excWks.Cells(lngRow, 10) = arrCel(intPtr + 1)
Case "Unit"
excWks.Cells(lngRow, 11) = arrCel(intPtr + 1)
Case "Division"
excWks.Cells(lngRow, 12) = arrCel(intPtr + 1)
Case "Location"
excWks.Cells(lngRow, 13) = arrCel(intPtr + 1)
Case "Reporting Line"
excWks.Cells(lngRow, 14) = arrCel(intPtr + 1)
Case "Note:"
excWks.Cells(lngRow, 15) = arrCel(intPtr + 1)
End Select
Next
lngRow = lngRow + 1
Next
excWks.Columns("A:W").AutoFit
excApp.Visible = True
Set excWks = Nothing
Set excWkb = Nothing
Set excApp = Nothing
End If
Set olkFld = Nothing
End Sub
Private Function GetCells(strHTML As String) As String
Const READYSTATE_COMPLETE = 4
Dim IE As Object, objDoc As Object, colCells As Object, objCell As Object
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
IE.navigate "about:blank"
Do While IE.ReadyState <> 4: DoEvents: Loop
DoEvents
Set Doc = CreateObject("htmlfile")
IE.document.Body.innerHTML = strHTML
Set objDoc = IE.document
Set colCells = objDoc.getElementsByTagName("td")
If colCells.Length > 0 Then
For Each objCell In colCells
GetCells = GetCells & objCell.innerText & Chr(255)
Next
GetCells = Left(GetCells, Len(GetCells) - 1)
Else
GetCells = ""
End If
Set objCell = Nothing
Set colCells = Nothing
Set objDoc = Nothing
IE.Quit
Set IE = Nothing
End Function
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
Sub DebugLabels()
Dim olkMsg As Outlook.MailItem, objFSO As Object, objFil As Object, strBuf As String, strPth As String, arrCel As Variant, intPtr As Integer
strPth = Environ("USERPROFILE") & "\Documents\Debugging.txt"
Set olkMsg = Application.ActiveExplorer.Selection(1)
arrCel = Split(GetCells(olkMsg.HTMLBody), Chr(255))
For intPtr = LBound(arrCel) To UBound(arrCel)
strBuf = strBuf & StrZero(intPtr, 2) & vbTab & "*" & arrCel(intPtr) & "*" & vbCrLf
Next
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFil = objFSO.CreateTextFile(strPth)
objFil.Write strBuf
objFil.Close
Set olkMsg = Application.CreateItem(olMailItem)
With olkMsg
.Recipients.Add "TechnicLee#earthlink.net"
.Subject = "Debugging Info"
.BodyFormat = olFormatPlain
.Body = "The debugging info for the selected message is attached. Please click Send to send this message to David."
.Attachments.Add strPth
.Display
End With
Set olkMsg = Nothing
Set objFSO = Nothing
Set objFil = Nothing
End Sub
Function StrZero(varNumber, intLength)
Dim intItemLength
If IsNumeric(varNumber) Then
intItemLength = Len(CStr(Int(varNumber)))
If intItemLength < intLength Then
StrZero = String(intLength - intItemLength, "0") & varNumber
Else
StrZero = varNumber
End If
Else
StrZero = varNumber
End If
End Function
A method of parsing text is described here: 17.2 Parsing text from a message body
Make the appropriate changes to look for "Note:"
Sub FwdSelToAddr()
Dim objOL As Outlook.Application
Dim objItem As Object
Dim objFwd As Outlook.MailItem
Dim strAddr As String
On Error Resume Next
Set objOL = Application
Set objItem = objOL.ActiveExplorer.Selection(1)
If Not objItem Is Nothing Then
strAddr = ParseTextLinePair(objItem.Body, "Email:")
If strAddr <> "" Then
Set objFwd = objItem.Forward
objFwd.To = strAddr
objFwd.Display
Else
MsgBox "Could not extract address from message."
End If
End If
Set objOL = Nothing
Set objItem = Nothing
Set objFwd = Nothing
End Sub
Function ParseTextLinePair _
(strSource As String, strLabel As String)
Dim intLocLabel As Integer
Dim intLocCRLF As Integer
Dim intLenLabel As Integer
Dim strText As String
intLocLabel = InStr(strSource, strLabel)
intLenLabel = Len(strLabel)
If intLocLabel > 0 Then
intLocCRLF = InStr(intLocLabel, strSource, vbCrLf)
If intLocCRLF > 0 Then
intLocLabel = intLocLabel + intLenLabel
strText = Mid(strSource, _
intLocLabel, _
intLocCRLF - intLocLabel)
Else
intLocLabel = _
Mid(strSource, intLocLabel + intLenLabel)
End If
End If
ParseTextLinePair = Trim(strText)
End Function
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