Find location last object on PDF page using iTextSharp - itext

How can I find the location and the height of the last object on a PDF page? There is no footer. I'm wanting to stamp a template below the last item. Not in the footer but directly below the last line of text. The amount of text may vary so I need to calculate if there is enough room at the bottom of the page to insert my template.
Thanks for any help,
Aaron

To determine where text and (bitmap) images on a given page end, have a look at the iText in Action, 2nd edition example ShowTextMargins which parses a PDF and adds a rectangle showing the text and (bitmap) images margin.
PdfReader reader = new PdfReader(src);
PdfReaderContentParser parser = new PdfReaderContentParser(reader);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(RESULT));
TextMarginFinder finder;
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
finder = parser.processContent(i, new TextMarginFinder());
PdfContentByte cb = stamper.getOverContent(i);
cb.rectangle(finder.getLlx(), finder.getLly(),
finder.getWidth(), finder.getHeight());
cb.stroke();
}
stamper.close();
reader.close();
Be aware, though, that this mechanism ignores vector graphics (often also used for underlining text, colored backgrounds, and decorative separating lines) because the underlying iText parser package still (as of iText version 5.4.5) ignores them.
Update: As of version 5.5.6 iText extends the parser package to also include vector graphics parsing. This allows for an extension of the original TextMarginFinder class implementing the new ExtRenderListener methods as presented in this answer resulting in an analogous class MarginFinder which does not only consider text but also other kind of content, e.g. bitmap images and vector graphics.

Related

iText 7: How can I insert diagrams into a `Document`?

I am using iText 7.2.1.
According to the documentation, I can only find elements like Image, Div, List, Paragraph, Table can be inserted into Document.
I want to draw some diagrams and insert it into my document. I need them to be part of my content stream. The existing PdfCanvas or Canvas can not do that. They seems to accept only absolute positions.
Is there a way inserting diagrams in iText 7?
In a comment you clarified
I want to draw diagrams using PdfCanvas instructions. Is it possible that I don't have to specify absolute position, and the diagram automatically follow the previous paragraph, and next paragraphs automatically follow this diagram. Is SVG the only way to do this?
You can create your diagram in a PdfFormXObject which has its own coordinate system. PdfCanvas instances can also be constructed for form XObjects.
Then you can wrap that XObject in an iText Image which in turn you can add to an iText Document to be automatically positioned.
So for a PdfDocument pdfDocument and a Document document:
PdfFormXObject xobject = new PdfFormXObject(new Rectangle([... area for your diagram ...]));
PdfCanvas pdfCanvas = new PdfCanvas(xobject, pdfDocument);
[... draw diagram on pdfCanvas ...]
Image image = new Image(xobject);
document.add(image);

pdfStamper.AcroFields.SetField dont keep appearance settings

I use iTextSharp 5.5.13 to create pdf file with text AcroFields and in a second step edit the pdf filling the AcroFields with some values.
For some fields i have to set a character spacing, so i use CreateAppearance method. this is the code:
var appearance = writer.DirectContent.CreateAppearance(box.Width, box.Height);
appearance.SetFontAndSize(baseFont, obj.FontSize);
appearance.SetColorFill(new iTextSharp.text.BaseColor(obj.Color));
appearance.SetCharacterSpacing(obj.CharSpacing);
formField.DefaultAppearanceString = appearance;
formField.SetAppearance(iTextSharp.text.pdf.PdfAnnotation.APPEARANCE_NORMAL, appearance);
writer.AddAnnotation(formField);
this code produce expected pdf result with fine character spacing in editable fields.
The problem is when i edit the pdf to fill AcroFields with:
pdfStamper.FormFlattening = true;
pdfStamper.AcroFields.GenerateAppearances = true;
pdfStamper.AcroFields.SetField(fieldName, fieldValue);
the resulting flattened pdf does not mantain the appearence character spacing...
What's wrong with my code?
Thanks
For generating text field appearances iText 5.x only uses the font, font size, and color information from the DA default appearance string (and the color information only if set using the g, rg, or k instructions), cf. the AcroFields method SplitDAelements which is used to extract information from the DA string.
So the iText 5.x appearance generation is quite limited and in particular does not support character spacing.
A possible work-around is for you to explicitly create all the appearances in your own code.

Create Table in Itext Pdf in java

I am creating a table in PDF in java using itext. I want to place it in top right corner.
Here is my code snippet. When I execute the below code, table is aligned in the bottom right of pdf but i want it on Top right corner.
PdfPTable table = new PdfPTable(1);
table.setHorizontalAlignment(Element.ALIGN_RIGHT);
table.setWidthPercentage(160 / 5.23f);
PdfPCell cell = new PdfPCell(new Phrase(" Date" , NORMAL));
cell.setBackgroundColor(BaseColor.BLACK);
cell.setBorderWidth(2f);
table.addCell(cell);
PdfPCell cellTwo = new PdfPCell(new Phrase("10/01/2015"));
cellTwo.setBorderWidth(2f);
table.addCell(cellTwo);
You have omitted the line that actually adds the table to the document.
Suppose that you have:
document.add(table);
In that case, iText will add it at the current position of the cursor. If no content was added yet, the table will be added at the top right. The top right is determined by the top margin and the right margin, but if those aren't 0, you may have the impression that the table isn't added at the top right.
You could also have:
PdfContentByte canvas = writer.getDirectContent();
table.writeSelectedRows(0, -1, document.right() - tablewidth, document.top(), canvas);
However, in that case you'd have to define the width of the table differently:
table.setTotalWidth(tableWidth);
I don't know how wide you want your table. You're using a rather odd formula to define the width percentage.
If this doesn't answer your question, please clarify by updating your question. Currently, it isn't entirely clear what you're doing. Your problem can't be reproduced. See the RightCornerTable example:
If my eyes don't fool me, the table is shown in the top-right corner when I use your code snippet and not in the bottom right as you claim...

How to add a table to a new page in an ItextSharp PdfStamper

I'm using ItextSharp to populate a Pdf template with data. The template is a single page form with a number of input fields. I can create a PdfStamper and populate the fields with no problem, however, I want to add a second page to the stamper and then add a dynamically created PdfPtable to that page. I can add a page using stamper.InsertPage(2,reader.GetpageSize()) but I can not work out how to add the table to the page.
Any help would be much appreciated.
Get your new page's PdfContentByte, then use PdfPTable.WriteSelectedRows(). There are 4 different overrides providing you with various options.
WriteSelectedRows just takes row [& column] numbers to draw, an X/Y location, and a PdfContentByte or array of same. This means it won't do any page breaking or width validation or what have you. It'll just draw what you ask it to draw, where you ask it to draw it. You have to do all the layout yourself.

How to create single PDF document with both portrait and landscape page using iTextSharp

I have been able to create portrait pages, and landscape pages in separate documents, but now require to do this in one document. I am using ITextSharp library and the document.setpagesize seems to apply to all pages. Is this correct?
I was using PDFLib and changing page orientation was not a problem in that library.
Any suggestions?
Paul.
It should only apply to pages rendered after that call.
Document doc = new Document(PageSize.WHAT_EVER);
PdfWriter writer = new PdfWriter( doc, outputStream );
doc.open();
// so long as you set the page size before add()ing anything, it should ignore the
// page sized used in the constructor.
doc.setPageSize(PageSize.LETTER); // 8.5" x 11"
// actually, I think you need to call newPage or actually add enough stuff to start a new page
// for setPageSize to take effect. setPageSize by itself won't do the trick.
doc.add(stuffToFillALetterPageButNotStartANewOne);
doc.setPageSize(new Rectangle(792f, 612f)); // 11" x 8.5"
doc.add(moreStuffToFillALandscapePageThusStartingANewPage);
doc.close();
The resulting PDF should have two pages. The will be 8.5x11, the other 11x8.5. Note that iText[sharp] won't generate rotated pages (8.5"x11" # 90 degrees (or 270... shudder)). It's... sharper than that.
Dealing with rotated pages is Not Fun. At least I've never run into one that was 8.5x11 at 180 rotation in my TOO_MANY_YEARS of experience with PDF. I'd just have to fly into a murderous rage at that point. Or maybe I should generate some PDFs that way just to see who I could catch with their pants down.
[insert fiendish cackle here]