9 返信 最新の回答 日時: Dec 14, 2017 12:43 AM ユーザー:Omachi

    InDesignの表で、セルのコンテンツが特定の文字列の場合に、セルの塗りを設定するスクリプトください(JavaScript)

    Omachi Most Valuable Participant

      Adobe Forum Realで頂いた質問です。本来、スクリプトを一から作ってくれというのはあり得ないんですが、

      アプリケーション自動化総合コミュニティフォーラム」オープンセールということで持ち帰ってきました。

      別に自分で回答しても構わないので、しばらくお付き合いください。

       

      要件は次の通りです。

      特定の文字列スウォッチ名
      あかC=0 M=100 Y=100 K=0
      あおC=100 M=50 Y=0 K=0
      きいろC=0 M=0 Y=100 K=0

      のような、文字列とスウォッチの組み合わせがあるとします。

       

      InDesignで表を作って、セルに文字を入れていきます。

      ヘッダー 1ヘッダー 2ヘッダー 3ヘッダー 4
      しろ235適当な文字あお
      くろあかあかじゃないオレンジ
      ももいろきいろあおきいろ

      こんな感じで入力が終わったら、スクリプトを実行します。

      スクリプトは、セルに入っている文字を調べて、特定の文字列と同じだったらセルの塗りにスウォッチを指定します。

       

      というものです。

       

      これが物足りないという方には次のレベル。

      「これを入力中に自動的に色が付くようにしてほしい」

      いや、それをするときはずっとInDesignを監視していなければいけないので、ものすごく大変なんです。

      といいましたら、納得して頂いたので、そこまで求められているわけではありません。

      自己研鑽したい方はどうぞ(^^;

       

      初めにも書きましたが、これは私が受けてきたので、最終的には私が責任をもって回答しますが、少し時間がかかります。

      その前に「できたから書きたい」という方がおられましたらご自由にどうぞ、ということです(^^)

        • 1. Re: InDesignの表で、セルのコンテンツが特定の文字列の場合に、セルの塗りを設定するスクリプトください(JavaScript)
          macneko.ayu Level 1

          CS5 omachi さん

           

          こんばんは。

          下記のスクリプトでどうでしょうか。

          テキストフレームを選択してから実行することを前提にしています。

          セルの背景色にスウォッチを適用するところはスウォッチが存在するか確認してから適用させることが正解だと思ったのですが、ちょっと冗長かなぁと思ったので try 〜 catch で処理しています。

           

          (function () {
              var docObj = app.activeDocument;
              if (app.selection[0].constructor.name !== "TextFrame") { return; }
              if (app.selection[0].tables.length === 0) { return; }
              app.selection[0].tables[0].select();
              var tableObj = app.selection[0];
              for (var i = 0, len = tableObj.cells.length; i < len; i++) {
                  var cellObj = tableObj.cells[i];
                  try {
                      cellObj.fillColor = app.activeDocument.swatches.itemByName(cellObj.contents);
                  } catch (e) {
          
                  }
              }
          })();
          
          

           

          >「これを入力中に自動的に色が付くようにしてほしい」

          EventListener で監視するのがいいんですかねー。

          時間あるときの宿題にしてみます。

          1 人が役に立つと言っています
          • 2. Re: InDesignの表で、セルのコンテンツが特定の文字列の場合に、セルの塗りを設定するスクリプトください(JavaScript)
            Ten A Adobe Community Professional

            イベント操作の例なのですが、選択関連での操作にはAFTER_SELECTION_ATTRIBUTE_CHANGEDが便利かと思います。以下がそのサンプルです。

             

            #targetengine "session"
            
            app.addEventListener(Event.AFTER_SELECTION_ATTRIBUTE_CHANGED , test).name = "eventTest";
            
            function test(ev){
              if (app.selection[0].parent.toString()!="[object Cell]") return;
              alert(app.selection[0].parent.contents);
              }
            

             

            ただし、AFTER_SELECTION_ATTRIBUTE_CHANGEDをそのまま取り回すと全ての操作においてイベントが発生しているため面倒なことになります。その為、Callback関数の冒頭でターゲット以外のものが選択されている場合に処理を中断する仕 組みを組み込んでいます。

            リスナにnameプロパティを当てているのはあとでitemByNameでリスナを停止させるためです。こうしておくと以下の様なワンライナーでイベントリスナを停止させることができます。

             

            app.eventListeners.itemByName("eventTest").remove();
            

             

            以上、イベント関連のTipsでした(^-^)/

            2 人が役に立つと言っています
            • 3. Re: InDesignの表で、セルのコンテンツが特定の文字列の場合に、セルの塗りを設定するスクリプトください(JavaScript)
              Omachi Most Valuable Participant

              >macneko.ayuさん

               

              すみませんが、

              cellObj.fillColor = app.activeDocument.swatches.itemByName(cellObj.contents);
              

              のところ勘違いしてます。

              平たく書けば

              if (cellObj.contents == "あか") {
                   cellObj.fillColor = app.activeDocument.swatches.itemByName("C=0 M=100 Y=100 K=0");
              } else if (...
              

              になります。

               

              この、(条件=特定の文字列と、スウォッチ名のペア)は、あとから変更する可能性が高いので、変数(配列など)で先頭に定義しておく必要があります。(もしくはファイルから読み込むとか)

              よろしくお願いします。

               

              あと、書き忘れてましたが、スウォッチは全て定義済みで、該当するスウォッチが見つからないというエラーは発生しないという前提です(さすがにそこまで面倒見切れません)。

              • 4. Re: InDesignの表で、セルのコンテンツが特定の文字列の場合に、セルの塗りを設定するスクリプトください(JavaScript)
                よそいち Level 1

                前提を「テキストフレーム全体から探す」にした場合

                ということで。case~switch文で分岐しました。

                名称未設定 1.jpg

                 

                  var Doc=app.activeDocument;
                
                
                  //スウォッチを定義
                  var red=Doc.swatches.itemByName("C=0 M=100 Y=100 K=0");//あか
                  var blue=Doc.swatches.itemByName("C=100 M=50 Y=0 K=0");//あお
                  var yellow=Doc.swatches.itemByName("C=0 M=0 Y=100 K=0");//きいろ
                
                
                  //テキストフレーム全体から探す
                  var txtFrms=Doc.textFrames;
                  var tfCount=txtFrms.length;
                  for(var i=0; i<tfCount; i++){
                      var tbs=txtFrms[i].tables;
                      var tbsCount=tbs.length;
                      for(var j=0; j<tbsCount;j++){
                        var ce=tbs[j].cells;
                        var cellCount=ce.length;
                        for(var k=cellCount-1; k>=0; k--)
                          switch(ce[k].contents){
                          case "あか":
                            ce[k].fillColor=red;
                            break;
                          case "きいろ":
                            ce[k].fillColor=yellow;
                          break;
                          case "あお":
                            ce[k].fillColor=blue;
                          break;
                            default:
                            //当てはまらないならスルー
                            break;
                          }
                        }
                    }
                
                1 人が役に立つと言っています
                • 5. Re: InDesignの表で、セルのコンテンツが特定の文字列の場合に、セルの塗りを設定するスクリプトください(JavaScript)
                  Omachi Most Valuable Participant

                  例文をやってみたんですが、AFTER_SELECTION_ATTRIBUTE_CHANGEDだとツールの切り替え時にもイベントが発生してエラーになっちゃいました。そこでAFTER_SELECTION_CHANGEDにしました。

                  結果はあとで投稿します。

                  • 6. Re: InDesignの表で、セルのコンテンツが特定の文字列の場合に、セルの塗りを設定するスクリプトください(JavaScript)
                    Omachi Most Valuable Participant

                    みなさん、書き込みありがとうございます。

                    しかしながら、私の提示の仕方が悪かったです。仕様をもう少し詰めてから書き込めばよかったと反省しています。

                    例示として「あか」「あお」「きいろ」としただけで、実際にどの文字列で反応させるかはお客さんの方で別途指定するというつもりだったんですが、伝わらなかったですね。

                     

                    この後に私の回答を書き込みます。

                    • 既に入力が完了している状態のものに色を付ける場合
                    • 入力中に自動で色を付ける場合

                    の両方のパターンで作成できました。一応テストしたつもりですが、不備がありましたら教えてください。

                    「入力中に自動で色を付ける場合」は自分でも感動しました。是非参考にしてください。

                    私の回答には一応正解マークをつけておきますが、よりよい回答を書き込まれた場合はそちらを正解にします。

                    • 7. Re: InDesignの表で、セルのコンテンツが特定の文字列の場合に、セルの塗りを設定するスクリプトください(JavaScript)
                      Omachi Most Valuable Participant

                      使用者に、セルの色(スウォッチ)と塗るための条件(特定の文字列に等しい)を複数指定してもらい、

                      その指示に従って、セル内の文字列が指定された条件であれば塗りにスウォッチを適用するスクリプト

                       

                      使用者側で、特定の文字列とスウォッチを指定するためのファイル。どちらの動作パターンでも使用します。ファイル名は何でもよい。

                      ###### 指定文字列とスウォッチの設定 ######
                      #
                      # スクリプト起動時にファイル選択ダイアログが出ますので、このファイルを選択してください。
                      #
                      # #で始まる行はコメントとして扱われます。
                      # また、空行は無視されます。
                      # 文字列とスウォッチ名をタブで区切って記述します。
                      # 例
                      # さくら    C=0 M=30 Y=0 K=0
                      #
                      あお    C=100 M=50 Y=0 K=0
                      あか    C=0 M=100 Y=100 K=0
                      きいろ    C=0 M=0 Y=100 K=0
                      

                       

                      既に入力が完了している状態のものに色を付ける場合

                      cellcolor.jsx

                      // セル内の文字が特定の文字列の場合に、セルの塗りを設定するスクリプト
                      
                      if (app.documents.length < 1) {
                          alert("ドキュメントを開いてください");
                          exit();
                      }
                      
                      var cset = [];
                      var tmp, i;
                      var doc = app.activeDocument;
                      var sws = doc.swatches;
                      
                      //定義ファイルの読み込み
                      var iniFile = File.openDialog("設定ファイルを指定してください");
                      iniFile.open("r");
                      while (!iniFile.eof){
                          tmp = iniFile.readln().split("\t");
                          tmp[0] = tmp[0].replace(/^\s+/, "").replace(/\s+$/, "");
                          if (tmp[0] != "" && tmp[0].slice(0, 1) != "#") {
                              tmp[1] = tmp[1].replace(/^\s+/, "").replace(/\s+$/, "");
                              cset.push([tmp[0], tmp[1]]);
                          }
                      }
                      iniFile.close();
                      //スウォッチの存在確認
                      tmp = "";
                      for (i = 0; i < cset.length; i++) {
                          if (!sws.itemByName(cset[i][1]).isValid) {
                              tmp += cset[i][1] + "\r";
                          }
                      }
                      if (tmp != "") {
                          alert("以下のスウォッチが見つかりません\r\r" + tmp +
                              "\rドキュメントを確認するか、" + iniFile.name +
                              "\rファイル中のスウォッチ名を確認してください");
                          exit();
                      }
                      //選択状態の確認
                      var sel = doc.selection;
                      if (sel.length != 1) {
                          alert("表のあるテキストフレームを1つ選択するか、\r" +
                              "表内に文字カーソルを立ててください");
                          exit();
                      }
                      //選択されているオブジェクト別に対象を特定して実行
                      switch (sel[0].constructor.name) {
                          case "TextFrame":
                              //ストーリー中の表全てを対象。テキストフレーム内に限定する場合はsel[0].tables
                              var tbls = sel[0].parentStory.tables;
                              if (tbls.length > 0) {
                                  for (i = 0; i < tbls.length; i++){
                                      cellcolor(tbls[i]);
                                  }
                              } else {
                                  tmp = "notfound";
                              }
                              break;
                          case "Table":
                              cellcolor(sel[0]);
                              break;
                          case "Cell":
                              cellcolor(sel[0].parent);
                              break;
                          case "Text":
                          case "TextStyleRange":
                          case "TextColumn":
                          case "Paragraph":
                          case "Line":
                          case "Word":
                          case "Character":
                          case "InsertionPoint":
                              if (sel[0].parent.constructor.name == "Cell") {
                                  cellcolor(sel[0].parent.parent);
                              } else {
                                  tmp = "notfound";
                              }
                              break;
                          default:
                              tmp = "notfound";
                      }
                      //終了処理
                      if (tmp == "notfound") {
                          alert("表は見つかりませんでした");
                      }
                      
                      //セルに色を付ける
                      function cellcolor(targetTable) {
                          var j, k;
                          var ac = targetTable.cells;
                          for (j = 0; j < ac.length; j++) {
                              for (k = 0; k < cset.length; k++) {
                                  if (ac[j].contents == cset[k][0]) {
                                      ac[j].fillColor = sws.itemByName(cset[k][1]);
                                      break;
                                  }
                              }
                          }
                      }
                      

                       

                      入力中に自動で色を付ける場合

                      スクリプト実行中は、別のファイルを開かないでください。スウォッチの一致しないドキュメントでたまたま条件にあった場合にエラーが出るはずです。

                      また、スクリプト実行中に別のドキュメントを開いて閉じると、追加したイベントが削除されるので、何らかのエラーやメッセージが出る可能性があります。その場合、もう一度スクリプトを実行して みてください。

                       

                      監視動作を開始するスクリプト

                      cellcolor_start.jsx

                      #targetengine "cellColorSession"
                      
                      if (app.documents.length < 1) {
                          alert("ドキュメントを開いてください");
                          exit();
                      }
                      
                      var cset = [];
                      var tmp, i;
                      var doc = app.activeDocument;
                      var sws = doc.swatches;
                      var sws0 = sws.itemByName("None");
                      
                      //定義ファイルの読み込み
                      var iniFile = File.openDialog("設定ファイルを指定してください");
                      iniFile.open("r");
                      while (!iniFile.eof){
                          tmp = iniFile.readln().split("\t");
                          tmp[0] = tmp[0].replace(/^\s+/, "").replace(/\s+$/, "");
                          if (tmp[0] != "" && tmp[0].slice(0, 1) != "#") {
                              tmp[1] = tmp[1].replace(/^\s+/, "").replace(/\s+$/, "");
                              cset.push([tmp[0], tmp[1]]);
                          }
                      }
                      iniFile.close();
                      //スウォッチの存在確認
                      tmp = "";
                      for (i = 0; i < cset.length; i++) {
                          if (!sws.itemByName(cset[i][1]).isValid) {
                              tmp += cset[i][1] + "\r";
                          }
                      }
                      if (tmp != "") {
                          alert("以下のスウォッチが見つかりません\r\r" + tmp +
                              "\rドキュメントを確認するか、" + iniFile.name +
                              "\rファイル中のスウォッチ名を確認してください");
                          exit();
                      }
                      
                      //イベントを追加
                      app.addEventListener(Event.AFTER_SELECTION_CHANGED, fillCellColor).name = "cellColorEvent";
                      
                      function fillCellColor(ev){
                          if (app.selection.length == 0) return;
                          var parentObject = app.selection[0].parent;
                          if (parentObject.constructor.name != "Cell") return;
                          
                          var filled = false;
                          for (var k = 0; k < cset.length; k++) {
                              if (parentObject.contents == cset[k][0]) {
                                  parentObject.fillColor = sws.itemByName(cset[k][1]);
                                  filled = true;
                                  break;
                              }
                          }
                          if (!filled) parentObject.fillColor = sws0;
                      }
                      
                      //ドキュメントを閉じるときに追加したイベントを削除(これをしないと閉じるときにメッセージが出る)
                      app.addEventListener(Event.BEFORE_CLOSE, function (ev) {
                          if (app.eventListeners.itemByName("cellColorEvent").isValid) {
                              app.eventListeners.itemByName("cellColorEvent").remove();
                          }
                      });
                      
                      

                       

                      監視動作を終了するスクリプト

                      途中でやめる場合に使用します。

                      cellcolor_stop.jsx

                      if (app.eventListeners.itemByName("cellColorEvent").isValid) {
                          app.eventListeners.itemByName("cellColorEvent").remove();
                      }
                      
                      • 8. Re: InDesignの表で、セルのコンテンツが特定の文字列の場合に、セルの塗りを設定するスクリプトください(JavaScript)
                        Omachi Most Valuable Participant

                        12月4日 追記

                        cellcolor_start.jsxの44行目に

                        if (app.selection.length == 0) return;
                        

                        を追加しました。何も選択しない場合にエラーが出るのを修正しました。

                        • 9. Re: InDesignの表で、セルのコンテンツが特定の文字列の場合に、セルの塗りを設定するスクリプトください(JavaScript)
                          Omachi Most Valuable Participant

                          追記です。ファイルを開くダイアログで「キャンセル」された場合の処理が抜けていますので、

                          var iniFile = File.openDialog("設定ファイルを指定してください");  

                          のあとに、次を書き加えてください。

                          if (iniFile == null) {
                              alert("キャンセルされました");
                              exit();
                          }