Illustrator で文書内の画像のパス一覧を書き出す JavaScript

Illustratorの画像ファイルのリンクが切れたときなんて記事を書いたので、せっかくだから俺は赤い扉を画像のリンク先をどばーっと書き出すJSを書いてみた。\(^o^)/オワタになってないかどうかの確認用です。
10.0向けに作って、一応CSに対応させたつもり。リファレンス見たかぎりCS2以降も大丈夫だと思うけど、環境がないので動作確認はWindows版Illustrator10.0とCSのみ行ってます。

// アクティブな文書内の画像の絶対パスを外部テキストファイルに書き出す
// ドキュメントのあるフォルダに「linkPath_<ドキュメント名>.txt」をつくって書き出し
// 埋め込みオブジェクトについても、ファイル情報があるものはとりあえず取得してみた

// Illustratorのバージョン(2桁の数字)
var appVersion = parseInt(version.substr(0,2),10);
// アクティブドキュメント取得しておく
var actDoc = activeDocument;

// ドキュメント上の画像を取得
var placed = actDoc.placedItems; // AI/PSD/EPS/PDF(埋め込むと編集できるもの)
var raster = actDoc.rasterItems; // ビットマップ画像

// パス文字列格納用の配列を作成
var resultArr = new Array;

// 配置画像について処理
var placedLen = placed.length;
for (var i = 0; i < placedLen ; i++) {
  var tmp = placed[i];
  var status = "Link"; // placedItemはリンクしかないので分岐なし
  var fileName = (appVersion > 10) ? decodeURI(tmp.file.absoluteURI) : tmp.file.fullName;
  resultArr.push(status + "\t" + fileName);
}

// ビットマップ画像について処理
var rasterLen = raster.length;
for (var i = 0; i < rasterLen ; i++) {
  try {
    var tmp = raster[i];
    if (tmp.file) {
      var status = (tmp.embedded) ? "Embed" : "Link"; // リンクか埋め込みか
      var fileName = (appVersion > 10) ? decodeURI(tmp.file.absoluteURI) : tmp.file.fullName;
    }
    resultArr.push(status + "\t" + fileName);
  } catch (e) {
    // リンク先ファイルの情報のない画像(ラスタライズしたものとか)は
    // fileプロパティにアクセスするとエラーになるので何も処理させない
  }
}

// ここから外部ファイルに書き出す処理
var saveFolder = actDoc.path; // アクティブなドキュメントの保存フォルダ
var actDocName = actDoc.name; // アクティブなドキュメントの名前

// 新規ファイルオブジェクトをつくる
var saveFile = new File(saveFolder + "/linkPath_" + actDocName + ".txt");

// 書き込みモードでファイルを開き、改行でjoinした配列を書き込んで閉じる
saveFile.open("w");
var success = saveFile.write(resultArr.join("\n"));
saveFile.close();

// 書き込みが成功したらダイアログを出す(いらない)
if(success) {
  var saveFileName = (appVersion > 10) ? decodeURI(saveFile.name) : saveFile.name;
  alert("配置画像のパスを保存しました。\n" + "ファイル名 : " + saveFileName);
}
else {
  alert("しっぱいしました");
}
// ここまで外部ファイルに書き出す処理

10.0にはFile.absoluteURIプロパティがなくて、CS以降にはFile.fullNameがないので分岐しています。
日本語ファイル名でもちゃんと日本語になるはず。

Link	/e/ほにゃらら/ほげげげ.eps
Link	/e/ほにゃらら/はちゅねさん.tif
Embed	/e/ほにゃらら/俺の嫁.tif

って感じで書き出されます。

参考

四苦八苦して↑を書いてる間に、なにする?DTP+Webの人が配置画像の相対パスを取得するJSを作られたようです。ていうか相対パスのほうが便利だ……!
イラストレーターのリンクを相対パスでテキストに保存しておくといいかも - なにする?DTP+WEB

Illustratorの画像ファイルのリンクが切れたとき(修正版)

勘違いがあったため、書き直しました。偉そうなこと言って恥ずかしいな……。

自動リンク修正の挙動まとめ

【前提1】Illustratorは画像ファイルへのリンクを絶対パスで記憶している。
【前提2】画像は、ファイルの名前が同じなら同一のファイルとみなされる。ファイル名以外の情報(ファイルサイズ、タイムスタンプなど)は判断材料にならない。

Illustratorで文書を開いたとき、配置されている画像ファイルを以下の順番で探しに行く。

  1. 文書が保持している絶対パスのフォルダ(文書変更なし)
  2. 今回のIllustrator起動後、最後に「再リンク」「リンクの置き換え」などで指定したフォルダ(文書変更あり)*1
  3. 開いている文書が入っているフォルダ(文書変更あり)

上から順番に辿って、記憶されている画像ファイル名と同じ名前のファイルがあったら問答無用でリンクされる。
Illustratorを起動してから一度もリンクの修正を行っていない場合は、2.はすっとばして3.に進む。)
これで見つからなかった場合に、はじめて手動でリンクを設定するダイアログが出る。

なにが危険か

1.は問題ないとして、2.と3.は警告のダイアログも出さず勝手にリンクを修正してしまう。
特にやっかいなのが2.で、たとえば「文書と、それに使用している画像ファイルをそれぞれフォルダにまとめておく」という形で管理しておいたとしても、

ある文書でリンクを手動修正
↓
Illustratorを起動したまま別の(リンクの切れた)文書を開く
↓
画像ファイルを(開いた文書と同じフォルダではなく)「直前に指定したリンク先のフォルダ」へ探しに行く
↓
名前が同じファイルを発見、警告なしでリンク
↓
\(^o^)/オワタ


ってなる。
Windows XPIllustrator 10.0で検証済み。

つまり私は2.と3.を逆に考えていたわけです。危ない危ない。
結論としては同じで、ファイル名はユニークにしましょうね、ってことなんですが……ルールが徹底できてなかったデータを扱う場合に、挙動を知っておくのは意味があるなと思いました。

今後注意すべきことメモ

  • ファイルには必ず一意のファイル名をつける(作業中に古くなったファイルも、別フォルダに隔離するだけじゃなくファイル名まで変える)
  • ちゃんと調べてから書く orz

*1:開いただけなのに、ファイルを閉じるときに「保存しますか?」って出るときがあるのはたぶんこれが原因。ちなみに復帰しても、もう一度同じリンク先の検索が行われるので意味がない。

InDesign CS で索引項目をすべて削除するJavaScript

索引系のスクリプト書いてるとき、テスト用に使ってるもの。
何ら特殊なことはしていません。

// アクティブな文書の索引項目をすべて削除する
if(app.documents.length > 0)
{
  if(app.activeDocument.indexes.length > 0)
  {
    var topics = app.activeDocument.indexes[0].topics;
    while(topics.length > 0) // 見出しがある間ずっとループ
    {
      topics.firstItem().remove();
    }

    alert("削除完了");
  }
}

ついでなので、現在開いているすべての文書に対して同じ処理をするものが↓こちら。

// 開いているすべての文書の索引項目をすべて削除する
if(app.documents.length > 0)
{
  var docs = app.documents;
  var docsLen = docs.length;

  for(i = 0 ; i < docsLen ; i++) // すべての文書に対してループ
  {
    var tmpDoc = docs[i]

    if(tmpDoc.indexes.length > 0)
    {
      var topics = tmpDoc.indexes[0].topics;
      while(topics.length > 0) // 見出しがある間ずっとループ
      {
        topics.firstItem().remove();
      }
    }

  }
    alert("削除完了");
}

そんだけ。
CSでしか確認してないけど、おそらくCS2以降でも動くでしょう。

Illustratorの画像ファイルのリンクが切れたとき

いま駆け込み寺でアツいあのスレの話。

Illustratorは貼りこんだ画像ファイルのリンクを絶対パスで持ってるので、フォルダごと移動などするとリンクが切れる。リンクが切れている文書を開いたとき、元の画像ファイルが見つかれば自動的にリンクを更新し、見つからなければ警告を出す。
そこまではいいとして、問題は以下の挙動。

間違ったことを書いていたので、後ほど別エントリで訂正します。ごめんなさい><

  1. ファイル名が同じなら、同じファイルとみなされる(ファイル名以外の情報は判断材料にならない)
  2. リンク先を探すとき、まず最初に「文書と同一のフォルダに入ってるファイル」から探す。もちろん、判断材料はファイル名のみ。この場合は問答無用でリンクが更新され、警告もなし。
  3. 同じフォルダに見つからなければ、カレントフォルダへ探しに行く。この場合はリンク先を更新するかどうかの警告が出る……はず。
  4. それでも見つからない場合、手動で探してね! ってダイアログが出る。

上記は誤りがあるので、参考にしないでください><

要するに、フォルダを分けるだけの画像ファイル管理は危険がいっぱいってことです。ちょっとした操作で意図しないファイルにリンクしてしまう可能性がかなり高い。
ページごととか折ごととか言ってる暇があったら一意のファイル名にリネームしたほうがいいと思うよ!

ちなみにInDesignはもう少し賢くリンクファイルを見分けてくれるし、マメに警告してくれる。それでも事故を防ぐためには、同じファイル名は使わないのがいいです。
個人的には、人に処理してもらいたいデータを作るときには「こういうふうに操作してくれるはずだから、大丈夫」って考えは排除するべきだと思ってます。それを怠って仕上がりに問題があった場合、相手だけを責めることはできないと思います。自分もこの仕事でお金もらってる身ですから……。

追記:例えばページごとにフォルダ分けるとかしてるなら、ページ番号を画像ファイル名の頭にくっつけるとかが、簡単かつわかりやすくていいかなと思う。工夫すればいっぺんにやれそうだし。

このブログの記事、ちゃんと検索に引っかかるらしい。googleさんもマメだなあ。
検索文字列見てるとなかなか面白くて、今のところInDesignの索引とか外部ファイルの読み書きあたりで来てる人がいるみたい。役に立たない情報でごめんなさいね。
VBを探してる人もいる感じなので、そんな記事も書いてみようかな。JSと両方書くとか。

InDesign CS で選択中のオブジェクト/テキストに含まれる画像ファイルの名前を書き出す JavaScript

オブジェクトだろうがテキストフレームだろうがテキストだろうが、とにかく今選択中のものに含まれている画像のファイル名をだばぁと書き出す。インライングラフィックもおk。

var selectedItems = app.selection;
var str = "";

if(selectedItems.length > 0)
{
  while(selectedItems.length > 0)
  {
    var tempItem = selectedItems.pop();

    if(tempItem.constructor.name == "Image") // 画像を直接選択してる場合
    { var selectedGraphics = [tempItem]; }
    else
    { var selectedGraphics = tempItem.allGraphics; }

    while(selectedGraphics.length > 0)
    {
      str += selectedGraphics.pop().itemLink.name + "\n";
    }
  }

  // 結果表示(strが空のままだったら画像がなかったってことなので通知)
  alert( (str != "") ? str : "画像が含まれていません" );
}
else
{
  alert("何も選択されていません");
}

解説は暇なときに気が向いたら書く。(だんだんいい加減に……)
このままじゃとても使えないので、アレンジが必要。

InDesign CS で文書内の画像のパス一覧を書き出す JavaScript

似たような名前のファイルを使いまわしてると、どのフォルダのファイルにリンクしてるかわからなくなるときがあるので、配置した画像のリンク先をどばーっと書き出すJSを書いてみた。
例によってCS用。でもたぶんCS2とCS3でも動くんじゃないかしら……
せっかくファイルとフォルダのあたりを勉強したので、テキストファイルに書き出してみることにする。

// アクティブな文書内の画像のパスをすべて書き出す
// ドキュメントのあるフォルダに「linkPath_<ドキュメント名>.txt」をつくって書き出し
// ページごとに分ける(「ページ数<タブ>パス<改行>」)

if(app.documents.length > 0) {

  var resultArr = new Array; // 結果文字列の格納用配列(タブ区切りテキスト)

  var pageObjs = app.activeDocument.pages; // ページオブジェクトのコレクション
  var pLen = pageObjs.length;

  // 全ページループ
  for(var p = 0 ; p < pLen ; p++) {

    var tmpPage = pageObjs[p];

    var graphArr = tmpPage.allGraphics; // 現在のページにある画像の配列
    var gLen = graphArr.length;

    // 全画像についてパスを取得、格納用配列に格納
    for(var g = 0 ; g < gLen ; g++) {
      resultArr.push(tmpPage.name + "\t" + decodeURI(graphArr[g].itemLink.filePath));
    }

  } // 全ページループここまで


  // 画像があったらパスの一覧をテキストファイルに保存する
  if(resultArr.length != 0) {

    var saveFolderPath = app.activeDocument.filePath; // アクティブなドキュメントの保存フォルダ
    var actDocName = app.activeDocument.name; // アクティブなドキュメントの名前

    // 新規ファイルオブジェクトをつくる
    var saveFile = new File(saveFolderPath + "/linkPath_" + actDocName + ".txt");

    // 書き込みモードでファイルを開き、改行でjoinした配列を書き込んで閉じる
    saveFile.open("w");
    var success = saveFile.write(resultArr.join("\n"));
    saveFile.close();

    // 書き込みが成功したらダイアログを出す(いらない)
    if(success) {
      alert("リンクされた画像のパスを保存しました。\n" + "ファイル名 : " + decodeURI(saveFile.name));
    }

  }
  else {
    alert("リンクされた画像はありません。");
  }

}

テストがめんどくさいからアクティブな文書だけにしちゃったけど、実際使うなら開いてる文書すべてを一気に処理したほうが楽だろうな。

ちなみにファイル名とか保存先とか決めちゃったのはFile.saveDialogがなんだか使いにくかったから。