Search code examples
c#sharepoint-2010pdf-generationitext

Why is the customization of my PDF fonts using iTextSharp failing?


I want to decorate various paragraphs in a PDF file by bolding some text, using different fonts, and colors. I thought I found the code for how to do that (below), but it's not working - all the text is the same font, color (black), and size. Why are my virtual sweat-inducing efforts to prettyify the PDF file so far in vain? Here is my code:

using (var ms = new MemoryStream())
{

    using (var doc = new Document(PageSize.A4, 50, 50, 25, 25))
    {
        using (var writer = PdfWriter.GetInstance(doc, ms))
        {
            doc.Open();

            // Mimic the appearance of Duckbill_Platypus.pdf
            var docTitle = new Paragraph("Duckbilled Platypi - they're not what's for dinner");
            var titleFont = FontFactory.GetFont("Courier", 18, BaseColor.BLACK);
            docTitle.Font = titleFont;
            doc.Add(docTitle);

            var subTitle = new Paragraph("Baby, infant, toddler, and perhaps 'Terrible 2s' Platypi are called Platypups");
            var subtitleFont = FontFactory.GetFont("Times Roman", 13, BaseColor.BLACK);
            subTitle.Font = subtitleFont;
            doc.Add(subTitle);

            var importantNotice = new Paragraph("Teenage platypi are sometimes called Platydude[tte]s");
            var importantNoticeFont = FontFactory.GetFont("Courier", 13, BaseColor.RED);
            importantNotice.Font = importantNoticeFont;
            doc.Add(importantNotice);

            ListColumns lc;
            for (int i = 0; i < listOfListItems.Count; i++)
            {
                lc = listOfListItems[i];
                sb.AppendLine(String.Format(@"<p>Request date is {0}; Payee Name is {1}; Remit Address or Mail Stop is {2}; Last 4 of SSN or ITIN is {3}; 204 Submitted or on file is {4}; Requester Name is {5}; Dept or Div Name is {6}; Phone is {7}; Email is {8}</p>",
                    lc.li_requestDate, lc.li_payeeName, lc.li_remitAddressOrMailStop, lc.li_last4SSNDigitsOrITIN, lc.li_204SubmittedOrOnFile, lc.li_requesterName, lc.li_deptDivName, lc.li_phone, lc.li_email));
            }

            String htmlToRenderAsPDF = sb.ToString();

            //XMLWorker also reads from a TextReader and not directly from a string
            using (var srHtml = new StringReader(htmlToRenderAsPDF))
            {
                XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, srHtml);
            }

            doc.Close();
        }
    }
    try
    {
        var bytes = ms.ToArray();
        var testFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "iTextSharpTest.pdf");
        File.WriteAllBytes(testFile, bytes);
    }
    catch (Exception ex)
    {
        String exMsg = ex.Message;
        ; // what is "ex" here?
    }

I'm setting two sizes of font (18 and 13), two colors (black and red), two fonts ("Courier" and "Times Roman") yet all my hours of travail here for PDF fancification seem yet in vain (apologies to Vachel Lindsay and Abraham Lincoln).


Solution

  • You should use the font when creating the Paragraph:

    Font f = new Font(FontFamily.COURIER);
    Paragraph p = new Paragraph("text", f);
    document.add(p);
    

    Or you should wait to add content until you've set the font:

    Paragraph p = new Paragraph();
    Font f = new Font(FontFamily.COURIER);
    p.setFont(f);
    p.addText("text");
    document.add(p);
    

    In your code, you have something like this:

    Paragraph p = new Paragraph("text");
    Font f = new Font(FontFamily.COURIER);
    p.setFont(f);
    document.add(p);
    

    When setting the font using setFont(), you set the font for the text that will be added to the paragraph, not to the text that is already stored in the paragraph.

    For instance:

    Paragraph p = new Paragraph("font 1 ");
    p.setFont(new Font(FontFamily.COURIER);
    p.add("font 2");
    document.add(p);
    

    This will add the text font 1 in the default font and font 2 in Courier.