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

How to get coordinates of table column or cell

Explorer ,
Apr 19, 2023 Apr 19, 2023

Copy link to clipboard

Copied

Hi, I've been searching for a way to get the coordinates of a table column or cell. The reason I need this data is that I want to place another object inline with a specific column/cell. I've seen some forums discussing the idea of using createOutlines() to tempoarily create an outline that I can use for it's geometricBounds property, but that doesn't seem to work (The exception I get is "NoPathCreated"). Any idea on how I could get this data would be appreciated!

TOPICS
How to , Scripting , UXP Scripting

Views

1.9K

Translate

Translate

Report

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 1 Correct answer

Community Expert , Apr 19, 2023 Apr 19, 2023

Hi @Phil 815, I've written a script that includes a function getCellBounds. See this thread for the script. To get the bounds of a column (assuming that bounds of a cell wouldn't be adequate), you could calculate it similarly to the way getTableBounds function works. Let me know how you go.

- Mark

Votes

Translate

Translate
Community Expert ,
Apr 19, 2023 Apr 19, 2023

Copy link to clipboard

Copied

Hi @Phil 815, I've written a script that includes a function getCellBounds. See this thread for the script. To get the bounds of a column (assuming that bounds of a cell wouldn't be adequate), you could calculate it similarly to the way getTableBounds function works. Let me know how you go.

- Mark

Votes

Translate

Translate

Report

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 ,
Apr 25, 2023 Apr 25, 2023

Copy link to clipboard

Copied

These answers were extremely helpful and got me to a solution. Thank you!

Votes

Translate

Translate

Report

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
Community Expert ,
Apr 19, 2023 Apr 19, 2023

Copy link to clipboard

Copied

Hi @Phil 815 ,

also look into the TableCellBox.jsx script by Marc Autret:

https://github.com/indiscripts/IdGoodies/blob/master/snip/TableCellBox.jsx

 

The Magic Parent Bounding Box
Marc Autret, August 04, 2022

https://www.indiscripts.com/post/2022/08/magic-parent-bounding-box

 

And a discussion in German that inspired Marc Autret at hilfdirselbst.ch:

https://www.hilfdirselbst.ch/foren/Koordinaten_einer_Tabellenzelle_P583998.html

 

Regards,
Uwe Laubender
( Adobe Community Expert )

Votes

Translate

Translate

Report

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
Community Expert ,
Apr 23, 2023 Apr 23, 2023

Copy link to clipboard

Copied

Thanks @Laubender, that script looks very sophisticated! 🙂

Votes

Translate

Translate

Report

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
Participant ,
Jun 06, 2023 Jun 06, 2023

Copy link to clipboard

Copied

The script is really amazing, but I managed to crash InDesign multiple times using it.

Im pretty sure the crash is caused by a table, that is inside an anchored text frame:

TextFrame → anchored TextFrame → Table     crashes every time
TextFrame → Table                          works reliably

 

Votes

Translate

Translate

Report

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
Community Expert ,
Jun 06, 2023 Jun 06, 2023

Copy link to clipboard

Copied

@C330 S said: "The script is really amazing, but I managed to crash InDesign multiple times using it."

 

Hi @C330 S ,

did you test Marc Autret's TableCellBox.jsx or did you test @m1b 's script function getCellBounds ?

 

Regards,
Uwe Laubender
( Adobe Community Expert )

Votes

Translate

Translate

Report

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
Participant ,
Jun 06, 2023 Jun 06, 2023

Copy link to clipboard

Copied

I did use TableCellBox.jsx 

Votes

Translate

Translate

Report

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
Community Expert ,
Jun 06, 2023 Jun 06, 2023

Copy link to clipboard

Copied

Perhaps @Marc Autret will update their excellent script to work with anchored tables. In the meantime, I have modified my getCellBounds function to handle this case:

/**
 * Gets the bounds of the selected cell.
 * Draws a rectangle just for demonstration.
 * @author m1b
 * @discussion https://community.adobe.com/t5/indesign-discussions/table-s-position-amp-scripting/m-p/13555533
 */

function main() {

    var doc = app.activeDocument,
        selectedCell = getCell(app.selection[0]);

    if (
        selectedCell == undefined
        || !selectedCell.isValid
    ) {
        alert('Please select a table cell and run script again.');
        return;
    }

    var bounds = getCellBounds(selectedCell);

    // draw a rectangle with the calculated bounds
    var justForShowing = doc.layoutWindows[0].activePage.rectangles.add({ geometricBounds: bounds, fillColor: doc.swatches[4] });
    justForShowing.transparencySettings.blendingSettings.opacity = 50;

}; // end main

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Get Cell Bounds Demo");


/**
 * Returns the geometricBounds of the cell;
 * @author m1b
 * @version 2023-06-07
 * @param {Cell} cell - an Indesign Table Cell.
 * @param {String} [boundsType] - can be 'geometricBounds' or 'visibleBounds' (default: 'geometricBounds').
 * @returns {Array<Number>}
 */
function getCellBounds(cell, boundsType) {

    app.scriptPreferences.measurementUnit = MeasurementUnits.POINTS;

    boundsType = boundsType || 'geometricBounds';

    if (!cell.hasOwnProperty('index'))
        throw Error('getCellBounds failed: bad cell parameter.');

    var table = cell.parent;
    while (table.constructor.name != 'Table')
        table = table.parent;

    table.insertLabel('findMe', '1');

    var textFrame = table.parent;

    while (textFrame.parent.constructor.name == 'Character') {
        // inside anchored frame
        textFrame = textFrame.parent.parentTextFrames[0];
    }

    var cellID = cell.id,
        dupTextFrame = textFrame.duplicate(),
        dupTable;

    // find the table in dup text frame
    tableSearch:
    for (var i = 0; i < dupTextFrame.tables.length; i++) {
        if (dupTextFrame.tables[i].extractLabel('findMe') == '1') {
            dupTable = dupTextFrame.tables[i];
            break tableSearch;
        }
    }

    if (dupTable == undefined) {

        // find the table in anchored text frames
        tableSearch:
        for (var i = 0; i < dupTextFrame.textFrames.length; i++) {
            for (var j = 0; j < dupTextFrame.textFrames[i].tables.length; j++)
                if (dupTextFrame.textFrames[i].tables[j].extractLabel('findMe') == '1') {
                    dupTable = dupTextFrame.textFrames[i].tables[j];
                    break tableSearch;
                }
        }

    }

    if (dupTable == undefined)
        throw Error('getCellBounds failed: Could not find table in duplicate.');

    // convert cell to graphic, so we can get the bounds
    var dupCell = dupTable.cells.itemByID(cellID);
    dupCell.convertCellType(CellTypeEnum.GRAPHIC_TYPE_CELL);

    var bounds = dupCell.rectangles[0].geometricBounds;

    // clean up
    table.insertLabel('findMe', '');
    dupTextFrame.remove();

    // add strokeWidths
    if (boundsType === 'visibleBounds') {
        bounds[0] -= cell.topEdgeStrokeWeight;
        bounds[1] -= cell.leftEdgeStrokeWeight;
        bounds[2] += cell.bottomEdgeStrokeWeight;
        bounds[3] += cell.rightEdgeStrokeWeight;
    }
    else if (boundsType === 'geometricBounds') {
        bounds[0] -= cell.topEdgeStrokeWeight / 2;
        bounds[1] -= cell.leftEdgeStrokeWeight / 2;
        bounds[2] += cell.bottomEdgeStrokeWeight / 2;
        bounds[3] += cell.rightEdgeStrokeWeight / 2;
    }

    return bounds;

};


/**
 * Attempts to return a Cell, given an object.
 * @author m1b
 * @version 2023-02-06
 * @param {InsertionPoint|Text|Cells|Table} obj - an object related to a Cell.
 * @returns {Cell}
 */
function getCell(obj) {

    if (obj == undefined)
        return;

    if (obj.constructor.name == 'Cell')
        return obj;

    if (obj.parent.constructor.name == 'Cell')
        return obj.parent;

    if (
        obj.hasOwnProperty('cells')
        && obj.cells.length > 0
    )
        return obj.cells[0];

};

 

Votes

Translate

Translate

Report

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 ,
Jun 07, 2023 Jun 07, 2023

Copy link to clipboard

Copied

Thanks @C330 S  for the bug report. I get a crash when the cell/table belongs to an anchored frame and itself owns an anchored object.

 

Here are the three “simple” cases I've tested so far:

  1. target cell IS anchored (OK)
  2. target cell HAS an anchored object (OK)
  3. target cell IS and HAS… (KO)

 

cellbox-various-cases.gif

 

I'll try to fix case #3 asap…

Can you share an IDML so I can investigate your own example?

 

Best,

Marc

Votes

Translate

Translate

Report

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
Participant ,
Jun 07, 2023 Jun 07, 2023

Copy link to clipboard

Copied

@m1b and @Marc Autret thanks a lot for your answers. 
I might not be able to look into it before next week, but I will definitely give you feedback. I will also check, if I can give you an IDML (it’s work for a customer).

Mark, your observation absolutely makes sense, as I have an anchor mark in each of these tables (actually finding these anchored objects is the starting point of my script). 

Votes

Translate

Translate

Report

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 ,
Jun 08, 2023 Jun 08, 2023

Copy link to clipboard

Copied

Hi all,

 

I didn't find any error in TableCellBox.jsx, matrices and transformations are properly calculated even in the Anchored-To-Anchored case reported by @C330 S. However, the line that makes ID crash is this one:

 

   sto.move(MX.loBEG,cell.texts[0].insertionPoints[0]);

 

which helps us identify the InDesign bug tucked behind the issue: given a Text objet source that contains an anchored object (AO), any attempt to move it into another AO will crash ID. The bug is not even related to Table or Cell objects.

 

 

// Tested in InDesign CS6/CC, Win10
// (see animation below)
// ---

TFS = app.activeDocument.textFrames;

source = TFS.itemByName('source').texts[0]; // Text: contains the anchor

host = TFS.itemByName('host');              // TextFrame: 'host' frame
dest = host.textFrames.itemByName('dest');  // TextFrame: 'dest' frame

//source.move(LocationOptions.AT_BEGINNING,host); // WOULD BE OK
source.move(LocationOptions.AT_BEGINNING,dest);   // --> ID crash

 

 

Anchoring-to-Anchored-Bug.gif

The bug seems specific to the move() method, regardless of whether it is invoked from a Text or a parent Story. Using duplicate() instead appears to work, so we could use that as a workaround (before removing the temporary frame). But duplicate() has a serious cost: it creates separate objects (new ids, etc.), which breaks the cellBox routine's commitment to remain transparent 😕

 

Maybe our friend @Laubender will find a way around this bad compromise. [Of course there is no hope that Adobe cares about this bug and tries to fix it. They focus on serious things: renaming masterpage to parentpage, etc]

 

Best,

Marc

Votes

Translate

Translate

Report

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 ,
Jun 08, 2023 Jun 08, 2023

Copy link to clipboard

Copied

Update: The InDesign bug at the root of the issue is circumvented in TableCellBox.jsx v3 released today.

 

Anchoring-to-Anchored-Fix.gif

 

Best,

Marc

 

 

Votes

Translate

Translate

Report

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
Participant ,
Jun 16, 2023 Jun 16, 2023

Copy link to clipboard

Copied

Hi m1b and Marc, 

I finally got some time to test both scripts. My layout looks like this: 

 

Anchors.png

 

I have a text frame containing a table (»innerhalb …«). The table contains another anchored text frame with an ID (»0226«). The frame with the table is anchored in the main text flow (»Was bedeutet …«). (This actually makes sense, although it may not look like it.)

 

Both scripts work fine, InDesign didn’t crash a single time, the results were (mostly) perfect.


In my case, @m1b’s getCellBounds fails sometimes, when the text flows into a second line within a cell: 

getCellBounds.gif

 

The calculated size (grey rectangle) is not high enough (this is the ›mostly‹ part). Sometimes it is very small, sometimes it is almost high enough (like in the gif above). The cell is not created by merging two cells into one (I don’t know the proper english InDesign term for this). 

 

Marc’s TableCellBox always returns the correct size: 

TableCellBox.gif

 

Unfortunately Marc’s script is so cryptic to me, that I wasn’t able to modify it to suit my needs. 

My goal is, to write coordinates after the ID (coordinates of the bottom right corner of the cell containing the anchor mark). I don’t need very high precision. If the result is off by less than one millimetre, its’s fine for me. 

 

I found out that the variable q contains these coordinates after line 161. 
So if I just return q, instead of the statement in line 167, I have everything, I need. – Almost.

 

  • Firstly, I du not understand how to prevent the yellow rectangle from beeing drawn. 
  • Secondly, the coordinates, I get are to small by about 5 point.
    I can easily correct the values, but I’m wondering, if I’m missing something. 

 

@Marc Autret would you be so kind as to give me a hint about these two things?

 

Thank you very much, 

Martin 

 

Votes

Translate

Translate

Report

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 ,
Jun 20, 2023 Jun 20, 2023

Copy link to clipboard

Copied

Hi @C330 S 

 

Thanks for your feedback.

 

quote

(…)

Unfortunately Marc’s script is so cryptic to me, that I wasn’t able to modify it to suit my needs. 

My goal is, to write coordinates after the ID (coordinates of the bottom right corner of the cell containing the anchor mark). I don’t need very high precision. If the result is off by less than one millimetre, its’s fine for me. 

 

I found out that the variable q contains these coordinates after line 161. 
So if I just return q, instead of the statement in line 167, I have everything, I need. – Almost.

 

  • Firstly, I du not understand how to prevent the yellow rectangle from beeing drawn. 
  • Secondly, the coordinates, I get are to small by about 5 point.
    I can easily correct the values, but I’m wondering, if I’m missing something. 

(…)

By @C330 S

 

1. Basically, you can just proceed as follows:
– get the result object ret=cellBox(targetCell);
– store ret.box.geometricBounds, or visibleBounds, etc., for further processing;
– remove the box: ret.box.remove().

 

2. But keep in mind that ret.box.geometricBounds or similar properties may be misleading:

MarcAutret_0-1687275291481.png

so it is usually safer to rely on the coordinates that the function returns. I've just enhanced the returned structure to make it a bit more practical:

• first, you can now skip the rectangle creation by passing false as 2nd arg: ret=cellBox(targetCell,false).

• also, ret now exposes the properties topLeft, topRight, bottomLeft, bottomRight, which translate each anchor in spread coordinate space (that is, in points and relative to the center point of the spread). As long as the spread is not itself transformed, you can use those coordinates for processing data regardless of the rulers origin and state.

 

Edit. — Secondly, the coordinates, I get are to small by about 5 point.” The current version of cellBox compensates the edge stroke weight of the cell(s) in order to produce coordinates in the sense of a geometric path. Maybe that's the reason why you have such an offset. If you strictly need the inner geometry (disregarding stroke weight), comment the lines

   (t=pp.leftEdgeStrokeWeight||0) && (lt[0]-=t/2); // Left edge shift.
   (t=pp.topEdgeStrokeWeight||0) && (lt[1]-=t/2); // Top edge shift.
(…)
   (t=pp.rightEdgeStrokeWeight||0) && (rb[0]+=t/2); // Right edge shift.
   (t=pp.bottomEdgeStrokeWeight||0) && (rb[1]+=t/2); // Rottom edge shift.

If, on the contrary, you are looking for the outer geometry (fully including stroke weight), change t/2 into t.

 

Hope that helps.

 

Best,

Marc

Votes

Translate

Translate

Report

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
Participant ,
Jun 21, 2023 Jun 21, 2023

Copy link to clipboard

Copied

@Marc Autretthank you very much!

I suspected the solution could be something as easy as ret.box.remove(), but I couldn’t find it. 

 

I like the version with the argument false even better. ret.bottomRight gives me exactly the position I need. Now I only have to figure out, how to convert to page coordinates in millimeters, but I’m sure I’ll get there.

Regarding the »coordinates too small by 5pt«: 

I don’t think I wrote it clearly: I compared the coordinates in variable q with the coordinates of the generated yellow rectangle. Since the rectangle dosn’t have a border, I thought, the coordinates would be identical. The thinking error must be mine, as the script clearly produces the right result (the rectangle).


In the end it doesn’t matter, because the new version already gives the correct numerical result. 

 

Best regards, 

Martin 

Votes

Translate

Translate

Report

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 ,
Jun 21, 2023 Jun 21, 2023

Copy link to clipboard

Copied

LATEST
quote

@Marc Autretthank you very much!


(…) Now I only have to figure out, how to convert to page coordinates in millimeters, but I’m sure I’ll get there.


By @C330 S

 

The returned structure has topLefttopRightbottomLeft, and bottomRight coordinates computed relative to the Spread coordinate space, which does not match, in general, the custom ruler system (zeroPoint, units, etc).

 

• Strictly regarding the POINTS→MILLIMETERS conversion, you can use the UnitValue class:
   var mmValue = UnitValue(ptValue,'pt').as('mm');

 

• Now to convert spread space coordinates into page or ruler coordinates, the PDF https://indiscripts.com/tag/CST may help. In simple cases (=untransformed page and spread) it's just a matter of translating [x,y] according to the vector [dx,dy] that goes from the origin of the page (or ruler system) to the center point of the spread (i.e., the origin of the spread space).

 

Best,

Marc

Votes

Translate

Translate

Report

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
Community Expert ,
Apr 20, 2023 Apr 20, 2023

Copy link to clipboard

Copied

What exactly do you mean by "inline"?

 

Votes

Translate

Translate

Report

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
Community Expert ,
Jun 08, 2023 Jun 08, 2023

Copy link to clipboard

Copied

@Marc Autret said: "[Of course there is no hope that Adobe cares about this bug and tries to fix it. They focus on serious things: renaming masterpage to parentpage, etc]"

 

Hi Marc,

just voted to fix the bug at InDesign UserVoice:

 

Moving Anchoring Text to Anchored Object Crashes InDesign
Marc Autret, June 08, 2023
https://indesign.uservoice.com/forums/913162-adobe-indesign-sdk-scripting-bugs-and-features/suggesti...

 

Posted code there:

 

Code:
// Tested in ID CS6 and CC
// (see animation)
const BEG = LocationOptions.AT_BEGINNING;
var TFS = app.activeDocument.textFrames;

source = TFS.itemByName('source').texts[0]; // Text: contains the anchor

host = TFS.itemByName('host'); // TextFrame: 'host' frame
dest = host.textFrames.itemByName('dest'); // TextFrame: 'dest' frame

source.move(BEG,dest); // --> ID crash
//source.move(BEG,host); // WOULD BE OK
//source.duplicate(BEG,dest); // WOULD BE OK

 

 

Thanks Marc for reporting the bug.

 

PS: Attached the InDesign test document with the named text frames.

 

Regards,
Uwe Laubender
( Adobe Community Expert )

Votes

Translate

Translate

Report

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