0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

InDesign JavaScript ファイルから索引

Last updated at Posted at 2021-10-19

ファイルから索引を作成するスクリプトは、これで良いのかな・・・?

/*
このスクリプトを利用して起こった不具合の責任は取れません。
ご了承下さい。

更新 2021/11/12
*/

// アプリ指定
#target "indesign";

// スクリプト名
var scriptName = "ファイルから索引";

//スクリプトの動作指定(一つのアンドゥ履歴にする、及び、アンドゥ名)
app.doScript(function(){

    // 分割文字
    var splitText = ",";

    // ダイアログ
    var dialogueFlg = confirm("アクティブドキュメントにテキストまたはCSVのファイルから索引の見出しと参照を作成します。" + "\r\r"
    + "参照の検索文字列(正規表現)は「"+ splitText + "」で区切られた9番目になります。" + "\r"
    + "9番目が空白の場合は最下層の項目が参照の検索文字列になります。" + "\r\r"
    + "「検索と置換」の 『正規表現』 での検索の「検索形式」の入力での検索も可能です。"+ "\r\r"
    + "追加する参照が既存の参照と重複する場合は追加しません。" + "\r\r"
    + "ファイルの例(一行目は利用しません)" + "\r"
    + "項目1,読み,項目2,読み,項目3,読み,項目4,読み,参照の検索文字列" +"\r"
    + "動物,どうぶつ,猫,ねこ,三毛(日本固有種),みけ(にほんこゆうしゅ),,,三毛" +"\r"
    + "Id,インデザイン" +"\r"
    + "adobe"
    ,"", scriptName);

    // Noの場合
    if(dialogueFlg == false){

        // 終了
        exit();
    }

    /* 検索文字列以外を使う場合の処理 */
    // 正規表現の検索プロパティのフラグ
    var findGrepPreferencesPropertyFlg = false;

    // 検索形式一覧
    var findFormatList = [];

    // 正規表現の検索のプロパティ名の数だけ変数に入れて繰り返す
    for(var findGrepPreferencesProperty in app.findGrepPreferences.properties){

        // プロパティ名が「findWhat」、「parent」、「bulletChar」、「numberingRestartPolicies」では無い場合
        if(findGrepPreferencesProperty != "findWhat" && findGrepPreferencesProperty != "parent" && findGrepPreferencesProperty != "bulletChar" && findGrepPreferencesProperty != "numberingRestartPolicies"){

            // プロパティの内容が「NothingEnum.NOTHING」、「」、「null」ではない場合
            if(app.findGrepPreferences[findGrepPreferencesProperty] != NothingEnum.NOTHING && app.findGrepPreferences[findGrepPreferencesProperty] != "" && app.findGrepPreferences[findGrepPreferencesProperty] != null){

                findGrepPreferencesPropertyFlg = true;

                // 検索形式を集める
                findFormatList.push(findGrepPreferencesProperty + ":" + app.findGrepPreferences[findGrepPreferencesProperty]);
            }
        }
    }
    /* ここまで */

    // 索引が無い場合
    if(app.activeDocument.indexes.count() == 0){

        // 索引を作成
        app.activeDocument.indexes.add();
    }

    // テキスト検索の初期化
    app.findTextPreferences = NothingEnum.NOTHING;

    // 見出しの最初の数
    var firstTopicNumber = searchTopicNumber(app.activeDocument.indexes.firstItem(),0);

    // テキストファイル読み込みダイアログ
    var openFile = File.openDialog("索引を作成する為のテキストファイルを指定して下さい。","*.txt,*.csv");

    // 読み込むファイルの確認
    if(openFile){

        // ファイルオブジェクト作成
        fileObject = new File(openFile);

        // 読み込み
        var openFlg = fileObject.open("r");

        // 進行状況のパレット
        var processingPalette = new Window("palette", "進行状況", undefined, {closeButton: false});
        processingPalette.orientation = "column";
        processingPalette.alignChildren = ["left","top"];
        processingPalette.spacing = 5;
        processingPalette.margins = 10;
        
        // 子階層のパネル
        var processingPanel = processingPalette.add("panel", undefined, undefined,); 
        processingPanel.text = "参照検索(正規表現)"; 
        processingPanel.preferredSize.height = 80; 
        processingPanel.orientation = "column"; 
        processingPanel.alignChildren = ["left","top"]; 
        processingPanel.spacing = 5; 
        processingPanel.margins = 10;

        // パネルの文章
        var paletteSearchText = processingPanel.add("statictext", [0, 0, 570, 15], undefined);
        processingPanel.add("statictext", undefined, "検索形式 : " + findFormatList.join(" + "));
        var paletteProcessingText = processingPanel.add("statictext", [0, 0, 570, 15], undefined);

        // パレットの文章
        processingPalette.add("statictext", [0, 0, 0, 5], undefined);
        processingPalette.add("statictext", undefined, "「Esc」キーでスクリプトを取消し出来ます(Macは不明)。");
        processingPalette.add("statictext", [0, 0, 0, 5], undefined);
        processingPalette.add("statictext", [0, 0, 595, 55], "処理で文字を選択します。" + "\r"
        + "ドキュメントウィンドウの最小化(「ウィンドウメニュー」>「アレンジ」>「ウィンドウを分離」の後、「ウィンドウメニュー」>「アレンジ」>「最小化」)や各種パネルを閉じておくのをおすすめします。"
        ,{multiline: true});

        // 表示
        processingPalette.show();

        // ファイルが開けた場合
        if (openFlg == true){

            // 検索結果
            var grepResult;

            // 一行分の文字
            var lineText = "";

            // 検索文字
            var searchText = "";

            // 分割後の文字配列
            var splitTextArray;

            // 新規見出し
            var newTopic;

            // 見出し階層数
            var topicHierarchyNumber = 0;

            // 新規参照
            var newReference;

            // 参照追加数
            var referenceNumber = 0;

            // 行数
            var lineNumber = 0;

            // 新規の参照が作成される前の検索結果の最初の挿入点のIndex
            var previousReferenceFirstInsertionPointsIndex;

            // 対象の文字
            var targetCharacter;

            // 対象のIndex
            var targetIndex;

            // 項目数
            var topicNmuber = 0;

            // 検索結果数
            var searchNumber = 0;

            // 最後の行まで繰り返す
            while (!fileObject.eof){

                // 初期化
                topicHierarchyNumber = 0;

                // 一行読み込み
                lineText = fileObject.readln();

                // 増やす
                lineNumber++;

                // 一行目の場合
                if(lineNumber == 1){

                    // 次の繰り返しへ
                    continue;
                }

                // 分割文字で分割
                splitTextArray = lineText.split(splitText);

                // 項目1が空白で無い、かつ、分割の数が9以下の場合
                if(splitTextArray[0] != "" && splitTextArray.length <= 9){

                    // 増やす
                    topicNmuber++;

                    // 初期化
                    newTopic = app.activeDocument.indexes.firstItem();

                    // 項目の数だけ繰り返す
                    for(var i = 0; i <= splitTextArray.length - 1 && i < 8; i += 2){

                        // 初期化
                        searchText = "";

                        // 索引項目(見出し)が空白で無い場合
                        if(splitTextArray[i] != ""){

                            // 入れる
                            topicReading = splitTextArray[i + 1];          

                            // エラー処理
                            try{

                                // 見出し作成
                                newTopic = newTopic.topics.add(splitTextArray[i],splitTextArray[i + 1]);

                            // エラーの場合
                            }catch(e){

                                // 警告
                                alert("見出しが作成出来ませんでした。" + "\r" + "「索引」ウィンドウの「ソートオプション...」メニューを確認して下さい。");

                                // 繰り返しから抜ける
                                break;
                            }

                            // 見出しの階層数を増やす
                            topicHierarchyNumber++;
                        }
                    }

                    // 分割が9つ有る場合
                    if(splitTextArray.length == 9){

                        // 入れる
                        searchText = splitTextArray[8];

                    // 以外の場合
                    }else{

                        // 最下層の項目部分の分割を入れる
                        searchText = splitTextArray[topicHierarchyNumber * 2 - 2];
                    }   

                    // 検索文字文字列、もしくは、検索形式が有る場合
                    if(searchText != "" || findGrepPreferencesPropertyFlg == true){

                        // 検索文字列
                        app.findGrepPreferences.findWhat = searchText;

                        // 処理中表示
                        paletteSearchText.text = "検索文字列 : " + searchText;
                        paletteProcessingText.text = "進行状況 : 項目:" + topicNmuber + " 検索結果:0";

                        // ドキュメント全体から検索
                        grepResult = app.activeDocument.findGrep();

                        // 検索結果の数だけ繰り返す
                        grepResultLabel:
                        for(var i = 0; i < grepResult.length; i++){

                            // 入れる
                            searchNumber = i + 1;

                            // 処理中表示
                            paletteProcessingText.text = "進行状況 : 項目:" + topicNmuber + " 検索結果:" + searchNumber;

                            // 検索結果を選択
                            grepResult[i].select();

                            // 選択の最初の挿入点のIndexを入れる(参照を作成するとIndexが変化するので)
                            previousReferenceFirstInsertionPointsIndex = app.activeDocument.selection[0].insertionPoints.firstItem().index;

                            // 参照形式を指定して参照作成
                            newReference = newTopic.pageReferences.add(grepResult[i],PageReferenceType.CURRENT_PAGE);

                            // 参照の位置がずれる場合(バグ?)
                            if(previousReferenceFirstInsertionPointsIndex != newReference.sourceText.index){

                                // 参照の挿入点を移動させる
                                newReference.sourceText.parent.characters.item(newReference.sourceText.index)
                                .move(LocationOptions.BEFORE,newReference.sourceText.parent.characters
                                .item(newReference.sourceText.index + previousReferenceFirstInsertionPointsIndex - newReference.sourceText.index));
                            }

                            // 追加
                            referenceNumber++;

                            /* 重複しているか */
                            // 対象のIndex
                            targetIndex = newReference.sourceText.index;

                            // 最初の挿入点では無い場合
                            if(targetIndex != 0){

                                // 前に調べていく
                                while(targetIndex >= 0){

                                    // 減らす
                                    targetIndex--;

                                    // 対象の文字
                                    targetCharacter =newReference.sourceText.parent.characters.item(targetIndex);

                                    // 検索文字列
                                    app.findTextPreferences.findWhat = "^I";

                                    // 索引マーカーが検索された場合
                                    if(targetCharacter.findText().length > 0){

                                        // 追加した参照のひとつ前から前に繰り返す
                                        for(var ii = newReference.parent.pageReferences.count() - 2; ii >= 0; ii--){

                                            // 対象のマーカーの挿入点が新規追加した参照の目次の参照の挿入点と同じ場合
                                            if(targetCharacter.insertionPoints.firstItem() == newReference.parent.pageReferences.item(ii).sourceText){

                                                // 参照を削除
                                                newReference.remove();

                                                // 減らす
                                                referenceNumber--;

                                                // ラベルの次の繰り返しへ
                                                continue grepResultLabel;
                                            }
                                        }
                                    }

                                    // 検索文字列
                                    app.findTextPreferences.findWhat = "^a";

                                    // アンカー付きオブジェクトマーカーが検索された場合
                                    if(targetCharacter.findText().length > 0){

                                        // 次の繰り返しへ
                                        continue;
                                    }

                                    // 抜ける
                                    break;
                                }
                            }
                            /* ここまで */

                        }
                    }
                }
            }

            // ファイルを閉じる
            fileObject.close();

        // 開けなかった場合
        }else{

            // 警告
            alert("ファイルが開けませんでした。");
        }

    // キャンセルの場合
    }else{

        // 終了
        exit();
    }

    // 索引の更新
    app.activeDocument.indexes.firstItem().update();

    // 初期化
    app.findTextPreferences = NothingEnum.NOTHING;
    app.findGrepPreferences.findWhat = NothingEnum.NOTHING;

    // 選択の解除
    app.activeDocument.selection = NothingEnum.NOTHING;

    // 見出しの追加数
    var additionalTopicNumber = searchTopicNumber(app.activeDocument.indexes.firstItem(),0) - firstTopicNumber;

    // 結果
    alert("見出し追加数:" + additionalTopicNumber + "\r"
    + "参照追加数:" + referenceNumber);

//スクリプトの動作指定の続き
}, ScriptLanguage.JAVASCRIPT, [scriptName], UndoModes.ENTIRE_SCRIPT, scriptName);

// 見出しの数検索用
function searchTopicNumber(targetTopic,topicNumber){

    // 見出しの数だけ繰り返す
    for(var i = 0; i < targetTopic.topics.count(); i++){

        // 数を追加
        topicNumber++;

        // 循環
        topicNumber = searchTopicNumber(targetTopic.topics.item(i),topicNumber);
    }

    // 数を返す
    return topicNumber;
}
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?