Issue with system.print.createPrintJob

logger = system.util.getLogger("Popup_Printing")
# Tuneable parameters
PRINT_DELAY_MS = 250       # polling interval (ms) for render check
BETWEEN_PAGES_DELAY_MS = 5000  # delay between finishing one page and starting the next
POPUP_PATH = 'Popups/Popup_Printing'
COMPONENT_NAME = 'P2L'
def openPopup():
   try:
       win = system.nav.openWindow(POPUP_PATH)
       pb = win.rootContainer.getComponent('ProgressBar')
       pb.visible = True
   except Exception as e:
       logger.error("Failed to open popup: {}".format(e))
def closePopup():
   try:
       win = system.gui.getWindow(POPUP_PATH)
       pb = win.rootContainer.getComponent('ProgressBar')
       pb.visible = False
       system.nav.closeWindow(POPUP_PATH)
   except Exception as e:
       logger.error("Failed to close popup: {}".format(e))
def doPrint(component, table, page, nextFn):
   """Create and execute the print job, then trigger next page after a pause."""
   try:
       job = system.vision.createPrintJob(component)
       job.setShowPrintDialog(False)
       job.setPageHeight(1800)
       job.setPageWidth(1200)
       job.setMargins(0)
       job.setOrientation(1)
       job.print()
       logger.info("Printed {} page {}".format(table, page))
       # Add a delay before moving to the next page
       system.util.invokeLater(nextFn, BETWEEN_PAGES_DELAY_MS)
   except Exception as e:
       logger.error("Print failed on {} page {}: {}".format(table, page, e))
       closePopup()
def waitUntilReady(component, callback):
   """
   Poll until component is finished rendering.
   Falls back to 1 second if no busy flag is available.
   """
   try:
       if hasattr(component, "isRendering") and component.isRendering:
           system.util.invokeLater(lambda: waitUntilReady(component, callback), PRINT_DELAY_MS)
       else:
           system.util.invokeLater(callback, 3000)  # small buffer
   except Exception as e:
       logger.warn("Render check failed, falling back to delay: {}".format(e))
       system.util.invokeLater(callback, 3000)
def printNext(pages, idx, component):
   if idx >= len(pages):
       system.util.invokeLater(closePopup, 3000)
       return
   table, page = pages[idx]
   logger.info("Preparing {} page {}".format(table, page))
   component.currentPage = page
   component.repaint()
   # Wait until ready, then print
   waitUntilReady(
       component,
       lambda: doPrint(component, table, page,
                       lambda: printNext(pages, idx + 1, component))
   )
def printLabels(event):
   try:
       serial = system.tag.readBlocking(["[P2L]Serial_No"])[0].value
       logger.info("Serial Number: {}".format(serial))
       tables_pages = [
           ('EVAP', 1), ('Hardware', 2), ('Hoses', 3),
           ('Condenser', 4), ('Heater', 5), ('Inverter', 6),
           ('Appearance', 7)
       ]
       component = event.source.parent.getComponent(COMPONENT_NAME)
       pages_to_print = []
       query = "SELECT COUNT(*) AS ERow FROM FCAT_TABLE1 WHERE DESCRIPTION = ? AND ANSWER > 0 AND SERIALNUMBER = ?"
       for tbl, pg in tables_pages:
           rows = system.db.runPrepQuery(query, [tbl, serial])
           if rows and rows[0]['ERow'] > 0:
               pages_to_print.append((tbl, pg))
               logger.info("Queued {} page {}".format(tbl, pg))
       if pages_to_print:
           printNext(pages_to_print, 0, component)
       else:
           system.gui.messageBox("No pages to print.", "Info")
           system.util.invokeLater(closePopup, 3000)
   except Exception as e:
       logger.error("Error preparing labels: {}".format(e))
       closePopup()
# --- Entry Point ---
system.util.invokeLater(openPopup, 2500)    
system.util.invokeLater(lambda: printLabels(event), 2500)




I am working with vision , and have a report viewer with 7 pages, the script will check if each page has atlest 1 row for a particular serial number tag , if its empty it wont print that page, the only problem here is some times i am printing blank pages, and if i try to run same serial number in the designer the report viewer is loaded with proper data, something is not working sometimes. I cant find it, any suggestions would be greatful.
I am executing the script to print pages 1 after other, i have 3 seconds delay between every page for the report viewer to load, but looks like the page is not loaded with 3 seconds delay, increasing the delay also didnt help. the pages load correctly if i check in designer ( without any delay)

This feels like a lot of code to work around something that would be trivial to do within the actual reporting module, using a table and an unstructured row to display your data.

I am also trying to make use of extension function - onReportGenerated.
But ony catch here is i need to print only those pages which has valid rows of data from database

Having invalid data in the database is concerning, but, assuming that's unavoidable:

Why generate a report page at all if you know the data is invalid? If the data is known to be invalid, what is the condition for that? Why not filter out 'invalid' data in your query that populate the report, or post-process it with a script data source, rather than at "view time" in Vision?

2 Likes

What i meant by invalid data is -
I have 7 different queries in report viewer for each page, for a given serial number there can be 1 or few pages applicable with data,( valid data) rest queries or pages will be empty.(inavlid data) , so i have written a query to see if the number of rows for each page is greater than 1( valid data ) , if yes then print only those pages and ignore others.

Invalid(or Not applicable) Data–

Report –

If you turn off Print Empty Group on your header do you still get empty pages?

If you actually do want those in your output, fair enough, but it seems like it would be simpler not to have them :person_shrugging:

If the 'Print Empty Group' setting doesn't do it, then I'm pretty sure a table group would. It just really seems like the right thing to do here is to fix the report, not throw a ton of extra work after the fact to clean it up.

I recommend you restructure your data queries to a nested format. The outer query would return serial numbers and non-optional metadata for them. Each of your queries with optional results would be nested under the main query.

This lets you set up a table group on the main query's key, and then have distinct report subsections/tables with the table group that will show up for the nested rows. This will automatically omit report sections that have now rows in their nested query.

3 Likes
reportViewer = event.source.parent.getComponent('P2L')
reportViewer.print()

For now, i just want to print all pages irrespective of data in them, I have a script written ona mouse click button as mentioned above,
even in this case , the report viewer is empty in vision client, in same instance i have my designer open and i can see data in the designer.

Designer –

Vision Client -

I put the report viewer in a popup window and opened the window when print is needed, this loaded the contents and i am able to print all the contents properly, Before this i was keeping the report viewer always, and printing from scripting,