Skip to main content
Known Participant
April 26, 2018
Answered

Change spot color and move to specific layer

  • April 26, 2018
  • 5 replies
  • 4459 views

I am new with scripting in Illustrator but see a need to script some repetitive tasks.

I start with a document that has most art on Layer 15 colored with various spot colors

I need to select all strokes of a specific color, change it to another color and move it to a different sub layer.

Layer 15

     all art

Template layer

     Cut

     Bleed

     Score

Can someone please get me started with the commands? I picked up on others who were moving items to different layers, but not changing colors also.

This topic has been closed for replies.
Correct answer Disposition_Dev

I understand now what you mean about repeat. If I select a single item and run the script that I put together, it works. It shows an error when I select more than one item. I will dig deeper to find out how to get everything in the selection list.


should be something like:

repeat with curItem in selectedObjects

     move curItem to beginning of layer "Dimension" of myDoc

end repeat

5 replies

June 27, 2020

Hello, William!

Do you know how to activate the Global option on Swatch options in Illustrator using a Script?

 

Disposition_Dev
Community Expert
August 7, 2018

hmm. yea, i'm at a loss. i haven't used applescript in years because even when i was attempting the most basic of tasks, i found it very difficult and wildly unreliable.

some people do quite well with AS, but for me, i found it unworkable for the purposes of my illustrator workflow.

Known Participant
August 7, 2018

No worry sir. I am hoping others in the Adobe community have had success with this and know why I am unable to move a selection to another layer.

Disposition_Dev
Community Expert
August 7, 2018

per the scripting guide, this is the syntax for moving a group to a layer

tell application "Adobe Illustrator"

     set allPageItems to every page item of document 1

     move allPageItems to beginning of layer 1 of document 1

end tell

Disposition_Dev
Community Expert
August 7, 2018

is there some reason not to revert your OS version so that you can use ESTK (or perhaps find a qualified developer )?

You will quickly find many insurmountable roadblocks with Applescript.

Known Participant
August 7, 2018

We use other software that has moved forward and is no longer able to install on older OS.

Macs have always been like living between a rock and a hard place at times. 90% of commercial functionality comes from 3rd party software and as you know, technology is pushing hard to make the deepest pocket happy. Not all developers update at the same time so it is a hit or miss as to when you "should" update and when you have to.

My needs for developing this function are limited to selecting specific colored items and either moving them to a specific layer, or changing the ink AND moving it to another specific layer. After that we have workflows used for color management, trapping, 3D rendering and the like. It is this setup process that I'd like to clean up.

Disposition_Dev
Community Expert
May 8, 2018

Morning, Ed. Just checking in to see how this was going. =)

Known Participant
May 8, 2018

Having trouble getting extendscript installed. Running OS 10.13 on Mac and installer is not playing nice.

I have not made progress. May go with AppleScript but that would limit platform.

Ed Schrempf

Graphic Packaging

Disposition_Dev
Community Expert
May 8, 2018

Ah.. I do believe that Sierra is the problem. Though i'm not sure whether anyone has definitively found a workaround yet. There's some speculation that you can go to the "Show Older Apps" dropdown menu in the Creative Cloud app? I'm not sure, and i can't test it because i very intentionally hold off on new OS updates for this very purpose. It seems more often than not, the updates cause more problems than they fix.

I do hope you get it fixed up though. Good luck. =)

Disposition_Dev
Community Expert
April 26, 2018

Welcome, Ed.

Nice to see a familiar 847 and 630 area code out in the wild. i'm an inhabitant of the western burbs as well. =)

To begin answering your question, I'll point you in the direction of the official Adobe Illustrator Scripting guides. There's lots of great documentation here that gives you, at the very least, a quick peek into the inner workings of Adobe's scripting API's. You have a choice between Javascript, Applescript and VBS. My personal opinioin is that you ought to skip right over AS and VBS due to the limited access to the API as well as cross platform compatibility issues. Additionally, i don't know how to help with either of those languages, so that's also a large portion of my motivation to encourage the use of JavaScript. =)

Illustrator Scripting | Adobe Developer Connection

I would go to that link, identify your version of Illustrator, and then bookmark the appropriate link, or even download the PDF to your local machine for easy access.

Now, to begin actually answering your question.

It would be helpful to know what version of Illustrator you are using, so we know what functionality we have access to. For example, we have much greater access to far more elements in CC+ versions than we had in CS5 and previous. For now, I'll assume you're using CC since Adobe has made it quite difficult to opt out of their subscription services.

Rather than writing out the script that you're asking about, I'll highlight the syntax necessary to do some of the tasks that you're asking for because if scripting is something you want to learn how to do, there is tremendous value in the trial and error process.

Targeting a specific layer:

Layers can be targeted in a couple of different ways. You can access a layer via it's index, like so:

    

     var myLayer = app.activeDocument.layers[0];

this line gets the first layer in the currently active document (indexes are zero based).

Layers can also be accessed via their name. The "name" property of a layer is displayed in the layers panel. Unlike many other objects inside the document object, a layer has a name whether you've named it or not. By default, there is one layer in a document and it is called "Layer 1". Other objects, such as groupItems have an 'undefined' name by default.

You may access a layer by name in one of two ways:

   

     var myLayer = app.activeDocument.layers.getByName("My Layer");

or

     var myLayer = app.activeDocument.layers["My Layer"];

I use the second option because it does the exact same thing and it requires less typing, which is good because i'm lazy. =)

*NOTE*

From my personal experience, if you have the ability to access an object by name instead of index, you should do so because of the problems that can arise when elements are added or removed (because this has the potential to change the indexes of all other similar elements).

Targeting almost any other object inside the DOM:

Our lesson about layers above can easily be ported into almost any other object in the DOM. If an object is named (either from the script, or manually in the GUI), you can access it by it's name just like in the layers example. (There is a lot of nuance here regarding scope which i'm happy to go into if you want to know more). But you can also access any object by it's index within a given scope (again, there is nuance regarding the index of a given object depending upon which scope you're looking in).

Targeting a swatch inside the document:

app.activeDocument.swatches is an array of swatch objects (as seen in your swatches panel). Each element of the swatches array can be accessed by index or name. So per your question, you will find what you're looking for with the following:

     var mySwatch = app.activeDocument.swatches["Name Of Target Swatch"];

Lastly, to wrap this up before i end up writing a textbook here.... perhaps it's too late for that..

Utilizing our access to menu commands:

This section assumes that you are using Adobe Illustrator CC or newer.

Please see the following documentation for the available menu commands via the app.executeMenuCommand(); method. This functionality was sadly never documented directly by Adobe, so these were all discovered through painstaking trial and error. Sadly i do not remember who is responsible for this documentation, so if anyone knows, please let me know so I can properly attribute the credit.

Illustrator CC2014 Menu Commands Reference - 手抜きLab@DTPの現場

For your purposes, you'll be looking for one of the following, depending upon your exact needs:

     app.executeMenuCommand("Find Fill & Stroke menu item") //select all objects with the same fill and stroke color as the currently selected item(s)

     app.executeMenuCommand("Find Fill Color menu item"); //select all objects with the same fill color, agnostic of stroke color

     app.executeMenuCommand("Find Stroke Color menu item"); //select all objects with the same stroke color, agnostic of fill color

Hopefully this is a good starting off point. I know there was a lot of information there, but I wish that i had a deeper understanding of how things worked when i first started as it would have saved a lot of headache. Please do ask any specific questions you may have, I'm glad to help.

Good luck!

Known Participant
April 26, 2018

This is one of the most thorough responses I have seen on almost any forum. Thank you for that. I do wish to have better understanding of this so reading the reference material is ideal.

I am using CC2018 on a Macintosh so at least I have that on my side.

Before I get deep into trying to understand this whole thing, you say there is access to most all menu commands. I was hoping my end Java Script would be able to select any line stroked with spot color1 and change it to spot color2, and move it to a layer I define in the script.

I see how I can move items to specific layers, but do I manually select them first?

I would pretty much be starting with a very fixed list of inks and layers.

I am hoping to have a script select the items filed with a color, move it to a predefined layer, and color it a different ink.

Would this be possible in one script or should it be several, one for each color.

I imagine if it can happen in one, that each color handling would happen at a time.

For instance:

var mySwatch = app.activeDocument.swatches["Color1"];

app.executeMenuCommand("Find Stroke Color menu item");

move to

var myLayer = app.activeDocument.layers["Layer1"];

var mySwatch = app.activeDocument.swatches["Color2"];

app.executeMenuCommand("Find Stroke Color menu item");

move to

var myLayer = app.activeDocument.layers["Layer2"];

I know the syntax is way off, but just trying to present my thought process.

Ed Schrempf

Disposition_Dev
Community Expert
April 26, 2018

You are very welcome. I owe everything i know to this forum, so passing that information on to others is an important piece of the puzzle for me.

Your syntax isn't off at all. all of those statements (except the move to lines) are spot on.

There are some things to note, however. Let's dive a little deeper. The app.executeMenuCommand() method behaves exactly as it does in the GUI. So you can test it out and see what happens. If you have nothing selected in the document, and then you attempt to use the GUI menus like so: Select > Same > Stroke Color you will see that nothing happens, and no error is reported. Knowing this, you always need to make sure that you have a selection before executing the menu command, otherwise nothing will happen and you won't know until you look at the file after the fact and see that nothing changed.

So that brings us to your question about selections. selection is a property of the document object and it manifests as an array of pageItems (pageItems include almost any element that you can see on the drawing area.. textFrames, pathItems, compoundPathItems, groupItems, etc.).

You can write your script to either accept the currently selected item(s) in the document, or better yet, you can begin with no selection, and have the script make the selections dynamically for you. (each of these has their pros and cons, but for the time being, we'll assume that you are working with files that have a predictable structure and the target items are reliably found where they should be.)

For reference, here's how you'd manipulate each item of the current selection (we're assuming plain old pathItems now, just simple shapes with no fancy stuff). Let's say we want to change the fillColor of each pathItem to a spot color called "Color 2" (this swatch must exist in your swatches panel already or you'll get an error).

function test()

{

    var docRef = app.activeDocument;

    var sel = docRef.selection; //this is an array of objects

    //this swatch must exist in your swatches panel before

    //executing the script. We can go over creating new

    //swatches later.

    var destSwatch = docRef.swatches["Color 2"];

    //lets loop the sel array and change the fill color of each

    //item to a spot color called "Color 2"

    for (var x = 0, len = sel.length; x < len; x++)

    {

        //here we update the fillColor property of

        //the current selected item

        //note that 'destSwatch' is an object,

        //so we need to acces its 'color' property

        sel.fillColor = destSwatch.color;

    }

}

test();

*quick note* You'll notice that any time i write some code, i wrap it in a container/wrapper/test function. This just helps to prevent any global variables from being saved in the environment and potentially contaminating some other script. This way, any variables created by the script are effectively destroyed at the end. Since Illustrator doesn't support later versions of ECMAScript and the constant let, we kind of have to fake it.

Now, assuming you want to make a selection from within your script. You'll first need to know the "address" of the item you want to select. The address is simply the path through the DOM tree. It is possible to access any object that is a child of the document object directly from the document object.. however, for now suffice it to say that it's generally a bad idea. I'll expound on this later. For the purposes of this test, let's assume we want to select all items on a given layer called "My Layer". For this, we'll do the same looping procedure as we did in the last test, but we'll be looping the "pageItems" array of the layer called "My Layer". Let's have a look:

function test()

{

    var docRef = app.activeDocument;

    var layers = docRef.layers;

    var swatches = docRef.swatches;

    var destSwatch = swatches["Color 2"];

    var myLayer = layers["My Layer"];

    //first let's clear out any existing selection so it doesn't

    //muddle up our results. When we're finished, we only want

    //certain items to be selected.

    docRef.selection = null;

    //now loop the pathItems on the layer called "My Layer"

    for (var x = 0, len = myLayer.pathItems.length; x < len; x++)

    {

        //set the current pathItems selected property to true

        myLayer.pathItems.selected = true;

    }

    //send an alert to the GUI letting the user know

    //how many items have been selected.

    //length is the property used to get the number

    //of elements in an array

    alert(docRef.selection.length);

    //get the selection array

    var sel = docRef.selection;

    //loop the selection array

    for(var x=0,len=sel.length;x<len;x++)

    {

        //change the fillColor of the current pathItem

        sel.fillColor = destSwatch.color;

    }

}

test();

Hope this helps. =)

PS. another really important resource for you to checkout is the OMV (or Object Model Viewer) that comes baked into the ExtendScript Toolkit. I assume you're using the ESTK to execute these test scripts. If you're not, you should. It gives you tons of development and debugging tools. You can access the OMV from ESTK with "CMD + /" or through the Help menu. the OMV lets you search or browse through all of the different objects in the DOM as well as their properties and methods.