I'm trying to parse Outlook emails into an Excel spreadsheet.
All of the "vText"s are being output in column B and not B through E.
Original email text:
Caller: First Last
Phone: 123-456-7890
For: Company Name - Address
City: Metropolis
MSGID: 3068749608
I extract the Caller, Phone and MSGID fields just fine, but parsing the Company Name hasn't worked. It randomly pastes the Phone or MSGID values into that column instead.
Option Explicit
Private Const xlUp As Long = -4162
Sub CopyAllMessagesToExcel()
Dim objOL As Outlook.Application
Dim objItems As Outlook.Items
Dim objFolder As Outlook.MAPIFolder
Dim olItem As Outlook.MailItem
Dim xlApp As Object
Dim xlWB As Object
Dim xlSheet As Object
Dim vText, vText2, vText3, vText4, vText5 As Variant
Dim sText As String
Dim rCount As Long
Dim bXStarted As Boolean
Dim enviro As String
Dim strPath As String
Dim Reg1 As Object
Dim M1 As Object
Dim M As Object
Dim OutlookNamespace As NameSpace
enviro = CStr(Environ("USERPROFILE"))
'the path of the workbook
strPath = enviro & "file path"
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
'Open the workbook to input the data
Set xlWB = xlApp.Workbooks.Open(strPath)
Set xlSheet = xlWB.Sheets("Sheet1")
'Find the next empty line of the worksheet
'rCount = xlSheet.Range("B" & xlSheet.Rows.Count).End(xlUp).Row 'original code
rCount = xlSheet.Range("A" & xlSheet.Rows.Count).End(xlUp).Row
rCount = rCount + 1
Set objOL = Outlook.Application
Set OutlookNamespace = objOL.GetNamespace("MAPI")
Set objFolder = OutlookNamespace.GetDefaultFolder(olFolderInbox).Folders("SubFolder").Folders("SubSubFolder")
Set objItems = objFolder.Items
For Each olItem In objItems
On Error Resume Next
With olItem
sText = olItem.Body
Set Reg1 = CreateObject("VBScript.RegExp")
' \s* = invisible spaces
' \d* = match digits
' \w* = match alphanumeric
Dim i As Integer
For i = 1 To 4
With Reg1
'.IgnoreCase = True
Select Case i 'each Case = one specific string parsed
Case 1
'pull everything after Caller (separated by :), and stop at line end \n
.Pattern = "(Caller[:]([\w-\s]*)\s*)\n"
Case 2
.Pattern = "(Phone[:]([\d-\s]*)\s*)\n"
'#### CASE 3 NOT WORKING
Case 3
'pull everything after For (separated by :), and stop at the dash [-]
.Pattern = "(For[:]([\w-\s]*)\s*)[-]"
Case 4
'pull everything after MSGID, and stop at the dash [-]
.Pattern = "(MSGID[:]([\w-\s]*)\s*)[-]"
End Select
End With
If Reg1.Test(sText) Then
' each "(\w*)" and the "(\s)" are assigned a vText variable
Set M1 = Reg1.Execute(sText)
For Each M In M1
vText = Trim(M.SubMatches(1))
vText2 = Trim(M.SubMatches(2))
vText3 = Trim(M.SubMatches(3))
vText4 = Trim(M.SubMatches(4))
Next
xlSheet.Range("a" & rCount) = .ReceivedTime
xlSheet.Range("b" & rCount) = vText
xlSheet.Range("c" & rCount) = vText2
xlSheet.Range("d" & rCount) = vText3
xlSheet.Range("e" & rCount) = vText4
'xlSheet.Range("D" & rCount) = .Subject
'xlSheet.Range("f" & rCount) = vText5
'##Checking on output per iteration:
'MsgBox ("inputting data in row #" & rCount)
' next line
rCount = rCount + 1
End If
Next i
' do whatever
Debug.Print .Subject
End With
Next
'xlWB.Close 1
'If bXStarted Then
' xlApp.Quit
'End If
Set M = Nothing
Set M1 = Nothing
Set Reg1 = Nothing
Set xlApp = Nothing
Set xlWB = Nothing
Set xlSheet = Nothing
Set objItems = Nothing
Set objFolder = Nothing
Set objOL = Nothing
End Sub
I'd move the regex into a separate function:
Function ExtractText(txt As String, patt As String)
Static reg As Object
Dim matches, rv As String 'EDIT: moved from Static line
If reg Is Nothing Then
Set reg = CreateObject("VBScript.RegExp")
'set up IgnoreCase etc here...
End If
reg.Pattern = patt
If reg.Test(txt) Then
Set matches = reg.Execute(txt)
rv = matches(0).submatches(1)
End If
ExtractText = rv
End Function
Then the core of your main code becomes something like this:
Set objOL = Outlook.Application
Set OutlookNamespace = objOL.GetNamespace("MAPI")
Set objFolder = OutlookNamespace.GetDefaultFolder(olFolderInbox).Folders("SubFolder").Folders("SubSubFolder")
Set objItems = objFolder.Items
For Each olItem In objItems
sText = olItem.Body
xlSheet.Range("a" & rCount) = .ReceivedTime
xlSheet.Range("b" & rCount) = ExtractText(sText, "(Caller[:]([\w-\s]*)\s*)\n")
xlSheet.Range("c" & rCount) = ExtractText(sText, "(Phone[:]([\d-\s]*)\s*)\n")
xlSheet.Range("d" & rCount) = ExtractText(sText, "(For[:]([\w-\s]*)\s*)[-]")
xlSheet.Range("e" & rCount) = ExtractText(sText, "(MSGID:\s?(\d{1,})-)")'<<edit
'xlSheet.Range("D" & rCount) = .Subject
'xlSheet.Range("f" & rCount) = vText5
'MsgBox ("inputting data in row #" & rCount)
rCount = rCount + 1
Next olItem
Related
I am trying to get the string after a word that gives me the needed data and all the phrase after every "-" into a new cell in excel except in RE: , where I omit "RE:" and only leave the TS... ticket ID.
This code works by selecting the emails in outlook and then running the macro for only that selected emails.
This is an example of a subject that has the
Example Subject
RE: TS001889493 - Translation failure - Inbound - ( VEXP/ HONCE/ Document Type 214 - Map AVE_NMHG_I_214_4010_XML_SAT - Error Conditional Relationship Error in N103 (0066) [ ref:_00D50c9MW._5000z1J3cG8:ref ]
Example of body
Dear Valued Trading Partner,
We received the attached 214 transactions from Sender ID: VEXP/ Receiver ID: HONCE that failed due to Conditional Relationship Error in the N1_03 (0066).
As per the map logic, If either N103 or N104 is present, then the other is required as they are in conditional relationship with each other.
But in the input file received, N104 value is missing hence the error.
Transaction Details: #4#
Attached
Please correct and resend the data.
Thank you,
Simon Huggs | Sass support - Basic
ref:_00D50c9MW._5000z1J3cG8:ref
What happens in the #num# is that it gets the sum of all these after making a match of the "TS" ticket ID.
This is the code I have up until now
Option Explicit
Sub WritingTicketNumberAndfailuresnew()
Dim xlApp As Object
Dim xlWB As Object
Dim xlSheet As Object
Dim rCount, STicket, SticketNumber As Long
Dim bXStarted As Boolean
Dim enviro As String
Dim strPath, SSubject As String
Dim currentExplorer As Explorer
Dim Selection As Selection
Dim olItem As Outlook.MailItem
Dim obj As Object
Dim strColS, strColB, sassupport, sMailDateReceived, SFrom As String
Dim Actions1, Actions2, Actions3, Actions4 As Boolean
Dim I, cnt, email_needed As Integer
' Get Excel set up
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
'Open a specific workbook to input the data the path of the workbook under the windows user account
enviro = CStr(Environ("USERPROFILE"))
strPath = enviro & "\Documents\topthreeticket.xlsx"
Set xlWB = xlApp.Workbooks.Open(strPath)
Set xlSheet = xlWB.Sheets("Sheet1")
' Add column names
xlSheet.Range("A1") = "Email Subject"
xlSheet.Range("B1") = "Map Name"
xlSheet.Range("C1") = "Case Number"
xlSheet.Range("D1") = "No. Of Failures"
xlSheet.Range("E1") = "Date"
xlSheet.Range("F1") = "Week Number"
sassupport = "sassuport#sass.com"
On Error Resume Next
'Find the next empty line of the worksheet
rCount = xlSheet.Range("A" & xlSheet.Rows.Count).End(-4162).Row
'needed for Exchange 2016. Remove if causing blank lines.
rCount = rCount + 1
' get the values from outlook
Set currentExplorer = Application.ActiveExplorer
Set Selection = currentExplorer.Selection
For Each obj In Selection
Set olItem = obj
'collect the fields for ticket number and failure count
strColS = olItem.Subject
strColB = olItem.Body
SFrom = olItem.SenderEmailAddress
sMailDateReceived = olItem.ReceivedTime
Dim sFailures, stmp1, stmp2, stmp3 As String
Dim RegX As Object, Mats As Object
Dim Found As Boolean
' Check the number of failures from body
sFailures = "0"
stmp1 = strColB
Set RegX = CreateObject("VBScript.RegExp")
With RegX
.Global = True
.Pattern = "#\d+#"
Set Mats = .Execute(stmp1)
End With
If (RegX.Test(stmp1)) Then
stmp2 = Mats(0)
Found = True
stmp3 = Mid(stmp2, 2, Len(stmp2) - 2)
sFailures = stmp3
Else
With RegX
.Pattern = "#d\d+"
Set Mats = .Execute(stmp1)
End With
If (RegX.Test(stmp1)) Then
stmp2 = Mats(0)
Found = True
stmp3 = Mid(stmp2, 2, Len(stmp2) - 1)
sFailures = stmp3
End If
End If
Set Mats = Nothing
Set RegX = Nothing
Dim tmp As String
Dim RegX2 As Object, Mats1 As Object
tmp = strColS
Set RegX2 = CreateObject("VBScript.RegExp")
With RegX2
.Global = True
.Pattern = "TS00\d{7}"
Set Mats1 = .Execute(tmp)
End With
If (RegX2.Test(tmp)) Then
Set Mats1 = RegX2.Execute(tmp)
tmp = Mats1(0)
Else
With RegX2
.Pattern = "T.S\d{9}"
Set Mats1 = .Execute(tmp)
End With
If (RegX.Test(tmp)) Then
tmp = Mats1(0)
End If
End If
Set Mats1 = Nothing
Set RegX2 = Nothing
Dim tempticketnum, tmpdate As String
Dim ticketnumposition As Integer
'write them in the excel sheet
If SFrom = sassupport Then
xlSheet.Range("A" & rCount) = strColS
xlSheet.Range("B" & rCount) = tmp2
xlSheet.Range("C" & rCount) = tmp
xlSheet.Range("D" & rCount) = sFailures ' number of failures
xlSheet.Range("E" & rCount) = sMailDateReceived
rCount = rCount + 1
End If
Next
Set olItem = Nothing
Set obj = Nothing
Set currentExplorer = Nothing
Set xlSheet = Nothing
Set xlWB = Nothing
Set xlApp = Nothing
End Sub
You can use the SPLIT function in VBA, something like so
Sub x()
Dim s As String
Dim a() As String
s = "this-will-test-this-out"
a = Split(s, "-")
Range("a1").Resize(UBound(a) + 1, 1).Value = Application.Transpose(a)
End Sub
The code below is used to extract data of email from any folder in Outlook and display those data in an Excel file.
The data will display the sender name,sender email address, the subject and the time received.
But is there a way for the code to detect if the email have any attachment and will display yes or no for the presence of attachment or attachments in the email in another Excel column ?
Attached below is the code:
Option Explicit
Sub ExportDataToExcel()
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 olItem As Outlook.MailItem
Dim obj As Object
Dim strColA, strColB, strColC, strColD As String
Dim currentExplorer As Outlook.NameSpace
Dim Selection As Outlook.MAPIFolder
' Get Excel set up
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
'======== Open a specific workbook to input the data ============
'the path of the workbook under the windows user account
enviro = CStr(Environ("USERPROFILE"))
strPath = enviro & "\Desktop\New folder\OutlookItems.xlsx"
Set xlWB = xlApp.Workbooks.Open(strPath)
Set xlSheet = xlWB.Sheets("Sheet1")
'================== End Specific workbook ====================
'=================== Use New Workbook ========================
'Set xlWB = xlApp.Workbooks.Add
'Set xlSheet = xlWB.Sheets("Sheet1")
'================== end use new workbook =====================
' Add column names
xlSheet.Range("A1") = "SENDER"
xlSheet.Range("B1") = "SENDER ADDRESS"
xlSheet.Range("C1") = "MESSAGE SUBJECT"
xlSheet.Range("D1") = "RECEIVED TIME"
xlSheet.Range("A1").Interior.Color = RGB(0, 255, 255)
xlSheet.Range("B1").Interior.Color = RGB(0, 255, 255)
xlSheet.Range("C1").Interior.Color = RGB(0, 255, 255)
xlSheet.Range("D1").Interior.Color = RGB(0, 255, 255)
' Process the message record
On Error Resume Next
'Find the next empty line of the worksheet
rCount = xlSheet.Range("A" & xlSheet.Rows.Count).End(-4162).Row
'needed for Exchange 2016. Remove if causing blank lines.
rCount = rCount + 1
' get the values from outlook
Set currentExplorer = Application.GetNamespace("MAPI")
Set Selection = currentExplorer.PickFolder
For Each obj In Selection.Items
Set olItem = obj
'collect the fields
strColA = olItem.SenderName
strColB = olItem.SenderEmailAddress
strColC = olItem.Subject
strColD = olItem.ReceivedTime
'================== Get all recipient addresses ===================
' instead of To names
Dim strRecipients As String
Dim Recipient As Outlook.Recipient
For Each Recipient In olItem.Recipients
strRecipients = Recipient.Address & "; " & strRecipients
Next Recipient
'================== end all recipients addresses ==================
'==================== 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 =====================
'write them in the excel sheet
xlSheet.Range("A" & rCount) = strColA ' sender name
xlSheet.Range("B" & rCount) = strColB ' sender address
xlSheet.Range("C" & rCount) = strColC ' message subject
xlSheet.Range("D" & rCount) = strColD ' recieved time
'Next row
rCount = rCount + 1
' size the cells
xlSheet.Columns("A:D").EntireColumn.AutoFit
xlSheet.Columns("C:C").ColumnWidth = 100
xlSheet.Range("A2").Select
xlSheet.Columns("A:D").VerticalAlignment = xlTop
Next
xlApp.Visible = True
' to save but not close
'xlWB.Save
' to save and close
' xlWB.Close 1
' If bXStarted Then
' xlApp.Quit
' End If
' end save and close
Set olItem = Nothing
Set obj = Nothing
Set currentExplorer = Nothing
Set xlSheet = Nothing
Set xlWB = Nothing
Set xlApp = Nothing
End Sub
Sure, check that olItem.Attachments.Count > 0
Simply use If olItem.Attachments.Count > 0 Then strColE = "YES"
Example
'================== end all recipients addresses ==================
' check for attachment
Dim strColE As String
If olItem.Attachments.Count > 0 Then strColE = "YES"
'==================== Get the Exchange address ====================
Then add xlSheet.Range("E" & rCount) = strColE ' Attament to
'write them in the excel sheet
xlSheet.Range("A" & rCount) = strColA ' sender name
xlSheet.Range("B" & rCount) = strColB ' sender address
xlSheet.Range("C" & rCount) = strColC ' message subject
xlSheet.Range("D" & rCount) = strColD ' recieved time
xlSheet.Range("E" & rCount) = strColE ' Attament
I have been tasked with getting a list of all the users who sent mail to a mailbox in Outlook and transferring it to an excel sheet. Specifically, the sender's name, email address, as well as retrieving the sender's alias from the GAL address book.
For a somewhat large amount of the users, instead of their email address transferring, the X500 address is what shows up as follows: /O=OREGON STATE UNIVERSITY/OU=EXCHANGE ADMINISTRATIVE GROUP (FYDIBOHF23SPDLT)/CN=RECIPIENTS/CN
This is just an example I found online but the format is exactly the way it shows up in the Excel sheet.
I don't have a large knowledge of VBA, so maybe not getting too technical would be helpful.
Here's the code I have (the majority of which I found online):
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 oAL As Outlook.AddressList
Dim olAE As Outlook.AddressEntries
Dim oAE As Outlook.AddressEntry
Dim currentExplorer As Explorer
Dim Selection As Selection
Dim olItem As Outlook.MailItem
Dim obj As Object
Dim strColB, strColC, strColD As String
enviro = CStr(Environ("USERPROFILE"))
'where to find excel sheet
strPath = enviro & "\Documents\EmailList.xlsx"
On Error Resume Next
Set xlApp = GetObject(, "Excel.Application")
If err <> 0 Then
Set xlApp = CreateObject("Excel.Application")
End If
'Where to transfer the info
Set xlWB = xlApp.workbooks.Open(strPath)
Set xlSheet = xlWB.sheets("Sheet1")
'Find the next empty line of the worksheet
rCount = xlSheet.Range("C" & xlSheet.Rows.Count).End(4000).Row
' where to find the information
Set currentExplorer = Application.ActiveExplorer
Set Selection = currentExplorer.Selection
For Each obj In Selection
Set olItem = obj
'extract the information
strColB = olItem.SenderName
strColC = olItem.SenderEmailAddress
strColD = olItem.Sender.GetExchangeUser.Alias
'Get the Exchange address
Dim olEU As Outlook.ExchangeUser
Dim oEDL As Outlook.ExchangeDistributionList
Dim recip As Outlook.Recipient
Set recip = Application.session.CreateRecipient(strColB)
If InStr(1, strColC, "/") > 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
strColC = olEU.PrimarySmtpAddress
End If
Case OlAddressEntryUserType.olOutlookContactAddressEntry
Set olEU = recip.AddressEntry.GetExchangeUser
If Not (olEU Is Nothing) Then
strColC = olEU.PrimarySmtpAddress
End If
Case OlAddressEntryUserType.olExchangeDistributionListAddressEntry
Set oEDL = recip.AddressEntry.GetExchangeDistributionList
If Not (oEDL Is Nothing) Then
strColC = olEU.PrimarySmtpAddress
End If
End Select
End If
'write them in the excel sheet
xlSheet.Range("B" & rCount) = strColB
xlSheet.Range("C" & rCount) = strColC
xlSheet.Range("D" & rCount) = strColD
'Next row
rCount = rCount + 1
Next
xlWB.Close 1
If bXStarted Then
xlApp.Quit
End If
Set olItem = Nothing
Set obj = Nothing
Set currentExplorer = Nothing
Set xlApp = Nothing
Set xlWB = Nothing
Set xlSheet = Nothing
You never guard for the fact that GetExchangeUser can return null. And why do you call CreateRecipient? You already have the AddressEntry object
Off the top of my head:
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 oAL As Outlook.AddressList
Dim olAE As Outlook.AddressEntries
Dim oAE As Outlook.AddressEntry
Dim currentExplorer As Explorer
Dim Selection As Selection
Dim olItem As Outlook.MailItem
Dim obj As Object
Dim strColB, strColC, strColD As String
Dim olEU As Outlook.ExchangeUser
dim olSender As Object
enviro = CStr(Environ("USERPROFILE"))
'where to find excel sheet
strPath = enviro & "\Documents\EmailList.xlsx"
On Error Resume Next
Set xlApp = GetObject(, "Excel.Application")
If err <> 0 Then
Set xlApp = CreateObject("Excel.Application")
End If
'Where to transfer the info
Set xlWB = xlApp.workbooks.Open(strPath)
Set xlSheet = xlWB.sheets("Sheet1")
'Find the next empty line of the worksheet
rCount = xlSheet.Range("C" & xlSheet.Rows.Count).End(4000).Row
' where to find the information
Set currentExplorer = Application.ActiveExplorer
Set Selection = currentExplorer.Selection
For Each obj In Selection
Set olItem = obj
'extract the information
strColB = olItem.SenderName
strColC = olItem.SenderEmailAddress
set olSender = olItem.Sender
if Not (olSender Is Nothing) Then
set olEU = olSender.GetExchangeUser
if (olEU Is Nothing) Then
strColD = ""
Else
strColC = olEU.PrimarySmtpAddress
strColD = olEU.Alias
End If
'write them in the excel sheet
xlSheet.Range("B" & rCount) = strColB
xlSheet.Range("C" & rCount) = strColC
xlSheet.Range("D" & rCount) = strColD
'Next row
rCount = rCount + 1
End If
Next
xlWB.Close 1
If bXStarted Then
xlApp.Quit
End If
Set olItem = Nothing
Set obj = Nothing
Set currentExplorer = Nothing
Set xlApp = Nothing
Set xlWB = Nothing
Set xlSheet = Nothing
I have macro which exports all data from Outlook INBOX to Excel along with time and date, but I need to set up to a particular folder to be copied in a same way.
How do I setup to specific subfolder?
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
'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
You are using ActiveExplorer.CurrentFolder on your code, the CurrentFolder Property represents the current folder that is displayed in the explorer, code should run on any Active Explorer- just navigate on any folder that you like to run the code on.
If you prefer to change then You need to modify the following lines of code to set up your specified folder,
' get the values from outlook
Set objOL = Outlook.Application
Set objFolder = objOL.ActiveExplorer.CurrentFolder
To something like this
' get the values from outlook
Set objOL = Outlook.Application
Dim olNs As Outlook.NameSpace
Set olNs = objOL.GetNamespace("MAPI")
Set objFolder = olNs.GetDefaultFolder(olFolderInbox).Folders("SubFolder Name Here")
See Folder Object (Outlook) MSDN Use the Folders property of a NameSpace object or another Folder object to return the set of folders in a NameSpace or under a folder. You can navigate nested folders by starting from a top-level folder, say the Inbox, and using a combination of the Folder.Folders property, which returns the set of folders underneath a Folder object in the hierarchy,
Example:
GetDefaultFolder(olFolderInbox).Folders("SubFolderName") _
.Folders("SubFolderName")
and the Folders.Item method, which returns a folder within the Folders collection.
I am needing to copy some data from emails into a spreadsheet with a VBA, here is how the data is formatted in the email:
Items/Cost:
Item Description 1: $38.88
Quantity: 1
Item Description 2: $39.99
Quantity: 1
The Item Description is always different. Here is how I would like the output to be formatted when copied to Excel:
And here is my current code that I've tried:
Sub CopyToExcel()
Dim xlApp As Object
Dim xlWB As Object
Dim xlSheet As Object
Dim xl
Dim olItem As Outlook.MailItem
Dim vText As Variant
Dim sText As String
Dim vItem As Variant
Dim i As Long
Dim rCount As Long
Dim bXStarted As Boolean
Dim rTime As Date
Const strPath As String = "C:\Tracking.xlsx" 'the path of the workbook
If Application.ActiveExplorer.Selection.Count = 0 Then
MsgBox "No Items selected!", vbCritical, "Error"
Exit Sub
EndIf
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
'Open the workbook to input the data
Set xlWB = xlApp.Workbooks.Open(strPath)
Set xlSheet = xlWB.Sheets("Sheet1")
xlWB.Sheets(1).Cells.Delete
'Process each selected record
rCount = xlSheet.UsedRange.Rows.Count
'cCount = xlSheet.UsedRange.Columns.Count
For Each olItem In Application.ActiveExplorer.Selection
sText = olItem.Body
rTime = Format(olItem.ReceivedTime, "mmmm d, yyyy")
vText = Split(sText, Chr(13))
'Find the next empty line of the worksheet
rCount = rCount + 1
'Check each line of text in the message body
For i = UBound(vText) To 0 Step -1
If InStr(vText(i), "Items/Cost:") Then
'ParseText = vText(i + 1) & vbCrLf
xlSheet.Range("A" & rCount) = Trim(vText(2))
vItem = Split(vText(4), Chr(58))
xlSheet.Range("B" & rCount) = Trim(vItem(1))
xlSheet.Range("A" & rCount + 1) = Trim(vText(6))
vItem = Split(vText(8), Chr(58))
xlSheet.Range("B" & rCount + 1) = Trim(vItem(1))
xlSheet.Range("A" & rCount + 2) = Trim(vText(10))
vItem = Split(vText(12), Chr(58))
xlSheet.Range("B" & rCount + 2) = Trim(vItem(1))
xlSheet.Range("A" & rCount + 3) = Trim(vText(14))
vItem = Split(vText(16), Chr(58))
xlSheet.Range("B" & rCount + 3) = Trim(vItem(1))
xlSheet.Range("A" & rCount + 4) = Trim(vText(18))
vItem = Split(vText(20), Chr(58))
xlSheet.Range("B" & rCount + 4) = Trim(vItem(1))
End If
Next i
xlWB.Save
Next olItem
Set xlApp = Nothing
Set xlWB = Nothing
Set xlSheet = Nothing
Set olItem = Nothing
End Sub
Also I'm no expert at VB so any help is greatly appreciated.
UPDATE:
I figured out how to extract it the way I want to but it's sloppy and not dynamic. Sometimes there are 2 items and sometimes 5, so i need it to be adaptable. Can someone help me clean it up by chance?
Try the following
Option Explicit
Sub EmailToCsv()
Dim olItem As Outlook.MailItem
Dim xlApp As Excel.Application
Dim xlWB As Excel.Workbook
Dim xlSheet As Excel.Worksheet
Dim vText As Variant
Dim sText As String
Dim vItem As Variant
Dim i As Long
Dim RowCount As Long
Dim xlStarted As Boolean
Dim FilePath As String
'// Update File location
FilePath = "C:\Temp\Tracking.xlsx"
'// Process Selections
If Application.ActiveExplorer.Selection.Count = 0 Then
MsgBox "No Items selected!", vbCritical, "Error"
Exit Sub
End If
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")
xlStarted = True
End If
On Error GoTo 0
'// Open the workbook to input the data
Set xlWB = xlApp.Workbooks.Open(FilePath)
Set xlSheet = xlWB.Sheets("Sheet1")
'// Process each selected record
For Each olItem In Application.ActiveExplorer.Selection
sText = olItem.Body
vText = Split(sText, Chr(13)) ' Chr(13)) carriage return
'// Find the next empty line of the worksheet
RowCount = xlSheet.Range("A" & xlSheet.Rows.Count).End(xlUp).Row
RowCount = RowCount + 1
'// Check each line of text in the message body
For i = UBound(vText) To 0 Step -1
'// Item Description 1
If InStr(1, vText(i), "Item Description 1:") > 0 Then
vItem = Split(vText(i), Chr(58)) ' Chr(58) ":"
xlSheet.Range("A" & RowCount) = "Item Description 1: " & Trim(vItem(1))
End If
'// Quantity
If InStr(1, vText(i), "Quantity:") > 0 Then
vItem = Split(vText(i), Chr(58))
xlSheet.Range("B" & RowCount) = Trim(vItem(1))
End If
'// Item Description 2
If InStr(1, vText(i), "Item Description 2:") > 0 Then
vItem = Split(vText(i), Chr(58))
xlSheet.Range("A" & RowCount + 1) = "Item Description 2: " & Trim(vItem(1))
End If
'// Quantity
If InStr(1, vText(i), "Quantity:") > 0 Then
vItem = Split(vText(i), Chr(58))
xlSheet.Range("B" & RowCount + 1) = Trim(vItem(1))
End If
Next i
Next olItem
'// SaveChanges & Close
xlWB.Close SaveChanges:=True
If xlStarted Then
xlApp.Quit
End If
Set xlApp = Nothing
Set xlWB = Nothing
Set xlSheet = Nothing
Set olItem = Nothing
End Sub