@M.Heinz The issue occurs because the your code relies on a trick that merges consecutive table into a single table, and the trick happens to produce an acceptable result in some scenarios, but not others. You should modify your code.
The code actually creates not one but two consecutive tables. There is MS Word behavior that merges such tables into a single table. Aspose.Words tries to imitate that behavior.
The logic that merges the tables relies on known table column widths. The problematic tables are auto-fit tables, and column widths are normally computed when building document layout (as actual column widths depend on the content metrics not known at the document model level). Here lies the problem:
When the document is saved to docx without updating document layout first, document validation logic sees that no column widths are computed by layout. The widths are needed to produce a valid docx. So validation codes employs a simplified version of table layout that does not work very well in general case, but produces some column widths that are better than none. The logic is applied to each table independently, before the tables are merged. As the tables are very simple, the computed widths are enough to produce the expected result when the tables are combined and saved to .docx.
If document layout is built first, validation code does not try to compute table column widths independently. The tables are just merged using the default cell width for all cells, producing a jagged table where the cell in row 1 spans only the first column. As the cell has preferred width 100%, the column occupies most of the available space.
The table that layout operates on is equivalent to a table generated by the following code. Basically it is your code but instead of two consecutive tables it generates two rows in a single table. Otherwise, the code is the same:
// First row with 100% width
Table table = builder.StartTable();
Cell cell = builder.InsertCell();
cell.CellFormat.PreferredWidth = PreferredWidth.FromPercent(100);
builder.Write("row 1 - single cell");
builder.EndRow();
// Last row with 2 cells 50% width each
// table = builder.StartTable();
cell = builder.InsertCell();
cell.CellFormat.PreferredWidth = PreferredWidth.FromPercent(50);
builder.Write("row 2 - cell 1");
cell = builder.InsertCell();
cell.CellFormat.PreferredWidth = PreferredWidth.FromPercent(50);
builder.Write("row 2 - cell 2");
builder.EndTable();
Using this code with your tests will consistently generate a jagged table, both with or without layout update, as the code does not employ “consecutive table merge trick”.
It sounds complex, because it actually is complex.
In order to get the desired result, the code should indicate that the cell in row 1 spans 2 columns. This can be done by adding a merged cell. The below code will consistently generate the desired table for all your tests, as it does not rely on “consecutive table merge trick”:
// First row with 100% width
Table table = builder.StartTable();
Cell cell = builder.InsertCell();
cell.CellFormat.PreferredWidth = PreferredWidth.FromPercent(100);
builder.Write("row 1 : 2 merged cells");
cell.CellFormat.HorizontalMerge = CellMerge.First;
// Add a merged cell to maintain the regular table structure.
cell = builder.InsertCell();
cell.CellFormat.HorizontalMerge = CellMerge.Previous;
builder.EndRow();
// Last row with 2 cells 50% width each
cell = builder.InsertCell();
cell.CellFormat.PreferredWidth = PreferredWidth.FromPercent(50);
builder.Write("row 2 - cell 1");
cell = builder.InsertCell();
cell.CellFormat.PreferredWidth = PreferredWidth.FromPercent(50);
builder.Write("row 2 - cell 2");
builder.EndTable();