3

I'm having an issue with iText when generating PDF from HTML. I'm passing the "import information section" from Locize, which contains bold tags and list bullet

<li>\n                    
   <b>Toll-free</b> (within Canada and the USA): 
   <b>1.800.xxxxxxx</b>\n                
</li>\n  

The pdf file is generated in Confirmation.cs. The parameter "medSrc" passing from Confirmation.cs to ImportantInformation.cs is listed below. Somehow, the bold style and the list bullets just don't apply to the outcome pdf file.

I have been debugging this for a while and still no clue about what's going on. Does anyone know what I missed?

Thank you in advance!

Confirmation.cs

    ...
    namespace xxx.Pdf.xxx.xxx
    {
    public partial class Confirmation
    {
        private IApplication application;

        public Confirmation(IApplication application)
        {
            this.application = application;
        }

        public byte[] Create()
        {
            var memoryStream = new MemoryStream();
            var css = Content.Css;

            //Create Document
            PdfDocument pdfDocument = new PdfDocument(new PdfWriter(memoryStream));
            PageSize pageSize = PageSize.LETTER;
            Document document = new Document(pdfDocument, pageSize);

            Header headerHandler = new Header(document);
            PageXofY footerHandler = new PageXofY(pdfDocument);
            document.SetTopMargin(headerHandler.GetTableHeight());

            //Assign event-handlers
            pdfDocument.AddEventHandler(PdfDocumentEvent.START_PAGE, headerHandler);
            pdfDocument.AddEventHandler(PdfDocumentEvent.END_PAGE, footerHandler);

           ...
            // ======>Important Information <=======
            var importantInfo = new ImportantInformation();
            Table impInfoTable = importantInfo.CreateTable(
                HtmlUtility.MergeCssWithHtml(css, Content.ImportantInformationEmergencyMedical),
                HtmlUtility.MergeCssWithHtml(css, Content.ImportantInformationTripCancellation));

            document.Add(impInfoTable).Add(new Paragraph("\n"));

            //set column parameters
            float offset = 36;
            float columnWidth = (pageSize.GetWidth() - offset * 2 + 15) / 2;
            float columnHeight = pageSize.GetHeight() - offset * 2;
            float tableWidth = columnWidth - 10;

            //define column area
            Rectangle[] columns = new Rectangle[]
            {
                new Rectangle(offset , offset, columnWidth, columnHeight),
                new Rectangle(columnWidth + 30, offset, columnWidth, columnHeight)
            };
            document.SetRenderer(new ColumnDocumentRenderer(document, columns));

            document.Add(new AreaBreak(AreaBreakType.LAST_PAGE));

            foreach (Applicant applicant in application.Applicants)
            {
                ApplicantTable applicantTable = new ApplicantTable();
                Table table = applicantTable.CreateTable(applicant, tableWidth);
                //Table another = applicantTable.CreateTable(application.Applicants[1], tableWidth);

                document.Add(table).Add(new Paragraph("\n").SetFontSize(3));
            }

            footerHandler.WriteTotal(pdfDocument);

            document.Close();

            pdfDocument.Close();

            var pdf = memoryStream.ToArray();

            return pdf;
        }
    }
}

ImportantInformation.cs

...
namespace xxx.xxx.xxx.Pdf
{
    public class ImportantInformation
    {
    public Table CreateTable(string medSrc, string tciSrc)
    {
        float[] colWidth = new float[] { 50f, 50f };
        Table table = new Table(UnitValue.CreatePercentArray(colWidth));
        table.SetWidth(new UnitValue(UnitValue.PERCENT, 100));

        PdfFont avenir = FontFactory.CreateAvenirLightStandardMedium();

        Paragraph title = new Paragraph().Add("**IMPORTANT INFORMATION**").SetFontSize(12).SetFont(avenir).SetBold().SetTextAlignment(TextAlignment.CENTER);
        Cell titleCell = new Cell(1, 2).Add(title).SetBorder(Border.NO_BORDER);
        table.AddCell(titleCell);

        Cell medImportantinfo = new Cell()
            .SetBorder(Border.NO_BORDER)
            .Add(new Paragraph("Paragraph A")
            .SetFirstLineIndent(10f)
            .SetBold()
            .SetFontSize(9)
            .SetFont(avenir));
        Cell tciImportantInfo = new Cell()
            .SetBorder(Border.NO_BORDER)
            .Add(new Paragraph("Paragraph B")
            .SetFirstLineIndent(10f)
            .SetBold()
            .SetFontSize(9)
            .SetFont(avenir));

        IList<IElement> medInfo = HtmlToCellFormat.HtmlToElements(medSrc);

        IList<IElement> tciInfo = HtmlToCellFormat.HtmlToElements(tciSrc);

        foreach (IElement e in medInfo)
        {
            medImportantinfo.ElementToCell(e);
        }

        foreach (IElement e in tciInfo)
        {
            tciImportantInfo.ElementToCell(e);
        }

        table.AddCell(medImportantinfo).AddCell(tciImportantInfo);

        return table;
        }
    }
}

The medSrc:

<html>
<body>\n    
    <ul style=\"text-align: justify; list-style-type: disc; font-family: avenir, Arial, Helvetica, sans-serif; font-size: 10px\">\n        
        <li>\n            In the event of a medical emergency contact:\n            
            <ul style=\"text-align: justify; list-style-type: circle; font-family: avenir, Arial, Helvetica, sans-serif; font-size: 10px\">\n                
                <li>\n                    
                    <b>Toll-free</b> (within Canada and the USA): 
                    <b>1.800xxxxxx</b>\n                
                </li>\n                
                <li>\n                    
                    <b>Collect</b> (from all other locations): 
                    <b>1.xxxxxx</b>\n                
                </li>\n            
            </ul>\n        
        </li>\n        
        ...
    </body>
</html>

Updates: Here is the definition for the functions of ElementToCell and HtmlToElements

public static class HtmlToCellFormat
{
    public static string baseUri = "/";

    public static void ElementToCell(this Cell cell, IElement e)
    {
        var type = e.GetType().ToString();
        if (e.GetType() == typeof(Image))
        {

            cell.Add((Image)e);
        }
        else if (e.GetType() == typeof(Paragraph) || (e.GetType() == typeof(List)))
        {
            cell.Add((IBlockElement)e);
        }
    }

    public static IList<IElement> HtmlToElements(string content)
    {
        ConverterProperties properties = new ConverterProperties();
        properties.SetBaseUri(baseUri);
        FontProvider fontProvider = new DefaultFontProvider(false, false, false);
        FontProgram fontProgram = FontProgramFactory.CreateFont();
        fontProvider.AddFont(fontProgram, "");
        properties.SetFontProvider(fontProvider);
        IList<IElement> elements = HtmlConverter.ConvertToElements(content, properties);
        return elements;
    }
}
mkl
  • 90,588
  • 15
  • 125
  • 265
Julie C.
  • 629
  • 2
  • 11
  • 20
  • The variables `medImportantinfo` and `tciImportantInfo` are of type [`Cell`](http://itextsupport.com/apidocs/iText7/latest/com/itextpdf/layout/element/Cell.html), but I can't find the `ElementToCell()` method in those classes. I'm not a C# developer, but I can't find that method in iText 7 for .NET either: https://github.com/itext/itext7-dotnet/blob/develop/itext/itext.layout/itext/layout/element/Cell.cs What is that method about? If I google for it, I only find a valid reference to your question: https://www.google.com/search?q=iText+ElementToCell+cell – Bruno Lowagie Jun 19 '18 at 16:35
  • It's strange that you'd use a method `ElementToCell()` on a `Cell` instead of using the method `Add()`. Of course, for the `Add()` method to work, you might need to cast the `IElement` to an `IBlockElement` or an `Image` element. – Bruno Lowagie Jun 19 '18 at 16:41
  • @BrunoLowagie I just added the definition of the function you are asking about. We defined the ElementToCell by our own for some to deal with different types – Julie C. Jun 19 '18 at 17:03
  • OK, thanks for clarifying. I'd use something like `if (e instanceof IBlockElement)` in Java, but I don't know if that exists in C#. Comparing `string` values looks awkward to me, but since I don't know C#, I can't help you any further.. – Bruno Lowagie Jun 19 '18 at 17:14
  • @BrunoLowagie no problem, thanks for your time – Julie C. Jun 19 '18 at 17:58

1 Answers1

1

I fixed this issue by reading the article from iText https://developers.itextpdf.com/content/itext-7-converting-html-pdf-pdfhtml/chapter-6-using-fonts-pdfhtml

Simply change

FontProvider fontProvider = new DefaultFontProvider(false, false, false); 

to

FontProvider fontProvider = new DefaultFontProvider(true, true, true);
Julie C.
  • 629
  • 2
  • 11
  • 20