Open Outlook Mail .msg file using VBA from Excel - excel

I'm trying to open .msg files from a specified directory using VBA but I keep getting a runtime error.
The code i have:
Sub bla()
Dim objOL As Object
Dim Msg As Object
Set objOL = CreateObject("Outlook.Application")
inPath = "C:\Users\SiliconPlus\Desktop\Si+ Contact Lists\Contact_Si+"
thisFile = Dir(inPath & "\*.msg")
Set Msg = objOL.CreateItemFromTemplate(thisFile)
' now use msg to get at the email parts
MsgBox Msg.Subject
Set objOL = Nothing
Set Msg = Nothing
End Sub
Here is the runtime error:
Run-time error '-2147287038 (80030002)':
Cannot open file: AUTO Andy Low Yong Cheng is out of the office (returning 22 09 2014).msg.
The file may not exist, you may not have permission to open it, or it may be open in another program. Right-click the folder that contains the file, and then click properties to check your permissions for the folder.

Kenneth Li You didn't had the full path when opening the file. Try this:
Sub bla_OK()
Dim objOL As Object
Dim Msg As Object
Set objOL = CreateObject("Outlook.Application")
inPath = "C:\Users\SiliconPlus\Desktop\Si+ Contact Lists\Contact_Si+"
thisFile = Dir(inPath & "\*.msg")
'Set Msg = objOL.CreateItemFromTemplate(thisFile)
Set Msg = objOL.Session.OpenSharedItem(inPath & "\" & thisFile)
' now use msg to get at the email parts
MsgBox Msg.Subject
Set objOL = Nothing
Set Msg = Nothing
End Sub

If you get an error, try the Late Biding (Dim Msg As Object) right under the MsgBox (need to be uncommented) :
Sub Kenneth_Li()
Dim objOL As Outlook.Application
Dim Msg As Outlook.MailItem
Msgbox "If you get an error, try the Late Biding right under this (need to be uncommented)"
'Dim objOL As Object
'Dim Msg As Object
Set objOL = CreateObject("Outlook.Application")
inPath = "C:\Users\SiliconPlus\Desktop\Si+ Contact Lists\Contact_Si+"
thisFile = LCase(Dir(inPath & "\*.msg"))
Do While thisFile <> ""
'Set Msg = objOL.CreateItemFromTemplate(thisFile)
'Or
'Set Msg = objOL.OpenSharedItem(thisFile)
'Set Msg = GetNameSpace("MAPI").OpenSharedItem(thisFile)
'Eventually with Shell command (here for notepad)
'Shell "notepad " & thisFile
Set Msg = objOL.Session.OpenSharedItem(thisFile)
Msg.display
MsgBox Msg.Subject
thisFile = Dir
Loop
Set objOL = Nothing
Set Msg = Nothing
End Sub
Or you can find a nice VB solution there : http://www.mrexcel.com/forum/excel-questions/551148-open-msg-file-using-visual-basic-applications.html#post2721847
And here for more details on Shell method : http://p2p.wrox.com/access-vba/27776-how-open-msg-file-vbulletin.html#post138411

Another way is to run the file programmatically (in VBA use the Shell command). It will be opened in Outlook where you can get an active inspector window with the item opened.

You should check follow code and can modify your code
Sub CreateFromTemplate()
Dim MyItem As Outlook.MailItem
Set MyItem = Application.CreateItemFromTemplate("C:\temp\*.msg")
MyItem.Display
End Sub

Try this
Sub GetMSG()
' True includes subfolders
' False to check only listed folder
ListFilesInFolder "C:\Users\lengkgan\Desktop\Testing", True
End Sub
Sub ListFilesInFolder(SourceFolderName As String, IncludeSubfolders As Boolean)
Dim FSO As Scripting.FileSystemObject
Dim SourceFolder As Scripting.Folder, SubFolder As Scripting.Folder
Dim FileItem As Scripting.File
Dim strFile, strFileType, strAttach As String
Dim openMsg As MailItem
Dim objAttachments As Outlook.Attachments
Dim i As Long
Dim lngCount As Long
Dim strFolderpath As String
'where to save attachments
strFolderpath = "C:\Users\lengkgan\Desktop\Testing"
Set FSO = New Scripting.FileSystemObject
Set SourceFolder = FSO.GetFolder(SourceFolderName)
For Each FileItem In SourceFolder.Files
strFile = FileItem.Name
' This code looks at the last 4 characters in a filename
' If we wanted more than .msg, we'd use Case Select statement
strFileType = LCase$(Right$(strFile, 4))
If strFileType = ".msg" Then
Debug.Print FileItem.Path
Set openMsg = Outlook.Application.CreateItemFromTemplate(FileItem.Path)
openMsg.Display
'do whatever
Set objAttachments = openMsg.Attachments
lngCount = objAttachments.Count
If lngCount > 0 Then
For i = lngCount To 1 Step -1
' Get the file name.
strAttach = objAttachments.Item(i).Filename
' Combine with the path to the Temp folder.
strAttach = strFolderpath & strAttach
' Save the attachment as a file.
objAttachments.Item(i).SaveAsFile strAttach
Next i
End If
openMsg.Close olDiscard
Set objAttachments = Nothing
Set openMsg = Nothing
' end do whatever
End If
Next FileItem
If IncludeSubfolders Then
For Each SubFolder In SourceFolder.SubFolders
ListFilesInFolder SubFolder.Path, True
Next SubFolder
End If
Set FileItem = Nothing
Set SourceFolder = Nothing
Set FSO = Nothing
End Sub
Edited : How to add the reference
Click Tools > Reference.
Check the needed reference

Related

Save Outlook attachment using a cell value as the file name

I'm trying to save the Outlook attachment from a particular sub folder to a local path.
I'm able to save the file as is to the local path.
The requirement is to save the xl attachment using a cell value of ThisWorkbook as the file name.
Sub ManualPunchAttachmentsExtract()
Dim OlFolder As Outlook.MAPIFolder
Dim OlMail As Object
Dim OlApp As Outlook.Application
Dim OlItems As Outlook.Items
Dim Get_namespace As Outlook.Namespace
Dim strFolder As String
Dim i As Integer
ThisWorkbook.Activate
Sheets("MP File Save").Activate
Range("H3").Activate
Set OlApp = GetObject(, "Outlook.Application")
If err.Number = 429 Then
Set OlApp = CreateObject("Outlook.Application")
End If
strFolder = InputBox("Please Enter the Folder Path alongwith ' \ ' at the end", Path)
'Set Get_namespace = OlApp.GetNamespace("MAPI")
Set OlFolder = OlApp.GetNamespace("MAPI").Folders("shaikajaz.k#flex.com").Folders("Archive").Folders("Juarez").Folders("Manual Punch")
Set OlItems = OlFolder.Items
'.Restrict("[Unread]=true")
For Each OlMail In OlItems
If OlMail.UnRead = False Then
Else
ThisWorkbook.Activate
Sheets("MP File Save").Activate
ActiveCell.Value = OlMail.Subject
ActiveCell.Offset(0, 1).Value = OlMail.ReceivedTime
If OlMail.attachments.Count > 0 Then
For i = 1 To OlMail.attachments.Count
OlMail.attachments.Item(i).SaveAsFile strFolder & "\" & OlMail.attachments.Item(i).FileName
OlMail.UnRead = False
ThisWorkbook.Activate
ActiveCell.Offset(1, 0).Select
Next i
Else
End If
End If
Next
MsgBox ("Done")
End Sub
First of all, iterating over all items in an Outlook folder is not realy a good idea. Use the Find/FindNext or Restrict methods of the Items class instead. So, instead of the following code:
For Each OlMail In OlItems
If OlMail.UnRead = False Then
Use this:
Private Sub FindAllUnreadEmails(folder As Outlook.MAPIFolder)
Dim searchCriteria As String = "[UnRead] = true"
Dim counter As Integer = 0
Dim mail As Outlook._MailItem = Nothing
Dim folderItems As Outlook.Items = Nothing
Dim resultItem As Object = Nothing
If (folder.UnReadItemCount > 0) Then
folderItems = folder.Items
resultItem = folderItems.Find(searchCriteria)
While Not IsNothing(resultItem)
If (TypeOf (resultItem) Is Outlook._MailItem) Then
counter += 1
mail = resultItem
Debug.Print("#" + counter.ToString() + _
" - Subject: " + mail.Subject)
End If
resultItem = folderItems.FindNext()
End While
Else
Debug.Print("There is no match in the " + _
folder.Name + " folder.")
End If
End Sub
Note, attached files can have the same file name. So, to uniquelly identify files I'd suggest introducing any IDs in the file name when attachments are saved to the disk.
Finally, to save the attached file with a workbook's content name you need to pass a cell value to the SaveAsFile method:
OlMail.attachments.Item(i).SaveAsFile strFolder & "\" & yourWorksheet.Range("B2").Value

How to reference a search folder?

We are using a VBA macro in Excel to count mails in several Outlook subfolders.
I'd also like to use it to count mails in searchfolders, but it isn't working.
The code loops through different Outlook folders, the location of each of this folders is available in a column in an Excel sheet. (mailbox#mail.com\folder\subfolder - with different possibilities of mailboxes / folders).
We refer to this folder with the following code:
set mailfolder = GetFolder(email_folder)
This is the GetFolder function:
Function GetFolder(ByVal strFolderPath As String) As MAPIFolder
' strFolderPath needs to be something like
' "Public Folders\All Public Folders\Company\Sales" or
' "Personal Folders\Inbox\My Folder"
Dim objApp As Outlook.Application
Dim objNS As Outlook.Namespace
Dim colFolders As Outlook.Folders
Dim objFolder As Outlook.MAPIFolder
Dim arrFolders() As String
Dim i As Long
On Error Resume Next
'strFolderPath = Replace(strFolderPath, "/", "\")
arrFolders() = Split(strFolderPath, "\")
Set objApp = CreateObject("Outlook.Application")
Set objNS = objApp.GetNamespace("MAPI")
Set objFolder = objNS.Folders.Item(arrFolders(0))
If Not objFolder Is Nothing Then
For i = 1 To UBound(arrFolders)
Set colFolders = objFolder.Folders
Set objFolder = Nothing
Set objFolder = colFolders.Item(arrFolders(i))
If objFolder Is Nothing Then
Exit For
End If
Next
End If
Set GetFolder = objFolder
Set colFolders = Nothing
Set objNS = Nothing
Set objApp = Nothing
On Error GoTo 0
End Function
Is there a way to adapt this function to find the searchfolders?
Use the folder name. No path.
Private Sub Test_Unread()
FindSearchFolder "Unread Mail"
End Sub
Private Sub FindSearchFolder(fldrName As String)
Debug.Print
Debug.Print "Searching for " & fldrName
Dim objStores As Stores
Dim objStore As Store
Dim objSearchFolders As folders
Dim objSearchFolder As folder
Dim objItem As Object
Dim bFound As Boolean
Dim i As Long
Set objStores = Session.Stores
For Each objStore In objStores
Debug.Print
Debug.Print "objStore: " & objStore
bFound = False
Set objSearchFolders = objStore.GetSearchFolders
For Each objSearchFolder In objSearchFolders
Debug.Print " objSearchFolder: " & objSearchFolder
If objSearchFolder.name = fldrName Then
Debug.Print " Found in " & objStore
bFound = True
Set ActiveExplorer.CurrentFolder = objSearchFolder
Debug.Print objSearchFolder.Items.count
End If
If bFound = True Then Exit For
Next
If bFound = False Then Debug.Print " Not found in " & objStore
Next
End Sub
If you find an error that is unfixable/unexplainable, when testing/manipulating searchfolders, close Outlook and restart.

How to open Outlook messages stored in the file system from Excel?

I am trying to open msg (Outlook item) files saved in my desktop folder (C:\Desktop\Index) and search for attachments (single/zip file).
I am getting
'object doesn't support this property or method' error for:
Set openMsg = Application.CreateItemFromTemplate(FileItem.Path)
Option Explicit
Sub GetMSG()
*True includes sub folders
*False to check only listed folder
ListFilesInFolder "C:\Desktop\Index\", True
End Sub
Sub ListFilesInFolder(SourceFolderName As String, IncludeSubfolders As Boolean)
Dim FSO As Scripting.FileSystemObject
Dim SourceFolder As Scripting.Folder, SubFolder As Scripting.Folder
Dim FileItem As Scripting.File
Dim strFile, strFileType, strAttach As String
Dim openMsg As MailItem
Dim objAttachments As Outlook.Attachments
Dim i As Long
Dim lngCount As Long
Dim strFolderpath As String
'where to save attachments
strFolderpath = "C:\Desktop\Index\Attachments\"
Set FSO = New Scripting.FileSystemObject
Set SourceFolder = FSO.GetFolder(SourceFolderName)
For Each FileItem In SourceFolder.Files
strFile = FileItem.Name
' This code looks at the last 4 characters in a filename
' If we wanted more than .msg, we'd use Case Select statement
strFileType = LCase$(Right$(strFile, 4))
If strFileType = ".msg" Then
Debug.Print FileItem.Path
Set openMsg = Application.CreateItemFromTemplate(FileItem.Path)
openMsg.Display
'do whatever
Set objAttachments = openMsg.Attachments
lngCount = objAttachments.Count
If lngCount > 0 Then
For i = lngCount To 1 Step -1
' Get the file name.
strAttach = objAttachments.Item(i).Filename
' Combine with the path to the Temp folder.
strAttach = strFolderpath & strAttach
' Save the attachment as a file.
objAttachments.Item(i).SaveAsFile strAttach
Next i
End If
openMsg.Close olDiscard
Set objAttachments = Nothing
Set openMsg = Nothing
' end do whatever
End If
Next FileItem
If IncludeSubfolders Then
For Each SubFolder In SourceFolder.SubFolders
ListFilesInFolder SubFolder.Path, True
Next SubFolder
End If
Set FileItem = Nothing
Set SourceFolder = Nothing
Set FSO = Nothing
End Sub
Write this before the error:
Dim OutApp As Object
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItemFromTemplate(FileItem.Path)
When you are using Application, it refers to the Excel application and not to the Outlook application. And the Excel Application does not support CreateItemFromTemplate.
You can also use early binding:
Dim OutApp As New Outlook.Application
Set OutMail = OutApp.CreateItemFromTemplate(FileItem.Path)

Update current file

I'm creating code wherein Outlook will extract all emails to an existing Excel file.
The code works and extracts all emails from a selected folder. However, when I try to use the same code on a separate folder, let's say Sent Items, it doesn't extract the data and opens a Read only version of the Excel file.
I plan to leave Outlook and Excel Open.
How can I work with any Outlook folder and still update the Excel file?
Private Sub Application_NewMailv7()
Dim objNS As NameSpace
Dim objFolder As MAPIFolder
Dim currentExplorer As Explorer
Dim Selection As Selection
Dim obj As Object
Dim objOL As Outlook.Application
Dim objItems As Outlook.Items
Dim myItem As MailItem
Dim myXLApp As Excel.Application
Dim myXLWB As Excel.Workbook
Dim StrBody As String
Dim TotalRows As Long, i As Long
Set objOL = Outlook.Application
Set objFolder = objOL.ActiveExplorer.CurrentFolder
Set objItems = objFolder.Items
Set myXLApp = New Excel.Application
myXLApp.Visible = True
Set myXLWB = myXLApp.Workbooks.Open("C:\Users\username\Desktop\Folder Name\SR Historyv2.xlsx")
Set excWks = myXLWB.Worksheets("Sheet1")
TotalRows = Sheets(1).Range("A65536").End(xlUp).Row
i = TotalRows + 1
For Each obj In objItems
If obj.Class = olMail Then
'Add a row for each field in the message you want to export
excWks.Cells(i, 1) = Format(obj.ReceivedTime, "mm/dd/yyyy")
excWks.Cells(i, 2) = obj.SenderEmailAddress
excWks.Cells(i, 3) = obj.Subject
i = i + 1
'myXLWB.Save
End If
Next
Set obj = Nothing
Set objItems = Nothing
Set objFolder = Nothing
Set objOL = Nothing
End Sub
Try the following and if you would like to run Outlook Rule, let me know I will update the answer
Option Explicit
Sub Excel()
Dim xlApp As Object 'Excel App
Dim xlWB As Object 'WorkBook
Dim xlSheet As Object
Dim rngCount As Long
Dim xlStarted As Boolean
Dim xlPath As String
Dim olExplorer As Explorer
Dim olSelection As Selection
Dim olItem As Outlook.MailItem
Dim olMsg As Object
Dim xlColA, xlColB, xlColC, xlColD As String
'// Path of the Workbook - update only -> "\Folder Name\Folder Name\Book1.xlsx"
xlPath = Environ("USERPROFILE") & _
"\Documents\Temp\Book1.xlsx"
'// Set up Excel Application
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(xlPath)
Set xlSheet = xlWB.Sheets("Sheet1") ' or use (1) or (Sheet Name)
'// Record msg
On Error Resume Next
'// Find the next empty line of the worksheet
rngCount = xlSheet.Range("A" & xlSheet.Rows.Count).End(-4162).Row
'// Get the values from Outlook
Set olExplorer = Application.ActiveExplorer
'// Select Outlook msg
Set olSelection = olExplorer.Selection
For Each olMsg In olSelection
Set olItem = olMsg
'// Info to collect
xlColA = olItem.ReceivedTime
xlColB = olItem.SenderName
xlColC = olItem.SenderEmailAddress
xlColD = olItem.To
'// Write it to Excel sheet
xlSheet.Range("A" & rngCount) = xlColA
xlSheet.Range("B" & rngCount) = xlColB
xlSheet.Range("C" & rngCount) = xlColC
xlSheet.Range("D" & rngCount) = xlColD
'// Go to Next row
rngCount = rngCount + 1
Next
'// Save & Close Excel.Application
xlWB.Close 1
If xlStarted Then
xlApp.Quit
End If
'// Clean up
Set olItem = Nothing
Set olMsg = Nothing
Set olExplorer = Nothing
Set xlApp = Nothing
Set xlWB = Nothing
Set xlSheet = Nothing
End Sub
Do you close the SR Historyv2 workbook after you run the script or do you want to keep it open the entire time? If you keep it open and run the script again it will open the workbook a second time and that will be read only. For the second question i would suggest you look into the ItemAdd event in Outlook. This will only work if Outlook is open. https://msdn.microsoft.com/en-us/library/office/aa171270(v=office.11).aspx
I got this code working properly
Set myXLApp = GetObject(, "Excel.Application")
'specify the History File
With myXLApp
.Workbooks("SR Historyv2.xlsx").Activate
End With
It keeps the file to open and lets the other macro access it without being read-only.

Saving .XLSX Attachments from Outlook 2010 w/ VBA

We use Outlook 2010 and receive emails with Excel attachments. We manually save the attachment in a sub-folder that we create within a divisional folder on a network drive.
What I'm curious about is if it's possible to
Use code to check incoming emails to see if they have an attachment,
Then check the attachment to see if it's an .XLSX,
If so, open the attachment, check the value of a particular cell,
then store the account name and account number as a string and a variable
then use those to create the sub-folders in the appropriate Windows directory.
** I forgot to post what I had done so far. I believe Brett answered my ??, but maybe someone else would be able to use snippets of it.
Private Sub cmdConnectToOutlook_Click()
Dim appOutlook As Outlook.Application
Dim ns As Outlook.Namespace
Dim inbox As Outlook.MAPIFolder
Dim item As Object
Dim atmt As Outlook.Attachment
Dim filename As String
Dim i As Integer
Set appOutlook = GetObject(, "Outlook.Application")
Set ns = appOutlook.GetNamespace("MAPI")
Set inbox = ns.GetDefaultFolder(olFolderInbox)
i = 0
If inbox.Items.Count = 0 Then
MsgBox "There are no messages in the Inbox.", vbInformation, _
"Nothing Found"
Exit Sub
End If
For Each item In inbox.Items
For Each atmt In item.Attachments
If Right(atmt.filename, 4) = "xlsx" Then
filename = "\\temp\" & atmt.filename
atmt.SaveAsFile filename
i = i + 1
End If
Next atmt
Next item
MsgBox "Attachments have been saved.", vbInformation, "Finished"
Set atmt = Nothing
Set item = Nothing
Set ns = Nothing
End Sub
Having said it is lengthy here is one way to do it. My code from VBA Code to save an attachment (excel file) from an Outlook email that was inside another email as an attachment may also be of interest
You will need to update your file path, and the cell range from the file that you are opening
In my testing I sent a message to myself with a pdf file and an excel workbook with "bob" in the A1 in the first sheet
The code below found the excel file, saved it, opened it, create a directory c:\temp\bob then killed the saved file
Private Sub Application_NewMailEx _
(ByVal EntryIDCollection As String)
'Uses the new mail techniquer from http://www.outlookcode.com/article.aspx?id=62
Dim arr() As String
Dim lngCnt As Long
Dim olAtt As Attachment
Dim strFolder As String
Dim strFileName As String
Dim strNewFolder
Dim olns As Outlook.NameSpace
Dim olItem As MailItem
Dim objExcel As Object
Dim objWB As Object
'Open Excel in the background
Set objExcel = CreateObject("excel.application")
'Set working folder
strFolder = "c:\temp"
On Error Resume Next
Set olns = Application.Session
arr = Split(EntryIDCollection, ",")
On Error GoTo 0
For lngCnt = 0 To UBound(arr)
Set olItem = olns.GetItemFromID(arr(lngCnt))
'Check new item is a mail message
If olItem.Class = olMail Then
'Force code to count attachments
DoEvents
For Each olAtt In olItem.Attachments
'Check attachments have at least 5 characters before matching a ".xlsx" string
If Len(olAtt.FileName) >= 5 Then
If Right$(olAtt.FileName, 5) = ".xlsx" Then
strFileName = strFolder & "\" & olAtt.FileName
'Save xl attachemnt to working folder
olAtt.SaveAsFile strFileName
On Error Resume Next
'Open excel workbook and make a sub directory in the working folder with the value from A1 of the first sheet
Set objWB = objExcel.Workbooks.Open(strFileName)
MkDir strFolder & "\" & objWB.sheets(1).Range("A1")
'Close the xl file
objWB.Close False
'Delete the saved attachment
Kill strFileName
On Error Goto 0
End If
End If
Next
End If
Next
'tidy up
Set olns = Nothing
Set olItem = Nothing
objExcel.Quit
Set objExcel = Nothing
End Sub

Resources