Search code examples
pythonprintingdocx

Print a word document from Python 3 after setting some printer properties


I have a word document that I would like to print from inside Python. I also need to set some printer properties, like the tray, duplex printing etc. So far I have only partly succeeded to print, by using win32api.ShellExecute but this will open Word to print and it will get the printer properties set in Word, which is not desirable. If I use win32print module I am able to set the properties as I want but I haven't been able to send the document to the printer.

In sort, the part of the code that seems to work for setting my printer properties is as follows:

import win32con
import win32gui
import win32print

# pDevMode Constants
# DefaultSource
TRAY_1 = 260
TRAY_2 = 259
# Duplex
SINGLE_SIDE = 1
DUPLEX_OVER = 2
DUPLEX_UP = 3
# Color
COLOR = 2
MONOCHROME = 1

device_name = win32print.GetDefaultPrinter()
handle = win32print.OpenPrinter(device_name)

properties = win32print.GetPrinter(handle, 2)
devmode = properties['pDevMode']

devmode.DefaultSource = TRAY_1
devmode.Fields |= win32con.DM_DEFAULT_SOURCE

win32print.DocumentProperties(None, handle, device_name, devmode, devmode, win32con.DM_IN_BUFFER | win32con.DM_OUT_BUFFER)

hdc = win32gui.CreateDC("", device_name, devmode)
win32print.StartDoc(hdc, ("Print Document", None, None, 0))
win32print.StartPage(hdc)

...

win32print.EndPage(hdc)
win32print.EndDoc(hdc)


The above will print an empty page (as expected) from the correct tray.

I am not sure how to send the document though. I have been reading my file and trying to send to the printer with:

            with open(document_path, "rb") as file:
                data = file.read()
                win32print.WritePrinter(printer_handle, data)

but doesn't work.

I am also a bit confused with StartDoc/StartDocPrinter, StartPage/StartPagePrinter functions in win32print... Whatever I tried so far didn't seem to work.

Any help would be much appriciated


Solution

  • So I got it working in the end...

    Apparently there is no need for win32gui.CreateDC

    What I was missing to actually register the pDevMode changes to the printer was:

    win32print.SetPrinter(printer_handle, 2, properties, 0)
    

    right after the DocumentProperties line. For this to work though I had to add the PRINTER_DEFAULTS argument to the printer handle command as follows:

    PRINTER_DEFAULTS = {
        "DesiredAccess": win32print.PRINTER_ALL_ACCESS
    }
    
    printer_handle = win32print.OpenPrinter(printer_name, PRINTER_DEFAULTS)
    

    Then with a ShellExecute command I was able to print with the set settings