网络上很多扫描版的PDF电子书都缺少书签。特别是对计算机教程类的大部头来说,由于需要经常翻阅,没有书签的痛苦可想而知

今天我来讲讲怎样利用JavaScript在Acrobat一键生成书签。

基本思路:大多数的扫描版PDF电子图书都可以在官网或者各大网上书店找到目录,很多都是带有页码的(图1)。 将目录用文本文件保存起来,作为附件添加到PDF中,利用JavaScript读取附件,生成数组,用循环处理字符串,再生成书签。


图1就是某网上书店的目录页面,可以看到后面每行都带有页码,这就是我们想要的!

在Acrobat中利用Javascript根据目录一键生成带页码的书签_第1张图片
图1



下面是具体步骤:

1.把目录复制粘贴到一个文本文件中,并保存为 UTF-8的编码。(图2)

在Acrobat中利用Javascript根据目录一键生成带页码的书签_第2张图片
图2

2.下载文末的附件,把Bookmark.js文件解压出来复制到Acrobat安装目录下的JavaScript文件夹里面,默认是Adobe\Acrobat 9.0\Acrobat\Javascripts。

3.打开Acrobat,并打开需要添加书签的PDF文件。

选择"帮助"菜单下的"Mark”选项。<-就是我们刚刚用JS添加的!(图3)

在Acrobat中利用Javascript根据目录一键生成带页码的书签_第3张图片

图3


4.选中"Mark"菜单后会弹出下面的选择文件窗口

在Acrobat中利用Javascript根据目录一键生成带页码的书签_第4张图片


5.接下来弹出的这个对话框要讲解一下(图6)
在Acrobat中利用Javascript根据目录一键生成带页码的书签_第5张图片
图6


页码为1的页面就是PDF文件的第一页,但一般都不是正文的第一页。

如图7所示,页码为1的页面是PDF文件的第14页,这里我已修改了页码。
在Acrobat中利用Javascript根据目录一键生成带页码的书签_第6张图片

图7


这样就可以按照目录的页数直接找到要看的页面,就是看实体书一样。

因此,对于图7来说,图6中就应该输入14,然后按确定

稍等一下,带连接的书签就自动生成了(图8)。

注:如果书签比较长,比较长,这个过程会卡顿一会,没办法,JS没有多线程


在Acrobat中利用Javascript根据目录一键生成带页码的书签_第7张图片

图8


有的PDF没有页码1的页面,只有页码2或其它,这时需要把推断出的页码1的页数填入
在Acrobat中利用Javascript根据目录一键生成带页码的书签_第8张图片

如上图,页码2的页数是15,则页码1的页数是14,以此类推。


注意事项:
  1. 有的PDF正文内可能插有其他的内容,例如发布网站的广告等,这时要把这些页面删掉,以确保正文的页数跟目录是一致的,否则将连接不到正确的页面。

  2. 脚本也能处理没有页数的目录,但是需要手动设置书签的目标了…

  3. Acrobat Pro的版本要高于9.3,否则不能读取附件内容。

  1. 在Acrobat中利用Javascript根据目录一键生成带页码的书签_第9张图片


好了,本文就到此结束了,有任何疑问请回帖,希望本文对你有帮助!


最后附上JS的源码:


app.addMenuItem({
    cName : "Mark",
    cParent : "Help", //加在”帮助(Help)“菜单下面
    nPos : 0, //0为尽可能最顶,忽略则最底位置
    cExec : "makeBookmark();",
    cEnable : "event.rc= (event.target != null);" //当有文档打开时(event.target != null)才可用
});
function makeBookmark() {
    //提示导入目录
    if (!(this.importDataObject("txtBookmark"))) {
        return
    }
    //检验目录是否TXT文本格式
    var MyData = this.getDataObject("txtBookmark");
    if (MyData["MIMEType"] != "text/plain") {
        app.alert("附件不是TXT格式!");
        this.removeDataObject("txtBookmark");
        return
    }
    var FirstPageNum = app.response({
            cQuestion : "输入页码为1的实际页数",
            cTitle : "若缺少1页码,则输入2页码的实际页数,依此类推",
            cDefault : "2",
            cLabel : "输入:"
        });
    if (FirstPageNum != null) {
        var MyStream = this.getDataObjectContents("txtBookmark");
        var MyString = util.stringFromStream(MyStream, "utf-8");
        //替换全角空格 Unicode值\u3000
        MyString = MyString.replace(/\u3000/g, "\u0020");
        //处理前后空格 Unicode值\u0020
        MyString = MyString.replace(/^\u0020\.*|\u0020$/gm, "");
        var myArr = MyString.split("\n");
        this.bookmarkRoot.remove();
        this.bookmarkRoot.createChild("目录");
        var Bkm = new Array(10); //创建一个数组来缓存书签
        Bkm[0] = this.bookmarkRoot.children[0];
        var HasPart = false; //设置一个flag表示是否遇到“部分”等没有.号的大分类
        for (var i in myArr) {
            var myRow = myArr[i];
            if (myRow.length > 2) { //空行的length=1,设置为2即不处理空行
                var Num_Dot = 0;
                var BeforeSpace = myRow.match(/^(\d+\.)+\d+\u0020/g); //1.2.3空格
                if (BeforeSpace != null) {
                    var DotMatches = BeforeSpace.toString().match(/\./g); //匹配.符号
                    Num_Dot = DotMatches.length + HasPart;
                } else {
                    var myRegExp = /第.*[\d一二三四五六七八九十]+.*部分|附录|索引/;
                    if (myRegExp.test(myRow)) {
                        Num_Dot = 0;
                        HasPart = true;
                    } else {
                        Num_Dot = HasPart + 0;
                    }
                }
                var LastSpaceIndex = myRow.lastIndexOf("\u0020"); //最后一个空格的位置
                var Page = Number(myRow.slice(LastSpaceIndex));
                var Page_Bookmark = isNaN(Page) ? 0 : Page - 2 + Number(FirstPageNum); //书签指向的页码
                var Name_Bookmark = isNaN(Page) ? myRow : myRow.slice(0, LastSpaceIndex); //书签的名字
                with (Bkm[Num_Dot]) {
                    createChild(Name_Bookmark, "this.pageNum=" + Page_Bookmark + ";", (children != null ? children.length : 0));
                    Bkm[Num_Dot + 1] = children[children.length - 1]; //目录中最后一个章节
                }
            }
        }
        collapsBM(Bkm[0]);
    }
}
function collapsBM(BM) { //折叠所有书签
    if (BM.children != null) {
        if (BM != this.bookmarkRoot) {
            for (var i in BM.children) {
                if (BM.children[i].children != null) {
                    BM.children[i].open = false;
                }
            }
        }
        for (var i in BM.children) {
            collapsBM(BM.children[i])
        }
    }
}
附近请下最后一个。