Trying to create a bookmark for creating a table of contents but I am unable to create it

Product:

Product Version:

(Think of this as an email subject)

I want to create a new pdf file by merging multiple files. But when I am trying to add a bookmarks like table of contents, Cover page etc. then I am unable to do it. As I have tried many code samples posted in the community and also from Samples that we can find out in Download section (Apryse Developer Portal) but still I am unable to get the desired results. I am using PdfTron latest version

Here is my Sample code I am using:

try
            {
                _logger.LogInformation("Starting boardpack/book files export.");

                var migrationSettingForMeetingPaqList = _resourcesQuery.GetMigrationSettingForMeetingsPaq(customerId)?.ToList() ?? new List<MigrationSettingMeetingPaq>();


                string lis = "Sample demo Liscense";
                PDFNet.Initialize(lis);
                string directoryPath = fileDumpPath;
                using (PDFDoc mergedPdf = new PDFDoc())
                {
                    mergedPdf.InitSecurityHandler();
                    string fileExtension = string.Empty;
                    //string[] files = Directory.GetFiles(directoryPath, "*.*");


                    foreach (var filePath in exportedBooks.Take(5))
                    {
                        try
                        {
                            if (filePath.FileName != null)
                            {
                                fileExtension = Path.GetExtension(filePath.FileName).ToLower();
                            }
                            if (fileExtension == ".pdf" || fileExtension == ".pptx" || fileExtension == ".docx" || fileExtension == ".xlsx")
                            {
                                using (PDFDoc docToMerge = new PDFDoc(directoryPath + "\\" + filePath.FileName))
                                {


                                    if (fileExtension == ".pdf")
                                    {
                                        mergedPdf.InsertPages(mergedPdf.GetPageCount() + 1, docToMerge, 1, docToMerge.GetPageCount(), PDFDoc.InsertFlag.e_none);
                                    }
                                    else
                                    {
                                        WordToPDFOptions options = new WordToPDFOptions();
                                        pdftron.PDF.Convert.ToPdf(docToMerge, filePath.FileUrl);

                                        //tempPdfDoc.InsertPages(tempPdfDoc.GetPageCount() + 1, tempPdfDoc, 1, tempPdfDoc.GetPageCount(), PDFDoc.InsertFlag.e_none);

                                        //string outputFilePath = Path.Combine(fileDumpPath, "merged_output23.pdf");
                                        //string outputDirectory = Path.GetDirectoryName(outputFilePath);
                                        //if (!Directory.Exists(outputDirectory))
                                        //{
                                        //    Directory.CreateDirectory(outputDirectory);
                                        //}

                                        //// Save the PDF file
                                        //tempPdfDoc.Save(outputFilePath, SDFDoc.SaveOptions.e_linearized);
                                        //ConvertToPdf(docToMerge, filePath, fileDumpPath);
                                        mergedPdf.InsertPages(mergedPdf.GetPageCount() + 1, docToMerge, 1, docToMerge.GetPageCount(), PDFDoc.InsertFlag.e_none);
                                    }
                                }

                                //else if (fileExtension == ".png")
                                //{
                                //    using (PDFDoc pdfdoc = new PDFDoc())
                                //    {
                                //        Console.WriteLine("Converting from XPS");

                                //        pdftron.PDF.Convert.FromXps(pdfdoc, filePath + "simple-xps.xps");
                                //        pdfdoc.Save(fileDumpPath + "xps2pdf v2.pdf", SDFDoc.SaveOptions.e_remove_unused);
                                //        // Console.WriteLine("Saved xps2pdf v2.pdf");
                                //    }
                                //}
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine($"Error processing file {filePath}: {ex.Message}");
                        }
                    }

                    try
                    {
                        int pageIdx = 1;
                        int docPage = 0;
                        Bookmark bm = null;
                        int tocIdx = 0;
                        string debug = "";
                        string textValue = "";
                        var agendaPageCount = 0;
                        ElementBuilder eb = new ElementBuilder();
                        ElementWriter ew = new ElementWriter();
                        Element e = null;

                        if (migrationSettingForMeetingPaqList.Count > 0)
                        {
                            foreach (var setting in migrationSettingForMeetingPaqList)
                            {
                                switch (setting.Name)
                                {
                                    case "Re-Create Existing Book":

                                        break;
                                    case "Cover Page":
                                        if (setting.IsSelected)
                                        {
                                            bm = pdftron.PDF.Bookmark.Create(mergedPdf, setting.Name);
                                            bm.SetAction(pdftron.PDF.Action.CreateGoto(pdftron.PDF.Destination.CreateFit(mergedPdf.GetPage(pageIdx))));
                                            mergedPdf.AddRootBookmark(bm);
                                            pageIdx++;
                                        }
                                        break;
                                    case "Table of Contents":
                                        if (setting.IsSelected)
                                        {
                                            bm = pdftron.PDF.Bookmark.Create(mergedPdf, setting.Name);
                                            bm.SetAction(pdftron.PDF.Action.CreateGoto(pdftron.PDF.Destination.CreateFit(mergedPdf.GetPage(pageIdx))));
                                            mergedPdf.AddRootBookmark(bm);
                                            tocIdx = pageIdx;
                                            pageIdx++;
                                        }
                                        break;
                                    case "Boardpack Agenda":
                                        if (setting.IsSelected)
                                        {
                                            debug = "Set Text Value";
                                            var meeting = migrationSettingForMeetingPaqList.FirstOrDefault(x => x.Name == "Boardpack Minutes");
                                            if (meeting != null && meeting.IsSelected)
                                            {
                                                textValue = "Minutes";
                                            }

                                            debug = "Bookmark.Create";
                                            bm = pdftron.PDF.Bookmark.Create(mergedPdf, textValue);

                                            debug = "PDFDoc.GetPage " + pageIdx.ToString() + " of " + mergedPdf.GetPageCount().ToString();
                                            pdftron.PDF.Page pg = mergedPdf.GetPage(pageIdx);

                                            debug = "Destination.CreateFit to page " + pageIdx.ToString() + " of " + mergedPdf.GetPageCount().ToString();
                                            pdftron.PDF.Destination dest = pdftron.PDF.Destination.CreateFit(pg);

                                            debug = "Action.CreateGoto";
                                            pdftron.PDF.Action act = pdftron.PDF.Action.CreateGoto(dest);

                                            debug = "Bookmark.SetAction";
                                            bm.SetAction(act);

                                            debug = "PDFDoc.AddRootBookmark";
                                            mergedPdf.AddRootBookmark(bm);

                                            debug = "Up Page Count";
                                            pageIdx += agendaPageCount;

                                            docPage = pageIdx;
                                            var cnt = 0;
                                            foreach (var mpdoc in exportedBooks)
                                            {
                                                cnt++;
                                                if (cnt > 5) break;
                                                var extension = Path.GetExtension(mpdoc.FileName).ToLower();
                                                if (extension == ".pdf" || extension == ".pptx" || extension == ".docx" || extension == ".xlsx")
                                                {
                                                    textValue = mpdoc.FileName;
                                                    bm = pdftron.PDF.Bookmark.Create(mergedPdf, textValue);
                                                    bm.SetAction(pdftron.PDF.Action.CreateGoto(pdftron.PDF.Destination.CreateFit(mergedPdf.GetPage(docPage))));
                                                    mergedPdf.AddRootBookmark(bm);
                                                    PDFDoc doc = mergedPdf;
                                                    docPage += 1;
                                                }
                                            }
                                        }
                                        break;
                                    case "Boardpack Minutes":

                                        break;
                                    case "PDF Meeting Docs":

                                        break;
                                    case "e-signature page":

                                        break;
                                    case "Doc Approval Detail":

                                        break;
                                }
                            }
                        }

                        try
                        {
                            double pts = 10;
                            double ptsH = 4;


                            Element eH, eR;

                            pdftron.PDF.Page tocPage = mergedPdf.GetPage(tocIdx);

                            float fpts = System.Convert.ToSingle(pts);
                            float fptsH = System.Convert.ToSingle(ptsH);

                            //System.Drawing.Font sysFontBig = new System.Drawing.Font(new FontFamily(System.Drawing.Text.GenericFontFamilies.SansSerif), fpts + 2, FontStyle.Bold, System.Drawing.GraphicsUnit.Point);
                            //System.Drawing.Font sysFontReg = new System.Drawing.Font(new FontFamily(System.Drawing.Text.GenericFontFamilies.SansSerif), fpts, FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
                            System.Drawing.Font sysFontBig = new System.Drawing.Font("SansSerif", fpts + fptsH, FontStyle.Bold, GraphicsUnit.Point);
                            System.Drawing.Font sysFontReg = new System.Drawing.Font("SansSerif", fpts, FontStyle.Regular, GraphicsUnit.Point);
                            pdftron.PDF.Font pdfFontBld = pdftron.PDF.Font.Create(mergedPdf, sysFontBig.Name, "");
                            pdftron.PDF.Font pdfFontReg = pdftron.PDF.Font.Create(mergedPdf, sysFontReg.Name,"");


                            double lMargin = 72;
                            double rMargin = 72;
                            double tMargin = 50;
                            double bMargin = 72;
                            double tocTitleSpacing = 15;
                            double tocRowSpacing = 10;
                            double xPos = 0;
                            double yPos = 0;
                            double textLen = 0;
                            int numBM = 0;

                            bm = mergedPdf.GetFirstBookmark();
                            while (bm.IsValid())
                            {
                                numBM++;
                                bm = bm.GetNext();
                            }


                            eb.Reset();
                            eH = eb.CreateTextRun("Head", pdfFontBld, pts + ptsH);
                            eR = eb.CreateTextRun("Row", pdfFontReg, pts);

                            double pw = tocPage.GetPageWidth();
                            double ph = tocPage.GetPageHeight();

                            double tableSize = ph - tMargin - eH.GetGState().GetFontSize() - tocTitleSpacing - bMargin;
                            double rowSize = eR.GetGState().GetFontSize() + tocRowSpacing;
                            int rowsPerPage = (int)(tableSize / rowSize);
                            int tocPageCount = (int)(numBM / rowsPerPage);
                            if ((tocPageCount * rowsPerPage) < numBM)
                            {
                                tocPageCount++;
                            }
                            for (int i = 1; i < tocPageCount; i++)
                            {
                                Page p = mergedPdf.PageCreate();
                                if (mergedPdf.GetPageCount() < 2)
                                {
                                    mergedPdf.PagePushBack(p);
                                }
                                else
                                {
                                    mergedPdf.PageInsert(mergedPdf.GetPageIterator(tocIdx + 1), p);
                                }
                            }
                            //
                            // Create Table of Contents
                            //
                            bool newTocPage = true;
                            int curTocIdx = -1;
                            int curRowNum = 1;

                            bm = mergedPdf.GetFirstBookmark();
                            while (bm.IsValid())
                            {
                                if (newTocPage)
                                {
                                    curTocIdx++;
                                    tocPage = mergedPdf.GetPage(tocIdx + curTocIdx);
                                    ew.Begin(tocPage);
                                    eb.Reset();
                                    ew.WriteElement(eb.CreateTextBegin());
                                    yPos = ph - tMargin;
                                    if (curTocIdx == 0)
                                    {
                                        textValue = "Table of Contents";
                                    }
                                    else
                                    {
                                        textValue = "Table of Contents (cont.)";
                                    }
                                    e = eb.CreateTextRun(textValue);
                                    e.GetGState().SetHorizontalScale(100);
                                    e.GetGState().SetCharSpacing(1.25);
                                    e.GetGState().SetTextRenderMode(GState.TextRenderingMode.e_fill_stroke_text);
                                    textLen = e.GetTextLength();
                                    xPos = (pw / 2) - (textLen / 2);
                                    e.SetTextMatrix(1, 0, 0, 1, xPos, yPos);
                                    ew.WriteElement(e);
                                    yPos -= (eH.GetGState().GetFontSize() + tocTitleSpacing);
                                    curRowNum = 1;
                                    newTocPage = false;
                                    ew.WriteElement(eb.CreateTextEnd());
                                    ew.End();
                                }
                                ew.Begin(tocPage);
                                eb.Reset();
                                ew.WriteElement(eb.CreateTextBegin());
                                textValue = bm.GetTitle();
                                e = eb.CreateTextRun(textValue);
                                textLen = e.GetTextLength();
                                xPos = lMargin;
                                double max = pw - rMargin;
                                var tocInclPageNums = true;
                                if (tocInclPageNums) { max -= rMargin; }
                                while (xPos + textLen > max)
                                {
                                    textValue = textValue.Substring(0, textValue.Length - 1);
                                    e = eb.CreateTextRun(textValue + "...");
                                    textLen = e.GetTextLength();
                                }
                                e.SetTextMatrix(1, 0, 0, 1, xPos, yPos);
                                ew.WriteElement(e);

                                pdftron.PDF.Destination bmDest = bm.GetAction().GetDest();
                                pdftron.PDF.Page bmPage = bmDest.GetPage();
                                int pageNum = bmPage.GetIndex();
                                if (tocInclPageNums == true)
                                {
                                    textValue = bmPage.GetIndex().ToString();
                                    e = eb.CreateTextRun(textValue);
                                    textLen = e.GetTextLength();
                                    xPos = pw - rMargin - textLen;
                                    e.SetTextMatrix(1, 0, 0, 1, xPos, yPos);
                                    ew.WriteElement(e);
                                }
                                pdftron.PDF.Rect bmRect = new pdftron.PDF.Rect();
                                e.GetBBox(bmRect);
                                ew.WriteElement(eb.CreateTextEnd());
                                Obj stm = ew.End();

                                bmRect.x1 = lMargin;
                                bmRect.x2 = pw - rMargin;
                                pdftron.PDF.Annots.Link lnk = pdftron.PDF.Annots.Link.Create(mergedPdf, bmRect, bm.GetAction());
                                lnk.SetBorderStyle(new pdftron.PDF.Annot.BorderStyle(Annot.BorderStyle.Style.e_solid, 0));
                                tocPage.AnnotPushBack(lnk);

                                yPos -= (eR.GetGState().GetFontSize() + tocRowSpacing);
                                curRowNum++;
                                if (curRowNum > rowsPerPage)
                                {
                                    newTocPage = true;
                                }
                                bm = bm.GetNext();
                            }

                        }
                        catch (Exception ex)
                        {
                            throw new Exception("Generate Error(f):  " + ex.Message);
                        }
                        // Save the merged PDF
                        string outputFilePath = Path.Combine(fileDumpPath, "merged_output.pdf");
                        mergedPdf.Save(outputFilePath, SDFDoc.SaveOptions.e_remove_unused);
                        Console.WriteLine($"Merged PDF saved to: {outputFilePath}");
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"Error saving merged PDF: {ex.Message}");
                    }
                }

Hi sthakre,

Can you let me know what product and version you are using?

PDFTron - 10.6.0 with .net core

But when I am trying to add a bookmarks like table of contents, Cover page etc. then I am unable to do it.

I got the files you sent privately, and it worked fine for me. I tried the following.

  1. Opened test_paq_updated.pdf in Adobe Reader.
  2. Enabled Interactive elements (which for my Adobe Reader is disabled to start with).
  3. Navigated to page 2, the table of contents.
  4. There are Link annotations on that page, and if I click on say “Minutes” I am taken to page 3, the Minutes page, which seems perfectly fine to me.

Please describe exactly what is wrong.