How to reduce redundant code when adding content at absolute positions?
This is part of a vb.net app that uses the itextsharp library:
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) 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) 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 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)});
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:
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.