Inconsistent behavior with UpdatePageLayout() when using tables with different column counts

My bad on the ConsoleApp btw., it was still configured to be a .NET Framework 4.8 app (in the TestConsole.zip).

Nonetheless, with my original code, all of the tests with a .NET 8 console app yield the same results for me: One part looks broken.

Without the firstTable.AutoFit(AutoFitBehavior.FixedColumnWidths); all preliminary test cases look good. Thanks so much for the brilliant catch!

I guess, we’ll migrate production code to this setup then, pending all other test cases.

Thanks again so much for your help!

2 Likes

Just if someone is curious: What we actually ended up having to do, was using

  • a single table,
  • more cells per row and then merging them and
  • fixed cell widths (not PreferredWidths).

All other avenues either didn’t display all cells with equivalent widths or had some rows stick out on the right most edge for no apparent reason (in some cases).

Something similar to this:

// data
List<List<string>> rows = null; // set data

// For equal spacing, we need to insert LCM(cell_count_of_all_rows) cells into each row and merge them appropriately:
var cellsPerRow = LeastCommonMultiple(rows.Select(cells => cells.Count).Distinct());

var totalWidth = builder.PageSetup.PageWidth - builder.PageSetup.LeftMargin - builder.PageSetup.RightMargin;

var table = builder.StartTable();
foreach (var cells in rows) // "cells" are the cells to display for the current row
{
    var cellWidthPts = totalWidth / cellsPerRow;
    var cellsPerCell = cellsPerRow / cells.Count; // How many cells need to be merged to one cell for the current row. (Because "cells.Count" is part of the LCM computation, this division does not have a remainder!)

    foreach (var cellValue in cells)
    {
        var cell = builder.InsertCell();
        cell.CellFormat.HorizontalMerge = CellMerge.None;
        cell.CellFormat.Width = cellWidthPts;

		builder.Write(cellValue);
		
		// Merge cells, s.t. the cells will use an equal width in the table
		if (cellsPerCell > 1)
		{
			cell.CellFormat.HorizontalMerge = CellMerge.First;

			// idx 0 equals "cell"
			for (var i = 1; i < cellsPerCell; i++)
			{
				var dummyCell = builder.InsertCell();
				dummyCell.CellFormat.Width = cellWidthPts;
				dummyCell.CellFormat.HorizontalMerge = CellMerge.Previous;
			}
		}
    }
    builder.EndRow();
}
builder.EndTable();
table.AutoFit(AutoFitBehavior.FixedColumnWidths);


// == Helper functions ==

private static int GreatestCommonDivisor(int n1, int n2)
{
    if (n2 == 0)
        return n1;
    else
        return GreatestCommonDivisor(n2, n1 % n2);
}

private static int LeastCommonMultiple(IEnumerable<int> numbers)
{
    return numbers.Aggregate((a, b) => a * b / GreatestCommonDivisor(a, b));
}
2 Likes

Interesting that the behavior change lined up exactly with the 25.01 update. Did you ever try locking the table’s AutoFit settings explicitly to Fixed Column Widths before calling UpdatePageLayout()? I’ve seen that prevent Aspose from recalculating widths in ways you don’t expect. And also, thanks for posting the final solution

Yeah, we did. But because we’ve only been setting the PreferredWidth with our previous solution, and that apparently doesn’t set the Width property instantaneously ( → it only does set Width during rendering, i.e. UpdatePageLayout() → which since the update breaks in our use case…) and thus when calling table.AutoFit(AutoFitBehavior.FixedColumnWidths);, none of the cell Widths are set and subsequently all cells assume the min. required width to fit their respective contents. We explicitly want the table to use 100% of the page width though to achieve a consistent look and feel regardless of cell contents.

(Meaning that both these tables

|a    |b    |
| --- | --- |
|short|short|

and

|a          |b          |
| --------- | --------- |
|much longer|much longer|

should use the same width per column and total width; which, due to the text length in the second row, they clearly don’t in this example…)

A final idea, we were having is to format the entire thing using even more tables. Basically making a table with one column and the required number of rows and then in each row/cell insert an entirely new table which contains the actual PreferredWidth in % and then using AutoFitBehaviour.AutoFitToWindow throughout. This obviously might misalign other stuff, e.g. like

||a somewhat long text|b ||
|  ---------------------  |
||lorem ipsum|lorem ipsum||

but we haven’t been required to mess with that, because we’ve managed to achieve the posted workaround first. And of course formatting this to look pretty would have been an other nightmare…

1 Like

The issues you have found earlier (filed as WORDSNET-28535) have been fixed in this Aspose.Words for .NET 25.10 update also available on NuGet.