Ayoub.A
Ayoub.A

Reputation: 2093

Java: Print table of data

I want to be able to print a list of data using PrinterJob, but it seems PrinterJob prints only Nodes, so when I use a TableView and print it, first it does not print all elements, second I do not like the design. My application already has a functionality of creating pdf tables (a sample is show at the end of this question) and my question is how can I print this pdf, and this proccess of printing is it the same for a POS printer as for a normal printer?

enter image description here

EDIT

Based on the answer of James_D 2, I used this code to print:

Document document = createLogDocument(items);
if (document != null) {
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    PdfWriter.getInstance(document, byteArrayOutputStream);

    byte[] pdfData = byteArrayOutputStream.toByteArray();

    DocFlavor pdfInFormat = DocFlavor.BYTE_ARRAY.PDF;

    Doc myDoc = new SimpleDoc(pdfData, pdfInFormat, null);

    PrintRequestAttributeSet set = new HashPrintRequestAttributeSet();

    PrintService[] services = PrintServiceLookup.lookupPrintServices(pdfInFormat, set);
    if (services.length > 0) {
        PrintService service = ServiceUI.printDialog(null, 50, 50, services, services[0], null, set);


        DocPrintJob job = service.createPrintJob();
        job.print(myDoc, set);

    }
}
} catch (DocumentException e) {
     e.printStackTrace();
} catch (PrintException e) {
    e.printStackTrace();
}

as for the createLogDocument it's as follows:

private static Document createLogDocument(List<Log> logs) throws DocumentException {
Document document = new Document();
document.open();

PdfPTable table = new PdfPTable((new float[]{10, 20, 50, 10, 10}));
table.setWidthPercentage(100);
table.setSpacingAfter(20);
table.setSpacingAfter(20);

PdfPTable header = new PdfPTable((new float[]{10, 20, 50, 10, 10}));
header.setWidthPercentage(100);
header.setSpacingAfter(20);
header.setSpacingBefore(20);

PdfPCell cell = null;

setHeaderCell(cell, "Date", header);
setHeaderCell(cell, "Type", header);
setHeaderCell(cell, "Details", header);
setHeaderCell(cell, "Client", header);
setHeaderCell(cell, "Employee", header);

for (Log log : logs) {

    setNormalCell(cell, log.getDate().toString(), table);

    setNormalCell(cell, log.getDescription().split(":")[0], table);

    setNormalCell(cell, log.getDescription().split(":")[1], table);

    setNormalCell(cell, log.getClient().getName(), table);

    setNormalCell(cell, log.getEmployee().getName(), table);
}

boolean b = true;
for (PdfPRow r : table.getRows()) {
    for (PdfPCell c : r.getCells()) {
        c.setBackgroundColor(b ? BaseColor.LIGHT_GRAY : BaseColor.WHITE);
    }
    b = !b;
}

document.add(header);
document.add(table);
document.close();

return document;

}

But when I exectue this code I get a java.io.IOException saying that No file in print request. What mistake am I making?

Upvotes: 1

Views: 1050

Answers (2)

Ayoub.A
Ayoub.A

Reputation: 2093

Well I changed my createLog method to return a byte array, and it seams to work fine.

try {
        byte[] pdfData = createLogDocument(items);

        if (pdfData.length != 0) {

            DocFlavor pdfInFormat = DocFlavor.BYTE_ARRAY.PDF;

            Doc myDoc = new SimpleDoc(pdfData, pdfInFormat, null);

            PrintRequestAttributeSet set = new HashPrintRequestAttributeSet();

            PrintService[] services = PrintServiceLookup.lookupPrintServices(pdfInFormat, set);

            if (services.length > 0) {
                PrintService service = ServiceUI.printDialog(null, 50, 50, services, services[0], null, set);

                if (service != null) {
                    DocPrintJob job = service.createPrintJob();
                    job.print(myDoc, set);
                }

            }
        }

    } catch (DocumentException e) {
        e.printStackTrace();
    } catch (PrintException e) {
        e.printStackTrace();
    }

As for the createLogDocument method:

private static byte[] createLogDocument(List<Log> logs) throws DocumentException {
    Document document = new Document();

    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    PdfWriter.getInstance(document, byteArrayOutputStream);

    document.open();

    //Fill the document with info

    document.close();
    byte[] pdfData = byteArrayOutputStream.toByteArray();

    return pdfData;
}

Upvotes: 0

James_D
James_D

Reputation: 209225

The JavaFX print API will not be able to print your TableView will all the data in it. Recall that table views do not create cells for all of the items in the table: cells are only created for visible items (those not scrolled out of the view) and are reused as needed (e.g. when the user scrolls). Since the JavaFX print API prints nodes, and no nodes exist representing all of the data, then this simply won't work.

Since you already have a PDF representation of the data in your table, you can use the standard javax.print API to print the PDF. The package documentation has details on how to do this, but in brief you would do:

FileInputStream pdfStream;
try {
   pdfStream = new FileInputStream("file.pdf");
} catch (FileNotFoundException ffne) {
   ffne.printStackTrace();
}
if (pdfStream == null) {
    return;
}

DocFlavor pdfInFormat = DocFlavor.INPUT_STREAM.PDF;
Doc myDoc = new SimpleDoc(pdfStream, pdfInFormat, null);  
PrintRequestAttributeSet aset = 
        new HashPrintRequestAttributeSet();
PrintService service = 
  PrintServiceLookup.lookupDefaultPrintService(psInFormat, aset);
if (service != null) {
   DocPrintJob job = service.createPrintJob();
   try {
        job.print(myDoc, aset);
   } catch (PrintException pe) {
        pe.printStackTrace();
   }
}

If your PDF is in memory, rather than in a file, and you can get the data in the form of a byte[], you can do

byte[] pdfData = ... ;
DocFlavor pdfInFormat = DocFlavor.BYTE_ARRAY.PDF;
Doc myDoc = new SimpleDoc(pdfData, pdfInFormat, null);  

instead of working with the file as above.

Upvotes: 1

Related Questions