Apache PDFBox Java library - Is there an API for creating tables?
Solution 1
Source: Creating tables with PDFBox
The following method draws a table with the specified table content. Its a bit of a hack and will work for small strings of text. It does not perform word wrapping, but you can get an idea of how it is done. Give it a go!
/**
* @param page
* @param contentStream
* @param y the y-coordinate of the first row
* @param margin the padding on left and right of table
* @param content a 2d array containing the table data
* @throws IOException
*/
public static void drawTable(PDPage page, PDPageContentStream contentStream,
float y, float margin,
String[][] content) throws IOException {
final int rows = content.length;
final int cols = content[0].length;
final float rowHeight = 20f;
final float tableWidth = page.findMediaBox().getWidth() - margin - margin;
final float tableHeight = rowHeight * rows;
final float colWidth = tableWidth/(float)cols;
final float cellMargin=5f;
//draw the rows
float nexty = y ;
for (int i = 0; i <= rows; i++) {
contentStream.drawLine(margin, nexty, margin+tableWidth, nexty);
nexty-= rowHeight;
}
//draw the columns
float nextx = margin;
for (int i = 0; i <= cols; i++) {
contentStream.drawLine(nextx, y, nextx, y-tableHeight);
nextx += colWidth;
}
//now add the text
contentStream.setFont( PDType1Font.HELVETICA_BOLD , 12 );
float textx = margin+cellMargin;
float texty = y-15;
for(int i = 0; i < content.length; i++){
for(int j = 0 ; j < content[i].length; j++){
String text = content[i][j];
contentStream.beginText();
contentStream.moveTextPositionByAmount(textx,texty);
contentStream.drawString(text);
contentStream.endText();
textx += colWidth;
}
texty-=rowHeight;
textx = margin+cellMargin;
}
}
Usage:
PDDocument doc = new PDDocument();
PDPage page = new PDPage();
doc.addPage( page );
PDPageContentStream contentStream = new PDPageContentStream(doc, page);
String[][] content = {{"a","b", "1"},
{"c","d", "2"},
{"e","f", "3"},
{"g","h", "4"},
{"i","j", "5"}} ;
drawTable(page, contentStream, 700, 100, content);
contentStream.close();
doc.save("test.pdf" );
Solution 2
I created a small api for creating tables using PDFBox. It can be found on github ( https://github.com/dhorions/boxable ) .
A sample of a generated pdf can be found here http://goo.gl/a7QvRM.
Any hints or suggestions are welcome.
Solution 3
Since I had the same problem some time ago I started to build a small library for it which I am also trying to keep up to date.
It uses Apache PDFBox 2.x and can be found here: https://github.com/vandeseer/easytable
It allows for quite some customizations like setting the font, background color, padding etc. on the cell level, vertical and horizontal alignment, cell spanning, word wrapping and images in cells.
Drawing tables across several pages is also possible.
You can create tables like this for instance:
The code for this example can be found here – other examples in the same folder as well.
Solution 4
The accepted answer is nice but it will work with Apache PDFBox 1.x only, for Apache PDFBox 2.x you will need to modify a little bit the code to make it work properly.
So here is the same code but that is compatible with Apache PDFBox 2.x:
The method drawTable
:
public static void drawTable(PDPage page, PDPageContentStream contentStream,
float y, float margin, String[][] content) throws IOException {
final int rows = content.length;
final int cols = content[0].length;
final float rowHeight = 20.0f;
final float tableWidth = page.getMediaBox().getWidth() - 2.0f * margin;
final float tableHeight = rowHeight * (float) rows;
final float colWidth = tableWidth / (float) cols;
//draw the rows
float nexty = y ;
for (int i = 0; i <= rows; i++) {
contentStream.moveTo(margin, nexty);
contentStream.lineTo(margin + tableWidth, nexty);
contentStream.stroke();
nexty-= rowHeight;
}
//draw the columns
float nextx = margin;
for (int i = 0; i <= cols; i++) {
contentStream.moveTo(nextx, y);
contentStream.lineTo(nextx, y - tableHeight);
contentStream.stroke();
nextx += colWidth;
}
//now add the text
contentStream.setFont(PDType1Font.HELVETICA_BOLD, 12.0f);
final float cellMargin = 5.0f;
float textx = margin + cellMargin;
float texty = y - 15.0f;
for (final String[] aContent : content) {
for (String text : aContent) {
contentStream.beginText();
contentStream.newLineAtOffset(textx, texty);
contentStream.showText(text);
contentStream.endText();
textx += colWidth;
}
texty -= rowHeight;
textx = margin + cellMargin;
}
}
The Usage updated to use the try-with-resources statement to close the resources properly:
try (PDDocument doc = new PDDocument()) {
PDPage page = new PDPage();
doc.addPage(page);
try (PDPageContentStream contentStream = new PDPageContentStream(doc, page)) {
String[][] content = {{"a", "b", "1"},
{"c", "d", "2"},
{"e", "f", "3"},
{"g", "h", "4"},
{"i", "j", "5"}};
drawTable(page, contentStream, 700.0f, 100.0f, content);
}
doc.save("test.pdf");
}
Related videos on Youtube
Comments
-
Keshav almost 2 years
I am using the Apache PDFBox java library to create PDFs. Is there a way to create a data-table using pdfbox? If there is no such API to do it, I would require to manually draw the table using drawLine etc., Any suggestions on how to go about this?
-
Rekin over 13 yearsAnd what about table cell content?
-
dogbane over 13 yearsTo set cell text you will have to call
drawString
. It gets complicated if you want to wrap text within cells. -
Mark Pope almost 11 yearsI've added a basic form of word wrapping (including \n in the content string when you want it to wrap) and also custom column widths: gist.github.com/scobal/6125430
-
androidDev about 10 yearswill it work for Android also?? because you have used java.awt.color class which is not supported by Dalvik VM.
-
Vikas Sharma over 8 yearsHi, can i use apache pdf box for html rendering?I didn't find any solution so far.
-
Warren Nocos about 8 yearsAre rowspan and colspan supported?
-
quodlibet about 8 yearscolspan is supported ( example s3.amazonaws.com/misc.quodlibet.be/Boxable/… ).
-
ssindelar almost 8 yearsActually tried Boxable. I must say if you have a small fixed table it works well. But if you need to customize something, like e.g. fixed column widths, you are screwed. Also the code quality is laking. Odd data structures like "List<List>", ignoring generics where ever possible and a couple of other odd things.
-
quodlibet almost 8 yearsHi @Casey, thanks for using Boxable. We're always open to improving the library. You are very welcome to address some of the issues yourself and submit a pull request, or to open issues for specific problems you encounter. I'm sure the contributers will do their best to accomodate your needs.
-
Shashank Saxena over 7 years@androidDev This is late, but for others who want to use Apache PdfBox for Android, there is very good library that I found. github.com/TomRoush/PdfBox-Android
-
Dinesh M about 7 yearsdrawLine method is now depricated. Any other alternative options. Thanks!
-
Nicolas Filotto about 7 years@DineshMailapur for the record, I proposed an updated version for v 2.x stackoverflow.com/a/44721627/1997376
-
GhostCat almost 7 yearsHalf way through!
-
GhostCat almost 7 yearsSure will! I might slow down upon reaching the legendary badge ... but well, still 35 days to go for that.