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

Script: Why It Does Not Process All Items

New Here ,
Aug 04, 2024 Aug 04, 2024

Copy link to clipboard

Copied

The script does not process all visible and unlocked items in the document. is it because of the duplicates?

 

Objective:

The working script should duplicate items with fills, remove their strokes, and delete the original items' fills. After processing, the script should:

1. Duplicate match item (change fills, strokes).

2.  Create three layers named fills, strokes, and both.

3. Move items to the corresponding layers.

4. Remove any empty layers to clean up.

Problem:

Not all items are being processed correctly, and it is unclear why.

 

Illustrator Script:

 

function processItems() {
app.activeDocument.selection = null;

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

// Duplicate and process items
for (var i = items.length -1; i > 0 ; i--) {
var item = items[i];
if (item.visible && !item.locked && item.filled) {
var copiedItem = item.duplicate();
copiedItem.stroked = false;
item.filled = false;
copiedItem.move(item, ElementPlacement.PLACEAFTER);
}
}

var layers = doc.layers;
var strokesLayer, fillsLayer, bothLayer;

// Function to get or create a layer
function getOrCreateLayer(name) {
for (var i = 0; i < layers.length; i++) {
if (layers[i].name === name) {
return layers[i];
}
}
var layer = doc.layers.add();
layer.name = name;
return layer;
}

fillsLayer = getOrCreateLayer("Fills");
strokesLayer = getOrCreateLayer("Strokes");
bothLayer = getOrCreateLayer("Both");

// Move items to the appropriate layers
for (var i = 0; i < items.length; i++) {
var item = items[i];
if (item.visible && !item.locked) {
if (item.stroked && item.filled) {
item.move(bothLayer, ElementPlacement.PLACEINSIDE);
} else if (item.stroked) {
item.move(strokesLayer, ElementPlacement.PLACEINSIDE);
} else if (item.filled) {
item.move(fillsLayer, ElementPlacement.PLACEINSIDE);
}
}
}
}

processItems();

TOPICS
Scripting

Views

85

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
Adobe
Community Expert ,
Aug 04, 2024 Aug 04, 2024

Copy link to clipboard

Copied

Hi @mto38987394jxod, the reason is probably because when you duplicate an item, you might be invalidating some of your existing item references. In Illustrator, a reference to a page item is not explicitly for that page item, but think of it more something like "the 2nd Item on the 2nd Layer of 1st Document". So, for example, if you have a collection of 10 page items and you duplicate one of them into the beginning of the 2nd Layer, then  "the 2nd Item on the 2nd Layer of 1st Document" will give you a different page item!

 

You have some options. (1) you could be careful about which order and to where you duplicate the items, so that the page items remaining to be processed still have valid references, eg. don't duplicate or remove items *before* them in the layer order, or (2) you could first explicitly store all the pageItem's `uuid` properties, and then during processing, at the last minute, get a fresh reference to the page item with with Document.getItemByUuid eg.

var item = doc.getPageItemFromUuid(mySavedUuid);

 

I hope that helps, but let me know if I've guessed wrong about the reason for your issue.

- Mark

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 ,
Aug 04, 2024 Aug 04, 2024

Copy link to clipboard

Copied

LATEST

thank you, yes, i need to check if thats the problem. and thanks for the bonus code, for me its overkilled, but it can help me to find in code how all works. Thanks for your help!!

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 ,
Aug 04, 2024 Aug 04, 2024

Copy link to clipboard

Copied

By the way, as a bonus, here is a function I wrote to help me with gathering page item references. Maybe it will be useful, or maybe overkill! It won't really help you with what I guess your issue here is, but it makes collecting page items nice and encapsulated.

- Mark

/** ------------------------------------------------------------------- *
 *  GET ITEMS                                                           *
 * -------------------------------------------------------------------- *
 * @author m1b                                                          *
 * @version 2024-03-01                                                  *
 * -------------------------------------------------------------------- *
 * Collects page items from a `from` source, eg. a Document, Layer,     *
 * GroupItem, or Array. Will look inside group items up to `maxDepth`.  *
 * Search can be filtered using `filter` function. Note that the        *
 * filter function is evaluated last in the filtering process.          *
 * -------------------------------------------------------------------- *
 * Example 1. Get all items in document:                                *
 *                                                                      *
 *    var myItems = getItems({ from: app.activeDocument });             *
 *                                                                      *
 * -------------------------------------------------------------------- *
 * Example 2. Get all selected items except groups:                     *
 *                                                                      *
 *    var myItems = getItems({                                          *
 *      from: app.activeDocument.selection,                             *
 *      getGroupItems: false,                                           *
 *    });                                                               *
 *                                                                      *
 * -------------------------------------------------------------------- *
 * Example 3. Using `filter` function to choose item type:              *
 *                                                                      *
 *    var myItems = getItems({                                          *
 *      from: app.activeDocument,                                       *
 *      filter: function (item) {                                       *
 *        return (                                                      *
 *          'PathItem' === item.typename                                *
 *          || 'CompoundPathItem' === item.typename                     *
 *        );                                                            *
 *      }                                                               *
 *    });                                                               *
 *                                                                      *
 * -------------------------------------------------------------------- *
 * Example 4. Using `filter` function:                                  *
 *                                                                      *
 *    var myItems = getItems({                                          *
 *      from: app.activeDocument,                                       *
 *      filter: onlyPngLinks                                            *
 *    });                                                               *
 *                                                                      *
 *    function onlyPngLinks(item, depth) {                              *
 *       return (                                                       *
 *           'PlacedItem' === item.typename                             *
 *           && '.png' === item.file.name.slice(-4).toLowerCase()       *
 *       );                                                             *
 *    };                                                                *
 *                                                                      *
 * -------------------------------------------------------------------- *
 * Example 4. Using the `filter` function for custom collecting:        *
 *                                                                      *
 * This example bypasses the normal returned array and instead          *
 * captures items in an "external" array `itemsByDepth`.                *
 *                                                                      *
 *    var itemsByDepth = [];                                            *
 *                                                                      *
 *    function getItemsByDepth(item, depth) {                           *
 *      if (undefined == itemsByDepth[depth])                           *
 *        itemsByDepth[depth] = [];                                     *
 *      itemsByDepth[depth].push(item);                                 *
 *    };                                                                *
 *                                                                      *
 *    getItems({                                                        *
 *      from: app.activeDocument,                                       *
 *      filter: getItemsByDepth                                         *
 *    });                                                               *
 *                                                                      *
 * -------------------------------------------------------------------- *
 * @Param {Object} options - parameters
 * @Param {PageItem|Array<PageItem>|Document|Layer} options.from - the thing(s) to look in, eg. a selection.
 * @Param {Function} [options.filter] - function that, given a found item, must return true (default: no filtering).
 * @Param {Boolean} [options.getPageItems] - whether to include page items in returned items (default: true).
 * @Param {Boolean} [options.getGroupItems] - whether to include GroupItems in returned items (default: true).
 * @Param {Boolean} [options.getLayers] - whether to include Layers in returned items (default: false).
 * @Param {Boolean} [options.getHiddenItems] - whether to include hidden items in returned items (default: true).
 * @Param {Boolean} [options.getLockedItems] - whether to include locked items in returned items (default: true).
 * @Param {Boolean} [options.getGuideItems] - whether to include guide items in returned items (default: false).
 * @Param {Number} [options.maxDepth] - deepest folder level (recursion depth limit) (default: 99).
 * @Param {Boolean} [options.returnFirstMatch] - whether to return only the first found item (default: false).
 * @Param {Number} [depth] - the current depth (private).
 * @Returns {Array|PageItem} - all the found items in a flat array, or the first found item if `returnFirstMatch`.
 */
function getItems(options, depth) {

    // defaults
    options = options || {};

    var found = [],
        depth = depth || 0,
        items = options.from;

    if (!options.initialized)
        // once-off initialization
        if (!initialize())
            return [];

    itemsLoop:
    for (var i = 0, item, len = items.length; i < len; i++) {

        item = items[i];

        if (
            false === excludeFilter(item)
            && true === includeFilter(item)
        ) {
            // item found!
            found.push(item);

            if (options.returnFirstMatch)
                break itemsLoop;
        }

        if (
            'GroupItem' !== item.constructor.name
            && 'Layer' !== item.typename
        )
            // only items with children from here
            continue itemsLoop;

        if (
            excludeHidden(item)
            || excludeLocked(item)
        )
            // don't look into excluded containers
            continue itemsLoop;

        if (depth >= options.maxDepth)
            // don't go deeper
            continue itemsLoop;

        // set up for the next depth
        options.from = item.pageItems;

        // look inside
        found = found.concat(Mittens.getItems(options, depth + 1));

    }

    // this level done
    if (true == options.returnFirstMatch)
        return found[0];
    else
        return found;

    /**
     * Returns true when the item should be not be found.
     * @Param {PageItem|Layer} item
     * @Returns {Boolean}
     */
    function excludeFilter(item) {

        return (

            isAlreadyFound(item)

            // is hidden
            || excludeHidden(item)

            // is locked
            || excludeLocked(item)

            // is guide
            || (
                false === options.getGuideItems
                && true === item.guides
            )

            // is layer
            || (
                false === options.getLayers
                && 'Layer' === item.typename
            )

            // is group item
            || (
                false === options.getGroupItems
                && 'GroupItem' === item.typename
            )

            // is page item
            || (
                false === options.getPageItems
                && 'GroupItem' !== item.typename
                && undefined != item.uuid
            )

        );

    };

    /**
     * Returns true when the item should be included.
     * @Param {PageItem|Layer} item
     * @Returns {Boolean}
     */
    function includeFilter(item) {

        return (
            undefined == options.filter
            || options.filter(item, depth)
        );

    };

    /**
     * Returns true when the item should
     * be excluded because it is hidden.
     * @Param {PageItem|Layer} item
     * @Returns {Boolean}
     */
    function excludeHidden(item) {

        return (
            false === options.getHiddenItems
            && (
                true === item.hidden
                || false === item.visible
            )
        );

    };

    /**
     * Returns true when the item should
     * be excluded because it is locked.
     * @Param {PageItem|Layer} item
     * @Returns {Boolean}
     */
    function excludeLocked(item) {

        return (
            false === options.getLockedItems
            && true === item.locked
        );

    };

    /**
     * Returns true if item was already
     * found, and marks item as found,
     * to avoid finding same item twice.
     * @Param {PageItem|Layer} item
     * @Returns {Boolean}
     */
    function isAlreadyFound(item) {

        var uuid = item.hasOwnProperty('uuid')
            ? item.uuid
            : item.typename + item.zOrderPosition,

            isFound = !!options.isFound[uuid];

        options.isFound[uuid] = true;

        return isFound;

    }

    /**
     * Returns the initialised `options` object.
     * @Returns {Object}
     */
    function initialize() {

        // make a new object, so we don't pollute the original
        options = {
            initialized: true,
            depth: 0,
            isFound: {},
            filter: options.filter,
            getPageItems: false !== options.getPageItems,
            getGroupItems: false !== options.getGroupItems,
            getLayers: true === options.getLayers,
            getHiddenItems: false !== options.getHiddenItems,
            getLockedItems: false !== options.getLockedItems,
            getGuideItems: true === options.getGuideItems,
            maxDepth: options.maxDepth,
            returnFirstMatch: options.returnFirstMatch,
        };

        if (
            undefined == options.maxDepth
            || !options.maxDepth instanceof Number
        )
            options.maxDepth = 99;

        // items is a single layer
        if ('Layer' === items.typename)
            items = [items];

        // items is a document
        else if ('Document' === items.constructor.name) {

            var layers = items.layers;
            items = [];

            for (var i = 0; i < layers.length; i++)
                items.push(layers[i]);

        }

        else if ('Array' !== items.constructor.name)
            items = [items];

        return items.length > 0;

    };

};

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