Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Merging PDFs programatically while maintaining the "Combine files..." bookmark structure?

I originally asked this on Adobe's forums but yet to receive any reponses.

I have to merge a set of many (100+) PDF files into a single report on a weekly basis, and so far, I have been doing the process by hand by selecting the files, right clicking, and selecting "Combine supported files in Acrobat". What I would like to do is replicate this exact same process programmatically (preferrably in Excel/VBA, but C# or Batch commands are acceptable alternatives). I currently have code that will combine pdf files, but it it does not keep the bookmark structure the same way that "Combine supported files in Acrobat" does.

In other words, say I have three files called "A.pdf", "B.pdf", and "C.pdf", and each file contains two bookmarks called "Bkmrk 1" and "Bkmrk 2". I want to programatically combine these three files into a single file that has 9 bookmarks that look like the structure below:

A
    Bkmrk 1
    Bkmrk 2
B
    Bkmrk 1
    Bkmrk 2
C
    Bkmrk 1
    Bkmrk 2

I at first tried automating the process via the Acrobat SDK, but from what I understand the Acrobat SDK does not allow programs to interact with the dialog box that appears when you execute the "Combine Files" menu option, so that did not work. I also tried the option to programatically insert pages from one pdf file into another, but that does not produce the bookmark structure that I am looking for, nor does it let me manipulate the bookmark heirarchy to create the bookmark structure I am looking for.

Does anyone have an idea of how to do this? Any help would be greatly appreciated!

like image 937
random_guy7531 Avatar asked Apr 01 '11 13:04

random_guy7531


People also ask

How do I combine PDF files without losing bookmarks?

In the first picklist, select Combine files into one PDF. Click the Options button. Check Add file names as bookmarks. Click OK.

How do I combine PDFs into one file with bookmarks?

In Adobe Acrobat Pro click on “File” in the upper left hand corner. From this menu you will scroll down and select “Combine” > “Merge Files into a single PDF” from the pop-out menu. Drag and drop files to add them, and then arrange them in the order you want.

How do I bundle PDF files together?

Open Acrobat to combine files: Open the Tools tab and select "Combine files." Add files: Click "Add Files" and select the files you want to include in your PDF. You can merge PDFs or a mix of PDF documents and other files.

Does merging PDF reduce quality?

Inserting a PDF file into another or combining PDF files is normally a lossless operation.


1 Answers

This was pure hell to get working, so I'm happy to share what I've got. This was adapted from code I found here, and will merge files, and put bookmarks at each merge point:

Private mlngBkmkCounter     As Long

Public Sub updfConcatenate(pvarFromPaths As Variant, _
                           pstrToPath As String)

    Dim origPdfDoc      As Acrobat.CAcroPDDoc
    Dim newPdfDoc       As Acrobat.CAcroPDDoc
    Dim lngNewPageCount As Long
    Dim lngInsertPage   As Long
    Dim i               As Long

    Set origPdfDoc = CreateObject("AcroExch.PDDoc")
    Set newPdfDoc = CreateObject("AcroExch.PDDoc")
    mlngBkmkCounter = 0

    'set the first file in the array as the "new"'
    If newPdfDoc.Open(pvarFromPaths(LBound(pvarFromPaths))) = True Then
        updfInsertBookmark "Test Start", lngInsertPage, , newPdfDoc
        mlngBkmkCounter = 1

        For i = LBound(pvarFromPaths) + 1 To UBound(pvarFromPaths)
            Application.StatusBar = "Merging " & pvarFromPaths(i) & "..."
            If origPdfDoc.Open(pvarFromPaths(i)) = True Then
                lngInsertPage = newPdfDoc.GetNumPages
                newPdfDoc.InsertPages lngInsertPage - 1, origPdfDoc, 0, origPdfDoc.GetNumPages, False
                updfInsertBookmark "Test " & i, lngInsertPage, , newPdfDoc
                origPdfDoc.Close
                mlngBkmkCounter = mlngBkmkCounter + 1
            End If
        Next i
        newPdfDoc.Save PDSaveFull, pstrToPath
    End If

ExitHere:
    Set origPdfDoc = Nothing
    Set newPdfDoc = Nothing
    Application.StatusBar = False
    Exit Sub

End Sub

The insert-bookmark code... You would need to array your bookmarks from each document, and then set them

Public Sub updfInsertBookmark(pstrCaption As String, _
                              plngPage As Long, _
                     Optional pstrPath As String, _
                     Optional pMyPDDoc As Acrobat.CAcroPDDoc, _
                     Optional plngIndex As Long = -1, _
                     Optional plngParentIndex As Long = -1)

    Dim MyPDDoc         As Acrobat.CAcroPDDoc
    Dim jso             As Object
    Dim BMR             As Object
    Dim arrParents      As Variant
    Dim bkmChildsParent As Object
    Dim bleContinue     As Boolean
    Dim bleSave         As Boolean
    Dim lngIndex        As Long

    If pMyPDDoc Is Nothing Then
        Set MyPDDoc = CreateObject("AcroExch.PDDoc")
        bleContinue = MyPDDoc.Open(pstrPath)
        bleSave = True
    Else
        Set MyPDDoc = pMyPDDoc
        bleContinue = True
    End If

    If plngIndex > -1 Then
        lngIndex = plngIndex
    Else
        lngIndex = mlngBkmkCounter
    End If

    If bleContinue = True Then
        Set jso = MyPDDoc.GetJSObject
        Set BMR = jso.bookmarkRoot

        If plngParentIndex > -1 Then
            arrParents = jso.bookmarkRoot.Children
            Set bkmChildsParent = arrParents(plngParentIndex)
            bkmChildsParent.createchild pstrCaption, "this.pageNum= " & plngPage, lngIndex

        Else
            BMR.createchild pstrCaption, "this.pageNum= " & plngPage, lngIndex
        End If

        MyPDDoc.SetPageMode 3 '3 — display using bookmarks'

        If bleSave = True Then
            MyPDDoc.Save PDSaveIncremental, pstrPath
            MyPDDoc.Close
         End If
    End If

ExitHere:
    Set jso = Nothing
    Set BMR = Nothing
    Set arrParents = Nothing
    Set bkmChildsParent = Nothing
    Set MyPDDoc = Nothing
End Sub

To use:

Public Sub uTest_pdfConcatenate()

    Const cPath As String = "C:\MyPath\"

    updfConcatenate Array(cPath & "Test1.pdf", _
                          cPath & "Test2.pdf", _
                          cPath & "Test3.pdf"), "C:\Temp\TestOut.pdf"
End Sub
like image 183
downwitch Avatar answered Sep 23 '22 23:09

downwitch