【问题标题】:Merging PDFs programatically while maintaining the "Combine files..." bookmark structure?以编程方式合并 PDF,同时保持“合并文件...”书签结构?
【发布时间】:2011-07-27 17:11:45
【问题描述】:

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

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

换句话说,假设我有三个名为“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

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

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

【问题讨论】:

    标签: c# pdf vba batch-file excel


    【解决方案1】:

    开始工作简直就是地狱,所以我很高兴分享我所拥有的。这是改编自我找到的代码here,将合并文件,并在每个合并点放置书签:

    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
    

    插入书签代码...您需要从每个文档中排列书签,然后设置它们

    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
    

    使用方法:

    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
    

    【讨论】:

    • 我已验证此方法有效。它合并 PDF 文档并为每个新文件提供一个书签名称。我为自己修改了代码,使文件名成为书签名称。
    【解决方案2】:

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

    有 30 天的无限制试用期,所以如果它不适合您,您不会真的错过时间。

    【讨论】:

      【解决方案3】:

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

      马里奥

      【讨论】:

        【解决方案4】:

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

        没有什么特别应该做的。您只需一个接一个地附加所有文档即可。

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

        免责声明:我为图书馆供应商 Bit Miracle 工作。

        【讨论】:

          【解决方案5】:

          Acrobat SDK可以让您创建和阅读书签。检查您的 SDK API 参考:

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

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

          【讨论】:

            猜你喜欢
            • 2012-04-28
            • 2020-03-05
            • 2021-01-26
            • 2019-11-17
            • 2017-03-29
            • 1970-01-01
            • 2018-11-07
            • 1970-01-01
            • 2017-05-09
            相关资源
            最近更新 更多