Exporting new email to file - vba

There are a few sources from which we receive specific emails. The easiest way to categorize them is by mail title or even source email address.
We are trying to automatically save all incoming emails to file, whether it's a TXT or PDF so we can pull up a back up file when there is a problem with the network, email or whatever else is malfunctioning.
I tried to create a macro from a few similar topics;
Private Sub Application_Startup()
Dim olNs As Outlook.NameSpace
Dim Inbox As Outlook.MAPIFolder
Set olNs = Application.GetNamespace("MAPI")
Set Inbox = olNs.GetDefaultFolder(olFolderInbox)
Set Items = Inbox.Items
End Sub
Private Sub Items_ItemAdd(ByVal Item As Object)
If TypeOf Item Is Outlook.MailItem Then
SaveMailAsFile Item ' call sub
End If
End Sub
Public Sub SaveMailAsFile(ByVal Item As Object)
Dim olNs As Outlook.NameSpace
Dim Inbox As Outlook.MAPIFolder
Dim SubFolder As Outlook.MAPIFolder
Dim Items As Outlook.Items
Dim ItemSubject As String
Dim NewName As String
Dim RevdDate As Date
Dim Path As String
Dim Ext As String
Dim i As Long
Set olNs = Application.GetNamespace("MAPI")
Set Inbox = olNs.GetDefaultFolder(olFolderInbox)
Set Items = Inbox.Items.Restrict("[Subject] = 'VVAnalyze Results'")
Path = Environ("USERPROFILE") & "\Desktop\Backup Reports\"
ItemSubject = Item.Subject
RevdDate = Item.ReceivedTime
Ext = "txt"
For i = Items.Count To 1 Step -1
Set Item = Items.Item(i)
DoEvents
If Item.Class = olMail Then
Debug.Print Item.Subject ' Immediate Window
Set SubFolder = Inbox.Folders("Temp") ' <--- Update Fldr Name
ItemSubject = Format(RevdDate, "YYYYMMDD-HHNNSS") _
& " - " & _
Item.Subject & Ext
ItemSubject = FileNameUnique(Path, ItemSubject, Ext)
Item.SaveAs Path & ItemSubject, olTXT
Item.Move SubFolder
End If
Next
Set olNs = Nothing
Set Inbox = Nothing
Set SubFolder = Nothing
Set Items = Nothing
End Sub
'// Check if the file exists
Private Function FileExists(FullName As String) As Boolean
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists(FullName) Then
FileExists = True
Else
FileExists = False
End If
Exit Function
End Function
'// If the same file name exist then add (1)
Private Function FileNameUnique(Path As String, _
FileName As String, _
Ext As String) As String
Dim lngF As Long
Dim lngName As Long
lngF = 1
lngName = Len(FileName) - (Len(Ext) + 1)
FileName = Left(FileName, lngName)
Do While FileExists(Path & FileName & Chr(46) & Ext) = True
FileName = Left(FileName, lngName) & " (" & lngF & ")"
lngF = lngF + 1
Loop
FileNameUnique = FileName & Chr(46) & Ext
Exit Function
End Function
While I understand that Outlook cache is available even off line some are insisting to have back up files on a physical hard drive.
I know I could manually select those files and create a copy by drag&drop but that is insufficient.
I am aware of
https://www.techhit.com/messagesave/screenshots.html. It would be difficult to have this idea accepted because GDPR blah blah blah.

You could use this code, paste it in the ThisOutlookSession module.
To test this code sample without restarting Outlook, click in the Application_Startup procedure then click Run.
Option Explicit
Private WithEvents Items As Outlook.Items
Private Sub Application_Startup()
Dim Ns As Outlook.NameSpace
Set Ns = Application.GetNamespace("MAPI")
Set Items = Ns.GetDefaultFolder(olFolderInbox).Items
End Sub
Private Sub Items_ItemAdd(ByVal Item As Object)
If TypeOf Item Is Outlook.MailItem Then
Dim sPath As String
Dim dtDate As Date
Dim sName As String
Dim enviro As String
enviro = CStr(Environ("USERPROFILE"))
sName = Item.Subject
ReplaceCharsForFileName sName, "_"
dtDate = Item.ReceivedTime
sName = Format(dtDate, "yyyymmdd", vbUseSystemDayOfWeek, _
vbUseSystem) & Format(dtDate, "-hhnnss", _
vbUseSystemDayOfWeek, vbUseSystem) & "-" & sName & ".msg"
' use My Documents for older Windows.
sPath = enviro & "\Documents\"
Debug.Print sPath & sName
Item.SaveAs sPath & sName, olMSG
End If
End Sub
Private Sub ReplaceCharsForFileName(sName As String, _
sChr As String _
)
sName = Replace(sName, "/", sChr)
sName = Replace(sName, "\", sChr)
sName = Replace(sName, ":", sChr)
sName = Replace(sName, "?", sChr)
sName = Replace(sName, Chr(34), sChr)
sName = Replace(sName, "<", sChr)
sName = Replace(sName, ">", sChr)
sName = Replace(sName, "|", sChr)
End Sub
For more information, please refer to this link:
Save all incoming messages to the hard drive
Save outlook mail automatically to a specified folder

Related

Outlook Button in Ribbon for saving mail (incoming and outgoing) to nominated destination in new folder

I want to create a button in Outlook that saves an incoming mail in a folder named:
"yyyymmdd - {sender's initials} - {email subject}".
Similarly, I need a button for outgoing mail that needs to be saved in a folder named:
"yyyymmdd - {email subject}".
Since I work in a variety of directories, a user input will be required to specify the project number where the relevant mail needs to go, ie:
C:\Users\User.Name{project_name_input}.
I tried some VBA scripts, but I am not good at it. I haven't gotten close to a solution.
I have managed to solve this by using some script found at the link below and some modifications to make it work the way I wanted on my machine:
https://www.slipstick.com/developer/code-samples/save-selected-message-file/
The script:
Option Explicit
Function BrowseForFolder(Optional OpenAt As Variant) As Variant
Dim ShellApp As Object
Set ShellApp = CreateObject("Shell.Application"). _
BrowseForFolder(0, "Please choose a folder", 0, OpenAt)
On Error Resume Next
BrowseForFolder = ShellApp.self.Path
On Error GoTo 0
Set ShellApp = Nothing
Select Case Mid(BrowseForFolder, 2, 1)
Case Is = ":"
If Left(BrowseForFolder, 1) = ":" Then GoTo Invalid
Case Is = "\"
If Not Left(BrowseForFolder, 1) = "\" Then GoTo Invalid
Case Else
GoTo Invalid
End Select
Exit Function
Invalid:
BrowseForFolder = False
End Function
Public Sub SaveMessageAsMsg()
Dim oMail As Outlook.MailItem
Dim objItem As Object
Dim sPath As String
Dim dtDate As Date
Dim sName As String
Dim enviro As String
Dim mSender As String
Dim sendName As String
Dim sendSurname As String
Dim strFolderpath As String
Dim fName As String
Dim objAttachments As Outlook.Attachments
Dim i As Long
Dim lngCount As Long
Dim objOL As Outlook.Application
Dim StrFile As String
enviro = CStr(Environ("USERPROFILE"))
strFolderpath = BrowseForFolder(enviro)
For Each objItem In ActiveExplorer.Selection
If objItem.MessageClass = "IPM.Note" Then
Set oMail = objItem
sName = oMail.Subject
sName = Replace(sName, "FW: ", "")
sName = Replace(sName, "RE: ", "")
ReplaceCharsForFileName sName, "-"
mSender = oMail.Sender
sendName = Split(mSender)(0)
sendName = Left(sendName, 1)
sendSurname = Split(mSender)(1)
sendSurname = Left(sendSurname, 1)
dtDate = oMail.ReceivedTime
fName = Format(dtDate, "yyyymmdd", vbUseSystemDayOfWeek, _
vbUseSystem) & " - " & sendName & sendSurname & " - " & sName
sName = Format(dtDate, "yyyymmdd", vbUseSystemDayOfWeek, _
vbUseSystem) & " - " & sName & ".msg"
CreateIncomeFolder strFolderpath, fName
sPath = strFolderpath & fName & "\"
Debug.Print sPath & sName
oMail.SaveAs sPath & sName, olMSG
End If
Next
Set objOL = Outlook.Application
Set objItem = objOL.ActiveExplorer.Selection.Item(1)
Set objAttachments = objItem.Attachments
lngCount = objAttachments.Count
If lngCount > 0 Then
For i = lngCount To 1 Step -1
If objAttachments.Item(i).Size > 10000 Then
StrFile = objAttachments.Item(i).FileName
Debug.Print StrFile
StrFile = sPath & StrFile
objAttachments.Item(i).SaveAsFile StrFile
End If
Next i
End If
End Sub
Public Sub SaveOutogingMessageAsMsg()
Dim oMail As Outlook.MailItem
Dim objItem As Object
Dim sPath As String
Dim dtDate As Date
Dim sName As String
Dim enviro As String
Dim mSender As String
Dim strFolderpath As String
Dim fName As String
enviro = CStr(Environ("USERPROFILE"))
strFolderpath = BrowseForFolder(enviro)
For Each objItem In ActiveExplorer.Selection
If objItem.MessageClass = "IPM.Note" Then
Set oMail = objItem
sName = oMail.Subject
sName = Replace(sName, "FW: ", "")
sName = Replace(sName, "RE: ", "")
ReplaceCharsForFileName sName, "-"
mSender = oMail.Sender
sName = Replace(sName, "FW- ", "")
sName = Replace(sName, "RE- ", "")
dtDate = oMail.ReceivedTime
fName = Format(dtDate, "yyyymmdd", vbUseSystemDayOfWeek, _
vbUseSystem) & " - " & sName
sName = Format(dtDate, "yyyymmdd", vbUseSystemDayOfWeek, _
vbUseSystem) & " - " & sName & ".msg"
CreateFolder strFolderpath, fName
sPath = strFolderpath & fName & "\"
Debug.Print sPath & sName
oMail.SaveAs sPath & sName, olMSG
End If
Next
End Sub
Private Sub ReplaceCharsForFileName(sName As String, _
sChr As String _
)
sName = Replace(sName, "'", sChr)
sName = Replace(sName, "*", sChr)
sName = Replace(sName, "/", sChr)
sName = Replace(sName, "\", sChr)
sName = Replace(sName, ":", sChr)
sName = Replace(sName, "?", sChr)
sName = Replace(sName, Chr(34), sChr)
sName = Replace(sName, "<", sChr)
sName = Replace(sName, ">", sChr)
sName = Replace(sName, "|", sChr)
End Sub
Sub CreateFolder(strFolderpath As String, fName As String)
On Error GoTo eh
MkDir strFolderpath & fName
Exit Sub
eh:
MsgBox "Message has already been saved", vbOKOnly
End Sub
Sub CreateIncomeFolder(strFolderpath As String, fName As String)
On Error GoTo eh
MkDir strFolderpath & fName
Exit Sub
eh:
MsgBox "Message has already been saved", vbOKOnly
End Sub

save email from outlook to local drive using vba

i am trying to save a selected mail from outlook to a folder dynamically created with mail's subject name. The code ran successfully for one mail. if i select different mail and try to run the macro it is showing path not found error. My code is below:
Public Sub OpslaanMails()
Dim OlApp As Outlook.Application
Set OlApp = New Outlook.Application
Set OlApp = CreateObject("Outlook.Application")
Dim fName, sName As String
Dim oMail As Outlook.MailItem
fName = "F:\Test\inwards\"
Set oMail = OlApp.ActiveExplorer.Selection.Item(1)
sName = oMail.Subject
makeSelectionDir (sName)
sPath = fName & "\" & sName & "\"
oMail.SaveAs sPath & sName & ".msg", olMsg
For Each oAttach In oMail.Attachments
oAttach.SaveAsFile sPath & oAttach.FileName
Set oAttach = Nothing
Next
End Sub
Sub makeSelectionDir(sName As String)
Dim fName, sPath As String
fName = "F:\Test\inwards\"
sPath = fName & sName
With CreateObject("Scripting.FileSystemObject")
If Not .FolderExists(sName) Then .CreateFolder sPath 'error is in this line
End With
End Sub
Make sure sName does not contain any characters illegal in a file name, such as ":".
I used your idea and changed two or three things to make it more robust.
Put this in a module in Outlook VBA Editor and run, having selected an email.
I also added the time and date at the beginning of the folder and email file names.
I left the part about saving file attachements but know that they are already embedded in the .msg file.
Const ILLEGAL_CHARACTERS = Array("*", "/", "\", "?", """", "<", ">", ":", "|")
Sub SaveEmailToFile()
Dim oMail As MailItem
Dim sPath As String
Dim sObj As String
Dim oAttach As Attachment
'Select email and process subject
If ActiveExplorer.Selection.Count = 0 Then
MsgBox "No emails are selected."
Exit Sub
End If
Set oMail = ActiveExplorer.Selection.Item(1)
With oMail
sObj = oMail.Subject
'Remove illegal characters from email subject
If sObj = "" Then
sObj = "No Object"
Else
For Each s In ILLEGAL_CHARACTERS
sObj = Replace(sObj, s, "")
Next s
End If
'Get date and time string from email received timestamp
dateStr = Year(.ReceivedTime) & "_" & _
Month(.ReceivedTime) & "_" & _
Day(.ReceivedTime) & " " & _
Hour(.ReceivedTime) & " " & _
Minute(.ReceivedTime) & " " & _
Second(.ReceivedTime) & " "
End With
sPath = "C:\Someplace\" & dateStr & sObj & "\"
'Create folder
With CreateObject("Scripting.FileSystemObject")
If Not .FolderExists(sPath) Then .CreateFolder sPath
End With
'Save email and attachements
oMail.SaveAs sPath & oMail.Subject & ".msg", olMSG
For Each oAttach In oMail.Attachments
oAttach.SaveAsFile sPath & oAttach.FileName
Next oAttach
End Sub
I could only recreate the error
path not found
if fName was not valid.
Option Explicit ' Consider this mandatory
' Tools | Options | Editor tab
' Require Variable Declaration
' If desperate declare as Variant
Public Sub OpslaanMails()
Dim fName As String
Dim sName As String
Dim sPath As String
Dim oMail As MailItem
Dim oAttach As Attachment
fName = "F:\Test\inwards\"
Debug.Print "fName: " & fName
Set oMail = ActiveExplorer.Selection.Item(1)
sName = oMail.subject
Debug.Print "sName: " & sName
' Double slash accepted by Windows but not by some programmers
'If Right(fName, 1) = "\" Then
' fName = Left(fName, Len(fName) - 1)
' Debug.Print
' Debug.Print "fName: " & fName
'End If
' Double slash after fName preferable to no slash
sPath = fName & "\" & sName & "\"
Debug.Print "sPath: " & sPath
makeSelectionDir fName, sPath
' Possible illegal characters in sName not addressed.
' Do not test with replies nor forwards,
' the : in the subject is not a legal character.
oMail.SaveAs sPath & sName & ".msg", olMsg
For Each oAttach In oMail.Attachments
oAttach.SaveAsFile sPath & oAttach.FileName
Set oAttach = Nothing
Next
End Sub
Sub makeSelectionDir(fName As String, sPath As String)
With CreateObject("Scripting.FileSystemObject")
' Test for fName
' Otherwise there is file not found error in the create
If .FolderExists(fName) Then
' if subfolder does not exist create it
If Not .FolderExists(sPath) Then
.createFolder sPath
End If
Else
Debug.Print
Debug.Print "Folder " & fName & " does not exist."
'MsgBox "Folder " & fName & " does not exist."
End
End If
End With
End Sub
Inconsistency of sName vs sPath has been addressed in
If Not .FolderExists(sName) Then .CreateFolder sPath

Loop to set up watches on a selection of Outlook folders

I'm doing the following in VBA in Outlook. Upon dragging an Outlook item to a specified folder, I save this Outlook item to my computer (i.e. a filing system).
Private WithEvents Items As Outlook.Items
Private WithEvents Items2 As Outlook.Items
Private Sub Application_Startup()
Dim Ns As Outlook.NameSpace
Set Ns = Application.GetNamespace("MAPI")
Set Items = Ns.GetDefaultFolder(olFolderInbox).Parent.Folders("Hello").Items
Set Items2 = Ns.GetDefaultFolder(olFolderInbox).Parent.Folders("Bye").Items
End Sub
Private Sub Items_ItemAdd(ByVal Item As Object)
If TypeOf Item Is Outlook.MailItem Then
Dim sPath As String
Dim dtDate As Date
Dim sName As String
Dim enviro As String
enviro = CStr(Environ("USERPROFILE"))
sName = Item.Subject
ReplaceCharsForFileName sName, "_"
dtDate = Item.ReceivedTime
sName = Format(dtDate, "yyyymmdd", vbUseSystemDayOfWeek, _
vbUseSystem) & Format(dtDate, " - hhnn ", _
vbUseSystemDayOfWeek, vbUseSystem) & "- " & sName & ".msg"
sPath = "Y:\BM_Clientenmap\D\Hello\emails\"
Debug.Print sPath & sName
Item.SaveAs sPath & sName, olMSG
End If
End Sub
Private Sub Items2_ItemAdd(ByVal Item As Object)
If TypeOf Item Is Outlook.MailItem Then
Dim sPath As String
Dim dtDate As Date
Dim sName As String
Dim enviro As String
enviro = CStr(Environ("USERPROFILE"))
sName = Item.Subject
ReplaceCharsForFileName sName, "_"
dtDate = Item.ReceivedTime
sName = Format(dtDate, "yyyymmdd", vbUseSystemDayOfWeek, _
vbUseSystem) & Format(dtDate, " - hhnn ", _
vbUseSystemDayOfWeek, vbUseSystem) & "- " & sName & ".msg"
sPath = "Y:\BM_Clientenmap\D\Bye\emails\"
Debug.Print sPath & sName
Item.SaveAs sPath & sName, olMSG
End If
End Sub
Private Sub ReplaceCharsForFileName(sName As String, _
sChr As String)
sName = Replace(sName, "/", sChr)
sName = Replace(sName, "\", sChr)
sName = Replace(sName, ":", sChr)
sName = Replace(sName, "?", sChr)
sName = Replace(sName, Chr(34), sChr)
sName = Replace(sName, "<", sChr)
sName = Replace(sName, ">", sChr)
sName = Replace(sName, "|", sChr)
End Sub
This code saves an Outlook item to the computer in directory sPath (Sub Items/Items2_AddItem), if the user adds a file to the directory specified in the variable Items/Items2 declared at the top.
The problem is it requires me to manually add in VBA which folders VBA should "watch" when an item is added, and where to save these files. As a result, it requires me to write a new Items variable and new Items_ItemAdd sub for every folder I have.
I want to do the following:
Select the folder that should be "watched" for an item added, and the folder to which it should be saved, through user interface in Outlook instead of VBA. Users should select multiple folders (I don't care if they have to select them one at a time), with multiple save folders on the computer.
I want Outlook to remember the choices that the user made upon closing Outlook.
To make it more user friendly, I thought about the following.
User selects folder in Outlook. Code that I found that does this:
Set FSO = CreateObject("Scripting.FileSystemObject")
Set myOlApp = Outlook.Application
Set iNameSpace = myOlApp.GetNamespace("MAPI")
Set ChosenFolder = iNameSpace.PickFolder
If ChosenFolder Is Nothing Then
GoTo ExitSub:
End If
User then selects the folder the item should be saved to on computer. Code that I found that allows you to set a variable to an input filepath:
Function BrowseForFolder(StrSavePath As String, Optional OpenAt As String) As String
Dim objShell As Object
Dim objFolder ' As Folder
Dim enviro
enviro = CStr(Environ("USERPROFILE"))
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.BrowseForFolder(0, "Please choose a folder", 0,
enviro & "\Computer\")
StrSavePath = objFolder.self.Path
On Error Resume Next
On Error GoTo 0
ExitFunction:
Set objShell = Nothing
End Sub
I want the above code to run when the user presses a button in the ribbon to which my macro would be set.
I want Outlook to watch these folders that the user has selected (i.e. what Sub Items_ItemAdd does). This is where I get stuck. I want the choices of the user to be remembered (i.e. so the user doesn't have to select his folders every time he opens Outlook) after Outlook is closed.
Now my questions are as follows:
I imagined one way to make this work is to create a new variable Items(i) and a new Sub Items(i)_ItemAdd directly in the VBA code every time the user selects the folder and save folder. However, I read this is impossible to do in Outlook, unlike in Excel. Is this true? If not: how to create VBA code using VBA in Outlook?
Another way I can imagine is the following. I save the input that the user made to a text file, and I read from the text file and save that to an array. However, I do not know how to use the array in the rest of my code. I do not think it's possible to create a Sub with a variable name, or run a sub with "ItemAdd" 'watcher' included in a for-loop that runs through the array and creates Sub functions based on the index in the Array or something like that.
Hope anyone can help me. Or knows any other ideas on how to make my idea work.
This doesn't address how you collect or store the various folders, but shows how to manage a collection of "watched" folders with separate "save to" paths.
First, create a class to manage each folder:
Option Explicit
Private OlFldr As Folder
Private SavePath As String
Public WithEvents Items As Outlook.Items
'called to set up the object
Public Sub Init(f As Folder, sPath As String)
Set OlFldr = f
Set Items = f.Items
SavePath = sPath
End Sub
Private Sub Items_ItemAdd(ByVal Item As Object)
If TypeOf Item Is Outlook.MailItem Then
'Just a simple message to show what's going on.
'You can add code here to save the item, or you can pass
' arguments to a common sub defined in a regular module
MsgBox "Mail '" & Item.Subject & "' was added to Folder '" & OlFldr.Name & _
"' and will be saved to '" & SavePath & "'"
End If
End Sub
Here's how you'd use that class to set up your watched folders:
Option Explicit
Dim colFolders As Collection '<< holds the clsFolder objects
Private Sub SetupFolderWatches()
'This could be called on application startup, or from the code which collects
' user selections for folders/paths
Dim Ns As Outlook.NameSpace, inboxParent, arrFolders, f, arr
Set Ns = Application.GetNamespace("MAPI")
Set colFolders = New Collection
Set inboxParent = Ns.GetDefaultFolder(olFolderInbox).Parent
'you'd be reading this info from a file or some other storage...
arrFolders = Array("Test1|C:\Test1_Files\", "Test2|C:\Test2_Files\")
For Each f In arrFolders
arr = Split(f, "|")
colFolders.Add GetFolderObject(inboxParent.Folders(arr(0)), CStr(arr(1)))
Next f
End Sub
'"factory" function to create folder objects
Function GetFolderObject(foldr As Folder, sPath As String)
Dim rv As New clsFolder
rv.Init foldr, sPath
Set GetFolderObject = rv
End Function

Automatically export specific emails to text file from Outlook

I am trying to use a VBA script to automatically export all incoming emails with a specific subject to text files that I will then parse with a Python script. The code below works for the most part, but it will randomly skip some of the emails come in.
I haven't found any reason as to why this is, and it doesn't skip emails from the same sender each day, it varies.
We have about 20-30 emails coming in during a 30 minute period or so if that matters. I'd love some help with this.
Private Sub Items_ItemAdd(ByVal Item As Object)
Dim strSubject As String
strSubject = Item.Subject
If TypeOf Item Is Outlook.MailItem And strSubject Like "VVAnalyze Results" Then
SaveMailAsFile Item
End If
End Sub
Private Sub SaveMailAsFile(oMail As Outlook.MailItem)
Dim dtDate As Date
Dim sName As String
Dim sFile As String
Dim sExt As String
sPath = "C:\Users\ltvstatus\Desktop\Backup Reports\"
sExt = ".txt"
sName = oMail.Subject
ReplaceCharsForFileName sName, "_"
dtDate = oMail.ReceivedTime
sName = Format(dtDate, "yyyymmdd", vbUseSystemDayOfWeek, _
vbUseSystem) & Format(dtDate, "-hhnnss", _
vbUseSystemDayOfWeek, vbUseSystem) & "-" & sName & sExt
oMail.SaveAs sPath & sName, olSaveAsTxt
End Sub
Your code looks okay to me so I am not sure if your overwriting your saved emails with new one or your getting to many emails at once while the code is processing one and skipping the other...
I have modified your code to loop in your Inbox and added Function to create new file name if the file already exist...
if you receive 10 email in 1 second, the function will create FileName(1).txt, FileName(2).txt and so on...
I will also advise you to move the emails to subfolder as you SaveAs txt...
Item.Move Subfolder
CODE UPDATED
Option Explicit
Private WithEvents Items As Outlook.Items
Private Sub Application_Startup()
Dim olNs As Outlook.NameSpace
Dim Inbox As Outlook.MAPIFolder
Set olNs = Application.GetNamespace("MAPI")
Set Inbox = olNs.GetDefaultFolder(olFolderInbox)
Set Items = Inbox.Items
End Sub
Private Sub Items_ItemAdd(ByVal Item As Object)
If TypeOf Item Is Outlook.MailItem Then
SaveMailAsFile Item ' call sub
End If
End Sub
Public Sub SaveMailAsFile(ByVal Item As Object)
Dim olNs As Outlook.NameSpace
Dim Inbox As Outlook.MAPIFolder
Dim SubFolder As Outlook.MAPIFolder
Dim Items As Outlook.Items
Dim ItemSubject As String
Dim NewName As String
Dim RevdDate As Date
Dim Path As String
Dim Ext As String
Dim i As Long
Set olNs = Application.GetNamespace("MAPI")
Set Inbox = olNs.GetDefaultFolder(olFolderInbox)
Set Items = Inbox.Items.Restrict("[Subject] = 'VVAnalyze Results'")
Path = Environ("USERPROFILE") & "\Desktop\Backup Reports\"
ItemSubject = Item.Subject
RevdDate = Item.ReceivedTime
Ext = "txt"
For i = Items.Count To 1 Step -1
Set Item = Items.Item(i)
DoEvents
If Item.Class = olMail Then
Debug.Print Item.Subject ' Immediate Window
Set SubFolder = Inbox.Folders("Temp") ' <--- Update Fldr Name
ItemSubject = Format(RevdDate, "YYYYMMDD-HHNNSS") _
& " - " & _
Item.Subject & Ext
ItemSubject = FileNameUnique(Path, ItemSubject, Ext)
Item.SaveAs Path & ItemSubject, olTXT
Item.Move SubFolder
End If
Next
Set olNs = Nothing
Set Inbox = Nothing
Set SubFolder = Nothing
Set Items = Nothing
End Sub
'// Check if the file exists
Private Function FileExists(FullName As String) As Boolean
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists(FullName) Then
FileExists = True
Else
FileExists = False
End If
Exit Function
End Function
'// If the same file name exist then add (1)
Private Function FileNameUnique(Path As String, _
FileName As String, _
Ext As String) As String
Dim lngF As Long
Dim lngName As Long
lngF = 1
lngName = Len(FileName) - (Len(Ext) + 1)
FileName = Left(FileName, lngName)
Do While FileExists(Path & FileName & Chr(46) & Ext) = True
FileName = Left(FileName, lngName) & " (" & lngF & ")"
lngF = lngF + 1
Loop
FileNameUnique = FileName & Chr(46) & Ext
Exit Function
End Function

Using Outlook VBA to save selected email(s) as a text file

I am trying to save selected emails in Outlook as Text files.
I would like it to work like this:
Saves one email at a time but saves all selected emails instead of just a single email.
They need to each be saved as a new file. I know that the export feature saves them all as one large text file, but need them to each have their own.
Here's what I have so far:
Sub SaveEmail()
Dim Msg As Outlook.MailItem
' assume an email is selected
Set Msg = ActiveExplorer.Selection.item(2)
' save as text
Msg.SaveAs "C:\My Location", OLTXT
End Sub
It looks like you need to iterate over all selected items in the explorer window and save each one using the txt file format. Be aware, the Selection object may contain various Outlook item types. The following code showshow to iterate over all items selected and detect what item is:
Private Sub GetSelectedItem_Click()
' This uses an existing instance if available (default Outlook behavior).
' Dim oApp As New Outlook.Application - for running in external applications
Dim oExp As Outlook.Explorer
Dim oSel As Outlook.Selection ' You need a selection object for getting the selection.
Dim oItem As Object ' You don't know the type yet.
Set oExp = Application.ActiveExplorer ' Get the ActiveExplorer.
Set oSel = oExp.Selection ' Get the selection.
For i = 1 To oSel.Count ' Loop through all the currently .selected items
Set oItem = oSel.Item(i) ' Get a selected item.
DisplayInfo oItem ' Display information about it.
Next i
End Sub
Sub DisplayInfo(oItem As Object)
Dim strMessageClass As String
Dim oAppointItem As Outlook.AppointmentItem
Dim oContactItem As Outlook.ContactItem
Dim oMailItem As Outlook.MailItem
Dim oJournalItem As Outlook.JournalItem
Dim oNoteItem As Outlook.NoteItem
Dim oTaskItem As Outlook.TaskItem
' You need the message class to determine the type.
strMessageClass = oItem.MessageClass
If (strMessageClass = "IPM.Appointment") Then ' Calendar Entry.
Set oAppointItem = oItem
MsgBox oAppointItem.Subject
MsgBox oAppointItem.Start
ElseIf (strMessageClass = "IPM.Contact") Then ' Contact Entry.
Set oContactItem = oItem
MsgBox oContactItem.FullName
MsgBox oContactItem.Email1Address
ElseIf (strMessageClass = "IPM.Note") Then ' Mail Entry.
Set oMailItem = oItem
MsgBox oMailItem.Subject
MsgBox oMailItem.Body
ElseIf (strMessageClass = "IPM.Activity") Then ' Journal Entry.
Set oJournalItem = oItem
MsgBox oJournalItem.Subject
MsgBox oJournalItem.Actions
ElseIf (strMessageClass = "IPM.StickyNote") Then ' Notes Entry.
Set oNoteItem = oItem
MsgBox oNoteItem.Subject
MsgBox oNoteItem.Body
ElseIf (strMessageClass = "IPM.Task") Then ' Tasks Entry.
Set oTaskItem = oItem
MsgBox oTaskItem.DueDate
MsgBox oTaskItem.PercentComplete
End If
End Sub
You can add the SaveAs statement shown in your code where required.
Thank you everybody for your help. I was able to find the answer. Below is what worked for me.
Sub SaveSelectedMailAsTxtFile()
Const OLTXT = 0
Dim currentExplorer As Explorer
Dim Selection As Selection
Dim oMail As Outlook.MailItem
Dim obj As Object
Dim sPath As String
Dim dtDate As Date
Dim sName As String
Set currentExplorer = Application.ActiveExplorer
Set Selection = currentExplorer.Selection
For Each obj In Selection
Set oMail = obj
sName = oMail.Subject
ReplaceCharsForFileName sName, "_"
dtDate = oMail.ReceivedTime
sName = Format(dtDate, "yyyymmdd", vbUseSystemDayOfWeek, _
vbUseSystem) & Format(dtDate, "-hhnnss", _
vbUseSystemDayOfWeek, vbUseSystem) & "-" & sName & ".txt"
oMail.SaveAs "C:\my\path\" & sName, OLTXT
Next
End Sub
Private Sub ReplaceCharsForFileName(sName As String, _
sChr As String _
)
sName = Replace(sName, "/", sChr)
sName = Replace(sName, "\", sChr)
sName = Replace(sName, ":", sChr)
sName = Replace(sName, "?", sChr)
sName = Replace(sName, Chr(34), sChr)
sName = Replace(sName, "<", sChr)
sName = Replace(sName, ">", sChr)
sName = Replace(sName, "|", sChr)
End Sub
To save a single selected mail to a text file:
Selected email will be saved to a text file in the path specified in the code
Sub SaveMailAsFile()
Const OLTXT = 0
Dim oMail As Outlook.mailItem
Dim sPath As String
Dim dtDate As Date
Dim sName As String
Set oMail = Application.ActiveExplorer.Selection.Item(1)
sName = oMail.Subject
ReplaceCharsForFileName sName, "_"
dtDate = oMail.ReceivedTime
sName = Format(dtDate, "yyyymmdd", vbUseSystemDayOfWeek, _
vbUseSystem) & Format(dtDate, "-hhnnss", _
vbUseSystemDayOfWeek, vbUseSystem) & "-" & sName & ".txt"
oMail.SaveAs "C:\path\to\save\" & sName, OLTXT
End Sub
Private Sub ReplaceCharsForFileName(sName As String, _
sChr As String _
)
sName = Replace(sName, "/", sChr)
sName = Replace(sName, "\", sChr)
sName = Replace(sName, ":", sChr)
sName = Replace(sName, "?", sChr)
sName = Replace(sName, Chr(34), sChr)
sName = Replace(sName, "<", sChr)
sName = Replace(sName, ">", sChr)
sName = Replace(sName, "|", sChr)
End Sub
To save all selected mails to a text file:
NOTE: Click on Tools -> References -> Check the box for Microsoft Scripting Runtime before using this code.
Selected email(s) will be save to the user's standard Documents folder with the date and time stamp
Sub MergeSelectedEmailsIntoTextFile()
Dim objFS As New Scripting.FileSystemObject, objFile As Scripting.TextStream
Dim objItem As Object, strFile As String
Dim Folder As Folder
Dim sName As String
' Use your User folder as the initial path
Dim enviro As String
enviro = CStr(Environ("USERPROFILE"))
If ActiveExplorer.Selection.Count = 0 Then Exit Sub
' use the folder name in the filename
Set Folder = Application.ActiveExplorer.CurrentFolder
' add the current date to the filename
sName = Format(Now(), "yyyy-mm-dd-hh-MM-ss")
' The folder pathyou use needs to exist
strFile = enviro & "\Documents\" & sName & "-" & Folder & ".txt"
Set objFile = objFS.CreateTextFile(strFile, False)
If objFile Is Nothing Then
MsgBox "Error creating file '" & strFile & "'.", vbOKOnly + vbExclamation _
, "Invalid File"
Exit Sub
End If
For Each objItem In ActiveExplorer.Selection
With objFile
.Write vbCrLf & "--Start--" & vbCrLf
.Write "Sender: " & objItem.Sender & " <" & objItem.SenderEmailAddress & ">" & vbCrLf
.Write "Recipients : " & objItem.To & vbCrLf
.Write "Received: " & objItem.ReceivedTime & vbCrLf
.Write "Subject: " & objItem.Subject & vbCrLf & vbCrLf
.Write objItem.Body
.Write vbCrLf & "--End--" & vbCrLf
End With
Next
objFile.Close
MsgBox "Email text extraction completed!", vbOKOnly + vbInformation, "DONE!"
Set objFS = Nothing
Set objFile = Nothing
Set objItem = Nothing
End Sub
Reference: Save email message as text file
Hers is a shorter Solution I came up with that just saves the body of the message.
Sub selectToText()
Dim Omail As Outlook.MailItem
Set Omail = Application.ActiveExplorer.Selection.Item(1)'Selected Message
Dim subject As String: subject = Omail.subject 'Get subject
Dim rmv As Variant: rmv = Array("\", "/", ":", "*", "?", """", "<", ">", "|") 'Invalid chars for a file name
Dim r As Variant 'holds a char
Dim txtFile As String 'holds dir to save to
For Each r In rmv ' remove invalid chars
subject = Replace(subject, r, "")
Next r
txtFile = "C:\" & subject & ".txt" 'set save to location CHANGE this to where you want to save!
Open txtFile For Output As #1
Write #1, Omail.Body 'write email body to save location
Close #1
End Sub