VBA, объединить PDF файлы в один PDF файл
Я пытаюсь объединить PDF в один PDF файл с помощью vba. Я бы не хотел использовать инструмент plug-in и попытался использовать acrobat api ниже.
Я пробовал что-то вроде, но не могу заставить его работать. Я не получаю сообщение об ошибке, но, возможно, мне не хватает частей.
Любая помощь будет оценена по достоинству.
Sub Combine()
Dim n As Long, PDFfileName As String
n = 1
Do
n = n + 1
PDFfileName = Dir(ThisWorkbook.Path & "firstpdf" & n & ".pdf")
If PDFfileName <> "" Then
'Open the source document that will be added to the destination
objCAcroPDDocSource.Open ThisWorkbook.Path & "pathwithpdfs" & PDFfileName
If objCAcroPDDocDestination.InsertPages(objCAcroPDDocDestination.GetNumPages - 1, objCAcroPDDocSource, 0, objCAcroPDDocSource.GetNumPages, 0) Then
MsgBox "Merged " & PDFfileName
Else
MsgBox "Error merging " & PDFfileName
End If
objCAcroPDDocSource.Close
End If
Loop While PDFfileName <> ""
End Sub
новый код:
Новый код:
Sub main()
Dim arrayFilePaths() As Variant
Set app = CreateObject("Acroexch.app")
arrayFilePaths = Array("mypath.pdf", _
"mypath2.pdf")
Set primaryDoc = CreateObject("AcroExch.PDDoc")
OK = primaryDoc.Open(arrayFilePaths(0))
Debug.Print "PRIMARY DOC OPENED & PDDOC SET: " & OK
For arrayIndex = 1 To UBound(arrayFilePaths)
numPages = primaryDoc.GetNumPages() - 1
Set sourceDoc = CreateObject("AcroExch.PDDoc")
OK = sourceDoc.Open(arrayFilePaths(arrayIndex))
Debug.Print "SOURCE DOC OPENED & PDDOC SET: " & OK
numberOfPagesToInsert = sourceDoc.GetNumPages
OK = primaryDoc.InsertPages(numPages, sourceDoc, 0, numberOfPagesToInsert, False)
Debug.Print "PAGES INSERTED SUCCESSFULLY: " & OK
OK = primaryDoc.Save(PDSaveFull, arrayFilePaths(0))
Debug.Print "PRIMARYDOC SAVED PROPERLY: " & OK
Set sourceDoc = Nothing
Next arrayIndex
Set primaryDoc = Nothing
app.Exit
Set app = Nothing
MsgBox "DONE"
End Sub
Ответы
Ответ 1
Вам необходимо установить/использовать Adobe Acrobat.
Я использовал ссылки этого ресурса re
https://wwwimages2.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/iac_api_reference.pdf
EDIT: замена массива для автоматически генерируемого (в основном, основного PDF файла, заданного пользователем) списком путей к pdf файлам, которые вы хотите вставить в первичный pdf файл)
Вы можете использовать что-то вроде ниже, чтобы создать сборник документов, который будет вставлен в ваш основной документ. Первым файлом в collection
будет file
который вы вставляете, как и в первом примере. Затем назначьте путь папки к папке с files
PDF, которые вы хотели бы видеть вставленными в ваш основной документ, в inputDirectoryToScanForFile
. loop
в этом коде добавит путь к каждому файлу PDF в этой папке в вашу collection
. Это пути, которые позже используются в вызовах API adobe для вставки pdf в ваш основной.
Sub main()
Dim myCol As Collection
Dim strFile As String
Dim inputDirectoryToScanForFile As String
Dim primaryFile As String
Set myCol = New Collection
primaryFile = "C:\Users\Evan\Desktop\myPDf.Pdf"
myCol.Add primaryFile
inputDirectoryToScanForFile = "C:\Users\Evan\Desktop\New Folder\"
strFile = Dir(inputDirectoryToScanForFile & "*.pdf")
Do While strFile <> ""
myCol.Add strFile
strFile = Dir
Loop
End Sub
Код, который берет первичный файл и вставляет другие файлы PDF в этот файл:
Sub main()
Dim arrayFilePaths() As Variant
Set app = CreateObject("Acroexch.app")
arrayFilePaths = Array("C:\Users\Evan\Desktop\PAGE1.pdf", _
"C:\Users\Evan\Desktop\PAGE2.pdf", _
"C:\Users\Evan\Desktop\PAGE3.pdf")
Set primaryDoc = CreateObject("AcroExch.PDDoc")
OK = primaryDoc.Open(arrayFilePaths(0))
Debug.Print "PRIMARY DOC OPENED & PDDOC SET: " & OK
For arrayIndex = 1 To UBound(arrayFilePaths)
numPages = primaryDoc.GetNumPages() - 1
Set sourceDoc = CreateObject("AcroExch.PDDoc")
OK = sourceDoc.Open(arrayFilePaths(arrayIndex))
Debug.Print "SOURCE DOC OPENED & PDDOC SET: " & OK
numberOfPagesToInsert = sourceDoc.GetNumPages
OK = primaryDoc.InsertPages(numPages, sourceDoc, 0, numberOfPagesToInsert, False)
Debug.Print "PAGES INSERTED SUCCESSFULLY: " & OK
OK = primaryDoc.Save(PDSaveFull, arrayFilePaths(0))
Debug.Print "PRIMARYDOC SAVED PROPERLY: " & OK
Set sourceDoc = Nothing
Next arrayIndex
Set primaryDoc = Nothing
app.Exit
Set app = Nothing
MsgBox "DONE"
End Sub
Ответ 2
Это мое понимание вашего вопроса:
Требования:
• Объединенная серия PDF файлов, расположенных в одной и той же папке книги, содержащей процедуру
• Имена файлов Pdf переходят от firstpdf1.pdf
к firstpdfn.pdf
где n
- общее количество файлов, которые должны быть объединены
Давайте рассмотрим ваш исходный код:
• Все переменные должны быть объявлены:
Dim objCAcroPDDocSource as object, objCAcroPDDocDestination as object
• В этой строке отсутствует разделитель путей "\"
:
PDFfileName = Dir(ThisWorkbook.Path & "firstpdf" & n & ".pdf")
Он должен быть PDFfileName = Dir(ThisWorkbook.Path & "\" & "firstpdf" & n & ".pdf")
• Поэтому эта строка всегда возвращает ""
(в файле ThisWorkbook.Path
файл pdf не найден):
If PDFfileName <> "" Then
Дополнительно:
• Эти строки вернутся: Error - 424 Object required
для объектов objCAcroPDDocSource
и objCAcroPDDocDestination
не был инициализирован:
objCAcroPDDocSource.Open ThisWorkbook.Path & "pathwithpdfs" & PDFfileName
If objCAcroPDDocDestination.InsertPages(objCAcroPDDocDestination.GetNumPages - 1, objCAcroPDDocSource, 0, objCAcroPDDocSource.GetNumPages, 0) Then
objCAcroPDDocSource.Close
• objCAcroPDDocDestination
никогда не открывался.
Решения: эти процедуры используют библиотеку Adobe Acrobat
Библиотека Adobe Acrobat - ранняя граница
Для того, чтобы создать Reference Vb в Adobe библиотеку в редакторе VBA меню нажмите Tools
"Ссылки then select the
Adobe Acrobat Library in the dialog window then press the
, in the dialog window then press the
OK" кнопку.
Sub PDFs_Combine_EarlyBound()
Dim PdfDst As AcroPDDoc, PdfSrc As AcroPDDoc
Dim sPdfComb As String, sPdf As String
Dim b As Byte
Rem Set Combined Pdf filename - save the combined pdf in a new file in order to preserve original pdfs
sPdfComb = ThisWorkbook.Path & "\" & "Pdf Combined" & Format(Now, " mmdd_hhmm ") & ".pdf" 'change as required
Rem Open Destination Pdf
b = 1
sPdf = ThisWorkbook.Path & "\" & "firstpdf" & b & ".pdf"
Set PdfDst = New AcroPDDoc
If Not (PdfDst.Open(sPdf)) Then
MsgBox "Error opening destination pdf:" & vbCrLf _
& vbCrLf & "[" & sPdf & "]" & vbCrLf _
& vbCrLf & vbTab & "Procees will be cancelled!", vbCritical
Exit Sub
End If
Do
Rem Set & Validate Source Pdf
b = b + 1
sPdf = ThisWorkbook.Path & "\" & "firstpdf" & b & ".pdf"
If Dir(sPdf, vbArchive) = vbNullString Then Exit Do
Rem Open Source Pdf
Set PdfSrc = New AcroPDDoc
If Not (PdfSrc.Open(sPdf)) Then
MsgBox "Error opening source pdf:" & vbCrLf _
& vbCrLf & "[" & sPdf & "]" & vbCrLf _
& vbCrLf & vbTab & "Procees will be cancelled!", vbCritical
GoTo Exit_Sub
End If
With PdfDst
Rem Insert Source Pdf pages
If Not (.InsertPages(-1 + .GetNumPages, PdfSrc, 0, PdfSrc.GetNumPages, 0)) Then
MsgBox "Error inserting source pdf:" & vbCrLf _
& vbCrLf & "[" & sPdf & "]" & vbCrLf _
& vbCrLf & vbTab & "Procees will be cancelled!", vbCritical
GoTo Exit_Sub
End If
Rem Save Combined Pdf
If Not (.Save(PDSaveFull, sPdfComb)) Then
MsgBox "Error saving combined pdf:" & vbCrLf _
& vbCrLf & "[" & sPdfComb & "]" & vbCrLf _
& vbCrLf & vbTab & "Procees will be cancelled!", vbCritical
GoTo Exit_Sub
End If
PdfSrc.Close
Set PdfSrc = Nothing
End With
' sPdf = Dir(sPdf, vbArchive)
' Loop While sPdf <> vbNullString
Loop
MsgBox "Pdf files combined successfully!", vbExclamation
Exit_Sub:
PdfDst.Close
End Sub
Библиотека Adobe Acrobat - Поздняя ссылка
Нет необходимости создавать ссылку Vb для библиотеки Adobe
Sub PDFs_Combine_LateBound()
Dim PdfDst As Object, PdfSrc As Object
Dim sPdfComb As String, sPdf As String
Dim b As Byte
Rem Set Combined Pdf filename - save the combined pdf in a new file in order to preserve original pdfs
sPdfComb = ThisWorkbook.Path & "\" & "Pdf Combined" & Format(Now, " mmdd_hhmm ") & ".pdf" 'change as required
Rem Open Destination Pdf
b = 1
sPdf = ThisWorkbook.Path & "\" & "firstpdf" & b & ".pdf"
Set PdfDst = CreateObject("AcroExch.PDDoc")
If Not (PdfDst.Open(sPdf)) Then
MsgBox "Error opening destination pdf:" & vbCrLf _
& vbCrLf & "[" & sPdf & "]" & vbCrLf _
& vbCrLf & vbTab & "Procees will be cancelled!", vbCritical
Exit Sub
End If
Do
Rem Set & Validate Source filename
b = b + 1
sPdf = ThisWorkbook.Path & "\" & "firstpdf" & b & ".pdf"
If Dir(sPdf, vbArchive) = vbNullString Then Exit Do
Rem Open Source filename
Set PdfSrc = CreateObject("AcroExch.PDDoc")
If Not (PdfSrc.Open(sPdf)) Then
MsgBox "Error opening source pdf:" & vbCrLf _
& vbCrLf & "[" & sPdf & "]" & vbCrLf _
& vbCrLf & vbTab & "Procees will be cancelled!", vbCritical
GoTo Exit_Sub
End If
With PdfDst
Rem Insert Source filename pages
If Not (.InsertPages(-1 + .GetNumPages, PdfSrc, 0, PdfSrc.GetNumPages, 0)) Then
MsgBox "Error inserting source pdf:" & vbCrLf _
& vbCrLf & "[" & sPdf & "]" & vbCrLf _
& vbCrLf & vbTab & "Procees will be cancelled!", vbCritical
GoTo Exit_Sub
End If
Rem Save Combined Pdf
If Not (.Save(1, sPdfComb)) Then
MsgBox "Error saving combined pdf:" & vbCrLf _
& vbCrLf & "[" & sPdfComb & "]" & vbCrLf _
& vbCrLf & vbTab & "Procees will be cancelled!", vbCritical
GoTo Exit_Sub
End If
PdfSrc.Close
Set PdfSrc = Nothing
End With
' sPdf = Dir(sPdf, vbArchive)
' Loop While sPdf <> vbNullString
Loop
MsgBox "Pdf files combined successfully!", vbExclamation
Exit_Sub:
PdfDst.Close
End Sub
Ответ 3
Приведенный ниже код, полученный при переполнении стека, перечислит все подпапки в папке.
Sub FolderNames()
'Update 20141027
Application.ScreenUpdating = False
Dim xPath As String
Dim xWs As Worksheet
Dim fso As Object, j As Long, folder1 As Object
With Application.FileDialog(msoFileDialogFolderPicker)
.Title = "Choose the folder"
.Show
End With
On Error Resume Next
xPath = Application.FileDialog(msoFileDialogFolderPicker).SelectedItems(1) & "\"
'Application.Workbooks.Add
Set xWs = Application.ActiveSheet
Sheets("Sheet1").Cells.Clear
xWs.Cells(1, 1).Value = xPath
xWs.Cells(2, 1).Resize(1, 5).Value = Array("Path", "Dir", "Name", "Date Created", "Date Last Modified")
Set fso = CreateObject("Scripting.FileSystemObject")
Set folder1 = fso.GetFolder(xPath)
getSubFolder folder1
xWs.Cells(2, 1).Resize(1, 5).Interior.Color = 65535
xWs.Cells(2, 1).Resize(1, 5).EntireColumn.AutoFit
Application.ScreenUpdating = True
End Sub
Sub getSubFolder(ByRef prntfld As Object)
Dim SubFolder As Object
Dim subfld As Object
Dim xRow As Long
For Each SubFolder In prntfld.SubFolders
xRow = Range("A1").End(xlDown).Row + 1
Cells(xRow, 1).Resize(1, 5).Value = Array(SubFolder.Path, Left(SubFolder.Path, InStrRev(SubFolder.Path, "\")), SubFolder.Name, SubFolder.DateCreated, SubFolder.DateLastModified)
Next SubFolder
For Each subfld In prntfld.SubFolders
getSubFolder subfld
Next subfld
End Sub
Этот код объединит все файлы PDF в подпапке и сохранит выходные данные в выбранной папке назначения.
Sub Merger()
Dim i As Integer
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("Sheet1")
Dim k As Integer
Dim st As String
Dim na As String
Dim dest As String
With Application.FileDialog(msoFileDialogFolderPicker)
.Title = "Choose the Destination folder"
.Show
End With
dest = Application.FileDialog(msoFileDialogFolderPicker).SelectedItems(1) & "\"
k = sh.Range("A1048576").End(xlUp).Row
For i = 3 To k
st = sh.Cells(i, 1).Value
na = sh.Cells(i, 3).Value
Call Main(st, na, dest)
Next
MsgBox "The resulting files are created" & vbLf & p & DestFile, vbInformation, "Done"
End Sub
Sub Main(ByVal st As String, ByVal na As String, dest As String)
Dim DestFile As String
DestFile = "" & dest & na & ".pdf" ' <-- change TO Your Required Desitination
Dim MyPath As String, MyFiles As String
Dim a() As String, i As Long, f As String
Dim R As Range
Dim ws As Worksheet
Dim n As Long
' Choose the folder or just replace that part by: MyPath = Range("E3")
With Application.FileDialog(msoFileDialogFolderPicker)
'.InitialFileName = "C:\Temp\"
.AllowMultiSelect = True
'If .Show = False Then Exit Sub
MyPath = st
DoEvents
End With
' Populate the array a() by PDF file names
If Right(MyPath, 1) <> "\" Then MyPath = MyPath & "\"
ReDim a(1 To 2 ^ 14)
f = Dir(MyPath & "*")
While Len(f)
If StrComp(f, DestFile, vbTextCompare) Then
i = i + 1
a(i) = f
'a().Sort
End If
f = Dir()
Wend
'SORTING--------------------------------------------------------
Set ws = ThisWorkbook.Sheets("Sheet2")
' put the array values on the worksheet
Set R = ws.Range("A1").Resize(UBound(a) - LBound(a) + 1, 1)
R = Application.Transpose(a)
' sort the range
R.Sort key1:=R, order1:=xlAscending, MatchCase:=False
' load the worksheet values back into the array
For n = 1 To R.Range("A1048576").End(xlUp).Row
a(n) = R(n, 1)
Next n
If i Then
ReDim Preserve a(1 To i)
MyFiles = Join(a, ",")
Application.StatusBar = "Merging, please wait ..."
Call MergePDFs(MyPath, MyFiles, DestFile)
Application.StatusBar = False
Else
MsgBox "No PDF files found in" & vbLf & MyPath, vbExclamation, "Canceled"
End If
End Sub
'ZVI: 2013-08-27 http://www.vbaexpress.com/forum/showthread.php?47310-Need-code-to-merge-PDF-files-in-a-folder-using-adobe-acrobat-X
'Требуется ссылка: VBE - Инструменты - Ссылки - Acrobat
Sub MergePDFs(MyPath As String, MyFiles As String, Optional DestFile As String)
Dim a As Variant, i As Long, n As Long, ni As Long, p As String
Dim AcroApp As New Acrobat.AcroApp, PartDocs() As Acrobat.CAcroPDDoc
If Right(MyPath, 1) = "\" Then p = MyPath Else p = MyPath & "\"
a = Split(MyFiles, ",")
ReDim PartDocs(0 To UBound(a))
On Error GoTo exit_
If Len(Dir(DestFile)) Then Kill p & DestFile
For i = 0 To UBound(a)
' Check PDF file presence
If Dir(p & Trim(a(i))) = "" Then
MsgBox "File not found" & vbLf & p & a(i), vbExclamation, "Canceled"
Exit For
End If
' Open PDF document
Set PartDocs(i) = CreateObject("AcroExch.PDDoc")
PartDocs(i).Open p & Trim(a(i))
If i Then
' Merge PDF to PartDocs(0) document
ni = PartDocs(i).GetNumPages()
If Not PartDocs(0).InsertPages(n - 1, PartDocs(i), 0, ni, True) Then
MsgBox "Cannot insert pages of" & vbLf & p & a(i), vbExclamation, "Canceled"
End If
' Calc the number of pages in the merged document
n = n + ni
' Release the memory
PartDocs(i).Close
Set PartDocs(i) = Nothing
Else
' Calc the number of pages in PartDocs(0) document
n = PartDocs(0).GetNumPages()
End If
Next
If i > UBound(a) Then
' Save the merged document to DestFile
If Not PartDocs(0).Save(PDSaveFull, DestFile) Then
MsgBox "Cannot save the resulting document" & vbLf & p & DestFile, vbExclamation, "Canceled"
End If
End If
exit_:
' Inform about error/success
If Err Then
MsgBox Err.Description, vbCritical, "Error #" & Err.Number
ElseIf i > UBound(a) Then
'MsgBox "The resulting file is created:" & vbLf & p & DestFile, vbInformation, "Done"
End If
' Release the memory
If Not PartDocs(0) Is Nothing Then PartDocs(0).Close
Set PartDocs(0) = Nothing
' Quit Acrobat application
AcroApp.Exit
Set AcroApp = Nothing
End Sub
Ответ 4
У меня нет точной оценки для вашей проблемы, однако у меня был подобный, а именно, что я хотел добавить поля в pdf от VBA.
Я могу сказать вам, что Adobe имеет JavaScript API, который вы можете контролировать через vba.
Вот ссылка на API https://www.adobe.com/devnet/acrobat/javascript.html
И это часть кода, который я использовал в VBA для управления полями в PDF файлах.
Set app = CreateObject("Acroexch.app")
app.Show
Set AVDoc = CreateObject("AcroExch.AVDoc")
Set AForm = CreateObject("AFormAut.App") 'from AFormAPI
AVDoc.Open(pathsdf, "")
Ex = "Put your JavaScript Code here"
AForm.Fields.ExecuteThisJavaScript Ex
Вероятно, вам стоит посмотреть на метод insertPages в API.
Все, что возможно, это использование сборки в ссылке с VBA на Acrobat. Тем не менее, я нашел его очень ограниченным, и я не работал с ним. Есть только несколько доступных объектов, вот несколько примеров:
Dim AcroApp As Acrobat.AcroApp
Dim objAcroAVDoc As New Acrobat.AcroAVDoc
Dim objAcroPDDoc As Acrobat.AcroPDDoc
Dim objAcroPDPage As Acrobat.AcroPDPage
Dim annot As Acrobat.AcroPDAnnot