Skip to main content
carlk22442003
Participant
June 10, 2016
解決済み

Code to merge two PDFs of scanned book: one of odd pages, the other of the even pages.

  • June 10, 2016
  • 返信数 5.
  • 15369 ビュー

I am looking for an efficient way to merge two PDFs: one with all odd pages scanned from a book, one with all even pages. This question has been posted many times in many different forums.  I am unable to get the Javascript given in the following forum to work.  https://forums.adobe.com/thread/286654.  Generally, answers to this question are not helpful to me because 1) they provide instructions that apply to an earlier version of Adobe (I’m using Adobe Acrobat Pro DC), or 2) they involve purchasing software that I have found to be ineffective. A step by step post to complete code that can do the job and be pasted and saved as a custom command through the command Wizard (see the Jan 13, 2016 11:27 AM post at https://forums.adobe.com/thread/2063936, for an example of a good answer to a different question) would be much appreciated.  Thanks, Carl

解決に役立った回答 Karl Heinz Kremer

You can use a big portion of the script that was posted in the other thread and create a custom command out of it. It actually makes the script easier to understand, because all the "stuff" that is about adding menus and elevating the scripts rights is not necessary anymore.

See here for instructions about how to create a custom command in Acrobat DC:

Create Custom Commands in Adobe Acrobat DC Pro - KHKonsulting LLC

Instead of the sample code from the blog post, you would use this (which is really just a copy&paste from the original script):

    // create an array to use as the rect parameter in the browse for field

    var arRect = new Array();

    arRect[0] = 0;

    arRect[1] = 0;

    arRect[2] = 0;

    arRect[3] = 0;

    // create a non-visible form field to use as a browse for field

    var f = this.addField("txtFilename", "text", this.numPages - 1, arRect);

    f.delay = true;

    f.fileSelect = true;

    f.delay = false;

    // user prompted to select file to collate the open document with

    app.alert("Select the PDF file to merge with")

    // open the browse for dialog

    f.browseForFileToSubmit();

    var evenDocPath = f.value;

    var q = this.numPages;

    var t = app.thermometer;

    t.duration = q;

    t.begin();

    // insert pages from selected document into open document

    for (var i = 0; i < q; i++) {

        var j = i * 2;

        this.insertPages(j, evenDocPath, i);

        t.value = i;

        t.text = 'Inserting page ' + (i + 1);

    }

    t.end();

    // remove unused field

    this.removeField("txtFilename");

Given the instructions in my blog post, you should be able to create this custom command and run it. For running it, the important part is that you load the "odd" part of the document first, then start the custom command and then select the "even" part of the document.

返信数 5

Participant
September 6, 2025

Attached is modified script file to merge two documents generated separetely by a 1-sided scanner.

The pages of the Second document are merged in reverse order, becasue when you flip the stakc of paper and scan it the last reverse page becomes the first page int he scond doc.

The script will produce the result is in the correct page order as the original.
The script assumes that you ahev both documents open in acrobat - visible in two separate tabs.
Execute the custom command when the first documents (from pages) is in focus.

Setup the custom command and paste the script below into it. The file is uploaded as .txt instead of .js because the forum forbids files with .js extensions.

Participant
September 6, 2025

Hmm - in case the uploaded file is not available - here is the script:

function mergeAlternatePagesFromOpenDocs() {
try {
// Store reference to current document
var currentDoc = this;
var currentDocName = this.documentFileName;

// Get all currently open documents
var openDocs = [];
var docNames = [];

// Try to access open documents - this may require privileged context
if (typeof app.activeDocs === "undefined" || app.activeDocs === null) {
app.alert("Unable to access open documents.\n\nMake sure you have multiple PDFs open in Acrobat.", 1);
return;
}

// Collect all open documents except the current one
for (var i = 0; i < app.activeDocs.length; i++) {
var doc = app.activeDocs[i];
if (doc && doc.documentFileName !== currentDocName) {
openDocs.push(doc);
docNames.push(doc.documentFileName);
}
}

// Check if there are other open documents
if (openDocs.length === 0) {
app.alert("No other PDF documents are currently open.\n\nPlease open the PDF you want to merge with and try again.", 1);
return;
}

var selectedDoc = null;
var selectedIndex = -1;

// If only one other document is open, use it automatically
if (openDocs.length === 1) {
var response = app.alert("Merge with \"" + docNames[0] + "\"?\n\nDoc2 pages will be inserted in REVERSE order\n(Doc1-p1, Doc2-lastpage, Doc1-p2, Doc2-secondtolast, ...)", 2, 2);
if (response === 4) { // Yes button
selectedDoc = openDocs[0];
selectedIndex = 0;
} else {
app.alert("Operation cancelled.", 3);
return;
}
} else {
// Multiple documents open - let user choose
var dialog = {
selectedIdx: -1,

initialize: function(dialog) {
// Create list items object
var listItems = {};
for (var i = 0; i < docNames.length; i++) {
listItems[docNames[i]] = (-1);
}
dialog.load({
"list": listItems
});
},

commit: function(dialog) {
var results = dialog.store();
var listResults = results["list"];
for (var item in listResults) {
if (listResults[item] > 0) {
// Find the index by matching the name
for (var i = 0; i < docNames.length; i++) {
if (docNames[i] === item) {
this.selectedIdx = i;
break;
}
}
break;
}
}
},

description: {
name: "Select PDF to Merge",
align_children: "align_left",
width: 400,
height: 250,
elements: [
{
type: "static_text",
name: "Select a document to merge into \"" + currentDocName + "\":",
font: "dialog"
},
{
type: "list_box",
item_id: "list",
width: 380,
height: 150
},
{
type: "static_text",
name: "Selected document pages will be inserted in REVERSE order",
font: "dialog"
},
{
alignment: "align_fill",
type: "ok_cancel",
ok_name: "Merge",
cancel_name: "Cancel"
}
]
}
};

// Show the dialog
var dialogResult = app.execDialog(dialog);

if (dialogResult === "ok" && dialog.selectedIdx >= 0) {
selectedDoc = openDocs[dialog.selectedIdx];
selectedIndex = dialog.selectedIdx;
} else {
app.alert("Operation cancelled.", 3);
return;
}
}

// Verify we have a selected document
if (!selectedDoc || selectedIndex < 0) {
app.alert("No document selected. Operation cancelled.", 1);
return;
}

// Store the path of the selected document
var selectedDocPath = selectedDoc.path;
var selectedPages = selectedDoc.numPages;
var currentPages = currentDoc.numPages;

// Verify the path is valid
if (!selectedDocPath || selectedDocPath === "") {
app.alert("Warning: Document path not available. Attempting direct merge...", 3);
}

// Determine how many pairs we'll create
var maxPairs = Math.max(currentPages, selectedPages);

// Set up thermometer (progress bar)
var t = app.thermometer;
t.duration = maxPairs;
t.begin();

// We'll track the insertion offset as pages are added
var insertionOffset = 0;
var insertedCount = 0;

// Process each pair position
for (var i = 0; i < maxPairs; i++) {
try {
// For each position i:
// - Doc1 page is at index i (if it exists)
// - Doc2 page is at index (selectedPages - 1 - i) for reverse order

var doc2PageIndex = selectedPages - 1 - i;

// Only insert if Doc2 has a page at this position
if (doc2PageIndex >= 0) {
// Calculate where to insert this page
// It should go after the i-th page of doc1 (if it exists)
var insertPosition = i + 1 + insertionOffset;

// Make sure we don't exceed the document bounds
if (insertPosition > currentDoc.numPages) {
insertPosition = currentDoc.numPages;
}

// Insert the page from doc2 in reverse order
if (selectedDocPath && selectedDocPath !== "") {
currentDoc.insertPages(insertPosition - 1, selectedDocPath, doc2PageIndex, doc2PageIndex);
} else {
currentDoc.insertPages(insertPosition - 1, selectedDoc, doc2PageIndex, doc2PageIndex);
}

insertedCount++;
insertionOffset++; // We've added a page, so adjust offset
}

t.value = i;
t.text = 'Processing pair ' + (i + 1) + ' of ' + maxPairs;

} catch (pageError) {
console.println("Error inserting page from position " + doc2PageIndex + ": " + pageError.message);
// Continue with next page
}
}

// End thermometer
t.end();

// Check if any pages were inserted
if (insertedCount === 0) {
app.alert("Error: No pages could be inserted.\n\nThe selected document may be protected or corrupted.", 1);
return;
}

// Success message with example
var exampleText = "";
if (currentPages <= 3 && selectedPages <= 3) {
exampleText = "\n\nResult order example:\n";
for (var i = 0; i < currentPages; i++) {
exampleText += "Doc1-p" + (i + 1);
var revIndex = selectedPages - i;
if (revIndex > 0) {
exampleText += ", Doc2-p" + revIndex;
}
if (i < currentPages - 1) {
exampleText += ", ";
}
}
}

app.alert("Documents merged successfully!\n\n" +
"Original pages (Doc1): " + currentPages + "\n" +
"Inserted pages (Doc2): " + insertedCount + " of " + selectedPages + "\n" +
"Total pages: " + currentDoc.numPages +
exampleText, 3);

} catch (e) {
// More detailed error handling
var errorMsg = "Error: " + e.message;

if (e.message.indexOf("file") !== -1) {
errorMsg += "\n\nPossible causes:\n" +
"- The selected document may be protected\n" +
"- The file may be corrupted\n" +
"- Insufficient permissions\n\n" +
"Try saving both documents and reopening them.";
} else {
errorMsg += "\n\nMake sure you have at least two PDF documents open.";
}

app.alert(errorMsg, 1);
}
}

// Call the function
mergeAlternatePagesFromOpenDocs.call(this);

Participant
June 28, 2019

It is not working for me.

It is only inserting the first page of the document 2 in the document 1, nothing more.

Can you help me, Karl Heinz Kremer ?

Does anyone else know what the problem is?

Karl Heinz  Kremer
Community Expert
Community Expert
July 1, 2019

It worked for everybody else, so I would assume there is something wrong with your code. Are you getting any errors on the JavaScript console?

Participant
October 29, 2024

Hello Looking for google app script to  combine  multiple files in google drive ny using adobe api. need help on this. i can pay for this. 

Inspiring
August 20, 2018

One small point, which is obvious (but an idiot like me missed it): both documents need to have the same number of pages. If you didn't scan the last page because it was blank, the script will hang forever.

Karl Heinz  Kremer
Community Expert
Community Expert
June 10, 2016

You can use a big portion of the script that was posted in the other thread and create a custom command out of it. It actually makes the script easier to understand, because all the "stuff" that is about adding menus and elevating the scripts rights is not necessary anymore.

See here for instructions about how to create a custom command in Acrobat DC:

Create Custom Commands in Adobe Acrobat DC Pro - KHKonsulting LLC

Instead of the sample code from the blog post, you would use this (which is really just a copy&paste from the original script):

    // create an array to use as the rect parameter in the browse for field

    var arRect = new Array();

    arRect[0] = 0;

    arRect[1] = 0;

    arRect[2] = 0;

    arRect[3] = 0;

    // create a non-visible form field to use as a browse for field

    var f = this.addField("txtFilename", "text", this.numPages - 1, arRect);

    f.delay = true;

    f.fileSelect = true;

    f.delay = false;

    // user prompted to select file to collate the open document with

    app.alert("Select the PDF file to merge with")

    // open the browse for dialog

    f.browseForFileToSubmit();

    var evenDocPath = f.value;

    var q = this.numPages;

    var t = app.thermometer;

    t.duration = q;

    t.begin();

    // insert pages from selected document into open document

    for (var i = 0; i < q; i++) {

        var j = i * 2;

        this.insertPages(j, evenDocPath, i);

        t.value = i;

        t.text = 'Inserting page ' + (i + 1);

    }

    t.end();

    // remove unused field

    this.removeField("txtFilename");

Given the instructions in my blog post, you should be able to create this custom command and run it. For running it, the important part is that you load the "odd" part of the document first, then start the custom command and then select the "even" part of the document.

carlk22442003
carlk22442003作成者
Participant
June 15, 2016

Hi Karl,

Thanks for making that so incredibly easy, that worked perfectly.

Carl

try67
Community Expert
Community Expert
June 10, 2016

Well, if you're interested in a tool that is guaranteed to do it, and is compatible with Acrobat DC (although it's not free), check out this one I've developed: Custom-made Adobe Scripts: Acrobat -- Combine Even-Odd Pages