Skip to content

Add TableEntity DXF round-trip (cells, alignment, merges, flow direction)#1085

Open
ilCosmico wants to merge 3 commits into
DomCR:masterfrom
ilCosmico:dxf-table-entity-write
Open

Add TableEntity DXF round-trip (cells, alignment, merges, flow direction)#1085
ilCosmico wants to merge 3 commits into
DomCR:masterfrom
ilCosmico:dxf-table-entity-write

Conversation

@ilCosmico

@ilCosmico ilCosmico commented May 20, 2026

Copy link
Copy Markdown
Contributor

Until now the DXF writer only emitted the block reference for a TableEntity. This change writes the AcDbTable subclass too, with rows, columns, per-cell data, margins, flow direction, alignment (group 170 plus the matching cell flag at group 91), and merge ranges (per-cell via BorderWidth/BorderHeight and MergedValue).

On the reader side, per-cell alignment is now captured and the table-level MergedCellRanges is rebuilt by scanning the grid, so a DXF table comes back with the same merge layout as one read from DWG.

Known limitation: with no proxy graphic preview attached, AutoCAD and DWG TrueView draw the table twice (once from the anonymous block, once from the cell stream). Readers that consume the cell stream directly show a single, correct table.

Closes #995

@ilCosmico ilCosmico changed the title Add minimal TableEntity write support in DxfWriter Add TableEntity DXF round-trip (cells, alignment, merges, flow direction) May 22, 2026
@ilCosmico
ilCosmico force-pushed the dxf-table-entity-write branch from ca91691 to 84cd0ff Compare May 22, 2026 15:10
@ilCosmico

Copy link
Copy Markdown
Contributor Author

Hi @DomCR, I just saw your March comment on #995 about wanting to refactor CadTable before tackling the writers. This PR sits on top of the existing TableEntity API and does not touch CadTable internals, just the DXF reader and writer code paths, so it should not get in the way of that refactor. We had a downstream need for the round trip sooner, which is why I went ahead. If your refactor lands first and the shape changes, I can rebase, or close this PR if you would rather start fresh. Whatever works best for you.

@ilCosmico
ilCosmico force-pushed the dxf-table-entity-write branch from 84cd0ff to 67eb93f Compare June 15, 2026 11:58
DxfWriter previously skipped TableEntity with a "not implemented"
notification, so saving a CadDocument containing an ACAD_TABLE produced
a DXF with an empty modelspace.

Emit the AcDbBlockReference (Insert) subclass first so the viewer can
instantiate the anonymous BlockRecord that holds the table's rendered
geometry, then the AcDbTable subclass with the table-level data
(version, horizontal direction, value flag, row/column counts and
sizes, style and block references) and a minimal per-cell payload
(type, edge/merge flags, autofit, border counts, optional text content
and rotation).

Advanced cell features (block-cell payloads, multi-run formatted
content, custom data, borders, format runs, merged ranges) are not yet
round-tripped and will emit a Warning notification so consumers know
some data is lost.
When the writer emits both a populated AcDbBlockReference (pointing at
the anonymous BlockRecord that holds the exploded table geometry) and a
fully populated AcDbTable subclass with rows, columns and per-cell
content, AutoCAD renders the table twice: once from the BlockReference
and once from the AcDbTable cells, with the two renderings offset
because AutoCAD's AcDbTable renderer does not pick up the Insert's
transform.

Emit only the AcDbTable header (version, horizontal direction, value
flag, style and block handles) with row and column counts set to 0.
AutoCAD then has no cell data to render from and falls back to drawing
the BlockReference, which gives a single correctly positioned table.
Cell metadata is not round-tripped through DXF in this minimal pass; a
follow-up can add it together with the proxy graphic preview that
AutoCAD-produced files emit (DXF group codes 160/310) so the AcDbTable
renderer is shadowed by the proxy graphic instead of being suppressed.
The DXF writer for TableEntity was emitting cell rows and cell contents but
dropping the per-cell alignment (group code 170) and the cell flag bits that
mark which overrides are active (group code 91). A strict reader fell back
to the table style defaults, so the original alignment set on each cell was
lost on round-trip.

Emit the cell flag with the baseline state value AutoCAD-produced files use
(262192) and OR in 0x01 plus a 170 record when the cell carries an explicit
alignment override. On the reader side, capture group 170 onto the cell
StyleOverride so callers see the alignment through the regular API.

The DXF cell stream also encodes merged cells per-cell only: the top-left
anchor carries the column and row span in BorderWidth/BorderHeight (175/176)
and the remaining cells carry MergedValue=1 (173). The table-level
MergedCellRanges collection that consumers actually iterate was never
populated. Rebuild it in CadTableEntityTemplate.build() by scanning the grid
after all cells are parsed, so DXF and DWG paths expose the same shape.
@ilCosmico
ilCosmico force-pushed the dxf-table-entity-write branch from 67eb93f to 6ff541a Compare June 17, 2026 09:18
@ilCosmico

Copy link
Copy Markdown
Contributor Author

Hi @DomCR, coming back to this now that the CadTable refactor has landed. The PR still merges cleanly on top of the new API, and it covers the TableEntity DXF write path that is currently a not-implemented notify on master.

I saw you have already started on the writers with the TableStyle DXF support, so I did not want to just push ahead and step on that. If it helps, I am glad to lend a hand finishing the table writers starting from this PR, rebasing or reshaping it to match your refactor, and taking the DWG side too if you want it. Totally your call on scope and how to split things. And if you would rather keep this part yourself, no problem at all, just let me know and I will step back.

Either way, thanks for the refactor, it made this much cleaner to build on.

@DomCR

DomCR commented Jul 14, 2026

Copy link
Copy Markdown
Owner

Hi @ilCosmico,

Before implementing the support for the tables in dxf I want to solve the problem with the TableContent class, which is obsolete for the newer versions of dwg but is used in older dwg and dxf.

I still need to refactor the dxf reader to fix the mess that the TableContent created and see how can it be created if the user needs to write it.

Having said that, if this implementation works with existing files and it rewrites a dxf file with a table, I can create a transfer branch and check it once I refactor the TableContent part.

Let me know what you prefer to do.

@ilCosmico

ilCosmico commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

Hi @DomCR, that plan works for me. The transfer branch is fine, and I will rebase or adapt the PR after the TableContent refactor lands, whatever shape it takes.

On your question: yes, the implementation round-trips existing files. A dxf with a table reads and rewrites with cells, per-cell alignment, merge ranges and flow direction preserved, and we validated it downstream with our product tests against files from real drawings. One known limitation, noted here for transparency: the writer does not emit the proxy graphic preview blob, so viewers regenerate the table from the data instead of the cached preview. Content and layout are correct, only the hover preview behaves differently, as in the screenshot below (the rotated overlay is the regenerated preview during hover).

A_TrueView

Take your time with the refactor, and thanks for keeping this on the table 😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DxfTable in Dxf and Dwg writers

2 participants