Darshaka
Darshaka

Reputation: 189

How to Page Break HTML Content in HTML Renderer

I have a project where HTML code is converted to a PDF using HTML Renderer. The HTML code contains a single table. The PDF is displayed but the issue is that the contents of the table are cut off at the end. So is there any solution to the problem?enter image description here

PdfDocument pdf=new PdfDocument();

            var config = new PdfGenerateConfig()
            {
                MarginBottom = 20,
                MarginLeft = 20,
                MarginRight = 20,
                MarginTop = 20,
            };
            //config.PageOrientation = PageOrientation.Landscape;
            config.ManualPageSize = new PdfSharp.Drawing.XSize(1080, 828);

            pdf = PdfGenerator.GeneratePdf(html, config);

            byte[] fileContents = null;
            using (MemoryStream stream = new MemoryStream())
            {
                pdf.Save(stream, true);
                fileContents = stream.ToArray();
                return new FileStreamResult(new MemoryStream(fileContents.ToArray()), "application/pdf");
            }

Upvotes: 4

Views: 9728

Answers (3)

Kris
Kris

Reputation: 35

I've just figured out how to make it work, rather than page-break-inside on a TD, do that on the TABLE. Here's the code:

table { page-break-inside: avoid; }

I'm currently on the following versions (not working on stable versions at the moment): HtmlRenderer on v1.5.1-beta1 PDFsharp on v1.51.5185-beta

Upvotes: 2

Matt Eno
Matt Eno

Reputation: 697

As far as I know page breaks are not supported, but I've done a bit of a work-around (which may not work for all cases) by splitting the HTML into separate pages using a page break class, then adding each page to the pdf.

See example code below:

    //This will only work on page break elements that are direct children of the body element.
    //Each page's content must be inside the pagebreak element
    private static PdfDocument SplitHtmlIntoPagedPdf(string html, string pageBreakBeforeClass, PdfGenerateConfig config, PdfDocument pdf)
    {
        var htmlDoc = new HtmlDocument();
        htmlDoc.LoadHtml(html);
        var htmlBodyNode = htmlDoc.DocumentNode.SelectSingleNode("//body");

        var tempHtml = string.Empty;
        foreach (var bodyNode in htmlBodyNode.ChildNodes)
        {
            if (bodyNode.Attributes["class"]?.Value == pageBreakBeforeClass)
            {
                if (!string.IsNullOrWhiteSpace(tempHtml))
                {
                    //add any content found before the page break
                    AddPageToPdf(htmlDoc,tempHtml,config,ref pdf);
                    tempHtml = string.Empty;
                }
                AddPageToPdf(htmlDoc,bodyNode.OuterHtml,config,ref pdf);
            }
            else
            {
                tempHtml += bodyNode.OuterHtml;
            }
        }
        if (!string.IsNullOrWhiteSpace(tempHtml))
        {
            //add any content found after the last page break
            AddPageToPdf(htmlDoc, tempHtml, config, ref pdf);
        }

        return pdf;
    }

    private static void AddPageToPdf(HtmlDocument htmlDoc, string html, PdfGenerateConfig config, ref PdfDocument pdf)
    {
        var tempDoc = new HtmlDocument();
        tempDoc.LoadHtml(htmlDoc.DocumentNode.OuterHtml);
        var docNode = tempDoc.DocumentNode;
        docNode.SelectSingleNode("//body").InnerHtml = html;
        var nodeDoc = PdfGenerator.GeneratePdf(docNode.OuterHtml, config);
        using (var tempMemoryStream = new MemoryStream())
        {
            nodeDoc.Save(tempMemoryStream, false);
            var openedDoc = PdfReader.Open(tempMemoryStream, PdfDocumentOpenMode.Import);
            foreach (PdfPage page in openedDoc.Pages)
            {
                pdf.AddPage(page);
            }
        }
    }

Then call the code as follows:

            var pdf = new PdfDocument();
            var config = new PdfGenerateConfig()
            {
                MarginLeft = 5,
                MarginRight = 5,
                PageOrientation = PageOrientation.Portrait,
                PageSize = PageSize.A4
            };
            if (!string.IsNullOrWhiteSpace(pageBreakBeforeClass))
            {
                pdf = SplitHtmlIntoPagedPdf(html, pageBreakBeforeClass, config, pdf);
            }
            else
            {
                pdf = PdfGenerator.GeneratePdf(html, config);
            }

For any html that you want to have in its own page, just put the html inside a div with a class of "pagebreak" (or whatever you want to call it). If you want to, you could add that class to your css and give it "page-break-before: always;", so that the html will be print-friendly.

Upvotes: 3

HTMLRenderer should be able break the table to the next page.
See also:
https://github.com/ArthurHub/HTML-Renderer/pull/41

Make sure you are using the latest version. You may have to add those CSS properties.

Also see this answer:
https://stackoverflow.com/a/37833107/162529

Upvotes: 3

Related Questions