Print report directly without using standard Print action from a browser

Hi all,

Is there a way to print a report directly from your application without using the browser’s print action.

For example if you print out an invoice, its just directly sent to the printer rather than opening a new tab where one can have options to save or print.

Thanks.

Hello @mabutabee,

Tell me more about what you want to do. Do you want to programmatically configure the printer and print a report by pressing a button?

Regards,
Nikita

Hi,

Yes i want to programmatically configure the printer and print a report by pressing a button.

The challenge with the pop-up is that it gives the user an option to save or download the report and once it is saved it could be printed multiple times from the user’s machine. So in the case of an invoice multiple copies can be reprinted from the saved or downloaded one.

thanks

Hello @mabutabee,

Sorry for the long answer. You can do it like this.

Controller:

@Inject
private DataService dataService;

@Inject
private ReportService reportService;


@Subscribe("printBtn")
public void onPrintBtnClick(Button.ClickEvent event) throws IOException, PrinterException {
    LoadContext<Report> lContext = new LoadContext<>(Report.class);
    lContext.setQueryString("select r from report$Report r where r.code = 'code'");

    Report report = dataService.load(lContext);
    ReportOutputDocument reportOutputDocument = reportService.createReport(report, new HashMap<>());
    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(reportOutputDocument.getContent());

    PrintService service = PrintServiceLookup.lookupDefaultPrintService();
    String printServiceName = service.getName();

    PDDocument document = PDDocument.load(byteArrayInputStream);

    PrintService myPrintService = findPrintService(printServiceName);

    PrinterJob job = PrinterJob.getPrinterJob();
    job.setPageable(new PDFPageable(document));

    job.setPrintService(myPrintService);
    job.print();
}

protected PrintService findPrintService(String printerName) {
    PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null);
    for (PrintService printService : printServices) {
        if (printService.getName().trim().equals(printerName)) {
            return printService;
        }
    }
    return null;
}

Screen:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<window xmlns="http://schemas.haulmont.com/cuba/screen/window.xsd"
        caption="msg://caption"
        messagesPack="com.company.reporttest.web.screens">
    <layout>
        <vbox>
            <button caption="Print report"
                    id="printBtn"/>
        </vbox>
    </layout>
</window>

And you will need to add reporting.openoffice.path to the core module.

Regards,
Nikita

1 Like

Hi @shchienko,

Thanks for the help, it has solved my challenge

HI,

I’m trying to use this code in my browser, but i keep getting this error:

  • package org.apache.pdfbox.pdmodel does not exist
  • package org.apache.pdfbox.printing does not exist
  • cannot find symbol class PDDocument
  • cannot find symbol variable PDDocument
  • cannot find symbol class PDFPageable

cuba version 7.2.12. legacy browser screen.

Can anyone please help?

Regards,

LS

Hi,
You need to add the PDFBox library dependency to your project to get access to these classes.

Thanks Alex the error is gone.

But now i’m getting a null pointer exception. my guess is that the output document(report template) is missing in the code.

at com.company.hrmmulti.web.screens.payrollitem.PayrollItemBrowse.onPrintBtnClick(PayrollItemBrowse.java:38) ~[HRIntelli-web-0.1-SNAPSHOT.jar:na]

Controller:
ReportOutputDocument reportOutputDocument = reportService.createReport(report, new HashMap<>());

What am i missing?

Lloyd

Problem solved. report system code added in the controller.

The report required parameter, which is generated when creating a report is not found.

" IllegalArgumentException: Required report parameter “entity” not found".

please help

Update:

I found a topic where is stated that in the parameter editor of the report Default value must not be empty. So when i select a default value, everything works except the fact that only one record can be printed(the default value). How do i get this to print selected records or records presented after filtering?

Hi,
When you invoke report programmatically, you must pass all required parameters in a Map.

E.g. call this method:

com.haulmont.reports.app.service.ReportService#createReport(com.haulmont.reports.entity.Report, java.util.Map<java.lang.String,java.lang.Object>)

Thanks for the reply Alexander. I still can’t get this to work. So far this is my code but the parameters are still not found.

@Inject
private DataService dataService;
@Inject
private ReportService reportService;
@Inject
private Button reportButton;
@Inject
private Button printButton;
@Inject
private GroupTable payrollItemsTable;

@Subscribe("printBtn")
public void onPrintBtnClick(Button.ClickEvent event) throws IOException, PrinterException {
    LoadContext<Report> lContext = new LoadContext<>(Report.class);
    lContext.setQueryString("select r from report$Report r where r.code = 'werknemers_loonstrook'");

    Report report = dataService.load(lContext);
    Map<String, Object> params = new HashMap<>();
    super.init(params);
    ReportOutputDocument reportOutputDocument = reportService.createReport(report, new HashMap<>(params));
    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(reportOutputDocument.getContent());

    PrintService service = PrintServiceLookup.lookupDefaultPrintService();
    String printServiceName = service.getName();

    PDDocument document = PDDocument.load(byteArrayInputStream);

    PrintService myPrintService = findPrintService(printServiceName);

    PrinterJob job = PrinterJob.getPrinterJob();
    job.setPageable(new PDFPageable(document));

    job.setPrintService(myPrintService);
    job.print();
}

protected PrintService findPrintService(String printerName) {
    PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null);
    for (PrintService printService : printServices) {
        if (printService.getName().trim().equals(printerName)) {
            return printService;
        }
    }
    return null;
}

With this code the problem is partly solved. If i don’t select a record i still get the error message that the parameter is not found, where else i should expect an error like “No record selected”. When i select a record the document is sent to my printer. That woks fine. Although the output is not aligned al the template, but that’s another problem. Maybe a preview before printing could solve that problem. Any ideas how to do that?

So for anyone who needs it this is the code:

@Inject
private DataService dataService;
@Inject
private ReportService reportService;
@Inject
private Button reportButton;
@Inject
private Button printButton;
@Inject
private GroupTable payrollItemsTable;

@Subscribe("printBtn")
public void onPrintBtnClick(Button.ClickEvent event) throws IOException, PrinterException {
    
    Map<String, Object> reportParams = new HashMap<>();
    reportParams.put("entity", payrollItemsTable.getSingleSelected());

    LoadContext<Report> lContext = new LoadContext<>(Report.class);
    lContext.setQueryString("select r from report$Report r where r.code = 'contractors_loonstrook'");

    Report report = dataService.load(lContext);
    ReportOutputDocument reportOutputDocument = reportService.createReport(report, reportParams);
    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(reportOutputDocument.getContent());

    PrintService service = PrintServiceLookup.lookupDefaultPrintService();
    String printServiceName = service.getName();

    PDDocument document = PDDocument.load(byteArrayInputStream);

    PrintService myPrintService = findPrintService(printServiceName);

    PrinterJob job = PrinterJob.getPrinterJob();
    job.setPageable(new PDFPageable(document));

    job.setPrintService(myPrintService);
    job.print();
}

protected PrintService findPrintService(String printerName) {
    PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null);
    for (PrintService printService : printServices) {
        if (printService.getName().trim().equals(printerName)) {
            return printService;
        }
    }
    return null;
}