tablas - java exportar pdf
Tablas en PDF con saltos de página horizontales. (5)
¿Alguien sabe un motor de diseño de PDF (preferiblemente de código abierto) para Java, capaz de representar tablas con saltos de página horizontales? "Separación de página horizontal" es al menos el nombre de la función en BIRT, pero para aclarar: si una tabla tiene demasiadas columnas para que quepan en el ancho de página disponible, quiero que la tabla se divida horizontalmente en varias páginas, por ejemplo, para una Tabla de 10 columnas, las columnas 1-4 que se mostrarán en la primera página y las columnas 5-10 en la segunda página. Por supuesto, esto también debe repetirse en las páginas siguientes, si la tabla tiene demasiadas filas para encajar verticalmente en una página.
Hasta ahora, ha sido bastante difícil buscar productos. Calculo que tal característica puede tener un nombre diferente en otros productos, lo que dificulta el uso de la tía Google para encontrar una solución adecuada.
Hasta ahora, he intentado:
BIRT afirma que es compatible con esto, pero la implementación real es tan defectuosa que no se puede utilizar. Pienso que es evidente por tal funcionalidad, que la altura de la fila se mantiene constante en todas las páginas, lo que hace posible alinear las filas al colocar las páginas una al lado de la otra. Sin embargo, BIRT calcula la altura de fila requerida por separado para cada página.
Jasper no tiene apoyo.
También consideré Apache FOP, pero no encuentro ninguna sintaxis adecuada para esto en la especificación XSL-FO.
Por lo general, iText es un poco demasiado "bajo" para esta tarea (lo que dificulta el diseño de otras partes de los documentos PDF previstos), pero no parece ofrecer soporte.
Dado que parece haber algunas docenas de otros motores de informes o diseño, que pueden encajar o no y me resulta un poco difícil adivinar qué buscar exactamente, esperaba que alguien ya tuviera requisitos similares y pueda proporcionar al menos Una sugerencia en la dirección correcta. Es relativamente importante que el producto se pueda integrar fácilmente en una aplicación de servidor Java, una biblioteca nativa de Java sería ideal.
Ahora, para mantener las filas alineadas en todas las páginas, las alturas de las filas se deben calcular de la siguiente manera:
Row1.height = max(A1.height, B1.height, C1.height, D1.height)
Row2.height = max(A2.height, B2.height, C2.height, D2.height)
Mientras que BIRT actualmente parece hacer algo como:
Page1.Row1.height = max(A1.height, B1.height)
Page2.Row1.height = max(C1.height, D1.height)
Page1.Row2.height = max(A2.height, B2.height)
Page2.Row2.height = max(C2.height, D2.height)
Jasper no tiene apoyo.
Según la documentación de Jasper, tiene soporte, a través de:
- Elemento de salto de columna (es decir, un elemento de salto con un atributo type = column). Esto se puede colocar en cualquier ubicación en un informe.
- Atributo isStartNewColumn en grupos / encabezados
Consulte http://books.google.com.au/books?id=LWTbssKt6MUC&pg=PA165&lpg=PA165&dq=jasper+reports+%22column+break%22&source=bl&ots=aSKZfqgHR5&sig=KlH4_OiLP-cNsBPGJ7yzWPYgH_k&hl=en&sa=X&ei=h_1kUb6YO6uhiAeNk4GYCw&redir_esc=y#v=onepage&q=column%20break&f=false juego de la http://books.google.com.au/books?id=LWTbssKt6MUC&pg=PA165&lpg=PA165&dq=jasper+reports+%22column+break%22&source=bl&ots=aSKZfqgHR5&sig=KlH4_OiLP-cNsBPGJ7yzWPYgH_k&hl=en&sa=X&ei=h_1kUb6YO6uhiAeNk4GYCw&redir_esc=y#v=onepage&q=column%20break&f=false
Si está realmente atascado, como último recurso, puede usar Excel / OpenOffice Calc: copie los datos manualmente en las celdas, formatee manualmente según lo desee, guarde como formato xls. Luego, use apache POI de java para poblar / reemplazar dinámicamente los datos deseados e imprimir en un archivo / PDF. Al menos proporciona un control muy preciso del formato de columna y fila / saltos / márgenes, etc.
¿Has probado http://code.google.com/p/flying-saucer/ ? Se supone que convierte HTML a PDF.
Es posible mostrar una tabla de la forma que desee con iText
. Necesitas usar posicionamiento de tabla personalizado y escritura personalizada de filas y columnas.
Pude adaptar este ejemplo de iText para escribir en varias páginas horizontal y verticalmente. La idea es recordar el inicio y el final de la fila que entran verticalmente en una página. He puesto todo el código para que puedas ejecutarlo fácilmente.
public class Main {
public static final String RESULT = "results/part1/chapter04/zhang.pdf";
public static final float PAGE_HEIGHT = PageSize.A4.getHeight() - 100f;
public void createPdf(String filename)
throws IOException, DocumentException {
// step 1
Document document = new Document();
// step 2
PdfWriter writer
= PdfWriter.getInstance(document, new FileOutputStream(filename));
// step 3
document.open();
//setup of the table: first row is a really tall one
PdfPTable table = new PdfPTable(new float[] {1, 5, 5, 1});
StringBuilder sb = new StringBuilder();
for(int i = 0; i < 50; i++) {
sb.append("tall text").append(i + 1).append("/n");
}
for(int i = 0; i < 4; i++) {
table.addCell(sb.toString());
}
for (int i = 0; i < 50; i++) {
sb = new StringBuilder("some text");
table.addCell(sb.append(i + 1).append(" col1").toString());
sb = new StringBuilder("some text");
table.addCell(sb.append(i + 1).append(" col2").toString());
sb = new StringBuilder("some text");
table.addCell(sb.append(i + 1).append(" col3").toString());
sb = new StringBuilder("some text");
table.addCell(sb.append(i + 1).append(" col4").toString());
}
// set the total width of the table
table.setTotalWidth(600);
PdfContentByte canvas = writer.getDirectContent();
ArrayList<PdfPRow> rows = table.getRows();
//check every row height and split it if is taller than the page height
//can be enhanced to split if the row is 2,3, ... n times higher than the page
for (int i = 0; i < rows.size(); i++) {
PdfPRow currentRow = rows.get(i);
float rowHeight = currentRow.getMaxHeights();
if(rowHeight > PAGE_HEIGHT) {
PdfPRow newRow = currentRow.splitRow(table,i, PAGE_HEIGHT);
if(newRow != null) {
rows.add(++i, newRow);
}
}
}
List<Integer[]> chunks = new ArrayList<Integer[]>();
int startRow = 0;
int endRow = 0;
float chunkHeight = 0;
//determine how many rows gets in one page vertically
//and remember the first and last row that gets in one page
for (int i = 0; i < rows.size(); i++) {
PdfPRow currentRow = rows.get(i);
chunkHeight += currentRow.getMaxHeights();
endRow = i;
//verify against some desired height
if (chunkHeight > PAGE_HEIGHT) {
//remember start and end row
chunks.add(new Integer[]{startRow, endRow});
startRow = endRow;
chunkHeight = 0;
i--;
}
}
//last pair
chunks.add(new Integer[]{startRow, endRow + 1});
//render each pair of startRow - endRow on 2 pages horizontally, get to the next page for the next pair
for(Integer[] chunk : chunks) {
table.writeSelectedRows(0, 2, chunk[0], chunk[1], 236, 806, canvas);
document.newPage();
table.writeSelectedRows(2, -1, chunk[0], chunk[1], 36, 806, canvas);
document.newPage();
}
document.close();
}
public static void main(String[] args) throws IOException, DocumentException {
new Main().createPdf(RESULT);
}
}
Entiendo que quizás iText
sea un nivel demasiado bajo solo para informes, pero puede emplearse junto con herramientas de informes estándar para necesidades especiales como esta.
Actualización: ahora las filas más altas que la altura de la página se dividen primero. El código no se divide si la fila es 2, 3, ..., n veces más alta, pero también puede adaptarse para esto.
La misma idea aquí que Dev Blanked pero usando wkhtmltopdf ( https://code.google.com/p/wkhtmltopdf/ ) y algunos javascript, puede lograr lo que necesita. Cuando ejecuta wkhtmltopdf contra este fiddle , obtiene el resultado que se muestra a continuación (captura de pantalla de las páginas pdf). Puede colocar la clase "break-after" en cualquier lugar de la fila del encabezado. Utilizamos wkhtmltopdf del lado del servidor en una aplicación web Java EE para producir informes dinámicos y el rendimiento es realmente muy bueno.
HTML
<body>
<table id="table">
<thead>
<tr><th >Header 1</th><th class="break-after">Header 2</th><th>Header 3</th><th>Header 4</th></tr>
</thead>
<tbody>
<tr valign="top">
<td>A1<br/>text<br/>text</td>
<td>B1<br/>text</td>
<td>C1</td>
<td>D1</td>
</tr>
<tr valign="top">
<td>A2</td>
<td>B2<br/>text<br/>text<br/>text</td>
<td>C2</td>
<td>D2<br/>text</td>
</tr>
</tbody>
</table>
</body>
Guión
$(document).ready(function() {
var thisTable = $(''#table''),
otherTable= thisTable.clone(false, true),
breakAfterIndex = $(''tr th'', thisTable).index($(''tr th.break-after'', thisTable)),
wrapper = $(''<div/>'');
wrapper.css({''page-break-before'': ''always''});
wrapper.append(otherTable);
thisTable.after(wrapper);
$(''tr'', thisTable).find(''th:gt('' + breakAfterIndex + '')'').remove();
$(''tr'', thisTable).find(''td:gt('' + breakAfterIndex + '')'').remove();
$(''tr'', otherTable).find(''th:lt('' + (breakAfterIndex + 1) + '')'').remove();
$(''tr'', otherTable).find(''td:lt('' + (breakAfterIndex + 1) + '')'').remove();
$(''tr'', table).each(function(index) {
var $this =$(this),
$otherTr = $($(''tr'', otherTable).get(index)),
maxHeight = Math.max($this.height(), $otherTr.height());
$this.height(maxHeight);
$otherTr.height(maxHeight);
});
});