Solved

Outlook 2003 "print it" rule

Posted on 2009-07-01
16
929 Views
Last Modified: 2012-05-07
Is there a way in Outlook 2003 to set the "print it" rule to print to a specific network printer and not to the default printer?
0
Comment
Question by:boettcher1
  • 7
  • 7
  • 2
16 Comments
 
LVL 76

Expert Comment

by:David Lee
ID: 24756429
Hi, boettcher1.

Not with a rule alone.  It's possible with a rule that runs a macro.  Is that an option?
0
 

Author Comment

by:boettcher1
ID: 24756579
I would love to try that if you can walk me through how to do it!!
0
 
LVL 76

Expert Comment

by:David Lee
ID: 24756906
Here's the code for doing this.  It works by switching the default printer to the desired printer, printing the message, and then switching the default printer back to what it was.  Follow these instructions to set up and use this.

1.  Start Outlook
2.  Click Tools > Macro > Visual Basic Editor
3.  If not already expanded, expand Modules and click on Module1
4.  Copy the code below and paste it into the right-hand pane of the VB editor window
5.  Edit the code and make changes as needed.  I included comments where a line needs to be edited.
6.  Click the diskette icon on the toolbar to save changes
7.  Close the VB Editor
8.  Click Tools > Macro > Security
9.  Set the Security Level to Medium
10.  Create a rule that fires when this person receives a message.  
11.  Set the action portion of the rule to "run a script" and select this script as the one to run

That should do it.
Public Declare Function GetProfileString Lib "kernel32" Alias "GetProfileStringA" _
        (ByVal lpAppName As String, ByVal lpKeyName As String, _
        ByVal lpDefault As String, ByVal lpReturnedString As String, _
        ByVal nSize As Long) As Long
 
Function GetDefaultPrinter() As String
    Dim strPrinter As String, _
        intReturn As Integer
    strPrinter = Space(255)
    intReturn = GetProfileString("Windows", ByVal "device", "", strPrinter, Len(strPrinter))
    If intReturn Then
        strPrinter = UCase(Left(strPrinter, InStr(strPrinter, ",") - 1))
    End If
    GetDefaultPrinter = strPrinter
End Function
 
Sub PrintMessageToSpecificPrinter(Item As Outlook.MailItem)
    Dim wshNet As Object, _
        strCurrentDefault As String
    strCurrentDefault = GetDefaultPrinter()
    Set wshNet = CreateObject("Wscript.Network")
    'Change the printer name on the next line to that of the printer you want attachments printed to
    wshNet.SetDefaultPrinter "Microsoft Office Document Image Writer"
    Item.PrintOut
    wshNet.SetDefaultPrinter strCurrentDefault
    Set wshNet = Nothing
    Set objFSO = Nothing
End Sub

Open in new window

0
Free learning courses: Active Directory Deep Dive

Get a firm grasp on your IT environment when you learn Active Directory best practices with Veeam! Watch all, or choose any amount, of this three-part webinar series to improve your skills. From the basics to virtualization and backup, we got you covered.

 

Author Comment

by:boettcher1
ID: 24757256
BlueDevilFan,
  When calling the printer in wshNet.SetDefaultPrinter "-----------" how does it want the printer named?  I have tried the following of which none worked:
"\\server name\printer name"
"printername on server name" (this is how it looks in Printers and Faxes)
"hostname"

Thank you for taking the time to "spoon feed" this to me!!
0
 

Author Comment

by:boettcher1
ID: 24757822
BlueDevilFan,
  I now have it switching between the default printer and the network printer I want to print to just fine.  However, when the email prints, it always waits for the default to get set back to the original default printer and then prints.  Thus printing to the wrong printer.  Is there something that I can change in the code?

Thanks!
0
 
LVL 76

Expert Comment

by:David Lee
ID: 24758357
"when the email prints, it always waits for the default to get set back to the original default printer and then prints"
I can't imagine how that's possible.  Line 23 sets the default printer to the printer of your choice.  Line 24 prints the message.  Line 25 switches the default printer back to what it was originally.  The process cannot "wait" for the printer to switch before printing.  It has to print when the print command is issued.  I'm not disputing that the print is going to the wrong printers, merely explaining that the code cannot wait for a switch to occur before printing.  Insert the following line of code between lines 24 and 25.

    Sleep 2000

Add the following line of code to the top of the module

    Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

This introduces a two second delay between printing and restoring the default printer.  Let me know what happens.
0
 

Author Comment

by:boettcher1
ID: 24762354
I added those two lines.  It changes the default printer to the one I want to print to waits the 2 seconds and then changes the default printer back to the original default printer and prints to that printer.  
0
 
LVL 76

Expert Comment

by:David Lee
ID: 24762390
I'm not disputing what you're seeing, but that seems impossible.  There's simply no way for the code to not print when it's told to do so or for it to wait until the printer has switched back.  I've tested this on two different machines I have and it works perfectly on both.  As a test remove line #25 altogether and run it again.  
0
 

Author Comment

by:boettcher1
ID: 24762411
When I do that it changes the default printer to the one I want my email to print to.  Prints to the correct printer.  But does not change the default back.
0
 
LVL 76

Expert Comment

by:David Lee
ID: 24762448
Right.  The test was to show that the process cannot wait for the original printer to be the default again before printing.  If that was happening, then the item would not have printed at all.  It would have sat there waiting for the original default printer to be restored so it could print to it.  The problem appears to be a timing issue.  Apparently the print process is taking so long that the default has switched back to the original printer.  Put line 25 back in place and increase the amount of sleep time from 2000 to 5000.
0
 

Author Comment

by:boettcher1
ID: 24762494
Okay.  I did that.  It changes the defaul printer to the one I want to print to, waits 5 seconds, changes back to the original default printer and prints there.  

I agree with you. I don't get why it won't print to the correct printer.  The command to print  comes before the command to change back to the original default printer.  It isn't making sense why your code isn't working.  In theory, it looks perfect.
0
 

Expert Comment

by:statzd
ID: 24765330
BlueDevilFan,

I plugged in your code and experienced the same thing that boettcher1 did: when run, it will change the default printer to the new one, then change the default printer back to the original, then print, in that order, even though the order of the code says "change printer, print email, change printer back".

 The mailitem.printout method doesn't appear to actually execute to the printer until the script completes, and so when it executes the printer is already back to the original default.

It doesn't make much sense to me either.

I also tried creating separate scripts run by separate Outlook rules (all rules triggered by same criteria):

Rule 1:
  Run script 1: change default printer to \\printserver2\printer2

Rule 2:
  Run script 2: print email

Rule 3:
  Run script 3: change default printer back to \\printserver1\printer1

This also seems to run as 1 complete process, and doesn't send the print command until the third rule and script completes (so prints to the wrong printer).

I also tried running your original code and my abbreviated code with 30 seconds of Sleep just to convince myself that it wasn't a process timing thing - instead of flipping back to the original default printer and printing right away, it just waits 30 seconds, then changes back to the original and prints. The print process just won't execute until the script completes.

A quick work around is to just have a separate Outlook rule and print script for each of the emails that should go to a different printer. Each script changes the default printer to the correct one for that particular email, but does not change it back so that it prints to the right one.
This work-around doesn't satisfy me, though, as with more than a few rules it would become a paint o maintain.

 I simplified your code down for testing purposes by hardcoding printer names.

Sub PrintMessageToSpecificPrinter(Item As outlook.mailItem)
    Dim wshNet As Object
    Set wshNet = CreateObject("Wscript.Network")
    'Change the printer name on the next line to that of the printer you want attachments printed to
    wshNet.SetDefaultPrinter "\\printserver1\printer1"
 
 Item.PrintOut
 
    wshNet.SetDefaultPrinter "\\printserver2\printer2"
 
    Set wshNet = Nothing
    
    Set objFSO = Nothing
    
End Sub

Open in new window

0
 
LVL 76

Expert Comment

by:David Lee
ID: 24781102
Hi, statzd.

Thanks for testing and providing additional feedback.  Apparently the difference is running the code from a rule.  I wasn't running the code from a rule, I was running it manually.  Apparently that makes a huge difference.  I cannot get the code to work reliably from a rule.  Sometimes it works and other times it doesn't.  I can't figure out why.  So, I've abandoned this approach altogether.  Let's try a different solution.

This approach saves the message to your Temp folder then uses Word to print to a specific printer.  Unfortunately this solution doesn't work from a rule either.  We have to use another means of triggering the code.  The solution to that is in the next post.
Sub PrintMe(Item As Outlook.MailItem)
    Dim strFilename As String, wrdApp as Object, wrdDoc As Object
    strFilename = Environ("TEMP") & "\OutlookMessage.rtf"
    Item.SaveAs strFilename, olRTF
    Set wrdApp = CreateObject("Word.Application")
    Set wrdDoc = wrdApp.Documents.Open(strFilename)
    'Change the printer name on the following line'
    wrdApp.ActivePrinter = "HP Deskjet 3320"
    wrdDoc.PrintOut
    wrdDoc.Close False
    Set wrdDoc = Nothing
    wrdApp.Quit False
    Set wrdApp = Nothing
End Sub

Open in new window

0
 
LVL 76

Accepted Solution

by:
David Lee earned 250 total points
ID: 24781116
Follow these instructions to use this code.

1.  Start Outlook
2.  Click Tools > Macro > Visual Basic Editor
3.  If not already expanded, expand Microsoft Office Outlook Objects and click on ThisOutlookSession
4.  Copy the code from the Code Snippet box and paste it into the right-hand pane of
5.  Outlook's VB Editor window
6.  Edit the code as needed.  I included comment lines wherever something needs to or can change
7.  Click the diskette icon on the toolbar to save the changes
8.  Close the VB Editor
9.  Click Tools > Macro > Security
10. Set the Security Level to Medium
11. Close Outlook
12. Start Outlook
13. Outlook will display a dialog-box warning that ThisOutlookSession contains macros and asking if you want to allow them to run.  Say yes.

This code monitors the inbox for new items.  When an item arrives the code checks to see if it is a message.  If it is, then it checks to see if it meets whatever condition(s) you've set.  In other words, it emulates a rule without using rules.  If the item meets your condition(s), then it is printed.

Dim WithEvents olkFolder As Outlook.Items
 
Private Sub Application_Quit()
    Set olkFolder = Nothing
End Sub
 
Private Sub Application_Startup()
    Set olkFolder = Session.GetDefaultFolder(olFolderInbox).Items
End Sub
 
Private Sub olkFolder_ItemAdd(ByVal Item As Object)
    If Item.Class = olMail Then
        'Edit the condition on the followign line.  You can have other conditions, these are just an example.'
        If Item.Subject = "Some Subject" Or Item.SenderName = "John Doe" Then
            PrintMe Item
        End If
    End If
End Sub

Open in new window

0
 

Author Comment

by:boettcher1
ID: 24806794
I tried the new code.  My email will come into my inbox but does not print.  I used:

 Dim WithEvents olkFolder As Outlook.Items
 
Private Sub Application_Quit()
    Set olkFolder = Nothing
End Sub
 
Private Sub Application_Startup()
    Set olkFolder = Session.GetDefaultFolder(olFolderInbox).Items
End Sub
 
Private Sub olkFolder_ItemAdd(ByVal Item As Object)
    If Item.Class = olMail Then
        'Edit the condition on the followign line.  You can have other conditions, these are just an example.'
        If Item.Subject = "hey" Or Item.SenderName = "John Doe" Then
            PrintMe Item
        End If
    End If
End Sub
 
0
 

Assisted Solution

by:statzd
statzd earned 250 total points
ID: 24807734
boettcher1,

the PrintMe subroutine needed to be included with the second code snippet, which was why the script didn't print, but I plugged that in and then had weird issues with writing to the %TEMP% folder, so I changed the saveas directory to C:\ and then it worked fine for me. That was probably a problem local to my system or account, so you may or may not need to do that.  I also added a few lines to set the default printer back. Here's BlueDevilFan's code including the PrintMe routine:

Dim WithEvents olkFolder As outlook.Items
 
Private Sub Application_Quit()
    Set olkFolder = Nothing
End Sub
 
Private Sub Application_Startup()
    Set olkFolder = Session.GetDefaultFolder(olFolderInbox).Items
End Sub
 
Private Sub olkFolder_ItemAdd(ByVal Item As Object)
    If Item.Class = olMail Then
        'Edit the condition on the followign line.  You can have other conditions, these are just an example.'
        If Item.Subject = "Message1" Then
            PrintMe Item
        End If
    End If
End Sub
 
Sub PrintMe(Item As outlook.mailItem)
    Dim strFilename As String, strDefaultPrinter As String, wrdApp As Object, wrdDoc As Object
    strFilename = "c:\OutlookMessage.rtf"
    Item.SaveAs strFilename, olRTF
    Set wrdApp = CreateObject("Word.Application")
    Set wrdDoc = wrdApp.Documents.Open(strFilename)
    'Change the printer name on the following line'
    strDefaultPrinter = wrdApp.ActivePrinter
    wrdApp.ActivePrinter = "\\printserver1\printer2"
    wrdDoc.PrintOut
    wrdDoc.Close False
    Set wrdDoc = Nothing
    wrdApp.ActivePrinter = strDefaultPrinter
    
    wrdApp.Quit False
    Set wrdApp = Nothing
End Sub

Open in new window

0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

How to resolve IMCEAEX NDRs in Exchange or Exchange Online related to invalid X500 addresses.
When you have clients or friends from around the world, it becomes a challenge to arrange a meeting or effectively manage your time. This is where Outlook's capability to show 2 time zones in one calendar comes in handy.
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
CodeTwo Sync for iCloud (http://www.codetwo.com/sync-for-icloud?sts=6554) automatically synchronizes your Outlook 2016, 2013, 2010 or 2007 folders with iCloud folders available via iCloud Control Panel. This lets you automatically sync them with…

860 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question