Copy link to clipboard
Copied
Hello everyone, I tried to show with the pictures
what I want to do with the script.
Is there someone who can help me with this?
1-) Select all in layer
2-) New Color Group
3-) Add name for new color group.With default settings.
4-)And result like this
Hi,
Try following version
var doc = app.activeDocument;
for (var l = 0; l < doc.layers.length; l++) {
app.executeMenuCommand('deselectall');
var _layer = doc.layers[l];
_layer.hasSelectedArtwork = true;
addColorGroup();
}
function addColorGroup() {
var actionStr = [
"/version 3",
"/name [ 5",
" 5365742031",
"]",
"/isOpen 1",
"/actionCount 1",
"/action-1 {",
" /name [ 9",
" 416464436f6c6f7273",
...
Copy link to clipboard
Copied
Hi,
Try following version
var doc = app.activeDocument;
for (var l = 0; l < doc.layers.length; l++) {
app.executeMenuCommand('deselectall');
var _layer = doc.layers[l];
_layer.hasSelectedArtwork = true;
addColorGroup();
}
function addColorGroup() {
var actionStr = [
"/version 3",
"/name [ 5",
" 5365742031",
"]",
"/isOpen 1",
"/actionCount 1",
"/action-1 {",
" /name [ 9",
" 416464436f6c6f7273",
" ]",
" /keyIndex 0",
" /colorIndex 0",
" /isOpen 0",
" /eventCount 1",
" /event-1 {",
" /useRulersIn1stQuadrant 0",
" /internalName (ai_plugin_swatches)",
" /localizedName [ 8",
" 5377617463686573",
" ]",
" /isOpen 1",
" /isOn 1",
" /hasDialog 1",
" /showDialog 0",
" /parameterCount 1",
" /parameter-1 {",
" /key 1835363957",
" /showInPalette 4294967295",
" /type (enumerated)",
" /name [ 15",
" 4e657720436f6c6f722047726f7570",
" ]",
" /value 17",
" }",
" }",
"}",
""
].join("\n");
var actionFileDestStr = Folder.desktop + "/MyAction.aia";
var actionFile = File(actionFileDestStr);
actionFile.open('w');
actionFile.write(actionStr);
actionFile.close();
app.loadAction(actionFile);
app.doScript("AddColors", "Set 1");
actionFile.remove();
app.unloadAction("Set 1", '');
}
Copy link to clipboard
Copied
It's perfect. exactly as I want.
thanks
Copy link to clipboard
Copied
Hi @Goldberg_1453, just before posting this I see that you already have @Charu Rajput's excellent and efficient answer and probably don't need my long-winded contribution.
However, our two scripts take very different approaches, and will have different results depending on your exact situation. For example, I think that Charu's script has the advantage of including more than just the first fill and stroke colors (ie. complex appearances) because it executes built-in menu commands, whereas my script does everything through the scripting DOM. Anyway, on the chance that you—or someone else coming here—would benefit from seeing my different approach, here it is, mostly based on functions I have written beforehand.
- Mark
/**
* Collects colors from selected items, and
* populates a swatch group with those colors.
* Notes:
* - IMPORTANT: can only work with an item's *basic*
* appearance, meaning its first fillColor and strokeColor.
* @author m1b
* @discussion https://community.adobe.com/t5/illustrator-discussions/new-color-group-whit-script/m-p/13871446
*/
(function () {
var settings = {
colorGroupName: 'My Color Group',
showResults: true,
showUI: true,
};
var colorGroupName = settings.colorGroupName,
doc = app.activeDocument,
items = itemsInsideGroupItems(doc.selection);
if (items.length == 0) {
alert('Please select one or more page items and try again.');
return;
}
if (
settings.showUI
&& !(colorGroupName = prompt('Enter name for color group:', colorGroupName))
)
return;
var results = makeSwatchGroupFromItemsColors(items, doc, colorGroupName);
if (settings.showResults)
alert('Collected ' + results.addedColorsCount + ' colors.');
})();
/**
* Creates a new SwatchGroup populated with
* colors derived from the supplied items.
* Note: function will *duplicate* existing
* global or spot colors and spot tints.
* @author m1b
* @version 2023-06-17
* @param {Array<PageItem>} items - Illustrator page items.
* @param {Document} doc - the Illustrator Document to convert.
* @param {String} name - the name of the new SwatchGroup.
*/
function makeSwatchGroupFromItemsColors(items, doc, name) {
var colorables = [],
colorablesCounter = 0,
addedColorsCounter = 0,
alreadyProcessed = {};
// get the basic colorables
for (var i = 0; i < items.length; i++)
colorables = colorables.concat(getBasicColorablesFromItem(doc, items[i]));
colorablesCounter += colorables.length;
// make the swatch group
var swatchGroup = getByName(doc.swatchGroups, name);
if (!swatchGroup) {
swatchGroup = doc.swatchGroups.add();
swatchGroup.name = name;
}
for (var i = 0; i < colorables.length; i++) {
var col = colorables[i].color,
id = stringify(col);
if (alreadyProcessed[id])
continue;
else
alreadyProcessed[id] = true;
var sw = doc.swatches.add();
sw.color = col;
swatchGroup.addSwatch(sw);
addedColorsCounter++;
}
return {
colorableCount: colorablesCounter,
addedColorsCount: addedColorsCounter,
};
};
/**
* Returns array of swatches or colors
* found in fill or stroke of page item.
* @author m1b
* @version 2022-10-11
* @param {PageItem} item - an Illustrator page item.
* @returns {Object} - {fillColors: Array<Color>, strokeColors: Array<Color>}
*/
function getBasicColorablesFromItem(doc, item) {
if (item == undefined)
throw Error('getBasicColorablesFromItem: No `item` supplied.');
var colorables = [];
// collect all the colorables
if (item.constructor.name == 'PathItem') {
colorables = colorables.concat(getBasicColorables(item));
}
else if (
item.constructor.name == 'CompoundPathItem'
&& item.pathItems
) {
colorables = colorables.concat(getBasicColorables(item.pathItems[0]));
}
else if (
item.constructor.name == 'RasterItem'
) {
// only way to get the raster item's color
var originalSelection = doc.selection;
doc.selection = [item];
colorables.push({
color: doc.defaultFillColor,
colorize: item,
});
doc.selection = originalSelection;
}
else if (
item.constructor.name == 'TextFrame'
&& item.textRanges
) {
var ranges = getTextStyleRanges(item.textRange, ['fillColor', 'strokeColor']);
for (var i = ranges.length - 1; i >= 0; i--)
colorables = colorables.concat(getBasicColorables(ranges[i]));
}
else if (item.constructor.name == 'GroupItem') {
for (var i = 0; i < item.pageItems.length; i++)
colorables = colorables.concat(getBasicColorables(item.pageItems[i]));
}
return colorables;
};
/**
* Returns array of colorable things.
* @date 2023-04-20
* @param {PageItem} item - an Illustrator page item.
* @returns {Array<Object>}
*/
function getBasicColorables(item) {
var colorables = [],
noColor = "[NoColor]";
if (
item.hasOwnProperty('fillColor')
&& item.fillColor != noColor
&& (
!item.hasOwnProperty('filled')
|| item.filled == true
)
&& item.fillColor != undefined
)
colorables.push({
color: item.fillColor,
fillColor: item
});
if (
item.hasOwnProperty('strokeColor')
&& item.strokeColor != noColor
&& (
!item.hasOwnProperty('stroked')
|| item.stroked == true
)
&& item.strokeColor != undefined
)
colorables.push({
color: item.strokeColor,
strokeColor: item
});
return colorables;
};
/**
* Returns an array of TextRanges,
* determined by mapping changes
* in supplied keys. For example,
* supplying the 'fillColor' key
* will return ranges divided when
* the text's fillColor changes.
* @author m1b
* @version 2023-04-26
* @param {TextRange} textRange - an Illustrator TextRange.
* @param {Array<String>} keys - an array of keys to match, eg ['fillColor'].
*/
function getTextStyleRanges(textRange, keys) {
if (
textRange == undefined
|| textRange.constructor.name != 'TextRange'
)
throw Error('getTextStyleRanges: bad `textRange` supplied.');
if (
keys == undefined
|| keys.constructor.name != 'Array'
)
throw Error('getTextStyleRanges: bad `textRange` supplied.');
// check keys are valid
for (var j = 0; j < keys.length; j++)
if (!textRange.characterAttributes.hasOwnProperty(keys[j]))
throw Error('getTextStyleRanges: bad key supplied ("' + keys[j] + '")');
var ranges = [],
start = 0,
currentValues = {};
charactersLoop:
for (var i = 0; i < textRange.length; i++) {
var tr = textRange.textRanges[i],
matches = true;
// check each key
keysLoop:
for (var j = 0; j < keys.length; j++) {
if (i == 0)
currentValues[keys[j]] = tr.characterAttributes[keys[j]];
else if (stringify(tr.characterAttributes[keys[j]]) !== stringify(currentValues[keys[j]])) {
matches = false;
break keysLoop;
}
}
currentValues[keys[j]] = tr.characterAttributes[keys[j]];
if (
i == textRange.length - 1
|| !matches
) {
// start a new range
var newTextRange = textRange.textRanges[start];
newTextRange.end = i == textRange.length - 1 ? i + 1 : i;
ranges.push(newTextRange);
start = i;
}
}
return ranges;
};
/**
* Stringify tailored for the purpose
* of identifying identical Swatches.
* @author m1b
* @version 2023-04-26
* @param {Object} obj - the object to stringify.
* @returns {String}
*/
function stringify(obj) {
var str = obj.toString();
for (var key in obj) {
if (!obj.hasOwnProperty(key))
continue;
if (
key == 'spot'
|| key == 'color'
)
str += stringify(obj[key]);
else
str += obj[key];
}
return str;
};
/**
* Returns array containing items, including
* items found inside GroupItems
* @author m1b
* @version 2022-05-23
* Example usage:
* var items = itemsInsideGroupItems(doc.selection, ['PathItem', 'CompoundPathItem']);
* @param {Array<PageItem>} items - array or collection of Illustrator page items.
* @param {String|Array<String>} [typenames] - item constructor names to target (default: target all typenames).
* @param {Number} [level] - recursion level (private parameter).
* @returns {Array<PathItem>} the path items found.
*/
function itemsInsideGroupItems(items, typenames, level) {
try {
if (level == undefined)
level = 0;
var found = [];
for (var i = 0; i < items.length; i++) {
var item = items[i];
if (
item.uuid == undefined
|| item.parent.typename == 'CompoundPathItem'
)
continue;
if (item.typename == 'GroupItem') {
found = found.concat(itemsInsideGroupItems(item.pageItems, typenames, level + 1));
}
else if (typenames === undefined || itemIsType(item, typenames)) {
found.push(item);
}
}
return found;
} catch (err) {
alert('itemsInsideGroupItems: ' + err)
}
};
/**
* Returns true if item.typename
* matches any of the typenames supplied.
* @param {PageItem} item - an Illustrator page item.
* @param {String|Array<String>} typenames - the typenames to check against.
* @returns {Boolean}
*/
function itemIsType(item, typenames) {
if (!typenames.constructor.name == 'Array')
typenames = [typenames];
var matched = false;
for (var i = 0; i < typenames.length; i++) {
if (typenames[i] == item.typename) {
matched = true;
break;
}
}
return matched;
};
/**
* Gets a thing by name from array of named things.
* @param {Array<any>} things - array of named things.
* @param {String} name - the name to look for.
* @returns {Any} - the found thing.
*/
function getByName(things, name) {
for (var i = 0; i < things.length; i++)
if (things[i].name == name)
return things[i];
};
Copy link to clipboard
Copied
@m1b - Thank you, We shoould always have second approach to do things, you never know what section of code give you something new.. 🙂
Get ready! An upgraded Adobe Community experience is coming in January.
Learn more