Hi all,
I need to merge many PDF into a single PDF file. I have 5 PDFs with different contents. All i need to do is Merge these files into a single PDF file thru apple script. Any help?
-Rekha
Hi all,
I need to merge many PDF into a single PDF file. I have 5 PDFs with different contents. All i need to do is Merge these files into a single PDF file thru apple script. Any help?
-Rekha
Actually i need to do this thru Apple Script.
Hi
If you download it! then i think there is a few various scripts in the download which do what you want!!
You can also do it in Automator ( which you can if need have applescript run)
Actions:
Get selected finder Items.
Sort Finder Items:
Options ( by, comments.)( in, ascending order) (show Action When Run)
Combine PDF pages:
Options (Combine documents by, Appending pages)
Rename Finder Items : (I also chose not to ADD a copy )
Options ( choose what you want , I chose (Make Sequnetial, new name., place number after name)
)
Move Finder Items:
Options ( choose your options )
save as Finder Plugin,
Example:
I have two pdfs.
In the spotlight comments of the files (which is empty) I type a 1 in the file I want to be first and 2 in the one I want to be second.
Select the files and control click to get the contextual Automator pdf merger plugin, and run it.
I have the show sort options ticked. In case I want to change my method, but the one set is, ( by, comments.)( in, ascending order). So the file with a 1 in the spotlight comments will be first and the one with the 2 will be next, and so onâŚ
Hi Rekha,
as pidge said the use of joinPDF means that you can use just applescript and do shell scripts to combine pdfs and it works really well! I was looking to do the same thing as you a while ago and recently revisited it, and with some help in direction from the legend StefanK Iâve got it work! The Combine_PDFs handler is the part that you should look to incorporate in your script as it uses the joinPDF function. Hope this helps?
--try
tell application "Finder"
set sourcefolder to folder "Export_Objects:Downsample:Success" as alias
set inputfolder to folder "Export_Objects:Downsample:Input" as alias
set CombinedPDFfolder to folder "Export_Objects:Combined PDF" as alias
end tell
tell application "Finder"
set Success_PDF_List to name of every file of sourcefolder
if Success_PDF_List âⰠ{} then
set search_string to characters 1 thru 14 of item 1 of Success_PDF_List as string
else
error number -128
end if
set Input_PDF_List to name of every file of inputfolder
if Input_PDF_List = {} then
my Combine_PDFs(sourcefolder, search_string, CombinedPDFfolder)
else if (Input_PDF_List as string) contains search_string then
repeat until Input_PDF_List as string does not contain search_string
delay 30
set Input_PDF_List to name of every file of inputfolder
end repeat
my Combine_PDFs(sourcefolder, search_string, CombinedPDFfolder)
else if (Input_PDF_List as string) does not contain search_string then
my Combine_PDFs(sourcefolder, search_string, CombinedPDFfolder)
end if
end tell
on Combine_PDFs(sourcefolder, search_string, CombinedPDFfolder)
set startpath to (path to desktop as string) & "Export_Objects:temp" as alias
set startpathPOSIX to POSIX path of startpath
set filepath1 to (path to desktop as string) & "Export_Objects:Downsample:Success"
set filepath1POSIX to POSIX path of filepath1
set destpath to startpathPOSIX & search_string & "-" & "combined.pdf"
tell application "Finder"
set files_to_process to name of every file of the sourcefolder whose name contains search_string
set RawScript to "joinPDF " & "'" & destpath & "'" & space
repeat with thefile in files_to_process
set fullpath to "'" & filepath1POSIX & "/" & thefile & "'" & space
set RawScript to RawScript & "'" & filepath1POSIX & "/" & thefile & "'" & space
end repeat
end tell
do shell script RawScript
set deletescript to "rm "
repeat with thenewfile in files_to_process
set mynewfullpath to "'" & filepath1POSIX & "/" & thenewfile & "'" & space
set deletescript to deletescript & filepath1POSIX & "/" & thenewfile & space
end repeat
do shell script deletescript
set combinedPDF_alias to (path to desktop as string) & "Export_Objects:temp:" & search_string & "-" & "combined.pdf" as alias
tell application "Finder" to move combinedPDF_alias to CombinedPDFfolder with replacing
end Combine_PDFs
There is a very easy way to do this by using a python script from an Automator action:
Useable with do shell script.
As long as youâre running Mavericks or later, this will do it for you:
use scripting additions
use framework "Foundation"
use framework "Quartz" -- required for PDF stuff
set inFiles to (choose file of type {"pdf"} with prompt "Choose your PDF files:" with multiple selections allowed)
set destPosixPath to POSIX path of (choose file name default name "Combined.pdf" with prompt "Save new PDF to:")
its combineFiles:inFiles savingTo:destPosixPath
on combineFiles:inFiles savingTo:destPosixPath
-- make URL of the first PDF
set inNSURL to current application's class "NSURL"'s fileURLWithPath:(POSIX path of item 1 of inFiles)
-- make PDF document from the URL
set theDoc to current application's PDFDocument's alloc()'s initWithURL:inNSURL
-- loop through the rest
set oldDocCount to theDoc's pageCount()
set inFiles to rest of inFiles
repeat with aFile in inFiles
-- make URL of the next PDF
set inNSURL to (current application's class "NSURL"'s fileURLWithPath:(POSIX path of aFile))
-- make PDF document from the URL
set newDoc to (current application's PDFDocument's alloc()'s initWithURL:inNSURL)
-- loop through, moving pages
set newDocCount to newDoc's pageCount()
repeat with i from 1 to newDocCount
-- get page of old PDF
set thePDFPage to (newDoc's pageAtIndex:(i - 1)) -- zero-based indexes
-- insert the page
(theDoc's insertPage:thePDFPage atIndex:oldDocCount)
set oldDocCount to oldDocCount + 1
end repeat
end repeat
set outNSURL to current application's class "NSURL"'s fileURLWithPath:destPosixPath
-- save the new PDF
(theDoc's writeToURL:outNSURL)
end combineFiles:savingTo:
You will have to put it in a script library under Mavericks.
Hi Shane,
I would like to use your script but without having the operator rely on having to browse to the PDF files. For instance, I have a folder on the Desktop called âView PDFsâ that will always have 2 single-page PDFs. I have had no luck trying to modify your script whereas it would select all the files within my View PDFs folder. Is there anyway you could âPleaseâ help me out and modify your script so it can be hardcoded to where it selects all the files of a given folder without the need of a choose dialog?
Thanks in advance,
-Jeff
Something like:
use scripting additions
use framework "Foundation"
use framework "Quartz" -- required for PDF stuff
set inFolderPosix to POSIX path of ((path to desktop as text) & "View PDFs")
set destPosixPath to POSIX path of ((path to desktop as text) & "Combined.pdf")
its combineFilesIn:inFolderPosix savingTo:destPosixPath
on combineFilesIn:inFolderPosix savingTo:destPosixPath
set dirURL to current application's class "NSURL"'s fileURLWithPath:inFolderPosix
set theURLs to current application's NSFileManager's defaultManager()'s contentsOfDirectoryAtURL:dirURL includingPropertiesForKeys:{} options:(current application's NSDirectoryEnumerationSkipsHiddenFiles) |error|:(missing value)
-- make PDF document from the URL
set theDoc to current application's PDFDocument's alloc()'s initWithURL:(theURLs's firstObject())
-- loop through the rest
set oldDocCount to theDoc's pageCount()
repeat with i from 1 to ((theURLs's |count|()) - 1)
-- make URL of the next PDF
-- make PDF document from the URL
set newDoc to (current application's PDFDocument's alloc()'s initWithURL:(theURLs's objectAtIndex:i))
-- loop through, moving pages
set newDocCount to newDoc's pageCount()
repeat with i from 1 to newDocCount
-- get page of old PDF
set thePDFPage to (newDoc's pageAtIndex:(i - 1)) -- zero-based indexes
-- insert the page
(theDoc's insertPage:thePDFPage atIndex:oldDocCount)
set oldDocCount to oldDocCount + 1
end repeat
end repeat
set outNSURL to current application's class "NSURL"'s fileURLWithPath:destPosixPath
-- save the new PDF
(theDoc's writeToURL:outNSURL)
end combineFilesIn:savingTo:
AWESOME!!!
This works wonderfully.
Not sure if you need (or care) to know since you were obviously working quickly - I needed to change âinFolderâ to âinFolderPosixâ in the follow line:
set dirURL to current applicationâs class âNSURLâ's fileURLWithPath:inFolder
new line:
set dirURL to current applicationâs class âNSURLâ's fileURLWithPath:inFolderPosix
Thank you very much (once again) Shane!
-Jeff
This is basically the same, with an additional step that allow to visualise in a table several infos for the chosen PDFs, and the possibility to leave some of those PDFs out (so they wonât be part of the combined final PDF), and also to reorganise their order (by dragging them up or down) which will affect how they will be joined in final combined PDF.
I am sure it can be improvedâŚ
Ciao
L.
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
use framework "Foundation"
use framework "AppKit" -- for NSImage
use framework "Quartz" -- required for PDF stuff
use script "Myriad Tables Lib" version "1.0.9"
set inFiles to (choose file of type {"public.image", "com.adobe.pdf"} with prompt "Choose your files (images or PDFs):" with multiple selections allowed) -- is a list of alias
set destPosixPath to POSIX path of (choose file name default name "Combined.pdf" with prompt "Save new PDF to:") -- is a POSIX path
# let's order the files
# get information about contents
set {theJoin, theNames, theSizes, theKinds, theFiles} to {{}, {}, {}, {}, {}}
tell application "Finder"
repeat with i in inFiles
set end of theJoin to true
set end of theNames to displayed name of i
set end of theSizes to size of i
set end of theKinds to kind of i
set end of theFiles to i as alias
end repeat
end tell
-- convert from "columns" to "rows"
set theData to swap columns and rows in {theJoin, theNames, theSizes, theKinds, theFiles}
-- show table
set myTable to make new table with data theData column headings {"Join", "Name", "Size", "Kind"} with prompt "Choose files to join by checking the checkbox, and the order in which the files willl be joined by dragging them up or down." editable columns {1} with multiple selections allowed
modify table myTable with alternate backgrounds and row dragging
-- modify columns in table myTable date format "d MMM yyyy, H:mm"
modify columns in table myTable columns list {4} head alignment align center
modify columns in table myTable columns list {2} with bold type
set theResult to display table myTable
-- extract the files, which will be returned as file references
set theNames to extract column 5 from values selected of theResult
set NewList to extract column 5 from values returned of theResult
set NewList2 to {PDFName:extract column 5 from values returned of theResult, PDFValue:extract column 1 from values returned of theResult}
set NewList3 to {}
repeat with i in values returned of theResult
if item 1 of i then
set end of NewList3 to item 5 of i
end if
end repeat
my combineFiles:NewList3 savingToPDF:destPosixPath
on combineFiles:inFiles savingToPDF:destPosixPath
-- make URL of the first file
set inNSURL to current application's |NSURL|'s fileURLWithPath:(POSIX path of item 1 of inFiles)
-- make PDF document from the URL
if (inNSURL's pathExtension()'s isEqualToString:"pdf") as boolean then
set theDoc to current application's PDFDocument's alloc()'s initWithURL:inNSURL
else
set theDoc to my pdfDocFromImageURL:inNSURL
end if
-- loop through the rest
set oldDocCount to theDoc's pageCount()
set inFiles to rest of inFiles
repeat with aFile in inFiles
-- make URL of the next PDF
set inNSURL to (current application's |NSURL|'s fileURLWithPath:(POSIX path of aFile))
-- make PDF document from the URL
if (inNSURL's pathExtension()'s isEqualToString:"pdf") as boolean then
set newDoc to (current application's PDFDocument's alloc()'s initWithURL:inNSURL)
else
set newDoc to (my pdfDocFromImageURL:inNSURL)
end if
-- loop through, moving pages
set newDocCount to newDoc's pageCount()
repeat with i from 1 to newDocCount
-- get page of PDF
set thePDFPage to (newDoc's pageAtIndex:(i - 1)) -- zero-based indexes
-- insert the page into main PDF
(theDoc's insertPage:thePDFPage atIndex:oldDocCount)
set oldDocCount to oldDocCount + 1
end repeat
end repeat
set outNSURL to current application's |NSURL|'s fileURLWithPath:destPosixPath
-- save the main PDF
(theDoc's writeToURL:outNSURL)
end combineFiles:savingToPDF:
on pdfDocFromImageURL:inNSURL
set theImage to current application's NSImage's alloc()'s initWithContentsOfURL:inNSURL
set theSize to theImage's |size|()
set theRect to {{0, 0}, theSize}
set theImageView to current application's NSImageView's alloc()'s initWithFrame:theRect
theImageView's setImage:theImage
set theData to theImageView's dataWithPDFInsideRect:theRect
return current application's PDFDocument's alloc()'s initWithData:theData
end pdfDocFromImageURL:
The OP has a good solution and I wanted to raise a related matter. Iâm rewriting my PDF AppleScripts to use ASObjCâwhich Iâm just learningâand I had a question about error correction.
I ran Shaneâs script with 3 PDF files in the source folder and everything worked as expected. To introduce an error, I created a text file in the folder and changed its extension to PDF. I reran Shaneâs script and it threw an error:
What is the best way to handle this error? For now, I will include the code that calls the handler in a try statement, but this is a bit cumbersome because the handler is called at numerous points in my script. Thanks.
You can use a try, or a test for missing value:
if theDoc is missing value then -- something went wrong
Thanks Shane. I had this wrong. The line that causes the error is actually the prior line so this can be dealt with something like:
set theURLs to current application's NSFileManager's defaultManager()'s contentsOfDirectoryAtURL:dirURL includingPropertiesForKeys:{} options:(current application's NSDirectoryEnumerationSkipsHiddenFiles) |error|:(missing value)
if theURLs = missing value then -- catch error
display alert "The error message"
error number -128
end if
set theDoc to current application's PDFDocument's alloc()'s initWithURL:(theURLs's firstObject())
It can be more helpful if you sow the relevant error:
set {theURLs, theError} to current application's NSFileManager's defaultManager()'s contentsOfDirectoryAtURL:dirURL includingPropertiesForKeys:{} options:(current application's NSDirectoryEnumerationSkipsHiddenFiles) |error|:(reference)
if theURLs = missing value then -- catch error
display alert (theError's localizedDescription() as text)
error number -128
end if
Thanks Shane. Iâll use that.
This is proabably more of a question for Shane, since it involves his code below. I am wondering how the sequencing of the pages is determined. I have experienced mixed results on different machines in terms of what file becomes page 1 vs. page 2. For all intents and purposes - In my situation, I am always dealing with just 2 separate PDFs in the same folder on the desktop that is called âView PDFsâ - Inside that âView PDFsâ folder will always be two PDFs that are similarly named except for their filenameâs ending. For exmple, thsi folder will contain two spearare PDFs named as follows:
AD03103_side1.pdf
AD03103_side2.pdf
What I am seeking is a method to always have the file that contains âside1â become page 1, and the file containing âside2â to become page 2. However, I am not sure how to incorporate that logic into the code seen below. I understand this is a lot to ask - so if it cannot be easily done, please ignore.
Thanks,
-Jeff
use scripting additions
use framework "Foundation"
use framework "Quartz" -- required for PDF stuff
set inFolderPosix to POSIX path of ((path to desktop as text) & "View PDFs")
set destPosixPath to POSIX path of ((path to desktop as text) & "Combined.pdf")
its combineFilesIn:inFolderPosix savingTo:destPosixPath
on combineFilesIn:inFolderPosix savingTo:destPosixPath
set dirURL to current application's class "NSURL"'s fileURLWithPath:inFolderPosix
set theURLs to current application's NSFileManager's defaultManager()'s contentsOfDirectoryAtURL:dirURL includingPropertiesForKeys:{} options:(current application's NSDirectoryEnumerationSkipsHiddenFiles) |error|:(missing value)
-- make PDF document from the URL
set theDoc to current application's PDFDocument's alloc()'s initWithURL:(theURLs's firstObject())
-- loop through the rest
set oldDocCount to theDoc's pageCount()
repeat with i from 1 to ((theURLs's |count|()) - 1)
-- make URL of the next PDF
-- make PDF document from the URL
set newDoc to (current application's PDFDocument's alloc()'s initWithURL:(theURLs's objectAtIndex:i))
-- loop through, moving pages
set newDocCount to newDoc's pageCount()
repeat with i from 1 to newDocCount
-- get page of old PDF
set thePDFPage to (newDoc's pageAtIndex:(i - 1)) -- zero-based indexes
-- insert the page
(theDoc's insertPage:thePDFPage atIndex:oldDocCount)
set oldDocCount to oldDocCount + 1
end repeat
end repeat
set outNSURL to current application's class "NSURL"'s fileURLWithPath:destPosixPath
-- save the new PDF
(theDoc's writeToURL:outNSURL)
end combineFilesIn:savingTo:
Jeffkr. You directed your question to Shane but I couldnât resist responding, just FWIW.
It appears that your source folder contains only two PDFâs and if thatâs the case you might want to consider using the Finder. It returns the PDF files generally sorted by name and Finder has a sort function if youâd rather sort in some other manner. Finder can be abysmally slow but in this case it might be worth considering.
Anyways, my suggestion is:
use framework "Foundation"
use framework "Quartz"
use scripting additions
set sourceFolder to ((path to desktop as text) & "View PDFs:")
set targetFile to ((path to desktop as text) & "Combined.pdf")
tell application "Finder"
set sourceFiles to (every file in folder sourceFolder whose name ends with ".pdf") as alias list
end tell
mergeFiles(sourceFiles, targetFile)
on mergeFiles(sourceFiles, targetFile)
set firstFile to current application's class "NSURL"'s fileURLWithPath:(POSIX path of item 1 of sourceFiles)
set firstDoc to current application's PDFDocument's alloc()'s initWithURL:firstFile
set firstDocCount to firstDoc's pageCount()
repeat with anItem in (rest of sourceFiles)
set aFile to (current application's class "NSURL"'s fileURLWithPath:(POSIX path of anItem))
set aDoc to (current application's PDFDocument's alloc()'s initWithURL:aFile)
set aDocCount to aDoc's pageCount()
repeat with i from 1 to aDocCount
set thePDFPage to (aDoc's pageAtIndex:(i - 1))
(firstDoc's insertPage:thePDFPage atIndex:firstDocCount)
set firstDocCount to firstDocCount + 1
end repeat
end repeat
set mergedFile to current application's class "NSURL"'s fileURLWithPath:(POSIX path of targetFile)
(firstDoc's writeToURL:mergedFile)
end mergeFiles
Thank you very much Pavine,
I am pretty sure you are on the right track, however can you assist in modifying the script a bit further so it actually combines the 2 pdfs? It is probably just some syntax error?
use framework "Foundation"
use framework "Quartz"
use scripting additions
set sourceFolder to ((path to desktop as text) & "View PDFs")
set targetFile to ((path to desktop as text) & "Combined.pdf")
tell application "Finder"
set sourceFiles to (every file in folder sourceFolder whose name ends with ".pdf") as alias list
end tell
my mergeFiles(sourceFiles, targetFile)
on mergeFiles(sourceFiles, targetFile)
set firstFile to current application's class "NSURL"'s fileURLWithPath:(POSIX path of item 1 of sourceFiles)
set firstDoc to current application's PDFDocument's alloc()'s initWithURL:firstFile
set firstDocCount to firstDoc's pageCount()
repeat with anItem in (rest of sourceFiles)
set aFile to (current application's class "NSURL"'s fileURLWithPath:(POSIX path of anItem))
set aDoc to (current application's PDFDocument's alloc()'s initWithURL:aFile)
set aDocCount to aDoc's pageCount()
repeat with i from 1 to aDocCount
set thePDFPage to (aDoc's pageAtIndex:(i - 1))
(firstDoc's insertPage:thePDFPage atIndex:firstDocCount)
set firstDocCount to firstDocCount + 1
end repeat
end repeat
set mergedFile to current application's class "NSURL"'s fileURLWithPath:(POSIX path of targetFile)
(firstDoc's writeToURL:mergedFile)
end mergeFiles