Skip to main content
dublove
Legend
October 23, 2026
Answered

How to select Lines "from 0 to Any line backwards“ that outside the current column?

Hello everyone.

Assumption:
My text box has two columns, and the first column has 12 lines. When I use the following code to select, it will report an error.

var d = app.activeDocument;
var item = app.selection[0];
item.texts[0].textColumns[0].itemByRange(0, 15).select();

The reason is that it exceeds 12 lines.


But I used the following, which only applies to the left column and not to the right column, because it starts selecting from the 0th lines of the left column(it should from right lines 0th):

var d = app.activeDocument;
var item = app.selection[0];
item.texts[0].parentTextFrames[0].lines.itemByRange(0, 20).select();

I want it to be applicable to any single column.
Or any column in multiple columns, how can I modify it.

Thnak you very much.

The forum still cannot upload images

    CORCTON34033231
    CORCTON34033231Correct answer
    Community Expert
    October 23, 2026

    Hi dublove — you're right, story is the right container here. story.lines spans the entire threaded story across all text frames, while frame.lines and textColumn.lines stop at the frame/column boundary. So: find line 0 of the cursor's column first, then count 15 lines forward through story.lines:

     

    var sel = app.selection[0];

    var ip = (sel instanceof InsertionPoint) ? sel : sel.insertionPoints[0];

    var story = ip.parentStory;

     

    // 1) find the first character of the column holding the cursor

    var cols = ip.parentTextFrames[0].textColumns;

    var colStart = -1;

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

        var chars = cols[i].characters;

        if (chars.length === 0) continue;

        var s = chars[0].index;

        var e = chars[chars.length - 1].index;

        if (ip.index >= s && ip.index <= e) { colStart = s; break; }

    }

    if (colStart === -1) {

        alert("Please place the text cursor inside the text frame and run again.");

    } else {

        // 2) story.lines runs across all threaded frames - locate the first line of that column

        var storyLines = story.lines;

        var firstLine = -1;

        for (var k = 0; k < storyLines.length; k++) {

            var lc = storyLines[k].characters;

            if (lc.length === 0) continue;

            if (lc[0].index >= colStart) { firstLine = k; break; }

        }

        if (firstLine === -1) {

            alert("Could not find the starting line.");

        } else {

            var lastLine = Math.min(firstLine + 14, storyLines.length - 1);

            storyLines.itemByRange(firstLine, lastLine).select();

        }

    }

     

    One note: itemByRange() throws if the end index runs past the last line, so the Math.min() guard stays. Let me know if it selects across the two text boxes now.

    9 replies

    CORCTON34033231
    Community Expert
    CORCTON34033231Community ExpertCorrect answer
    Community Expert
    October 23, 2026

    Hi dublove — you're right, story is the right container here. story.lines spans the entire threaded story across all text frames, while frame.lines and textColumn.lines stop at the frame/column boundary. So: find line 0 of the cursor's column first, then count 15 lines forward through story.lines:

     

    var sel = app.selection[0];

    var ip = (sel instanceof InsertionPoint) ? sel : sel.insertionPoints[0];

    var story = ip.parentStory;

     

    // 1) find the first character of the column holding the cursor

    var cols = ip.parentTextFrames[0].textColumns;

    var colStart = -1;

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

        var chars = cols[i].characters;

        if (chars.length === 0) continue;

        var s = chars[0].index;

        var e = chars[chars.length - 1].index;

        if (ip.index >= s && ip.index <= e) { colStart = s; break; }

    }

    if (colStart === -1) {

        alert("Please place the text cursor inside the text frame and run again.");

    } else {

        // 2) story.lines runs across all threaded frames - locate the first line of that column

        var storyLines = story.lines;

        var firstLine = -1;

        for (var k = 0; k < storyLines.length; k++) {

            var lc = storyLines[k].characters;

            if (lc.length === 0) continue;

            if (lc[0].index >= colStart) { firstLine = k; break; }

        }

        if (firstLine === -1) {

            alert("Could not find the starting line.");

        } else {

            var lastLine = Math.min(firstLine + 14, storyLines.length - 1);

            storyLines.itemByRange(firstLine, lastLine).select();

        }

    }

     

    One note: itemByRange() throws if the end index runs past the last line, so the Math.min() guard stays. Let me know if it selects across the two text boxes now.

    Translate
    dublove
    dubloveAuthor
    Legend
    October 23, 2026

    ​@CORCTON34033231 

    I think this issue still needs to be addressed using 'story' as a container in order to continue the selection line to the next text box.

    Translate
    CORCTON34033231
    Community Expert
    Community Expert
    October 23, 2026

    Hi dublove,

     

    Understood — to select lines starting at the cursor's column and continuing past it, use the text frame's lines collection (which runs in story order across all columns), starting at the line index where the cursor's column begins:

     

    var sel = app.selection[0];

    var ip = (sel instanceof InsertionPoint) ? sel : sel.insertionPoints[0];

    var frame = ip.parentTextFrames[0];

    var cols = frame.textColumns;

    var ipIndex = ip.index;

     

    var colFirstChar = -1;

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

        var chars = cols[i].characters;

        if (chars.length === 0) continue;

        var startIdx = chars[0].index;

        var endIdx = chars[chars.length - 1].index;

        if (ipIndex >= startIdx && ipIndex <= endIdx) { colFirstChar = startIdx; break; }

    }

     

    if (colFirstChar === -1) {

        alert("Please place the text cursor inside the text frame and run again.");

    } else {

        var frameLines = frame.lines;

        var firstLine = -1;

        for (var k = 0; k < frameLines.length; k++) {

            if (frameLines[k].characters[0].index >= colFirstChar) { firstLine = k; break; }

        }

        var lastLine = Math.min(firstLine + 15, frameLines.length - 1);

        frameLines.itemByRange(firstLine, lastLine).select();

    }

     

    Two notes: characters[-1] isn't valid in ExtendScript — use characters[characters.length - 1] for the last character. And place the text cursor in the target column before running (a text selection works too — the script uses its first insertion point). Let me know if the selection lands where you expect.

    Translate
    dublove
    dubloveAuthor
    Legend
    October 23, 2026

    Hi ​@CORCTON34033231 

    The new version only applies to the same text box.
    Not applicable across two text boxes.

    Translate
    CORCTON34033231
    Community Expert
    Community Expert
    October 23, 2026

    Hi dublove,

    Thanks for clarifying — so the column should be detected from the text cursor, not hardcoded. This version finds the column the cursor is in, then selects lines 0-15 of that column:

    var sel = app.selection[0];var ip = (sel instanceof InsertionPoint) ? sel : sel.insertionPoints[0];var cols = ip.parentTextFrames[0].textColumns;

    var col = null;for (var i = 0; i < cols.length; i++) {    if (cols[i].characters.length === 0) continue;    var startIdx = cols[i].characters[0].index;    var endIdx = (i < cols.length - 1)        ? cols[i + 1].characters[0].index        : cols[i].characters[-1].index + 1;    var inCol = (i < cols.length - 1)        ? (ip.index >= startIdx && ip.index < endIdx)        : (ip.index >= startIdx && ip.index <= endIdx);    if (inCol) { col = cols[i]; break; }}

    if (col === null) {    alert(“Please place the text cursor inside the text frame and run again.”);} else {    var endLine = Math.min(15, col.lines.length - 1);    col.lines.itemByRange(0, endLine).select();}

    Two notes:- Place the text cursor in the target column before running (a text selection works too — it uses the start of the selection).- Math.min(15, ...) avoids the itemByRange error when the column has fewer lines.

    Let me know if it selects the right column now.

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    Translate
    dublove
    dubloveAuthor
    Legend
    October 23, 2026

    Hi ​@CORCTON34033231 

    Your code will still only select the text in the current column.
    Also, did you write the code on your phone?
    Why didn't you use formatting code?

    var sel = app.selection[0];
    var ip = (sel instanceof InsertionPoint) ? sel : sel.insertionPoints[0];
    var cols = ip.parentTextFrames[0].textColumns;

    var col = null;
    for (var i = 0; i < cols.length; i++) {
    if (cols[i].characters.length === 0) continue;
    var startIdx = cols[i].characters[0].index;
    var endIdx = (i < cols.length - 1) ? cols[i + 1].characters[0].index : cols[i].characters[-1].index + 1; var inCol = (i < cols.length - 1) ? (ip.index >= startIdx && ip.index < endIdx) : (ip.index >= startIdx && ip.index <= endIdx);
    if (inCol) {
    col = cols[i]; break;
    }
    }

    if (col === null) {
    alert('Please place the text cursor inside the text frame and run again.');
    } else {
    var endLine = Math.min(20, col.lines.length - 1);
    col.lines.itemByRange(0, endLine).select();
    }

     

    Translate
    CORCTON34033231
    Community Expert
    Community Expert
    October 23, 2026

    Hi dublove,

     

    The key is that each TextColumn has its own lines collection. parentTextFrames[0].lines runs through the whole frame column by column (left column first, then the right one), which is why itemByRange(0, 20) only covered the left column.

     

    To select lines of any single column, address that column directly:

     

    var item = app.selection[0];

    var col = item.texts[0].textColumns[1]; // 0 = left, 1 = right, 2 = third, ...

    var lastLine = Math.min(20, col.lines.length - 1);

    col.lines.itemByRange(0, lastLine).select();

     

    Two things to keep in mind:

     

    - itemByRange() throws an error when the end index is past the end of the collection — that's why textColumns[0].itemByRange(0, 15) failed with only 12 lines. Clamp the end index with Math.min() against col.lines.length - 1.

    - Wrap it in a small function if you want to reuse it for any column index:

     

    function selectLinesInColumn(colIndex, startLine, endLine) {

        var col = app.selection[0].texts[0].textColumns[colIndex];

        var end = Math.min(endLine, col.lines.length - 1);

        col.lines.itemByRange(startLine, end).select();

    }

    selectLinesInColumn(1, 0, 20); // right column, lines 0-20

    Translate
    dublove
    dubloveAuthor
    Legend
    October 23, 2026

    Hi ​@CORCTON34033231 

    Thank you very much.
    After testing, it seems that your code selects the row in the last column of two columns?And first, select the text that spans two columns.

    That's not what I said.

    What I mean is to start from the 0th line of the cursor column and select the following 15 lines.

    Really annoying~I still can't upload pictures.🤢

    Translate