Skip to content
Hrvoje Štimac edited this page Mar 4, 2017 · 27 revisions

Welcome to the boxable wiki!

This is only initial documentation for boxable project which will grow from basic FAQ to full-fledged documentation.

FAQ

Creating text,image,table with boxable

Okay, first things first. What we always need is

PDPage myPage = new PDPage(PDRectangle.A4);
PDDocument mainDocument = new PDDocument();
PDPageContentStream contentStream = new PDPageContentStream(mainDocument, myPage);

Text

That is something that we always need. Now, how about random text in PDF document, i.e our document title

contentStream.beginText();
contentStream.setFont(PDType1Font.HELVETICA_BOLD, 22);
contentStream.moveTextPositionByAmount(50, 700);
contentStream.drawString("Document title");
contentStream.endText();

Also it is pretty easy to write some text inside PDF Document with PDStreamUtils.write(final PDPageContentStream stream, final String text, final PDFont font, final float fontSize, final float x, final float y, final Color color) method where :

  • text - The text which will be displayed.
  • font - The font of the text
  • fontSize - The font size of the text
  • x - Start X coordinate for text.
  • y - Start Y coordinate for text.
  • color - Color of the text

Maybe it is better to put that in some context, for example, writing document title

[...]
private PDPageContentStream cos;
private PDPage page;
private PDFont font = PDType1Font.HELVETICA;
private float leftMargin = 50;
private marginBetweenYElements = 10;
private float titleFontSize = 18;
[...]
private void drawPageTitle() throws IOException {
        // draw document title first
        PDStreamUtils.write(cos, "Document title", titleFontSize, leftMargin, yPosition,
                Color.BLACK);

        // drop Y position with default margin between vertical elements
        yPosition -= marginBetweenYElements;
    }

Table

What about simple table? Say no more:

//Dummy Table
    float margin = 50;
// starting y position is whole page height subtracted by top and bottom margin
    float yStartNewPage = myPage.getMediaBox().getHeight() - (2 * margin);
// we want table across whole page width (subtracted by left and right margin ofcourse)
    float tableWidth = myPage.getMediaBox().getWidth() - (2 * margin);

    boolean drawContent = true;
    float yStart = yStartNewPage;
    float bottomMargin = 70;
// y position is your coordinate of top left corner of the table
    float yPosition = 550;

    BaseTable table = new BaseTable(550, yStartNewPage, bottomMargin, tableWidth, margin, mainDocument, myPage, true, drawContent);


    Row<PDPage> headerRow = table.createRow(15f);
    Cell<PDPage> cell = headerRow.createCell(100, "Header");
    table.addHeaderRow(headerRow);


    Row<PDPage> row = table.createRow(12);
    cell = row.createCell(30, "Data 1");
    cell = row.createCell(70, "Some value");

    table.draw();


    contentStream.close();
    mainDocument.addPage(myPage);
    mainDocument.save("testfile.pdf");
    mainDocument.close();

Image

It is very similar process just like writing text. All work is done by ''Ìmage.draw(final PDDocument doc, final PDPageContentStream stream, float x, float y)'' method where:

  • doc - PDDocument where drawing will be applied
  • stream - PDPageContentStream where drawing will be applied
  • x - X coordinate for image drawing
  • y - Y coordinate for image drawing

Lets put that in context, for example, drawing logo on our PDF document:

[...]
Image image = new Image(ImageIO.read(new File("/../logo.png")));
// imagine we have pretty big logo and we want scale that a little bit
float imageWidth = 75;
image = image.scaleByWidth(imageWidth);
image.draw(document, contentStream, xPosition, yPosition)

Important Always close your contentStream before saving the document!

[...]
contentStream.close();
// Save the document
File file = new File("test.pdf");
 System.out.println("Sample file saved at : " + file.getAbsolutePath());
 Files.createParentDirs(file);
 doc.save(file);
 doc.close();

If you don’t do this you will be getting something like:

java.lang.IllegalStateException: Cannot read while there is an open stream writer
    at org.apache.pdfbox.cos.COSStream.createRawInputStream(COSStream.java:128)
[...]

Some other interesting methods for drawing and image scaling are:

draw(final PDDocument doc, final PDPageContentStream stream, float x, float y)
scaleByWidth(float width)
scaleByHeight(float height)
scale(float boundWidth, float boundHeight)

And that’s it! You are ready to go! If you want to see some more stylish tables please check next chapter.

Various table layout styles

  • The same table is printed multiple times with different layouts
  • Different pre-defined styles are used
  • 0 or more layouters can be applied to a table.
//Draw table once with default Style
table.getRows().get(0).getCells().get(0).setText("Test 4 -  Default Style");
table.getLayouters().add(new DefaultCellLayouter(Styles.DEFAULT));
table.draw();

image

//Green Style with Zebra Layouter
table.getRows().get(0).getCells().get(0).setText("Test 4 -  Green Style with Zebra Layouter");
table.getLayouters().clear();
table.getLayouters().add(new DefaultCellLayouter(Styles.GREEN));
table.getLayouters().add(new ZebraCellLayouter(Styles.GREEN));
table.draw();

image

//Candy Style with Vertical Zebra Layouter
table.getRows().get(0).getCells().get(0).setText("Test 4 -  Candy Style with Vertical Zebra Layouter");
table.getLayouters().clear();
table.getLayouters().add(new DefaultCellLayouter(Styles.CANDY));
table.getLayouters().add(new VerticalZebraCellLayouter(Styles.CANDY));
table.draw();

image

//Default Style with  Zebra Layouter and Matrix Layouter
table.getRows().get(0).getCells().get(0).setText("Test 4 -  Default Style with Zebra Layouter and Matrix Layouter and centered headers");
table.getLayouters().clear();
table.getLayouters().add(new DefaultCellLayouter(Styles.DEFAULT));
table.getLayouters().add(new ZebraCellLayouter(Styles.DEFAULT));
table.getLayouters().add(new MatrixCellLayouter(Styles.DEFAULT));
table.draw();

image

//Custom style
table.getRows().get(0).getCells().get(0).setText("Test 4 -  Custom Style");
DefaultStyle customStyle = new DefaultStyle()
                    .withBorder(new LineStyle(Color.ORANGE, (float) 0.5))
                    .withFont(PDType1Font.COURIER)
                    .withAlignAccent2(HorizontalAlignment.CENTER);
table.getLayouters().clear();
table.getLayouters().add(new DefaultCellLayouter(customStyle));
table.draw();

image

Here's the output for all of the above : APIv2.0.pdf

Landscape (A4)

PDPage page = new PDPage(new PDRectangle(PDRectangle.A4.getHeight(), PDRectangle.A4.getWidth()));

Portrait (A4)

PDPage page = new PDPage(PDRectange.A4);

How to get table height dynamically?

float newYPosition = table.draw();

How I can get current page if my table is on multiple pages? If table is displayed on multiple pages the current page can be obtained with table.getCurrentPage(). Something like :

[...]
// did we change the page?
if (table.getCurrentPage() != page) {
    cos.close();
    page = table.getCurrentPage();
    cos = new PDPageContentStream(document, page, true, true);
}

Retrieving current table page

If table is displayed on multiple pages the current page can be obtained with table.getCurrentPage(). Something like :

[...]
// did we change the page?
if (table.getCurrentPage() != page) {
    cos.close();
    page = table.getCurrentPage();
    cos = new PDPageContentStream(document, page, true, true);
}
Clone this wiki locally