Skip to content

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

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

ilCosmico wants to merge 9 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 2 times, most recently 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 😅

@ilCosmico
ilCosmico force-pushed the dxf-table-entity-write branch from 6ff541a to e0343ab Compare September 23, 2026 13:09
@ilCosmico

Copy link
Copy Markdown
Contributor Author

Rebased on current master, plus two commits. Cell values are now written for every value type found in the DXF that AutoCAD saved from sample_AC1032.dwg (long, double, string, date and point), with their flags, units and format taken from the model. Before, only text values were written, so numbers and dates were lost. FIELD values go through the same code and now read back as well. I also reworded a few comments.

On sample_AC1032.dwg all 19 cells come back with their type and value, and DWG TrueView shows them with their formats. To open that file in TrueView I had to work around the hatch issue reported in #1253, which is unrelated to tables.

if (!value.IsEmpty)
{
case CadValueType.Unknown:
this._writer.Write(91, 0);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Has this case been tested? the removal of the code 91 caused some issues on my end.

@DomCR

DomCR commented Sep 29, 2026

Copy link
Copy Markdown
Owner

Hi @ilCosmico,

To push this forward, could we separate the changes made in CadValue from the TableEntity?

The CadValue seem to be small and add functionality, for the table I need to test with all the versions which is quite difficult, TableContent is not yet implemented and the older versions needed to create a table that it doesn't result in a corrupted file.

@DomCR

DomCR commented Sep 29, 2026

Copy link
Copy Markdown
Owner

Before starting the task, which has more priority for you, the TableEntity or the ACIS data?

These 2 task are quite big on the library and they will take time.

@ilCosmico

Copy link
Copy Markdown
Contributor Author

Hi @DomCR, the ACIS data is the priority for me, so please start with that one. I won't be able to look at the PRs today, but I'll be back on them from tomorrow.

writeCadValue now writes the unit type, the format and the formatted
value, skips the data of empty and unknown values and writes dates as
the 16 byte block AutoCAD uses. The reader decodes that block back into
the date.
An unknown value without the empty flag, as read from a pre R2007
DWG, carries its data in 91 like the DWG writer does, otherwise it
is lost when the DXF is read back.
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.
Cells now write their CELL_VALUE through the shared writeCadValue
instead of a text only block, for the value types found in AutoCAD
files: unknown, long, double, string, date and point.
@ilCosmico

Copy link
Copy Markdown
Contributor Author

Split as you asked: the CadValue part is now #1263, and this PR is rebased on top of it, so it only touches the TableEntity files. No rush on this one, the ACIS work comes first for us.

This branch has not been deployed

No deployments
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