Created
May 17, 2021 12:15
-
-
Save FurloSK/0f9dae1d6a5f29fb232eeb5325e96fc0 to your computer and use it in GitHub Desktop.
Combine, reverse or alternate PDF pages in Adobe Acrobat
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Combine, reverse or alternate PDF pages in Adobe Acrobat | |
// | |
// Original author: Planet PDF (http://www.planetpdf.com/) | |
// Modified by Jeff Baitis: | |
// added Acrobat 9 and Acrobat X compatibility; improved Collate function with status bar. | |
// Completely rewritten and tweaked by FurloSK. | |
// How to use: | |
// 1. Put this file into ~/Library/Application Support/Adobe/Acrobat/9.0/JavaScripts | |
// 2. Run Acrobat 9 | |
// 3. Execute the command from Edit menu | |
/* | |
Acrobat DC SDK Documentation (navigate to Javascript -> JavaScript for Acrobat API Reference -> JavaScript API): | |
https://help.adobe.com/en_US/acrobat/acrobat_dc_sdk/2015/HTMLHelp/ | |
*/ | |
// Add a menu item to reverse all pages in the active document | |
app.addMenuItem({cName: "Reverse document pages", cParent: "Edit", nPos: 1, cExec: "trusted_ReversePages();", cEnable: "event.rc = (event.target != null);"}); | |
// Add a menu item to collate with another document on the filesystem | |
app.addMenuItem({ cName: "Combine odd and even pages", cParent: "Edit", nPos: 2, cExec: "trusted_CollatePages();", cEnable: "event.rc = (event.target != null);"}); | |
// Add a menu item to combine two parts of document as alternating odd and even pages | |
app.addMenuItem({ cName: "Alternate document pages", cParent: "Edit", nPos: 3, cExec: "trusted_AlternateDocumentPages();", cEnable: "event.rc = (event.target != null);"}); | |
// ============================================================================ | |
// Reverse pages function | |
// ============================================================================ | |
trusted_ReversePages = app.trustedFunction(function() | |
{ | |
app.beginPriv(); // Explicitly raise privileges | |
var t = app.thermometer; | |
t.duration = this.numPages; | |
t.begin(); | |
for (i = this.numPages - 1; i >= 0; i--) | |
{ | |
t.value = (i-this.numPages)*-1; | |
this.movePage(i); | |
t.text = 'Moving page ' + (i + 1); | |
} | |
t.end(); | |
app.endPriv(); | |
}) | |
// ============================================================================ | |
// Collating pages function | |
// ============================================================================ | |
/* | |
Title: Collate Document | |
Author: FurloSK, https://www.furlo.sk | |
Purpose: User is prompted to select document to insert/collate. | |
Original author: Sean Stewart, ARTS PDF, www.artspdf.com | |
*/ | |
trusted_CollatePages = app.trustedFunction(function() | |
{ | |
var scriptName = 'Combine odd and even pages'; | |
// start script with raised privileges | |
app.beginPriv(); | |
console.show(); | |
console.clear(); | |
console.println('['+scriptName+']: Starting script.\n'); | |
app.alert({ | |
nIcon: 3, | |
cTitle: 'Combine Odd and Even pages', | |
cMsg: 'This tool will allow you to combine two documents together, alternating between their pages.\n\nThis is useful when you have two separate documents, one with odd and the other with even pages, and you need to put them together.\n\nIn the next dialog, select the document from which you want to insert pages into the document you have currently opened.\n\nIf you do not want to continue, just cancel the dialog.' | |
}); | |
// ask user for file to be inserted and save its path | |
var filePicker = app.browseForDoc(); | |
if (typeof filePicker === "undefined") { | |
return helper_endScript(scriptName); | |
} | |
var insertDocPath = filePicker.cPath; | |
// open selected file to get its number of pages | |
var insertDoc = app.openDoc({ | |
cPath: insertDocPath, | |
bHidden: true | |
}); | |
// count pages in both docs | |
var openedDocPages = this.numPages; | |
var insertDocPages = insertDoc.numPages; | |
// close selected document | |
insertDoc.closeDoc(); | |
console.println('Selected file to insert: "' + insertDocPath + '".'); | |
console.println('Opened document has ' + this.numPages + ' pages.'); | |
console.println('Selected document has ' + insertDocPages + ' pages.'); | |
// ask user where to start inserting pages (default: after first page) | |
var startPageResponse = app.response({ | |
cTitle: 'Choose starting page', | |
cQuestion: 'Enter the page number in opened document after which the first page of the selected document should be inserted (i.e., entering 1 will insert the first page of the selected document as a page 2 into the opened document).\nTo start inserting pages before page 1, enter 0.\n\nEnter number between 0 and ' + openedDocPages + '.', | |
cLabel: 'Destination page:', | |
cDefault: '1' | |
}); | |
if (startPageResponse === null) { | |
return helper_endScript(scriptName); | |
} | |
// parse page number and fix it for script purposes (Acrobat counts pages from 0) | |
var startPage = parseInt(startPageResponse); | |
if (startPage < 0 || startPage > openedDocPages) { | |
return helper_endScript(scriptName, 'Invalid page number.'); | |
} | |
startPage = startPage - 1; | |
// count number of "overflow pages" - these will simply be added | |
// at the end of opened document (and warning will be issued) | |
var excessPages = insertDocPages - openedDocPages + startPage; | |
var excessStart = insertDocPages - excessPages; | |
// prepare progress bar | |
var progressBar = app.thermometer; | |
progressBar.duration = insertDocPages; | |
progressBar.begin(); | |
// page insertion - actual work! | |
console.println('\n'); | |
console.println('Will insert ' + insertDocPages + ' pages from selected document after every other page of opened document starting with page ' + (startPage + 1) + '.'); | |
{ | |
// insert pages from selected document into opened document | |
for (var loadPage = 0; (loadPage < insertDocPages && loadPage < excessStart); loadPage++) { | |
// insert one page from selected document | |
this.insertPages(startPage + (loadPage * 2), insertDocPath, loadPage); | |
console.println(' Inserted page #' + (loadPage + 1) + ' of selected document as page ' + (startPage + 2 + (loadPage * 2)) + ' of opened document'); | |
} | |
// insert overflowing pages to the end of document | |
if (excessPages > 0) { | |
// insert all overflow pages to current end of opened document | |
this.insertPages(openedDocPages + excessStart - 1, insertDocPath, excessStart, insertDocPages - 1 /*excessStart + excessPages - 1*/); | |
console.println(' Warning: Appended ' + excessPages + ' overflowing pages to the end of opened document.'); | |
app.alert({ | |
nIcon: 1, | |
cTitle: 'Overflowing pages found', | |
cMsg: 'Selected document had ' + excessPages + ' more pages than the opened document. These were simply appended to the end of opened document.' | |
}); | |
} | |
} | |
// hide progress bar | |
progressBar.end(); | |
// end script and exit privileged context | |
console.println('\n'); | |
console.println('['+scriptName+']: Finished successfully.'); | |
app.endPriv(); | |
}) | |
// ============================================================================ | |
// Alternate document pages function | |
// ============================================================================ | |
trusted_AlternateDocumentPages = app.trustedFunction(function() | |
{ | |
var scriptName = 'Alternate document pages'; | |
// start script with raised privileges | |
app.beginPriv(); | |
console.show(); | |
console.clear(); | |
console.println('['+scriptName+']: Starting script.\n'); | |
app.alert({ | |
nIcon: 3, | |
cTitle: 'Alternate document pages', | |
cMsg: 'This tool will allow you to select part of document which will be distributed (or "spread") through the rest of the document. Each page of the selected interval of pages will be moved to every other page of the unselected part of document.\n\nThis is useful when you have odd pages together and even pages together in two separate parts of your document (e.g. first half of the document are odd pages, second half even pages, or vice versa) and you need to combine them to create a proper final document.\n\nFirst, you will have to select portion of document that should be moved. For this, you will be asked to provide numbers of first and last pages of its interval. Secondly, you will be asked where to start moving these pages.\n\nIf you do not want to continue, just cancel the next dialog.' | |
}); | |
// count pages in document | |
var openedDocPages = this.numPages; | |
console.println('Opened document has ' + this.numPages + ' pages.'); | |
// get beginning of interval of pages to move | |
var intervalStartResponse = app.response({ | |
cTitle: 'Choose first page to move', | |
cQuestion: 'Enter the page number which marks the beginning of the portion of document you want to move (i.e., the first page of the interval of pages that will be distributed over the rest of the document).\n\nEnter number between 1 and ' + openedDocPages + '.', | |
cLabel: 'First page to move:', | |
cDefault: parseInt(openedDocPages/2 + 1) | |
}); | |
if (intervalStartResponse === null) { | |
return helper_endScript(scriptName); | |
} | |
// parse page number | |
var intervalStart = parseInt(intervalStartResponse); | |
if (intervalStart < 0 || intervalStart > openedDocPages) { | |
return helper_endScript(scriptName, 'Invalid page number.'); | |
} | |
// get end of interval of pages to move | |
var intervalEndResponse = app.response({ | |
cTitle: 'Choose last page to move', | |
cQuestion: 'Enter the page number which marks the end of the portion of document you want to move (i.e., the last page of the interval of pages that will be distributed over the rest of the document)\n\nEnter number between ' + intervalStart + ' and ' + openedDocPages + '.', | |
cLabel: 'Last page to move:', | |
cDefault: openedDocPages | |
}); | |
if (intervalEndResponse === null) { | |
return helper_endScript(scriptName); | |
} | |
// parse page number | |
var intervalEnd = parseInt(intervalEndResponse); | |
if (intervalEnd > openedDocPages || intervalStart > intervalEnd) { | |
return helper_endScript(scriptName, 'Invalid page number.'); | |
} | |
// fix page numbers for script purposes (Acrobat counts pages from 0) | |
intervalStart = intervalStart - 1; | |
intervalEnd = intervalEnd - 1; | |
// count number of pages to move | |
var moveCount = intervalEnd - intervalStart + 1; | |
console.println('Chosen to move ' + moveCount + ' pages from page #' + (intervalStart + 1) + ' to page #' + (intervalEnd + 1) + '.'); | |
// ask user where to start inserting pages (default: after first page) | |
var destinationPageResponse = app.response({ | |
cTitle: 'Choose destination starting page', | |
cQuestion: 'Enter the page number after which the first page of the selected document part should be inserted (i.e., entering 1 will insert the first page of the selected document portion as a page 2).\nTo start inserting pages before page 1, enter 0.\n\nEnter number between 0 and ' + (openedDocPages - moveCount + 1) + '.', | |
cLabel: 'Destination page:', | |
cDefault: '1' | |
}); | |
if (destinationPageResponse === null) { | |
return helper_endScript(scriptName); | |
} | |
// parse destination page number and fix it for script purposes (Acrobat counts pages from 0) | |
var destinationPage = parseInt(destinationPageResponse); | |
if (destinationPage < 0 || destinationPage + moveCount - 1 > openedDocPages) { | |
return helper_endScript(scriptName, 'Invalid page number.'); | |
} | |
destinationPage = destinationPage - 1; | |
// count shift of pages | |
var moveShift = (destinationPage < intervalStart | |
? destinationPage - intervalStart + 1 | |
: destinationPage - intervalStart | |
); | |
console.println('Chosen to shift selected document part by ' + Math.abs(moveShift) + ' pages ' + (moveShift > 0 ? 'forward.' : 'backward.')); | |
// prepare progress bar | |
var progressBar = app.thermometer; | |
progressBar.duration = moveCount; | |
progressBar.begin(); | |
// page shifting - actual work! | |
console.println('\n'); | |
console.println('Going to move ' + moveCount + ' pages starting with page ' + (intervalStart + 1) + ' after every other page of document starting with page ' + (destinationPage + 1) + '.'); | |
{ | |
var srcPage = intervalStart; | |
var dstPage = destinationPage; | |
var toMove = moveCount; | |
// This is a tricky business, because shifting destionations can actually intersect | |
// with selected document portion that should be shifted. | |
// Some hints as to how the movePage() function works: | |
// this.movePage(1, 0); will put 2nd page after 1st (thus, no change) | |
// this.movePage(3, 3); will put 4th page after 4th (again, no change) | |
// this.movePage(2, 0); will put 3rd page after 1st (shift by -1) | |
// this.movePage(3, 4); will put 4th page after 5th (shift by +1) | |
for (var movePage = 0; movePage < moveCount; movePage++) { | |
this.movePage(srcPage, dstPage); | |
toMove--; | |
console.println(' Moved page #' + (srcPage + 1) + ' after page ' + (dstPage + 1) + '.'); | |
// calculate next moved page | |
if (dstPage < srcPage) { | |
dstPage = dstPage + 2; | |
srcPage++; | |
// destination collides with interval of to-be-moved pages -> jump over it | |
if (dstPage >= srcPage) { | |
dstPage += toMove; | |
} | |
} | |
else { | |
dstPage++; | |
} | |
} | |
} | |
// hide progress bar | |
progressBar.end(); | |
// end script and exit privileged context | |
console.println('\n'); | |
console.println('['+scriptName+']: Finished successfully.'); | |
app.endPriv(); | |
}) | |
function helper_endScript(scriptName, error) { | |
console.println('\n'); | |
console.println('['+scriptName+'] Script cancelled' + (!error ? ' by user.' : ': ' + error)); | |
if (!error) { | |
console.hide(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment