Highlighted

Javascript to split top level bookmarks using bm names for file names

Engaged ,
Oct 01, 2017

Copy link to clipboard

Copied

Hello all!

Adobe Acrobat DC pro

Mac os 10.12.6

I want to create a acrobat action to split top level bookmarks using bm names for file names, to my surprise Adobe doesn't have that as an option under the "tools to add" when creating a new action. I was equally surprised to find very little discussion or code postings on the net about this subject.

What I did find doesn't work. I was hoping one of the experts on the forum could take a look at the code below and give some direction on how to get it to work.

Thanks in advance!!

BookmarkCollection bookmarks = document.Bookmarks;

for ( int index=0, fromPage=0; index<bookmarks.Count; index++ )

{

   // determine last page of next part

   int toPage = -1;

   Bookmark bookmark = null;

   if ( index == bookmarks.Count-1 )

   {

      // last bookmark - append all remaining pages

      toPage = document.Pages.Count;

   }

   else

   {

      // not the last bookmark - append up to the next bookmark

      bookmark = bookmarks[index+1];

      GoToAction action = bookmark.Actions[0] as GoToAction;

      if ( null != action )

      {

         InternalDestination destination = action.Destination as

            InternalDestination;

         if ( null != destination )

         {

            toPage = destination.Page.Index;

         }

      }

   }

   // create a new part

   if ( -1 != toPage && null != bookmark )

   {

      Document part = new Document();

      for ( int pageIndex=fromPage; pageIndex<toPage; pageIndex++ )

      {

         part.Pages.Add( document.Pages[pageIndex].Clone() );

      }

      using ( FileStream fileOut = new FileStream(

         bookmark.Title + ".pdf", FileMode.Create, FileAccess.Write ) )

      {

         part.Write( fileOut );

      }

      fromPage = toPage;

   }

}

Adobe Community Professional
Correct answer by Thom Parker | Adobe Community Professional

Opps , missed that part, well here is an update,

bkTrgt.forEach(function(a,i,k){oDoc.extractPages(k,((i+1)<k.length)?k[i+1]-1:oDoc.numPages-1,oDoc.bookmarkRoot.children.name + ".pdf"})

The bookmarks children have exactly the same indexes as the page numbers in the array, so I just changed the code the get the save file name from the bookmark name at the index that is being operated on..

TOPICS
Acrobat SDK and JavaScript, Macintosh

Views

1.7K

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more

Javascript to split top level bookmarks using bm names for file names

Engaged ,
Oct 01, 2017

Copy link to clipboard

Copied

Hello all!

Adobe Acrobat DC pro

Mac os 10.12.6

I want to create a acrobat action to split top level bookmarks using bm names for file names, to my surprise Adobe doesn't have that as an option under the "tools to add" when creating a new action. I was equally surprised to find very little discussion or code postings on the net about this subject.

What I did find doesn't work. I was hoping one of the experts on the forum could take a look at the code below and give some direction on how to get it to work.

Thanks in advance!!

BookmarkCollection bookmarks = document.Bookmarks;

for ( int index=0, fromPage=0; index<bookmarks.Count; index++ )

{

   // determine last page of next part

   int toPage = -1;

   Bookmark bookmark = null;

   if ( index == bookmarks.Count-1 )

   {

      // last bookmark - append all remaining pages

      toPage = document.Pages.Count;

   }

   else

   {

      // not the last bookmark - append up to the next bookmark

      bookmark = bookmarks[index+1];

      GoToAction action = bookmark.Actions[0] as GoToAction;

      if ( null != action )

      {

         InternalDestination destination = action.Destination as

            InternalDestination;

         if ( null != destination )

         {

            toPage = destination.Page.Index;

         }

      }

   }

   // create a new part

   if ( -1 != toPage && null != bookmark )

   {

      Document part = new Document();

      for ( int pageIndex=fromPage; pageIndex<toPage; pageIndex++ )

      {

         part.Pages.Add( document.Pages[pageIndex].Clone() );

      }

      using ( FileStream fileOut = new FileStream(

         bookmark.Title + ".pdf", FileMode.Create, FileAccess.Write ) )

      {

         part.Write( fileOut );

      }

      fromPage = toPage;

   }

}

Adobe Community Professional
Correct answer by Thom Parker | Adobe Community Professional

Opps , missed that part, well here is an update,

bkTrgt.forEach(function(a,i,k){oDoc.extractPages(k,((i+1)<k.length)?k[i+1]-1:oDoc.numPages-1,oDoc.bookmarkRoot.children.name + ".pdf"})

The bookmarks children have exactly the same indexes as the page numbers in the array, so I just changed the code the get the save file name from the bookmark name at the index that is being operated on..

TOPICS
Acrobat SDK and JavaScript, Macintosh

Views

1.7K

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Oct 01, 2017 0
Most Valuable Participant ,
Oct 01, 2017

Copy link to clipboard

Copied

Any specific reason not to use the built-in command that does that? It's under the Split Document function.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 01, 2017 0
Most Valuable Participant ,
Oct 01, 2017

Copy link to clipboard

Copied

PS. The code above was not written for Acrobat.

PPS. I've developed a script (a long time ago) that does it, if you're interested: Custom-made Adobe Scripts: Acrobat -- Extract Chapters by Bookmarks

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 01, 2017 0
Engaged ,
Oct 01, 2017

Copy link to clipboard

Copied

Hello,

I wanted to create a acrobat action to split top level bookmarks so I could point to a folder location full of bookmarked pdfs, so I wouldn't have to physically open each file and go through the process: Organize Pages/Split/Split by: Top level bookmarks/Output Options/Use bookmark names for file names.

Thanks......

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 01, 2017 0
Adobe Community Professional ,
Oct 01, 2017

Copy link to clipboard

Copied

The built-in Split function will split files based on top level bookmarks and can be run against multiple files as though it were being initiated from an Action. Unless there is something you're leaving out of your question, there's no need to create an Action to do this.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 01, 2017 0
Engaged ,
Oct 01, 2017

Copy link to clipboard

Copied

Thanks for the reply Joel

Your'e correct as the Acrobat split function can be run against multiple files, I am working on creating an action that Creates Bookmarks-From Tags then I am running js to make them top level bookmarks, I just wanted to add the split function to make it fully automated.

Thanks

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 01, 2017 0
Adobe Community Professional ,
Oct 01, 2017

Copy link to clipboard

Copied

You may be over complicating this. What software is adding the tags?

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 01, 2017 0
Engaged ,
Nov 09, 2017

Copy link to clipboard

Copied

Hello!

This is what I have for the action to create top level bookmarks from a tagged pdf and then split based on the bookmark names.

The problem i am having is I can't figure out how to loop to iterate over the bookmarks, executing

each one and then using the current page number information to determine the page range of each bookmark,

and then extract it as a new file with different page counts based on the # of pages between the bookmarks. What I am getting are pdfs named by the bookmarks with only one page and none of the pages between the bookmarks.

/* MakeTopLevelBookmarks */

var bm = this.bookmarkRoot;

var bmToDeleteArray = new Array();

// Iterate through each bookmark

var ibmLength = bm.children.length;

for (var i = 0; i < ibmLength; i++)

{

    var bmToCheck = bm.children;

    if((bmToCheck.name.indexOf("Structure")!=-1) && (bmToCheck.children!=null))

    {

        console.println("found bookmark with children " + i);

   

        var ibmChildrenToMoveLength = bmToCheck.children.length;

        for(var j=0; j<ibmChildrenToMoveLength; j++)

        {

           console.println("moving bookmark " + j);

           bm.insertChild(bmToCheck.children[0], bm.children.length);

        }

        bmToDeleteArray[bmToDeleteArray.length] = bmToCheck;

    }

}

for (var i = 0; i < bmToDeleteArray.length; i++)

{

// Delete bookmark

   bmToDeleteArray.remove();

}

delete bmToDeleteArray;

/* Now Split */

if (this.bookmarkRoot.children!=null)

{

for (var i=0; i < this.bookmarkRoot.children.length; i++)

{

var bm = this.bookmarkRoot.children.execute();

var bmname = this.bookmarkRoot.children.name;

this.extractPages({nStart:bm + this.pageNum++,  cPath: ""+ bmname +".pdf"});

}

}

Thanks in advance for any help!!

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Nov 09, 2017 0
Adobe Community Professional ,
Nov 09, 2017

Copy link to clipboard

Copied

Loop Twice, once to collect target page data into an array, and then loop over the array to split out the pages

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Nov 09, 2017 0
Engaged ,
Nov 10, 2017

Copy link to clipboard

Copied

Hi Thom,

I am new to scripting, I understand the concept I just don't know the method/properties to perform the function.

Thanks in advance for any help!!

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Nov 10, 2017 0
Adobe Community Professional ,
Nov 13, 2017

Copy link to clipboard

Copied

This type of coding is very tricky because you have to make several assumptions, any of which could break the script.

Assumptions

1. the bookmark goes to a page (could open an URL or do something else).

2. The pages are in order.

3. Executing happens synchronously, or fast enough to seem synchronous.

So here is some code that collects all the top level bookmark destinations, assuming all the assumptions are met.

oDoc = this;

bkTbkTrgt = []

this.bookmarkRoot.children.forEach(function(a){a.execute();bkTrgt.push(pageNum);})

Now extracting the pages is just a matter of walking this list

bkTrgt.forEach(function(a,i,k){oDoc.extractPages(k,((i+1)<k.length)?k[i+1]-1:oDoc.numPages-1,oDoc.documentFileName.replace(/\./,i+"."));})

There's the whole thing in 4 lines of code. Run it from the Console Window

I'll add this as a tool to pdfscripting.com, except with checks for the assumptions

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Nov 13, 2017 0
Engaged ,
Nov 15, 2017

Copy link to clipboard

Copied

Hello Thom!

Thank you for explaining about the assumptions and what to consider.............

In this case the bookmarks are intended only to be used for Identifying the first page in a rang of pages and for the spilt/extracted file naming.

The code you provided is splitting the pages correctly but the naming of the extracted files are not of their respective Bookmark names but of the file name and base numbering.

I've tried a few attempts to modify the code with no good results.

Thanks again for any help!!!!!

oDoc = this;

bkTrgt = []

this.bookmarkRoot.children.forEach(function(a){a.execute();bkTrgt.push(pageNum);})

bkTrgt.forEach(function(a,i,k){oDoc.extractPages(k,((i+1)<k.length)?k[i+1]-1:oDoc.numPages-1,oDoc.documentFileName.replace(/\./,i+"."));})

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Nov 15, 2017 0
Adobe Community Professional ,
Nov 15, 2017

Copy link to clipboard

Copied

Opps , missed that part, well here is an update,

bkTrgt.forEach(function(a,i,k){oDoc.extractPages(k,((i+1)<k.length)?k[i+1]-1:oDoc.numPages-1,oDoc.bookmarkRoot.children.name + ".pdf"})

The bookmarks children have exactly the same indexes as the page numbers in the array, so I just changed the code the get the save file name from the bookmark name at the index that is being operated on..

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Nov 15, 2017 0
Engaged ,
Nov 15, 2017

Copy link to clipboard

Copied

Thank you very much!!

oDoc = this;

bkTrgt = []

this.bookmarkRoot.children.forEach(function(a){a.execute();bkTrgt.push(pageNum);})

bkTrgt.forEach(function(a,i,k){oDoc.extractPages(k,((i+1)<k.length)?k[i+1]-1:oDoc.numPages-1,oDoc.bookmarkRoot.children.name + ".pdf");});

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Nov 15, 2017 0
Contributor ,
Sep 15, 2020

Copy link to clipboard

Copied

Hi Mike,

 

Could you post the full code that's working? I'm a code noob, and tried to follow this thread, but it's all gone over my head!

 

Cheers,

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Sep 15, 2020 0
Engaged ,
Oct 15, 2020

Copy link to clipboard

Copied

Hi Pu_Kah,

sorry for the delayed response.....here's the working code.

 

oDoc = this;

 

bkTrgt = []

 

this.bookmarkRoot.children.forEach(function(a){a.execute();bkTrgt.push(pageNum);})

 

bkTrgt.forEach(function(a,i,k){oDoc.extractPages(k,((i+1)<k.length)?k[i+1]-1:oDoc.numPages-1,oDoc.bookmarkRoot.children.name + ".pdf");});

 

 

Regards,

Mike

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Oct 15, 2020 0