In this article I will demonstrate a method for getting to a Table using the prescribed methods in the API context.body.
Background
In previous articles we jhave seen how to create a table from scratch using the API or using OOXML. In this article we will look at how to reference an existing table and get a handle on it. We are going to look at two methods, one direct and one indirect, both have advantages and disadvantages.
Getting a table via the API directly
Within the the API model you can access all tables through the context.document.body.tables
The Methods (at leave in v1.3) are rather limiting and you cannot get a Table directly by name or id.
const tableCollection = context.document.body.tables;
and from there you can reference each table individually through the index.
theTable = tableCollection.items[i]
What this does not however facilitate is getting the table you want, directly. Let’s say I want to get the Insects table from the image below – how do I get that?
Well if you KNOW it is the nth table in the document then you are fine – but the chances are you don’t or at best can’t be sure.
Testing each table
What you can do is cycle through all the tables in the collection and test the first cell. I have specifically created these tables in such a manner that the first cell in the table is testable. Cycling through all the tables allows me to do a simple test of the first cell and if it is Insects then I know I am in the right table.
In this example we get all tables and then once we have the Insects table I insert a row:
async function runAllTables() { await Word.run(async (context) => { const tableCollection = context.document.body.tables; // Queue a commmand to load the results. context.load(tableCollection); await context.sync() //cycle through the tbale collection and test the first cell of each table looking for insects for (var i = 0; i < tableCollection.items.length; i++) { var theTable = null; theTable = tableCollection.items[i]; var cell1 = theTable.values[0][0]; if (cell1 == "Insects") { //once found, load the table in memory and add a row context.load(theTable, ''); await context.sync(); let numRows = theTable.rowCount.toString() theTable.addRows("End", 1, [[numRows, "Lightning Bug"]]) } } }); }
As the number of tables in the document increase this gets slower and slower (understandably). There is also a limitation on the fact that you might not be able to identify the Table with a value in the first cell as easily (depends on requirements). As you can see from this example in the console.log I added the length of time to complete the addRow and it is 77ms on three tables. If I copy and past the first two tables and make a lot more of them you can see the speed gets slower (124ms) which might not seem like a lot, but in a large document with lots of large tables it can become significant to the end user.
Searching for a word in the document, and then getting the table parent
If you are able to identify a string in your table, you can search for that string and then get the parentTable. That method for finding your table is much more efficient and faster than getting all tables in a collection as per the previous method.
In this example we search for Insects, get the parentTable and then simply insert a row with a new value
async function runSearch() { await Word.run(async (context) => { const body = context.document.body const insectRangeCollection = body.search("Insects"); // Queue a commmand to load the results. context.load(insectRangeCollection); await context.sync() //get the parent table from the search result range const table1 = insectRangeCollection.getFirst().parentTable context.load(table1, ''); await context.sync() let numRows2 = table1.rowCount.toString() table1.addRows("End", 1, [[numRows2, "Butterfly"]]) }); }
As with the previous example – if I copy and paste the first two tables and make a lot more of them, you will see that this search and add row process remains approx the same speed as before.
Conclusion
While neither of these methods are ideal, if you know what is possible before you start to create your solution you can work in your options. Not having an obvious getTableById method is somewhat limiting.