File Access Error when auto printing in Outlook 2013 - vba

I have the following code that auto prints my pdf when an email is received. Every now and then i get a file access error and it holds up all emails from being checked. Most times it happens multiple times when it happens.
I have tried a couple things but still get that error every now and then.
Sub LSPrint(Item As Outlook.MailItem)
On Error GoTo OError
'detect Temp
Dim oFS As FileSystemObject
Dim sTempFolder As String
Set oFS = CreateObject("Scripting.FileSystemObject")
'Temporary Folder Path
sTempFolder = oFS.GetSpecialFolder(TemporaryFolder)
'creates a special temp folder
cTmpFld = sTempFolder & "\OETMP" & Format(Now, "yyyymmddhhmmss")
MkDir (cTmpFld)
'save & print
Dim oAtt As Attachment
For Each oAtt In Item.Attachments
FileName = oAtt.FileName
fullfile = cTmpFld & "\" & FileName
'save attachment
oAtt.SaveAsFile (fullfile)
'prints attachment
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.NameSpace(0)
Set objFolderItem = objFolder.ParseName(fullfile)
objFolderItem.InvokeVerbEx ("print")
Next oAtt
'Cleanup
If Not oFS Is Nothing Then Set oFS = Nothing
If Not objFolder Is Nothing Then Set objFolder = Nothing
If Not objFolderItem Is Nothing Then Set objFolderItem = Nothing
If Not objShell Is Nothing Then Set objShell = Nothing
OError:
If Err <> 0 Then
MsgBox Err.Number & " - " & Err.Description
Err.Clear
End If
Exit Sub
End Sub

Likely the file has not finished saving.
Sub LSPrint(Item As Outlook.MailItem)
' Remove this line to determine the line with the error
' On Error GoTo OError
dim i as long
'detect Temp
Dim oFS As FileSystemObject
Dim sTempFolder As String
Set oFS = CreateObject("Scripting.FileSystemObject")
'Temporary Folder Path
sTempFolder = oFS.GetSpecialFolder(TemporaryFolder)
'creates a special temp folder
cTmpFld = sTempFolder & "\OETMP" & Format(Now, "yyyymmddhhmmss")
MkDir (cTmpFld)
'save & print
Dim oAtt As Attachment
For Each oAtt In Item.Attachments
FileName = oAtt.FileName
fullfile = cTmpFld & "\" & FileName
'save attachment
oAtt.SaveAsFile (fullfile)
'prints attachment
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.NameSpace(0)
On Error GoTo OErrorDelay
' Assuming it is the line with the error
Set objFolderItem = objFolder.ParseName(fullfile)
on error goto 0
objFolderItem.InvokeVerbEx ("print")
Next oAtt
'Cleanup
Set oFS = Nothing
Set objFolder = Nothing
Set objFolderItem = Nothing
Set objShell = Nothing
exit sub
OError:
MsgBox Err.Number & " - " & Err.Description
Err.Clear
Exit Sub
OErrorDelay:
' Assuming the error is due to the file not yet being available
' Some method to delay the print request
' This will use the minimum delay, if it works
i = i + 1
' some "reasonable" number
if i > 100000 then goto OError
resume
End Sub

Related

VBA Outlook automatically print to email attachment error '438': Object doesn't support this property or method

I want you to print the attachment of the incoming email. But it runs into an 438 error :( What could be wrong?
Code:
Sub AttachmentPrint(Item As Outlook.MailItem)
On Error GoTo OError
Dim oFS As FileSystemObject
Dim sTempFolder As String
Set oFS = New FileSystemObject
sTempFolder = oFS.GetSpecialFolder(TemporaryFolder)
cTmpFld = sTempFolder & "\OETMP" & Format(Now, "yyyymmddhhmmss")
MkDir (cTmpFld)
Dim oAtt As Attachment
For Each oAtt In Item.Attachments
FileName = oAtt.FileName
FileType = LCase$(Right$(FileName, 4))
FullFile = cTmpFld & "\" & FileName
oAtt.SaveAsFile (FullFile)
Select Case FileType
Case ".doc", "docx", ".pdf", ".txt", ".jpg"
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.NameSpace(0)
Set objFolderItem = objFolder.ParseName(FullFile)
objFolderItem.InvokeVebrEx ("Print")
End Select
Next oAtt
If Not oFS Is Nothing Then Set oFS = Nothing
If Not objFolder Is Nothing Then Set objFolder = Nothing
If Not objFolderItem Is Nothing Then Set objFolderItem = Nothing
If Not objShell Is Nothing Then Set objShell = Nothing
OError:
If Err <> 0 Then
MsgBox Err.Number & " - " & Err.Description
Err.Clear
End If
Exit Sub
End Sub
Not all objects support all properties and methods. This error has the following cause and solution:
You specified a method or property that doesn't exist for this automation object. See the object's documentation for more information on the object and check the spellings of properties and methods.
To find out what property or method causes the issue I'd recommend removing the On Error GoTo OError line. So, you will be able to run the code and see what line exactly causes the problem.
Typo in objFolderItem.InvokeVebrEx ("Print").
Option Explicit ' Consider this mandatory
' Tools | Options | Editor tab
' Require Variable Declaration
' If desperate declare as Variant
Private Sub Test()
AttachmentPrint ActiveInspector.CurrentItem
End Sub
Sub AttachmentPrint(Item As MailItem)
' Reference Microsoft Scripting Runtime
Dim oFS As FileSystemObject
Dim sTempFolder As String
Dim cTmpFld As String
Dim fileName As String
Dim FileType As String
Dim FullFile As String
Dim objShell As Object
Dim objFolder As Object
Dim objFolderItem As Object
Set oFS = New FileSystemObject
sTempFolder = oFS.GetSpecialFolder(TemporaryFolder)
cTmpFld = sTempFolder & "\OETMP" & Format(Now, "yyyymmddhhmmss")
' You may delete this folder later
Debug.Print cTmpFld
MkDir cTmpFld
Dim oAtt As Attachment
For Each oAtt In Item.Attachments
fileName = oAtt.fileName
FileType = LCase$(Right$(fileName, 4))
FullFile = cTmpFld & "\" & fileName
oAtt.SaveAsFile FullFile
Select Case FileType
Case ".doc", "docx", ".pdf", ".txt", ".jpg"
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.NameSpace(0)
Set objFolderItem = objFolder.ParseName(FullFile)
'objFolderItem.InvokeVebrEx ("Print") ' <--- Typo ER438
objFolderItem.InvokeVerbEx ("Print")
End Select
Next oAtt
'https://stackoverflow.com/questions/19038350/when-should-an-excel-vba-variable-be-killed-or-set-to-nothing
' Not detrimental if memory is deallocated unnecessarily.
' You could decide to apply only when forced to do so.
'Set oFS = Nothing
'Set objFolder = Nothing
'Set objFolderItem = Nothing
'Set objShell = Nothing
End Sub
Thanks for the help, I rewrote it a bit and it works like this:
Sub Autoprint()
Dim objFileSystem As Object
Dim objSelection As Outlook.Selection
Dim objShell As Object
Dim objTempFolder As Object
Dim objTempFolderItem As Object
Dim oFS As FileSystemObject
Dim sTempFolder As String
Set oFS = New FileSystemObject
sTempFolder = "C:\temp"
cTmpFld = sTempFolder & "\nyomtatas" & Format(Now, "yyyymmddhhmmss")
MkDir (cTmpFld)
Dim oAtt As Attachment
For Each oAtt In Item.Attachments
FileName = oAtt.FileName
FileType = LCase$(Right$(FileName, 4))
FullFile = cTmpFld & "\" & FileName
oAtt.SaveAsFile (FullFile)
Select Case FileType
Case ".doc", "docx", ".pdf", ".txt", ".jpg"
Set objShell = CreateObject("Shell.Application")
Set objTempFolder = objShell.NameSpace(0)
Set objTempFolderItem = objTempFolder.ParseName(FullFile)
objTempFolderItem.InvokeVerbEx ("print")
End Select
Next oAtt
End Sub

How to print invoices automatically when multiple attachments are named the same?

My macro prints invoices automatically but when multiple attachments are named the same, it prints only the first one multiple times.
Sub LSPrint(Item As Outlook.MailItem)
On Error Resume Next
Dim oFS As FileSystemObject
Dim sTempFolder As String
Set oFS = New FileSystemObject
sTempFolder = oFS.GetSpecialFolder(TemporaryFolder)
cTmpFld = sTempFolder & "\OETMP" & Format(Now, "yyyymmddhhmmss")
MkDir (cTmpFld)
Dim oAtt As Attachment
For Each oAtt In Item.Attachments
FileName = oAtt.FileName
FullFile = cTmpFld & "\" & FileName
oAtt.SaveAsFile (FullFile)
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.NameSpace(0)
Set objFolderItem = objFolder.ParseName(FullFile)
objFolderItem.InvokeVerbEx ("print")
Next oAtt
If Not oFS Is Nothing Then Set oFS = Nothing
If Not objFolder Is Nothing Then Set objFolder = Nothing
If Not objFolderItem Is Nothing Then Set objFolderItem = Nothing
If Not objShell Is Nothing Then Set objShell = Nothing
OError:
If Err <> 0 Then
MsgBox Err.Number & " - " & Err.Description
Err.Clear
End If
Exit Sub
End Sub
How do I print multiple attachments if they are named the same?
Possibly renaming the files and then printing those.
As you stated, created a naming convention to force unique file names among the attachments. This is done here with variable i
Dim oAtt As Attachment
Dim i as Long: i = 1
For Each oAtt In Item.Attachments
FileName = oAtt.FileName
FullFile = cTmpFld & "\" & FileName & i '<-- add unique identifier
oAtt.SaveAsFile (FullFile)
'.... More stuff
i = i + 1 '<-- increment to next unique identifier
Next oAtt
Try changing the following line
FileName = oAtt.FileName
To
FileName = oAtt.FileName & Format(Now, " yyyymmddhhmmssms")

Saving Outlook Emails as ".msg" not as "File"

I've got this block of code to go through all the emails in my "Today" folder in Outlook, then save all the emails (.msg) to a folder named as the sender name.
Sometimes the files are saving with the file type "file".
How do I fix this to make sure the emails are saved as .msg files?
Sub SaveAttachments()
'https://www.fontstuff.com/outlook/oltut01.htm
'Declare Variables
Dim ns As NameSpace
Dim Inbox As Outlook.MAPIFolder
Dim Item As Object
Dim Atmt As Attachment
Dim Savefolder As String
Dim i As Integer
Set ns = GetNamespace("MAPI")
Set Inbox = ns.GetDefaultFolder(olFolderInbox).Folders("Today")
i = 0
'Stop script if there are no emails
If Inbox.Items.Count = 0 Then
MsgBox "There are no messages in the Inbox.", vbInformation, "Nothing Found"
Exit Sub
End If
'Display the number of emails
MsgBox Inbox.Items.Count, vbInformation, _
"Number of Emails?"
'Go through each email
For Each Item In Inbox.Items
'Create a path for the save folder
Savefolder = "C:\Users\work\Desktop\22_11_18\Test\" & Item.SenderName
'If the email has attachments, then create a folder
If Item.Attachments.Count > 0 Then
MkDir Savefolder
'If the folder already exists, skip to the next statement
On Error Resume Next
'Save the email as a .msg file
Item.SaveAs Savefolder & "\" & Item.Subject & ".msg"
End If
Next Item
End Sub
You can use subject if the characters in the subject are all valid.
Option Explicit
Private Sub SaveMail_ContainingAttachments_ValidSubject()
'Declare Variables
Dim ns As Namespace
Dim targetFolder As Folder
Dim itm As Object
Dim atmt As Attachment
Dim strSaveFolder As String
Dim validSubject As String
Set ns = GetNamespace("MAPI")
Set targetFolder = ns.GetDefaultFolder(olFolderInbox)
Set targetFolder = targetFolder.Folders("Today")
'Stop script if there are no emails
If targetFolder.Items.count = 0 Then
MsgBox "There are no messages in " & targetFolder & ".", vbInformation, "Nothing Found"
Exit Sub
End If
'Display the number of emails
MsgBox targetFolder.Items.count, vbInformation, "Number of Emails?"
'Go through each email
For Each itm In targetFolder.Items
'If the email has attachments, then create a folder
If itm.Attachments.count > 0 Then
'Create a path for the save folder
strSaveFolder = "C:\Users\work\Desktop\22_11_18\Test\" & itm.senderName
' Bypass error if the folder already exists
On Error Resume Next
MkDir strSaveFolder
' Discontinue error bypass as soon as the purpose is served
' Let unknown errors generate then fix them
On Error GoTo 0
' Replace or remove invalid characters
' Possible options "_" or " " or "" ....
validSubject = ReplaceIllegalChar(itm.subject, "_")
If validSubject <> itm.subject Then
Debug.Print itm.subject
Debug.Print validSubject
End If
'Save the email as a .msg file
itm.SaveAs strSaveFolder & "\" & validSubject & ".msg"
End If
Next itm
End Sub
Private Function ReplaceIllegalChar(strInput, strReplace)
Dim RegX As Object
Set RegX = CreateObject("vbscript.regexp")
RegX.Pattern = "[\" & Chr(34) & "\!\#\#\$\%\^\&\*\(\)\=\+\|\[\]\{\}\`\'\;\:\<\>\?\/\,]"
RegX.IgnoreCase = True
RegX.Global = True
' Replace with another string
ReplaceIllegalChar = RegX.Replace(strInput, strReplace)
ExitFunction:
Set RegX = Nothing
End Function

Rule that runs code to save attachments turns off

This Run a Script code to save attachments stops saving attachments because the rule turns off.
Public Sub SaveAttachmentsToDisk(MItem As Outlook.MailItem)
Dim oAttachment As Outlook.Attachment
Dim sSaveFolder As String
sSaveFolder = "C:\Users\andra.aeras\Documents\Test\"
For Each oAttachment In MItem.Attachments
If Right(oAttachment.FileName, 4) = "xlsx" Then
oAttachment.SaveAsFile sSaveFolder & oAttachment.DisplayName
End If
Next
End Sub
Is there a way to "enable" the rules or improve this code to run properly or run without using rules?
Try it like this.
Sub SaveEmailAttachmentsToFolder(OutlookFolderInInbox As String, _
ExtString As String, DestFolder As String)
Dim ns As Namespace
Dim Inbox As MAPIFolder
Dim SubFolder As MAPIFolder
Dim Item As Object
Dim Atmt As Attachment
Dim FileName As String
Dim MyDocPath As String
Dim I As Integer
Dim wsh As Object
Dim fs As Object
On Error GoTo ThisMacro_err
Set ns = GetNamespace("MAPI")
Set Inbox = ns.GetDefaultFolder(olFolderInbox)
Set SubFolder = Inbox.Folders(OutlookFolderInInbox)
I = 0
' Check subfolder for messages and exit of none found
If SubFolder.Items.Count = 0 Then
MsgBox "There are no messages in this folder : " & OutlookFolderInInbox, _
vbInformation, "Nothing Found"
Set SubFolder = Nothing
Set Inbox = Nothing
Set ns = Nothing
Exit Sub
End If
'Create DestFolder if DestFolder = ""
If DestFolder = "" Then
Set wsh = CreateObject("WScript.Shell")
Set fs = CreateObject("Scripting.FileSystemObject")
MyDocPath = wsh.SpecialFolders.Item("mydocuments")
DestFolder = MyDocPath & "\" & Format(Now, "dd-mmm-yyyy hh-mm-ss")
If Not fs.FolderExists(DestFolder) Then
fs.CreateFolder DestFolder
End If
End If
If Right(DestFolder, 1) <> "\" Then
DestFolder = DestFolder & "\"
End If
' Check each message for attachments and extensions
For Each Item In SubFolder.Items
For Each Atmt In Item.Attachments
If LCase(Right(Atmt.FileName, Len(ExtString))) = LCase(ExtString) Then
FileName = DestFolder & Item.SenderName & " " & Atmt.FileName
Atmt.SaveAsFile FileName
I = I + 1
End If
Next Atmt
Next Item
' Show this message when Finished
If I > 0 Then
MsgBox "You can find the files here : " _
& DestFolder, vbInformation, "Finished!"
Else
MsgBox "No attached files in your mail.", vbInformation, "Finished!"
End If
' Clear memory
ThisMacro_exit:
Set SubFolder = Nothing
Set Inbox = Nothing
Set ns = Nothing
Set fs = Nothing
Set wsh = Nothing
Exit Sub
' Error information
ThisMacro_err:
MsgBox "An unexpected error has occurred." _
& vbCrLf & "Please note and report the following information." _
& vbCrLf & "Macro Name: SaveEmailAttachmentsToFolder" _
& vbCrLf & "Error Number: " & Err.Number _
& vbCrLf & "Error Description: " & Err.Description _
, vbCritical, "Error!"
Resume ThisMacro_exit
End Sub
Sub Test()
'Arg 1 = Folder name of folder inside your Inbox
'Arg 2 = File extension, "" is every file
'Arg 3 = Save folder, "C:\Users\Ron\test" or ""
' If you use "" it will create a date/time stamped folder for you in your "Documents" folder
' Note: If you use this "C:\Users\Ron\test" the folder must exist.
SaveEmailAttachmentsToFolder "MyFolder", "xls", ""
End Sub
Steps to follow:
1) Go to the VBA editor, Alt -F11
2) Tools>References in the Menu bar
3) Place a Checkmark before Microsoft Outlook ? Object Library
? is the Outlook version number
4) Insert>Module
5) Paste the code (two macros) in this module
6) Alt q to close the editor
7) Save the file

VBA: Only save the last (The most recent) email attachment in a local folder

I need to save the attachment of last email that has a specific subject (the most recent one) to a local folder, to do this I have created a folder in my Outlook and a rule to send every email with that specific subject to this folder. I have found a code that does what I needed except that it saves every single attachment in the email folder rather than saving only the most recent one. This is the code: how could i modify it so that it does what i need?
Sub Test()
'Arg 1 = Folder name of folder inside your Inbox
'Arg 2 = File extension, "" is every file
'Arg 3 = Save folder, "C:\Users\Ron\test" or ""
' If you use "" it will create a date/time stamped folder for you in your "Documents" folder
' Note: If you use this "C:\Users\Ron\test" the folder must exist.
SaveEmailAttachmentsToFolder "Dependencia Financiera", "xls", "W:\dependencia financiera\test dependencia\"
End Sub
Sub SaveEmailAttachmentsToFolder(OutlookFolderInInbox As String, _
ExtString As String, DestFolder As String)
Dim ns As NameSpace
Dim Inbox As MAPIFolder
Dim SubFolder As MAPIFolder
Dim Item As Object
Dim Atmt As Attachment
Dim FileName As String
Dim MyDocPath As String
Dim i As Integer
Dim wsh As Object
Dim fs As Object
On Error GoTo ThisMacro_err
Set ns = GetNamespace("MAPI")
Set Inbox = ns.GetDefaultFolder(olFolderInbox)
Set SubFolder = Inbox.Folders(OutlookFolderInInbox)
i = 0
' Check subfolder for messages and exit of none found
If SubFolder.Items.Count = 0 Then
MsgBox "There are no messages in this folder : " & OutlookFolderInInbox, _
vbInformation, "Nothing Found"
Set SubFolder = Nothing
Set Inbox = Nothing
Set ns = Nothing
Exit Sub
End If
'Create DestFolder if DestFolder = ""
' If DestFolder = "" Then
' Set wsh = CreateObject("WScript.Shell")
' Set fs = CreateObject("Scripting.FileSystemObject")
' MyDocPath = wsh.SpecialFolders.Item("mydocuments")
' DestFolder = MyDocPath & "\" & Format(Now, "dd-mmm-yyyy hh-mm-ss")
' If Not fs.FolderExists(DestFolder) Then
'fs.CreateFolder DestFolder
' End If
'End If
'If Right(DestFolder, 1) <> "\" Then
'DestFolder = DestFolder & "\"
'End If
' Check each message for attachments and extensions
'JUST BEED TGE FIRST EMAIL
'Debug.Print Item(1).SentOn
For Each Item In SubFolder.Items
For Each Atmt In Item.Attachments
If LCase(Right(Atmt.FileName, Len(ExtString))) = LCase(ExtString) Then
FileName = DestFolder & Atmt.FileName
Atmt.SaveAsFile FileName
'I = I + 1
End If
Next Atmt
Next Item
' Show this message when Finished
' If I > 0 Then
' MsgBox "You can find the files here : " _
& DestFolder, vbInformation, "Finished!"
' Else
' MsgBox "No attached files in your mail.", vbInformation, "Finished!"
' End If
' Clear memory
ThisMacro_exit:
Set SubFolder = Nothing
Set Inbox = Nothing
Set ns = Nothing
Set fs = Nothing
Set wsh = Nothing
Exit Sub
' Error information
ThisMacro_err:
MsgBox "An unexpected error has occurred." _
& vbCrLf & "Please note and report the following information." _
& vbCrLf & "Macro Name: SaveEmailAttachmentsToFolder" _
& vbCrLf & "Error Number: " & Err.Number _
& vbCrLf & "Error Description: " & Err.Description _
, vbCritical, "Error!"
Resume ThisMacro_exit
End Sub
You could try this
Sub SaveEmailAttachmentsToFolder(OutlookFolderInInbox As String, _
ExtString As String, DestFolder As String)
Dim ns As Namespace
Dim Inbox As Folder
Dim SubFolder As Folder
Dim subFolderItems As Items
Dim Atmt As attachment
Dim FileName As String
Set ns = GetNamespace("MAPI")
Set Inbox = ns.GetDefaultFolder(olFolderInbox)
Set SubFolder = Inbox.Folders(OutlookFolderInInbox)
Set subFolderItems = SubFolder.Items
If subFolderItems.count > 0 Then
subFolderItems.Sort "[ReceivedTime]", True
For Each Atmt In subFolderItems(1).Attachments
If LCase(Right(Atmt.FileName, Len(ExtString))) = LCase(ExtString) Then
FileName = DestFolder & Atmt.FileName
Atmt.SaveAsFile FileName
End If
Next Atmt
End If
' Clear memory
ThisMacro_exit:
Set SubFolder = Nothing
Set Inbox = Nothing
Set ns = Nothing
Set subFolderItems = Nothing
End Sub
Consider ItemAdd. The most recent item is already known. How do I trigger a macro to run after a new mail is received in Outlook?