Skip to main content
Participating Frequently
March 17, 2023
Answered

Script to apply a style to a range of text frames or pages

  • March 17, 2023
  • 2 replies
  • 3001 views

Hi! I am  designing a book of 4 signatures, with text spanning the entirety of the book. I want to use a different paragraph style for each signature, but the text should remain continuous. What would a script look like that basically says:

  • For text frames 1-16, use Paragraph Style 1
  • For text frames 17-32, use Paragraph Style 2
  • For text frames 33-48, use Paragraph Style 3
  • For text frames 49-64, use Paragraph Style 4

 

Or some equivalent of the above. I cannot achieve this with paragraph styles or Next Style since text breaks to a new signature mostly mid-paragraph. Trying to do this manually with character styles isn’t feasible, since any minute adjustment will reflow the text and disrupt the setting on all subsequent pages.

Thanks in advance for any help!

This topic has been closed for replies.
Correct answer FRIdNGE
// by FRIdNGE, Michel Allio [18/03/2023]

// Place the Cursor in the Main Story!
var myStory = app.selection[0].parentStory,
myTFrames = myStory.textContainers,
T = myTFrames.length,  t;
//---------------------------------------------
// To Be Clearly Defined:
var myPagesRanges = [16, 32, 48, 64];
var myCStyles = ["Character Style 1", "Character Style 2", "Character Style 3", "Character Style 4"];
//---------------------------------------------
var myPagesRange = 0;
var myCStyle = 0;
for ( t = 0; t < T; t++ ) {
    try {
        if ( t >= myPagesRanges[myPagesRange] ) {
            myPagesRange++
            myCStyle++
        }
        myTFrames[t].texts[0].appliedCharacterStyle = app.activeDocument.characterStyles.item(myCStyles[myCStyle]);
    } catch(e) {}
}
alert( "Done! …" )

 

(^/)  The Jedi

2 replies

m1b
Community Expert
Community Expert
March 18, 2023

Hi @clw48, sorry if I've misunderstood your exact situation, but from what I do understand I would do it this way:

1. add a script label to the text frames that you want to set the character style (I've used the format characterStyle:<nameOfCharacterStyleHere>)

2. The script will search through all text frames and if that format is found, then set the text of that frame.

Let me know if that works in your case.

- Mark

 

 

/**
 * Sets text of specially-labeled text frame's to specified character style.
 * First put text into a multi-textFrame threaded story.
 * Then label the frames with "characterStyle:<insert Character Style name here>".
 * Then run script.
 * @author m1b
 * @discussion https://community.adobe.com/t5/indesign-discussions/script-to-apply-a-style-to-a-range-of-text-frames-or-pages/m-p/13659632/thread-id/520047
 */
function main() {

    var doc = app.activeDocument,
        stories = doc.stories.everyItem().getElements(),
        matchLabel = /^characterStyle:(.+)/i;

    for (var i = 0; i < stories.length; i++) {
        var story = stories[i],
            frames = story.textContainers;

        for (var j = 0; j < frames.length; j++) {

            // examine the frame's script label
            var match = frames[j].label.match(matchLabel);
            if (
                match == null
                || match.length < 2
            )
                // no match
                continue;

            var charStyle = doc.characterStyles.itemByName(match[1]);
            if (!charStyle.isValid)
                // matched, but style not found
                continue;

            frames[j].texts[0].applyCharacterStyle(charStyle);

        }

    }

};

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Set Text Frame Character Styles');

 

Edit: added sample .indd. Run script with that first to check that it works as I expect it to.

FRIdNGE
FRIdNGECorrect answer
Inspiring
March 18, 2023
// by FRIdNGE, Michel Allio [18/03/2023]

// Place the Cursor in the Main Story!
var myStory = app.selection[0].parentStory,
myTFrames = myStory.textContainers,
T = myTFrames.length,  t;
//---------------------------------------------
// To Be Clearly Defined:
var myPagesRanges = [16, 32, 48, 64];
var myCStyles = ["Character Style 1", "Character Style 2", "Character Style 3", "Character Style 4"];
//---------------------------------------------
var myPagesRange = 0;
var myCStyle = 0;
for ( t = 0; t < T; t++ ) {
    try {
        if ( t >= myPagesRanges[myPagesRange] ) {
            myPagesRange++
            myCStyle++
        }
        myTFrames[t].texts[0].appliedCharacterStyle = app.activeDocument.characterStyles.item(myCStyles[myCStyle]);
    } catch(e) {}
}
alert( "Done! …" )

 

(^/)  The Jedi

Robert at ID-Tasker
Legend
April 3, 2023

Sure. Here is the document I've been testing with. It's actually 160 pages (4 x 40 page signatures), but I modified the code in both yours and Jedi's scripts as follows:

 

//a character style group with the 4 styles
var sg =
  app.activeDocument.characterStyleGroups.itemByName(
    "Signature Styles"
  ).allCharacterStyles;

//the signature text frame count
var sigl = 40;

function main() {
  var s = app.documents[0].selection;
  //check the selection
  if (s.length == 0 || !s[0].hasOwnProperty("parentStory")) {
    alert("Please Select a text frame or text");
    return;
  }
  //alert if the selection’s text frames do not = sig length *4
  var tf = s[0].parentStory.textContainers;
  if (tf.length != sigl * 4) {
    alert("The selected text has " + tf.length + " text frames");
  }
  var c = 0;
  var as;
  for (var i = 0; i < tf.length; i++) {
    // use % to get every nth frame
    if (i % sigl == 0) {
      as = sg[c];
      c++;
    }
    tf[i].texts[0].appliedCharacterStyle = as;
  }
}

app.doScript(
  main,
  ScriptLanguage.JAVASCRIPT,
  undefined,
  UndoModes.ENTIRE_SCRIPT,
  "Set Text Frame Character Styles"
);

 

And:

 

// by FRIdNGE, Michel Allio [18/03/2023]

// Place the Cursor in the Main Story!
var myStory = app.selection[0].parentStory,
  myTFrames = myStory.textContainers,
  T = myTFrames.length,
  t;
//---------------------------------------------
// To Be Clearly Defined:
var myPagesRanges = [40, 80, 120, 160];
var myCStyles = [
  "Character Style 1",
  "Character Style 2",
  "Character Style 3",
  "Character Style 4",
];
//---------------------------------------------
var myPagesRange = 0;
var myCStyle = 0;
for (t = 0; t < T; t++) {
  try {
    if (t >= myPagesRanges[myPagesRange]) {
      myPagesRange++;
      myCStyle++;
    }
    myTFrames[t].texts[0].appliedCharacterStyle =
      app.activeDocument.characterStyles.item(myCStyles[myCStyle]);
  } catch (e) {}
}
alert("Done! …");

 


Because you have NoBreak set in your Character Style 1:

 

 

 

In your source document it's locally overriden - deactivated - but if you select your whole text and ClearOverrides BEFORE running script(s) - your text will be overset 😉

 

The same is with 2nd, 3rd and 4th Char Style 😉

 

In fact - ALL your CharStyles have the same problem ...

 

Robert at ID-Tasker
Legend
March 18, 2023

Can you split it into 4x separate Threads / Stories? 

 

Or you really need to change formatting mid-paragraph - between TextFrames?? 

 

 

clw48Author
Participating Frequently
March 18, 2023

I really need to change the formatting between text frames.

 

I've been working with ChatGPT to try to come up with a solution. I've come close but can't get it quite right. It seems a script that applies character styles to page ranges will be the best bet. I have the following, but when I run it, all my text disappears and becomes overset beyond the text frames:

 

// Get the active document
var doc = app.activeDocument;

// Define the page range for each character style
var style1Pages = [1, 40];
var style2Pages = [41, 80];
var style3Pages = [81, 120];
var style4Pages = [121, 160];

// Apply character styles to each page range
for (var i = style1Pages[0]; i <= style1Pages[1]; i++) {
  var tf = doc.pages[i-1].textFrames.item(0);
  if (tf.isValid) {
    tf.parentStory.characters.everyItem().appliedCharacterStyle = doc.characterStyles.itemByName("Character Style 1");
  }
}
for (var i = style2Pages[0]; i <= style2Pages[1]; i++) {
  var tf = doc.pages[i-1].textFrames.item(0);
  if (tf.isValid) {
    tf.parentStory.characters.everyItem().appliedCharacterStyle = doc.characterStyles.itemByName("Character Style 2");
  }
}
for (var i = style3Pages[0]; i <= style3Pages[1]; i++) {
  var tf = doc.pages[i-1].textFrames.item(0);
  if (tf.isValid) {
    tf.parentStory.characters.everyItem().appliedCharacterStyle = doc.characterStyles.itemByName("Character Style 3");
  }
}
for (var i = style4Pages[0]; i <= style4Pages[1]; i++) {
  var tf = doc.pages[i-1].textFrames.item(0);
  if (tf.isValid) {
    tf.parentStory.characters.everyItem().appliedCharacterStyle = doc.characterStyles.itemByName("Character Style 4");
  }
}
rob day
Community Expert
Community Expert
March 18, 2023

I really need to change the formatting between text frames.

 

Hi @clw48 , A paragraph can’t have multiple Paragraph Styles applied, so if you were trying to that without a script you would have to override the Paragraph Style when it changes text frames. A script would have to handle the override, or use Character Styles as Mark is suggesting—seems like that would get messy.