Friday, May 27, 2022

#1 2022-05-07 10:03:37 am

From:: Prescott, Arizona
Registered: 2018-09-04
Posts: 1327

Merge PDF Files

Recent versions of macOS have the native ability to merge PDF files, and a search of this forum will yield a number of scripts that perform this same function. I wrote and use the script included below because:

* It can be saved as an app and an icon can be placed on the Finder toolbar for frequent use.
* The script will optionally move the selected files to the trash after they are merged.
* The script includes a shorthand capability which can be tailored to the user's preference.

It is important to note that the order in which the selected PDFs are merged will differ, depending on the user's macOS version. In the last few versions of macOS, the files will be merged in the order they are selected, but, in older versions, the files will be merged in the order they are shown in the Finder (if memory serves).

The script's shorthand feature is controlled by two arrays at the top of the "getTargetFile" handler. For example, 


set searchStrings to current application's NSArray's arrayWithArray:{", ", "dx"}
set replaceStrings to current application's NSArray's arrayWithArray:{" - ", theDate()}

In this simple example, if the user enters the first line below, the actual file name will be the second line:

Work in progress, Peavine Products, dx
Work in progress - Peavine Products - 2022.05.07.pdf

To test this script, copy it to a script editor, select two or more PDF files in a Finder window, and run the script. I use this script frequently on my Monterey computer, but please test it with file copies to insure it works as expected.


-- Revised 2022.05.14

use framework "AppKit"
use framework "Foundation"
use framework "Quartz"
use scripting additions

on main()
   tell application "Finder" to set theFiles to selection as alias list
   set theFiles to current application's NSArray's arrayWithArray:theFiles
   set fileCount to theFiles's |count|()
   if fileCount < 2 then errorAlert("One or no files selected")
   set thePath to (theFiles's objectAtIndex:0)'s URLByDeletingLastPathComponent()
   set thePredicate to current application's NSPredicate's predicateWithFormat:"self.pathExtension !=[c] 'pdf'"
   set extensionCheck to (theFiles's filteredArrayUsingPredicate:thePredicate)'s |count|()
   if extensionCheck ≠ 0 then errorAlert("A selected file does not have a PDF extension")
   set {targetFile, deleteOption} to getTargetFile(thePath, fileCount)
   mergeFiles(theFiles, fileCount, targetFile)
   current application's NSWorkspace's sharedWorkspace()'s activateFileViewerSelectingURLs:{targetFile}
   if deleteOption = "Merge/Delete" then trashFiles(theFiles)
end main

on getTargetFile(thePath, fileCount)
   set searchStrings to current application's NSArray's arrayWithArray:{", ", ",", "dx"}
   set replaceStrings to current application's NSArray's arrayWithArray:{" - ", " - ", theDate()}
   display dialog "Enter a file name without extension for " & fileCount & " merged PDF files" default answer "Merged File Name" buttons {"Cancel", "Merge/Delete", "Merge"} cancel button 1 default button 3 with title "PDF Merge"
   set {targetName, deleteOption} to {text returned, button returned} of result
   if targetName = "" then errorAlert("A file name was not entered")
   set targetName to current application's NSString's stringWithString:targetName
   repeat with i from 0 to ((searchStrings's |count|()) - 1)
       set targetName to (targetName's stringByReplacingOccurrencesOfString:(searchStrings's objectAtIndex:i) withString:(replaceStrings's objectAtIndex:i))
   end repeat
   set targetFile to (thePath's URLByAppendingPathComponent:targetName)'s URLByAppendingPathExtension:"pdf"
   set fileExists to targetFile's checkResourceIsReachableAndReturnError:(missing value)
   if (fileExists as boolean) is true then errorAlert("A file with that name already exists")
   return {targetFile, deleteOption}
end getTargetFile

on theDate()
   set currentDate to current application's NSDate's |date|()
   set dateFormatter to current application's NSDateFormatter's new()
   dateFormatter's setDateFormat:"yyyy.MM.dd"
   return (dateFormatter's stringFromDate:currentDate) as text
end theDate

on mergeFiles(theFiles, fileCount, targetFile)
   set outDoc to current application's PDFDocument's alloc()'s initWithURL:(theFiles's objectAtIndex:0)
   set outDocPageCount to outDoc's pageCount()
   repeat with i from 1 to (fileCount - 1)
       set aDoc to (current application's PDFDocument's alloc()'s initWithURL:(theFiles's objectAtIndex:i))
       set aDocPageCount to aDoc's pageCount()
       repeat with j from 0 to (aDocPageCount - 1)
           (outDoc's insertPage:(aDoc's pageAtIndex:j) atIndex:outDocPageCount)
           set outDocPageCount to outDocPageCount + 1
       end repeat
   end repeat
   outDoc's writeToURL:targetFile
end mergeFiles

on trashFiles(theFiles)
   set fileManager to current application's NSFileManager's defaultManager()
   repeat with i from 0 to ((theFiles's |count|()) - 1)
       (fileManager's trashItemAtURL:(theFiles's objectAtIndex:i) resultingItemURL:(missing value) |error|:(missing value))
   end repeat
end trashFiles

on errorAlert(dialogMessage)
   display alert "An error has occurred" message dialogMessage as critical
   error number -128
end errorAlert


Last edited by peavine (2022-05-13 07:08:03 am)

2018 Mac mini - macOS Monterey - Script Debugger 8



Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)