2

I create an application, that merges multiple pdfs with a bookmark. If the origin pdfs already have bookmarks, I want to keep them and just add a bookmark at the beginning of the pdf. I use the following code: The title and the path in the code come from user input.

from PyPDF2 import PdfFileReader, PdfFileMerger
from PyPDF2.utils import PdfReadError

merger = PdfFileMerger()
pages_total = 0
for path, title in zip(paths, titles):
    merger.append(path, import_bookmarks=True)
    with open(path, "rb") as file:
           pdf = PdfFileReader(file, "rb")
           pages_one = pdf.getNumPages()
           pages_total += pages_one

    merger.addBookmark(f"{title}", pages_total - pages_one, parent=None)

 save_path = input() + ".pdf"  
 merger.write(save_path)
 merger.close()

The new pdf has all bookmarks, that points to the right pages. However, that bookmark for the entire pdf appears after the pdfs that already existed. How can I change the order in which the bookmarks are displayed?

The picture below hopefully clarifies the problem. The last bookmark was added and should be the first in the list.

enter image description here

Mazze
  • 383
  • 3
  • 13

1 Answers1

1

I found a solution. First I create a parent bookmark with the the pdf title. Then I get all existing bookmarks in the pdf with pdf.getOutlines() and iterate over the output:

parent = merger.addBookmark(f"{title}", pages_total - pages_one, parent=None)
for i in pdf.getOutlines():
     if isinstance(i, list):  # if nested bookmarks exists
         nested_boomarks(parent=child, bookmarks=i, merger=merger, pdf=pdf)
     else:
         child = merger.addBookmark(i["/Title"], pdf.getDestinationPageNumber(i), parent=parent)
                           

When there are bookmarks inside the bookmarks I use this recursive function.

def nested_boomarks(parent, bookmarks, merger, pdf):
        for i in bookmarks:
            if isinstance(i, list):
                nested_boomarks(child, i, merger, pdf)
            else:
                child = merger.addBookmark(i["/Title"], pdf.getDestinationPageNumber(i), parent=parent)

This way I get the following output: enter image description here

Mazze
  • 383
  • 3
  • 13