Sorting bookmarks in a document

Here's how to sort bookmarks into position order in a document.  We'll use Advanced Array functions heavily here.

First we get the bookmarks positions and the elements they refer to, and add a path to them to identify where they occur in the document. These paths will look something like this - here they are sorted. I make use of the childIndex method to get where an element is relative to its parent, and recursively go back up through the document to create a sortable index for each bookmark in the document, and then sort it using this generated path. Finally I get rid of the sorting aid, and get back to an array of bookMarks - this time sorted in the order they appear in the document.

The code

function sortBookMarks () { return DocumentApp.getActiveDocument().getBookmarks().map( function (b) { return { path : pathInDocument(b.getPosition().getElement()), bookMark:b } ; }) .sort ( function (a,b) { return ( a.path>b.path ? 1 : (a.path < b.path ? -1 : 0)); }) .map ( function (b) { return b.bookMark; }); function pathInDocument(element,path) { path = path || "" ; var parent = element.getParent(); if (parent) { path = pathInDocument( parent , Utilities.formatString ( '%04d.%s', parent.getChildIndex(element),path )); } return path; } }

The test

To use this create a document with various paragraphs, list items, tables etc, some of which contain the target words or phrases, run this and check the log to ensure the bookmarks get sorted according to document order.
function testBookMarkData() { // delete all current bookmarks DocumentApp.getActiveDocument().getBookmarks().forEach( function (b) { b.remove(); }); // add some test ones insertSomeBookMarks ("google"); insertSomeBookMarks ("script"); insertSomeBookMarks ("apps"); // show order before var bookMarks = DocumentApp.getActiveDocument().getBookmarks(); bookMarks.forEach( function (b) { Logger.log(b.getId() + ':' + b.getPosition().getElement().asText().getText()); }); // show order after var sortedBookMarks = sortBookMarks(); sortedBookMarks.forEach( function (b) { Logger.log(b.getId() + ':' + b.getPosition().getElement().asText().getText()); }); } function insertSomeBookMarks(searchItem) { // insert bookmarks for all the searchitems var doc = DocumentApp.getActiveDocument(); var body = doc.getBody(); var rangeElement = body.findText (searchItem); while (rangeElement !== null) { var position = doc.newPosition(rangeElement.getElement(),rangeElement.getStartOffset()); var bookMark = position.insertBookmark(); rangeElement = body.findText(searchItem, rangeElement); } }
For help and more information join our forumfollow the blogfollow me on twitter

You want to learn Google Apps Script?

Learning Apps Script, (and transitioning from VBA) are covered comprehensively in my my book, Going Gas - from VBA to Apps script, available All formats are available now from O'Reilly,Amazon and all good bookshops. You can also read a preview on O'Reilly

If you prefer Video style learning I also have two courses available. also published by O'Reilly.
Google Apps Script for Developers and Google Apps Script for Beginners.