There are times when it is necessary to adjust the page indices of bookmarks in PDFs that link to other pages.. for instance, when combining two PDFs using PdfDocument.Combine .. the resulting output PDF will only contain the bookmark tree of the original first document.
To address this you need to walk the PdfBookmarkTree.Bookmarks and adjust the indices of any PdfIndexedPageReference objects
These are actually kind of deep down in the structure and it may not be entirely obvious where to look, so we've created this convenience method code for you
Convenience Method Code:
// <summary>
/// Iterates bookmark list and adjusts any PdfIndexedPageRference by a given offset
/// </summary>
/// <param name="bkMks" />The PdfBookmarkList to operate upon
/// <param name="pageOffset" />The number of pages to shift the index by
private static void ShiftPageNumbers(PdfBookmarkList bkMks, int pageOffset)
{
// Skip if the offset is 0 - its basically a no-op
if (pageOffset != 0)
{
foreach (PdfBookmark bm in bkMks)
{
// Each boomark can have multiple click actions so we loop
foreach (PdfAction rawAction in bm.ClickAction)
{
// we only want to operate on a very specific subtype of a specific subtype
if (rawAction.GetType() == typeof(PdfGoToViewAction))
{
PdfGoToViewAction action = rawAction as PdfGoToViewAction;
PdfPageReference rawPgRef = action.Destination.Page;
if (rawPgRef.GetType() == typeof(PdfIndexedPageReference))
{
PdfIndexedPageReference indexedRef = rawPgRef as PdfIndexedPageReference;
indexedRef.PageIndex = indexedRef.PageIndex + pageOffset;
}
}
}
}
}
}
Usage:
string finalOutFile = @"C:\pathTo\FINAL_combined.pdf";
string inFile1 = @"C:\pathTo\inFile1.pdf";
string inFile2 = @"C:\pathTo\inFile2.pdf";
string tempCombinedFile = @"C:\pathTo\tempFile.pdf":
PdfDocument.Combine(tempCombinedFile, new string[] { inFile1, file2});
PdfDocument destDoc = new PdfDocument(tempCombinedFile);
PdfDocument srcDoc = new PdfDocument(inFile2);
int pageOffset = destDoc.Pages.Count - srcDoc.Pages.Count;
ShiftPageNumbers(srcDoc.BookmarkTree.Bookmarks, pageOffset);
foreach(PdfBookmark bm in srcDoc.BookmarkTree.Bookmarks)
{
destDoc.BookmarkTree.Bookmarks.Add(bm);
}
destDoc.Save(finalOutFile);
File.Delete(tempCombinedFile);