Skip to main content
Skip table of contents

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

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

VBNET
Dim cb As PdfContentByte = writer.DirectContent
cb.BeginText()
cb.SetFontAndSize(Californian, 36)
cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER,
    "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)
cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER,
    _hours +" Hours", 297.05, 285.44, 0)
cb.SetFontAndSize(Bold_Times, 16)
cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER,
    _dates, 494.95, 285.44, 0)
cb.SetFontAndSize(Bold_Times, 16)
cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, _class1, 396, 250.34, 0)IfNotString.IsNullOrWhiteSpace(_class2)Then
    cb.SetFontAndSize(Bold_Times, 16)
    cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, _class2, 396, 235.34, 0)EndIf
cb.SetFontAndSize(Copper, 16)
cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER,
    _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)
cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER,
    "Some Company Manager", 396, 162.64, 0)
cb.EndText()

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 stringx_Cordy_Cordtilt. 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:

JAVA
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:

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

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

JAVA
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.