Print Labels from Client

Hi team,

I need to print labels automatically from a Vision client without requiring a button click. I've implemented the logic in the change event of a client tag. The printers available on the client systems are also configured on the gateway server.

The same logic works as expected with my local Ignition instance, but it's not functioning correctly when I try it through a Vision client button, tag, script console, or gateway event.

In summary, I want to print a report from the client using the client's default printer based on a specific condition. Additionally, I'd like guidance on how to handle printing to a USB printer.

Script used:

from javax.print import PrintServiceLookup as PSL

printerList = PSL.lookupPrintServices(None, None)

defaultPrinter = PSL.lookupDefaultPrintService()

for printer in printerList:
    print printer.getName()

print 'Default printer : ' + defaultPrinter.getName()
defprin =defaultPrinter.getName()
#system.gui.messageBox(defprin)
settings = {'primaryPrinterName':defprin, 'backupPrinterName': 'none', 'copies': 1, 'printBothSides': True,
'collate': True, 'useRaster': False, 'rasterDPI': 1200, 'useAutoLandscape': False, 'pageOrientation': 'portrait'}
system.report.executeAndDistribute(path='Report', project = 'CMS', parameters=None, action='print', actionSettings=settings)

EDIT:
When i try to pass the printer name directly, it is working but in gateway it shows defaultPrinter as none with below error

<type 'exceptions.AttributeError'>, 'NoneType' object has no attribute 'getName'

system.report.executeAndDistribute only ever runs in gateway scope, and can only reach printers directly available to the gateway. (The gateway service user, specifically.)

1 Like

You can use executeReport instead, to get the report bytes as a PDF, then pass that to the local printer directly using a modified form of the code Jordan posted here:

This is not how I print in Vision. My printing normally looks something like this:

objectToBePrinted = # Get this somehow

# Pass the object to be printed into the createPrintJob utility function
job = system.print.createPrintJob(objectToBePrinted)

# Decide whether or not to show the print dialog
# ...to give the user the opertunity to access options like changing printers or printing multiples
job.setShowPrintDialog(False)

# Set the margines to zero in an effort to maximize print size
job.setMargins(0)

# Set the print orientation: 0 = Landscape, 1 = Portrait
job.setOrientation(1)

# Execute the printer call
job.print()
1 Like

Hi,
I have tried the suggested method, why am i getting the below error?


Pl Note: I have set Microsoft print to pdf as default.
I am also getting below error in the printer queue, if i set the default printer

I have tried this, but how to pass objectToBePrinted from report? I am stuck at this point.

Justin's code only works for actual vision components or windows, not for arbitrary binary objects. You must use the print service for arbitrary content, and you need to send the arbitrary content through a printer driver that understands it. PDF may not be supported.

Hi,

Now i have tried with different approach and it is working properly. Only prerequisite of this script is to have Adobe reader. Do u see any issue here?

import os
import sys
import traceback
from java.io import FileOutputStream

# Cache the Acrobat path to avoid searching each time
acrobat_path = None

def find_acrobat_executable():
    global acrobat_path
    if acrobat_path:
        return acrobat_path
    
    acrobat_dirs = [
        r"C:\Program Files\Adobe",
        r"C:\Program Files (x86)\Adobe"
    ]
    possible_executables = ['acrord32.exe', 'acrobat.exe', 'Acrobat.exe','AcroRd32.exe']

    for acrobat_dir in acrobat_dirs:
        if not os.path.exists(acrobat_dir):
            continue

        for root, dirs, files in os.walk(acrobat_dir):
            for file in files:
                if file in possible_executables:
                    acrobat_path = os.path.join(root, file)
                    return acrobat_path
    
    return None

def printLabel():
    pdfBytes = system.report.executeReport(path="XXX", project='XXX', fileType="pdf")
    
    tempFilePath = system.file.getTempFile("pdf")
    with open(tempFilePath, "wb") as tempFile:
        tempFile.write(pdfBytes)
    
    print_success = False
    
    try:
        os_name = system.util.getProperty("os.name")
        
        if os_name.startswith("Windows"):
            acrobat_path = find_acrobat_executable()
            system.tag.writeBlocking('[client]Print', ['Print Started'])
            
            if acrobat_path:
                # Update command to use /t for printing
                command = '"{}" /t "{}"'.format(acrobat_path, tempFilePath)
                print("Command to be executed: {}".format(command))  # Debug print
                
                result = os.system(command)
                print("Result of command execution: {}".format(result))  # Debug print
                
                if result == 0:
                    system.tag.writeBlocking('[client]Print', ['Printed successfully'])
                    print_success = True
#                else:
#                    system.gui.messageBox("Failed to print. Command returned non-zero result.")
            else:
                system.tag.writeBlocking('[client]Print', ['Adobe Reader or Acrobat executable not found.'])
                
    except Exception as e:
        exType, ex, tb = sys.exc_info()
        iMessage = "ERROR in 'Script -' line {}: {}, {}".format(traceback.tb_lineno(tb), exType, ex)
        system.gui.messageBox("Failed to Print, make sure Adobe Reader or Acrobat is running properly.\n" + iMessage)
    
    finally:
        for exe in ['acrord32.exe', 'acrobat.exe', 'Acrobat.exe','AcroRd32.exe']:
            os.system('taskkill /F /IM {}'.format(exe))

EDIT:
My actual requirement is,

After every transaction, labels should be printed attached to each client at a high speed (automatic print). Printers here will be different for each client ( 1 printer for A5 pdf, 1 label printer)
I think there must be some simple solution for this.
I require your feedback on this @justinedwards.jle @PGriffith @pturmel .
Thanks in advance

That's a significant caveat on its own. You're depending both on Acrobat being installed and it continuing to support this immediate print command line flag. I would attempt to accomplish this task entirely using Java's built in APIs.

I haven't ever done the exact task you're trying to accomplish, and I don't have the time to come up with an example script. Someone else may be more generous with their time.

I'll also gently remind you that this forum is not an official support channel, and there are no service level agreements nor any obligation of support. I didn't really have anything to offer when you first posted, so direct messaging me in addition to the tag on the post was not necessary or appreciated. You are welcome to try to contact the support department officially for help with this script, though it's not really their purview, either - you haven't found any bug in Ignition, you're just trying to accomplish a piece of integration work.

Cool. I plan on taking Thursday off, but with all have to get done at home on that day, I probably won't get to this.

If I were on your team, and this code was working, I probably wouldn't touch it, but my inclinations are to refactor the code to get rid of that global variable and the try/except clause.

1 Like

Also I tried your code with container print logic and it is working properly.

1 Like

Hi,

I am facing dimension issue here,
image
Size of this container is 220 * 140.
Printed label:

Script used:

objectToBePrinted =printObject
		
		# Pass the object to be printed into the createPrintJob utility function
		job = system.print.createPrintJob(objectToBePrinted)
		
		# Decide whether or not to show the print dialog
		# ...to give the user the opertunity to access options like changing printers or printing multiples
		job.setShowPrintDialog(False)
		

		
		# Set the print orientation: 0 = Landscape, 1 = Portrait
		job.setOrientation(1)
		job.setPageWidth(2.95)
		job.setPageHeight(1.96)
		job.setPrinterName(printer)
		job.setFitToPage(True)
		job.setMargins(0.2)
	
		if printer is not None:
			# Execute the printer call
			job.print()
		
			
			return 1
		else:
			
			return 2

Label size should be 7.5 cm width * 5cm height. Can someone help with this?

Adjusting setPageWidth doesn't help? It's possible that setFitToPage will need to be false for those settings to have effect.

Also, it is possible to set the margins seperately:

No, it didnt help. I have set setFitToPage to false and got the same output.

Have you tried adjusting job.setRightMargin(x.xx)?
...or if arbitrarily moving that one way or the other doesn't help, are you printing a container? Perhaps keep the container size what it is, and resize the internal component a little bit to get the margin you need.

Yes, i tried adjusting margin but again it is getting cutoff.
Am trying to print a container and i have set layout - relative and maintain aspect ratio

I have achieved the print with correct dimension using ZPL.

But i am looking for other options so that we need not depend on specific printer.