9 Replies Latest reply on Feb 27, 2015 1:42 AM by Cesai

    Print PDFs with Python?

    Caleb1987
      People often come into my office requesting maps of their property.  I have a script that will open up a command prompt window then allow the non-GIS users in my office to enter a Parcel ID number in the command window. Once user input has been accepted, the script will automatically select that parcel, zoom to it, then export it to PDF.  I would like to add a print function to automatically print the PDF of the map.  I know that I can use the PrintMap function to print straight from ArcMap, however, this does not come out very clear.  I am wondering if anyone knows of a way to use python to print a PDF?
        • Re: Print PDFs with Python?
          lpinner
          You can use the Adobe Reader command line print option. If you leave the printer name blank, reader will print to the default printer.
          AcroRd32 /N /T PdfFile [PrinterName [ PrinterDriver [ PrinterPort ] ] ]


          Python example:
          import subprocess  printer='MyPrinter' pdffile=r'C:\Some Dir\some pdf.pdf' acroread=r'C:\Program Files (x86)\Adobe\Reader 9.0\Reader\AcroRd32.exe'  #'"%s"'is to wrap double quotes around paths # as subprocess will use list2cmdline internally if we pass it a list #which escapes double quotes and Adobe Reader doesn't like that cmd='"%s" /N /T "%s" "%s"'%(acroread,pdffile,printer)  proc = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE) stdout,stderr=proc.communicate() exit_code=proc.wait()
            • Re: Print PDFs with Python?
              carrierkh

              Luke,

               

              Your example certainly helped me in getting started. The hard part for me was hard coding the path for adobe as it is not that flexible and would require each machine to be at the same level of Adobe Reader. This led me to look for a more dynamic way of handling this so I thought I would share my findings if anyone should come across your post. I still had problems with ArcMap locking when the pdf was open and had to manually kill the adobe process in task manager to free up ArcMap so I issued a simple command to kill the process after 5 seconds allowing adobe reader to open the document, and send the pdf to the print spool. In our case we were automating a report using an *.rlf file and exporting it to a pdf, we needed a way to print both a map and the report which is what the below was doing. Thank you for your contribution and sharing your code!

               

              import _winreg as winreg
              import time, arcpy, os, subprocess
              
              # This is where you would specify the path to your pdf
              pdf = 'Place the path to your pdf here.pdf'
              
              # Dynamically get path to AcroRD32.exe
              AcroRD32Path = winreg.QueryValue(winreg.HKEY_CLASSES_ROOT,'Software\\Adobe\\Acrobat\Exe')
              
              acroread = AcroRD32Path
              
              #print('variable acroread is : {0}'.format(acroread))
              
              # The last set of double quotes leaves the printer blank, basically defaulting to the default printer for the system.
              cmd= '{0} /N /T "{1}" ""'.format(acroread,pdf)
              
              # See what the command line will look like before execution
              print(cmd)
              
              # Open command line in a different process other than ArcMap
              proc = subprocess.Popen(cmd)
              
              # 2 lines below would not close adobe reader and locked ArcMap.
              #stdout,stderr=proc.communicate()
              #exit_code=proc.wait()
              
              # Needed to put a sleep in here so the command line had time to open the pdf and spool the job to the printer.
              time.sleep(5)
              
              # Kill AcroRD32.exe from Task Manager
              os.system("TASKKILL /F /IM AcroRD32.exe")
              
              
                • Re: Print PDFs with Python?
                  Caleb1987

                  That is pretty cool, Ken!  In the past I have just used glob, which should also find AcroRd32.exe no matter what the version:

                   

                  acroread = glob.glob(r"C:\Program Files (x86)\Adobe\Reader*\Reader\AcroRd32.exe")[0]

                   

                  I like yours better though.  I was also having issues with adobe reader remaining open after PDF was printed so thanks for sharing termination part!

              • Re: Print PDFs with Python?
                Caleb1987
                You are the smartest man alive!!! Thank you soo much, worked like a charm!

                Here is the code in case anyone is interested in doing something similar:

                # This script allows a user to input a parcel ID number
                # This will automatically save the map to PDF so it can be printed
                # Written by Caleb Mackey  9/17/2012
                # Print PDF section courtesy of Luke Pinner 9/18/2012
                
                import arcpy, os, sys, traceback
                import subprocess
                arcpy.env.overwriteOutput = True
                
                def userinput():
                    mxd = arcpy.mapping.MapDocument("G:\\Map_Documents\\Walkin_requests\\Customer_map.mxd")
                    df = arcpy.mapping.ListDataFrames(mxd, "Main")[0]
                    parcels = arcpy.mapping.ListLayers(mxd, "Parcels GIS Acres", df)[0]
                    pdfpath = 'C:\\Documents and Settings\\gis\\Desktop\\PRINT_MAPS\\'
                    txtfile = pdfpath + 'Parcelmap_ERROR.txt'
                    acroread = r'C:\Program Files\Adobe\Reader 10.0\Reader\AcroRd32.exe'
                    try:
                        print "Enter Parcel Number WITHOUT dashes and hit ENTER"
                        parcelid = raw_input()
                        parcel_num = str(parcelid)
                
                        print 'selecting parcel...'
                        query = "SOL_PID ='%s'" % parcel_num
                        arcpy.SelectLayerByAttribute_management(parcels, "NEW_SELECTION", query)
                        result = arcpy.GetCount_management(parcels)
                        if str(result) == '0':
                            print 'Invalid SQL statement, check parcel ID'
                            print 'Please verify the Parcel ID and try again'
                            return userinput();
                        
                        elif str(result) > 0:
                            df.zoomToSelectedFeatures()
                            df.extent = parcels.getSelectedExtent(True)
                            df.scale *= 1.65
                            arcpy.RefreshActiveView()
                
                            print 'Exporting to pdf...'
                            pdf = pdfpath + str(parcel_num) + '.pdf'
                            pdfname = str(parcel_num) + '.pdf'
                            if arcpy.Exists(pdf):
                                arcpy.Delete_management(pdf)
                            arcpy.mapping.ExportToPDF(mxd,pdfpath + str(parcel_num) + '.pdf')
                
                            del mxd
                            print 'PDF Exported, to view open ' + str(pdfname) + ' in the "PRINT MAPS" folder.'
                            print 'Sending document to default printer'
                
                            #### Print PDF Code thanks to Luke Pinner #####
                            # '"%s"'is to wrap double quotes around paths
                            # as subprocess will use list2cmdline internally if we pass it a list
                            # which escapes double quotes and Adobe Reader doesn't like that
                            cmd='"%s" /N /T "%s"' %(acroread,pdf)
                
                            proc = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
                            stdout,stderr=proc.communicate()
                            exit_code=proc.wait()
                            print 'Successful'
                                    
                    except:
                           print arcpy.GetMessages(2)
                try:
                    userinput()
                        
                except:
                    # Get the traceback object
                    tb = sys.exc_info()[2]
                    tbinfo = traceback.format_tb(tb)[0]
                
                    # Concatenate information together concerning the error into a message string
                    pymsg = "PYTHON ERRORS:\nTraceback info:\n" + tbinfo + "\nError Info:\n" + str(sys.exc_info()[1])
                    msgs = "ArcPy ERRORS:\n" + arcpy.GetMessages(2) + "\n"
                
                    # Return python error messages for use in script tool or Python Window
                    arcpy.AddError(pymsg)
                    arcpy.AddError(msgs)
                
                    # Print Python error messages for use in Python / Python Window
                    print pymsg + "\n"
                    print msgs
                
                    # Print Log file
                    txtFile = open(txtfile, "w")
                    txtFile.write(pymsg)
                    txtFile.write(msgs)
                    txtFile.write(query)
                
                    txtFile.close()
                
                • Re: Print PDFs with Python?
                  davidbrett
                  Thanks for sharing this!!

                  Is there a way to specify printer options using this method?
                  Specifically, set color or black and white, paper size, scaling, print quality, etc.?
                  • Re: Print PDFs with Python?
                    Caleb1987
                    Thanks for sharing this!!

                    Is there a way to specify printer options using this method?
                    Specifically, set color or black and white, paper size, scaling, print quality, etc.?


                    The method that Luke provided is just passing some command parameters through the python subprocess module.  I am not aware of any ways to pass print settings through the command prompt.  There may be a way. 

                    I would recommend looking at the python CUPS module, aka [url=https://pypi.python.org/pypi/pycups]pycups[/url].  This module seems to give you control to connecting to printers as well as setting up printing properties.
                    • Re: Print PDFs with Python?
                      lpinner
                      I would recommend looking at the python CUPS module, aka [url=https://pypi.python.org/pypi/pycups]pycups[/url].


                      CUPS is Linux/UNIX only.

                      I don't know if there's a(n easy) way to control the print output on Windows.
                      • Re: Print PDFs with Python?
                        davidbrett
                        I ended up using win32api and win32print and setting my default printer preferences.  There is a way to expose all the printer defaults, but I haven't figured out how to set them yet.

                        import osfrom os import path
                        from os import listdir
                        from os.path import isfile, join
                        import win32api
                        import win32print
                        
                        
                        mypath = r"\\<your path goes here>"
                        
                        #list all the files in a folder
                        files = [ f for f in listdir(mypath) if isfile(join(mypath,f)) ]
                        
                        
                        for file in files:
                            file = mypath + "\\" + file
                            if "11x17" in file and "County" in file: 
                                win32api.ShellExecute (
                                  0,
                                  "print",
                                  file,
                                  #
                                  # If this is None, the default printer will
                                  # be used anyway.
                                  #
                                  '/d:"%s"' % win32print.GetDefaultPrinter (),
                                  ".",
                                  0
                                )
                            
                        del files
                        del mypath
                        



                        this will show all the properties for all your connected printers:
                        
                        
                        #Lists properties and capabilities for all the printers installed on a computer.
                        import win32com.client
                        strComputer = "."
                        objWMIService = win32com.client.Dispatch("WbemScripting.SWbemLocator")
                        objSWbemServices = objWMIService.ConnectServer(strComputer,"root\cimv2")
                        colItems = objSWbemServices.ExecQuery("Select * from Win32_PrinterConfiguration")
                        for objItem in colItems:
                            print "Bits Per Pel: ", objItem.BitsPerPel
                            print "Caption: ", objItem.Caption
                            print "Collate: ", objItem.Collate
                            print "Color: ", objItem.Color
                            print "Copies: ", objItem.Copies
                            print "Description: ", objItem.Description
                            print "Device Name: ", objItem.DeviceName
                            print "Display Flags: ", objItem.DisplayFlags
                            print "Display Frequency: ", objItem.DisplayFrequency
                            print "Dither Type: ", objItem.DitherType
                            print "Driver Version: ", objItem.DriverVersion
                            print "Duplex: ", objItem.Duplex
                            print "Form Name: ", objItem.FormName
                            print "Horizontal Resolution: ", objItem.HorizontalResolution
                            print "ICM Intent: ", objItem.ICMIntent
                            print "ICM Method: ", objItem.ICMMethod
                            print "Log Pixels: ", objItem.LogPixels
                            print "Media Type: ", objItem.MediaType
                            print "Name: ", objItem.Name
                            print "Orientation: ", objItem.Orientation
                            print "Paper Length: ", objItem.PaperLength
                            print "Paper Size: ", objItem.PaperSize
                            print "Paper Width: ", objItem.PaperWidth
                            print "Pels Height: ", objItem.PelsHeight
                            print "Pels Width: ", objItem.PelsWidth
                            print "Print Quality: ", objItem.PrintQuality
                            print "Scale: ", objItem.Scale
                            print "Setting ID: ", objItem.SettingID
                            print "Specification Version: ", objItem.SpecificationVersion
                            print "TT Option: ", objItem.TTOption
                            print "Vertical Resolution: ", objItem.VerticalResolution
                            print "X Resolution: ", objItem.XResolution
                            print "Y Resolution: ", objItem.YResolution
                            print "---------------------------------------------------"
                        

                        Source: http://win32com.goermezer.de/content/view/145/189/


                        • Re: Print PDFs with Python?
                          Cesai

                          I got it . Thank you very much for your help. Translation courtesy of Google .

                          From Spain