Skip to main content
Participating Frequently
February 11, 2025
Answered

Get content of textframe on specific layer and page

  • February 11, 2025
  • 4 replies
  • 373 views

I've got an InDesign file with dozens of pages which I need to export as separate pages through a script. That part works fine but what I would like to do is name the exporting files after the content of a specific textframe on each page. The textframe is the only frame on a separate layer. What I currently have is this:

var _doc = app.activeDocument;
var _rangeFirst = parseInt(_range[0]) - 1;
var _rangeLast = parseInt(_range[_range.length - 1]);

var _textFrames = _doc.layers.item('myLayer').textFrames;
var _naming;
for (var k = _rangeFirst; k < _rangeLast; k++) {
    _naming = _doc.pages[k].pageItems[{itemLayer : 'myLayer'}].textFrames[0].contents;
alert(_naming)
}

I know that pageItems[{itemLayer : 'myLayer'}] does not work, VSC has been quite vocal about that ;). What is the correct syntax in this case? Any help is much appreciated.

Correct answer m1b

Hi @ep_nna, similar to the answers you already have, here is the way I would approach it.

- Mark

/**
 * Demonstration of getting a Page's textFrame from a layer.
 * 
 * @author m1b
 * @version 2025-02-13
 * @discussion https://community.adobe.com/t5/indesign-discussions/get-content-of-textframe-on-specific-layer-and-page/m-p/15145413
 */
function main() {

    var doc = app.activeDocument,

        // the layer containing the "names" text frame(s)
        namesLayer = doc.layers.itemByName('Names Layer');

    if (!namesLayer.isValid)
        return alert('There is no "Names Layer".');

    var pages = doc.pages,
        names = [];

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

        // call the function to get the name
        var pageName = getFirstTextOnLayerOnPage(namesLayer, pages[i]);

        if (!pageName)
            // couldn't get name!
            continue;

        // just for demo
        names.push(pageName);

        // now that you have the name, you can do the export here

    };

    // just for demo
    alert('Names:\n' + names.join('\n'));

};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Do Script');

/**
 * Returns contents of the first text frame on `layer` on `page`.
 * @author m1b
 * @version 2025-02-13
 * @param {Layer} layer - the target Layer.
 * @param {Page} page - the target page.
 * @returns {String?}
 */
function getFirstTextOnLayerOnPage(layer, page) {

    if (!layer || !page)
        throw new Error('getFirstTextOnLayerOnPage: bad parameter.');

    var textFrames = page.textFrames;

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

        var frame = textFrames[i];

        if (frame.itemLayer === layer)
            return frame.contents;

    }

};

4 replies

m1b
Community Expert
m1bCommunity ExpertCorrect answer
Community Expert
February 13, 2025

Hi @ep_nna, similar to the answers you already have, here is the way I would approach it.

- Mark

/**
 * Demonstration of getting a Page's textFrame from a layer.
 * 
 * @author m1b
 * @version 2025-02-13
 * @discussion https://community.adobe.com/t5/indesign-discussions/get-content-of-textframe-on-specific-layer-and-page/m-p/15145413
 */
function main() {

    var doc = app.activeDocument,

        // the layer containing the "names" text frame(s)
        namesLayer = doc.layers.itemByName('Names Layer');

    if (!namesLayer.isValid)
        return alert('There is no "Names Layer".');

    var pages = doc.pages,
        names = [];

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

        // call the function to get the name
        var pageName = getFirstTextOnLayerOnPage(namesLayer, pages[i]);

        if (!pageName)
            // couldn't get name!
            continue;

        // just for demo
        names.push(pageName);

        // now that you have the name, you can do the export here

    };

    // just for demo
    alert('Names:\n' + names.join('\n'));

};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Do Script');

/**
 * Returns contents of the first text frame on `layer` on `page`.
 * @author m1b
 * @version 2025-02-13
 * @param {Layer} layer - the target Layer.
 * @param {Page} page - the target page.
 * @returns {String?}
 */
function getFirstTextOnLayerOnPage(layer, page) {

    if (!layer || !page)
        throw new Error('getFirstTextOnLayerOnPage: bad parameter.');

    var textFrames = page.textFrames;

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

        var frame = textFrames[i];

        if (frame.itemLayer === layer)
            return frame.contents;

    }

};
Robert at ID-Tasker
Legend
February 11, 2025

@ep_nna 

 

Or if you have them on a separate layer - name them:

 

 

and then use itemByName:

 

https://www.indesignjs.de/extendscriptAPI/indesign-latest/#TextFrames.html#d1e533551__d1e533820

 

 

for (var k = _rangeFirst; k < _rangeLast; k++) {
    _naming = _doc.pages[k].textFrames.itemByName("name_for_exported_file").contents;
alert(_naming)
}

 

Robert at ID-Tasker
Legend
February 11, 2025
_doc.layers.item('myLayer').textFrames.everyItem().name = "name_for_exported_file";
Robert at ID-Tasker
Legend
February 11, 2025

@ep_nna 

 

You need to build a list/collection of the indexes - or names - of the pages from those TextFrames - and use in your loop.

 

Inspiring
February 11, 2025

You can go thru textframes and pick the right layer. Not very pretty but works.

 

for (var i = 0; i < _doc.pages[0].textFrames.length; i++ ){
if (_doc.pages[0].textFrames[i].itemLayer.name == 'myLayer'){
_naming = _doc.pages[0].textFrames[i].contents;
break;
}
}

 

Or thru layer items (prettier without the if-clause). The item order is not the same as page order. If you need order create an array of names and page numbers and arrange.

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

    page_number = _doc.layers.item('myLayer').textFrames.item(i).parentPage.name;
    _naming = _doc.layers.item('myLayer').textFrames.item(i).contents;
}