Generate Table of Contents | |
The html to pdf converter can give a document a table of contents with page numbers, through TableOfContents. The Mode property chooses how it is built:
FillExisting - the page already has a table of contents (internal links to its sections); each entry gets a leader and the number of the page its section is on.
InsertHtml - the table of contents is written into the page from its headings, styled by the page's CSS, then numbered.
GeneratePages - the table of contents is drawn on pages of its own, inserted into the pdf document, with the fonts, colors and spacing set in the options.
In every mode the page numbers are the numbers the document shows: they start at the FirstPageNumber of the displayed footer, and pages inserted by GeneratePages are counted. Leaders and numbers are decorative in a tagged document, so accessible (PDF/UA) and archival (PDF/A) documents stay conformant. JavaScript must be enabled.
Set ContainerSelector to the element that holds the table of contents. Every <a href="#id"> link inside it gets a leader and the number of the page its target is on, drawn at the end of the line where the link's text ends and right-aligned to the container, so the table keeps the look the page gives it. A link whose target is not in the document gets no number.
HtmlToPdf converter = new HtmlToPdf(); converter.Options.TableOfContents.Mode = PdfTableOfContentsMode.FillExisting; converter.Options.TableOfContents.ContainerSelector = "#toc"; converter.Options.TableOfContents.Leader = PdfTableOfContentsLeader.Dots; string url = "https://www.example.com/document2.html"; PdfDocument doc = converter.ConvertUrl(url); doc.Save("toc.pdf"); doc.Close();
HeadingSelectors lists the headings, one selector per level. The table is written at the start of the page, at its end or inside a placeholder element (HtmlPlacement), as a <nav class="selectpdf-toc"> with an optional <h2 class="selectpdf-toc-title"> and nested <ol> lists whose items have the classes selectpdf-toc-entry and selectpdf-toc-level-N, so the page's CSS can style it. It gets a page of its own (PageBreak).
HtmlToPdf converter = new HtmlToPdf(); PdfTableOfContentsOptions toc = converter.Options.TableOfContents; toc.Mode = PdfTableOfContentsMode.InsertHtml; toc.HeadingSelectors = new string[] { "h1", "h2" }; toc.Title = "Table of Contents"; converter.Options.CustomCSS = "nav.selectpdf-toc li { font-size: 14px; }"; string url = "https://www.example.com/document3.html"; PdfDocument doc = converter.ConvertUrl(url); doc.Save("toc.pdf"); doc.Close();
The table is drawn on pages inserted at the start, after the first page or at the end (PagePosition), with the page size, margins, header and footer of the converted pages. Each entry is a link to its heading. The title has its own font, color and alignment, and each level its own font, color, indent and spacing (PdfTableOfContentsLevelStyle); NumberEntries numbers the entries.
HtmlToPdf converter = new HtmlToPdf(); PdfTableOfContentsOptions toc = converter.Options.TableOfContents; toc.Mode = PdfTableOfContentsMode.GeneratePages; toc.HeadingSelectors = new string[] { "h1", "h2" }; toc.PagePosition = PdfTableOfContentsPagePosition.AfterFirstPage; toc.Title = "Table of Contents"; toc.TitleAlign = PdfTextHorizontalAlign.Center; toc.NumberEntries = true; toc.LevelStyles = new PdfTableOfContentsLevelStyle[] { new PdfTableOfContentsLevelStyle { Font = PdfFont.CreateStandardFont(PdfStandardFont.TimesBold, 13), SpacingBefore = 10, }, new PdfTableOfContentsLevelStyle { Font = PdfFont.CreateStandardFont(PdfStandardFont.TimesRoman, 11), Indent = 20, }, }; string url = "https://www.example.com/document3.html"; PdfDocument doc = converter.ConvertUrl(url); doc.Save("toc.pdf"); doc.Close();
For a layout the modes above do not cover, the page numbers can be drawn by your own code: the Get Web Elements Location in PDF feature reports where the table's entries and their targets landed in the pdf, and the entries and their targets are given the CSS class "toc" and paired IDs (TOC_Title1 / TOC_Target1, and so on), so the page of each target is known. This is how the table of contents was numbered before the TableOfContents option existed.
// number of items in the table of contents (TOC) int TOC_Items = 13; // CSS class for TOC items (titles and targets) string TOC_Class = "toc"; // font size for page numbers in the table of contents int TOC_Page_Font_Size = 12; // CSS class for PDF bookmarks string Bookmarks_Class = "bookmark"; // Each TOC item is represented by a title with ID TOC_Title{0} // and a target (internal link) with ID TOC_Target{0} // Both TOC titles and targets must have the same CSS Class ("toc" in our sample) // the url of the document that will be converted string url = "https://www.example.com/document2.html"; // instantiate a html to pdf converter object HtmlToPdf converter = new HtmlToPdf(); converter.Options.MarginTop = 20; converter.Options.MarginRight = 20; converter.Options.MarginBottom = 20; converter.Options.MarginLeft = 20; // set the css selectors for the automatic bookmarks // (elements with CSS class "bookmark") converter.Options.PdfBookmarkOptions.CssSelectors = new string[] { "*." + Bookmarks_Class }; // set the css selectors for the TOC related elements // (elements with CSS class "toc") // (alternatively, full list of IDs can be specified) converter.Options.WebElementsMappingOptions.CssSelectors = new string[] { "*." + TOC_Class }; // display the bookmarks when the document is opened in a viewer converter.Options.ViewerPreferences.PageMode = PdfViewerPageMode.UseOutlines; // footer settings converter.Options.DisplayFooter = true; converter.Footer.Height = 30; // page numbers can be added using a PdfTextSection object, using a system font // (subset-embedded). Liberation Sans resolves on any host: the library bundles it // and serves it from embedded bytes when it is not installed. PdfFont footerFont = PdfFont.CreateFromSystemFont("Liberation Sans", 10f); PdfTextSection text = new PdfTextSection(0, 10, "Page: {page_number} of {total_pages} ", footerFont); text.HorizontalAlign = PdfTextHorizontalAlign.Right; converter.Footer.Add(text); // create a new pdf document converting an url PdfDocument doc = converter.ConvertUrl(url); // create font for page numbers PdfFont pageNumberFont = doc.Fonts.Add( PdfFont.CreateStandardFont(PdfStandardFont.Helvetica, TOC_Page_Font_Size)); // get the right coordinate of the table of contents // to position the page numbers float tocRight = doc.Pages[0].ClientRectangle.Width - 50; // add page numbers for the table of contents items for (int tocItem = 1; tocItem <= TOC_Items; tocItem++) { string tocTitleID = String.Format("TOC_Title{0}", tocItem); string tocTargetID = String.Format("TOC_Target{0}", tocItem); WebElement tocTitle = converter.Options.WebElementsMappingOptions .Result.GetElementByHtmlId(tocTitleID); WebElement tocTarget = converter.Options.WebElementsMappingOptions .Result.GetElementByHtmlId(tocTargetID); if (tocTitle == null || tocTarget == null) { // TOC items not found continue; } // get the TOC title page and rendering rectangle PdfPage tocPage = doc.Pages[tocTitle.PdfRectangles[0].PageIndex]; RectangleF tocTitleRectangle = tocTitle.PdfRectangles[0].Rectangle; // get the page number of target where the TOC entry points int tocTargetPageNumber = tocTarget.PdfRectangles[0].PageIndex + 1; // add dashed line from TOC title to the page number PdfLineElement dashedLine = new PdfLineElement( tocTitleRectangle.Right + 5, tocTitleRectangle.Y + tocTitleRectangle.Height - 4, tocRight, tocTitleRectangle.Y + tocTitleRectangle.Height - 4); dashedLine.LineStyle.LineWidth = 1; dashedLine.LineStyle.LineDashStyle = PdfLineDashStyle.Dash; dashedLine.ForeColor = Color.Black; tocPage.Add(dashedLine); // create the page number text element to the right of the TOC title PdfTextElement pageNumberTextElement = new PdfTextElement(tocRight + 5, tocTitleRectangle.Y, -1, tocTitleRectangle.Height, tocTargetPageNumber.ToString(), pageNumberFont); pageNumberTextElement.HorizontalAlign = PdfTextHorizontalAlign.Left; pageNumberTextElement.VerticalAlign = PdfTextVerticalAlign.Middle; pageNumberTextElement.ForeColor = Color.Black; // add the page number to the right of the TOC entry tocPage.Add(pageNumberTextElement); } // save pdf document doc.Save("Sample.pdf"); // close pdf document doc.Close();