Link to home
Start Free TrialLog in
Avatar of cllocc
cllocc

asked on

Print attachments from an email automatically?

Is there a VB script or batch file that would allow me to print only the attachments of unread emails or emails in a certain folder in outlook 2010 automatically?
Avatar of Ravindran Gopinathan
Ravindran Gopinathan
Flag of United States of America image

http://www.vbaexpress.com/kb/getarticle.php?kb_id=522

Check this.. It has a macro that would server your exact purpose! You can get more just by Googling :)
Avatar of cllocc
cllocc

ASKER

Thanks! It seems that the script can print MS Office based files. can the script be tweaked to print files with .pdf or .img file extensions?
ASKER CERTIFIED SOLUTION
Avatar of Ravindran Gopinathan
Ravindran Gopinathan
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of cllocc

ASKER

great, I will be testing these out and let you know
Writing some code for you now...stand by
Avatar of cllocc

ASKER

ravindran_eee:
The concept would be the same.. You have to tweak the print subroutine a little bit based on the extension of the file.. For printing PDFs you can use something like this

Shell """C:\Program Files\Adobe\Reader 8.0\Reader\acrord32.exe"" /h /p """ + FileName + """", vbHide

http://www.howtogeek.com/howto/microsoft-office/batch-print-pdf-attachments-in-outlook/

I followed instructions on the website and after some tweaking of my own, the script is working now. I just need to test again on 2 more computers but I think your solution definitely works
Avatar of cllocc

ASKER

craisin:
Writing some code for you now...stand by

I definitely appreciate the effort, but I got the code from website working. Unless you are making something better that allows for more customization, otherwise the code off the website works great.

Thanks again.
Avatar of cllocc

ASKER

Ok, another issue. I created a public folder and added it to my favorites. PDFs will be coming to this public folder. How can i edit the script so that I can point the script to the public folder in my favorites?  Currently, the path to the public folder in my favorites is displayed as follows:

 \\Public Folders - user@mydomain.com\Favorites
Yes, this code is much better.

Try it out.


You simply run the macro ""PrintAttachments" when an email message is selected.

The code will ascertain from the system what program is the executable program to operate on the attachment.
If the attachment is a ZIP file, it will examine each file in the zip and print each file (if possible) using recursion.
I have not yet ascertained the way of handling "html" or "htm" files, but perhaps someone else can shed a light on that.

Anyfile not printed whill be reported in a message after the macro runs.

Hope you like this idea.

Cheers
Chris
(craisin)



Const MAX_FILENAME_LEN = 260
Private Declare Function FindExecutable Lib "shell32.dll" Alias "FindExecutableA" (ByVal lpFile As String, ByVal lpDirectory As String, ByVal lpResult As String) As Long

Public Sub PrintAttachments()

'Code to print all attachments to an email
  Dim oItem As Object
  Dim oAttach As outlook.Attachment
  Dim cNoPrint As String
  Dim cTempFile As String
     
 'obtain pointer to current email message
  Set oItem = Application.ActiveInspector.CurrentItem
  For Each oAttach In oItem.Attachments
    cTempFile = "c:\" + oAttach.FileName
    oAttach.SaveAsFile cTempFile
    PrintFile cTempFile, cNoPrint
  Next
  If Len(cNoPrint) > 0 Then
    MsgBox "The following files could not be printed:" + vbCrLf + _
           "(No file Association or macro cannot yet handle extension)" + vbCrLf + vbCrLf + cNoPrint
  End If
End Sub
Private Sub PrintFile(cTempFile As String, ByRef cNoPrint As String)
Dim i As Integer
Dim s As String
Dim nAt As Integer
Dim cExt As String
Dim cRun As String
Dim nFile As Integer
Dim cLine As String
Dim nRun As Long
Dim fs As Object
Set fs = CreateObject("Scripting.FileSystemObject")
s = String(MAX_FILENAME_LEN, 32)
'Retrieve the name and handle of the executable, associated with this file
i = FindExecutable(cTempFile, vbNullString, s)
If i > 32 Then
  cRun = Left$(s, InStr(s, Chr$(0)) - 1)
  nAt = InStrRev(cTempFile, ".")
  cExt = Mid(cTempFile, nAt)
  Select Case LCase(cExt)
    Case ".zip"
      cRun = fs.GetparentFoldername(cRun) + "\"
      cRun = cRun + "wzunzip.exe " + Chr(34) + cTempFile + Chr(34) + " c:\TempZipExtract"
      Shell cRun, vbHide
      cTempFile = Dir("C:\TempZipExtract\*.*")
      Do While cTempFile <> ""   ' Start the loop
         PrintFile "c:\TempZipExtract\" + cTempFile, cNoPrint 'Recursion!
         cTempFile = Dir
      Loop
    Case ".pdf"
      Shell cRun + "/h /p " + Chr(34) + cTempFile + Chr(34), vbHide
    Case ".txt"
      Shell "NOTEPAD.EXE /p " + cTempFile, vbHide
    Case "html", "htm"
      'code to print HTML files should be placed here
      'then remove the following
      
    Case Else
      nRun = Shell(cRun + " " + cTempFile, vbHide)
      If nRun = 0 Then
        cNoPrint = cNoPrint + cTempFile
      End If
  End Select
Else
  cNoPrint = cNoPrint + cTempFile
End If
End Sub

Open in new window

Avatar of cllocc

ASKER

so if i run this macro will it print attachments of emails in my entire inbox or a certain folder? Will my just navigating to the folder then running the macro be enough to only print the attachments in that folder or would i have to specify that folder in the code?
Avatar of cllocc

ASKER

You simply run the macro ""PrintAttachments" when an email message is selected.

Is there anyway to setup this up like the other macro so when it runs, it automatically checks a specified folder without the user having to select individual emails?
Further to the previous code, you could add code to go through all the emails in a certain folder (or multiple folders), and for each email that has not been read or in a certain folder to run the "PrintAttachments" code:

e.g. Dim oEmail As Object
       For each oEmail in Application.ActiveInspector    'or folder name
           PrintAttachments
       Next

This is just an idea....it has not been tested. I am not sure whether "Application.ActiveInspector" will work, but I have been working on this for 5 hours now and it is 3.40am...so I am off to bed!  :-)

Cheers
Chris
(craisin)
     
   
Avatar of cllocc

ASKER

Wow, sounds like you are in south east asia or my australia? thanks again for the hard work, I'll have to see if I can tweak the code to be able to print from a public folder in my favorites.
As far as your "favourites" go, in the code I have supplied, you can tweak lines 14 to 18 as follows:


   For Each oAttach In oItem.Attachments
    if right(lcase(oAttach.filename),3) = "pdf" then
        cTempFile = "\\Public Folders - " +  
                            _user@mydomain.com\Favorites\"+oAttach.Filename
    else
        cTempFile = "c:\" + oAttach.FileName
    endif
    oAttach.SaveAsFile cTempFile
    PrintFile cTempFile, cNoPrint
  Next
At the moment the code will only pront the attachments of the currently selected email.

You will need to include further code to surround the block of code satarting at lines 12-13, viz:

    'obtain pointer to current email message
    Set oItem = Application.ActiveInspector.CurrentItem

Instead of "CurrentItem" the object "oItem" would be set to point to each email in a folder. In turn, each folder would be exaqmined.

The logic would be:

     For each folder in my Outlook
     .....Look at each email item.
          For each item (if it has not been read)
          .......PrintAttachments()

I would have to do a lot more testing to expamnd this, but I must get off to bed (I have to attend a funeral in about 5 hours!....Not my own, thank goodness!

Will check back later this afternoon.

Goodnight...
Chris
(craisin)

         
Avatar of cllocc

ASKER

Wow, thanks again, I will test out your suggestions and report back.
Yes, I am in Australia.......(Melbourne)....Off to the funeral now///will be able to do some more work on this later tonight (in about 15 hours time) since I am running a bridge club tonight and need to prepare all the hands etc. this afternoon.

Can work extensively on this tomorrow (Saturday) as well.......looks very promising.

The only problem I have (of course) is that when I test my printer keeps wanting top print heaps of stuff! :-)

Cheers....be back soon.

Chris
(craisin)
OK...This is where I am at.

The code below appears to work by scanning all the folders and subfolders.

Rather than PRINT everything during testing, I have a message box popping up  saying an item is being printed (simulation)  The box shows the filename and also the SUBJECT of the message to which the file is attached.

If you answer "NO" to the message, the macro stops.
If you answer "Yes" it continues (This could take a while if there are a lot of messages with attachments).

Once we are happy it is doing what it should, we can comment out the "ShowMsg" lines and UNComment the actual lines which do the printing within the sub "PrintFile".

Warning: The MsgBox at the end could be VERY big if a lot of files do not print.
We will remove this "Files not printed" message, I think, once we know every thing is running as it should.

Of course you can tweak the code to suit.

I think this code runs through ALL Folders, so if you only want it on the currently selected Folder, the code will need changing (perhaps a seperate version for "Current Folder" as opposed to "All Folders"?)

Give this a code a test and see how you go.

Cheers
Chris
(craisin)
Public Sub PrintAttachments()

'Code to print all attachments to an email
  Dim objOutlook As New outlook.Application
  Dim objNS As outlook.NameSpace
  Dim objFolder As outlook.MAPIFolder
  Dim nFolder As Long
  Dim objSubFolder As Object
  Dim oItems As Object
  Dim oItem As outlook.MailItem
  Dim oAttach As outlook.Attachment
  Dim cTempFile As String
  Dim cNoPrint As String

  
  Set objNS = objOutlook.Session
  Set objFolder = objNS.Folders.GetFirst
  
  On Error Resume Next  'just in case folder already exists....
  Kill "C:\TempPrint\TempZipExtract\*.*"
  RmDir "c:\TempPrint\TempZipExtract"
  Kill "C:\TempPrint\*.*"
  MkDir "C:\TempPrint"
  On Error GoTo 0

  'Set objFolder = outlook.Session.Folders.Item("Public Folders")

  For nFolder = 0 To objFolder.Folders.Count
    'Set objFolders = outlook.Session.Folders
    For Each objSubFolder In objFolder.Folders
      'obtain pointer to current email message
      Set oItems = objSubFolder.Items
      For Each oItem In oItems
        For Each oAttach In oItem.Attachments
          cTempFile = "c:\TempPrint\" + oAttach.FileName
          On Error GoTo skipprint
          oAttach.SaveAsFile cTempFile
          PrintFile cTempFile, cNoPrint, oItem
skipprint:
          DoEvents
        Next
        DoEvents
      Next
      DoEvents
    Next
    DoEvents
  Next
  If Len(cNoPrint) > 0 Then
    MsgBox "The following files could not be printed:" + vbCrLf + _
           "(No file Association or macro cannot yet handle extension)" + vbCrLf + vbCrLf + cNoPrint
  End If
  On Error Resume Next
  Kill "c:\TempPrint\*.*"
End Sub


Private Sub PrintFile(cTempFile As String, ByRef cNoPrint As String, oItem As outlook.MailItem)
Dim i As Integer
Dim s As String
Dim nAt As Integer
Dim cExt As String
Dim cRun As String
Dim nFile As Integer
Dim cLine As String
Dim nRun As Long
Dim fs As Object
Set fs = CreateObject("Scripting.FileSystemObject")
s = String(MAX_FILENAME_LEN, 32)
'Retrieve the name and handle of the executable, associated with this file
i = FindExecutable(cTempFile, vbNullString, s)
If i > 32 Then
  cRun = Left$(s, InStr(s, Chr$(0)) - 1)
  nAt = InStrRev(cTempFile, ".")
  cExt = Mid(cTempFile, nAt)
  Select Case LCase(cExt)
    Case ".zip"
      cRun = fs.GetparentFoldername(cRun) + "\"
      cRun = cRun + "wzunzip.exe " + Chr(34) + cTempFile + Chr(34) + " c:\TempPrint\TempZipExtract"
      Shell cRun, vbHide
      cTempFile = Dir("C:\TempPrint\TempZipExtract\*.*")
      Do While cTempFile <> ""   ' Start the loop
         PrintFile "c:\TempPrint\TempZipExtract\" + cTempFile, cNoPrint, oItem 'Recursion!
         cTempFile = Dir
      Loop
    Case ".pdf"
      ShowMsg "Printing " + cTempFile, oItem
      'Shell cRun + "/h /p " + Chr(34) + cTempFile + Chr(34), vbHide
    Case ".jpg", ".gif", ".tif"
      'do we reaally want to print graphics?
    Case ".txt"
      ShowMsg "Printing " + cTempFile + " using Notepad", oItem
      'Shell "NOTEPAD.EXE /p " + cTempFile, vbHide
    Case ".doc", ".docx"
      ShowMsg "Printing " + cTempFile, oItem
      'put ome code here to send a word document to the printer
    Case "html", "htm"
      'code to print HTML files should be placed here
    Case Else
      'I think we should not chance trying to print a file with an
      'extension for which we have not specifically allowed.
       cNoPrint = cNoPrint + cTempFile
  End Select
Else
  cNoPrint = cNoPrint + cTempFile
End If
End Sub


Private Sub ShowMsg(cMsg, oItem As outlook.MailItem)
  If MsgBox(cMsg + vbCrLf + "(Subject: " + oItem.Subject + ")" + vbCrLf + "Continue?", vbInformation + vbYesNo) = vbNo Then
    End
  End If
End Sub

Open in new window

Avatar of cllocc

ASKER

So with this code, say if I have two emails and both have a pdf attachment with the same name, will this script be able to save both files in the C temp folder and name the other one with a (1) suffix to prevent file name conflicts?

Not a big issue i guess, since I can guide the user to go to the temp file and delete the older file with the same name after it has been printed, but some automation in the task would be nice to prevent user errors.
Avatar of cllocc

ASKER

Also, chris, I have another question about how to auto move items from one folder to another, I'm not sure if you could help me out with that as well?
At line 105 in the "PrintFile" subroutine add the line:  "Kill cTempFile". That should delete the temporary file after it has been printed. Then the problem of "duplicated file names" would not be a problem.

If the file cannot be printed in that routine it will then still be deleted (which is what we are after).

Even though you have added that line, I would still leave in the other "Kill" lines in the "PrintAttachments" routine, just to be on the safe side.

As far as the "automove" question goes, are you talking about moving emails from one folder to another as they are received (rather than simply going into the "InBox")? If so, you will have to post it as another question, since it really has no connection with the question of printing attachments. I would be more than happy to he;p out then, but please hold off for about 10 hours though, so I can get some sleep first!  :-)

Cheers
Chris




 

Avatar of cllocc

ASKER

Already posted the question. ID: 27324253
Avatar of cllocc

ASKER

well after extensively testing both craisin's script and the script from how to geek posted by ravindran_eee, it seems that i was able to get the latter working very well. I tried to play around with yours, chris, but once the other script starting working to suit our company's needs, i didnt have the time or liberty to continue testing yours.

But, i do want to thank you, chris, for the time you put into the script, it was above and beyond the quality of effort i expected any expert at EE to put in. And certainly your script allowed me to get a bit more acquainted with VB script.

Thanks to both experts for helping me out.
Avatar of cllocc

ASKER

The script from ravindran eee posted on how to geek worked out exactly as needed.