TAWAMIラボ

2021/03/31 InDesign Script

InDesignスクリプトでメニューをいじる話

できること

  • あるメニュー(たとえばテキストの右クリックメニュー)に、別のメニュー(たとえば段落パネルメニュー)のメニュー項目を追加する。
  • サブメニューやメニューの区切り線を作る。
  • メニューアイテムを削除する(自分で追加した分以外はやらない方がいい)。
  • スクリプトを実行するための新しいメニュー項目を作る。

とかできます。

Menuオブジェクトについて

メニューをスクリプトでいじるのに重要なオブジェクトとして、MenuオブジェクトとMenuActionオブジェクトの2つがあります。

Menuオブジェクトは「メニューバーのメニュー」とか「段落パネルのメニュー」とかに相当するオブジェクトで、サブメニューや個々のメニュー項目(メニューアイテム)を子として持ちます。

Menuオブジェクトのコレクションは app.menus です。
まずはこのMenuオブジェクトの名前の一覧を作っておきましょう。

var s=""; var menus=app.menus; for(var i=0;i<menus.length;i++){ s+=menus[i].name+"\n"; } var f0=File("~/desktop/InDesignメニュー一覧.txt"); f0.open("w"); f0.write(s); f0.close();

このスクリプトを実行すると、デスクトップに「InDesignメニュー一覧.txt」というファイルができます。
今後、たとえばテキストの右クリックメニューを取得したいとなったら、この一覧の中からそれっぽい名前を探します。144番目(InDesign2020の場合)の「文字のコンテキストメニュー」がそれですので、

app.menus.item("文字のコンテキストメニュー");

で取得します。
ちなみにページアイテムの右クリックメニューは「レイアウトのコンテキストメニュー」です。

なお、0番目に「Main」というのがありますが、これはメニューバーのメニューのことです。
ファイルメニューや編集メニューなどは「Main」のサブメニューになっていますので、ファイルメニューは

app.menus[0].submenus.item("ファイル");

のようにして取得できます。

MenuActionオブジェクトについて

MenuActionオブジェクトは、各メニューアイテムが選択されたときに実行される動作(メニューアクション)を指すオブジェクトです。

メニューアイテムとメニューアクションは必ずしも1対1で存在するものではなくて、たとえば編集メニューの「ペースト」と右クリックメニューの「ペースト」はそれぞれ別のメニューアイテムですが、それに関連付けられたメニューアクションは同じものです。
言い換えれば1つのメニューアクションから、いろんなところにメニューアイテムを作ることができるということです。

MenuActionオブジェクトのコレクションは app.menusActions で取得できます。
例によってまずは一覧を取得しておきましょう。

var s=""; var menuActions=app.menuActions; for(var i=0;i<menuActions.length;i++){ s+=menuActions[i].id+","+menuActions[i].name+"\n"; } var f0=File("~/desktop/InDesignメニューアクション一覧.txt"); f0.open("w"); f0.write(s); f0.close();

メニューよりかなり多いので少し時間がかかりますが、デスクトップに「InDesignメニューアクション一覧.txt」というファイルができます。
今回はIDも一緒に取得しました。カンマの前がID、後が名前です。

それでは、例として特殊文字の「改段」を挿入する動作のMenuActionオブジェクトを取得してみます。
メニューアイテムとしては、メニューバー>書式>分割文字の挿入 の中にある「改段」のことです(右クリックメニューにもあります)。

MenuActionの名前は「改段」なので、

app.menuActions.item("改段");

で取得できるはず…なのですが、これには問題があります。
さきほどの一覧を検索してみると、「改段」という名前のMenuActionオブジェクトは5つあります。
IDでいうと18703,18780,119656,127806,127824の5つですね。
なのでこの方法では複数のMenuActionオブジェクトが同時に取得されてしまいエラーの元になります。

そこで、itemByIDを使ってIDから取得するという手があります。
メニューアクションを実行するメソッドinvokeを使って、

app.menuActions.itemByID(18703).invoke();

などと5つのIDを順に試していくと、どうやらID:119656がまともに動く「改段」の挿入であることがわかりました。
したがって今後は

app.menuActions.itemByID(119656); //改段の挿入

を使っていこう、ということになります。

もっと確実な方法もあります。

Menuオブジェクトからサブメニューをたどって、MenuItemオブジェクトを取得し、そのプロパティからassociatedMenuAction(関連付けられたメニューアクション)を参照する、という方法です。

app.menus[0].submenus.item("書式").submenus.item("分割文字の挿入").menuItems.item("改段").associatedMenuAction;

メニューを作ってみる

例として『グリッドフォーマットを適用せずにペースト』を、文字のコンテキストメニューに追加する、というのをやってみましょう。

これにはまずグリッドフォーマットを適用せずにペーストのメニューアクションが必要です。
先ほどの一覧を検索してみると「グリッドフォーマットを適用せずにペースト」は1つしかないようなので

var menuAction1=app.menuActions.item("グリッドフォーマットを適用せずにペースト");

で大丈夫です。
あとは文字のコンテキストメニューのMenuオブジェクトを取得して、menuItemsコレクションのaddメソッドを使えばできあがり。
※フレームグリッド内の右クリックでないと表示されないことにご注意ください

var menuAction1=app.menuActions.item("グリッドフォーマットを適用せずにペースト"); var menu1=app.menus.item("文字のコンテキストメニュー"); menu1.menuItems.add(menuAction1);

しかしこれでは追加されるのがメニューの一番下になります。
できれば「ペースト」の近くに作りたいですよね。

というわけで、今作ったメニューアイテムはいったん削除します。

app.menus.item("文字のコンテキストメニュー").menuItems.item("グリッドフォーマットを適用せずにペースト").remove();

「ペースト」の一つ下に追加するためには、ペーストのMenuItemオブジェクトを取得して、addの第2引数を「LocationOptions.AFTER」に、第3引数を取得したMenuItemオブジェクトにします。
こんな感じ。

var menuAction1=app.menuActions.item("グリッドフォーマットを適用せずにペースト"); var menu1=app.menus.item("文字のコンテキストメニュー"); var menuItem1=menu1.menuItems.item("ペースト"); menu1.menuItems.add(menuAction1,LocationOptions.AFTER,menuItem1);

ほかにも「メニューアイテムの1つ上」とか「メニューの先頭」とかも選べます。
詳しくはお~まちさんのDOMなどをご覧ください。

続くかも


コメント(3)

  1. Name:よっしー Date:2021/04/20 14:37[返信]

    はじめまして。
    Sppyへの質問なのですが、最新の記事なのでこちらに書かせていただきます。

    Sppy v1.4なのですが、Illustrator CS6(64bit)でスクリプトを実行すると「Error: 0x800401F3 – クラス文字列が無効です Line# 798: Return,ComObjActive(progID)」とエラーが表示されます。

    Illustrator 2020では正常に動作しているので、ProgIDの指定の問題だと思うのですが、Illustrator CS6(64bit)はデフォルトのC:\Program Files\Adobe\Adobe Illustrator CS6 (64 Bit)にインストールしてあります。
    asl.iniの一番下の行に
    AiProgId2=Illustrator.Application.CS6
    を書き加えても
    AiProgId2=Illustrator.Application.CS5
    を書き加えたも同じエラーが表示されます。

    レジストリで確認したところ、確かにCS6のProgIdがIllustrator.Application.CS5になっていました。

    あるふぁ(仮)さんのtwitterで「GetObject(,”Illustrator.Application.CS6″)のかわりにGetObject(“new:{63755935-C25A-42DF-87A1-51F144A0C216}”)で動きませんか?」というツイートを見たのですが、Sppyの「AiProgId2=Illustrator.Application.CS5」の箇所もCLSIDで記述できないでしょうか?
    試してみたのですが、asl.iniにどう書き加えればいいのかわかりません。
    どうぞよろしくお願いいたします。

    • Name:kawamoto_α Date:2021/04/26 13:40[返信]

      返事遅くなってすいません。
      「AiProgId2=Illustrator.Application.CS6」を書く位置ですが、昔は一番下でよかったんですが、その後の機能追加で一番下じゃなくなってます。
      [asl]の下([extra]より上)に書いてください。

      AiProgId2=Illustrator.Application.CS6
      でも
      AiProgId2=Illustrator.Application.CS5
      でもダメだったら
      AiProgId2={63755935-C25A-42DF-87A1-51F144A0C216}
      を試してみてください

  2. Name:よっしー Date:2021/04/26 14:22[返信]

    お返事、どうもありがとうございます。

    結局
    AiProgId2=Illustrator.Application.CS6
    でも
    AiProgId2=Illustrator.Application.CS5
    でもダメで、
    AiProgId2={63755935-C25A-42DF-87A1-51F144A0C216}
    で無事動作いたしました。

    たぶん複数のIllustratorがインストールしてあるせいだと思います。
    「AiProgId2=Illustrator.Application.CS5」では特定出来無かったと…

    どうもありがとうございました。

kawamoto_α へ返信する コメントをキャンセル

メールアドレスが公開されることはありません。