Skip to main content
Participating Frequently
November 6, 2009
Answered

Script to reorder pages?

  • November 6, 2009
  • 2 replies
  • 10303 views

I'm looking for a script to reorder the pages in a large document (a few hundred pages).

I need to be able to create the new order based on the old page numbers [for example: I need to specify that the new order should be 100, 212, 3, 9, 178.... all referencing the original page numbers.] When I move pages manually the old page numbers are no longer valid, which is why I can't do it manually.

Anyone that's seen/written such a script is invited to reply, as well as anyone who'd be willing to try writing one.  Thanks.

This topic has been closed for replies.
Correct answer Jongware

Hey, that was far more hard than I thought!

This script appears to be working -- but, admittedly, I only tested it with a 20-page document and some random reiterations. Run on a copy of your document, and holler if it ain't right. (And, boyo, do I hope it works ...)

You can fill in your new order in the first line, comma separated. You can also enter a range, like "5-10", if you happen to have a few pages in the original order. All numbers should be entered inbetween the quotes on one single line.

var order="1,20,2,19,3,18,4,17,5,16,6,15,7,14,8,13,9,12,10,11";

// Create an array out of the list:
ranges = toSeparate (order);

if (ranges.length != app.activeDocument.pages.length)
{
alert ("Page number mismatch -- "+ranges.length+" given, "+app.activeDocument.pages.length+" in document");
exit(0);
}

// Consistency check:
sorted = ranges.slice().sort(numericSort);
for (a=0; a<sorted.length-1; a++)
{
if (sorted < sorted[a+1]-1 ||
  sorted
== sorted[a+1])
  alert ("Mismatch from "+sorted
+" to "+sorted[a+1]);
}
// alert ("New order for "+order+"\nis "+ranges.join(", "));

// Convert from 1..x to 0..x-1:
for (moveThis=0; moveThis<ranges.length; moveThis++)
ranges[moveThis]--;

for (moveThis=0; moveThis<ranges.length; moveThis++)
{
if (moveThis != ranges[moveThis])
{
  try{
   app.activeDocument.pages[ranges[moveThis]].move (LocationOptions.BEFORE, app.activeDocument.pages[moveThis]);
  } catch(_) { alert ("problem with page "+moveThis+"/index "+ranges[moveThis]); }
}
for (updateRest=moveThis+1; updateRest<ranges.length; updateRest++)
  if (ranges[updateRest] < ranges[moveThis])
   ranges[updateRest]++;
}

function toSeparate (list)
{
s = list.split(",");
for (l=0; l<s.length; l++)
{
  try {
  if (s.indexOf("-") > -1)
  {
   indexes = s.split("-");
   from = Number(indexes[0]);
   to = Number(indexes[indexes.length-1]);
   if (from >= to)
   {
    alert ("Cannot create a range from "+from+" to "+to+"!");
    exit(0);
   }
   s = from;
   while (from < to)
    s.splice (++l,0,++from);
  }} catch(_){}
}
// s.sort (numericSort);
return s;
}

function numericSort(a,b)
{
return Number(a) - Number(b);
}

Copy and paste into a plain text editor -- the ESTK Editor that comes with InDesign is okay -- and save as "rearrangePages.jsx" into your scripting folder. It should immediately become available in your Scripts panel. Then just double-click to run.

It should warn you of duplicate numbers and some other mismatches I could think of. If it shows an error ("cannot create range"), your input is wrong. If it alerts you while running ("problem with page ...") it cannot move that page for some reason...

Absolutely No Guarantees. Run On A Copy Only. It May Seriously Damage Your Document If It Goes Wrong.

Participating Frequently
February 9, 2017

Hi,

I got this error:

TypeError: app.activeDocument is undefined

Anybody some idea how to fix it

Participating Frequently
February 9, 2017

I am sorry, it is InDesign,

i need it for acrobat

Peter Kahrel
Community Expert
Community Expert
September 10, 2021

You're in the wrong forum, please go to the Acrobat forum.

Jongware
Community Expert
JongwareCommunity ExpertCorrect answer
Community Expert
November 7, 2009

Hey, that was far more hard than I thought!

This script appears to be working -- but, admittedly, I only tested it with a 20-page document and some random reiterations. Run on a copy of your document, and holler if it ain't right. (And, boyo, do I hope it works ...)

You can fill in your new order in the first line, comma separated. You can also enter a range, like "5-10", if you happen to have a few pages in the original order. All numbers should be entered inbetween the quotes on one single line.

var order="1,20,2,19,3,18,4,17,5,16,6,15,7,14,8,13,9,12,10,11";

// Create an array out of the list:
ranges = toSeparate (order);

if (ranges.length != app.activeDocument.pages.length)
{
alert ("Page number mismatch -- "+ranges.length+" given, "+app.activeDocument.pages.length+" in document");
exit(0);
}

// Consistency check:
sorted = ranges.slice().sort(numericSort);
for (a=0; a<sorted.length-1; a++)
{
if (sorted < sorted[a+1]-1 ||
  sorted
== sorted[a+1])
  alert ("Mismatch from "+sorted
+" to "+sorted[a+1]);
}
// alert ("New order for "+order+"\nis "+ranges.join(", "));

// Convert from 1..x to 0..x-1:
for (moveThis=0; moveThis<ranges.length; moveThis++)
ranges[moveThis]--;

for (moveThis=0; moveThis<ranges.length; moveThis++)
{
if (moveThis != ranges[moveThis])
{
  try{
   app.activeDocument.pages[ranges[moveThis]].move (LocationOptions.BEFORE, app.activeDocument.pages[moveThis]);
  } catch(_) { alert ("problem with page "+moveThis+"/index "+ranges[moveThis]); }
}
for (updateRest=moveThis+1; updateRest<ranges.length; updateRest++)
  if (ranges[updateRest] < ranges[moveThis])
   ranges[updateRest]++;
}

function toSeparate (list)
{
s = list.split(",");
for (l=0; l<s.length; l++)
{
  try {
  if (s.indexOf("-") > -1)
  {
   indexes = s.split("-");
   from = Number(indexes[0]);
   to = Number(indexes[indexes.length-1]);
   if (from >= to)
   {
    alert ("Cannot create a range from "+from+" to "+to+"!");
    exit(0);
   }
   s = from;
   while (from < to)
    s.splice (++l,0,++from);
  }} catch(_){}
}
// s.sort (numericSort);
return s;
}

function numericSort(a,b)
{
return Number(a) - Number(b);
}

Copy and paste into a plain text editor -- the ESTK Editor that comes with InDesign is okay -- and save as "rearrangePages.jsx" into your scripting folder. It should immediately become available in your Scripts panel. Then just double-click to run.

It should warn you of duplicate numbers and some other mismatches I could think of. If it shows an error ("cannot create range"), your input is wrong. If it alerts you while running ("problem with page ...") it cannot move that page for some reason...

Absolutely No Guarantees. Run On A Copy Only. It May Seriously Damage Your Document If It Goes Wrong.

Marc Autret
Legend
November 7, 2009

Great job, Jong !

I see another approach using Page.id :

var order = "20, 1-4, 19, 18, 17, 5, 16, 6, 15, 7, 14, 8, 13, 9, 12, 10-11";
reorderPages(order);


function reorderPages(/*str*/newOrder)
//--------------------------------------
{
var pages = app.activeDocument.pages;

var pgMap = (function()
     {
     var items = newOrder.replace(/[^\d,-]/g,'').split(',');
     var r = [], bkp={}, i, sz, p;
    
     while(i=items.shift())
          {
          i = i.split('-');

          // don't allow "x-y-z"
          if ( (sz=i.length) > 2 ) return false;

          // don't allow "max-min"
          if ( i[0] > i[sz-1] ) return false;

          for( p=+i[0] ; p<= +i[sz-1] ; p++ )
               {
               if (!pages.item(''+p).isValid) return false;
              
               if (''+p in bkp) return false;
               bkp[''+p]=1;

               r.push(pages.item(''+p).id);
               }
          }
     return r;
     })();
    
if ( !pgMap )
     {
     alert("Invalid reordering string");
     return false;
     }

var sz = pgMap.length;
if (sz != pages.length)
     {
     alert ("Page number mismatch -- "+pgMap.length+" given, "+pages.length+" in document");
     return false;
     }

// at this point, {pgMap} contains a valid permutation

var i;
app.scriptPreferences.enableRedraw = false;
for( i=0 ; i < sz ; i++ )
     pages.itemByID(pgMap).move(LocationOptions.BEFORE, pages);
app.scriptPreferences.enableRedraw = true;
}

Does it work?

@+

Marc

Harbs.
Legend
November 7, 2009

Here's yet another approach: (This is a script I wrote quite a long time ago, so please excuse the style)

if (app.documents.length == 0){exit()}

reRun = movePages();
while (reRun){reRun = movePages()}

function movePages(){
var doc = app.activeDocument;
var origPN =[];
for (var i=0;i<doc.pages.length;i++){
//     var myPN = doc.pages.extractLabel("pageNumber");
     if (doc.pages.extractLabel("pageNumber") == ""){
          doc.pages.insertLabel("pageNumber",doc.pages.name);
          }
     origPN.push(doc.pages.extractLabel("pageNumber"));
     }
var myDialog = app.dialogs.add({name:"Move Pages",canCancel:true});
with(myDialog){
  with(dialogColumns.add()){
    with(borderPanels.add()){
      with(dialogColumns.add()){
        staticTexts.add({staticLabel:"Old Page Number:"});
        staticTexts.add({staticLabel:"New Page Number:"});
        staticTexts.add({staticLabel:"Rerun Script on OK:"});
        }
      with(dialogColumns.add()){
        var oldPNDD = dropdowns.add( {stringList: origPN, selectedIndex: 0} );
        var newPNField = textEditboxes.add({});
        var reRunCB = checkboxControls.add({checkedState:true})
        }
      }
    }
  }
var myResult = myDialog.show();
if(myResult == true){
  var oldPN = oldPNDD.selectedIndex;
  var newPN = newPNField.editContents;
  var reRun = reRunCB.checkedState;
  myDialog.destroy();
  }else{myDialog.destroy();exit()}
myReplPage = findPage(newPN,doc);
if (myReplPage == null){alert ("Invalid Page");exit()}
myOrigPage = findOrigPage(origPN[oldPN],doc);
if (myOrigPage.documentOffset > myReplPage.documentOffset){
  myOrigPage.move(LocationOptions.before,myReplPage);
  }else{
  myOrigPage.move(LocationOptions.after,myReplPage);
  }
return reRun
}
function findPage(myPage,doc){
  for (var i=0;i<doc.pages.length;i++){
    if (doc.pages.name == myPage){
      return doc.pages;
      }
    }
  return null;
  }

function findOrigPage(myPage,doc){
  for (var i=0;i<doc.pages.length;i++){
    if (doc.pages.extractLabel("pageNumber") == myPage){
      return doc.pages
      }
    }
  }

It went along with this accompanying script to clear out the saved page positions:

if (app.documents.length == 0){exit()}
var doc = app.activeDocument;
for (var i=0;i<doc.pages.length;i++){
     doc.pages.insertLabel("pageNumber","");
     }