biblioteca Apache PDFBox Java - ¿Existe una API para la creación de tablas?
Pregunta
Estoy utilizando la biblioteca de Java Apache PDFBox para crear archivos PDF. ¿Hay una manera de crear una tabla de datos usando PDFBox? Si no hay tal API para hacerlo, lo que requeriría para dibujar manualmente la tabla usando drawLine etc., ¿Alguna sugerencia sobre cómo hacer esto?
Solución
Fuente creación de tablas con PDFBox
La siguiente método dibuja una tabla con el contenido de la tabla especificado. Es un poco de un truco y va a trabajar para pequeñas cadenas de texto. No realiza el ajuste de texto, pero se puede tener una idea de cómo se hace. Darle una oportunidad!
/**
* @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;
}
}
Uso:
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" );
Otros consejos
He creado una pequeña API para crear tablas usando PDFBox. Se puede encontrar en github ( https://github.com/dhorions/boxable ).
Una muestra de un PDF generado se puede encontrar aquí http://goo.gl/a7QvRM .
¿Alguna pista o sugerencias son bienvenidos.
La respuesta aceptada es agradable, pero que trabajará con Apache 1.x PDFBox solamente, para Apache 2.x PDFBox que tendrá que modificar un poco el código para que funcione correctamente.
Así que aquí es el mismo código, pero que es compatible con Apache 2.x PDFBox
El drawTable
método:
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;
}
}
El uso actualiza para utilizar la tratar -con-recursos instrucción para cerrar adecuadamente los recursos:
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");
}
Desde que tuve el mismo problema hace un tiempo empecé a construir una pequeña biblioteca para ello las cuales yo también estoy tratando de mantenerse al día.
Utiliza Apache 2.x PDFBox y se puede encontrar aquí: https://github.com/vandeseer/easytable
Permite que desde hace algunos personalizaciones como establecer el tipo de letra, color de fondo, relleno, etc. en el nivel celular, la alineación vertical y horizontal, que se extiende celular, ajuste de texto y las imágenes en las células.
Dibujo tablas en varias páginas también es posible.
Se puede crear tablas como esta por ejemplo:
El código para este ejemplo se puede encontrar aquí - otros ejemplos en la misma carpeta también.