全角数字の字形を変更する

印刷物を組版するとき、「5月26日」というように、1文字の数字は全角、2文字以上は半角にすることがよくあります。お客さんによっては全角の数字が幅広に見えるのを嫌がるので、そんなときは半角っぽく見える全角数字の字形を使います。仕事がつまっているときに、チクチクと数字の字形を変える作業をしているとイラっとするので、スクリプトを書きました。

【 動作確認 】
Windows7 x64
InDesign CS4

【 使い方 】
1) 全角数字が含まれるテキストを範囲選択します。

2) 本スクリプトを実行します。

これにより、選択テキストの中の、全角数字の字形が変更されます。

/*
 * 全角数字の字形を変更する
 * 
 * Rev01 2011.05.26 初版
 *
 * 参考ページ: 丸数字などを簡単に変換できる「round_num 0.3」
 *             http://d.hatena.ne.jp/seuzo/20090527/1243353039
 */

/*******************************************************************************
 * グローバル変数
 *******************************************************************************/
var docObj = app.activeDocument;
var targetObj = new Array();

main();

/*******************************************************************************
 * [概要] メインルーチン
 *******************************************************************************/
function main() {
 if (app.documents.length == 0) {
    myError("文書が開かれていません。\n文書を開いて、テキストを選択してから実行してください。");
  } else if (app.activeDocument.selection.length == 0) {
    myError("何も選択されていません。\nテキストを選択してから実行してください。");
  } else {
    var selObj = docObj.selection[0];
    var objType = selObj.reflect.name;
    //alert(objType);
    objType = "Text, TextColumn, Story, Paragraph, Line, Word, Character, TextStyleRange, Table, Cell".match(objType);
    if (objType == null) {
      myError("テキストを選択してから実行してください。");
    }
  }

  // 変換対象の文字を拾い出す
  var hitObj = my_regex(selObj, "[0123456789]");
  for (i = 0; i < hitObj.length; i++) {
    //$.writeln(hitObj[i].contents);
    targetObj.push(hitObj[i]);
  }
  if (targetObj.length == 0) {
    myError("選択されたテキストの中に、全角数字はありませんでした。");
  }

  // CIDテーブルのセット
  var my_tbl = new Array(); // my_tblはCID番号の配列
  my_tbl[0] = [ 780,  781,  782,  783,  784,  785,  786,  787,  788,  789]; // 標準の全角数字
  my_tbl[1] = [9872, 9873, 9874, 9875, 9876, 9877, 9878, 9879, 9880, 9881]; // subscriptの全角数字
  
  // ターゲットをループ
  var my_count = 0;
  var tmp_result = "";
  //$.writeln("対象文字列の長さ = " + targetObj.length);
  for (i = 0; i < targetObj.length; i++) {
    var my_contents = targetObj[i].contents;  //ターゲットのテキスト
    //$.writeln(my_contents);
    var my_font = targetObj[i].appliedFont;   //ターゲットテキストのフォント

    for (var num = 0; num < 10; num++) {
      //字形検索置換
      try {
        tmp_result = change_glyph(targetObj[i], my_font, my_tbl[0][num], my_font, my_tbl[1][num]);
        if (tmp_result != "") {
          my_count++;
        }
      } catch(e) {
        targetObj[i].contents = my_contents;
      }
    }
  }

  // 結果レポート
  if (my_count == 0) {
    alert ("変更箇所はありませんでした。\n指定された字形を持たないフォントが使われている可能性があります。");
  } else if (targetObj.length > my_count) {
    var failure_count = targetObj.length - my_count;
    alert (targetObj.length + "箇所中、" + my_count + "箇所の数字を変換しました\n失敗した" + failure_count + "箇所については字形を持たないフォントが使われている可能性があります。");
  } else {
    alert ( my_count + "箇所の数字を変換しました");
  }
}

/*******************************************************************************
 * [概要] 字形検索置換
 *
 * [引数]
 *   my_range_obj : 検索置換の対象範囲
 *   find_font    : 変換前のフォント
 *   find_gid     : 変換前のglyph ID
 *   change_font  : 変換後のフォント
 *   change_gid   : 変換後のglyph ID
 *
 * [戻り値]
 *   置換後のオブジェクト
 *
 *******************************************************************************/ 
function change_glyph(my_range_obj, find_font, find_gid, change_font, change_gid) {
  var my_doc = app.activeDocument;
  app.findGlyphPreferences = NothingEnum.nothing;
  app.changeGlyphPreferences = NothingEnum.nothing;
  app.findGlyphPreferences.appliedFont = find_font;
  app.changeGlyphPreferences.appliedFont = change_font;
  app.findGlyphPreferences.glyphID = find_gid;
  app.changeGlyphPreferences.glyphID = change_gid;
  var my_result = my_range_obj.changeGlyph ();
  return my_result;
}

/*******************************************************************************
 * [概要] 正規表現で検索して、ヒットオブジェクトを(お尻から)返す
 *
 * [引数]
 *   my_range_obj : 選択されているテキスト
 *   my_find_str  : 正規表現
 *
 * [戻り値]
 *   正規表現検索にマッチした文字列の配列
 *
 *******************************************************************************/ 
function my_regex(my_range_obj, my_find_str) {
  //検索の初期化
  app.findGrepPreferences = NothingEnum.nothing;
  app.changeGrepPreferences = NothingEnum.nothing;
  //検索オプション
  app.findChangeGrepOptions.includeLockedLayersForFind = false;  // ロックされたレイヤーをふくめるかどうか
  app.findChangeGrepOptions.includeLockedStoriesForFind = false; // ロックされたストーリーを含めるかどうか
  app.findChangeGrepOptions.includeHiddenLayers = false;         // 非表示レイヤーを含めるかどうか
  app.findChangeGrepOptions.includeMasterPages = false;          // マスターページを含めるかどうか
  app.findChangeGrepOptions.includeFootnotes = false;            // 脚注を含めるかどうか
  app.findChangeGrepOptions.kanaSensitive = true;                // カナを区別するかどうか
  app.findChangeGrepOptions.widthSensitive = true;               // 全角半角を区別するかどうか

  app.findGrepPreferences.findWhat = my_find_str;                // 検索文字の設定
  //app.changeGrepPreferences.changeTo = my_change_str;          // 置換文字の設定
  return my_range_obj.findGrep(true);                            // 検索の実行(reverse)
}

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

【 免 責 】

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

【 注 意 】

フォントによっては、上記のスクリプトで変換した等幅半角字形と、欧文数字の字形の見た目に大きな差がありますので、変換後の字形をよく見てください。参考までに、いくつかのフォントで本スクリプトを実行した結果を示します。