Skip to main content
Skip table of contents

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.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.