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

Script "Divide TextFrame"

Contributor ,
Feb 06, 2023 Feb 06, 2023

There is an old, but sometimes helpfull script from John Wundes to devide Text frames.

 

/////////////////////////////////////////////////////////////////
//Divide TextFrame v.2.2 -- CS and up
//>=--------------------------------------
// Divides a multiline text field into separate textFrame objects.
// Basically, each line in the selected text object
// becomes it's own textFrame. Vertical Spacing of each new line is based on leading.
// 
// This is the opposite of my "Join TextFrames" scripts which
// takes multiple lines and stitchs them back together into the same object.
// New in 2.1 now right and center justification is kept.
// New in 2.2 better error checking, and now will run on more than one text frame at a time.
//>=--------------------------------------
// JS code (c) copyright: John Wundes ( john@wundes.com ) www.wundes.com
//copyright full text here:  http://www.wundes.com/js4ai/copyright.txt
////////////////////////////////////////////////////////////////// 

var doc = activeDocument;
var genError= "DivideTextFrame must be run on a point-text text-frame. ";
var ret_re = new RegExp("/[\x03]|[\f]|[\r\n]|[\r]|[\n]|[,]/"); 
if(doc){
        var docsel = doc.selection;
        var sel = [];
    //remember initial selection set
         for(var itemCt=0, len = docsel.length ;itemCt<len;itemCt++){
             if(docsel[itemCt].typename == "TextFrame"){
                  sel.push(docsel[itemCt]);
             }
         }
     
        if(sel.length){  //alert(sel.length+" items found.");
            for(var itemCt=0, len = sel.length ;itemCt<len;itemCt++){
                divide(sel[itemCt]);
            }      
        }else{
                alert(genError +"Please select a Text-Frame object. (Try ungrouping.)");
        }       
}else{
    alert(genError + "No document found.");
};
 
function divide(item){ 
    
	//get object position
    var selWidth = item.width; 
if(item.contents.indexOf("\n") != -1){
	//alert("This IS already a single line object!");
}else{
        
    //getObject justification
    var justification = item.story.textRange.justification;
    
	//make array
	var lineArr = fieldToArray(item);
	tfTop = item.top;
	tfLeft = item.left;
	item.contents = lineArr[0];

	//for each array item, create a new text line
	var tr = item.story.textRange;
	var vSpacing = tr.leading;
    var newTF;
	for(j=1 ; j<lineArr.length ; j++){
		newTF = item.duplicate(doc, ElementPlacement.PLACEATBEGINNING);
		newTF.contents = lineArr[j];
		newTF.top = tfTop - (vSpacing*j);
        if(justification == Justification.CENTER)
        { 	
             newTF.left = (tfLeft + (selWidth/2)) - (newTF.width/2);	
        }
    else 
            if(justification == Justification.RIGHT)
        {
            newTF.left = (tfLeft + selWidth) - newTF.width;	
        }
    else 
    {
           newTF.left = tfLeft;
    }
		newTF.selected = false;		
	}
}

function fieldToArray(myField) {  
		retChars = new Array("\x03","\f","\r","\n"); 
		var tmpTxt = myField.contents.toString();
		for (all in retChars )
        {
            tmpArr = tmpTxt.split(retChars[all]); 
        }  
		return tmpTxt.split(ret_re);
	}
 
    }

 

 

 

TOPICS
Scripting
5.5K
Translate
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 3 Correct answers

Guide , Feb 06, 2023 Feb 06, 2023

This splits the string: 

return tmpTxt.split(ret_re);

 

The for-in loop block returns an array to the variable tmpArr, which isn't used anywhere in the script. 

Translate
Mentor , Feb 07, 2023 Feb 07, 2023

Works for me, with or without Femke's correction (separates on return - got hard returns in your text?)

Translate
Advocate , Feb 07, 2023 Feb 07, 2023

Essayez cela...

 

 

// JavaScript Document for Illustrator
var remove = true;
var doc = activeDocument;
var genError= "DivideTextFrame must be run on a point-text text-frame. ";
  if(doc){
    var docsel = doc.selection;
    var k = 0;
      if(docsel.length){  //alert(sel.length+" items found.");
        for(var itemCt=0, len = docsel.length ;itemCt<len;itemCt++){
          if(docsel[itemCt].typename == "TextFrame"){
            if(docsel[itemCt].lines.length == 1){
              //alert("This IS 
...
Translate
Adobe
Guide ,
Feb 06, 2023 Feb 06, 2023

I don't use the latest version, but for-in loops are core Javascript, so I'm doubtful that they've stopped working in the latest version.  Nevertheless, it would be helpful if another user can confirm whether or not the script works in the latest version.  Meanwhile, what does the error message say and when does the error occur?  Also, as far as I can tell, the whole for-in loop block is superfluous in the script, so you can try removing

 

for (all in retChars )
        {
            tmpArr = tmpTxt.split(retChars[all]); 
        }

 

Translate
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
Contributor ,
Feb 06, 2023 Feb 06, 2023

Your're right.

Translate
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
Guide ,
Feb 06, 2023 Feb 06, 2023

This splits the string: 

return tmpTxt.split(ret_re);

 

The for-in loop block returns an array to the variable tmpArr, which isn't used anywhere in the script. 

Translate
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
Contributor ,
Feb 07, 2023 Feb 07, 2023

You're right.

Translate
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
Mentor ,
Feb 07, 2023 Feb 07, 2023

Works for me, with or without Femke's correction (separates on return - got hard returns in your text?)

Translate
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
Contributor ,
Feb 07, 2023 Feb 07, 2023

works

Translate
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 ,
Feb 07, 2023 Feb 07, 2023

Essayez cela...

 

 

// JavaScript Document for Illustrator
var remove = true;
var doc = activeDocument;
var genError= "DivideTextFrame must be run on a point-text text-frame. ";
  if(doc){
    var docsel = doc.selection;
    var k = 0;
      if(docsel.length){  //alert(sel.length+" items found.");
        for(var itemCt=0, len = docsel.length ;itemCt<len;itemCt++){
          if(docsel[itemCt].typename == "TextFrame"){
            if(docsel[itemCt].lines.length == 1){
              //alert("This IS already a single line object!");
              continue;
            }
            else{
              divide(doc,docsel[itemCt]);
              k++;
            }
          }
        }
        if(k == 0)alert(genError +"Please select a Text-Frame object. (Try ungrouping.)");
      }
      else{
        alert(genError + "No document found.");
      }
}
//------------
function divide(relativeObjet,item){
  //getObject justification and leading
  var justification = item.textRange.justification;
  var vSpacing0 = item.textRange.leading;
  var vSpacing =  vSpacing0;
  var tfTop = item.top;
  var tfLeft = item.left;
  var newTF;
    for(var j = 0; j < item.lines.length; j++){
        if (!item.lines[j].characters.length) {
          tfTop -= vSpacing0;
            continue;
        }
      newTF = relativeObjet.textFrames.add();
      item.lines[j].characters[0].duplicate(newTF.insertionPoints[0]);
      vSpacing = newTF.textRange.leading;
      newTF.contents = item.lines[j].contents;
      newTF.top = tfTop;
      tfTop -= vSpacing;
        switch (justification) {
          case (Justification.CENTER): newTF.left = tfLeft+(item.width-newTF.width)/2; break;
          case (Justification.RIGHT): newTF.left = tfLeft+item.width-newTF.width; break;
          default : newTF.left = item.left;
        }
        newTF.textRange.justification = justification;
    }
  if (remove) {item.remove();}
}

renl80416020_0-1675851015807.png

 

 

 

Translate
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
Contributor ,
Feb 08, 2023 Feb 08, 2023

@renél80416020

thanx for your contribution. When I try to run the script I get an error message, although I use point text (and it is not grouped):

"DivideTextFrame must be run on a point-text text-frame. Please select a Text-Frame object. (Try ungrouping.)"

If I create a two lines text, it will split the lines to single text frames.

Translate
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
Contributor ,
Feb 08, 2023 Feb 08, 2023

@renél80416020 @Met1  @femkeblanco O.k. the script is running well.

I thought the script was about to devide words but it was to devide lines... Just did not remeber it and mixed it up.

Thanxs for your answers.

Translate
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 ,
Dec 17, 2025 Dec 17, 2025
LATEST

// JavaScript Document for Adobe Illustrator
// Description: Divides a multi-line TextFrame into individual TextFrames per line.

var removeOriginal = true;
var doc = activeDocument;
var errorMessage = "Please select a Point-Text object. (Note: Grouped items must be ungrouped first).";

if (doc) {
var selections = doc.selection;
var processedCount = 0;

if (selections.length > 0) {
for (var i = 0; i < selections.length; i++) {
var currentItem = selections[i];

if (currentItem.typename == "TextFrame") {

// SAFETY CHECK: Ensure the target layer is not locked or hidden
if (currentItem.layer.locked || !currentItem.layer.visible) {
alert("Error: The layer '" + currentItem.layer.name + "' is locked or hidden. Please unlock it.");
continue;
}

// Only process if it has more than one line
if (currentItem.lines.length > 1) {
divideTextLines(currentItem.layer, currentItem);
processedCount++;
}
}
}

if (processedCount == 0) {
alert(errorMessage);
}
} else {
alert("No selection found. Please select a text object.");
}
}

/**
* Function to split lines into separate objects
* @Param {Layer} targetLayer - The layer where new text frames will be created
* @Param {TextFrame} originalItem - The original multi-line text frame
*/
function divideTextLines(targetLayer, originalItem) {
var justification = originalItem.textRange.justification;
var defaultLeading = originalItem.textRange.leading;

// Fallback for Auto Leading (0)
if (defaultLeading == 0) defaultLeading = originalItem.textRange.size * 1.2;

var currentTop = originalItem.top;
var originalLeft = originalItem.left;
var originalWidth = originalItem.width;
var newFrame;

for (var j = 0; j < originalItem.lines.length; j++) {
var currentLine = originalItem.lines[j];

// Skip empty lines
if (currentLine.characters.length === 0) {
currentTop -= defaultLeading;
continue;
}

// Create new text frame on the same layer
newFrame = targetLayer.textFrames.add();

// Copy formatting from the first character of the line
currentLine.characters[0].duplicate(newFrame.insertionPoints[0]);
newFrame.contents = currentLine.contents;

// Determine spacing for the next line
var lineLeading = newFrame.textRange.leading;
if (lineLeading == 0) lineLeading = newFrame.textRange.size * 1.2;

newFrame.top = currentTop;

// Handle Alignment (Left, Center, Right)
switch (justification) {
case Justification.CENTER:
newFrame.left = originalLeft + (originalWidth - newFrame.width) / 2;
break;
case Justification.RIGHT:
newFrame.left = originalLeft + originalWidth - newFrame.width;
break;
default:
newFrame.left = originalLeft;
}

newFrame.textRange.justification = justification;

// Move the cursor down for the next line
currentTop -= lineLeading;
}

// Remove the original multi-line object if enabled
if (removeOriginal) {
originalItem.remove();
}
}

Translate
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