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

Script for randomly replacing symbols

Community Beginner ,
May 08, 2015 May 08, 2015

Copy link to clipboard

Copied

Hi!

I'm looking for a script that will allow you to select some objects or symbols in your AI-file and then select some of your symbols from the symbols-library in your file and then randomly replace the original objects/symbols with the symbols selected. I have found a few scripts that does basically this but with random replacement of selected colours, transparency or angles but I need one for randomly replacing symbols.

Can someone help?

TOPICS
Scripting

Views

3.8K

Translate

Translate

Report

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

correct answers 2 Correct answers

Guide , May 10, 2015 May 10, 2015

Try this. it will use all symbols in document.

var doc = app.activeDocument;

var sym = doc.symbols;

var sel = doc.selection;

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

    var place = doc.symbolItems.add(sym[Math.floor(Math.random() * sym.length)]);

    place.height = sel.height;

    place.width = sel.width;

    place.top = sel.top;

    place.left = sel.left;

    sel.remove();

    place.selected = true;

}

Votes

Translate

Translate
Enthusiast , May 02, 2023 May 02, 2023

I revised an alternate workaround to selecting the symbols you want to randomize by placing them in a specific layer. On first run it will create the layer if it can't find it. Also revised the original script to size proportinatly based on height, and place the items within the original parent layer:

var doc = app.activeDocument;
var sym = doc.symbols;
var fullSelection = doc.selection;
try { doc.layers["Symbols_To_Place"] }
catch (e) {
    symLyr = doc.layers.add();
    symLyr.name = "Symbols_T
...

Votes

Translate

Translate
Adobe
Guide ,
May 10, 2015 May 10, 2015

Copy link to clipboard

Copied

Try this. it will use all symbols in document.

var doc = app.activeDocument;

var sym = doc.symbols;

var sel = doc.selection;

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

    var place = doc.symbolItems.add(sym[Math.floor(Math.random() * sym.length)]);

    place.height = sel.height;

    place.width = sel.width;

    place.top = sel.top;

    place.left = sel.left;

    sel.remove();

    place.selected = true;

}

Votes

Translate

Translate

Report

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 Beginner ,
May 11, 2015 May 11, 2015

Copy link to clipboard

Copied

That works perfectly!!!

Thanks so much!!!

Votes

Translate

Translate

Report

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 ,
Mar 27, 2018 Mar 27, 2018

Copy link to clipboard

Copied

Hi!

I need the exact action to do with a script. But it is my first time using script, how can I install it?

I tried through extendscript toolkit, but the script doesnt appear in illustrator.

Votes

Translate

Translate

Report

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 ,
Mar 27, 2018 Mar 27, 2018

Copy link to clipboard

Copied

try this

Installing scripts in the Scripts menu

To include a script in the Scripts menu (File > Scripts), save the script in the Scripts folder, located in the

/lllustrator CC/Presets folder in your lllustrator CC installation directory, for example C:\Program Files\Adobe\Adobe Illustrator CC 2018\Presets\en_US\Scripts

.

The script’s filename, minus

the file extension, appears in the Scripts menu.

Scripts that you add to the Scripts folder while Illustrator is running do not appear in the Scripts menu until

the next time you launch Illustrator.

Any number of scripts can be installed in the Scripts menu. If you have many scripts, use subfolders in the

Scripts folder to help organize the scripts in the Scripts menu. Each subfolder is displayed as a separate

submenu containing the scripts in that subfolder.

Executing scripts from the Other Scripts menu item

The Other Scripts item at the end of the Scripts menu (File > Scripts > Other Scripts) allows you to execute

scripts that are not installed in the Scripts folder.

Selecting Other Scripts displays a Browse dialog, which you use to navigate to a script file. When you select

the file, the script is executed.

Votes

Translate

Translate

Report

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
Enthusiast ,
May 02, 2023 May 02, 2023

Copy link to clipboard

Copied

I had to modify this for it to work in 2023:

var doc = app.activeDocument;
var sym = doc.symbols;
var fullSelection = doc.selection;
for (var i = 0; i < fullSelection.length; i++) {
    var sel = fullSelection[i];
    var place = doc.symbolItems.add(sym[Math.floor(Math.random() * sym.length)]);
    place.height = sel.height;
    place.width = sel.width;
    place.top = sel.top;
    place.left = sel.left;
    sel.remove();
    place.selected = true;
}

Simply had to set the whole selection as a variable first and make sure sel was set to an instance/iteration.

Votes

Translate

Translate

Report

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
Enthusiast ,
May 02, 2023 May 02, 2023

Copy link to clipboard

Copied

LATEST

I revised an alternate workaround to selecting the symbols you want to randomize by placing them in a specific layer. On first run it will create the layer if it can't find it. Also revised the original script to size proportinatly based on height, and place the items within the original parent layer:

var doc = app.activeDocument;
var sym = doc.symbols;
var fullSelection = doc.selection;
try { doc.layers["Symbols_To_Place"] }
catch (e) {
    symLyr = doc.layers.add();
    symLyr.name = "Symbols_To_Place";
    alert("Select Symbols to randomize\nBy placing in \"Symbols_To_Place\" Layer.")
}
var symTgt = doc.layers["Symbols_To_Place"].symbolItems;
var symAry = [];
for (var s = 0; s < symTgt.length; s++) {
    nm = symTgt[s].symbol.name;
    symAry.push(nm);
}
for (var i = 0; i < fullSelection.length; i++) {
    var sel = fullSelection[i];

    var place = doc.symbolItems.add(sym[symAry[Math.floor(Math.random() * symAry.length)]]);
    place.move(sel, ElementPlacement.PLACEBEFORE);
    //Base it off the height
    percent = sel.height / place.height;
    place.height = sel.height;
    place.width = place.width * percent;
    place.top = sel.top;
    place.left = sel.left;
    sel.remove();
    place.selected = true;
}

 

 

 

 

Votes

Translate

Translate

Report

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 Beginner ,
Jan 28, 2021 Jan 28, 2021

Copy link to clipboard

Copied

Great script! Could it be modified to use only selected symbols from the Symbols palette?

Votes

Translate

Translate

Report

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
Valorous Hero ,
Jan 29, 2021 Jan 29, 2021

Copy link to clipboard

Copied

The problem is that with scripting they don't let us know what symbols are even selected in the Symbols palette. However through ponderous workarounds, we can sort of get there.

If the action of using the Symbol panel's flyout menu's delete or duplicate commands is recordable, we can play it with a script. This means that we can read all the symbols in the document's symbols collection and then perform one of those actions and compare the before/after difference of what was there and not. However, if you do the delete action, you will have to do an Undo to get the symbols back and worse it may mangle some symbol instances you did not wish to disturb if those symbols are removed.

With Duplicate action all you have to do is remove all the symbols which are added that are considered new.

I can try this sometime this weekend and see if it works!

Votes

Translate

Translate

Report

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 Beginner ,
Jan 29, 2021 Jan 29, 2021

Copy link to clipboard

Copied

Silly-V,

Thanks for your response.

Very kind of you to test a workaround.

Take care.

Votes

Translate

Translate

Report

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
Valorous Hero ,
Jan 30, 2021 Jan 30, 2021

Copy link to clipboard

Copied

It worked. However, one must be wary of Illustrator's symbol naming copy conventions as new symbols get a sequential number on the end of them. When you copy "Symbol 1", it becomes called "Symbol 2". But when you copy both "Symbol 1" and "Symbol 2" you get "Symbol 3" and "Symbol 4". We could have extra code that does a more thorough check that tries to match that "Symbol 3" is a copy of "Symbol 1" and so on, but if you rename "Symbol 1" in set ["Symbol 1", "Symbol 2"] to "Symbol 23", the next duplicated symbol name would be "Symbol 3". And if you have ["Symbol 1", "Symbol 2", "Symbol 4"], the duplicated copies will fill a spot for "Symbol 3" but skip over and become "Symbol 5" the next duplication.

With all this happening, it's better to just stick with a convention of don't name symbols with digits on the end or don't copy symbols without renaming them to something less-generic. In my code it will only get the latest copy name so looking to match an auto-named "Symbol 3" will actually find "Symbol 4" in ["Symbol 1", "Symbol 2", "Symbol 4"] but auto-named "Symbol 5" will find "Symbol 4" in ["Symbol 1", "Symbol 2", "Symbol 3",  "Symbol 4"].

 

 

#target illustrator
function test () {

	if (typeof(String.escapeForRegexp) != "function") {
		String.prototype.escapeForRegexp = function () {
			return this.replace(/([\/.*+?|()[\]{}\\^$])/g, "\\$1");
		};
	}

	if (!Array.prototype.indexOf) {
		Array.prototype.indexOf = function(searchElement, fromIndex) {
			var k;
			if (this == null) {
				throw new TypeError('"this" is null or not defined');
			}
			var o = Object(this);
			var len = o.length >>> 0;
			if (len === 0) {
				return -1;
			}
			var n = +fromIndex || 0;
			if (Math.abs(n) === Infinity) {
				n = 0;
			}
			if (n >= len) {
				return -1;
			}
			k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
			while (k < len) {
				if (k in o && o[k] === searchElement) {
					return k;
				}
				k++;
			}
			return -1;
		};
	};

	/**
	 * Matches a name of a new copied symbol "Symbol 1" to a name in the list of symbols ["Symbol", "Other Symbol"] before processing.
	 * Will have no choice but to use latest copy name: "Symbol 3" in ["Symbol", "Symbol 1", "Symbol 2"] will result in "Symbol 2" even if the copied original was actually "Symbol 1".
	 *  {string[]} originalSymbolNames - Array of original symbol names before any were duplicated via action.
	 *  {string} symbolNameToCheck - The name of a new copied symbol.
	 *  {string} - Name of the original symbol to use, or name of the last copy of that symbol in the symbols panel.
	 */
	function getLatestSymbolCopyName (originalSymbolNames, symbolNameToCheck) {
		var thisSymbolName;
		var previousCopyNames = [];
		var endSuffixRx = /\s\d+$/;
		for (var i = 0; i < originalSymbolNames.length; i++) {
			thisSymbolName = originalSymbolNames[i];
			if (thisSymbolName.replace(endSuffixRx, "") == symbolNameToCheck.replace(endSuffixRx, "")) {
				previousCopyNames.push(thisSymbolName);
			}
		}
		previousCopyNames.sort(function (a, b) {
			if (endSuffixRx.test(a) && !endSuffixRx.test(b)) {
				return true;
			} else if (!endSuffixRx.test(a) && endSuffixRx.test(b)) {
				return false;
			}
			var aSuffix = a.match(endSuffixRx)[0].substr(1) * 1;
			var bSuffix = b.match(endSuffixRx)[0].substr(1) * 1;
			return aSuffix < bSuffix;
		});
		var latestCopyName = previousCopyNames[0];
		return latestCopyName;
	};

	/**
	 * Replaces a symbol instance art object's symbol reference to another symbol definition.
	 *  {AiSymbolItem} symbolArt - The symbol instance inside the document (on an artboard/in a layer).
	 *  {AiSymbol} symbolDefinition - Symbol definition in the Symbols panel.
	 */
	function replaceSymbolReference (symbolArt, symbolDefinition) {
		symbolArt.symbol = symbolDefinition;
	};

	function replaceDocumentArt (doc, docArt, symbolDefinition) {
		var newPlacedArt = doc.symbolItems.add(symbolDefinition);
		newPlacedArt.move(docArt, ElementPlacement.PLACEAFTER);
		newPlacedArt.height = docArt.height;
		newPlacedArt.width = docArt.width;
		newPlacedArt.top = docArt.top;
		newPlacedArt.left = docArt.left;
		docArt.remove();
		return newPlacedArt;
	};

	var doc = app.activeDocument;
	doc.layers[0].visible = true;
	doc.layers[0].locked = false;
	var sel = doc.selection;
	if (sel.length == 0) {
		alert("No selection");
		return;
	}
	var sym = doc.symbols;
	var originalSymbolNames = [];
	var endSuffixRx = /\s\d+$/;
	
	var thisSymbol, thisSymbolName;

	for (var i = 0; i < sym.length; i++) {
		thisSymbol = sym[i];
		thisSymbolName = thisSymbol.name;
		originalSymbolNames.push(thisSymbolName);
	}

	app.doScript("Duplicate Symbol", "Duplicate Symbol Set");

	var newSymbolNames = [];

	for (var i = 0; i < sym.length; i++) {
		thisSymbol = sym[i];
		thisSymbolName = thisSymbol.name;
		if (originalSymbolNames.indexOf(thisSymbolName) == -1) {
			newSymbolNames.push(thisSymbolName);
		}
	}

	if (newSymbolNames.length == 0) {
		alert("No symbols were found to be selected.");
		return;
	}

	// clean up copied symbols.
	for (var i = 0; i < newSymbolNames.length; i++) {
		thisSymbolName = newSymbolNames[i];
		thisSymbol = doc.symbols.getByName(thisSymbolName);
		thisSymbol.remove();
	}

	var selectedSymbolNames = [];
	var thisOriginalName;
	var thisNewName;
	var latestCopyName;
	for (var i = 0; i < originalSymbolNames.length; i++) {
		thisOriginalName = originalSymbolNames[i];
		for (var j = 0; j < newSymbolNames.length; j++) {
			thisNewName = newSymbolNames[j];
			if (thisNewName.replace(endSuffixRx, "") == thisOriginalName.replace(endSuffixRx, "")) {
				latestCopyName = getLatestSymbolCopyName(originalSymbolNames, thisNewName);
				selectedSymbolNames.push(latestCopyName);
				continue;
			}
		}
	}

	var symbolToPlace, symbolToPlaceName, dynamicIndex;
	var thisSelectedArt, replacingArt;
	var replacingItemUuids = [];
	for (var i = sel.length - 1; i > -1; i--) {
		thisSelectedArt = sel[i];
		dynamicIndex = Math.floor(Math.random() * selectedSymbolNames.length);
		symbolToPlaceName = selectedSymbolNames[dynamicIndex];
		symbolToPlace = sym.getByName(symbolToPlaceName);
		if (thisSelectedArt.typename == "SymbolItem") { // selected item is a symbol: replace the symbol.
			replaceSymbolReference(thisSelectedArt, symbolToPlace);
		} else if (thisSelectedArt.typename == "GroupItem" && thisSelectedArt.pageItems.length == 1) {
			if (thisSelectedArt.symbolItems.length == 1) {
				replaceSymbolReference(thisSelectedArt.symbolItems[0], symbolToPlace);
			} else {
				replacingArt = replaceDocumentArt(doc, thisSelectedArt.pageItems[0], symbolToPlace);
				replacingItemUuids.push(replacingArt.uuid);
			}
		} else {
			replacingArt = replaceDocumentArt(doc, thisSelectedArt, symbolToPlace);
			replacingItemUuids.push(replacingArt.uuid);
		}
	}

	var thisItem;
	for (var i = 0; i < replacingItemUuids.length; i++) {
		thisItem = doc.getPageItemFromUuid(replacingItemUuids[i]);
		thisItem.selected = true;
	}

};
test();

ANd here's the action file

/version 3
/name [ 20
	4475706c69636174652053796d626f6c20536574
]
/isOpen 1
/actionCount 1
/action-1 {
	/name [ 16
		4475706c69636174652053796d626f6c
	]
	/keyIndex 0
	/colorIndex 0
	/isOpen 1
	/eventCount 1
	/event-1 {
		/useRulersIn1stQuadrant 0
		/internalName (ai_plugin_symbol_palette)
		/localizedName [ 7
			53796d626f6c73
		]
		/isOpen 1
		/isOn 1
		/hasDialog 0
		/parameterCount 1
		/parameter-1 {
			/key 1835363957
			/showInPalette -1
			/type (enumerated)
			/name [ 16
				4475706c69636174652053796d626f6c
			]
			/value 4
		}
	}
}

 

Votes

Translate

Translate

Report

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 Beginner ,
Jan 31, 2021 Jan 31, 2021

Copy link to clipboard

Copied

Wow! Thank you. I will give it a shot.

Votes

Translate

Translate

Report

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