Reputation: 2513
I need to print some information directly (without user confirmation) and I'm using Python and the win32print
module.
I've already read the whole Tim Golden win32print page (even read the win32print doc, which is small) and I'm using the same example he wrote there himself, but I just print nothing.
If I go to the interactive shell and make one step at a time, I get the document on the printer queue (after the StartDocPrinter
), then I get the document size (after the StartPagePrinter, WritePrinter, EndPagePrinter
block) and then the document disappear from the queue (after the EndDocPrinter
) without printing.
I'm aware of the ShellExecute
method Tim Golden showed. It works here, but it needs to create a temp file and it prints this filename, two things I don't want.
Any ideas? Thanks in advance.
This is the code I'm testing (copy and paste of Tim Golden's):
import os, sys
import win32print
import time
printer_name = win32print.GetDefaultPrinter()
if sys.version_info >= (3,):
raw_data = bytes ("This is a test", "utf-8")
else:
raw_data = "This is a test"
hPrinter = win32print.OpenPrinter (printer_name)
try:
hJob = win32print.StartDocPrinter (hPrinter, 1, ("test of raw data", None, "RAW"))
try:
win32print.StartPagePrinter (hPrinter)
win32print.WritePrinter (hPrinter, raw_data)
win32print.EndPagePrinter (hPrinter)
finally:
win32print.EndDocPrinter (hPrinter)
finally:
win32print.ClosePrinter (hPrinter)
[EDIT]
I installed a pdf printer in my computer to test with another printer (CutePDF Writer) and I could generate the test of raw data.pdf
file, but when I look inside there is nothing. Meaning: all commands except WritePrinter
appears to be doing what they were supposed to do. But again, as I said in the comments, WritePrinter
return the correct amount of bytes that were supposed to be written to the printer. I have no other idea how to solve this, but just comproved there is nothing wrong with my printer.
Upvotes: 4
Views: 22280
Reputation: 181
The problem is the driver Version. If the Version is 4 you need to give XPS_PASS instead of RAW, here is a sample.
drivers = win32print.EnumPrinterDrivers(None, None, 2)
hPrinter = win32print.OpenPrinter(printer_name)
printer_info = win32print.GetPrinter(hPrinter, 2)
for driver in drivers:
if driver["Name"] == printer_info["pDriverName"]:
printer_driver = driver
raw_type = "XPS_PASS" if printer_driver["Version"] == 4 else "RAW"
try:
hJob = win32print.StartDocPrinter(hPrinter, 1, ("test of raw data", None, raw_type))
try:
win32print.StartPagePrinter(hPrinter)
win32print.WritePrinter(hPrinter, raw_data)
win32print.EndPagePrinter(hPrinter)
finally:
win32print.EndDocPrinter(hPrinter)
finally:
win32print.ClosePrinter(hPrinter)
Upvotes: 1
Reputation: 21
# U must install pywin32 and import modules:
import win32print, win32ui, win32con
# X from the left margin, Y from top margin
# both in pixels
X=50; Y=50
# Separate lines from Your string
# for example:input_string and create
# new string for example: multi_line_string
multi_line_string = input_string.splitlines()
hDC = win32ui.CreateDC ()
# Set default printer from Windows:
hDC.CreatePrinterDC (win32print.GetDefaultPrinter ())
hDC.StartDoc (the_name_will_appear_on_printer_spool)
hDC.StartPage ()
for line in multi_line_string:
hDC.TextOut(X,Y,line)
Y += 100
hDC.EndPage ()
hDC.EndDoc ()
#I like Python
Upvotes: 2
Reputation: 2513
I'm still looking for the best way to do this, but I found an answer that satisfy myself for the problem that I have. In Tim Golden's site (linked in question) you can find this example:
import win32ui
import win32print
import win32con
INCH = 1440
hDC = win32ui.CreateDC ()
hDC.CreatePrinterDC (win32print.GetDefaultPrinter ())
hDC.StartDoc ("Test doc")
hDC.StartPage ()
hDC.SetMapMode (win32con.MM_TWIPS)
hDC.DrawText ("TEST", (0, INCH * -1, INCH * 8, INCH * -2), win32con.DT_CENTER)
hDC.EndPage ()
hDC.EndDoc ()
I adapted it a little bit after reading a lot of the documentation. I'll be using win32ui
library and TextOut
(device context method object).
import win32ui
# X from the left margin, Y from top margin
# both in pixels
X=50; Y=50
multi_line_string = input_string.split()
hDC = win32ui.CreateDC ()
hDC.CreatePrinterDC (your_printer_name)
hDC.StartDoc (the_name_will_appear_on_printer_spool)
hDC.StartPage ()
for line in multi_line_string:
hDC.TextOut(X,Y,line)
Y += 100
hDC.EndPage ()
hDC.EndDoc ()
I searched in meta stackoverflow before answering my own question and here I found it is an encouraged behavior, therefore I'm doing it. I'll wait a little more to see if I get any other answer.
Upvotes: 4