There's no need to pay for Autobookmark or Evermap if you just need to sort your bookmarks alphabetically.
UPDATE: 2020-02-02 I added symbol handling, which wasn't done previously. Now you get __a__, __b__, instead of __a__, a, ab, abc...
. However, Acrobat seems to handle the other symbols (mostly) in its own order. For example, + and = aren't sorted as shown in the order below. For my usecase, this doesn't really matter. If it does for you, you can try removing all the symbols listed below (under var reA), just keeping _.
C:\Program Files (x86)\Adobe\Acrobat 11.0\Acrobat\Javascripts\freesort.js
(adjust the path as needed).// Copyright Sean Wingert, February 11, 2019 // Based largely on http://www.adobe.com/devnet/acrobat/pdfs/batch_sequences.pdf // and https://wiki.med.umich.edu/display/UMHSHELPDESK/Acrobat+-+Using+Acrobat+JavaScript+to+Sort+PDF+Pages // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 3 of the License, or // (at your option) any later version. // Create a separator in the Edit menu and add a Sort Bookmarks entry. This loads a few moments after Acrobat does. app.addMenuItem({cName:"-", cParent:"Edit", cExec:" "}); app.addMenuItem({cName:"Sort Bookmarks", cParent: "Edit", cExec: "freesort()"}); // Create a utility function to see if a PDF has been loaded first, which is a prerequisite // https://coderwall.com/p/_g3x9q/how-to-check-if-javascript-object-is-empty function isEmpty(obj) { for(var key in obj) { if(obj.hasOwnProperty(key)) return false; } return true; } // Create a function to sort the parent bookmarks (not their children or grandchildren) by name function freesort() { if(isEmpty(this.bookmarkRoot)) { app.alert("Error. Please open a PDF first."); return; } // set variables bm = this.bookmarkRoot; // the current PDF document bmArray = new Array(); // array to hold collected bookmarks // write bookmarks to an array because you can't sort this.bookmarkRoot.children.sort(compare) for (var i=0; i < bm.children.length; i++) bmArray[i] = bm.children[i]; // Use Natural Sort, AKA Human Sort (1,2,11,22), not Alphabetical sort (1,11,2,22) // Note: toLowerCase() makes this a case-insensitive sort. // https://stackoverflow.com/questions/4340227/sort-mixed-alpha-numeric-array var reA = /[^~`!@#\$%\^&*()\-+=\[\]{}\\|;:'",<.>/?_a-zA-Z\s]/g; var reN = /[^0-9]/g; function compare(a, b) { var a=a.name.toLowerCase(); var b=b.name.toLowerCase(); var aA = a.replace(reA, ""); var bA = b.replace(reA, ""); if (aA === bA) { var aN = parseInt(a.replace(reN, ""), 10); var bN = parseInt(b.replace(reN, ""), 10); return aN === bN ? 0 : aN > bN ? 1 : -1; } else { return aA > bA ? 1 : -1; } } // sort the array bmArray.sort(compare); // Move the bookmarks to the end of the list in their sorted order for (var i=0; i < bmArray.length; i++) bm.insertChild(bmArray[i], bm.children.length); // troubleshooting: print the results // for (var i=0; i < bmArray.length; i++) console.println(bmArray[i]); }
Note: Step 2 on a Mac looks like this:
/Applications/Adobe Acrobat Reader DC.app/Contents/Resources/JavaScripts/freesort.js
Comments
John (not verified)
Wed, 11/20/2019 - 18:43
Permalink
Your freesort routine
Thank you! It worked immediately and exactly as you said.
Nathan (not verified)
Fri, 12/13/2019 - 07:13
Permalink
Workaround for Reader?
Hi I am trying to use your excellent bit of code to resort a set of bookmarks that are already in a large PDF. Is there any way to implement this using reader? Following your instructions I do get the link in the edit menu, but it gives an error "An internal error occurred." Is there any way to edit the bookmarks for a PDF outside of adobe?
Thanks!
Nate
Add new comment