I'm using iText to create a PDF with a table. The table headers have 90 degree rotated text, which I'm adding using a CellEvent (code below). This works great, except when the table spans multiple pages the rotated cell header text flows off the top of the page.
I've tried setting cell.setFixedHeight(100) but it doesn't seem to affect the cell. I've tried this solution as well but I can't get the cell to display the resulting image with text at all.
#Override
public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {
PdfContentByte canvas = canvases[PdfPTable.TEXTCANVAS];
try {
canvas.setFontAndSize(BaseFont.createFont(BaseFont.HELVETICA_BOLD, BaseFont.WINANSI, false), this.fontSize);
} catch (DocumentException | IOException e) {
e.printStackTrace();
}
if (this.alignment == PdfPCell.ALIGN_CENTER) {
this.left = ((position.getRight() - position.getLeft()) / 2 );
}
else if (this.alignment == PdfPCell.ALIGN_MIDDLE) {
this.top = ((position.getTop() - position.getBottom()) / 2 );
}
canvas.showTextAligned(this.alignment, this.text, position.getLeft() + this.left, position.getTop() - this.top, this.rotation);
}
Here's what the cell header overflow looks like. In this example it should have the month and year (Mar 2016) displayed.
I'd like to have the cell to be arbitrary height dependent on the actual header text being used. Any ideas on how to solve this?
A cell event is triggered after a cell is drawn. You might already have suspected that much as iText passes a Rectangle object with the position to the cellLayout method. A PdfPCell object is passed, but it is to be used for read-only purposes only. As the position is fixed, you can't use the setFixedHeight() on it.
Looking at the screen shot, I am puzzled: why are you using a cell event to add content that is rotated by 90 degrees? The solution to your problem would be to use the setRotation() method:
PdfPCell cell = new PdfPCell(new Phrase("May 16, 2016"));
cell.setRotation(90);
Now the content will be rotated and the size of the cell will be adapted to the content. Please take a look at the RotatedCell example:
public void createPdf(String dest) throws IOException, DocumentException {
Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream(dest));
document.open();
PdfPTable table = new PdfPTable(8);
for (int i = 0; i < 8; i++) {
PdfPCell cell =
new PdfPCell(new Phrase(String.format("May %s, 2016", i + 15)));
cell.setRotation(90);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
table.addCell(cell);
}
for(int i = 0; i < 16; i++){
table.addCell("hi");
}
document.add(table);
document.close();
}
The result looks like this: rotated_cell.pdf
Note that the concepts horizontal and vertical are rotated to. If you want to center the rotated content horizontally, you have to center the vertical alignment for the content and the rotate the aligned content.
Related
I'm using itextpdf to create my pdf with tables. While creating table i need to align some column to right, but its now working properly , can you guys help me.
I tried googling too, but didt work out for me. im using itextpdf 5.4 version.
public void generateMonthlySubReport(String[][] StrArray,String dueMonth,int Amt){
try {
Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream(MON_SUB_FILE));
PdfPTable pt = new PdfPTable(StrArray[0].length);
pt.setTotalWidth(new float[]{ 55,120,360,140});
pt.setLockedWidth(true);
PdfPCell pcell = new PdfPCell();
document.open();
addKvLogo(document);
Chunk glue = new Chunk(new VerticalPositionMark());
Paragraph p1 = new Paragraph("Monthly Subscription Report",catFont);
p1.setAlignment(Element.ALIGN_CENTER);
addEmptyLine(p1,2);
document.add(p1);
Paragraph p2 = new Paragraph("Month : "+dueMonth);
p2.add(new Chunk(glue));
p2.add("Per Member : Rs."+Amt);
addEmptyLine(p2,2);
document.add(p2);
for(int i=0;i<StrArray.length;i++){
for(int j=0;j<StrArray[i].length;j++){
pcell = new PdfPCell();
if(i==0){
pcell.setBackgroundColor(BaseColor.LIGHT_GRAY);
}else{
pcell.setBackgroundColor(BaseColor.WHITE);
}
pcell.setUseAscender(true);
pcell.setMinimumHeight(22);
pcell.setPaddingLeft(10);
pcell.setHorizontalAlignment(Element.ALIGN_RIGHT);
pcell.setVerticalAlignment(Element.ALIGN_MIDDLE);
pcell.addElement(new Phrase(StrArray[i][j]));
pt.addCell(pcell);
}
}
pt.setTotalWidth(PageSize.A4.getWidth()-(document.leftMargin()*2));
pt.setLockedWidth(true);
document.add(pt);
document.close();
} catch (Exception e) {
e.printStackTrace();
}
} `
You are mixing text mode with composite mode.
This is text mode:
pcell = new PdfPCell(new Phrase(StrArray[i][j]));
pcell.setHorizontalAlignment(Element.ALIGN_RIGHT);
In this case, the alignment of the cell will be used for the alignment of the text.
This is composite mode:
pcell = new PdfPCell();
Paragraph p = new Parapgraph(StrArray[i][j])
p.setAlignment(Element.ALIGN_RIGHT);
pcell.addElement(p);
In this case, the alignment of the cell is ignored, in favor of the alignment of the element.
How to know the difference between text mode and composite mode?
iText automatically switches from text mode to composite mode in a PdfPCell the moment you use the addElement() method. As soon as you do this, some properties defined at the cell level are ignored. This explains why the content you are adding isn't right-aligned.
I need to make a PDF page that looks something like this:
I'm having problems to make two columns that fit on a small sized page.
This is my code:
public void createSizedPdf(String dest) throws IOException, DocumentException {
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(dest));
document.setMargins(5,5,5,5);
Rectangle one = new Rectangle(290,100);
one.setBackgroundColor(Color.YELLOW);
document.setPageSize(one);
document.open();
Paragraph consigneeName = new Paragraph("Ahmed");
Paragraph address = new Paragraph("Casa ST 121");
String codeBL = "14785236987541";
PdfContentByte cb = writer.getDirectContent();
Barcode128 code128 = new Barcode128();
code128.setBaseline(9);
code128.setSize(9);
code128.setCode(codeBL);
code128.setCodeType(Barcode128.CODE128);
Image code128Image = code128.createImageWithBarcode(cb, null, null);
Paragraph right = new Paragraph();
right.add(consigneeName);
right.add(address);
right.add(code128Image);
Chunk glue = new Chunk(new VerticalPositionMark());
Paragraph p = new Paragraph();
p.add(right);
p.add(new Chunk(glue));
p.add(code128Image);
document.add(p);
document.close();
}
One way to solve your problem, would be to create a template PDF with AcroForm fields. You could create a nice design manually, and then fill out the form programmatically by putting data (text, bar codes) at the appropriate places defined by the fields that act as placeholders.
Another way, is to create the PDF from scratch, which is the approach you seem to have taken, looking at your code.
Your question isn't entirely clear, in the sense that you share your code, but you don't explain the problem you are experiencing. As I already commented:
are you unable to scale images? are you unable to define a smaller
font size? are you unable to create a table with specific dimension?
You say I'm having problems to make two columns that fits in a small
sized page but you forgot to describe the problems.
You didn't give an answer to those questions, and that makes it very hard for someone to answer your question. The only thing a Stack Overflow reader could do, is to do your work in your place. That's not what Stack Overflow is for.
Moreover, the answer to your question is so trivial that it is hard for a Stack Overflow reader to understand why you posted a question.
You say you need to add data (text and bar codes) in two columns, you are actually saying that you want to create a table. This is an example of such a table:
If you look at the SmallTable example, you can see how it's built.
You want a PDF that measures 290 by 100 user units, with a margin of 5 user units on each side. This means that you have space for a table measuring 280 by 90 user units. Looking at your screen shot, I'd say that you have a column of 160 user units with and a column of 120 user units. I'd also say that you have three rows of 30 user units high each.
OK, then why don't you create a table based on those dimensions?
public void createPdf(String dest) throws IOException, DocumentException {
Rectangle small = new Rectangle(290,100);
Font smallfont = new Font(FontFamily.HELVETICA, 10);
Document document = new Document(small, 5, 5, 5, 5);
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(dest));
document.open();
PdfPTable table = new PdfPTable(2);
table.setTotalWidth(new float[]{ 160, 120 });
table.setLockedWidth(true);
PdfContentByte cb = writer.getDirectContent();
// first row
PdfPCell cell = new PdfPCell(new Phrase("Some text here"));
cell.setFixedHeight(30);
cell.setBorder(Rectangle.NO_BORDER);
cell.setColspan(2);
table.addCell(cell);
// second row
cell = new PdfPCell(new Phrase("Some more text", smallfont));
cell.setFixedHeight(30);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setBorder(Rectangle.NO_BORDER);
table.addCell(cell);
Barcode128 code128 = new Barcode128();
code128.setCode("14785236987541");
code128.setCodeType(Barcode128.CODE128);
Image code128Image = code128.createImageWithBarcode(cb, null, null);
cell = new PdfPCell(code128Image, true);
cell.setBorder(Rectangle.NO_BORDER);
cell.setFixedHeight(30);
table.addCell(cell);
// third row
table.addCell(cell);
cell = new PdfPCell(new Phrase("and something else here", smallfont));
cell.setBorder(Rectangle.NO_BORDER);
cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
table.addCell(cell);
document.add(table);
document.close();
}
In this example,
you learn how to change the font of the content in a cell,
you learn how to change horizontal and vertical alignment,
you learn how to scale a bar code so that it fits into a cell,
...
All of this functionality is explained in the official documentation. As I said before: you didn't explain the nature of your problem. What wasn't clear in the documentation for you? What is your question?
I have an example below that generates a table with ten rows, the last row taking up two lines. The document height is two points smaller than it needs to be to correctly fit the entire table. As expected the last row on the first page contains the word "Two" and the "Lines" portion continues on another page. The generated PDF, however, extends the last row to fit the entire document, excluding page margin padding, instead of using the height of the text in the last row to determine how high it should be. Note that I use table.setExtendLastRow(false, false) to guarantee that the table shouldn't be extended, and yet the last row is getting extended anyway. Any ideas how to stop the last row from being extended?
FileOutputStream out = new FileOutputStream(new File("table.pdf"));
Document document = new Document(new Rectangle(612, 242));
PdfWriter.getInstance(document, out);
document.open();
PdfPTable table = new PdfPTable(1);
table.setWidthPercentage(100);
table.setSplitLate(false);
table.setSplitRows(true);
table.setExtendLastRow(false, false);
for (int i = 0; i < 10; i++) {
PdfPCell cell;
if (i == 9) {
cell = new PdfPCell(new Phrase("Two\nLines"));
}
else {
cell = new PdfPCell(new Phrase(Integer.toString(i)));
}
table.addCell(cell);
}
document.add(table);
document.close();
I've uploaded a picture of what I'm seeing. Notice the spacing under the word "Two" is different than the spacing under all the other numbers in the rows. It appears to extend to the bottom of the page margin.
This is expected behavior and iText doesn't currently have support for this edge case.
I want to dynamically align the iText PdfTable.
How to set the x and y position based alignment in iTextPDF.
PdfPCell cell;
cell = new PdfPCell(testTable);
cell.setFixedHeight(44f);
cell.setColspan(3);
cell.setBorder(0);
table.addCell(cell);
table1.addCell(table);
please look in to this example...
public static void Main() {
// step 1: creation of a document-object
Document document = new Document();
try {
// step 2:
// we create a writer that listens to the document
// and directs a PDF-stream to a file
PdfWriter writer = PdfWriter.getInstance(document, new FileStream("Chap1002.pdf", FileMode.Create));
// step 3: we open the document
document.Open();
// step 4: we grab the ContentByte and do some stuff with it
PdfContentByte cb = writer.DirectContent;
// we tell the ContentByte we're ready to draw text
cb.beginText();
// we draw some text on a certain position
cb.setTextMatrix(100, 400);
cb.showText("Text at position 100,400.");
// we tell the contentByte, we've finished drawing text
cb.endText();
}
catch(DocumentException de) {
Console.Error.WriteLine(de.Message);
}
catch(IOException ioe) {
Console.Error.WriteLine(ioe.Message);
}
// step 5: we close the document
document.Close();
}
}
Please take a look at the C# port of the examples of chapter 4 of my book: http://tinyurl.com/itextsharpIIA2C04
You can add the table to a ColumnText object and add the column at an absolute position:
ColumnText column = new ColumnText(writer.DirectContent);
column.AddElement(table);
column.SetSimpleColumn(llx, lly, urx, ury);
column.Go();
In this snippet llx, lly and urx, ury are the coordinates of the lower-left corner and the upper-right corner of the column on the page (see the ColumnTable example).
In the PdfCalendar example, another method is used:
table.WriteSelectedRows(0, -1, x, y, writer.DirectContent);
The first parameters define which rows need to be drawn (0 to -1 means all rows), x and y define the absolute position.
I am writing a program that generates a pdf or rtf file with a table in it, using iText. I used the iText class table and cell, rather than the more specific RtfTable or pdfTable so that either file can be generated at the end. I needed to set the cell padding to a value of -1, or else there was too much space between each row of data on the printed sheet. However, I am now trying to add borders (specifically to the pdf file), and the cells are not lining up with the text. The bottom border of each cell cuts directly through the text. It only actually surrounds the text when the cell padding is set to 2 or higher. Below is a sample of what I am doing:
Document document = new Document();
Paragraph paragraph = new Paragraph();
Font iTextFont = new Font(Font.TIMES_ROMAN, 9, Font.NORMAL);
try{
PdfWriter.getInstance(document, new FileOutputStream("C:/datafiles/TestiText.pdf"));
document.open();
Table table = new Table(3);
table.setPadding(-1);
table.setWidth(90);
Cell cell1 = new Cell();
cell1.setBorder(Rectangle.BOX);
cell1.setVerticalAlignment(ElementTags.ALIGN_TOP);
table.setDefaultCell(cell1);
paragraph = new Paragraph("header", iTextFont);
Cell cell = new Cell(paragraph);
cell.setHeader(true);
cell.setColspan(3);
table.addCell(cell);
paragraph = new Paragraph("example cell", iTextFont);
table.addCell(paragraph);
paragraph = new Paragraph("one", iTextFont);
table.addCell(cell);
paragraph = new Paragraph("two", iTextFont);
cell = new Cell(paragraph);
table.addCell(paragraph);
paragraph = new Paragraph("Does this start a new row?", iTextFont);
table.addCell(paragraph);
paragraph = new Paragraph("Four", iTextFont);
table.addCell(paragraph);
paragraph = new Paragraph("Five", iTextFont);
table.addCell(paragraph);
document.add(table);
} catch (Exception e) {
//handle exception
}
document.close();
}
Is there a way to resolve this issue either by moving the whole border down a drop (without affecting the text placement), or to get rid of the spaces between each line (spacing appears to only be a problem above the text, not below) without setting the cell padding to -1?
Write a class or common methods to build your table -- whether you're using Table or PdfPTable.
These methods will handle standard alignment, measurement based on ascenders/descenders, etc for you.. They also provide a common place to add a "3pt blank paragraph" or whatever other standard formattings, you may need.
OO software isn't meant to be about clanking out repetitive, and potentially inconsistent, sections of code.
Hope this helps.
you should use PdfPTable it has many method that is useful and well wrapped component
i posted this answer so any one faces the same problem know where to start
it might not be the typical answer to the question but here it comes...
Organizing content in tables
The PDF output
import java.io.FileOutputStream;
import java.io.IOException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
public class Spacing {
/** The resulting PDF file. */
public static final String RESULT = "results/part1/chapter04/spacing.pdf";
/**
* Main method.
* #param args no arguments needed
* #throws DocumentException
* #throws IOException
*/
public static void main(String[] args)
throws DocumentException, IOException {
// step 1
Document document = new Document();
// step 2
PdfWriter.getInstance(document, new FileOutputStream(RESULT));
// step 3
document.open();
// step 4
PdfPTable table = new PdfPTable(2);
table.setWidthPercentage(100);
Phrase p = new Phrase(
"Dr. iText or: How I Learned to Stop Worrying " +
"and Love the Portable Document Format.");
PdfPCell cell = new PdfPCell(p);
table.addCell("default leading / spacing");
table.addCell(cell);
table.addCell("absolute leading: 20");
cell.setLeading(20f, 0f);
table.addCell(cell);
table.addCell("absolute leading: 3; relative leading: 1.2");
cell.setLeading(3f, 1.2f);
table.addCell(cell);
table.addCell("absolute leading: 0; relative leading: 1.2");
cell.setLeading(0f, 1.2f);
table.addCell(cell);
table.addCell("no leading at all");
cell.setLeading(0f, 0f);
table.addCell(cell);
cell = new PdfPCell(new Phrase(
"Dr. iText or: How I Learned to Stop Worrying and Love PDF"));
table.addCell("padding 10");
cell.setPadding(10);
table.addCell(cell);
table.addCell("padding 0");
cell.setPadding(0);
table.addCell(cell);
table.addCell("different padding for left, right, top and bottom");
cell.setPaddingLeft(20);
cell.setPaddingRight(50);
cell.setPaddingTop(0);
cell.setPaddingBottom(5);
table.addCell(cell);
p = new Phrase("iText in Action Second Edition");
table.getDefaultCell().setPadding(2);
table.getDefaultCell().setUseAscender(false);
table.getDefaultCell().setUseDescender(false);
table.addCell("padding 2; no ascender, no descender");
table.addCell(p);
table.getDefaultCell().setUseAscender(true);
table.getDefaultCell().setUseDescender(false);
table.addCell("padding 2; ascender, no descender");
table.addCell(p);
table.getDefaultCell().setUseAscender(false);
table.getDefaultCell().setUseDescender(true);
table.addCell("padding 2; descender, no ascender");
table.addCell(p);
table.getDefaultCell().setUseAscender(true);
table.getDefaultCell().setUseDescender(true);
table.addCell("padding 2; ascender and descender");
cell.setPadding(2);
cell.setUseAscender(true);
cell.setUseDescender(true);
table.addCell(p);
document.add(table);
// step 5
document.close();
}
}