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

Creating a dynamic action to use with app.doScript() method.

Valorous Hero ,
Feb 10, 2017 Feb 10, 2017

Copy link to clipboard

Copied

Since building dynamic actions is a topic unto itself, we often search for a reference thread to show somebody how to do this - and we often do so while trying to discuss work which is already involved and has nothing to do with actions or loading and playing them. Therefore I'm creating this thread to show an example and I'll paste the url to it when such questions arise.

Sometimes in Illustrator scripting we need to accomplish tasks which (sometimes counterintuitively) do not have scripting access via the DOM.

Fortunately since Illustrator CS6, they gave us the ability to play an action from a script with the app.doScript() command - which is not at all the same as Indesign's function of the same name. This one lets you play an action that exists inside the Actions panel. Immediately this may seem disappointing as users cannot be counted on to have specific actions at any given time.

However, they also gave the ability to load and remove actions from .aia action files. Your .aia file just needs to be somewhere and app.loadAction() can read it right into the Actions panel. Same with app.unloadAction(setName, actionName) - where (thanks to qwertyfly) using (setName, "") an empty string argument for the action name will remove the entire set. And when you try to remove an action that does not exist, well, it throws an error - which is how you can check for making absolutely sure that an action set is completely removed.

This may seem like a lot of work - to write a file, read it, play it and then discard it, often to do something that you'd think scripting should do in the first place.

Sometimes the action alone is enough to satisfy an objective - such as changing the document color mode. Other times it is necessary to alter actions in order to get use out of them - such as when you try to create a routine for saving a high-resolution "Export" JPG that is different in output and options form the "Save for Web" JPG. You may want to change some of the parameters such as resolution or the actual destination of the file.

Here is how you can do this.

First, record your action as you would normally: record a new set with a new action, call them what you need and then in the Actions flyout menu, save out a .aia file where you can find it. You can open the file in a text editor and read the contents - they are lines of special Actions 'code' which contains some cryptic text.

There are lines which look like a bunch of gibberish characters, they are hex-encoded strings for some parameter item which are strings, and they contain above them a number to signify the amount of characters inside the encoded string. (this is important later because this number also needs to be set properly when you put your own value in there) Other parameter items are simple numbers, but their keys are still obscured.

The truth is, while the string parameters are hexadecimal-encoded, the keys are both hexadecimal and decimal encoded! So if you wanted to know the special 4-letter keys, you'll have to run those through two decoder routines.

Next, you will need to put this entire string into your script and use some string-replacement or string-building to put your own data in those places of the action string where they matter. For example, putting your own file path into a save action.

And, after that you need to write a procedure for writing this new altered string to the file system and loading it into your Actions panel. Mind you, to leave things "as they were" you would need to remove the .aia file and the action that you have loaded.

Let's try with the save-a-jpeg workaround!

Here is the .aia string which is recorded from an Export JPEG action.

Screen Shot 2017-02-10 at 3.04.33 PM.png

/version 3

/name [ 8

  5475746f7269616c

]

/isOpen 1

/actionCount 1

/action-1 {

  /name [ 11

  4578706f7274204a504547

  ]

  /keyIndex 0

  /colorIndex 0

  /isOpen 1

  /eventCount 1

  /event-1 {

  /useRulersIn1stQuadrant 0

  /internalName (adobe_exportDocument)

  /localizedName [ 9

  4578706f7274204173

  ]

  /isOpen 1

  /isOn 1

  /hasDialog 1

  /showDialog 0

  /parameterCount 7

  /parameter-1 {

  /key 1885434477

  /showInPalette 0

  /type (raw)

  /value < 100

  0a00000001000000030000000200000000002c01020000000000000001000000

  69006d006100670065006d006100700000006f00630000000000000000000000

  0000000000000000000000000000000000000000000000000000000000000000

  00000100

  >

  /size 100

  }

  /parameter-2 {

  /key 1851878757

  /showInPalette 4294967295

  /type (ustring)

  /value [ 25

  2f55736572732f566173696c7948616c6c2f4465736b746f70

  ]

  }

  /parameter-3 {

  /key 1718775156

  /showInPalette 4294967295

  /type (ustring)

  /value [ 16

  4a5045472066696c6520666f726d6174

  ]

  }

  /parameter-4 {

  /key 1702392942

  /showInPalette 4294967295

  /type (ustring)

  /value [ 12

  6a70672c6a70652c6a706567

  ]

  }

  /parameter-5 {

  /key 1936548194

  /showInPalette 4294967295

  /type (boolean)

  /value 1

  }

  /parameter-6 {

  /key 1935764588

  /showInPalette 4294967295

  /type (boolean)

  /value 1

  }

  /parameter-7 {

  /key 1936875886

  /showInPalette 4294967295

  /type (ustring)

  /value [ 1

  32

  ]

  }

  }

}

We can see many parameters and their various cryptic blocks, but what you want to do is decode as many /type (ustring) elements as possible to get a sense of what the action is doing. At this website, you can do this fairly easily although tediously: Convert Hexadecimal To String Online

For example: "4a5045472066696c6520666f726d6174" turns into "JPEG file format".

In this action example, I am not worried about changing the other parameters dynamically - I'm assuming the settings used in my action are suitable for my purposes such as resolution being 300 for all time. The part I'd like to change is my file path so that my JPEG goes to the right place.

/value [ 25
2f55736572732f566173696c7948616c6c2f4465736b746f70
]

This line yields: "/Users/VasilyHall/Desktop"

So this is the line I'll need to replace.

Before anything else - here is how I'd embed the action string with ease. Using a text editor like Sublime text which lets you put many cursors down at one time, I can paste the action string in and find every nextline character. Then it's easy to highlight each line and put quotes around it as well as a comma in the end, or plusses - depending if you want to store the string as an array or a plain string in the script.

Screen Shot 2017-02-10 at 3.16.48 PM.png

I find the plusses a little cluttering so I opt to use this format:
var actionString = [     "string",

     "string"

].join("\n");

So my dynamic portion of the string which will be used with string replacement would look like this:

"  /value [ {{number_of_characters}}",

"  {{hex_encoded_path}}",

"  ]",

When the action is ready to be dispatched, a string replacement would look like this:

var myNewPath = Folder.myDocuments.toString() + "/Destination";

var myNewPathEncoded = hexEncode(myNewPath); // find a hex encode function via google
var thisActionString = actionString.replace("{{hex_encoded_path}}", myNewPathEncoded).replace("{{number_of_characters}}", myNewPath.length);

Now it's time to write the file.

var f = File(actionFileLocation);

f.open('w');

f.write(thisActionString);

f.close();

And now it's time to load the action.

app.loadAction(actionFileLocation);

Now we can play the action.

app.doScript("Export JPEG", "Tutorial");

This should save your jpeg, and as of this writing, this is the only way to get the JPEG export which isn't the Save-for-Web variety.

But, let us not forget the cleanup.

Remove the .aia file:

f.remove();

Remove the single-use dynamic action:

app.unloadAction("Tutorial", "");

There you have it: building dynamic actions to do simple and non-simple things, which regular scripting just can't do.

TOPICS
Scripting

Views

15.5K

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
New Here ,
Nov 30, 2020 Nov 30, 2020

Copy link to clipboard

Copied

Thank @Silly-V!

 

If you need quick reference for all the possible export settings, I've create an easy-to-read table in the ExportDocAsJPEG in ScriptSettings.md. Also, if anyone has builds or corrections (within reason), make a request on github (or DM me) and I'll update.

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 ,
Nov 30, 2020 Nov 30, 2020

Copy link to clipboard

Copied

awesome! thanks for sharing @Y8eebtBS 

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
Explorer ,
Feb 04, 2022 Feb 04, 2022

Copy link to clipboard

Copied

someone made a useful tool for this on reddit:

"I already posted the code you need here in the replies, but I actually find myself doing this all the time and have made a personal panel for copying concatenated .aia text so I can easily paste it inside a .jsx file. You can find my copycat panel here, the extension is located at ./archive/copycat_1.0.0.zxp, and you'd install it using a ZXP Installer like this one, then relaunch AI and find in Windows > Extensions > copycat.

At that point, you'd just drag your .aia file into the panel, then paste the result into your main script to use as the contents parameter of runActionFromString."

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 ,
Feb 04, 2022 Feb 04, 2022

Copy link to clipboard

Copied

quote

someone made a useful tool for this on reddit:

By @AJJ22656695e0lw

 

that would be Tom aka @Inventsable 

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
Advocate ,
Jul 14, 2022 Jul 14, 2022

Copy link to clipboard

Copied

I was wondering how you can add it to an existing ActionSet. I see now it will add a new Set with the same name. I tried looking into what False is in the function doScript, but cant seerm to find a reference

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 ,
Jul 31, 2022 Jul 31, 2022

Copy link to clipboard

Copied

IMHO the only way to manage anything like that is to parse aia text and to splice together such an aia text that you could erase the old set with the remove method that has no argument for action-name but only one string argument specifying the set name. I am not sure what happens if two action sets with the same name are loaded and the removal method is used though.

But, regardless, it will not throw an error until there is no such action-set named that name left in the panel - so you can keep looping with a while loop until there are no more such-named sets left and you are able to retrieve an error in a try-catch block.

So, only if you have access & management of the text files to be able to 'know' what exactly is loaded inside the actions panel, you could tecnically manipulate the text to add more action events, or splice in action events and replace the target set with your special new spliced set.

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
Advocate ,
Sep 05, 2022 Sep 05, 2022

Copy link to clipboard

Copied

LATEST

If i remember correctly, when 2 actions with the same name exist. It deletes the first one. I was adding one action dynamically which was name exactly the same. So now when i use this method, i add suffix of _tmp so i deletes the correct one.

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