Read the content of Email attachment to Excel - excel

I'm getting my Job logs to my Outlook email, where the subject contains most of the necessary details like what job, which day, what server and the status. I used Date as a parameter to get the email into Excel.
I'm trying to take it further. If a job fails generate a log either in the body of the email or as an email attachment.
For the log in the mail body I brought those to the sheet and parsed with the search term "Error" and captured the line.
For the attachment I can only save it in a folder and get the name in Excel. Is there any way I could read the content of the attachment, search for "Error" and bring only that line to the Excel sheet.
Option Explicit
Const AttachmentPath As String = "C:\users\maharaj\qalogs\"
Sub GetFromOutlook2()
Dim outlookAtch As Object
Dim NewFileName As String
NewFileName = AttachmentPath & Format(Date, "DD-MM-YYYY") & "-"
Dim OutlookApp As Outlook.Application
Dim OutlookNamespace As Namespace
Dim Folder As MAPIFolder
Dim OutlookMail As Variant
Dim i As Integer
Set OutlookApp = New Outlook.Application
Set OutlookNamespace = OutlookApp.GetNamespace("MAPI")
Set Folder = OutlookNamespace.GetDefaultFolder(olFolderInbox).Folders("QALOGS")
i = 1
For Each OutlookMail In Folder.Items
If OutlookMail.ReceivedTime "GREATER THAN or EQUAL TO" = Range("start_Date").Value Then
Range("email_Subject").Offset(i, 0).Value = OutlookMail.Subject
Range("email_Date").Offset(i, 0).Value = OutlookMail.ReceivedTime
Range("email_Sender").Offset(i, 0).Value = OutlookMail.SenderName
Range("email_Body").Offset(i, 0).Value = OutlookMail.Body
outlookAtch.SaveAsFile NewFileName & outlookAtch.Filename
Range("email_attachment").Offset(i, 0).Value = outlookAtch
End If
i = i + 1
Next OutlookMail
Set Folder = Nothing
Set OutlookNamespace = Nothing
Set OutlookApp = Nothing
End Sub

First of all, I'd recommend using the Restrict or Find/FindNext methods of the Items class instead of iterating over all items in the folder:
For Each OutlookMail In Folder.Items
If OutlookMail.ReceivedTime "GREATER THAN or EQUAL TO" = Range("start_Date").Value Then
Read more about these methods in the following articles:
How To: Use Find and FindNext methods to retrieve Outlook mail items from a folder (C#, VB.NET)
How To: Use Restrict method to retrieve Outlook mail items from a folder
Also, you may consider using the AdvancedSearch method of the Application class. The key benefits of using the AdvancedSearch method in Outlook are:
The search is performed in another thread. You don’t need to run another thread manually since the AdvancedSearch method runs it automatically in the background.
Possibility to search for any item types: mail, appointment, calendar, notes etc. in any location, i.e. beyond the scope of a certain folder. The Restrict and Find/FindNext methods can be applied to a particular Items collection (see the Items property of the Folder class in Outlook).
Full support for DASL queries (custom properties can be used for searching too). You can read more about this in the Filtering article in MSDN. To improve the search performance, Instant Search keywords can be used if Instant Search is enabled for the store (see the IsInstantSearchEnabled property of the Store class).
You can stop the search process at any moment using the Stop method of the Search class.
For the Attachment i can only able to save them in a folder and get give them name in the excel.
Yes, you are on the right avenue. The attached file should be saved on the disk first. Depending on the file extension you can automate an appropriate application for reading its content or just using IO operations for reading the content directly without involving Office applications.

Related

Excel VBA: How to combine multiple Excel files with same layout in a single folder into a single sheet?

So, I want to create an Excel VBA that saves all the attachments of an Outlook folder to the single Excel file (all the files will have the same layout but different data) and then combine the Excel files in that folder into the active worksheet.
I've already succeeded to save all attachments into one folder. However, I've failed to combine these files into one sheet. Can you help with that?
Thank you very much
I have tried several things for the second part of my problem but it didn't work. Here is the first part of my code:
Option Explicit
Sub IKDISKETI()
Dim ol As Outlook.Application
Dim ns As Outlook.Namespace
Dim fol As Outlook.Folder
Dim i As Object
Dim mi As Outlook.MailItem
Dim at As Outlook.Attachment
Set ol = New Outlook.Application
Set ns = ol.GetNamespace("MAPI")
Set fol = ns.Folders(1).Folders("IKDISKET")
For Each i In fol.Items
If i.Class = olMail Then
Set mi = i
If mi.Attachments.Count > 0 Then
Debug.Print mi.SenderName, mi.ReceivedTime, mi.Attachments.Count
For Each at In mi.Attachments
Debug.Print vbTab, at.DisplayName, at.Size
at.SaveAsFile "C:\IKDISKET\" & at.Filename
Next at
End If
End If
Next i
End Sub
Option Explicit
You can automate Excel for merging Excel files into a single one. For that you need to open each file and extract the required data. Note, you can use the Copy&Paste commands for copying the required information quicker. See Early and Late Binding (Visual Basic) for more information how to create a new Excel Application instance and open files.
Also if you deal with open XML documents only you may consider using the Open XML SDK, see Welcome to the Open XML SDK 2.5 for Office.

VBA Outlook email recipient format

Good day,
I'm trying to automate my outlook.
I have an excel list with mails and a code is composing drafts for me.
But here is a problem when I try to send a mail in web version it states
error: "This message can't be sent right now. Please try again later."
Mails appear correct in desktop version, but not in web.
Sub Box()
Dim objOL As Object
Set objOL = CreateObject("Outlook.Application")
Dim Name As Namespace
Set Name = objOL.GetNamespace("MAPI")
Dim Msg As MailItem
Set Msg = objOL.CreateItemFromTemplate
Msg.To = Cond.Cells(i, 2).Text
Msg.CC = Cond.Cells(i, 3).Text
Msg.Subject = PP.Range("F1").Text
Msg.HTMLBody = "<HTML><BODY>" & Cond.Cells(i, 4) & Cond.Cells(i, 5) & "</BODY></HTML>"
I've tried to. property I've tried Recipient.Add brackets <>.
Can you help me if you know how, please
First, you need to specify the file path of the template:
Set Msg = objOL.CreateItemFromTemplate
The Application.CreateItemFromTemplate method creates a new Microsoft Outlook item from an Outlook template (.oft) and returns the new item. It requires at least one parameter passed - the path and file name of the Outlook template for the new item.
Second, to set up To and CC properties:
Msg.To = Cond.Cells(i, 2).Text
Msg.CC = Cond.Cells(i, 3).Text
These properties expect to be set to a semicolon-delimited string list of display names for the To or CC recipients for the Outlook item. Make sure that you pass a valid string.
A better approach is to use the Recipients property of Outlook items. The Recipients.Add method creates a new recipient in the Recipients collection. Then don't forget to use the Resolve or ResolveAll methods. They attempt to resolve one or all the Recipient objects in the Recipients collection against the Address Book, for example:
' now we add new recipietns to the e-mail
recipientTo = recipients.Add("Eugene Astafiev")
recipientTo.Type = Outlook.OlMailRecipientType.olTo
recipientCC = recipients.Add("Someone Else")
recipientCC.Type = Outlook.OlMailRecipientType.olCC
recipientBCC = recipients.Add("eugene.astafiev#somedomain.com")
recipientBCC.Type = Outlook.OlMailRecipientType.olBCC
retValue = recipients.ResolveAll()
Read more about that in article that I wrote for the technical blog - How To: Fill TO,CC and BCC fields in Outlook programmatically.

How to send multiple hyperlinks with mail in Excel VBA, depending on the cell value

There is and light order managment system where you can order a few items. When you have chosen your order, you click a button, and the rows that is order and number of items is copied to a new confirmation sheet. This sheet is then supposed to be sent to a chosen reciever by oMail. This works fine.
But in one of the columns there is a certificate on PDF(hyperlink), that is linked to a server(local file on my computer:))
I'm trying to send this PDF's as multiple hyperlinks in the mail, but that is no sucess :p. The thing I want to do is check if the cell is empty, if not, attach the hyperlink(s) in my stringbody. And send the mail.
Here is my code:
I use a function also to make the range to html format:
It's more useful to edit e-mail body via GetInstector
For example:
Dim myInspector As Object'inspector object
Dim wdDoc As Object''document
Dim myitem As Object'mailitem
Set myitem = CreateObject("Outlook.Application").CreateItem(0)'creating mailitem from Excel
Set myInspector = myitem.GetInspector'set inspector to edit mailitem
Set wdDoc = myInspector.WordEditor'set MS Word to edit mailbody
With myitem'here you are setting the e-mail properties
.To = Email'fill to e-mail
.Subject = Subja'Subject
.Display'display mailitem etc.
End With
'here edit the body with MS Word methods
wdDoc.Range.Paragraphs.Add
wdDoc.Range.Paragraphs.item(1).Range.Text = "Something you want in 1st paragraph" & vbCr
wdDoc.Range.Paragraphs.Add
wdDoc.Range.Paragraphs.item(2).Range.Text = "Something else you want in 2nd paragraph " & vbCr
So, actually you edit e-mail programmatically the same as you do it in Word. It makes useless long and complicated string with HTML-tags. You add MS Word objects and forms.

How to save emails to a specific folder in drafts?

I wrote Excel VBA code to generate emails from a report that is downloaded into Excel. It saves to the "drafts" folder in Outlook.
I want to save to another folder within drafts to keep them separate from my regular drafts.
This is what I have.
With objMail
.To = rngTo
.Subject = "Next 2 Weeks Orders"
.HTMLBody = intro & vbNewLine & po & signiature
.Save
End With
There are several ways to create new items in Outlook. If you need to save a new item to a specific folder in Outlook you choices are:
Create a new item using the CreateItem method and then use the MoveTo method to place the item to the target folder.
Use the Items.Add method which places new items to the folder where the Items collection comes from. For example:
nSpace = OutlookApp.GetNamespace("MAPI")
targetFolder = nSpace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox)
folderItems = targetFolder.Items
mail = folderItems.Add(Outlook.OlItemType.olMailItem)
You can find all these ways described with code samples in the How to create and show a new Outlook mail item programmatically: C#, VB.NET article.
What is your code that actually creates objMail? Are you using Application.CreateItem? Use MAPIFolder.Items.Add on a specific folder instead. Assuming "My custom subfolder" is a child folder of the Drafts folder:
set folder = objOutlook.Session.GetDefaulFolder(16) 'olfolderDrafts
set folder = folder.Folders("My custom subfolder")
set objMail = folder.Items.Add

Save Outlook Attachment to Folder on PC using Excel VBA

I am trying to save attachments from a sub-folder in Outlook to a folder on my C drive using Excel VBA.
For example, in my inbox folder I have a sub-folder called 'data' and in this folder there are emails with different excel attachments of different data but with the same formatting and the same attachment name but with an updated date (Eg: "Attachment name + 28 March").
These emails are sent daily. I want all attachments, not already saved, saved to a folder on my C drive and then open each attachment to extract the relevant data to Excel.
I am able to extract the relevant data once the files are in my C drive but I am unable to set up a path from my Excel to Outlook without Outlook VBA (which I don't want to do).
This is what I have so far: (the comments are for my benefit because I am new to this)
Sub attachmentsave()
Dim olook As Outlook.Application
Dim omailitem As Outlook.mailitem
'whenever dealing with folders we need to define outlook.namespace This is a class that opens the gate for me to access all outlook folders
Dim onamespace As Outlook.Namespace
Dim fol As Outlook.Folder 'we need to tell vba where we have out emails with attachments stored
Dim atmt As Outlook.Attachment '.attachment is a class that will help us deal with emails that have attachments
Set olook = New Outlook.Application
Set omailitem = olook.CreateItem(olmailitem)
'messaging application protocol interface
Set onamespace = olook.GetNameSpace("MAPI")
Set fol = onamespace.GetDefaultFolder(olFolderInbox)
For Each omailitem In fol.items
For Each atmt In omailitem.attachments
atmt.SaveAsFile "C:/" & atmt.FileName
'all attachments in inbox should be save in C drive
Next
Next
End Sub
You need a macro-enabled Excel workbook with a reference to "Microsoft Output nn.n Object Library" where “nn.n” depends on the version of Office you are running. Please do not mix versions; I have never tried but I understand it causes problems.
I am assuming you are familiar with Excel VBA and know how to create a macro-enabled workbook. From your comments, I assume you do not know about references.
Much of the power of VBA is not native but comes from libraries which you can reference if you need their functionality. Open the VBA Editor and click Tools and then References. You will get a long list of available references. Those at the top will be ticked. For example, "Microsoft Excel nn.n Object Library" will be ticked. Without this reference, the compiler would not know what a range or a worksheet was. Note: "nn.n" depends on the version of Office you are using. For me, the value is "16.0" because I am using Office 365.
Unticked references are in alphabetic sequence. Scroll down the list until you find "Microsoft Outlook nn.n Object Library". Click the box to the left to tick this reference. Click "OK". If you click Tools then References again you will see "Microsoft Outlook nn.n Object Library" ticked and near the top. The compiler now has access to the definitions of MailItem, Folder and the rest of the Outlook Object Model.
Copy the code below to a new module:
Option Explicit
Sub ListStores()
' Needs reference to "Microsoft Output nn.n Object Library"
' where "nn.n" depends on the version of Outlook you are using.
Dim AppOut As New Outlook.Application
Dim InxStoreCrnt As Long
Dim FldrInbox As Outlook.Folder
With AppOut
With .Session
Debug.Print "List of stores:"
For InxStoreCrnt = 1 To .Folders.Count
Debug.Print " " & .Folders(InxStoreCrnt).Name
Next
Set FldrInbox = .GetDefaultFolder(olFolderInbox)
Debug.Print "Store for default Inbox: " & FldrInbox.Parent.Name
End With
End With
AppOut.Quit
Set AppOut = Nothing
End Sub
VBA usually has more than one method of achieving a desired effect. You have used “NameSpace” in your code whilst I have used “Session”. The documentation says these two methods are equivalent. If you write your own code, you can pick whichever method you prefer. But if you go looking for useful snippets, you must be ready for other people having different preferences.
Dim AppOut As New Outlook.Application creates an instance of Outlook that will access Outlook’s files on behalf of the macro.
With AppOut
With .Session
: : : :
End With
End With
I can replace : : : : with any Outlook VBA. If an Excel macro tries to access an email, the user will be warned and asked to give permission for the macro to run.
Outlook keeps emails, appointments, tasks and so on in files it calls Stores. You may see these called PST files because most have an extension of PST but an OST file is also a store. You may see them called Accounts because, by default, Outlook creates one store per email account. However, you can create as many extra stores as you want, none of which will be Accounts.
This code will create a list of the stores you can access:
Debug.Print "List of stores:"
For InxStoreCrnt = 1 To .Folders.Count
Debug.Print " " & .Folders(InxStoreCrnt).Name
Next
The output might look something like:
List of stores:
Outlook Data File
Smith John#ISPOne.com
Archive Folders
Backup
John Smith#ISPTwo.com
OutlookOutlook
The above is based on my home installation. A work installation is likely to be somewhat different. The differences will depend on the options chosen during installation. A work installation is also likely to included shared folders which I do not have on my system.
If you look at your folder pane, you will have names with other names indented underneath. The names be will the stores and will match the stores listed by the macro although the sequence will probably be different. The other names in the folder pane will be the folders within each store.
The last bit of my macro is:
Set FldrInbox = .GetDefaultFolder(olFolderInbox)
Debug.Print "Store for default Inbox: " & FldrInbox.Parent.Name
You have similar code to access an Inbox but this may not be the Inbox you want. On my system, this code outputs:
Store for default Inbox: Outlook Data File
“Outlook Data File” is Outlook’s default store. On my system, the calendar and my tasks are held in this store but my emails are not. I have two email accounts and each has their own store.
Try this above macro. Does GetDefaultFolderfind the Inbox you need to access?
Now add this macro:
Sub ListStoresAndFirstEmails()
' Needs reference to "Microsoft Output nn.n Object Library"
' where "nn.n" depends on the version of Outlook you are using.
Dim AppOut As New Outlook.Application
Dim InxFldrCrnt As Long
Dim InxStoreCrnt As Long
Dim FldrInbox As Outlook.Folder
With AppOut
With .Session
Debug.Print "List of stores and first emails:"
For InxStoreCrnt = 1 To .Folders.Count
Debug.Print " " & .Folders(InxStoreCrnt).Name
For InxFldrCrnt = 1 To .Folders(InxStoreCrnt).Folders.Count
If .Folders(InxStoreCrnt).Folders(InxFldrCrnt).Name = "Inbox" Then
Set FldrInbox = .Folders(InxStoreCrnt).Folders(InxFldrCrnt)
If FldrInbox.Items.Count > 0 Then
With FldrInbox.Items(1)
Debug.Print " Subject: " & .Subject
Debug.Print " Received: " & .ReceivedTime
Debug.Print " From: " & .SenderEmailAddress
End With
End If
Exit For
End If
Next
Next
End With
End With
AppOut.Quit
Set AppOut = Nothing
End Sub
This macro is also about investigating your stores. The macro scans down your stores. For each store, it scans down the list of level 1 folders looking for "Inbox". If it finds "Inbox", it assumes the oldest item in it is a MailItem and outputs its subject, received time and sender. If the oldest item is not a MailItem, you will get an error. I almost hope you do get an error to demonstrate the importance of not making assumptions.
Finally add:
Sub ListAttachments()
Dim AppOut As New Outlook.Application
Dim InxAttachCrnt As Long
Dim InxItemCrnt As Long
Dim InxStoreCrnt As Long
Dim FldrData As Outlook.Folder
With AppOut
With .Session
Set FldrData = .Folders("Outlook Data File").Folders("Inbox").Folders("Data")
End With
End With
Debug.Print "List emails with attachments within: ";
Debug.Print " " & FldrData.Name & " of " & FldrData.Parent.Name & _
" of " & FldrData.Parent.Parent.Name
With FldrData
For InxItemCrnt = 1 To FldrData.Items.Count
If .Items(InxItemCrnt).Class = olMail Then
With .Items(InxItemCrnt)
If .Attachments.Count > 0 Then
Debug.Print " Subject: " & .Subject
Debug.Print " Received: " & .ReceivedTime
Debug.Print " From: " & .SenderEmailAddress
For InxAttachCrnt = 1 To .Attachments.Count
Debug.Print " " & InxAttachCrnt & " " & .Attachments(InxAttachCrnt).DisplayName
Next
End If
End With
End If
Next
End With
AppOut.Quit
Set AppOut = Nothing
End Sub
I always keep some junk emails in store "Outlook Data File" for testing purposes.
In Set FldrData = .Folders("Outlook Data File").Folders("Inbox").Folders("Data") you need to replace "Outlook Data File" with the name of the store containing the emails of interest. If I understand correctly, the emails are in folder "Data" under folder "Inbox". If I have misunderstood, notice how I have used a chain of "Folders(xxxx)" to reach the required folder. In earlier emails I have used indices to reach stores and folders. Here I have specified a specific folder.
Within that folder I look for MailItems (showing how to avoid other items) and if they have attachments, list some properties of the email and the names of its attachments.
This is as far as I can go because I do not fully understand your explanation of how attachments are named or where you want attachments saved.

Resources