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

Scripting Issue that only occurs on Windows

New Here ,
Sep 25, 2025 Sep 25, 2025

So I've been using a hand made script for years and years now, it's actually a set of 2 scripts.
Script 1 "#LogAllDimensions-Alt.js" does what it says on the tin, it logs the Tranformation data like this:
"X_POS_0;Y_POS_0;WIDTH_0;HEIGHT_0$X_POS_1;Y_POS_1;WIDTH_1;HEIGHT_1$", it then shows a prompt containing the string however long it may be.
Then I can start selecting different objects and run Script 2: "#PositionObjectsBasedOnLog.js"
This does the opposite and splits the string at every "$" since those are dividers for each set of transformation data, then it splits each of those at ";" so that I get the raw X, Y, WIDTH, HEIGHT properties,
which are then used to reposition and resize my current selection accordingly.

I used to work at a printing company and I had to make efficient layouts when printing things so we don't waste more material than needed, but whenever we had to deal with extremely heavy images this got time consuming.
I made these scripts as a work around, I'd first use rectangles with the exact size as the images we'd need to print, I'd then puzzle together the layout and once that was figured out I only needed to place the actual images, make enough copies, select them and paste in the coordinates to set their new transformation data.

However at that company I worked on Macs, but now that I work elsewhere on a windows PC, some issues have arisen with "#PositionObjectsBasedOnLog.js"
When I paste in the transformation string it processes a couple of them only to then stop and spit out an error partway through.
No changes were made to this script between using it on Mac and Windows.
The weird thing is that if I edit the script and paste my string directly into it, then it works just fine, but if done through entering it into the prompt, this issue occurs.

Script 1 "#LogAllDimensions.js":

app.preferences.setBooleanPreference("ShowExternalJSXWarning", false);
var myDocument = app.activeDocument;
var convUnit = 2.834645;

var mySelection = new Object;
selections = myDocument.selection;

var stringToAlert = "";

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

	mySelection = myDocument.selection[i];

	stringToAlert = (stringToAlert + (mySelection.left / convUnit) + ";" + (mySelection.top / convUnit) + ";" + (mySelection.width / convUnit) + ";" + (mySelection.height / convUnit) + "$");

	if(i==(selections.length - 1)){
		alertUser();
	}

}

function alertUser(){
	prompt("Transformation Data for " + selections.length + " Objects:", stringToAlert);
}


Script 2 "#PositionObjectsBasedOnLog.js":

app.preferences.setBooleanPreference("ShowExternalJSXWarning", false);
var myDocument = app.activeDocument;

var convUnit = 2.834645;

var mySelection = new Object;
selections = myDocument.selection;
var stringValue = (prompt("Input Log Text Here:", ""));

var livePreviewEnabled = true;
var resizingEnabled = true;
var scaleMultiplier = 1;

for(i=0;i<selections.length;i++){
	mySelection = myDocument.selection[i];
	var splitString = stringValue.split("$");
	var splitStringValues = splitString[i].split(";");

	var leftPos = (parseFloat(splitStringValues[0]) * convUnit);
	var topPos = (parseFloat(splitStringValues[1]) * convUnit);
	var objWidth = (parseFloat(splitStringValues[2]) * convUnit);
	var objHeight = (parseFloat(splitStringValues[3]) * convUnit);

	//Disabled section for automatically rotating objects if it considers the width and height to be swapped.
	//This does work, but is extremely senstive to a difference of even 0.0000000001, so I had to disable it for now.
	/*
	if(objHeight > objWidth && mySelection.height < mySelection.width){
		mySelection.rotate(90);
	}

	if(objWidth > objHeight && mySelection.width < mySelection.height){
		mySelection.rotate(90);
	}
	*/

	mySelection.left = (leftPos * scaleMultiplier);
	mySelection.top = (topPos * scaleMultiplier);
	if(resizingEnabled==true){
		mySelection.width = (objWidth * scaleMultiplier);
		mySelection.height = (objHeight * scaleMultiplier);
	}
	if(livePreviewEnabled==true){
		app.redraw();
	}
}

 
Note: I'm no JS Expert, so excuse me if I'm handling things a bit inefficient.
Though do tell me because I'm curious to know how it could be done better.

TOPICS
Bug , Scripting
134
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
Adobe
New Here ,
Sep 25, 2025 Sep 25, 2025

Also the convUnit thing you see everywhere is to convert back and forth between Illustrator's internal unit system and millimeters since I can't directly tell the script to interpret values as mm

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

Could you show us the error you get? And even better, post a sample document? (Save as pdf, Illustrator editable). I might not be able to help because I use MacOS but it will be easier for someone else to test on Windows.

- Mark

 

PS: a tip—just call your `convUnit` mm, its much easier to understand:

const mm = 2.834645;

var doc = app.activeDocument;
var tf = doc.textFrames.add();
tf.contents = doc.name;
tf.top = 10 * mm;
tf.left = 5 * mm;

 or look at the built-in UnitValue object which handles unit conversions in a more formal way, but I don't usually bother with, personally.

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
New Here ,
Sep 25, 2025 Sep 25, 2025

Fair points, basically it complains about a closing curly bracket on line 42 as it seems to be trying to interpret that as data.
Which is weird as heck because although } is indeed not a numeric value, it should not be attempting to read that in the first place
ictopr_0-1758795234383.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
New Here ,
Sep 25, 2025 Sep 25, 2025

I've made a quick recording that goes through the process from start to finish, hope it helps

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

Hi @ict-opr I suspect the copy/pasting is adding something strange to the text string, maybe an invisible character, and I would try filtering the string to remove anything that isn't an expected character—let me know if you want to do that.

 

But, just for learning, I've written a version of your scripts combined into a single palette. It should—hopefully!— remove the error you are seeing because it doesn't do the string copy/pasting that your current workflow uses. I hope it will be useful, at least as a starting point. I apologize for the mess of BridgeTalk nonsense in the script but that is just what we have to do to use a palette, as opposed to a dialog.

 

Let me know how it goes.

- Mark

 

Screenshot 2025-09-26 at 00.44.12.png

/**
 * @file Position Items.js
 *
 * Variation of user @ict-opr's two scripts
 * showing use of palette to load positions
 * and later use them to position items.
 *
 * @author m1b
 * @version 2025-09-26
 * @discussion https://community.adobe.com/t5/illustrator-discussions/scripting-issue-that-only-occurs-on-windows/m-p/15520320
 */
//@targetengine 'positionItems'
(function () {

    // check if the window already exists by using a global variable
    if (
        "undefined" !== typeof $.global.palette
        && null !== $.global.palette
    ) {
        // NOTE: while debugging, you will want to disable this part
        // because it will stop your new palette from instantiating
        // (otherwise you'll need to restart Illustrator each time!)
        $.global.palette.active = true;
        $.global.palette.show();
        return;
    }

    // create a new ScriptUI palette (modeless window)
    $.global.palette = new Window("palette", "Position Items", undefined, { resizeable: false });

    const FIELD_DELIMITER = ';';
    const ITEM_DELIMITER = '$';

    var activePositions = '';

    var buttons = palette.add('group {orientation: "row", alignment:["fill","top"], alignChildren:["fill","top"] }');
    // var loadGroup = buttons.add('group {orientation: "column", alignChildren:["left","top"] }');
    var loadButton = buttons.add('button { text:"Load" }');
    // var positionGroup = buttons.add('group {orientation: "row", alignChildren:["left","top"] }');
    var positionButton = buttons.add('button { text:"Position" }');
    var loadedLabel = palette.add('statictext {text:"", alignment:["fill","top"], justify:"center" }');
    var resizeCheckbox = buttons.add('checkbox {text:"Resize Items", alignment:["fill","bottom"] }');

    /** load button is clicked - send `loadPositions` function to Illustrator */
    loadButton.onClick = function () {

        // a BridgeTalk message
        var bt = new BridgeTalk();
        bt.target = "illustrator";

        // convert the function to a string IIFE
        // this is a way to send code via bridgeTalk
        bt.body = "(" + loadPositions.toSource() + ")(#I,#F);"
            // include string parameters
            .replace('#I', '"' + ITEM_DELIMITER + '"')
            .replace('#F', '"' + FIELD_DELIMITER + '"');

        // handle the result returned from Illustrator
        bt.onResult = function (response) {
            activePositions = response.body || '';
            updateUI();
        };

        // send the script to Illustrator
        bt.send();

    };

    /** position button is clicked - send `positionItems` function to Illustrator */
    positionButton.onClick = function () {

        // a BridgeTalk message
        var bt = new BridgeTalk();
        bt.target = "illustrator";

        // convert the function to a string IIFE
        // this is a way to send code via bridgeTalk
        bt.body = "(" + positionItems.toSource() + ")(#P,#R,#I,#F);"
            // include string parameters
            .replace('#P', '"' + activePositions + '"')
            .replace('#R', '"' + (resizeCheckbox.value ? '1' : '') + '"')
            .replace('#I', '"' + ITEM_DELIMITER + '"')
            .replace('#F', '"' + FIELD_DELIMITER + '"');

        // send the script to Illustrator
        bt.send();

    };

    // show the palette
    updateUI();
    palette.center();
    palette.show();

    /** update the UI - positions count and button enabling */
    function updateUI() {
        var positionCount = (activePositions.split(ITEM_DELIMITER).length - 1);
        loadedLabel.text = positionCount + ' positions ready.';
        positionButton.enabled = positionCount > 0;
        resizeCheckbox.enabled = positionCount > 0;
    };

    /**
     * Returns a `positions` string from selected objects.
     * To be sent to Illustrator via BridgeTalk
     * @param {String} itemDelimiter - string to add between item position strings.
     * @param {String} fieldDelimiter - string to add between fields of an item position string.
     * @returns {String} - the position(s).
     */
    function loadPositions(itemDelimiter, fieldDelimiter) {

        /*
            IMPORTANT: you must use block comments in any function
            that you will be sending via BridgeTalk, because it seems
            to evaluate the whole body as a single line, therefore
            an inline comment will nullify everything after it.
        */
        if (0 === app.documents.length)
            return alert("Please open a document and try again.");

        var doc = app.activeDocument;
        var items = doc.selection;

        if (0 === items.length)
            return alert("Please select some page items and try again.");

        var positions = '';

        /* build the positions string */
        for (var i = 0, item; i < items.length; i++) {
            item = items[i];
            positions += [item.left, item.top, item.width, item.height].join(fieldDelimiter) + itemDelimiter;
        }

        return positions;

    };

    /**
     * Positions selected items according
     * to `activePositions` string.
     * To be sent to Illustrator via BridgeTalk
     * @param {String} positions - the positions to use.
     * @param {String} [resize] - whether to resize the item (default: do not resize).
     * @param {String} itemDelimiter - string to add between item position strings.
     * @param {String} fieldDelimiter - string to add between fields of an item position string.
     */
    function positionItems(positions, resize, itemDelimiter, fieldDelimiter) {

        /*
            IMPORTANT: you must use block comments in any function
            that you will be sending via BridgeTalk, because it seems
            to evaluate the whole body as a single line, therefore
            an inline comment will nullify everything after it.
        */

        var scaleMultiplier = 1;

        if (0 === app.documents.length)
            return alert("Please open a document and try again.");

        var doc = app.activeDocument;
        var items = doc.selection;
        if (0 === items.length)
            return alert("Please select some page items and try again.");

        positions = positions.split(itemDelimiter);
        var len = Math.min(positions.length, items.length);

        /* position the items */
        for (var i = 0, item, position; i <= len; i++) {

            item = items[i];
            position = positions[i].split(fieldDelimiter);

            var leftPos = Number(position[0]);
            var topPos = Number(position[1]);
            var objWidth = Number(position[2]);
            var objHeight = Number(position[3]);

            item.left = leftPos * scaleMultiplier;
            item.top = topPos * scaleMultiplier;

            if (resize) {
                item.width = (objWidth * scaleMultiplier);
                item.height = (objHeight * scaleMultiplier);
            }

        }

    };

})();

 

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
LATEST

Try running the script straight from the Scripts Menu, skip the Script Panel to see if it works.

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