Solved

Outlook 2003 "print it" rule

Posted on 2009-07-01
16
923 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
 

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
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 

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

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

Suggested Solutions

Find out how to use dynamic social media in email signatures with this top 10 DOs & DON’Ts.
Resolve DNS query failed errors for Exchange
This Experts Exchange video Micro Tutorial shows how to tell Microsoft Office that a word is NOT spelled correctly. Microsoft Office has a built-in, main dictionary that is shared by Office apps, including Excel, Outlook, PowerPoint, and Word. When …
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

757 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

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now