外部ファイルの指定に従ってフォントを置換するスクリプト(完成!?かな)

12/15に公開したスクリプトには問題がありました。置換対処のフォントがシステムにインストールされているフォントならば正常に動作するのですが、システムにインストールされていないフォントだと動作しませんでした。フォントオブジェクトを取得するのに、通常ならば下記のようにitemメソッドを使います。

fontObj = app.activeDocument.fonts.item("フォント名");

ところが、システムにインストールされていないフォントが対象の場合、itemメソッドの戻り値が常にnullになってしまいます。しかたがないので、itemメソッドの代わりをする関数を書いて対処しました。
さて、これで当初の目的の「過去にMac版QuarkExpressで作られた文書を、Win版InDesignに変換する作業」が効率化できるかどうか。月曜日に会社で試してみて、結果を報告します。
Windowsへ持っていくと文字化けするビュレットや絵文字も、このスクリプトの中で利用している検索・置換のAPIを使えば簡単に実装できると思います。

12/20 追記:
下記のスクリプトInDesign CS4, CS5では期待どおりに動作することが確認できました。しかし、CS3ではコメントで示してある位置でエラーが発生します。

【 動作確認 】Windows7 x64, InDesign CS4

/*
 * 外部ファイルに記述された対応に従って、文書内のすべてのテキストのフォントを置換する
 * 
 * Rev01 2010.12.14 初版
 * Rev02 2010.12.15 下記のページを参考に、検索・置換機能を使ってフォントを置換する
 *                  ように修正
 *   http://indisnip.wordpress.com/2010/08/24/findchange-missing-font-with-scripting/
 * Rev03 2010.12.18 システムにないフォントの置換ができるように改良
 *
 */

/*******************************************************************************
 * グローバル変数
 *******************************************************************************/
var oldFontList = [];  // 置換前のフォント名のリスト
var newFontList = [];  // 置換後のフォント名のリスト
var newFontObj  = [];  // 置換後のフォントオブジェクトの配列
var fontNameTable = { ExtraLight: 'EL',
                       Light:     'L',
                       Regular:   'R',
                       Medium:    'M',
                       Demibold:  'DB',
                       Bold:      'B',
                       ExtraBold: 'EB' };

main();

/*******************************************************************************
 * [概要] メインルーチン
 *******************************************************************************/
function main() {
  if (app.documents.length == 0) {
    myError("文書が開かれていません。\n文書を開いてから実行してください。");
  }

  readFontReplaceFile();  // 外部ファイルから、旧フォント名と新フォント名の対応を読み込む
  replaceFont();          // 検索・置換機能を使ってフォントを指定のフォントに置き換える
}

/*******************************************************************************
 * [概要] 外部ファイルから、旧フォント名と新フォント名の対応を読み込む
 *******************************************************************************/
function readFontReplaceFile() {
  var fileName = File.openDialog("フォント置換リストを記述したファイルを選択してください");
  if (fileName) {
    var fileObj = new File(fileName);
    var flag = fileObj.open("r");          // ファイルを読み込みモードで開く
    if (flag == true) {
      while (!fileObj.eof) {
        var oneLine = fileObj.readln();    // ファイルから1行読み込む
        var tmpArray = oneLine.split(","); // カンマで文字列を分割して、配列に格納
        oldFontList.push(tmpArray[0]);     // 置換前のフォント名を配列にプッシュ
        var tmpFontObj = app.fonts.item(tmpArray[1]);  // フォントオブジェクトを取得
        if (tmpFontObj != null) {
          newFontList.push(tmpArray[1]);   // 置換後のフォント名を配列にプッシュ
          newFontObj.push(tmpFontObj);     // 置換後のフォントオブジェクトを配列にプッシュ
        } else {
          aleart("システムにインストールされていないフォントです\nフォント名 = "+tmpArray[1]);
        }
      }
    } else {
      myError("ファイル [" + fileName + "] が開けませんでした。");
    }
  } else {
    exit(); // キャンセルボタンがクリックされた場合は、プログラムを終了する
  }
}

/*******************************************************************************
 * [概要] 検索・置換機能を使ってフォントの置換を行う
 *******************************************************************************/
function replaceFont() {
  app.findTextPreferences = NothingEnum.nothing;           // 検索テキストの指定をクリア
  app.changeTextPreferences = NothingEnum.nothing;         // 置換テキストの指定をクリア
  for (var i = 0; i < oldFontList.length; i++) {
    // システムにインストールされているフォントの場合は、itemメソッドにより
    // フォントオブジェクトを取得できる
    var oldFontObj = app.activeDocument.fonts.item(oldFontList[i]);
    if (oldFontObj == null) {
      // システムにインストールされていないフォントの場合は、文書で使われている
      // 全フォントをスキャンしてフォントオブジェクトを取得する
      oldFontObj = getFontObj(oldFontList[i]);
    }
    if (oldFontObj == null) {
      alert("フォントオブジェクトが取得できません\nフォント名 = " + oldFontList[i]);
    }
    app.findTextPreferences.appliedFont = oldFontObj;      // ←←← CS3ではココでエラー発生
    app.changeTextPreferences.appliedFont = newFontObj[i]; // 置換後のフォントを指定
    $.writeln("旧: " + oldFontList[i] + ", 新: " + newFontList[i]);
    app.activeDocument.changeText();                       // 検索・置換を実行
  }
}

/*******************************************************************************
 * [概要] 引数で指定されたフォント名を持つオブジェクトのポインタを返す
 *  
 * [詳細]
 *    本関数は、fontObj.item()メソッドの代替として作成した。
 *    システムにインストールされているフォントならば、fontObj.item(フォント名)で
 *    fontオブジェクトのポインタが取得できるが、システムにインストールされていない
 *    フォントの場合は fontObj.item(フォント名) の戻り値が null になってしまう。
 * 
 * [引数] 
 *    fontNameStr : フォント名
 *
 * [戻り値]
 *    null     → フォントが見つからなかった
 *    null以外 → フォントオブジェクトのポインタ
 *******************************************************************************/
function getFontObj(fontNameStr) {
  var alternativeFontName = "";   // fontTypeを省略形にしたフォント名
  if (fontNameStr in fontNameTable) {
    alternativeFontName = fontNameTable[fontNameStr];
  }

  myDocument = app.activeDocument;
  for (var i = 0; i < myDocument.fonts.length; i++) {
    var fontObj = myDocument.fonts[i];
    //$.writeln(fontObj.name);
    if ((fontObj.name === fontNameStr) ||
          ((alternativeFontName !== "") && (fontObj.name === alternativeFontName))) {
      return(fontObj);
    }
  }

  return(null); // フォントが見つからなかった場合
}

/*******************************************************************************
 * [概要] エラーメッセージを表示して、スクリプトを抜ける
 * 
 * [引数]
 *   msg : エラーメッセージ
 *******************************************************************************/
function myError(msg) { 
  if (arguments.length > 0) { alert(msg); }
  exit();
}

【 補 足 】

上記のスクリプトは、CS4以降でないと正しく動作しません。CS3で試したところ、システムにないフォントを置換しようとすると、上記のスクリプトにコメントで書いた位置でエラーになってしまいます。InD-Boardにも同様の書き込みがありました。
http://dtp-bbs.com/mt/indesignbbs/archives/3685javascript_20091016190455.html

【 免 責 】

上記スクリプトの使用により発生する、データの破損などのあらゆる不具合・不利益については、一切の責任を負いかねますのでご了解ください。