vba 在保持“合并文件...”书签结构的同时以编程方式合并 PDF?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5514176/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 12:56:33  来源:igfitidea点击:

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

c#pdfvbabatch-fileexcel-vba

提问by random_guy7531

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

我最初在 Adob​​e 的论坛上问过这个问题,但尚未收到任何回复。

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.

我必须每周将一组许多(100 多个)PDF 文件合并到一个报告中,到目前为止,我一直通过选择文件、右键单击并选择“合并支持的文件在杂技演员”。我想做的是以编程方式复制这个完全相同的过程(最好在 Excel/VBA 中,但 C# 或 Batch 命令是可接受的替代方案)。我目前有将 pdf 文件合并的代码,但它不会像“在 Acrobat 中合并支持的文件”那样保持书签结构。

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.pdf”、“B.pdf”和“C.pdf”的文件,每个文件包含两个名为“Bkmrk 1”和“Bkmrk 2”的书签。我想以编程方式将这三个文件组合成一个具有 9 个书签的文件,其结构如下所示:

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.

我起初尝试通过 Acrobat SDK 自动化该过程,但据我所知,Acrobat SDK 不允许程序与执行“组合文件”菜单选项时出现的对话框进行交互,因此这不起作用。我还尝试了以编程方式将页面从一个 pdf 文件插入另一个文件的选项,但这不会产生我正在寻找的书签结构,也不能让我操纵书签层次结构来创建我正在寻找的书签结构。

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

有谁知道如何做到这一点?任何帮助将不胜感激!

回答by downwitch

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

回答by Mario The Spoon

Use iText# (http://www.itextpdf.com/). imho it is one of the best PDF-tools around. A code to do (approximately) what you want can be found here http://java-x.blogspot.com/2006/11/merge-pdf-files-with-itext.htmlDo not worry that all examples talk about Java, the classes and functions are the same in .NET

使用 iText# (http://www.itextpdf.com/)。恕我直言,它是最好的 PDF 工具之一。可以在此处找到(大约)您想要的代码http://java-x.blogspot.com/2006/11/merge-pdf-files-with-itext.html不要担心所有示例都在谈论 Java , .NET 中的类和函数是一样的

hth

Mario

马里奥

回答by Bobrovsky

Docotic.Pdf librarycan merge PDF files while maintaining outline (bookmarks) structure.

Docotic.Pdf 库可以在保持大纲(书签)结构的同时合并 PDF 文件。

There is nothing special should be done. You just append all documents one after another and that's all.

没有什么特别应该做的。您只需一个接一个地附加所有文档,仅此而已。

using (PdfDocument pdf = new PdfDocument())
{
    string[] filesToMerge = ...
    foreach (string file in filesToMerge)
        pdf.Append(file);

    pdf.Save("merged.pdf");
}

Disclaimer: I work for Bit Miracle, vendor of the library.

免责声明:我为该库的供应商 Bit Miracle 工作。

回答by Kev

You might need to consider a commercial tool such as Aspose.Pdf.Kitto get the level of flexibility you're after. It does support file concatenation and bookmark manipulation.

您可能需要考虑使用诸如Aspose.Pdf.Kit 之类的商业工具来获得您所追求的灵活性水平。它确实支持文件连接和书签操作。

There's a 30 day unlimited trial so you can't really lose out other than time if it doesn't work for you.

有 30 天的无限制试用,因此如果它对您不起作用,除了时间之外,您不会真正失去。

回答by Mark Storer

The Acrobat SDK doeslet you create and read bookmarks. Check your SDK API Reference for:

Acrobat SDK确实允许您创建和阅读书签。检查您的 SDK API 参考以了解:

PDDocGetBookmarkRoot()

PDBookmark* (AddChild, AddNewChild, GetNext, GetPrev... lots of functions in there)

If the "combine files" dialog doesn't give you the control you need, make your own dialog.

如果“组合文件”对话框没有为您提供所需的控制,请创建您自己的对话框。