How to split WinForms PDF document based on each level of bookmarks?
The Syncfusion Essential® Winforms PDPDF is a feature-rich and high-performance .NET PDF library that is used to create, read, and edit PDF documents programmatically without Adobe dependencies. Using this library, you can split the PDF document based on each bookmarks using C# and VB.NET.
Steps to split the PDF document based on each bookmarks using C# programmatically
1. Create a new C# console application project.
2. Install the Syncfusion.PDF.WinForms NuGet packages as a reference to your .NET Framework application from NuGet.org.
3. Include the following namespaces in the Program.cs file.
C#
using Syncfusion.Pdf;
using Syncfusion.Pdf.Parsing;
using Syncfusion.Pdf.Interactive;
VB.NET
Imports Syncfusion.Pdf
Imports Syncfusion.Pdf.Parsing
Imports Syncfusion.Pdf.Interactive
4. The following code example shows how to split the PDF document based on each bookmarks using C#.
C#
//Load the PDF document
PdfLoadedDocument lDoc = new PdfLoadedDocument(@"../../Data/BookmarksPDF.pdf");
Dictionary<PdfPageBase, int> pages = new Dictionary<PdfPageBase, int>();
//Maintain collection for page and its index
for (int i = 0; i < lDoc.Pages.Count; i++)
{
PdfPageBase page = lDoc.Pages[i] as PdfPageBase;
pages.Add(page, i);
}
//Get all the bookmarks
PdfBookmarkBase bookmarks = lDoc.Bookmarks;
//Iterate throws all the bookmarks.
for (int i = 0; i < bookmarks.Count; i++)
{
//Get the bookmark.
PdfBookmark bk = bookmarks[i];
TotalBookmarks.Add(bk);
Getbookmark(bk);
}
//Create a dictionary with a bookmark and split up page range
List<SplitRange> splitRanges = new List<SplitRange>();
GetPageofBookmarks(lDoc, splitRanges, pages);
//Spit the PDF based on range of bookmark
for (int i = 0; i < splitRanges.Count; i++)
{
int startIndex = splitRanges[i].startIndex;
int endIndex = splitRanges[i].endIndex;
for (int j = 0; j < splitRanges.Count; j++)
{
if (splitRanges[j].startIndex > startIndex && splitRanges[j].endIndex <= endIndex)
{
splitRanges[i].endIndex = splitRanges[j].startIndex - 1; ;
}
}
//Create a new PDF document
PdfDocument document = new PdfDocument();
//Import the pages to the new PDF document
document.ImportPageRange(lDoc, startIndex, endIndex);
//Save the document in a specified folder
document.Save(DataPathOutput + "Output_" + i + ".pdf");
//Close the document
document.Close(true);
}
//Close the document
lDoc.Close(true);
splitRanges.Clear();
pages.Clear();
//Opens the folder where the output documents are saved
System.Diagnostics.Process.Start(DataPathOutput);
//Split bookmark with pages
private static List<SplitRange> GetPageofBookmarks(PdfLoadedDocument lDoc, List<SplitRange> splitRanges, Dictionary<PdfPageBase, int> pages)
{
for (int i = 0; i < TotalBookmarks.Count; i++)
{
if (TotalBookmarks[i].Destination != null)
{
PdfPageBase page = TotalBookmarks[i].Destination.Page;
if (pages.ContainsKey(page))
{
int startIndex = pages[page];
int endIndex = startIndex;
if (i + 1 < TotalBookmarks.Count && TotalBookmarks[i + 1].Destination != null)
{
page = TotalBookmarks[i + 1].Destination.Page;
if (pages[page] - 1 > startIndex)
endIndex = pages[page] - 1;
}
else
{
for (int j = 0; j < splitRanges.Count; j++)
{
int checkStartIndex = splitRanges[j].startIndex;
int checkEndIndex = splitRanges[j].endIndex;
if (endIndex > checkStartIndex && endIndex < checkEndIndex)
{
endIndex = checkEndIndex;
break;
}
else
endIndex = lDoc.Pages.Count - 1;
}
}
splitRanges.Add(new SplitRange() { bookmarkTitle = TotalBookmarks[i].Title, startIndex = startIndex, endIndex = endIndex });
}
}
}
return splitRanges;
}
//Get all level of bookmarks
public static void Getbookmark(PdfBookmark bookmark)
{
for (int i = 0; i < bookmark.Count; i++)
{
PdfBookmark bk = bookmark[i];
TotalBookmarks.Add(bk);
Getbookmark(bk);
}
}
VB.NET
'Load the PDF document
Dim lDoc As PdfLoadedDocument = New PdfLoadedDocument("../../Data/BookmarksPDF.pdf")
Dim pages As Dictionary(Of PdfPageBase, Integer) = New Dictionary(Of PdfPageBase, Integer)()
'Maintain collection for page and its index
For i As Integer = 0 To lDoc.Pages.Count - 1
Dim page As PdfPageBase = TryCast(lDoc.Pages(i), PdfPageBase)
pages.Add(page, i)
Next
'Get all the bookmarks
Dim bookmarks As PdfBookmarkBase = lDoc.Bookmarks
'Iterate throw all the bookmarks.
For i As Integer = 0 To bookmarks.Count - 1
'Get the bookmark.
Dim bk As PdfBookmark = bookmarks(i)
TotalBookmarks.Add(bk)
Getbookmark(bk)
Next
'Create a dictionary with a bookmark and split up page range
Dim splitRanges As List(Of SplitRange) = New List(Of SplitRange)()
GetPageofBookmarks(lDoc, splitRanges, pages)
'Spit the PDF based on range of bookmark
For i As Integer = 0 To splitRanges.Count - 1
Dim startIndex As Integer = splitRanges(i).startIndex
Dim endIndex As Integer = splitRanges(i).endIndex
For j As Integer = 0 To splitRanges.Count - 1
If splitRanges(j).startIndex > startIndex AndAlso splitRanges(j).endIndex <= endIndex Then
splitRanges(i).endIndex = splitRanges(j).startIndex - 1
End If
Next
'Create a new PDF document
Dim document As PdfDocument = New PdfDocument()
'Import the pages to the new PDF document
document.ImportPageRange(lDoc, startIndex, endIndex)
'Save the document in a specified folder
document.Save(DataPathOutput & "Output_" & i & ".pdf")
'Close the document
document.Close(True)
Next
'Close the document
lDoc.Close(True)
splitRanges.Clear()
pages.Clear()
'Opens the folder where the output documents are saved
System.Diagnostics.Process.Start(DataPathOutput)
'Split bookmark with pages
Private Function GetPageofBookmarks(ByVal lDoc As PdfLoadedDocument, ByVal splitRanges As List(Of SplitRange), ByVal pages As Dictionary(Of PdfPageBase, Integer)) As List(Of SplitRange)
For i As Integer = 0 To TotalBookmarks.Count - 1
If TotalBookmarks(i).Destination IsNot Nothing Then
Dim page As PdfPageBase = TotalBookmarks(i).Destination.Page
If pages.ContainsKey(page) Then
Dim startIndex As Integer = pages(page)
Dim endIndex As Integer = startIndex
If i + 1 < TotalBookmarks.Count AndAlso TotalBookmarks(i + 1).Destination IsNot Nothing Then
page = TotalBookmarks(i + 1).Destination.Page
If pages(page) - 1 > startIndex Then endIndex = pages(page) - 1
Else
For j As Integer = 0 To splitRanges.Count - 1
Dim checkStartIndex As Integer = splitRanges(j).startIndex
Dim checkEndIndex As Integer = splitRanges(j).endIndex
If endIndex > checkStartIndex AndAlso endIndex < checkEndIndex Then
endIndex = checkEndIndex
Exit For
Else
endIndex = lDoc.Pages.Count - 1
End If
Next
End If
splitRanges.Add(New SplitRange() With {
.bookmarkTitle = TotalBookmarks(i).Title,
.startIndex = startIndex,
.endIndex = endIndex
})
End If
End If
Next
Return splitRanges
End Function
'Get all level of bookmarks
Public Sub Getbookmark(ByVal bookmark As PdfBookmark)
For i As Integer = 0 To bookmark.Count - 1
Dim bk As PdfBookmark = bookmark(i)
TotalBookmarks.Add(bk)
Getbookmark(bk)
Next
End Sub
By executing the program, you will get the PDF document as follows.
A complete working sample can be downloaded from PdfBookmarkSplit.zip.
Take a moment to peruse the documentation. You can find other options like adding, Inserting, removing, and modifying bookmarks in an existing PDF document and features like named destination, interactive annotations, PDF form filling, and insert a hyperlink to PDF with code examples.
Refer to here to explore a rich set of Syncfusion Essential® PDF features.
An online sample link to Add Bookmarks.
Starting with v16.2.0.x, if you reference Syncfusion® assemblies from the trial setup or NuGet feed, include a license key in your projects. Refer to the link to learn about generating and registering the Syncfusion® license key in your application to use the components without trail message.
See Also:
https://help.syncfusion.com/file-formats/pdf/working-with-bookmarks
https://support.syncfusion.com/kb/article/8228/how-to-add-bookmarks-in-a-pdf-using-c-and-vb-net
https://support.syncfusion.com/kb/article/8368/how-to-get-bookmarks-from-a-pdf-using-c-and-vb-net
Conclusion
I hope you enjoyed learning about how to split WinForms PDF document based on each level of bookmarks.
For current customers, you can check out our components from the License and Downloads page. If you are new to Syncfusion®, you can try our 30-day free trial to check out our other controls.
If you have any queries or require clarifications, please let us know in the comments section below. You can also contact us through our support forums, Direct-Trac, or feedback portal. We are always happy to assist you!
How can we split just based on the top level only ? Your example will split all of bookmarks (top level, child, grand child, ...)
Or how can we choose which level of bookmark used splitting for ?