itextpdf : PdfPTable dont takes height - java

I migrated my publisher core from itext-2.... to itextpdf-5.5.6
In itext-2 I had an image into cell of a PdfPTable an my table's celle had same size that image.
Now, in itextpdf-5.5.6 image have small size like that cell.
For example I use
table.setTotalWidth(450);
and in core itextpdf it calculate height too :
//ITEXTPDF
calculateWidths();
calculateHeights();
calculateHeight call to getRowHeight
getRowHeight(k, true);
and it does not do the same that in itext-2 :
itext returns 400
itextpdf returns 23
I debbuged for itextpdf and found that in pdfLine.getMaxSize(..) there is the following code :
if (chunk.isImage()) {
Image img = chunk.getImage();
if (chunk.changeLeading()) {
float height = chunk.getImageHeight() + chunk.getImageOffsetY() + img.getSpacingBefore();
image_leading = Math.max(height, image_leading);
}
}
and in the case of itext i have no condition like that :
if (chunk.changeLeading()){......}
Is there an average for solve it ?

I found where was problem :
Paragraph para = new Paragraph(new Chunk((Image) element, 0, 0, Boolean.FALSE));
the last parameter of chunk is changeLeading and it just had to change as Boolean.TRUE
Thanks everybody for your responses

Related

How to set text field value position

I need to render the text field value correctly. I render the text field looks like the following:
final Rectangle rect = new Rectangle(100, page.getCropBox().getHeight() - (100 * pdf.getPageNumber(page)), 300, rectHeight);
field = PdfFormField.createText(pdf, rect, name);
field.setFontSize(14);
field.setValue(value);
field.setVisibility(VISIBLE);
form.addField(field, page);
and when I'm saving a pdf I have the result but when I'm trying to edit the following pdf using Acrobat Reader my text . How can I fix this issue?

values are getting overwritten in the table -PDFbox

I want to display the set of records in rows and columns. Am getting output but the thing is, it is getting overlapped. should i modify the loop can someone pls suggest.
ArrayList<ResultRecord> Records = new ArrayList<ResultRecord>(MainRestClient.fetchResultRecords(this.savedMainLog));
for(j=0; j<Records.size(); j++)
{
Row<PDPage> row4 = table.createRow(100.0f);
Cell<PDPage> cell10 = row4.createCell(15.0f, temp.getNumber());
Cell<PDPage> cell11 = row4.createCell(45.0f, temp.getDescription());
Cell<PDPage> cell12 = row4.createCell(15.0f, temp.getStatus());
Cell<PDPage> cell13 = row4.createCell(25.0f, temp.getRemarks());
}
The below is the full code for opening a PDF file. I want to retreive set of records in the row4 in the corresponding cells. But the is over written one above the another.
Expected output:
IT should display one below the another.
Is the overlapping reason,is it because of defining the row as row4.
try {
//table.draw();
cell.setFontSize(12);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
First of all, you should clarify the table drawing library you use. PDFBox only is the underlying PDF library. Considering the classes used I would assume you are using Boxable on top of it.
Furthermore, the reason why all the tables are printed over each other is that you start each table at the same position on the same page, you use
BaseTable table = new BaseTable(yPosition, yStartNewPage,
bottomMargin, tableWidth, margin, document, page, true, drawContent);
without ever changing yPosition or page.
To get one table after the other, you have to update yPosition and page accordingly, e.g. by using the return value of table.draw() and the state of table then, i.e. by replacing
table.draw();
by
yPosition = table.draw();
page = table.getCurrentPage();

Change the width of the cell content in java using PDFCell

Hi I have an app which generates PDF page using java iText, for a single column the width is changing so some times if there are more than 16 character the rest of the character go below in the PDF page
For Example I have a customer Acct which varies from 10 - 16 characters it appears like on my PDF page like
GW1BKCADT402814
1
instead i need it on the same line GW1BKCADT4028141.
The last character goes below in that column.
PdfPTable tTable = new PdfPTable( 13 );
PdfPCell c1 = PDFConstants.getDefaultPdfPCell( PdfPCell.ALIGN_LEFT, 2 );
c1.setPhrase( new Phrase( new Chunk( t.getCustomerAcc(), StyleConstantsPDF.FONT_NORAMAL_8 ) ));
tTable.addCell( c1 );

Tables in PDF with horizontal page breaks

Does someone know a (preferably open-source) PDF layout engine for Java, capable of rendering tables with horizontal page breaks? "Horizontal page breaking" is at least how the feature is named in BIRT, but to clarify: If a table has too many columns to fit across the available page width, I want the table to be split horizontally across multiple pages, e.g. for a 10-column table, the columns 1-4 to be output on the first page and columns 5-10 on the second page. This should of course also be repeated on the following pages, if the table has too many rows to fit vertically on one page.
So far, it has been quite difficult to search for products. I reckon that such a feature may be named differently in other products, making it difficult to use aunt Google to find a suitable solution.
So far, I've tried:
BIRT claims to support this, but the actual implementation is so buggy, that it cannot be used. I though it is self-evident for such a functionality, that the row height is kept consistent across all pages, making it possible to align the rows when placing the pages next to each other. BIRT however calculates the required row height separately for each page.
Jasper has no support.
I also considered Apache FOP, but I don't find any suitable syntax for this in the XSL-FO specification.
iText is generally a little bit too "low level" for this task anyway (making it difficult to layout other parts of the intended PDF documents), but does not seem to offer support.
Since there seem to be some dozens other reporting or layout engines, which may or may not fit and I find it a little bit difficult to guess exactly what to look for, I was hoping that someone perhaps already had similar requirements and can provide at least a suggestion in the right direction. It is relatively important that the product can be easily integrated in a Java server application, a native Java library would be ideal.
Now, to keep the rows aligned across all pages, the row heights must be calculated as follows:
Row1.height = max(A1.height, B1.height, C1.height, D1.height)
Row2.height = max(A2.height, B2.height, C2.height, D2.height)
While BIRT currently seem to do something like:
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)
It's possible to display a table the way you want with iText. You need to use custom table positioning and custom row and column writing.
I was able to adapt this iText example to write on multiple pages horizontally and vertically. The idea is to remember the start and end row that get in vertically on a page. I've put the whole code so you can easily run it.
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);
}
}
I understand that maybe iText is too low level just for reports, but it can be employed beside standard reporting tools for special needs like this.
Update: Now rows taller than page height are first splited. The code doesn't do splitting if the row is 2, 3,..., n times taller but can be adapted for this too.
Same idea here than Dev Blanked but using wkhtmltopdf (https://code.google.com/p/wkhtmltopdf/) and some javascript, you can achieve what you need. When running wkhtmltopdf against this fiddle you get the result shown below (screenshot of pdf pages). You can place the "break-after" class anywhere on the header row. We use wkhtmltopdf server-side in a Java EE web app to produce dynamic reports and the performance is actually very good.
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>
Script
$(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);
});
});
Have you tried http://code.google.com/p/flying-saucer/. It is supposed to convert HTML to PDF.
My advice is to use FOP transformer.
Here you can see some examples and how to use it.
Here you can find some examples with fop and tables.
Jasper has no support.
According to the Jasper documentation it does have support, via:
column break element (i.e. a break element with a type=column attribute). This can be placed at any location in a report.
isStartNewColumn attribute on groups/headers
See 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
If you're really stuck, as a last resort you could use Excel / OpenOffice Calc: manually copy data into cells, manually format it as you desire, save as xls format. Then use apache POI from java to dynamically populate/replace the desired data & print to file/PDF. At least it gives very fine-grained control of column & row formatting/breaks/margins etc.

iText: Table(com.​lowagie.​text) created only occupies 80% of the entire page , How to make it utilise the entire page

I am writing the following code in order to create a PDF file with a table in it.
Document document = new Document(PageSize.A4, 20, 20, 20, 80);
Font myfont = new Font(FontFactory.getFont(FontFactory.COURIER_BOLD, 13, Font.NORMAL));
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(request.getRealPath("/") + "SAMPLE.pdf"));
document.open();
Table table = new Table(2);
Cell c2 = new Cell();
int[] widths = {8, 150}; //Tried different values, but no change
table.setBorder(Rectangle.BOX);
table.setAlignment(Element.ALIGN_LEFT);
table.setSpacing(0);
table.setPadding(0);
table.setTableFitsPage(true); //Tried with 'false', even removed it, but no change
table.setWidths(widths);
c2 = new Cell(new Paragraph("1. ", myfont));
c2.setBorder(Rectangle.NO_BORDER);
table.addCell(c2);
c2 = new Cell(new Paragraph("TEST DATA ", myfont));
c2.setBorder(Rectangle.NO_BORDER);
table.addCell(c2);
c2 = new Cell(new Paragraph("2. ", myfont));
c2.setBorder(Rectangle.NO_BORDER);
table.addCell(c2);
c2 = new Cell(new Paragraph("TEST DATA", myfont));
c2.setBorder(Rectangle.NO_BORDER);
table.addCell(c2);
c2 = new Cell(new Paragraph("3. ", myfont));
c2.setBorder(Rectangle.NO_BORDER);
table.addCell(c2);
c2 = new Cell(new Paragraph("TEST DATA", myfont));
c2.setBorder(Rectangle.NO_BORDER);
table.addCell(c2);
document.add(table);
document.close();
But the file created contains a table that occupies around 80-85% of the page. I want it to utilise the entire page.
I tried making some adjustments to the code like changing the table.setTableFitsPage(true); to table.setTableFitsPage(false); and even tried removing it.
also altered around with the widths assigned. But in vain as in all cases it only gave me the file with a table occupying only 80-85% of page.
Is there something I am missing to add to my code or is there an attribute that is stopping the Table from taking up 100% of page.
It creates problem when the content is large as I end up getting long tables with spaces on the page still unoccupied.
Attached a screen-shot of the actual PDF file generated here!
Screen-shot of the PDF generated
You should rewrite your table code to use PdfPTable instead. You can find some examples of its use online. The entire 4th chapter of iText in Action 2nd ed is about tables, PdfPTables to be precise.
Lots of example code. Enjoy.
Use the PdfPTable class instead, and you can set the column widths on the entire table. Making it span the entire page can be done by constructing a
float delta = document.getPageSize().getWidth() / numberOfColumns;
// add delta numberOfColumn times
PdfPTable table = new PdfPTable(new float[] {delta, delta, delta, delta });
table.setWidthPercentage(100f);
The widths passed in the constructor determine how much space a given column gets relative to the width of the entire table.

Categories

Resources