Hello,
on the DOM level every table line (header, data, group header/footer, footer) inherits an Anchor property from TableLineBase TableLineBase.Anchor.
That Anchor object (PropertyAnchor) defines:
- Which line you are anchored to (“reference line” – in the Designer this is the line you pick in the anchoring dialog).
- Where relative to that line you want to be drawn: via ToTop →
- True = print above the reference line’s start
- False = print below the reference line’s end
PropertyAnchor, PropertyAnchor_members.
In other words:
-
The reference line is laid out first (including all wrapped/multi‑line content → final height is known).
-
The anchored line’s Y‑position is then computed from the final position of the reference, not from the original design-time position.
The improved positioning behavior is controlled by the option LlOption.ImprovedTableLineAnchoring LlOption.
With this option, non‑anchored lines are placed underneath the “tallest” line above them; anchored lines explicitly tie themselves to another line’s top or bottom.
Although the Designer uses a more visual dialog, internally it boils down to:
-
Anchor “Top” (ToTop = True):
Start of your line = start of the reference line (same Y).
This is typically used to “stack something above” or to share the same starting position.
-
Anchor “Bottom” (ToTop = False):
Start of your line = end of the reference line (reference Y + reference height).
This is the way to “follow” whatever height the reference line finally gets (e.g. due to multi‑line text).
The important consequence:
Anchoring to bottom explicitly tells LL: “Place me exactly where the reference line ends, regardless of how tall it becomes at runtime.”
As we understood - you described:
1. Row 1: Col1 empty, Col2 = field, no anchoring
2. Row 2: Col1 empty, Col2 = field, no anchoring
3. Row 3: Col1 = multi-line text (spanning visually both rows), no Col2, anchored to row 1, top
…is that correct?
With row 2 anchored to the bottom of row 1, row 2 will always start exactly where row 1 ends after considering all anchored content (like your multi-line text).
Therefore, there will be no gap; row 2 “follows” the actual height of row 1.
That’s why this setup fixes the gap in the “spanning multi-line text” scenario.
In the first setup, row 3 is anchored to row 1, but row 2 is not anchored at all.
With ImprovedTableLineAnchoring active, the engine behaves roughly like this LlOption:
1. Lay out row 1 and its anchored contents (your multi-line row 3).
2. Determine the maximum height consumed by this block.
3. Place the next non‑anchored line (row 2) below that block.
Visually, this turns your “row 3” into something that vertically extends row 1, and row 2 is moved down accordingly → the “gap” you see between what you think of as row 1 and row 2.
That’s technically correct behavior given your anchoring choice; it just doesn’t match the mental model “row 3 is a separate row that should overlap rows 1+2”.
The line-anchoring logic is affected by LlOption.ImprovedTableLineAnchoring LlOption.
There is a note in the docs that if you combine this with negative top margins in lines, you may need to disable the improved anchoring in order to get the expected result.
This can change placement characteristics subtly between LL versions.
Anchored lines / combined rows are not supported by all export formats in exactly the same visual way; some exporters do not emulate the exact internal table layout logic 1:1 (mentioned in the anchoring docs) PropertyAnchor.
Summarized:
- A line anchored to the top of another line shares its starting Y-position with that line.
- A line anchored to the bottom of another line starts exactly where the reference line ends after all its content (including multi-line text and anchored objects) has been laid out.
- With ImprovedTableLineAnchoring active, non-anchored lines underneath are positioned below the full height consumed by anchored content above.
You have a very valid point about documentation clarity.
The underlying mechanisms are only described via:
None of these currently walk through a concrete “multi-line text spanning rows” example, which would make this behavior much more intuitive.
Your request for more complex examples and a conceptual explanation is something we can definitely forward internally.