Skip to main content
Inspiring
June 24, 2025
Question

UXP Scripting: Why are the table objects I find "invalid?"

  • June 24, 2025
  • 2 replies
  • 282 views

I'm doing some processing of multiple paragraphs. If any of them is a table, I need to save it in an array for handling after I'm done with the other paragraphs (so the paragraph count of the selection doesn't change while I'm iterating through it).

 

This seems to work; but when I iterate through the table array, all of the Table objects in it are "invalid." I've even checked the constructor name of each, and found it is "Table." So WTH? The code is below (and WTH Adobe, why don't you fix the "code" formatting option in the editor on this page? How many times do we have to bring this up?).

    paras = app.selection[0].paragraphs;
    var lastParaType = "";
    var emptyParas = [];    // Keep track of empty paragraphs to remove.
    var tablesToProcess = [];   // Keep track of tables (probably notes) to deal with.
    for(paraIndex = 0; paraIndex < paras.length; paraIndex++)
    {
        currPara = paras.item(paraIndex);
        if(currPara.tables.length > 0)
        {
            for(i = 0; i < currPara.tables.length; i++)
            {
                tablesToProcess.push(currPara.tables.item(i));
                alert("This table is valid? " + currPara.tables.item(i).isValid); <---- RETURNS TRUE
            }
        }
....
}
 
And then after handling the other paragraphs:
 
    if(tablesToProcess.length > 0)
    {
        alert("Tables to process: " + tablesToProcess.length);
        alert("Table is " + tablesToProcess[0].isValid);
    }
 
This shows the expected number of tables in my test case, but the second line returns false. Any action on the second line fails with "invalid object" despite my not having removed any paragraphs yet.

2 replies

Brainiac
June 24, 2025

Try this:

var tablesToProcess = app.selection[0].paragraphs.everyItem().tables.everyItem().getElements();

 

Maybe the following is sufficient or even intended, it would excluded tables from the unselected parts of the first and last paragraphs. A single paragraph can hold multiple tables and text between them.

 

var tablesToProcess = app.selection[0].tables.everyItem().getElements();

 

Not sure how the constructor name worked for you, I thought we're supposed to use the .constructorName property in UXP.

 

You may also have a look at the myTable.toSpecifier() string to see where that table object is really pointing.

Assuming UXP does support toSpecifier(), if not so, use app.doScript() and let ExtendScript do the work.

 

@John D Herzog that's an array variable, no collection, thus no item() function.

Inspiring
June 24, 2025

Thanks! While I'd like to get to the bottom of it, I just ended up trashing the array and changing the code to re-acquire the tables from the selection after I do my other processing:

 

    // Process tables
    let tablesToProcess = app.selection[0].tables;
    if (tablesToProcess.length > 0)
    {
        alert("selection tables:" + tablesToProcess.length);
        alert("Cells for the first: " + tablesToProcess.item(0).cells.length);
    }
 
I wish the UXP Developer Tools worked, so I could debug properly without putting alerts everywhere. But oh well.
John D Herzog
Inspiring
June 24, 2025

What if you put tablesToProcess.item(0).isValid?

Inspiring
June 24, 2025

Thanks the reply. That throws an error because tablesToProcess is a legitimate array (explicitly declared with var tablesToProcess = []), not one of InDesign's collections.