Re-labelling individual text frames in a document with multiple text frames

New Here ,
Jan 25, 2021 Jan 25, 2021

Copy link to clipboard

Copied

Hello. I am an absolute beginner when it comes to scripting so feel free to use language that a slightly intelligent child would understand. I am working with a number of text frames on a single document and would like to make a script to manipulate them individually. The only way to differentiate between them is their x,y co-ordinates. How can I write a script to tell the computer "if the text box has these co-ordinates (x,y), then re-name the object 'A'"? (I want to re-name each text box first so that it's easier for further commands for each individual object)

 

As I am a novice, I appreciate any responses from most people in this community who can probably figure this out in two seconds.

TOPICS
Scripting

Views

185

Likes

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

correct answers 1 Correct Answer

Adobe Community Professional , Jan 25, 2021 Jan 25, 2021
To start a script, it is recommended to always put it into a wrapper function that encapsulates the entirety of your script. Otherwise Illustrator can remember things from your previous script and give the illusion of something working when it shouldn't be, or vice versa. We make a wrapper function: #target illustrator function test (){   // put script code inside here. } test(); You go through each text frame in the document by doing a loop like this. var doc = app.activeDocument; var thisFra...

Likes

Translate

Translate
Adobe Community Professional ,
Jan 25, 2021 Jan 25, 2021

Copy link to clipboard

Copied

… not in two seconds …

 

You can get the (top left) position of an selected item for example like this:

 

var aDoc = app.activeDocument;
alert(aDoc.selection[0].position);
// result: /*Array*/ /*[x,y] in pt*/ for example 133.166015625,-123.552734375

 

 

Do you see the problem?

You have to convert your unit to point unit. And normally you will hardly have a match with the position values (to the 9th decimal place).

 

Aa an example:

Assuming you have a selected item with the position [100, -100]

(if not - this script snippet will move the selected textFrame to this position, compares the position and names the textFrame)

 

// required: one selected textFrame
var aDoc = app.activeDocument;
var sel = aDoc.selection;
// in this example I move the selection to a exact defined
newPos = [100, -100];
sel[0].position = newPos;

var x = sel[0].position[0];
var y = sel[0].position[1];

if (x == newPos[0] && y == newPos[1]) {
    aDoc.selection[0].name = "your new name";    
    }

 

 

 

Likes

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 Professional ,
Jan 25, 2021 Jan 25, 2021

Copy link to clipboard

Copied

To start a script, it is recommended to always put it into a wrapper function that encapsulates the entirety of your script. Otherwise Illustrator can remember things from your previous script and give the illusion of something working when it shouldn't be, or vice versa.

We make a wrapper function:
#target illustrator

function test (){

  // put script code inside here.

}

test();

 

You go through each text frame in the document by doing a loop like this.

var doc = app.activeDocument;

var thisFrame;

for (var i = 0; i < doc.textFrames.length; i++) {

  thisFrame = doc.textFrames[i];

  // do something

}

 

Now, where it says 'do someting', that's where you would need to insert some code that checks the text frame for coordinates and launches the process to deal with each text frame. So, we can make a function like this:
function processTextFrame (txtFr) {

  

}

 

Inside that function you can insert various code that deals with the text frame, and there are multiple different ways everyone can write that kind of code in their own unique style. For beginners, the simplest kind would be to create a whole bunch of if-statements.

function processTextFrame (txtFr) {

  // make a 2-size array holding the numbers inside the .position of a text frame

  var coords = [Math.floor(txtFr.position[0]), Math.floor(txtFr.position[1])]; // Math.floor trims the decimals.

  if (coords[0] == 150 && coords[1] == 50) {

    txtFr.name = "A";

  } else if (coords[0] == 250 && coords[1] == 150) {

    txtFr.name = "B";

  } //.........................................

}

 

The if-statements block can get really big and hard to edit, but when starting out this kind of block can be a great learning tool for debugging and understanding variables and the like. 
The if-statement is powerful because inside each if-block there can be arbitrary code that does many various things, so you are free to create a huge statement series that contains unique large or small bodies of code. However, such code is rarely used if ever because chances are that you would like to process most items in a very similar way if not the exact same way. In this case, you only wish to rename the text frame, so you'd be interested in a body of code that takes your text frame, a set of known coordinates and their respective names you want to change items to, as inputs and only renames the artwork. The process inside the if-statements can be extracted into a function. This is simplistic, but this can be used to consolidate many lines of duplicated code, if your processing function has more than one line of instruction.

function renameItem (txtFr, name) {

  txtFr.name = name;

}

 

So now the if-statements can contain function calls with your arguments that are always expected to be there.

function processTextFrame (txtFr) {

  var coords = [Math.floor(txtFr.position[0]), Math.floor(txtFr.position[1])];

  if (coords[0] == 150 && coords[1] == 50) {

    renameItem(txtFr, "A");

  } else if (coords[0] == 250 && coords[1] == 150) {

    renameItem(txtFr, "B");

  } //.........................................

}

 

Eventually the if-statements can be way too big to manage and find one's way around so technique like using arrays and even bringing in data from a csv can be used in functions which are designed to match properties of a current item against the other input data. Here it would be nice if there could be a table of sorts where coordinates and their respective names are stored so that it could be looped-through and spare us the many if-statements in favor of one generic if-statement that just gets repeated many times.

Here is an example of an array of objects which contain the name and coordinates, being fed into a function that processed a text frame.

var processData = [

   // keys 0 and 1 are set like this to easily match with the position accessors .position[0] and [1] - although this is somewhat unintuitive as I've rarely seen keys set like this.

  { name : "A", 0 : 150, 1 : 50 },

  { name : "B", 0 : 250, 1 : 150 },

];

function processTextFrame (txtFr, processData) {

  var coords = [Math.floor(txtFr.position[0]), Math.floor(txtFr.position[1])];

  // for-loop that tries matching the text frame coordinates to a known entry inside the processData object.

  var thisDataEntry;

  for (var i = 0; i < processData.length; i++) {

    thisDataEntry = processData[i];

    // the one if-statement here

    if (thisDataEntry[0] == coords[0] && thisDataEntry[1] == coords[1]) {

      txtFr.name = thisDataEntry.name;

      // or renameItem(txtFr, thisDataEntry.name) if the renaming process is more than a manageable amount of lines to place into this if-block

    }

  }

}

 

So finally we can have a complete script featuring a data object.

 

function test () {
	var processData = [	
	  { name : "A", 0 : 150, 1 : 50 },	
	  { name : "B", 0 : 250, 1 : 150 },	
	];
	
	function processTextFrame (txtFr, processData) {	
	  var coords = [Math.floor(txtFr.position[0]), Math.floor(txtFr.position[1])];	
	  var thisDataEntry;	
	  for (var i = 0; i < processData.length; i++) {	
	    thisDataEntry = processData[i];	
	    if (thisDataEntry[0] == coords[0] && thisDataEntry[1] == coords[1]) {	
	      txtFr.name = thisDataEntry.name;
	    }	
	  }	
	}
	
	var doc = app.activeDocument;	
	var thisFrame;
	
	for (var i = 0; i < doc.textFrames.length; i++) {	
	  thisFrame = doc.textFrames[i];	
	  processTextFrame(thisFrame, processData);	
	}
}

test();

 

Compare to the same code in long-form using many if-statements:

 

function test () {
	var doc = app.activeDocument;	
	var thisFrame, coords;
	
	for (var i = 0; i < doc.textFrames.length; i++) {	
		thisFrame = doc.textFrames[i];
	  coords = thisFrame.position;	
		if (coords[0] == 150 && coords[1] == 50) {
			thisFrame.name = "A"
		}
		if (coords[0] == 250 && coords[1] == 150) {
			thisFrame.name = "B"
		}
		if (coords[0] == 350 && coords[1] == 250) {
			thisFrame.name = "C"
		}
		if (coords[0] == 450 && coords[1] == 350) {
			thisFrame.name = "D"
		}
	}
}
test();

 

So, I hope this helps in your journey!

Likes

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 Professional ,
Jan 25, 2021 Jan 25, 2021

Copy link to clipboard

Copied

LATEST

Just to add more information

you can follow the scripting guide which will give you access to all available properties and methods for Illustrator

 

https://illustrator-scripting-guide.readthedocs.io/objectmodel/objectModel/

 

 

Best regards

Likes

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