# Tables

How edits and getOoxml behave in a seeded document's tables, at a cell's edge and in its last cell.

The simulator serves no `Table` object, but a document you seed can hold tables. A range inside a table cell returns that cell's own paragraph in its `paragraphs`, the one `body.paragraphs` lists. So an add-in can map a search hit in a table to body paragraph indices:

```js
await office.seedDocx('fixtures/fee-schedule.docx');
await Word.run(async context => {
  const hit = context.document.body.search('Intake interview').getFirst();
  hit.paragraphs.load('items/text');
  await context.sync();
  // hit.paragraphs.items.map(p => p.text) -> ["Intake interview"]
});
```

### `getOoxml` of a range that ends inside a table cell takes that paragraph out of the table

The package holds, in order:

1. the rows the range reaches, the row it starts in from the cell it starts in;
2. what it covers of the row it ends in, as a table of its own;
3. the paragraph it ends in, as a body paragraph after the tables.

A range from before a table to the first cell of its last row writes the rows above as the table, and that cell's text after it.

### An edit can't cross a table cell's edge

`delete()` or `insertText(…, 'Replace')` through a range that crosses a cell's edge throws `GeneralException`, tracked or not, and leaves the document as it was. That holds for a range from one cell into another, and for one into or out of a table.

The exception is a range that runs from the table's first cell, or from before the table, into its last cell or past the table. Such an edit goes through:

| Edit | Result |
|---|---|
| untracked `delete()` that holds the table's start or its end | takes every cell it holds whole and the rows it empties; the table goes with its last cell |
| untracked `delete()` from inside the first cell into the last | takes only text |
| untracked `Replace` | deletes the same way, then writes its text where the range began |
| untracked `Replace` over exactly one table, from its first cell's start through its last cell's end | writes its text in the first cell and empties the rest |
| tracked | marks each cell's text deleted; every cell stays |

A range from a cell's text to the start of the next cell ends at the cell's end, which no edit takes.

### Deleting a cell's only paragraph can take its column

In a one-row table, or for a cell merged down every row, an untracked `delete()` can remove the cell and its column. It does for a `delete()` of the cell's only paragraph, or of a range holding the whole cell, its last paragraph mark included. A content control around the cell goes too, as does a block control that was all the cell held. The table goes with its last column.

In a table of more rows, the paragraph empties and the cell stays. Tracked, the text is marked deleted and the cell stays.

### Table widths

The simulator keeps the column widths the document wrote, and `getOoxml` writes those. Once a column goes, it writes table and cell widths summed from them.

**Differs from Word for the web:** Word lays out a table of automatic width from its text when the document opens. Its `getOoxml` then writes column widths the document never held, and once a column goes, table and cell widths summed from that layout.

---

Source: https://www.rystic.ai/docs/simulators/word/features/tables · Markdown: https://www.rystic.ai/docs/simulators/word/features/tables.md
