How to create Table Of Contents in iTextSharp

后端 未结 3 369
一向
一向 2020-12-10 17:37

I need to create a Table Of Contents with page numbers, but I don\'t know how. Next format:

heading1 ----------------page number  
  subHeading1-------------         


        
相关标签:
3条回答
  • 2020-12-10 17:51

    Thanks for the example, i needed this in C# and with multicolumn, so i rewrote this example as below:

    namespace GerarPDF
    {
    public class GerarPDF
    {
        public const String DEST = "results/example.pdf";
    
        public GerarPDF()
        {
            FileInfo file = new FileInfo(String.Concat(AppDomain.CurrentDomain.BaseDirectory, @"/", DEST));
            file.Directory.Create();
            this.createPdf(file.FullName);
        }
    
        public void createPdf(String dest)
        {
            FileStream fs = new FileStream(dest, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
    
            Document document = new Document(PageSize.LETTER);
            PdfWriter writer = PdfWriter.GetInstance(document, fs);
            document.Open();
    
            TOCEvent evento = new TOCEvent();
            writer.PageEvent = evento;
    
            for (int i = 0; i < 10; i++)
            {
                String title = "This is title " + i;
                Chunk c = new Chunk(title, new Font());
                c.SetGenericTag(title);
                document.Add(new Paragraph(c));
                for (int j = 0; j < 50; j++)
                {
                    document.Add(new Paragraph("Line " + j + " of title " + i + " page: " + writer.PageNumber));
                }
            }
            document.NewPage();
            document.Add(new Paragraph("Table of Contents", new Font()));
            Chunk dottedLine = new Chunk(new DottedLineSeparator());
            List<PageIndex> entries = evento.getTOC();
    
            MultiColumnText columns = new MultiColumnText();
            columns.AddRegularColumns(72, 72 * 7.5f, 24, 2);
    
            Paragraph p;
            for (int i = 0; i < 10; i++)
            {
                foreach (PageIndex pageIndex in entries)
                {
                    Chunk chunk = new Chunk(pageIndex.Text);
                    chunk.SetAction(PdfAction.GotoLocalPage(pageIndex.Name, false));
                    p = new Paragraph(chunk);
                    p.Add(dottedLine);
    
                    chunk = new Chunk(pageIndex.Page.ToString());
                    chunk.SetAction(PdfAction.GotoLocalPage(pageIndex.Name, false));
                    p.Add(chunk);
    
                    columns.AddElement(p);
                }
            }
            document.Add(columns);
    
            document.Close();
        }
    
        public class TOCEvent : PdfPageEventHelper
        {
            protected int counter = 0;
            protected List<PageIndex> toc = new List<PageIndex>();
    
            public override void OnGenericTag(PdfWriter writer, Document document, Rectangle rect, string text)
            {
                String name = "dest" + (counter++);
                int page = writer.PageNumber;
                toc.Add(new PageIndex() { Text = text, Name = name, Page = page });
                writer.DirectContent.LocalDestination(name, new PdfDestination(PdfDestination.FITH, rect.GetTop(0)));
            }
    
            public List<PageIndex> getTOC()
            {
                return toc;
            }
        }
    }
    
    public class PageIndex
    {
        public string Text { get; set; }
        public string Name { get; set; }
        public int Page { get; set; }
    }
    }
    
    0 讨论(0)
  • 2020-12-10 18:09

    this snipplet can it be recursive, the basic concept is:

    List<PdfPCell> celdas = new List<PdfPCell>();
    string urlSection=String.empty;    
    var estatus = new Phrase();
    estatus.Leading = 25;
    if (streams != null && streams.Any())
        primero = streams.FirstOrDefault(x => x.Id == enlace.Id);
    if (primero != null)
        urlSection = primero.UrlSection;
    
    //For the code and generate hyperlink:
    Chunk espacioTab = new Chunk(" " + enlace.Name, baseFontBig );
    
    espacioTab = Visor.Servicios.GeneracionPDF.PDFUtils.GenerarVinculo(" " + enlace.Name, urlSection, baseFontBig);
    estatus.Add(espacioTab);
    if (incluirPaginado)
    {
    
       if (primero != null)
           actualPage = primero.TotalPages;
       else
           actualPage = 0;
    
    ///This is important, generate dots like "...." to chunk end 
        estatus.Add(new Chunk(new iTextSharp.text.pdf.draw.DottedLineSeparator()));
    
        var linkPagina = new Chunk(actualPage.ToString());
        linkPagina = Visor.Servicios.GeneracionPDF.PDFUtils.GenerarVinculo(actualPage.ToString(), urlSection, baseFontBig );
        estatus.Add(linkPagina);
        resultado.paginaFinal = actualPage;
    }
    
    //This is for add to your cell or table
    PdfPCell rightCell = new PdfPCell()
    {
        Border = PdfPCell.NO_BORDER,
        Colspan = 3,
        PaddingLeft = espacioInicial.Length,
        ExtraParagraphSpace = 10,
    };
    rightCell.AddElement(estatus);
    celdas.Add(rightCell);
    

    And create a new method, this create a hyperlinkand you can invoque when you want

    /*Generar Vinculo (create hyperlink)**/
    public static Chunk GenerarVinculo(String tituloMostrar, string urlDirecion, iTextSharp.text.Font fuente)
    {
        Chunk espacioTab = new Chunk();
        try
        {
            if (String.IsNullOrEmpty(urlDirecion))
            urlDirecion = "Indice de Contenido";
    
            espacioTab = new Chunk(tituloMostrar, fuente);
            var accion = PdfAction.GotoLocalPage(urlDirecion, false);
            espacioTab.SetAction(accion);
        }                
        catch (Exception error) { }
        return espacioTab;
    }
    

    Hope helps someone

    0 讨论(0)
  • 2020-12-10 18:18

    You've probably implemented this yourself by name, but I made a small example myself for the sake of completeness.

    Please take a look at the CreateTOC example. It creates a PDF with some random text:

    You can clearly see the titles and the content under the titles. After we have added all our content, we start a new page, and we add a table of contents:

    The table of contents is composed by a series of key-value pairs, where the key is the title and the value is the page number. We create this list in a page event:

    public class TOCEvent extends PdfPageEventHelper {
    
        protected List<SimpleEntry<String, Integer>> toc = new ArrayList<>();
    
        @Override
        public void onGenericTag(PdfWriter writer, Document document, Rectangle rect, String text) {
            toc.add(new SimpleEntry(text, writer.getPageNumber()));
        }
    
        public List getTOC() {
            return toc;
        }
    }
    

    We use this page event like this:

    public void createPdf(String dest) throws IOException, DocumentException {
        Document document = new Document();
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(dest));
        TOCEvent event = new TOCEvent();
        writer.setPageEvent(event);
        document.open();
        for (int i = 0; i < 10; i++) {
            String title = "This is title " + i;
            Chunk c = new Chunk(title, titleFont);
            c.setGenericTag(title);
            document.add(new Paragraph(c));
            for (int j = 0; j < 50; j++) {
                document.add(new Paragraph("Line " + j + " of title " + i));
            }
        }
        document.newPage();
        document.add(new Paragraph("Table of Contents", titleFont));
        Chunk dottedLine = new Chunk(new DottedLineSeparator());
        List<SimpleEntry<String, Integer>> entries = event.getTOC();
        Paragraph p;
        for (SimpleEntry<String, Integer> entry : entries) {
            p = new Paragraph(entry.getKey());
            p.add(dottedLine);
            p.add(String.valueOf(entry.getValue()));
            document.add(p);
        }
        document.close();
    }
    

    First we create an instance of the event and we declare it to the writer:

    TOCEvent event = new TOCEvent();
    writer.setPageEvent(event);
    

    We mark the titles using setGenericTag():

    String title = "This is title " + i;
    Chunk c = new Chunk(title, titleFont);
    c.setGenericTag(title);
    document.add(new Paragraph(c));
    

    Once we've finished adding the content, we get all the entries:

    List<SimpleEntry<String, Integer>> entries = event.getTOC();
    

    We loop over this list and compose a Paragraph for every entry:

    for (SimpleEntry<String, Integer> entry : entries) {
        p = new Paragraph(entry.getKey());
        p.add(dottedLine);
        p.add(String.valueOf(entry.getValue()));
        document.add(p);
    }
    

    No one can argue that this was difficult. The event class takes less than 10 lines of code. Adding support for subheadings will add a handful of lines, but that shouldn't be difficult too. It's a matter of building a tree structure, and introducing some indentation where necessary.

    0 讨论(0)
提交回复
热议问题