How the document hub reads and edits them. References are to ECMA-376 Part 1 (5th edition) unless noted. Items marked to check against Word are what the hub does today where the text leaves the answer open.
Tables (§17.4)
- Rows and cells are enumerated through content-control and custom-XML wrappers, so nothing is hidden. A cell is a block
container (
TableCell);w:tcPris not a block. - Logical grid (
Table.Logical()): rows × grid columns. A cell starts at the running column (afterw:gridBefore) and coversw:gridSpancolumns (below 1 or above 16384 reads as 1). The grid width is the larger ofw:tblGridand the widest row, so rows wider than the grid widen it (docx.table-grid-mismatch). - Vertical merge (§17.4.85):
w:vMergewithw:val="restart"starts a region; withcontinueor no value it continues the cell directly above in the same starting grid column. A continuation under a cell that is not part of a merge still merges upward: the cell above becomes the region's start (observed in Word 365, 16.0.20527: three rows ofvMergecontinuations under an unmerged first cell read as one cell). The file is malformed, so the repair is reported asdocx.table-merge-orphan. A continuation in the first row, or with no cell starting in its column above, is a plain cell. - Horizontal merge: current files use
w:gridSpan. The legacyw:hMerge(restart/continue) widens the cell to its left; an orphan continuation is a plain cell. - A region is one
LogicalCellanchored at its top-left cell; the swallowed physical cells are inCovered. Empty grid positions (gridBefore,gridAfter, short rows) read as null. - Table styles:
Table.Lookreadsw:tblLook(attributes or the hex mask).StyleSheet.GetTableRegionsnames the conditional regions of a logical cell in application order (§17.7.6); the header row is not banded and banding counts from the row after it. A merged cell counts by its top-left position for banding.firstColandlastColfollow the row's first and last physical cell, so a row that starts aftergridBeforestill has its first cell in the first column (observed in Word 365, 16.0.20527). Band regions still count by grid position; Word's behaviour for bands in rows with merged or gapped cells has not been verified.ResolveTableCelllayers style table and cell properties, regions, the table's own properties and the cell's own; borders and margins are flattened per side (tblBorders/top,tcBorders/left,tblCellMar/start).w:tblLookattributes win over the hex mask when both are present (observed in Word 365, 16.0.20527).
Edits
Edits change only the table's markup; properties, unknown markup and untouched rows stay byte-identical, and only the part that holds the table is rewritten.
InsertRow(index)copies the row above (the first row at the top), clears the cells to one empty paragraph that keeps the first paragraph's properties, removesw:ins/w:del/w:trPrChangefrom the copy and the paragraph ids. A new cell continues a vertical merge exactly when the cells above and below belong to one region.DeleteRow(index)makes the next row's cell the start of a region that the removed row started. The only row cannot be deleted.InsertColumn(column)widens cells that span the insertion point, adds a plain empty cell elsewhere (copying the neighbour's width) and aw:gridColof the left neighbour's width. InsidegridBefore/gridAfterthe counts change instead.DeleteColumn(column)narrows spanning cells, removes cells that cover only that column, and removes thew:gridCol. The only column cannot be deleted.SetCellTextkeeps the first paragraph's properties and its first run's formatting and removes every other block of the cell.
Sections (§17.6)
- A section ends at the paragraph whose
w:pPrholds aw:sectPr(top level or in a block content control); the last section'sw:sectPrcloses the body. A body without one has one section of defaults. - Defaults when attributes are absent: Letter portrait (12240 × 15840), margins 1440, header and footer distance 720, gutter 0, one
column with 720 space,
w:typenext page. An unusablew:pgSzreads as Letter (docx.section-page-size-invalid). - Columns: for unequal layouts the
w:collist defines the count (docx.section-columns-mismatchwhenw:numdiffers). - Page numbering, line numbering, document grid,
w:titlePg,w:bidi,w:vAlign,w:textDirection,w:noEndnoteare read as data. Setters exist for page size, margins, break type, title page, page numbering and equal columns; they respect the schema sequence and create the body'sw:sectPrwhen missing.
Headers and footers (§17.10.5)
- A reference is
w:headerReference/w:footerReferencewithw:typedefault,firstorevenand anr:idof the main part. A reference that does not lead to a part is ignored (docx.header-missing); a second of the same kind and type is ignored (docx.header-reference-duplicate). - Linked to previous: a section without its own reference of a kind and type uses the nearest earlier section's. The first
section without one prints blank. There is no fallback between types: a missing
firstorevenstory is blank (or inherited for that type), never the default story. - Page choice (
Section.ForPage): withw:titlePg, the first page of the section usesfirst; else withw:evenAndOddHeaders(settings part), an even printed page number (after anypgNumTyperestart, not the physical page) useseven; elsedefault.Section.FirstPrintedPageNumbergives the number a section's first page prints. - Blank pages (
Section.RequiresBlankPageBefore): observed in Word 365 (16.0.20527), withw:evenAndOddHeaderson a new-page section whose first printed number has the other parity from the physical page it would start on starts one page later, after an empty page (restart at 1 after three pages: starts on physical page 5; restart at 2 after two pages: physical page 4). Layout inserts that page; the hub only answers the question. - To check against Word: a section with
w:titlePgand nofirstreference of its own, after a section that has one, inherits it (the hub), while LibreOffice prints the default header on that page. Section.AddOwncreates/word/headerN.xml(or footer) with one empty paragraph, the relationship and the reference.Document.EvenAndOddHeaderswritesw:evenAndOddHeadersinto settings, creating the part when needed.