
Disposition_Dev
Community Expert
Disposition_Dev
Community Expert
Activity
‎Jan 14, 2025
11:14 AM
2 Upvotes
So the function itself can't accept a group item because a group could have many objects of different colors. The logic in there that handles group items is because of a quirk in compound paths that can prevent you from being able to read the fill/stroke color of the compound path.
Essentially, the problem is that compoundPath does not have a "fillColor" property. To get the color of a compound path, you need to access the any pathItem in the compoundPath and get its fill/stroke. But it's possible (and quite easy) to build a compound path that contains no pathItems.... If you select some groupItems and then make a compoundPath out of them, compoundPath.pathItems.length will be 0. As an additional wrench in the works, compoundPath also doesn't have the properties "pageItems" or "groupItems".. so you can't traverse through the compound path until you find a pathItem.
So I had to build a workaround that breaks up the compound path, ungroups everything, then rebuilds the compound path out of pathItems so that the color can be extracted.
However, just yesterday I had an issue at work related to the same compoundPath buffoonery. And with the benefit of time and experience since I wrote this code originally, I realized none of that buffoonery is necessary.... The compound path doesn't need to be, and shouldn't be, altered. Instead of breaking apart and ungrouping everything, we can take advantage of one of the intrinsic properties of the compound path. Every item inside has the same fill/stroke properties. 😱🤯🤦
By creating a temporary pathItem inside the compoundPath in question, it's trivial to read the color info of that pathItem, which has inherited the color info from the rest of the compound path, then delete the temporary pathItem and boom... Color info extracted without disturbing the art at all.
I'll post an updated function later today.
... View more
‎Jan 13, 2025
02:26 PM
My guess is that you're passing in document.selection?
If so, the issue is that the function expects an object (like a pathItem or group item, etc). Document.selection is a "collection". Try using document.selection[0] instead.
... View more
‎Sep 27, 2024
01:43 PM
I know I'm late to the party here, and i wish i could be the dude who gives you an explanation for how and why this works..... but im completely baffled...
bumping this to the top to see if anyone else can shed some light.
... View more
‎Sep 16, 2024
12:36 PM
im a bit confused about what you want to do. you say that the jsx executes the ahk file.. but that means the script must already be running?
are you using the hotkey to trigger the script? or are you using the script to trigger the hotkey?
... View more
‎Sep 16, 2024
11:41 AM
can you share a screenshot of the dialog so we can see exactly what it says?
where did you download the apps from? i dont recall seeing any such dialog since before CC was launched. If you're downloading the apps from the creative cloud app, you should already be logged in and theres no reason to validate the app?
or is it a system message from your mac asking for your password to authorize the installation of something? does your user account on the computer have admin priviliges? if not, do you know who the admin is?
... View more
‎Sep 16, 2024
11:36 AM
It seems the definition of "chromebook" has evolved over the years. My son was issued a "chromebook" by his school, but it runs windows like a regular (low spec) laptop. But there are aslo chromebooks that do not use windows as an operating system.
Basically the problem isnt with the school or even the hardware itself, but rather with google's decision to use what is effectively a cross between a desktop OS and a mobile OS. Adobe software is designed for the two major desktop OSs (MacOS and Windows. Linux can run it too, but only if you run a virtual machine that runs windows).
I've never owned a chromebook, but my understanding is that the OS is built around the idea of cloud apps running from a remote server rather than running natively on the laptop itself. This helps save on size/weight and battery consumption. And with todays internet speeds, there isnt much of a performance hit (at least in things that the chromebook was designed for like text editing or document creation or web browsing).
However the downside is that it isnt really a full computer with a full operating system.
Depending on the specs of the machine, it may be possible to install windows and then install creative cloud and illustrator. But im guessing the internals of a chromebook would leave much to be wanting in terms of performance with illustrator.
Hope this helps. Feel free to ask anything if something is still a bit nebulous.
Dilliam_Wowling
... View more
‎Aug 22, 2024
11:38 AM
Here you go. This seems to work fine for me. Let me know if you still have issues with it.
function showDialog ()
{
var dialog = new Window( "dialog", "Pick and Preview Color" );
var initialColor;
// Function to update the preview panel color
function updatePreviewColor ( previewPanel, color )
{
previewPanel.graphics.backgroundColor = previewPanel.graphics.newBrush(
previewPanel.graphics.BrushType.SOLID_COLOR,
[ color.red / 255, color.green / 255, color.blue / 255, 1 ]
);
// previewPanel.graphics.foregroundColor = previewPanel.graphics.newBrush(
// previewPanel.graphics.BrushType.SOLID_COLOR,
// [ color.red / 255, color.green / 255, color.blue / 255, 1 ]
// );
// previewPanel.notify( "onDraw" ); // Force the panel to redraw
}
// Function to convert RGB values to hex color
function rgbToHex ( r, g, b )
{
return "#" + ( ( 1 << 24 ) + ( r << 16 ) + ( g << + b ).toString( 16 ).slice( 1 ).toUpperCase() );
}
// Group and elements for color picking
var colorGroup = dialog.add( "group" );
colorGroup.orientation = "row";
var colorInput = colorGroup.add( "edittext", undefined, "#000000" );
colorInput.size = [ 60, 30 ];
colorInput.enabled = false; // Disable until checkbox is selected
var colorPreview = colorGroup.add( "panel", undefined, "" );
colorPreview.size = [ 60, 30 ];
colorPreview.enabled = true; // Enable the panel
var colorButton = colorGroup.add( "button", undefined, "Pick Color" );
colorButton.size = [ , 30 ];
// Add color picker functionality
colorButton.onClick = function ()
{
initialColor = app.foregroundColor.rgb; // Store the initial foreground color
var pickedColor = app.showColorPicker();
if ( pickedColor !== -1 )
{
// Wait until the color picker is closed and then get the foreground color
$.sleep( 100 ); // Add a short delay to ensure the color picker updates
var color = app.foregroundColor.rgb;
var hexColor = rgbToHex( color.red, color.green, color.blue );
colorInput.text = hexColor;
updatePreviewColor( colorPreview, color );
}
// else
// {
// // Revert to the initial color if the picker is canceled
// app.foregroundColor.rgb = initialColor;
// }
};
// Add buttons
dialog.add( "statictext", undefined, " " ); // Adding a line gap before buttons
var buttons = dialog.add( "group" );
buttons.alignment = "center"; // Center align the buttons
var cancelButton = buttons.add( "button", undefined, "Cancel", { name: "cancel" } );
var okButton = buttons.add( "button", undefined, "OK", { name: "ok" } );
cancelButton.onClick = function ()
{
app.foregroundColor.rgb = initialColor;
dialog.close();
};
dialog.show();
}
showDialog();
... View more
‎Aug 22, 2024
10:56 AM
according to this reference, app.foregroundColor is readonly. it cant be changed via a script. (javascript at least... CEP may have access to that property). I just checked a different reference guide which says that this property is indeed read/write. my expertise is in illustrator scripting, but im trying to branch out. Ill dig into this and see if i can get some answers for you.
And as for the color not updating in your dialog/panel, i cant know for sure. I would guess that you need to add some kind of update call to the dialog after you change the color. it should just be
dialog.update();
but, since you cant change the app.foregroundColor this way, it probably doesnt matter if you can get your dialog displaying properly.
Ill play with some ideas and check back if i can find a way to update the foregroundColor via script.
... View more
‎Aug 22, 2024
10:42 AM
Adobe has worked very hard for quite a while to build the subscription model, specifically to prevent people from being able to continue to use the software they already paid for.
Im sure there's some convoluted workaround that could possibly work, but IMO, the amount of work that would go into that would be worth more than the subscription fee.
There are some other free vector based software out there, but i cant vouch for any of it because ive always had access to illustrator through my school or employer.
Best of luck on your mission if you choose to continue. Please circle back and let us know if you find anything. Surely theres at least one other person out there with the same issue.
... View more
‎Aug 14, 2024
11:27 PM
This is untested but should do the trick. And it needs some love in terms of pdf export options. unfortunately im not aware of any access to the "export for screens" dialog or functionality. But the same functionality should be doable with pdf save options. But im not sure what options you need for your use case.
function doDailyTask()
{
var doc = app.activeDocument;
app.executeMenuCommand("unlockAll");
app.executeMenuCommand("deselectall");
app.executeMenuCommand("selectallinartboard");
app.executeMenuCommand("lock");
app.executeMenuCommand("selectall");
app.executeMenuCommand("clear");
app.executeMenuCommand("unlockAll");
app.executeMenuCommand("deselectall");
deleteEmptyArtboards();
exportPDF();
function deleteEmptyArtboards()
{
var artboards = doc.artboards;
for (var i = artboards.length - 1; i >= 0; i--)
{
doc.artboards.setActiveArtboardIndex(i);
app.executeMenuCommand("selectallinartboard");
if (doc.selection.length == 0)
{
doc.artboards.remove(i);
}
app.executeMenuCommand("deselectall");
}
}
function exportPDF()
{
var exportOptions = new PDFSaveOptions();
exportOptions.artboardRange = doc.artboards.getActiveArtboardIndex() + 1;
//unfortunately, i dont believe we have script access to the export for screens dialog
//so you will have to set the pdf options manually right here
//heres the available options: https://ai-scripting.docsforadobe.dev/jsobjref/PDFSaveOptions.html
//export the active artboard
var outFileName = doc.path + "/" + doc.name.replace(".ai", ".pdf");
var outFile = new File(outFileName);
doc.saveAs(outFile, exportOptions);
}
}
doDailyTask();
... View more
‎Aug 14, 2024
10:35 PM
ok thanks. that helps.
well, here are the artboard properties that you can access. unfortunately it doesnt have any native "size" properties like height or width. so you have to calculate those from the artboardRect property, like this:
var rect = myArtboard.artboardRect;
var abWidth = rect[2] - rect[0];
var abHeight = rect[1] - rect[3];
var abSize = abWidth + "x" + abHeight; // "690x720"
once youve gathered the data you need, you can write to a csv file that can be used with excel. heres a sample of that:
var csvText = abName + "," + abSize + "," + abColorCode + "," + abThumbnailPath;
var csvFile = new File("path/to/file.csv");
csvFile.open("a"); // open in append mode, so that the existing content is not overwritten
csvFile.writeln(csvText); //write the text to the file
csvFile.close(); //close the file. failure to do so may result in data loss or corruption
The above assumes you have populated the variables abName, abSize, abColorCode, and abThumbnailPath. However, im unsure what you mean by "colour code" of the artboard. artboards dont have any properties related to color. an artboard isnt artwork, rather its a slightly fancy container that illustrator uses to export discreet sections of the "drawing area".
Additionally, im not sure how to get an actual image thumbnail into a spreadsheet from an illustrator script, you could export a thumbnail image to a specific location, then print that location to the csv and then do some magic in excel to populate those cells with the image at the relevant location.
To export a thumbnail:
var abIndex = 0;
app.activeDocument.artboards.setActiveArtboardIndex(abIndex);
var myArtboard = app.activeDocument.artboards[abIndex];
var myArtboardName = myArtboard.name;
var outFileName = myArtboardName + ".png";
var outFilePath = "~/Desktop/" + outFileName;
var exportOptions = new ExportOptionsPNG24();
exportOptions.artBoardClipping = true;
exportOptions.antiAliasing = true;
exportOptions.transparency = true;
exportOptions.verticalScale = 10;
exportOptions.horizontalScale = 10;
app.activeDocument.exportFile(new File(outFilePath), ExportType.PNG24, exportOptions);
//now, you can use outFilePath to get the path of the exported file and print it to the csv file
hope this helps point you in the right direction.
... View more
‎Aug 13, 2024
11:57 AM
instead of a video, could you write down the steps you want the script to take, as well as any decisions the script may need to make for certain steps if necessary?
... View more
‎Aug 13, 2024
11:53 AM
Its a bit unclear what you want to do.
Do you have an artboard that you want to analyze and then populate a spreadsheet with data about the artboard?
Or do you have a speadsheet with data and you want to make an artboard according to that data?
... View more
‎May 30, 2024
10:02 AM
In general, it's not a good idea to save directly to a network drive. while this isnt extremely likely, its possible that you lose connection with the server mid-save which either triggers, or is incidental to, a crash of illustrator. At best, you lose any changes since the last successful save. At worst, the file gets corrupted and you lose it all. Again, its not super likely, but it has happened to me.
Best practice is to save locally first, and then copy to the network. then if theres an issue during transfer, you still have a clean local copy.
the copying to the network can be handled automatically and periodically with a cron job, if necessary.
... View more
‎Dec 26, 2023
12:55 PM
hey everybody. my sincere apologies for the delay. i got busy, and then i forgot.
Heres the workaround code to make a request to some website from illustrator (or theoretically, any other adobe software that doesnt offer a native solution). Warning, this was purpose built for my purposes quite a while ago and i havent bothered updating it since its working for me, so it likely needs tweaks and is definitely pretty messy. and it might have some dependencies from my own utilities, but those are generic and easy.
for my needs, i have a single URL and i just paste in an identifier (order number or something) to the end of the URL and that gives me the data i need. If you are accessing data from some public API that requires credentials to be sent with the payload, im not exactly sure how to manage that. but hopefully this mess helps point someone in the right direction.
//curl data from a specified url and return the data as an anonymous object
function curlData ( url, arg )
{
var result, status = "empty";;
var htmlRegex = /<html>/gmi;
var scriptText,
scriptFile,
executor,
killExecutor;
url = url + arg;
//variables for the local data stuff
var documentsPath = "path/to/documents/folder/"
var curlDataPath = documentsPath + "curlData/"
var curlDataFolder = new Folder( curlDataPath );
if ( !curlDataFolder.exists )
{
curlDataFolder.create();
}
var localDataFile = File( curlDataPath + "curlData.txt" );
//clear out the local data file..
//make sure we always start with an empty string
localDataFile.open( "w" );
localDataFile.write( "" );
localDataFile.close();
if ( $.os.match( "Windows" ) )
{
//write the bat file that will be
//used to execute the vbs script
writeVbsFile();
//define the executor script
//cscript.exe runs the .vbs file as though the CL is being used
scriptText = "cscript.exe \"";
//path to vbs script
scriptText += curlDataPath + "socket_xhttpRequest.vbs\"";
//vbs argument 1 = url
scriptText += " \"" + url + "\" \"";
//vbs argument 2 = path to curlData.txt file
scriptText += curlDataPath + "curlData.txt";
scriptFile = File( curlDataPath + "batFile.bat" );
writeScriptFile( scriptFile, scriptText )
executor = scriptFile;
}
else
{
scriptText = [
"do shell script ",
"\"curl \\\"" + url,
"\\\" > \\\"",
curlDataPath + "curlData.txt" + "\\\"\""
].join( "" );
/
scriptFile = File( curlDataPath + "curl_from_illustrator.scpt" );
writeScriptFile( scriptFile, scriptText );
executor = File( resourcePath + "curl_from_illustrator.app" );
var localExecutor = File( documentsPath + "curlData/curl_from_illustrator.app" );
if ( localExecutor.exists )
{
executor = localExecutor;
}
}
var maxExecutorCalls = 5;
var currentExecutorCalls = 0;
var checkDelay = 200;
var numberOfChecks = 200;
var totalChecks = 0;
var parseFailResults = 0;
do
{
totalChecks = 0;
//go get the data
executor.execute();
//check the data
for ( var a = 0; a < numberOfChecks && status !== "valid"; a++ )
{
if ( status != "valid" )
{
checkData()
totalChecks++;
}
else if ( status === "html" )
{
break;
}
$.sleep( checkDelay );
}
}
while ( status !== "valid" && status !== "html" && currentExecutorCalls < maxExecutorCalls );
//validate
if ( status === "html" || ( status === "empty" && parseFailResults.length ) )
{
alert( "The request to \"" + url + arg + "\" returned invalid data for " + arg );
}
return result;
function readDataFile ()
{
var file = localDataFile;
file.open( "r" );
var contents = file.read();
file.close();
return contents;
}
function writeScriptFile ( file, txt )
{
file.open( "w" );
file.write( txt );
file.close();
}
function writeVbsFile ()
{
//go to the network and copy the contents of the
//socket_xhttpRequest.vbs file
//this allows me to manage updates by updating a
//single central file, but each person will be executing
//their own copy, which should avoid someone being denied
//access because another person is already executing the file?
//central file
var srcFile = File( dataPath + "socket_xhttpRequest.vbs" );
//local file
var destFile = File( curlDataPath + "socket_xhttpRequest.vbs" );
//read the source file's contents
srcFile.open( "r" );
var srcContents = srcFile.read();
srcFile.close();
//write the contents to the local file
writeDatabase( destFile, srcContents );
}
function checkData ()
{
var contents = readDataFile();
if ( contents === "" )
{
status = "empty";
}
else if ( contents.match( htmlRegex ) )
{
status = "html";
}
else
{
try
{
result = JSON.parse( contents );
status = "valid";
}
catch ( e )
{
status = "parseFail";
parseFailResults++;
}
}
}
}
... View more
‎Dec 04, 2023
12:58 PM
Ok. Let me dig up my curlFromIllustrator function and at the very least it might point you in the right direction.
It should do exactly what you're trying to do already, except for how you get the data after it's curled.
... View more
‎Dec 04, 2023
09:49 AM
it is possible. theres a workaround. what OS are you using? mac or windows?
... View more
‎Dec 04, 2023
09:45 AM
there is a workaround for executing shell scripts, but its not exactly elegant.
on mac, you can store a generic applescript app that only executes a shell script at a certain location. then you can use your jsx code to write the shell script text to that file, then execute the applescript app.
It can be done on windows as well. I know because i did it once, but unfortunately its been long enough that i have no idea how i did it. something about writing to a .bat file that executes some powershell code or something.
then youd just need your shell script code to save the results of the "curl" command to a file that can be read by the jsx.
... View more
‎Aug 23, 2023
10:28 AM
making global color changes like this is hard, for sure. because tons of different pageItems have different ways to access their colors. pathItems have a fillColor and strokeColor property.. but compoundPathItems do not (you have to access the first pathItem of the compound pathItem, which can cause errors because its possible to create a compoundPath out of groupItems. then you cant access the color without rebuilding the compoundPathItem).
then you can have linkedItems or symbolItems where you cant get the colors out of them without breaking the link/embedding or breaking the symbol. you just cant access the art inside of these items unless you give up some of their handy features.
then theres the issue where items can have multiple fills/strokes in the appearance panel. theres no way to access an items appearance, so all you can do is access the fillColor and strokeColor properies, which will not show you or let you edit the other fills/strokes.
then theres gradients where you have to access colors via PathItem.fillColor.gradient.gradientStops[index].color
Im not aware of any way to do this via script without looping every page item. And even then, some items cant be reliably updated with this method. =(
... View more
‎Aug 23, 2023
09:48 AM
1 Upvote
on mac you should be able to do it without applescript, by just using shell scripts instead.
write the shell script commands to a file, then execute the file with File.execute();
youd need to premake a .sh file and give it execute permissions though. but then you can just update the contents of that file dynamically with a script and then execute it.
... View more
‎Jul 27, 2023
11:45 AM
Im sensing an "X Y problem" here.
you want to export a PNG, but youre asking about how to select a layer.
The bad news: Layers can't be selected via script, as far as i know..
The good news: You don't need to. if you only want to export stuff on a certain layer(s), you can simply hide the other layers and then export normally.
The confusion: you said youre trying to select a layer, but all of your descriptions are about trying to select an envelope/plugin item...? are you trying to export a png of just that envelope item without anything else?
... View more
‎Jul 27, 2023
11:35 AM
can you share how the ai file is laid out? do you have artboards for each set, or one artboard and layers for each set? are you open to getting a folder of individual PDFs that can be merged with acrobat?
... View more
‎Jul 26, 2023
01:45 PM
definitely possible. and dare i say.. pretty easy and straightforward. ive done stuff like this many times before.
looks like carlos might be helping out, so i wont double up the work unless he doesnt have time to help out.
But as someone who's done a fair bit of plotting on vinyl, i would encourage you to also consider the order of the letters that will be cut so you can optimize the cutting path and avoid time consuming (and sometimes material consuming) travel time for the cutting tool. im sure youve seen it before where the plotter will cut one letter at the top left of the page, then cut another letter/shape at the bottom right, then move back to the top left to cut the next thing. This wastes time, puts extra wear and tear on the machine, and can sometimes skew the media (assuming youre cutting from a roll and the machine is trying to quickly feed the media back and forth) which can ruin the job and force you to start over.
... View more
‎Jul 26, 2023
01:10 PM
youre looking to do this with a script? not via the File > Package... option?
i dont know of any way to get the full path of a font... but in theory they should be coming from a specific place. so you could hard code the path to your system fonts (or whatever folder your font manager uses) and then get the font name from the api by looping all the textFrames in the document, making an array of the font names, via the TextFrameItem.textRange.textFont.name property, then write a text file with the full paths to each unique font name.
... View more
‎Jul 26, 2023
12:38 PM
1 Upvote
yea it can be difficult to find readymade illustrator scripts to fulfill specific requirements like this. its a relatively small community by software standards.
if youre willing to share your code and a sample file, i could help finish up the area function to do the logic i laid out above. send me a DM or an email to illustrator.dev.pro@gmail.com
... View more
‎Jul 25, 2023
02:14 PM
You could do the copy/pathfinder/analyze/delete without pausing the script, I believe.
... View more
‎Jul 24, 2023
06:45 PM
1 Upvote
im not aware of any scripts for that (which doesnt mean they dont exist). But my inital reaction is to make a copy of the plugin item, expand it to turn it into a regular shape (or group of regular shapes) then analyze the resuting object to get the area, then delete the copy you made.
... View more
‎Jun 06, 2023
12:37 PM
the variable docPI is set to the "collection" of pathItems. Collections are basically like "propietary" adobe arrays. theyre not really proprietary... thats not the right word. If youre familiar with strongly typed languages, collections are somewhat like "private functions" which just means you can't edit them directly like you could with a user defined array. To edit them, you need to use the available functions (like add(), remove(), etc).
That said, when you use moveToBeginning() or moveToEnd(), the argument you pass cant be a collection. It needs to be some kind of container object (eg, groupItem, layer, compoundPathItem, or document).
based on the little bit of code i can see, it looks like youre trying to move "g1" to the bottom of the layer order?
if so, you dont want the moveToEnd() method. what you want is zOrder. like this:
g1.zOrder(ZOrderMethod.SENDTOBACK)
let me know if youre looking for something else instead
... View more
‎Mar 28, 2023
09:07 AM
2 Upvotes
1. change the extension in the output file name to ".ai" instead of ".pdf" and remove the PDFSaveOptions
2. loop all the textFrames and outline them with textFrame.createOutline();
3. yes, you could send an alert. you could also use the script to shrink the text until it is no longer overset, then createOutline()
... View more
‎Mar 23, 2023
07:00 AM
first identify the textFrames you want to input information to. The easiest way is to name them, or put them on their own layer.
then loop those textFrames and update their "contents" property to match the required data.
var myTextFrame = app.activeDocument.textFrames[0];
myTextFrame.contents = "Hello World";
... View more