LoginSignup
6
5

More than 3 years have passed since last update.

Action Scriptを使ったら、PDFのページ並べ替え作業が劇的に短縮できる!

Last updated at Posted at 2019-07-16

 Acrobatでページ並べ替えをする作業が、ActionScriptを使うと劇的に短縮できることがわかったので、ここに覚え書きしておくことにします。
 なお、当方が使用しているのは Acrobat Pro DC (2015 Release)ですが、movePageメソッドが使えるのならOK。
(チュートリアルによれば、Acrobat Pro 5.0以降でいける模様です。なお、残念ながら無料バージョンの Acrobat Reader では使えません。Action Script全般に関してそうですが)

どういうときに movePage メソッドが必要なのか

 個人的に、なぜこれが必須になったか、という例を挙げることにしましょう。
 ズバリ、「本バッサリ裁断してスキャンかけた後、本のPDFを作成するとき」です。

<自分が困ったケース>
1. 本の末尾には、必ず索引がついているものです。ところが、往々にして日本語の本では、索引の部分だけ、ページが逆順になっていることがあります。
 例えば、[索引3]→[索引2]→[索引1]→奥付→裏表紙、という順番になっているケースがあるんです。日本語の本に多いです。
 PDFにしたとき、これが見づらくて仕方ありません。
 だから、この最後の索引の部分だけ、[索引1]→[索引2]→[索引3]→奥付→裏表紙、という形に並べ替えたかったのです。

2. 両面スキャンすると、片面だけどうしても横筋が入ってしまう現象が発生しました。読み取り部分をクリーンしてみたものの、効果ナシ。
 じゃあ2ページごとに横筋が入ってるPDFで我慢できるか?と言うところなのですが。実際に見てみたら分かると思いますが、これ、ものーっすごく不愉快です。2ページごとにイライラさせられるのは必定です。

 じゃあ、どうするか。
 スキャナーを2回回します。片面だけでやれば、なぜか横筋が入らなかったのです。すぐにスキャナを新調・修理に出すという状況下になかったので、コレで凌ぐしかなかったのです。

 最初は、1ページから片面で表だけを読み取らせる。これで出来上がるのが
 1, 3, 5, 7, 9, 11, 13, … (最後-1) :奇数ページ(正順)だけからなるPDF。

 次は、裏返して最後のページから、片面で裏だけを読み取らせる。これで出来上がるのが
 (最後), (最後-2), (最後-4), … , 8, 6, 4, 2 :偶数ページ(逆順)だけからなるPDF。
 
 この2つのPDFを単純結合したら、
 1, 3, 5, 7, 9, 11, 13, … (最後-1), (最後), (最後-2), (最後-4), … , 8, 6, 4, 2 というPDFが出来上がります。
 これを、
 1, 2, 3, 4, 5, 6, 7, 8, 9, …, (最後-2), (最後-1), (最後) というふうに、普通の順番に並べ替えたかったのです。

 いろいろとネットを捜索した結果、

全てのページを逆さまにしてしまうコード
for (i = this.numPages - 1; i >= 0; i--) this.movePage(i);

 という処理を見つけました。

 Acrobat で ActionScript を実行させる方法は、[ツール]―[アクションウィザード]―[新規アクション]。
 左ペインの[その他のツール]をクリック、[Javascriptを実行]をクリックすると、右ペインに勝手に「Javascriptを実行」のメニューが追加されるはずです。
 その真ん中くらいにある「設定を指定」をクリック。
 すると、JavaScriptエディターが飛び出してきます。そこに、コードを書く。書いたらOKで閉じる。で、[保存]を押すとアクション名と説明を入力させる画面が出てきます。
 そこでOKしたら、アクションリストの一番下、カスタムコマンドという所にそのメニューがポンと追加されているはずです。

 これを実際に作動させてみると、確かに全てのPDFのページが逆になったので、ビックリしました:upside_down:
 ただ、この情報だけでは、自分のやらせたい処理をどう実現したら良いのか分からない・・・:disappointed_relieved:

 どうすればよいかわからない中、Action Script の チュートリアルにたどり着きました。これが、勝因を切り開く結果となりました。

Action Scriptのチュートリアル

JavaScript™ for Acrobat® API Reference
Adobe® Acrobat® SDK
April 2007 Version 8.1
https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/js_api_reference.pdf

ここのp.324に、movePage メソッドの説明がありました。
1.png

これがものすごく重要な情報で、つまり、文法が分かったのです。

movePage( 第1引数, 第2引数 )
 第1引数に、動かしたいページ番号を入れる。(省略した場合は最初のページ)
 第2引数に、「どのページの後に入れるか」のそのページ番号を入れる。(省略した場合は最後のページ)

 注意点は、0基準なので、ページ番号を -1 してやらなければならない、と。
 例えば Acrobatで p.10 と表示されていたら、それは ActionScript 側では p.9 として認識されている、ということですね。

ではいよいよ実装

  • PDFの特定のページ箇所だけ、順番を逆にする方法
     例えば、PDFのAcrobat表記で「654, 655, 656, 657」ページだけ「657, 656, 655, 654」にしたい、とします。
     AcrionScript側で認識している番号に [ ] を付けて表すことにします。
      1回目:[656] を [652] の後へ →「657, 654, 655, 656」
      2回目:[656] を [653] の後へ →「657, 656, 654, 655」
      3回目:[656] を [654] の後へ →「657, 656, 655, 654」

 よって、求める ActionScript は、次のようになります。

特定の範囲のページのみを逆さまにしてしまうコード
StartPage = 654; /*ここは逆にしたい(Acrobatでの)開始ページを指定*/
EndPage = 657;   /*ここは逆にしたい(Acrobatでの)終了ページを指定*/
MPN = EndPage - 1;
MoveTimes = EndPage - StartPage;
for (i = 0; i < MoveTimes; i++) this.movePage(MPN, StartPage - 2 + i);


  • 1, 3, 5,…,(最後-1),(最後),(最後-2),(最後-4),…, 8, 6, 4, 2 となっているPDFを、
    1, 2, 3, 4, 5, 6, 7, 8, 9, …, (最後-2), (最後-1), (最後) と普通に並べ替える方法

 小さい例で考えると一般化しやすいですね。
 PDFのAcrobat表記「1, 3, 5, 6, 4, 2」を「1, 2, 3, 4, 5, 6」にすると考えると、
  1回目:[5] を [0] の後へ →「1, 2, 3, 5, 6, 4」
  2回目:[5] を [2] の後へ →「1, 2, 3, 4, 5, 6」

 理解を確実にするために、もう1個増やしましょうか。
 PDFのAcrobat表記「1, 3, 5, 7, 8, 6, 4, 2」を「1, 2, 3, 4, 5, 6, 7, 8」にすると考えると、
  1回目:[7] を [0] の後へ →「1, 2, 3, 5, 7, 8, 6, 4」
  2回目:[7] を [2] の後へ →「1, 2, 3, 4, 5, 7, 8, 6」
  3回目:[7] を [4] の後へ →「1, 2, 3, 4, 5, 6, 7, 8」

 これで、構造が見えました。よって、求める ActionScript は、次のようになります。

「奇数(順)+偶数(逆)」を1から順序よく整列させるコード
MoveTimes = this.numPages / 2 - 1;
MPN = this.numPages - 1;
for (i = 0; i < MoveTimes; i++) this.movePage(MPN, 2*i);



たったこれだけで終わってしまう・・・


  • 2, 1, 4, 3, …,(最後-2),(最後-3),(最後),(最後-1) となっているPDFを、
    1, 2, 3, 4, 5, 6, 7, 8, 9, …, (最後-2), (最後-1), (最後) と普通に並べ替える方法

 これ、主に日本語の "左から開く形の和書PDFあるある" です。

 2ページ1面開きでコピーした後、何らかの仕掛けを使って、真ん中でそのPDFをブッタ切る、ということをやることがあります。この手が使えたら、コピーする手間が半分で済みますから。

 で、それで機械的にプログラムで真ん中で2つにブッタ切った時、必ず発生する形です。

 プログラムで真っ二つにブッタ切る方法は、例えば私が知ってる限りでは

 [方法1] muPDFをダウンロードして適当なフォルダに格納した後、コマンドプロンプトを呼び出して、

PDFを真っ二つに割るコマンド
mutool poster -x 2 (真ん中でブッタ切りたいPDF名).pdf (出力させたいPDFを名).pdf

と書いてポンと押してやる方法。

 [方法2]PDFの印刷のプロパティで「ポスター(2枚)」にして出力させることで、半分に分割することができます。たしか、99%とか98%にしてやらないとちゃんと半分に切れてくれなかったはずです。

 [方法3]TeXで \includepdf[angle=0, viewport=0mm 0mm 128.5mm 182mm, pages=\thepg]{\pdffn} というようにページの半分の箇所を指定して、実際はページの大きさは変わってないけど、左半分、右半分にフォーカスを移して、1ページづつになっているように見せかける、という技法

 この3つの方法、探せば必ずどこかに書いてある方法です。私、これをすべて試したのですが、この不具合は解消しなかったのです。

 なら、どうしていたのか。

 Acrobatの画面を見ながら、マウスのドラッグでいちいち偶数ページを2個前に持ってって・・・、ってのを、PDF丸ごと延々とやるしかなかったのです😂。本が800ページとかになると、400回もこの作業をやらなければいけなかったのです。・・・苦痛以外の何物でもありませんでした:triumph:

 しかし、これも、いとも簡単に済んでしまうことが、判明してしまったのです。

 小さい例で考えたら構造が見やすくなります。
 PDFのAcrobat表記「2, 1, 4, 3, 6, 5」を「1, 2, 3, 4, 5, 6」にすると考えると、
  1回目:[1] を [-1] の後へ →「1, 2, 4, 3, 6, 5」
  2回目:[3] を [1] の後へ →「1, 2, 3, 4, 6, 5」
  3回目:[5] を [3] の後へ →「1, 2, 3, 4, 5, 6」

 1~6ページまでをやるとしたら、6/2=3回、開始ページから始まって、+2づつインクリメントしてやればいい、ってことですね。

 よって、求める ActionScript は、次のようになります。

指定ページ間だけ、奇数と偶数ページを逆にするスクリプト(和書・左開きの本)
StartPage = 8; /*ここは開始したい(Acrobat上の)開始ページを指定*/
EndPage = 493;   /*ここは終了したい(Acrobat上の)終了ページを指定*/
MoveTimes = ((EndPage - StartPage)+1)/2;
for (i = 0; i < MoveTimes; i++) this.movePage(StartPage+2*i, StartPage+2*(i-1));

今まで苦労していたのは、一体何だったのか・・・・:sob:




なんで、なんで、これにもっと早く気づかなかった ―――――――――――
もっと早くにAcrobatのJavascript操作という可能性に気が付き、ActionScriptにチャレンジするべきでした。多分100時間くらいムダにしていると思います:weary:

 あとがき

 少量であれば手作業でもなんとかなると思いますが、自炊PDFが大量になってくると、死ねる作業量になってきます。600ページとか800ページの本が何十冊もあると。
 Action Script があるとないでは、天地の差がついてくるでしょう。
 
 今まで、手作業でページ整列作業をやっていただけに、確信を持って、そう言えます。
 まさにAcrobat Proを使う利点に、初めて目覚めました。
 いろいろとネットを調べ回ったのですが、movePagesについて書いているドキュメントがなかったので、ここにageておくことにします。
 
 自分と同じような作業に悩んでいる人にとって、確実に作業時間を爆縮することでしょう。
 どなたかの朗報にならんことを祈りつつ。:pray:



(2020/12/16 追記)
新たなテクニックを1つ、追記しておくことにします。

指定間のページ内の、奇数のページだけを削除する方法

 deletePagesを使うと、ページ削除ができます。
無題.png

指定ページ間内の、奇数のページだけを削除するスクリプト
/* 指定ページ間内の、奇数のページだけを削除するスクリプト*/
StartPage = 2; /* Acrobat上に出ている開始ページ-1(0頁スタートで考える)を指定(よって、必ず偶数)*/
EndPage = 1566; /* Acrobat上に出ている終了ページ-1(0頁スタートで考える)を指定(よって、必ず偶数)*/

MoveTimes = (EndPage - StartPage)/2;
for (i = 0; i < MoveTimes; i++) {
 deletePage = EndPage-2*i;
 this.deletePages(deletePage);
}

 注意点は、Acrobat Proで4ページ、と表示されていたら、ActionScriptの方ではそれは3ページとして認識されている、ということです。(0ページがスタートとみなされている)
 DeletePages の文法構造上、1枚1枚削除するしか方法がありませんでした。
1500ページの文書だと、15分くらいかかってしまいます。それでも、手作業に比べれば断然マシだと言えます。
 (必ず奇数)としましたが、if文つけて分岐させれば、偶数でも奇数でも対応できるようになります。メンドクサイのでしてないだけです。
 分岐バージョンは、下の参考ページの方のほうが詳しいです。



参考にしました。ありがとうございます。
・Acrobat Pro DCのスクリプトについてのメモ
https://qiita.com/tetsuya-k/items/eb37668d559ba98d22ac

6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5