Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Check Brand Colour Inconsistencies in InDesign

Participant ,
Sep 18, 2025 Sep 18, 2025

Hi,

 

I'm building a script for InDesign to check if any non-brand colours are used in the document. The script displays a palette/dialog and fetches all the swatches. The user then selects the required Brand colours and clicks the button to check any inconsistencies.

 

The current script prompts the correct number of inconsistencies. The quick navigation dialog box perfectly shows the next object on clicking the 'Next' button. However, the script is not selecting any object. I want the script to find the culprit object and select it, so that the user does not have to find it manually.

 

Can anyone fix it please.

 

Thanks.

 

 

#target indesign

// --- Global Variables ---
var doc;

// --- Main Execution ---
if (app.documents.length > 0) {
    doc = app.activeDocument;
    createAndRunChecker();
} else {
    alert("Please open an InDesign document before running this script.");
}

// =============================================================================
// Helper: indexOf replacement (ExtendScript safe)
// =============================================================================
function inArray(arr, val) {
    if (!arr) return -1;
    for (var i = 0; i < arr.length; i++) {
        if (arr[i] === val) return i;
    }
    return -1;
}

// =============================================================================
// Main UI
// =============================================================================
function createAndRunChecker() {

    var dialog = new Window("dialog", "Brand Colour Checker v8.0");
    dialog.orientation = "column";
    dialog.alignChildren = ["fill", "top"];
    dialog.spacing = 10;
    dialog.margins = 16;

    dialog.add("statictext", undefined, "Select Brand Colours from the Swatches:");

    var swatchPanel = dialog.add("panel", undefined, "Document Swatches");
    swatchPanel.orientation = "column";
    swatchPanel.alignChildren = "left";
    swatchPanel.margins = 10;

    var allSwatches = doc.swatches;
    var defaultNames = ["None", "Paper", "Black", "Registration"];

    for (var i = 0; i < allSwatches.length; i++) {
        var currentSwatch = allSwatches[i];
        try {
            if (currentSwatch && currentSwatch.isValid && inArray(defaultNames, currentSwatch.name) === -1) {
                var cb = swatchPanel.add("checkbox", undefined, currentSwatch.name);
                cb.swatchObject = currentSwatch;
                cb.value = false;
            }
        } catch (e) {
            $.writeln("Skipped swatch due to error: " + e);
        }
    }

    var btnGroup = dialog.add("group");
    btnGroup.alignment = "right";
    var cancelButton = btnGroup.add("button", undefined, "Cancel", { name: "cancel" });
    var checkButton = btnGroup.add("button", undefined, "Check Inconsistent Brand Colours", { name: "ok" });

    checkButton.onClick = function () {
        var brandSwatches = [];
        for (var i = 0; i < swatchPanel.children.length; i++) {
            var checkbox = swatchPanel.children[i];
            try {
                if (checkbox && checkbox.value === true && checkbox.swatchObject) {
                    brandSwatches.push(checkbox.swatchObject);
                }
            } catch (e) {
                $.writeln("Checkbox read error: " + e);
            }
        }

        if (brandSwatches.length === 0) {
            alert("Please select at least one brand colour to check against.");
            return;
        }

        dialog.close();

        try {
            var inconsistentItems = findInconsistentItems(brandSwatches);
            if (inconsistentItems.length > 0) {
                navigateThroughItems(inconsistentItems);
            } else {
                alert("✅ All Clear! No inconsistent brand colours were found.");
            }
        } catch (err) {
            alert("Error during check:\n" + (err && err.message ? err.message : err));
        }
    };

    cancelButton.onClick = function () {
        dialog.close();
    };

    dialog.center();
    dialog.show();
}

// =============================================================================
// Find Inconsistent Items
// =============================================================================
function findInconsistentItems(brandSwatches) {
    var foundItems = [];
    var allItems = doc.allPageItems;
    var defaultNames = ["None", "Paper", "Black", "Registration"];

    function isAllowedSwatch(swatch) {
        if (!swatch) return true;
        for (var i = 0; i < brandSwatches.length; i++) {
            try {
                var b = brandSwatches[i];
                if (b && swatch && b.id !== undefined && swatch.id !== undefined && b.id === swatch.id) return true;
                if (b && swatch && b.name && swatch.name && b.name === swatch.name) return true;
            } catch (e) {}
        }
        try {
            if (swatch && typeof swatch.name === "string" && inArray(defaultNames, swatch.name) !== -1) return true;
        } catch (e) {}
        return false;
    }

    for (var j = 0; j < allItems.length; j++) {
        var item = allItems[j];
        if (!item) continue;
        var reason = "";

        try {
            var fill = undefined;
            try { fill = item.fillColor; } catch (e) { fill = undefined; }

            if (fill && typeof fill.name === "string" && fill.name !== "None") {
                var fillName = fill.name || "";
                if (fillName === "") {
                    reason = "Unnamed fill colour used.";
                } else if (!isAllowedSwatch(fill)) {
                    reason = "Non-brand fill colour ('" + fillName + "') used.";
                } else {
                    var ft = undefined;
                    try { ft = item.fillTint; } catch (e) { ft = undefined; }
                    if (typeof ft === "number" && ft !== -1 && ft !== 100) {
                        reason = "Fill tint of " + ft + "% applied.";
                    }
                }
            }
        } catch (e) {}

        try {
            var stroke = undefined;
            try { stroke = item.strokeColor; } catch (e) { stroke = undefined; }

            if (!reason && stroke && typeof stroke.name === "string" && stroke.name !== "None") {
                var strokeName = stroke.name || "";
                if (strokeName === "") {
                    reason = "Unnamed stroke colour used.";
                } else if (!isAllowedSwatch(stroke)) {
                    reason = "Non-brand stroke colour ('" + strokeName + "') used.";
                } else {
                    var st = undefined;
                    try { st = item.strokeTint; } catch (e) { st = undefined; }
                    if (typeof st === "number" && st !== -1 && st !== 100) {
                        reason = "Stroke tint of " + st + "% applied.";
                    }
                }
            }
        } catch (e) {}

        try {
            var op = undefined;
            try { op = item.opacity; } catch (e) { op = undefined; }
            if (!reason && typeof op === "number" && op !== 100) {
                reason = "Opacity of " + op + "% applied.";
            }
        } catch (e) {}

        if (reason !== "") {
            foundItems.push({ item: item, reason: reason });
            continue;
        }

        // Check text characters inside TextFrames
        try {
            if (item.constructor && item.constructor.name === "TextFrame") {
                var chars = undefined;
                try { chars = item.characters; } catch (e) { chars = undefined; }
                if (chars && chars.length > 0) {
                    for (var k = 0; k < chars.length; k++) {
                        try {
                            var myChar = chars[k];
                            if (!myChar) continue;
                            var charFill = undefined;
                            try { charFill = myChar.fillColor; } catch (e) { charFill = undefined; }
                            if (charFill && typeof charFill.name === "string" && charFill.name !== "None" && !isAllowedSwatch(charFill)) {
                                var cname = charFill.name || "";
                                foundItems.push({ item: myChar, reason: "Inconsistent character colour ('" + cname + "') used." });
                                break;
                            }
                        } catch (innerE) {}
                    }
                }
            }
        } catch (e) {}
    }

    return foundItems;
}

// =============================================================================
// Navigation & Selection
// =============================================================================
function navigateThroughItems(items) {
    for (var i = 0; i < items.length; i++) {
        var obj = items[i].item;
        var reason = items[i].reason;

        if (!obj) continue;

        // --- If it's a Character, select parent TextFrame ---
        if (obj.constructor && obj.constructor.name === "Character") {
            if (obj.parentTextFrames && obj.parentTextFrames.length > 0) {
                obj = obj.parentTextFrames[0];
            }
        }

        // --- Unlock / unhide ---
        try { if (obj.locked) obj.locked = false; } catch(e) {}
        try { if (obj.hidden) obj.hidden = false; } catch(e) {}

        // --- Activate page ---
        try { if (obj.parentPage) app.activeWindow.activePage = obj.parentPage; } catch(e) {}

        // --- Select & zoom before dialog ---
        try { app.select(obj); } catch(e) {}
        try { app.activeWindow.zoomPercentage = 100; } catch(e) {}

        // --- Show dialog after selection ---
        var navDialog = new Window("dialog", "Quick Navigation");
        navDialog.orientation = "column";
        navDialog.alignChildren = ["fill", "top"];
        navDialog.spacing = 10;

        navDialog.add("statictext", undefined, "Inconsistency Found:");
        navDialog.add("statictext", [0,0,420,60], reason, {multiline:true});
        navDialog.add("statictext", undefined, (i + 1) + " of " + items.length);

        var navButtonGroup = navDialog.add("group");
        navButtonGroup.alignment = "center";
        var stopButton = navButtonGroup.add("button", undefined, "Stop");
        var nextButton = navButtonGroup.add("button", undefined, "Next");

        stopButton.onClick = function() { navDialog.close(0); };
        nextButton.onClick = function() { navDialog.close(1); };

        var res = navDialog.show();
        if (res === 0) break;
    }
}

 

TOPICS
Scripting
322
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 18, 2025 Sep 18, 2025

I'm looking at your post history and wondering if you're a human or a bot. The fact that some brand-new account posted your post a 100% match, at the exact same time, inclines me to believe that you're a bot - or., perhaps, a person not accustomed to running a botswarm.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Sep 19, 2025 Sep 19, 2025

Hi Joel,

No, I'm not a bot. I'm a human and this is my personal account to get support from experts like you on the Adobe Community. I know what you're talking about. Actually, I was working on two different browsers and mistakenly, I posted my request on the other browser. I didn't find an option to delete that post, so if anyone has permissions to delete a post, please remove it from the link.

here's the link of the mistake I have done:
https://community.adobe.com/t5/indesign-discussions/check-brand-colour-inconsistencies/m-p/15512187#...

 

I would appreciate, if I could get some support on my initial request.

Thanks,

Masood

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 19, 2025 Sep 19, 2025

I locked the other thread and left a trail to here - so all good no worries.

 

app.select(obj) isn’t always reliable, depending on the object type (characters, groups, nested items, etc.).

From my notes and what you have I think this might work

try {
    app.select(NothingEnum.NOTHING); // clear previous selection
    app.select(obj, SelectionOptions.REPLACE);
    app.activeWindow.activePage = obj.parentPage; // ensure page is visible
} catch(e) {
    $.writeln("Selection failed: " + e);
}

 

or you could try this

if (obj.constructor && obj.constructor.name === "Character") {
    try {
        app.select(NothingEnum.NOTHING);
        app.select(obj, SelectionOptions.REPLACE); // highlight text
    } catch(e) {}
} else {
    app.select(NothingEnum.NOTHING);
    app.select(obj, SelectionOptions.REPLACE);
}

 

Zooming I've had luck with something similar

// --- Unlock / unhide ---
try { if (obj.locked) obj.locked = false; } catch(e) {}
try { if (obj.hidden) obj.hidden = false; } catch(e) {}

// --- Activate page ---
try { if (obj.parentPage) app.activeWindow.activePage = obj.parentPage; } catch(e) {}

// --- Select & zoom before dialog ---
try {
    app.select(NothingEnum.NOTHING);
    app.select(obj, SelectionOptions.REPLACE);
    app.activeWindow.zoom(ZoomOptions.FIT_SELECTION);
} catch(e) {
    $.writeln("Selection/zoom failed: " + e);
}

 

I'm not the best scripter just trying to help, have a bunch of scripts and broke them into usable blocks for different uses, so it might seem cobbled together, because it is.

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Sep 25, 2025 Sep 25, 2025

Hi Eugene,

I tried your suggestions, but didn't get the results. I think the problem is with the Screen Redraw. I found another script in my drive, and remember that I was facing the same issue with that one too. Here's the code from that script.

Please see, if this could help fix my code. I'm not a coder, but I try my hands to create stuff like this for my personal use.

 

PS: What if we simplify the script only to find page items like all type of frames, rectangles, the parent text frame containing an inconsistent character, rather than the character itself?

 

#targetengine 'customChecksAndFixes'

// Create the panel window
var myWindow = new Window('palette', "Checks & Fixes - InDesign, v10.0", undefined, { resizeable: true });

// Add a message "Please Save Your File Before Running a Script!"
var messageText = myWindow.add('statictext', undefined, "Save Your File Before Clicking a Button...");
messageText.alignment = 'center';
// messageText.graphics.font = ScriptUI.newFont("dialog", "bold", 29); // Reduced font size
// buttonFontSize = 9;

// Create a scrollable panel for buttons
var buttonPanel = myWindow.add('panel', undefined, undefined, { scrolling: true });
// var buttonPanel = myWindow.add('panel', undefined, undefined, { scrolling: true, multiselect: false });
buttonPanel.orientation = 'column';
buttonPanel.alignChildren = 'left';
buttonPanel.margins = [5, 2, 1, 2];
// buttonPanel.maximumSize.height = 500; // Limit height to enable vertical scrolling


// ************************************************ CUSTOM  C H E C K S  –  B U T T O  N S

var checkRGB = buttonPanel.add('button', undefined, 'CHECK - RGB Image(s)');
var checkResolution = buttonPanel.add('button', undefined, 'CHECK - Images Below Minimum Resolution');

// ************************************************ F U N C T I O N S



// Check if the effective resolution of an image is below 300 dpi
checkResolution.onClick = function () {
    // Prompt the user for a DPI threshold
    var desiredValue = parseInt(prompt("Enter the Minimum DPI Required:", "300"), 10);

    // Check if the user entered a valid number
    if (isNaN(desiredValue) || desiredValue <= 0) {
        alert("Invalid DPI value. Please enter a positive number.");
    } else {
        var qualityCheck = 0;
        var foundArray = [];

        // Iterate through all graphics in the document
        for (var i = 0; i < app.documents[0].allGraphics.length; i++) {
            try {
                var img = app.documents[0].allGraphics[i];
                if (img.effectivePpi[0] < desiredValue || img.effectivePpi[1] < desiredValue) {
                    qualityCheck++;
                    foundArray.push(img); // Add image to the array
                }
            } catch (e) { }
        }

        if (qualityCheck === 0) {
            alert("No Image(s) Found Below: " + desiredValue + " DPI");
        } else {
            // alert("Image(s) Found Below: " + qualityCheck);

            // Navigate through the images
            for (var j = 0; j < foundArray.length; j++) {
                try {
                    app.select(foundArray[j]); // Select the image
                    // app.activeWindow.zoom(ZoomOptions.FIT_PAGE); // Set zoom level to fit the page
                    app.activeWindow.zoomPercentage = 100; // Set zoom level to 100%

                    // Create a custom dialog for navigation
                    var dialog = new Window("dialog", "Quick Navigation");
                    dialog.add("statictext", undefined, "Image(s) Found Below: " + desiredValue + " DPI");
                    dialog.add("statictext", undefined, (j + 1) + " of " + qualityCheck);

                    var buttonGroup = dialog.add("group");
                    buttonGroup.alignment = "center";

                    var cancelButton = buttonGroup.add("button", undefined, "Stop");
                    var nextButton = buttonGroup.add("button", undefined, "Next Image");

                    // Set button actions
                    nextButton.onClick = function () {
                        dialog.close(1); // Continue to next image
                    };

                    cancelButton.onClick = function () {
                        dialog.close(0); // Exit loop
                    };

                    // ************************************************ D I S C L A I M E R
                    var blankLine = dialog.add('statictext', undefined);
                    var copyrightText = dialog.add('statictext', undefined, 'ⓒ Masood Ahmad - 2024');
                    // copyrightText.alignment = 'center';

                    // Show the dialog
                    if (dialog.show() === 0) {
                        break; // Exit the loop if "Cancel" is clicked
                    }
                } catch (e) {
                    alert("Unable to locate one of the image(s).");
                }
            }
        }
    }
};


// Check for RGB Image(s)
checkRGB.onClick = function () {

    // Alert to ensure user is aware of image linking status
    // alert("Make sure all the images are linked properly if possible, but missing links will also be checked!");
    alert("Make sure all the images are Linked properly!")

    var myLinks = app.documents[0].links;
    var rgbCheck = 0;
    var foundArray = [];

    for (var i = 0; i < myLinks.length; i++) {
        try {
            var link = myLinks[i];
            if (link.status == LinkStatus.NORMAL || link.status == LinkStatus.LINK_MISSING) {
                var image = link.parent;
                if (image.space == "RGB") {
                    // alert("RGB image(s) Found. Please Convert to CMYK!");
                    rgbCheck++;
                    foundArray.push(image); // Add image to the array
                    // break;
                }
            }
        } catch (e) { }
    }

    if (rgbCheck === 0) {
        alert("RGB Image(s) Not-Found!");
    } else {
        // alert("RGB image(s) Found: " + rgbCheck + "\n Convert to CMYK!");

        // Navigate through the images
        for (var j = 0; j < foundArray.length; j++) {
            try {
                app.select(foundArray[j]); // Select the image
                // app.activeWindow.zoom(ZoomOptions.FIT_PAGE); // Set zoom level to fit the page
                app.activeWindow.zoomPercentage = 100; // Set zoom level to 100%

                // Create a custom dialog for navigation
                var dialog = new Window("dialog", "Quick Navigation");
                dialog.add("statictext", undefined, "RGB image(s) Found. Convert to CMYK");
                dialog.add("statictext", undefined, (j + 1) + " of " + rgbCheck);

                var buttonGroup = dialog.add("group");
                buttonGroup.alignment = "center";

                var cancelButton = buttonGroup.add("button", undefined, "Stop");
                var nextButton = buttonGroup.add("button", undefined, "Next Image");

                // Set button actions
                nextButton.onClick = function () {
                    dialog.close(1); // Continue to next image
                };

                cancelButton.onClick = function () {
                    dialog.close(0); // Exit loop
                };

                // ************************************************ D I S C L A I M E R
                var blankLine = dialog.add('statictext', undefined);
                var copyrightText = dialog.add('statictext', undefined, 'ⓒ Masood Ahmad - 2024');
                // copyrightText.alignment = 'center';

                // Show the dialog
                if (dialog.show() === 0) {
                    break; // Exit the loop if "Cancel" is clicked
                }
            } catch (e) {
                alert("Unable to locate one of the image(s).");
            }
        }

    }
};


// Show the panel
myWindow.show();

 

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 25, 2025 Sep 25, 2025

Let me know how this goes - hopefully something here either works directly for you or gives you a clue somewhere... 

In your navigateThroughItems(items) loop, replace the selection/zoom block with:

// --- Unlock / unhide ---
try { if (obj.locked) obj.locked = false; } catch(e) {}
try { if (obj.hidden) obj.hidden = false; } catch(e) {}

// --- If it's a Character, use its parent TextFrame ---
if (obj.constructor && obj.constructor.name === "Character") {
    try {
        if (obj.parentTextFrames && obj.parentTextFrames.length > 0) {
            obj = obj.parentTextFrames[0];
        }
    } catch(e) {}
}

// --- Activate page ---
try { if (obj.parentPage) app.activeWindow.activePage = obj.parentPage; } catch(e) {}

// --- Select & zoom ---
try {
    app.select(NothingEnum.NOTHING);
    app.select(obj, SelectionOptions.REPLACE);

    // Force screen redraw
    app.activeWindow.zoom(ZoomOptions.FIT_SELECTION);
    // OR: app.activeWindow.zoomPercentage = app.activeWindow.zoomPercentage;
    app.redraw();
} catch(e) {
    $.writeln("Selection/zoom failed: " + e);
}

 

If you want only frames/rectangles/text frames (ignoring characters directly)

Change your findInconsistentItems() so that whenever you detect an inconsistent Character, you push its parent frame instead:

 

if (myChar.parentTextFrames && myChar.parentTextFrames.length > 0) {
    foundItems.push({ item: myChar.parentTextFrames[0], reason: "Inconsistent character colour ('" + cname + "') used." });
}

 
What I'm trying to.... hmmm I'm not sure ha ha

Trying the “parent frame” approach and use zoom(FIT_SELECTION) to guarantee the object comes into view.

 

So something else comes to mind too

// ==================================
// Navigation & Selection (rewritten)
// ==================================
function navigateThroughItems(items) {
    for (var i = 0; i < items.length; i++) {
        var obj = items[i].item;
        var reason = items[i].reason;

        if (!obj) continue;

        // --- If it's a Character, select the parent TextFrame ---
        if (obj.constructor && obj.constructor.name === "Character") {
            try {
                if (obj.parentTextFrames && obj.parentTextFrames.length > 0) {
                    obj = obj.parentTextFrames[0];
                }
            } catch (e) {}
        }

        // --- Unlock / unhide if needed ---
        try { if (obj.locked) obj.locked = false; } catch (e) {}
        try { if (obj.hidden) obj.hidden = false; } catch (e) {}

        // --- Activate page containing the object ---
        try { if (obj.parentPage) app.activeWindow.activePage = obj.parentPage; } catch (e) {}

        // --- Select & zoom to object ---
        try {
            app.select(NothingEnum.NOTHING); // clear selection
            app.select(obj, SelectionOptions.REPLACE); // select the object
            app.activeWindow.zoom(ZoomOptions.FIT_SELECTION); // zoom to fit
            app.redraw(); // force screen refresh
        } catch (e) {
            $.writeln("Selection/zoom failed: " + e);
        }

        // --- Show navigation dialog ---
        var navDialog = new Window("dialog", "Quick Navigation");
        navDialog.orientation = "column";
        navDialog.alignChildren = ["fill", "top"];
        navDialog.spacing = 10;

        navDialog.add("statictext", undefined, "Inconsistency Found:");
        navDialog.add("statictext", [0,0,420,60], reason, { multiline:true });
        navDialog.add("statictext", undefined, (i + 1) + " of " + items.length);

        var navButtonGroup = navDialog.add("group");
        navButtonGroup.alignment = "center";
        var stopButton = navButtonGroup.add("button", undefined, "Stop");
        var nextButton = navButtonGroup.add("button", undefined, "Next");

        stopButton.onClick = function() { navDialog.close(0); };
        nextButton.onClick = function() { navDialog.close(1); };

        var res = navDialog.show();
        if (res === 0) break; // Stop button clicked, exit loop
    }
}

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 26, 2025 Sep 26, 2025

Hi @code_seeeeeker , Unless I’m misunderstanding the problem, it seems like an easier approach would be to delete the non brand swatches and when you are prompted for a replacment choose a brand color. It’s easy to do that via the UI and you should be able to do it via a script also— the swatch object has a remove() method which has a replaceWith parameter.

 

Trash the swatch named Non Brand Blue and replace with Brand 1:

 

Screen Shot 12.pngScreen Shot 13.png

 

Repeat for other non brand swatches:

 

Screen Shot 14.png

 

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Sep 29, 2025 Sep 29, 2025

Thanks, @rob day, I am awar of this and several other tricks, but sometimes I cannot delete the unused swatches as they are needed later. Second, the process is time-taking, so, I'm trying some magic with a script.

 

Hi, @Eugene Tyson , thanks for sharing the revised code, but it still not working.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 29, 2025 Sep 29, 2025

What happens 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Oct 07, 2025 Oct 07, 2025
LATEST

Nothing!

just on hold, trying to take a different approach.

THINKING...................

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines