Skip to main content
Lordrhavin
Inspiring
June 12, 2025
Question

How can I search for Text in Textframes even if it is not shown?

  • June 12, 2025
  • 3 replies
  • 467 views

The following code is supposed to scan thru all textframes.

   	app.findGrepPreferences = NothingEnum.nothing;
   	app.changeGrepPreferences = NothingEnum.nothing;
   	app.findChangeGrepOptions.includeFootnotes = true;
   	app.findChangeGrepOptions.includeHiddenLayers = true;
   	app.findChangeGrepOptions.includeLockedLayersForFind = false;
   	app.findChangeGrepOptions.includeLockedStoriesForFind = false;
   	app.findChangeGrepOptions.includeMasterPages = true;
   	app.findGrepPreferences.findWhat = "\{\{[^:]*\:[^}]*\}\}";

    var frames = app.activeDocument.textFrames;

    for (frame = 0; frame < frames.length; ++frame) {
        currentFrame = frames[frame];
        try {
       	    var hits = currentFrame.findGrep();
   	        for (var i = 0; i < hits.length; i++) {
   	    	    hits[i].contents = hits[i].contents.replace(/\{\{([^}]*)\}\}/g,lookupEntry);
      	    }
        } catch (e) {}
    }

 
   	app.findGrepPreferences = NothingEnum.nothing;
   	app.changeGrepPreferences = NothingEnum.nothing;

Sadly, it doesnt find Text that i no shown, like when the text is bigger than the frame.
How can I search thru all text in the frame regardless if it fits into it?

3 replies

Legend
June 13, 2025

You won't find text in text frames, if it is not in them. The term is "overset".

There are plenty other objects to ask. While Peter suggested to step up to the parentStory e.g. if you're coming from a selection, you can also target the entire document, or anything in between.

Either way also finds text where the opening curly brackets are in one frame, and and the closing brackets are in a later frame of the same story.

I'd use document.findGrep, or story.findGrep as Peter suggested and iterate document.stories rather than frames. If you have a single story with 100 frames, better avoid searching the entire story for each frame …

For iterating it is better to store all items in an intermediate array outside the loop, by using the getElements() function.

var stories = doc.stories.everyItem().getElements()

Also there are several ways to iterate the findGrep results from back to front regarding their text order, otherwise after changes to preceding text the following findings will point to other text as they work with numeric offset.

 

E.g. findGrep has an optional parameter "reverseOrder".

 

 

rob day
Community Expert
Community Expert
June 12, 2025

Maye try the changeGrep() function? That works for me—this removes multiple returns even when they are in overflow text:

 

 

Overflow text on run

 

 

 

You need to escape  "\" try this "\\"

 

//grepSearch("\\{\\{[^:]*\\:[^}]*\\}\\}", "/\\{\\{([^}]*)\\}\\}/g");

grepSearch("\\r+", "\\r");


/**
* Document Grep find and change 
* @ param f the find grep string 
* @ param c the change grep string
* @ return void 
*/
function grepSearch(f,c){
    app.findGrepPreferences = app.changeGrepPreferences = app.findChangeGrepOptions = null;
    app.findChangeGrepOptions.properties = app.findChangeGrepOptions.properties = {includeFootnotes:true, includeHiddenLayers:true, includeMasterPages:true, wholeWord:false}  
    app.findGrepPreferences.findWhat = f;
    app.changeGrepPreferences.changeTo = c;
    app.activeDocument.changeGrep( true )
}
Peter Kahrel
Community Expert
Community Expert
June 12, 2025

You should look in a frame's parent story, not just the text visible in a frame. So change this:

var hits = currentFrame.findGrep()

to this:

var hits = currentFrame.parentStory.findGrep()

 Why do you use JavaScript's regex for the replacements? It's safer to use InDesign's changeTo to avoid problems with formatting going all over the place.

Lordrhavin
Inspiring
June 13, 2025

indesigns changeTo takes a string. I need:

- In all texts:
{{cmd-string}}
-> swaps to a text-return of a function that gets called with the cmd-string and that knows the table-cell or text-field it start delimiter is into. So it needs a callback, and I started with the 'in all text-fields'-approach.

rob day
Community Expert
Community Expert
June 14, 2025

So it needs a callback

 

This returns an array of found text objects which you can loop thru. Keep in mind if there are back slashes in your Grep code you have to escape them—i.e., "\\{\\{[^:]*\\:[^}]*\\}\\}"   not   "\{\{[^:]*\:[^}]*\}\}"

 


var ra = grepSearch("Hello World");

//reverse loop
for (var i = ra.length-1; i > -1; i--){
	ra[i].properties = {pointSize:35, leading:40}
}; 

alert(ra.length + " Text Changes")

/**
* Document Grep find returns an array of text objects
* @ param f the find grep string 
* @ return an array of found texts 
*/
function grepSearch(f){
    app.findGrepPreferences = app.changeGrepPreferences = app.findChangeGrepOptions = null;
    app.findChangeGrepOptions.properties = app.findChangeGrepOptions.properties = {includeFootnotes:true, includeHiddenLayers:true, includeMasterPages:true, wholeWord:false}  
    app.findGrepPreferences.findWhat = f;
	return app.activeDocument.findGrep()
}