-
-
Notifications
You must be signed in to change notification settings - Fork 154
Home
Welcome to the boxable wiki!
- Creating text outside of the table
- Creating simple table
- Creating image
- Choosing various table layout designs
- How to set A4 Landscape?
- How to set A4 Portrait?
- How to get table height dynamically?
- Retrieving current table page
- How to draw two tables with same y position?
Okay, first things first. What we always need is our PDDocument and PDPage :
PDPage myPage = new PDPage(PDRectangle.A4);
PDDocument mainDocument = new PDDocument();
If we want to add something else in our PDF document except tables (i.e some text, image etc.) then we will need content stream:
PDPageContentStream contentStream = new PDPageContentStream(mainDocument, myPage);
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, here is second example how to write document title with method mention above.
[...]
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;
}
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();
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.
- 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();
//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();
//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();
//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();
//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();
Here's the output for all of the above : APIv2.0.pdf
PDPage page = new PDPage(new PDRectangle(PDRectangle.A4.getHeight(), PDRectangle.A4.getWidth()));
PDPage page = new PDPage(PDRectange.A4);
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);
}
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);
}
Let's say that we want two tables by each other (pay attention on spaceBetweenTables
variable and x/y positioning of the tables!)
int startNewPageY = 700;
int bottomMargin = 100;
int leftMargin = 25;
PDPage currentPage = new PDPage();
int spaceBetweenTables = 50;
// we want 2 tables so our table width is 50% of page width without left and right margin AND provided space between tables
float tableWidth = 0.5f * (currentPage.getMediaBox().getWidth() - (2 * leftMargin)- spaceBetweenTables);
PDDocument document = new PDDocument();
document.addPage(currentPage);
BaseTable table1 = new BaseTable(700, startNewPageY, bottomMargin, tableWidth, leftMargin, document,
currentPage, true, true);
[...]
table1.draw();
// pay attention where start x position for this table -> left margin + first table width + space between our tables
BaseTable table2 = new BaseTable(700, startNewPageY, bottomMargin, tableWidth, leftMargin + tableWidth + spaceBetweenTables, document,
currentPage, true, true);
[...]
table2.draw();
(Same principal is if you go with DataTable
implementation)
Then we should get something like this:
The same principle is for multiple tables where we need only adjust tableWidth
variable and BaseTable
's argument that is responsible for x positioning.
Special thanks to :
=======
Copyright 2017
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.