Copy link to clipboard
Copied
Hey good afternoon!
So i'm trying to create a script that will export any and all stories where the text is colored with a swatch the user can pick. So for example, if I have some text that's black and some text that's colored with a global swatch called "Bright Orange" or a spot color swatch called "PMS 186", and I run the script, it will ask me what swatch, and I will fill in a field. The the script will export all the stories in that document that use that swatch to a text file.
I asked Chat GPT to do this rather than bother a human. Unfortunately, I keep getting an error.
I will provide the script, then the error.
I am not a coder, so I am very out of my depth here.
Any light that can be shed is welcome.
// Prompt the user to input the swatch name
var swatchName = prompt("Enter the name of the swatch for the exported text:", "French Translation");
// Set the default swatch name if no input provided
if (!swatchName) {
swatchName = "French Translation";
}
// Get a reference to the active document
var doc = app.activeDocument;
// Get the CMYK spot color swatch by name
var colorSwatch = doc.colors.itemByName(swatchName);
// Check if the swatch exists
if (!colorSwatch.isValid) {
alert('The color swatch "' + swatchName + '" does not exist in the document.');
exit();
}
// Array to store the selected stories
var selectedStories = [];
// Loop through each story in the document
for (var i = 0; i < doc.stories.length; i++) {
var story = doc.stories[i];
// Loop through each text frame in the story
for (var j = 0; j < story.textContainers.length; j++) {
var textFrame = story.textContainers[j];
// Check if the text frame contains the requested swatch color and the word "colored"
if (hasSwatchColor(textFrame, colorSwatch) && textFrame.contents.toLowerCase().includes("colored")) {
selectedStories.push(story);
break;
}
}
}
// Create a new File object
var exportFile = new File("/Path/To/Export/Directory/output.txt"); // Set the desired output path and file name
// Open the file in write mode
exportFile.open("w");
// Loop through each selected story
for (var m = 0; m < selectedStories.length; m++) {
var selectedStory = selectedStories[m];
// Loop through each text frame in the story
for (var n = 0; n < selectedStory.textContainers.length; n++) {
var textFrame = selectedStory.textContainers[n];
// Write the text content to the file
exportFile.writeln(textFrame.contents);
}
}
// Close the file
exportFile.close();
alert("Stories with the word 'colored' using the swatch '" + swatchName + "' exported to a text file!");
// Function to check if a text frame contains the specified swatch color
function hasSwatchColor(textFrame, swatch) {
// Loop through each character in the text frame
for (var i = 0; i < textFrame.characters.length; i++) {
var character = textFrame.characters[i];
// Check if the character's fill color matches the specified swatch
if (character.fillColor === swatch) {
return true;
}
}
return false;
}and here the the error, on run, after it asks for the swatch:
JavaScript Error!
Error Number: 24
Error String: textFrame.contents.toLowerCase).includes is not a function
Engine: main
File: /Users/ myname/Library/Preferences / Adobe InDesign/Version
18.0/en US/Scripts/Scripts Panel/Export French.is
Line: 33
Source:
if (hasSwatchColor(textFrame, colorSwatch) &&
textFrame.contents.toLowerCase).includes("colored")) {
Change .includes("colored") to .indexOf("colored") and you should be ok. That's case-sensitive.
Impressive what ChatGPT comes up with, but at the same time it's very inefficient code in that it saves each story multiple times. But it works.
Hi @Mean Kidney Dan , As Peter notes the code is inefficient, and for a long doc might take some time because it loops through every character. A text search should be faster. Something like this, which lets the user choose the color from a dropdown list and checks if the story has already been written:
makeDialog();
var cs;
function makeDialog(){
var d = app.dialogs.add({name:"Choose a Swatch", canCancel:true});
with(d){
with(dialogColumns.add()){
cs = dr...
Copy link to clipboard
Copied
Change .includes("colored") to .indexOf("colored") and you should be ok. That's case-sensitive.
Impressive what ChatGPT comes up with, but at the same time it's very inefficient code in that it saves each story multiple times. But it works.
Copy link to clipboard
Copied
Thanks Peter! Your change works! Very appreciated!
Copy link to clipboard
Copied
Could you mark the answer as correct? That makes the forum more usable.
Copy link to clipboard
Copied
Hi @Mean Kidney Dan , As Peter notes the code is inefficient, and for a long doc might take some time because it loops through every character. A text search should be faster. Something like this, which lets the user choose the color from a dropdown list and checks if the story has already been written:
makeDialog();
var cs;
function makeDialog(){
var d = app.dialogs.add({name:"Choose a Swatch", canCancel:true});
with(d){
with(dialogColumns.add()){
cs = dropdowns.add({stringList:getArrayNames(app.activeDocument.swatches.everyItem().getElements()), selectedIndex:2});
}
if(d.show()){
cs = app.activeDocument.swatches.everyItem().getElements()[cs.selectedIndex];
exportStories();
d.destroy();
}
}
//gets a list of swatch names
function getArrayNames(arr){
var a = [];
for(var i = 0; i < arr.length; i++){
a.push(arr[i].name);
}
return a
}
}
function exportStories(){
//the chosen color
var ft = getTextByColor(cs);
var sid = [];
var s = "Stories using " + cs.name + "swatch\r\r"
if (ft.length > 0 ) {
for (var i = 0; i < ft.length; i++){
//checks if the story has already been exported
if (!checkItem(sid, ft[i].parentStory.id)) {
sid.push(ft[i].parentStory.id)
s += ft[i].parentStory.contents + "\r\r"
}
};
var exportFile = new File(Folder.desktop + "/output.txt");
exportFile.open("w");
exportFile.writeln(s);
}
}
//Gets results of a text color search, return search results as an array
function getTextByColor(fc){
app.findTextPreferences = app.changeTextPreferences = app.findChangeTextOptions = null;
app.findTextPreferences.fillColor = fc;
return app.activeDocument.findText()
}
//Checks if an item is in an array, return true if the item is in the array
function checkItem(a, obj) {
for (var i = 0; i < a.length; i++) {
if (a[i] === obj) {
return true;
}
}
return false;
}
Copy link to clipboard
Copied
wow thanks! This one is fantastic too! Love the swatch choice dialog.
Find more inspiration, events, and resources on the new Adobe Community
Explore Now