4

how can I change all the booksmarks settings of a pdf document to "Fit Page" in batch, instead of one by one?

I am using Adobe Acrobat Pro DC on Windows 7.

3 Answers 3

1

I wrote an Acrobat Pro plugin for this task: https://github.com/binghe/acrobat-actions/tree/master/Plug-ins

I recursively walk into all bookmarks, and to fix each bookmark object I have the following code:

    // Fixing actions
    PDAction action = PDBookmarkGetAction(b);
    if (PDActionIsValid(action)) {
    PDViewDestination dest = PDActionGetDest(action);
    if (PDViewDestIsValid(dest)) {
        ASInt32 pageNum;
        ASAtom fitType, targetFitType = ASAtomFromString("XYZ");
        ASFixedRect destRect;
        ASFixed zoom;
        PDViewDestGetAttr(dest, &pageNum, &fitType, &destRect, &zoom);
        if (fitType != targetFitType || zoom != PDViewDestNULL) {
        PDPage page = PDDocAcquirePage(doc, pageNum);
        newDest =
        PDViewDestCreate(doc,
                 page,            /* := pageNum */
                 targetFitType,   /* XYZ */
                 &destRect,
                 PDViewDestNULL,  /* when FitType is XYZ */
                 0);          /* unused */
        newAction = PDActionNewFromDest(doc, newDest, doc);
        PDBookmarkSetAction(b, newAction);
        PDViewDestDestroy(dest);
        PDActionDestroy(action);
        acc++;
        }
    }
    }
2
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review
    – Toto
    Commented Jul 15, 2022 at 9:18
  • Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
    – Community Bot
    Commented Jul 15, 2022 at 10:46
0

I haven't written an PDF-specific Javascript in a Long Time (>8 years), but I seem to recall that being possible in JS.

https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/js_api_reference.pdf

The new-fangled way to run a JS these days is to attach it to an "Action" with the "Action Wizard" tool (one of the "more tools" tools near the bottom). Use "New Action"->choose tools to add:->more tools->Execute JavaScript".

First you need to get the "doc" object. To do that you can set up a document or page level event (On Page Open, on page 1 for instance). event.target will be the doc object.

You then need to step through all the bookmarks. To do so, you need to step through all of each bookmarks .children, recursively because bookmarks don't have a nesting depth limit.

So something like:

var doc = event.target;

iterateKids(doc.bookmarkRoot);

function iterateKids(bookmark) {
  for (var kid : bookmark.kids) {
    ...
    iterateKids(kid);
  }
}

Now for the ..., I'm a little stumped. You can set a bookmark's action with bookmark.setAction("your javascript here");, but you really can't inspect the existing goto action or change its zoom setting.

Not in the published reference anyway. Or... EUREKA! Maybe.

You can trigger a bookmark's action. bookmark.execute(). You can also check doc.pageNum to get the current page. You can then set the doc's pageNum and zoomType in your injected script.

bookMark.setAction("this.pageNum = " + doc.pageNum + "; this.zoomType = zoomType.fitP;");

I haven't actually tried any of this, and boy am I rusty. None the less, I foresee some problems.

  • You may have a problem in that when you bookmark.execute();, the doc's pageNum and zoomType may not update until the current event is over, at which point this becomes considerably more complicated. You'd have to do something with app.setInterval("your JS here", timeBetweenExecutionsInMilliseconds); You'd set some doc-level variable[s] so you could pass information between your "execute the bookmark action" to "okay the view changed, lets update that bookmark we stored in a doc-level variable". You can just make up arbitrary names and assign them equally arbitrary values on any object in JS, so doc.currentBookmark = kid;. Then you'd clear that "currentBookmark" variable, and set an "oldBookmark" variable so your "walk through all the bookmarks" code could pick up where it left off rather than starting over from the beginning and finding one past where you were. Like I said. Complicated.
  • You may have no experience with JS at all. I've tried to write this to a beginner, but this is still jumping into the deep end to learn how to swim.
  • surprise, fear, and a nigh-fanatical dedication to the Pope!
0

Here's my tested Acrobat Javascript. There's no way I could find to add an additional action to a bookmark, for example, to change the view to "Fit Page" after existing actions are complete.

Here's what this script does for each bookmark:

  1. Execute the bookmark action(s).
  2. Remember the new page number and zoomType.
  3. If zoomType does -NOT- equal "FitPage" then replace bookmark action(s) with a Javascript that jumps to the page (remembered above) and changes the zoomType to "FitPage".

    function ChangeAllBookmarksToFitPage(Bm, nLevel, nLevelMax) { // nLevelMax ———> change maximum level of the processed bookmarks, starts from 0

    if (nLevel > nLevelMax)
    {
        return;
    }
    
    
    Bm.execute                              // execute the bookmark to jump to the target page
    
    if( !(this.zoomType == "FitPage") ) {
        // The bookmark was not set to "FitPage".
        //  Replace the existing bookmark action.
    
        // Get the current page number (page that the last bookmark linked to).
        var bmPage = parseInt(this.pageNum);    // bookmark target page is active; get the page number
    
        Bm.setAction("this.pageNum = " + bmPage + "; this.zoomType = zoomtype.fitP;");
    
    }
    
    
    // process children
    if (Bm.children != null)
    {     
     for (var i = 0; i < Bm.children.length; i++)
     {     
          ChangeAllBookmarksToFitPage(Bm.children[i], nLevel + 1);
     }     
    }
    

    }

Call it like this:

var root = this.bookmarkRoot;  // starting bookmark object
ChangeAllBookmarksToFitPage(root, 0, 10);

Note the 3 parameters:

  • Bm - a bookmark object
  • nLevel - the starting level (zero is at the root, so all bookmarks)
  • nLevelMax - the number of levels deep to go (if there are sub-bookmarks)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .