How to reduce redundant code when adding content at absolute positions?

This is part of a app that uses the itextsharp library:


Dim cb As PdfContentByte = writer.DirectContent
cb.SetFontAndSize(Californian, 36)
    "CERTIFICATE OF COMPLETION", 396, 397.91, 0)
cb.SetFontAndSize(Bold_Times, 22)
cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, name, 396, 322.35, 0)
cb.SetFontAndSize(Bold_Times, 16)
    _hours + " Hours", 297.05, 285.44, 0)
cb.SetFontAndSize(Bold_Times, 16)
    _dates, 494.95, 285.44, 0)
cb.SetFontAndSize(Bold_Times, 16)
cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, _class1, 396, 250.34, 0)
If Not String.IsNullOrWhiteSpace(_class2) Then
    cb.SetFontAndSize(Bold_Times, 16)
    cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, _class2, 396, 235.34, 0)
End If
cb.SetFontAndSize(Copper, 16)
    _conf_num + _prefix + " Annual Conference " + _dates, 396, 193.89, 0)
cb.SetFontAndSize(Bold_Times, 13)
cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "Some Name", 396, 175.69, 0)
cb.SetFontAndSize(Bold_Times, 10)
    "Some Company Manager", 396, 162.64, 0)
Plenty of lines in this snippet look awfully redundant and in my opinion, this can't be the cleanest way to do things. Unfortunately, I can't figure out how to create a separate function to which I can simply pass some parameters, such as string, x_Cord, y_Cord, tilt. Such a function would then perform the necessary operations on the PdfContentByte.

Posted on StackOverflow on Nov 23, 2012 by Skindeep2366

You're adding content "the hard way". If I were you, I'd write a separate class/factory/method that creates a Paragraph with the content. For instance:

FontProgramFactory.registerFont(californianSrc, "Californian");
FontProgramFactory.registerFont(californianSrc, " Bold_times");
protected PdfFont f1 = PdfFontFactory.createRegisteredFont("Californian", PdfEncodings.WINANSI, false);
protected PdfFont f2 = PdfFontFactory.createRegisteredFont("Bold_times", PdfEncodings.WINANSI, false);
public Paragraph getCustomParagraph(String name, int hours, ...) {
  Paragraph p = new Paragraph();
  p.add(new Text(" ").setFont(f1) .setFontSize(36));
  p.add(new Text(name).setFont(f2) .setFontSize(16));
 return p;

Then I would use ColumnDocumentRenderer to set the areas where I want the data to appear:

ColumnDocumentRenderer renderer = new ColumnDocumentRenderer(doc, new Rectangle[]{new Rectangle(20, 100, 250, 700), new Rectangle(300, 100, 250, 700)});
Paragraph p = getCustomParagraph(name, hours, ...);

Or if you only need to write one line that doesn't need to be wrapped it's better to use Canvas.showTextAligned() method:

PdfPage page = pdfDoc.addNewPage();
PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDoc);
Paragraph p = getCustomParagraph(name, hours, ...);
new Canvas(pdfCanvas, pdfDoc, page.getPageSize())
    .showTextAligned(p, 200, 500, pdfDoc.getPageNumber(page), TextAlignment.CENTER, VerticalAlignment.MIDDLE, 0);

The approach you've taken works, but... it involves writing PDF syntax almost "manually". That's more difficult and therefore more error-prone. You already discovered that, otherwise you wouldn't ask the question ;-)

Click this link if you want to see how to answer this question in iText 5.

Ready to use iText?

Try our iText 7 Library and add-ons FREE for 30 days. Test your proof of concept, and see if our solution is right for you.

Get my FREE trial

Still have questions? 

We're happy to answer your questions. Reach out to us and we'll get back to you shortly.

Contact us
Stay updated

Join 11,000+ subscribers and become an iText PDF expert by staying up to date with our new products, updates, tips, technical solutions and happenings.

Subscribe Now