InDesign スクリプト 要素を配置（マスターページをオーバーライドして）

マスターページをオーバーライドして要素を配置するスクリプトは、これで良いのかな・・・？

~~~JavaScript
/*
マスターページをオーバーライドして要素を配置
更新 2021/06/13

配置に使うXMLの例
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<Root>
<!--文字コードに注意-->
<猫の名前 placePageNumber='1' masterPageItemNumber='1'>こはく</猫の名前>
<猫の名前 placePageNumber='2' masterPageItemNumber=''>ぼんた</猫の名前>
<猫の名前 placePageNumber=''>くろい</猫の名前>
</Root>
*/

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

// スクリプト名
var scriptName = "要素を配置（マスターページをオーバーライドして）";

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

    //  配置ページ番号を指定する属性の属性名
    var placePageNumberAssignAttributeName ="placePageNumber";

    // マスターページのページアイテムを指定する属性の属性名
    var masterPageItemAssignAttributeName = "masterPageItemNumber";

    // ダイアログ
    var dialogueFlg = confirm("ページにあるオーバーライドされていないマスターページのページアイテムに要素を配置します。"
    + "\r\r" + "ページを指定するのに" + placePageNumberAssignAttributeName + "名の属性とその値（ページ番号）を使用します。"
    + "\r\r" + placePageNumberAssignAttributeName + "名の属性の値がない場合はページに順に配置されます。"
    + "\r\r" + "ページにあるオーバーライドされていないマスターページのページアイテムを指定するのに" + masterPageItemAssignAttributeName + "名の属性とその値（ページアイテムのページでの順番）を使用します。"
    + "\r\r" + masterPageItemAssignAttributeName + "名の属性、もしくはその値がない場合はページにあるオーバーライドされていないマスターページのページアイテムに順に配置されます。"
    + "\r\r" + "マスターページのページアイテムがロックされている場合はそのページアイテムには配置されません。","", scriptName);

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

        // 終了
        exit();
    }

    // 選択されているオブジェクト
    var selectObjects = [];

    // すべての選択を入れる
    selectObjects = app.activeDocument.selection;

    // すべての選択を解除
    app.activeDocument.selection = null;

    // （属性から取り込んだ）配置ページ番号
    var placePageNumber;

    // （属性から取り込んだ）マスターページのページのページアイテムの順番
    var masterPagePagePageItemAssignNumber;

    // ページの開始Index
    var pageStartIndex;

    // 配置ページ番号がない場合の配置予定ページIndex
    var nowPlacePageIndex = 0;

    // 配置数
    var placeNumber = 0;

    // 選択の数だけ繰り返す
    for(var i = 0; i < selectObjects.length; i++){

        // 初期化
        placePageNumber = "";
        masterPagePagePageItemAssignNumber = "";

        // 選択が要素の場合
        if (selectObjects[i].constructor.name == "XMLElement"){

            // XmlStoryの場合（未配置）
            if(getStoryConstructorName(selectObjects[i]) == "XmlStory"){

                // placePageNumberAssignAttributeName名の属性がある場合
                if(selectObjects[i].xmlAttributes.itemByName(placePageNumberAssignAttributeName).isValid == true){

                    // 属性の値を入れる
                    placePageNumber = selectObjects[i].xmlAttributes.itemByName(placePageNumberAssignAttributeName).value;

                    // 値がない場合
                    if(placePageNumber == ""){

                        // 配置ページ番号がない場合の配置予定ページIndexを入れる
                        pageStartIndex = nowPlacePageIndex;

                    // 属性の値が数字の場合
                    }else if(placePageNumber.match(/^[1-9][0-9]*$/) != null){

                        // 0を入れる
                        pageStartIndex = 0;

                     // 以外の場合
                     }else{

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

                    // masterPageItemAssignAttributeName名の属性がある場合
                    if(selectObjects[i].xmlAttributes.itemByName(masterPageItemAssignAttributeName).isValid == true){

                        // 属性の値を入れる
                        masterPagePagePageItemAssignNumber = selectObjects[i].xmlAttributes.itemByName(masterPageItemAssignAttributeName).value;

                        // 値がある場合
                        if(masterPagePagePageItemAssignNumber != ""){

                            // 属性の値が数字ではない場合
                            if(masterPagePagePageItemAssignNumber.match(/^[1-9][0-9]*$/) == null){

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

                    // 配置ページフラグ
                    var placePageFlg;

                    // ページの数だけ繰り返す（ラベルpageRepeat）
                    pageRepeat : 
                    for(var ii = pageStartIndex; ii < app.activeDocument.pages.length; ii++){

                        // falseを入れる
                        placePageFlg = false;

                        // 値がある場合
                        if(placePageNumber != ""){

                            // ページが存在する場合
                            if(app.activeDocument.pages[ii].name == placePageNumber){

                                // trueを入れる
                                placePageFlg = true;
                            }

                        // 以外の場合
                        }else{

                            // trueを入れる
                            placePageFlg = true;
                        }

                        // trueの場合
                        if(placePageFlg == true){

                            // 値がある場合
                            if(masterPagePagePageItemAssignNumber != ""){

                                // ページにオーバーライドされていないマスターページのページアイテムが存在しない場合
                                if(app.activeDocument.pages[ii].masterPageItems.length == 0){

                                    // 値がある場合
                                    if(placePageNumber != ""){

                                        // 繰り返しを抜ける
                                        break;

                                    // 以外の場合
                                    }else{

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

                                // ページアイテムの順番がマスターページのページアイテムの順番の範囲外の場合
                                if(masterPagePagePageItemAssignNumber > app.activeDocument.pages[ii].masterPageItems[0].parentPage.allPageItems.length){

                                    // 値がある場合
                                    if(placePageNumber != ""){

                                         // 繰り返しを抜ける
                                        break;

                                    以外の場合
                                    }else{

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


                            // オーバーライド許可フラグ
                            var overridePermissionFlg;

                            // ページにあるオーバーライドされていないマスターページのページアイテムの数だけ繰り返す
                            for(var iii = 0; iii < app.activeDocument.pages[ii].masterPageItems.length; iii++){

                                // falseを入れる
                                overridePermissionFlg = false

                                // 値がある場合
                                if(masterPagePagePageItemAssignNumber != ""){

                                    // ページのオーバーライドされていないマスターページのページアイテムのIdとページのオーバーライドされていないマスターページのページアイテムの一つ目のマスターページのページの順番で指定したページアイテムのIdが一致する場合
                                    if(app.activeDocument.pages[ii].masterPageItems[iii].id == app.activeDocument.pages[ii].masterPageItems[0].parentPage.allPageItems[masterPagePagePageItemAssignNumber - 1].id){

                                        // trueを入れる
                                        overridePermissionFlg = true;
                                    }

                                // 以外の場合
                                }else{

                                    // trueを入れる
                                    overridePermissionFlg = true;
                                }

                                // trueの場合
                                if(overridePermissionFlg == true){

                                    // ロックされていない場合
                                    if(app.activeDocument.pages[ii].masterPageItems[iii].locked == false){

                                        // geometricBoundsプロパティを持っている場合
                                        if(app.activeDocument.pages[ii].masterPageItems[iii].hasOwnProperty("geometricBounds") == true){

                                            // 値がない場合
                                            if(placePageNumber == ""){

                                                // iiを入れる
                                                pageStartIndex = ii;

                                                // 自動で配置した事を明記
                                                selectObjects[i].xmlAttributes.itemByName(placePageNumberAssignAttributeName).value = app.activeDocument.pages[ii].name + " (automaticPlacementResults)";

                                            }                                        

                                            // 値がない場合
                                            if(masterPagePagePageItemAssignNumber == ""){

                                                // マスターページのページアイテムの数だけ繰り返す
                                                for(var iiii = 0; iiii < app.activeDocument.pages[ii].masterPageItems[0].parentPage.allPageItems.length; iiii++){

                                                    // Idが同じ場合
                                                    if(app.activeDocument.pages[ii].masterPageItems[iii].id == app.activeDocument.pages[ii].masterPageItems[0].parentPage.allPageItems[iiii].id){

                                                        // ページ番号を書き込む属性が存在する場合
                                                        if (selectObjects[i].xmlAttributes.itemByName(masterPageItemAssignAttributeName).isValid == true) {

                                                            // 自動で配置した事を明記
                                                            selectObjects[i].xmlAttributes.itemByName(masterPageItemAssignAttributeName).value = iiii + 1 + " (automaticPlacementResults)";

                                                        // 存在しない場合
                                                        } else {

                                                            // 属性を追加して自動で配置した事を明記
                                                            selectObjects[i].xmlAttributes.add(masterPageItemAssignAttributeName,iiii + 1 + " (automaticPlacementResults)");
                                                        }
                                                    }
                                                }
                                            }

                                            // オーバーライドして配置
                                            selectObjects[i].placeXML(app.activeDocument.pages[ii].masterPageItems[iii].override(app.activeDocument.pages[ii]));

                                            // 数を増やす
                                            placeNumber++;

                                            // pageRepeatへ抜ける
                                            break pageRepeat;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    // 結果を表示
    alert("選択数 "  + selectObjects.length + "\r" + "配置数 " + placeNumber, scriptName);

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

/* ストーリーのコンストラクタ名を取得する関数、引数（オブジェクト）の宣言 */
function getStoryConstructorName(anyObject) {

    // parentStoryプロパティが存在する場合
    if (anyObject.hasOwnProperty("parentStory") == true) {

        // エラー処理
        try{

            // parentStoryの値がある場合
            if (anyObject.parentStory) {

                // コンストラクタ名を戻す
                return anyObject.parentStory.constructor.name;
            }

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

            // 抜ける
            return;
        }

    // Applicationの場合
    } else if (anyObject.constructor.name == "Application") {

        // 抜ける
        return;
    }

    // オブジェクトの階層を一つ上げて再帰関数
    return getStoryConstructorName(anyObject.parent);
}
/* ストーリーのコンストラクタ名を取得する関数の宣言終了 */
~~~