Skip to main content
Inspiring
July 15, 2022
解決済み

How to find whether my textFrame have OverriddenObjectStyle or not in my document using javascript

  • July 15, 2022
  • 返信数 2.
  • 2792 ビュー

I am trying to find all overridden ObjectStyles and where it is overridden in document! but i didn't find any solution regarding this online..there is only option to clearOverridden objectStyles. If anyone knows please help!

このトピックへの返信は締め切られました。
解決に役立った回答 m1b

And one last addition, for anyone who is interested. I've made huge improvements under the hood, including quite good xml parsing (thanks to Peter Sirka's nifty little function—see script comments) and displays the differences with much better context. The underlying function listDifferences(items,options) can now handle two or more files, and the formatting is separated.

- Mark

 

 

 

/**
 * Shows object style override differences
 * for the selected page item.
 *  m1b
 *  2022-07-18
 * @discussion https://community.adobe.com/t5/indesign-discussions/how-to-find-whether-my-textframe-have-overriddenobjectstyle-or-not-in-my-document-using-javascript/m-p/13071120
 *
 * Important note:
 * This is more strict than Indesign's own
 * object-style-overridden criteria, so
 * sometimes an object may show differences
 * while not showing the (+) symbol in the
 * Object Style panel.
 */

function main() {

    var doc = app.activeDocument,
        item = doc.selection[0];

    if (item.isValid)
        showObjectStyleOverrides(item);

}




/**
 * Determines if item has ObjectStyle overrides
 * and displays a list of the overriden properties.
 *
 *  m1b
 *  2022-07-18
 * @discussion https://community.adobe.com/t5/indesign-discussions/how-to-find-whether-my-textframe-have-overriddenobjectstyle-or-not-in-my-document-using-javascript/m-p/13071120
 *
 * Note: this function is MORE STRICT
 * than Indesign's normal determination
 * of overridden-ness.
 *
 *  {PageItem} item - an Indesign page item.
 *  {Boolean} - if true, then object has overrides.
 */
function showObjectStyleOverrides(item) {

    if (
        item == undefined
        || !item.isValid
        || typeof item.exportFile !== 'function'
    )
        return;

    // make a duplicate item
    dup = item.duplicate();

    var itemSnippet = saveSnippet(dup, 'item.xml');

    // with no objectStyle overrides
    dup.clearObjectStyleOverrides();

    // and make a snippet of that
    dupSnippet = saveSnippet(dup, 'dup.xml');

    // clean up
    dup.remove();

    // set up arguments for listDifferences
    var comparisons = [
        { label: 'PageItem', file: itemSnippet },
        { label: 'Object Style', file: dupSnippet }
    ];

    // in snippet XML, we don't care about these
    var options = { ignoreThese: /x:xmpmeta/ };

    // collect differences between the two
    var differences = listDifferences(comparisons, options);

    // display differences
    if (differences.length > 0)
        alerter(differences.length + ' Object Style Overrides', formatDifferences(differences), 1000, 500);
    else
        alert('This item has no Object Style overrides.');

}




/**
 * Compares XML text or XML text files and
 * returns a text summary of differences.
 *  m1b
 *  2022-07-18
 *
 * 
 * listDifferences(
 *   [
 *     { label: 'PageItem', file: itemSnippetFile },
 *     { label: 'Object Style', xml: dupSnippetText }
 *   ], {
 *     onlyThese: /text/i,
 *     ignoreThese: /color/i
 *   }
 * );
 *
 *  {Array} items - an array of items to compare
 *  {Object} [options] - object with options
 *  {String|RegExp} [options.onlyThese] - test to choose keys
 *  {String|RegExp} [options.ignoreThese] - test to exclude keys
 *  {String} - the formatted different properties
 */
function listDifferences(items, options) {

    var differences = [],
        objs = [],
        labels = [],
        lines = [],
        keys = [],

        // constants
        empty = '-- empty --';


    // initialise the items
    for (var i = 0; i < items.length; i++) {
        var item = items[i];

        // label
        if (item.label == undefined)
            item.label = String.fromCharCode(65 + k);

        // file
        if (
            item.file != undefined
            && item.file.exists
        )
            item.obj = parseXML(readFile(item.file));

        // string
        if (typeof (item.xml) === 'string')
            item.obj = parseXML(item.xml);

        // xml
        if (typeof (item.xml) === 'xml')
            item.obj = parseXML(item.xml.toString());

        // xml text
        if (item.obj == undefined)
            return ['Error: item "' + item.label + '" had no usable XML.'];

        objs[i] = item.obj;
        labels[i] = item.label;
        lines[item.label] = [];

        var itemKeys = item.obj.reflect.properties;

        // collect the item's keys
        for (var k = 0; k < itemKeys.length; k++)

            if (item.obj.hasOwnProperty(itemKeys[k]))
                keys.push(String(itemKeys[k]));

    }

    // combine keys from all items
    var keys = uniquify(keys);


    // expand the key/values

    for (var k = 0; k < keys.length; k++) {

        // current key to compare
        var key = keys[k];

        // add lines by expanding objs recursively
        for (var o = 0; o < objs.length; o++)
            lines[labels[o]] = lines[labels[o]].concat(expandLines(key, objs[o][key]));

    }


    // make an object that has an object for *every* key
    // and store values in that object, using the item's label

    var keys = [],
        comparator = [];

    for (var o = 0; o < objs.length; o++) {

        var label = labels[o];

        linesLoop:
        for (var l = 0; l < lines[label].length; l++) {

            var linesForKey = lines[label][l],
                key = linesForKey[0],
                value = linesForKey[1];

            if (
                options.ignoreThese != undefined
                && options.ignoreThese.test(key)
            )
                // user doesn't want this key
                continue linesLoop;

            if (
                options.onlyThese != undefined
                && !options.onlyThese.test(key)
            )
                // not what user asked for
                continue linesLoop;

            // add to new master keys
            keys.push(key);

            if (comparator[key] == undefined)
                // add line's key as an empty object
                comparator[key] = [];

            // comparator[key][label] = [];

            // add value, using label as key
            comparator[key][label] = value;

        }

    }

    // tidy up new keys
    var keys = uniquify(keys);

    // check if values are different
    // and add them to differences

    for (var k = 0; k < keys.length; k++) {

        var key = keys[k],
            isDifferent = false,

            // the value we check against
            currentValue = null,

            // will hold array for each object's line
            linesForKey = [];

        for (var o = 0; o < objs.length; o++) {

            var label = labels[o],
                v;

            // add label for this object
            if (
                comparator[key] === undefined
                || !comparator[key].hasOwnProperty(label)
                || comparator[key][label] == undefined
                || comparator[key][label] == 'undefined'
            )
                v = empty;

            else
                v = comparator[key][label];

            // store this line in case we need it
            linesForKey.push([label, key, v]);

            // initialise current value
            if (currentValue === null)
                currentValue = v;

            // or check if values are different
            else if (currentValue !== v)
                isDifferent = true;

        }

        if (isDifferent === true)
            differences.push(linesForKey);

    }

    return differences;
}




/**
 * Format the output of listDifferences function.
 *  {Array} differences - listDifferences() output
 */
function formatDifferences(differences) {

    var formatted = [],
        labelWidth = 0,

        // regex to tidy strings
        firstTwoElements = /^([^\.]+\.[^\.]+\.)/,
        linefeeds = /[\r\n]/g,
        emptyBrackets = /\[\]/g,
        tabs = /\t/g;

    // calculate label width
    for (var o = 0; o < differences[0].length; o++)
        if (labelWidth < differences[0][o][0].length)
            labelWidth = differences[0][o][0].length;


    for (var d = 0; d < differences.length; d++) {

        var linesForKey = [];

        for (var o = 0; o < differences[d].length; o++)
            linesForKey[o] = formatDifference.apply(null, differences[d][o]);

        formatted.push(linesForKey.join('\n'));
    }

    return formatted.join('\n\n');

    // helper functions
    function formatDifference() { var a = arguments; return pad(a[0], labelWidth + 2) + '\t' + tidyKey(a[1]) + ': ' + tidyValue(a[2]) };
    function tidyKey(key) { return key.replace(firstTwoElements, '').replace(emptyBrackets, '') };
    function tidyValue(value) { return value.replace(linefeeds, '\\n').replace(tabs, '\\t') };

}




/**
 * Convert a simple key/value object into
 * array of [[key, value], [key, value], ...]
 * if value is also an object, it will
 * recursively convert that also.
 *  {String} key - the starting key
 *  {String|Array|Object} obj - the starting value
 *  {Array} - [[key, value], [key, value], ...]
 */
function expandLines(key, obj, i) {

    key = String(key);
    var lines = [];

    if (obj == undefined)
        lines.push([key, 'undefined']);

    else if (obj.constructor.name == 'String')
        lines.push([key, obj]);

    else if (obj.constructor.name == 'Array')
        for (var i = 0; i < obj.length; i++)
            lines = lines.concat(expandLines(key + '[' + i + ']', obj[i], i));

    else if (obj.constructor.name == 'Object')
        for (var k in obj)
            if (obj.hasOwnProperty(k))
                lines = lines.concat(expandLines(key + '.' + k, obj[k], i));

    return lines;
}




/**
 * Reads a file contents.
 *  {File} file - the file to read.
 *  {String}
 */
function readFile(file) {
    if (
        file == undefined
        || !file.exists
    )
        return;

    file.open('r');
    var text = file.read();
    file.close();

    return text;
}




/**
 * Exports item as an Indesign snippet (XML) file.
 *  m1b
 *  {PageItem} item - an Indesign page item.
 *  {String} name - the snippet file name (include extension).
 */
function saveSnippet(item, name) {

    // put in temp folder
    var snippetFile = File(Folder.temp.fsName + '/' + name);

    // export as indesign snippet
    item.exportFile(ExportFormat.INDESIGN_SNIPPET, snippetFile, false);

    if (snippetFile.exists)
        return snippetFile;

}






/**
 * Show text in a multiline edit text field.
 *  {String} title - the title of the alerter
 *  {String|Array} obj - the text content (array of strings will work)
 *  {Number} [width] - the dialog width
 *  {Number} [height] - the dialog height
 */
function alerter(title, obj, width, height) {
    width = width || -1;
    height = height || -1;

    if (obj instanceof Array)
        obj = obj.join("\r");

    var w = new Window("dialog", title),
        et = w.add("edittext", undefined, obj, { multiline: true, scrolling: true });
    et.maximumSize.height = w.maximumSize.height - 100;
    et.minimumSize.height = 350;
    et.minimumSize.width = 350;
    et.preferredSize = [width, height];

    w.add("button", undefined, "Close", { name: "ok", alignment: ['right', 'center'] });
    w.show();
}




function uniquify(arr) {
    var seen = {},
        out = [],
        j = 0;

    for (var i = 0; i < arr.length; i++) {
        var item = arr[i];
        if (seen[item] !== 1) {
            seen[item] = 1;
            out[j++] = item;
        }
    }

    return out;
}





/**
 * Simple XML parser
 *  Peter Sirka
 * @url https://gist.github.com/petersirka/9e79b1d43cf6e579fc62
 *  {String} xml
 *  {Object}
 */
function parseXML(xml) {

    var beg = -1;
    var end = 0;
    var tmp = 0;
    var current = [];
    var obj = {};
    var from = -1;

    while (true) {

        beg = xml.indexOf('<', beg + 1);
        if (beg === -1)
            break;

        end = xml.indexOf('>', beg + 1);
        if (end === -1)
            break;

        var el = xml.substring(beg, end + 1);
        var c = el[1];

        if (c === '?' || c === '/') {

            var o = current.pop();

            if (from === -1 || o !== el.substring(2, el.length - 1))
                continue;

            var path = current.join('.') + '.' + o;
            var value = xml.substring(from, beg);

            if (typeof (obj[path]) === 'undefined')
                obj[path] = value;
            else if (obj[path] instanceof Array)
                obj[path].push(value);
            else
                obj[path] = [obj[path], value];

            from = -1;
            continue;
        }

        tmp = el.indexOf(' ');
        var hasAttributes = true;

        if (tmp === -1) {
            tmp = el.length - 1;
            hasAttributes = false;
        }

        from = beg + el.length;

        var isSingle = el[el.length - 2] === '/';
        var name = el.substring(1, tmp);

        if (!isSingle)
            current.push(name);

        if (!hasAttributes)
            continue;

        var match = el.match(/\w+\=\".*?\"/g);
        if (match === null)
            continue;

        var attr = {};
        var length = match.length;

        for (var i = 0; i < length; i++) {
            var index = match[i].indexOf('"');
            attr[match[i].substring(0, index - 1)] = match[i].substring(index + 1, match[i].length - 1);
        }

        obj[current.join('.') + (isSingle ? '.' + name : '') + '[]'] = attr;
    }

    return obj;
};




/**
 * Pad a string.
 *  m1b
 *  {String} str - the text to pad.
 *  {Number} width - number of characters to pad to.
 *  {String} [paddingChar] - the character to pad with.
 *  {Boolean} [rightAligned] - if true, will right align text.
 */
function pad(str, width, paddingChar, rightAligned) {

    width = Number(width);
    paddingChar = paddingChar || ' ';

    var padding = '';

    while (width > padding.length)
        padding += paddingChar;

    if (rightAligned)
        str = (padding + str).slice(-width);
    else
        str = (str + padding).slice(0, width);

    return str

}



// polyfill
if (!String.prototype.indexOf) {
    String.prototype.indexOf = function (obj) {
        var i;
        for (i = 0; i < this.length; i++) if (this[i] == obj) return i;
        return -1;
    }
}


app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Show ObjectStyle Overrides');

 

 

 

 

Example 1: First I alt-click on the object style in the Object Style panel (to clear overrides) then I change the column number of the text box to 2 column (the object style is 1 column).

Example 2: Again I start by alt-clicking on the object style in the Object Style panel (to clear overrides) then I move the rectangle's graphic.

 - Mark

返信数 2

m1b
Community Expert
Community Expert
July 15, 2022

Hi @Karthik SG, and @Kasyan Servetsky, this problem grabbed my interest and I came up with a strange script that has an interesting quirk: it is more strict than Indesign in deciding if an object has overrides.

 

The script reports if there are *any* differences between the object and the object after it has had any object style overrides removed. So this is great, because it does exactly what @Karthik SG has asked for.

 

However, it does a "better" job than Indesign's own system of determining if an item has object style overrides, so sometimes it will say there are overrides even when the Object Styles panel doesn't show the trailing (+) symbol. The script is technically correct though, because if you alt-click on the object style (to remove overrides) and run script again it will then report no overrides.

 

Please try it and let me know if it is useful!

- Mark

 

P.S. if you have control over what properties you are interested in, then Kasyan's approach might suit you more.

 

function main() {

    var doc = app.activeDocument,
        item = doc.selection[0];

    var result = hasObjectStyleOverrides(item);

    if (result != undefined)
        alert('Has style overrides: ' + (result ? 'YES' : 'NO'));



    /**
     * Determines if item has ObjectStyle overrides.
     * 
     * @author m1b
     * @version 2022-07-16
     * @discussion https://community.adobe.com/t5/indesign-discussions/how-to-find-whether-my-textframe-have-overriddenobjectstyle-or-not-in-my-document-using-javascript/m-p/13071120
     *
     * Note: this function is WAY MORE STRICT
     * than Indesign's normal determination
     * of overridden-ness.
     *
     * @param {PageItem} item - an Indesign page item.
     * @returns {Boolean} - if true, then object has overrides.
     */
    function hasObjectStyleOverrides(item) {

        if (
            item == undefined
            || !item.isValid
            || typeof item.exportFile !== 'function'
        )
            return;

        // make a duplicate item
        dup = item.duplicate();

        var itemSnippet = saveSnippet(dup, 'item.xml');

        // with no objectStyle overrides
        dup.clearObjectStyleOverrides();

        // and make a snippet of that
        dupSnippet = saveSnippet(dup, 'dup.xml');

        // compare the files, line by line
        // and count differences
        var differences = getDifferences(itemSnippet, dupSnippet, 10);

        // clean up
        dup.remove();

        // found any differences?
        return differences > 0;
    }


    /**
     * Compares two text files, line by line,
     * and word by word, and returns number
     * of differences.
     * @author m1b
     * @param {File} file1
     * @param {File} file2
     * @returns {Number}
     */
    function getDifferences(file1, file2, maxDifferences) {

        var differences = 0,
            atEverySpace = /\s+/g;

        // open both files
        file1.open('r');
        file2.open('r');

        while (
            !file1.eof
            && !file2.eof
            && differences <= maxDifferences
        ) {

            // compare, line by line, word by word
            var line1 = file1.readln().split(atEverySpace),
                line2 = file2.readln().split(atEverySpace),
                len = Math.min(line1.length, line2.length);

            // nothing to see after this element starts
            if (line1[1] == '<?xpacket')
                break;

            // compare words
            for (var i = 0; i < len; i++)
                if (line1[i] != line2[i])
                    differences++;

        }

        return differences;

    }




    /**
     * Exports item as an Indesign snippet (XML) file.
     * @author m1b
     * @param {PageItem} item - an Indesign page item.
     * @param {String} name - the snippet file name (include extension).
     */
    function saveSnippet(item, name) {

        // put in temp folder
        var snippetFile = File(Folder.temp.fsName + '/' + name);

        // export as indesign snippet
        item.exportFile(ExportFormat.INDESIGN_SNIPPET, snippetFile, false);

        if (snippetFile.exists)
            return snippetFile;

    }



}


app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Check ObjectStyle Overrides');

 

m1b
Community Expert
Community Expert
July 15, 2022

Here is an example usage that selects any objects on the active spread that have overridden object styles.

- Mark

 

var doc = app.activeDocument,
    items = doc.layoutWindows[0].activeSpread.pageItems;

doc.selection = [];

for (var i = 0; i < items.length; i++) {

    if (hasObjectStyleOverrides(items[i]))
        items[i].select(SelectionOptions.ADD_TO);

}
m1b
Community Expert
m1bCommunity Expert解決!
Community Expert
July 15, 2022

And one last addition, for anyone who is interested. I've made huge improvements under the hood, including quite good xml parsing (thanks to Peter Sirka's nifty little function—see script comments) and displays the differences with much better context. The underlying function listDifferences(items,options) can now handle two or more files, and the formatting is separated.

- Mark

 

 

 

/**
 * Shows object style override differences
 * for the selected page item.
 *  m1b
 *  2022-07-18
 * @discussion https://community.adobe.com/t5/indesign-discussions/how-to-find-whether-my-textframe-have-overriddenobjectstyle-or-not-in-my-document-using-javascript/m-p/13071120
 *
 * Important note:
 * This is more strict than Indesign's own
 * object-style-overridden criteria, so
 * sometimes an object may show differences
 * while not showing the (+) symbol in the
 * Object Style panel.
 */

function main() {

    var doc = app.activeDocument,
        item = doc.selection[0];

    if (item.isValid)
        showObjectStyleOverrides(item);

}




/**
 * Determines if item has ObjectStyle overrides
 * and displays a list of the overriden properties.
 *
 *  m1b
 *  2022-07-18
 * @discussion https://community.adobe.com/t5/indesign-discussions/how-to-find-whether-my-textframe-have-overriddenobjectstyle-or-not-in-my-document-using-javascript/m-p/13071120
 *
 * Note: this function is MORE STRICT
 * than Indesign's normal determination
 * of overridden-ness.
 *
 *  {PageItem} item - an Indesign page item.
 *  {Boolean} - if true, then object has overrides.
 */
function showObjectStyleOverrides(item) {

    if (
        item == undefined
        || !item.isValid
        || typeof item.exportFile !== 'function'
    )
        return;

    // make a duplicate item
    dup = item.duplicate();

    var itemSnippet = saveSnippet(dup, 'item.xml');

    // with no objectStyle overrides
    dup.clearObjectStyleOverrides();

    // and make a snippet of that
    dupSnippet = saveSnippet(dup, 'dup.xml');

    // clean up
    dup.remove();

    // set up arguments for listDifferences
    var comparisons = [
        { label: 'PageItem', file: itemSnippet },
        { label: 'Object Style', file: dupSnippet }
    ];

    // in snippet XML, we don't care about these
    var options = { ignoreThese: /x:xmpmeta/ };

    // collect differences between the two
    var differences = listDifferences(comparisons, options);

    // display differences
    if (differences.length > 0)
        alerter(differences.length + ' Object Style Overrides', formatDifferences(differences), 1000, 500);
    else
        alert('This item has no Object Style overrides.');

}




/**
 * Compares XML text or XML text files and
 * returns a text summary of differences.
 *  m1b
 *  2022-07-18
 *
 * 
 * listDifferences(
 *   [
 *     { label: 'PageItem', file: itemSnippetFile },
 *     { label: 'Object Style', xml: dupSnippetText }
 *   ], {
 *     onlyThese: /text/i,
 *     ignoreThese: /color/i
 *   }
 * );
 *
 *  {Array} items - an array of items to compare
 *  {Object} [options] - object with options
 *  {String|RegExp} [options.onlyThese] - test to choose keys
 *  {String|RegExp} [options.ignoreThese] - test to exclude keys
 *  {String} - the formatted different properties
 */
function listDifferences(items, options) {

    var differences = [],
        objs = [],
        labels = [],
        lines = [],
        keys = [],

        // constants
        empty = '-- empty --';


    // initialise the items
    for (var i = 0; i < items.length; i++) {
        var item = items[i];

        // label
        if (item.label == undefined)
            item.label = String.fromCharCode(65 + k);

        // file
        if (
            item.file != undefined
            && item.file.exists
        )
            item.obj = parseXML(readFile(item.file));

        // string
        if (typeof (item.xml) === 'string')
            item.obj = parseXML(item.xml);

        // xml
        if (typeof (item.xml) === 'xml')
            item.obj = parseXML(item.xml.toString());

        // xml text
        if (item.obj == undefined)
            return ['Error: item "' + item.label + '" had no usable XML.'];

        objs[i] = item.obj;
        labels[i] = item.label;
        lines[item.label] = [];

        var itemKeys = item.obj.reflect.properties;

        // collect the item's keys
        for (var k = 0; k < itemKeys.length; k++)

            if (item.obj.hasOwnProperty(itemKeys[k]))
                keys.push(String(itemKeys[k]));

    }

    // combine keys from all items
    var keys = uniquify(keys);


    // expand the key/values

    for (var k = 0; k < keys.length; k++) {

        // current key to compare
        var key = keys[k];

        // add lines by expanding objs recursively
        for (var o = 0; o < objs.length; o++)
            lines[labels[o]] = lines[labels[o]].concat(expandLines(key, objs[o][key]));

    }


    // make an object that has an object for *every* key
    // and store values in that object, using the item's label

    var keys = [],
        comparator = [];

    for (var o = 0; o < objs.length; o++) {

        var label = labels[o];

        linesLoop:
        for (var l = 0; l < lines[label].length; l++) {

            var linesForKey = lines[label][l],
                key = linesForKey[0],
                value = linesForKey[1];

            if (
                options.ignoreThese != undefined
                && options.ignoreThese.test(key)
            )
                // user doesn't want this key
                continue linesLoop;

            if (
                options.onlyThese != undefined
                && !options.onlyThese.test(key)
            )
                // not what user asked for
                continue linesLoop;

            // add to new master keys
            keys.push(key);

            if (comparator[key] == undefined)
                // add line's key as an empty object
                comparator[key] = [];

            // comparator[key][label] = [];

            // add value, using label as key
            comparator[key][label] = value;

        }

    }

    // tidy up new keys
    var keys = uniquify(keys);

    // check if values are different
    // and add them to differences

    for (var k = 0; k < keys.length; k++) {

        var key = keys[k],
            isDifferent = false,

            // the value we check against
            currentValue = null,

            // will hold array for each object's line
            linesForKey = [];

        for (var o = 0; o < objs.length; o++) {

            var label = labels[o],
                v;

            // add label for this object
            if (
                comparator[key] === undefined
                || !comparator[key].hasOwnProperty(label)
                || comparator[key][label] == undefined
                || comparator[key][label] == 'undefined'
            )
                v = empty;

            else
                v = comparator[key][label];

            // store this line in case we need it
            linesForKey.push([label, key, v]);

            // initialise current value
            if (currentValue === null)
                currentValue = v;

            // or check if values are different
            else if (currentValue !== v)
                isDifferent = true;

        }

        if (isDifferent === true)
            differences.push(linesForKey);

    }

    return differences;
}




/**
 * Format the output of listDifferences function.
 *  {Array} differences - listDifferences() output
 */
function formatDifferences(differences) {

    var formatted = [],
        labelWidth = 0,

        // regex to tidy strings
        firstTwoElements = /^([^\.]+\.[^\.]+\.)/,
        linefeeds = /[\r\n]/g,
        emptyBrackets = /\[\]/g,
        tabs = /\t/g;

    // calculate label width
    for (var o = 0; o < differences[0].length; o++)
        if (labelWidth < differences[0][o][0].length)
            labelWidth = differences[0][o][0].length;


    for (var d = 0; d < differences.length; d++) {

        var linesForKey = [];

        for (var o = 0; o < differences[d].length; o++)
            linesForKey[o] = formatDifference.apply(null, differences[d][o]);

        formatted.push(linesForKey.join('\n'));
    }

    return formatted.join('\n\n');

    // helper functions
    function formatDifference() { var a = arguments; return pad(a[0], labelWidth + 2) + '\t' + tidyKey(a[1]) + ': ' + tidyValue(a[2]) };
    function tidyKey(key) { return key.replace(firstTwoElements, '').replace(emptyBrackets, '') };
    function tidyValue(value) { return value.replace(linefeeds, '\\n').replace(tabs, '\\t') };

}




/**
 * Convert a simple key/value object into
 * array of [[key, value], [key, value], ...]
 * if value is also an object, it will
 * recursively convert that also.
 *  {String} key - the starting key
 *  {String|Array|Object} obj - the starting value
 *  {Array} - [[key, value], [key, value], ...]
 */
function expandLines(key, obj, i) {

    key = String(key);
    var lines = [];

    if (obj == undefined)
        lines.push([key, 'undefined']);

    else if (obj.constructor.name == 'String')
        lines.push([key, obj]);

    else if (obj.constructor.name == 'Array')
        for (var i = 0; i < obj.length; i++)
            lines = lines.concat(expandLines(key + '[' + i + ']', obj[i], i));

    else if (obj.constructor.name == 'Object')
        for (var k in obj)
            if (obj.hasOwnProperty(k))
                lines = lines.concat(expandLines(key + '.' + k, obj[k], i));

    return lines;
}




/**
 * Reads a file contents.
 *  {File} file - the file to read.
 *  {String}
 */
function readFile(file) {
    if (
        file == undefined
        || !file.exists
    )
        return;

    file.open('r');
    var text = file.read();
    file.close();

    return text;
}




/**
 * Exports item as an Indesign snippet (XML) file.
 *  m1b
 *  {PageItem} item - an Indesign page item.
 *  {String} name - the snippet file name (include extension).
 */
function saveSnippet(item, name) {

    // put in temp folder
    var snippetFile = File(Folder.temp.fsName + '/' + name);

    // export as indesign snippet
    item.exportFile(ExportFormat.INDESIGN_SNIPPET, snippetFile, false);

    if (snippetFile.exists)
        return snippetFile;

}






/**
 * Show text in a multiline edit text field.
 *  {String} title - the title of the alerter
 *  {String|Array} obj - the text content (array of strings will work)
 *  {Number} [width] - the dialog width
 *  {Number} [height] - the dialog height
 */
function alerter(title, obj, width, height) {
    width = width || -1;
    height = height || -1;

    if (obj instanceof Array)
        obj = obj.join("\r");

    var w = new Window("dialog", title),
        et = w.add("edittext", undefined, obj, { multiline: true, scrolling: true });
    et.maximumSize.height = w.maximumSize.height - 100;
    et.minimumSize.height = 350;
    et.minimumSize.width = 350;
    et.preferredSize = [width, height];

    w.add("button", undefined, "Close", { name: "ok", alignment: ['right', 'center'] });
    w.show();
}




function uniquify(arr) {
    var seen = {},
        out = [],
        j = 0;

    for (var i = 0; i < arr.length; i++) {
        var item = arr[i];
        if (seen[item] !== 1) {
            seen[item] = 1;
            out[j++] = item;
        }
    }

    return out;
}





/**
 * Simple XML parser
 *  Peter Sirka
 * @url https://gist.github.com/petersirka/9e79b1d43cf6e579fc62
 *  {String} xml
 *  {Object}
 */
function parseXML(xml) {

    var beg = -1;
    var end = 0;
    var tmp = 0;
    var current = [];
    var obj = {};
    var from = -1;

    while (true) {

        beg = xml.indexOf('<', beg + 1);
        if (beg === -1)
            break;

        end = xml.indexOf('>', beg + 1);
        if (end === -1)
            break;

        var el = xml.substring(beg, end + 1);
        var c = el[1];

        if (c === '?' || c === '/') {

            var o = current.pop();

            if (from === -1 || o !== el.substring(2, el.length - 1))
                continue;

            var path = current.join('.') + '.' + o;
            var value = xml.substring(from, beg);

            if (typeof (obj[path]) === 'undefined')
                obj[path] = value;
            else if (obj[path] instanceof Array)
                obj[path].push(value);
            else
                obj[path] = [obj[path], value];

            from = -1;
            continue;
        }

        tmp = el.indexOf(' ');
        var hasAttributes = true;

        if (tmp === -1) {
            tmp = el.length - 1;
            hasAttributes = false;
        }

        from = beg + el.length;

        var isSingle = el[el.length - 2] === '/';
        var name = el.substring(1, tmp);

        if (!isSingle)
            current.push(name);

        if (!hasAttributes)
            continue;

        var match = el.match(/\w+\=\".*?\"/g);
        if (match === null)
            continue;

        var attr = {};
        var length = match.length;

        for (var i = 0; i < length; i++) {
            var index = match[i].indexOf('"');
            attr[match[i].substring(0, index - 1)] = match[i].substring(index + 1, match[i].length - 1);
        }

        obj[current.join('.') + (isSingle ? '.' + name : '') + '[]'] = attr;
    }

    return obj;
};




/**
 * Pad a string.
 *  m1b
 *  {String} str - the text to pad.
 *  {Number} width - number of characters to pad to.
 *  {String} [paddingChar] - the character to pad with.
 *  {Boolean} [rightAligned] - if true, will right align text.
 */
function pad(str, width, paddingChar, rightAligned) {

    width = Number(width);
    paddingChar = paddingChar || ' ';

    var padding = '';

    while (width > padding.length)
        padding += paddingChar;

    if (rightAligned)
        str = (padding + str).slice(-width);
    else
        str = (str + padding).slice(0, width);

    return str

}



// polyfill
if (!String.prototype.indexOf) {
    String.prototype.indexOf = function (obj) {
        var i;
        for (i = 0; i < this.length; i++) if (this[i] == obj) return i;
        return -1;
    }
}


app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Show ObjectStyle Overrides');

 

 

 

 

Example 1: First I alt-click on the object style in the Object Style panel (to clear overrides) then I change the column number of the text box to 2 column (the object style is 1 column).

Example 2: Again I start by alt-clicking on the object style in the Object Style panel (to clear overrides) then I move the rectangle's graphic.

 - Mark

Kasyan Servetsky
Legend
July 15, 2022

I suggest the following approach:
Find all text frames with an object style applied and compare the properties used in style with those applied to each found item, If they are different, push the info into the array. Finally, display all the info in an alert, or write to a log file / console / whatever.

 

 

var arr = [];
main();

function main() {
	var doc = app.activeDocument;
	var objStyle = doc.objectStyles.itemByName("My Object Style");
	var foundItem;
	
	app.findChangeObjectOptions.objectType = ObjectTypes.TEXT_FRAMES_TYPE;
	
	app.findObjectPreferences = app.changeObjectPreferences = NothingEnum.NOTHING;
	app.findObjectPreferences.appliedObjectStyles = "My Object Style";
	var foundItems = doc.findObject();

	for (var i = 0; i < foundItems.length; i++) {
		foundItem = foundItems[i];
		ckeckProperties(foundItem, objStyle);
	}

	if (arr.length == 0) {
		alert("No overriden text frames were found.", "Script");
	}
	else {
		alert(arr.length + " overriden text frame" + ((arr.length == 1) ? " was" : "s were") + " found:\n" +arr.join("\n"), "Script");
	}
}

function ckeckProperties(item, objStyle) {
	if (item.fillColor != objStyle.fillColor) {
		arr.push("Color " + item.fillColor.name + " on page " + item.parentPage.name);
	}
}

 

 



The test doc is attached.
I used only one property -- fill color -- as an example. Other properties should be added depending on what's in your object style.

Karthik SG作成者
Inspiring
July 18, 2022

HI @Kasyan Servetsky This is  also working fine but we need to specify the property of each, What i actually want is to get the overridedObjectStyle's name with its page numbers! Thanks for your effort and it also made @m1b interested in this post.