Type: Composite Entity

Table object like a HTML-Table, buildup with basic DXF R12 entities.

Cells can contain Multiline-Text or DXF-BLOCKs, or you can create your own cell-type by extending the CustomCell object.

Cells can span over columns and rows.

Text cells can contain text with an arbitrary rotation angle, or letters can be stacked top-to-bottom.

BlockCells contains block references (INSERT-entity) created from a block definition (BLOCK), if the block definition contains attribute definitions (ATTDEF-entity), attribs created by Attdef.new_attrib() will be added to the block reference (ATTRIB-entity).

DXFEngine.table(insert, nrows, ncols, default_grid=True)
  • insert – insert point as 2D or 3D point
  • nrows (int) – row count
  • ncols (int) – column count
  • default_grid (bool) – if True always a solid line grid will be drawn, if False, only explicit defined borders will be drawn, default grid has a priority of 50.


Table.set_col_width(column, value)

Set width of ‘column’ to ‘value’.

  • column (int) – zero based column index
  • value (float) – new column width in drawing units
Table.set_row_height(row, value)

Set height of ‘row’ to ‘value’.

  • row (int) – zero based row index
  • value (float) – new row height in drawing units
Table.text_cell(row, col, text, span=(1, 1), style='default')

Create a new text cell at position (row, col), with ‘text’ as content, text can be a multi-line text, use '\\n' as line separator.

The cell spans over span cells and has the cell style with the name style.

Table.block_cell(row, col, blockdef, span=(1, 1), attribs={}, style='default')

Create a new block cell at position (row, col).

Content is a block reference inserted by a INSERT entity, attributes will be added if the block definition contains ATTDEF. Assignments are defined by attribs-key to attdef-tag association.

Example: attribs = {‘num’: 1} if an ATTDEF with tag==’num’ in the block definition exists, an attrib with text=str(1) will be created and added to the insert entity.

The cell spans over ‘span’ cells and has the cell style with the name ‘style’.

Table.set_cell(row, col, cell)

Insert a cell at position (row, col).

Table.get_cell(row, col)

Get cell at position (row, col).

Table.frame(row, col, width=1, height=1, style='default')

Create a Frame object which frames the cell area starting at (row, col), covering ‘width’ columns and ‘height’ rows.

Table.new_cell_style(name, **kwargs)

Create a new Style object ‘name’.

The ‘kwargs’ are the key, value pairs of of the dict Cellstyle.

Table.new_border_style(color=const.BYLAYER, status=True, priority=100, linetype=None):

Create a new border style.

  • status (bool) – True for visible, else False
  • color (int) – dxf color index
  • linetype (str) – linetype name, BYLAYER if None
  • priority (int) – drawing priority - higher values covers lower values

see also Borderstyle.


Get cell style by name.


Iterate over all visible cells.

Returns:a generator which yields all visible cells as tuples: (row , col, cell)


Just a python dict:

    # textstyle is ignored by block cells
    'textstyle': 'STANDARD',
    # text height in drawing units, ignored by block cells
    'textheight': DEFAULT_CELL_TEXT_HEIGHT,
    # line spacing in percent = <textheight>*<linespacing>, ignored by block cells
    'linespacing': DEFAULT_CELL_LINESPACING,
    # text stretch or block reference x-axis scaling factor
    'xscale': DEFAULT_CELL_XSCALE,
    # block reference y-axis scaling factor, ignored by text cells
    'yscale': DEFAULT_CELL_YSCALE,
    # dxf color index, ignored by block cells
    'textcolor': DEFAULT_CELL_TEXTCOLOR,
    # text or block rotation in degrees
    'rotation' : 0.,
    # Letters are stacked top-to-bottom, but not rotated
    'stacked': False,
    # horizontal alignment (const.LEFT, const.CENTER, const.RIGHT)
    'halign': DEFAULT_CELL_HALIGN,
    # vertical alignment (const.TOP, const.MIDDLE, const.BOTTOM)
    'valign': DEFAULT_CELL_VALIGN,
    # left and right margin in drawing units
    'hmargin': DEFAULT_CELL_HMARGIN,
    # top and bottom margin
    'vmargin': DEFAULT_CELL_VMARGIN,
    # background color, dxf color index, ignored by block cells
    'bgcolor': DEFAULT_CELL_BG_COLOR,
    # left border style
    'left': Style.get_default_border_style(),
    # top border style
    'top': Style.get_default_border_style(),
    # right border style
    'right': Style.get_default_border_style(),
    # bottom border style
    'bottom': Style.get_default_border_style(),


Just a python dict:

    # border status, True for visible, False for hidden
    # dxf color index
    # linetype name, BYLAYER if None
    # drawing priority, higher values cover lower values


import dxfwrite
from dxfwrite import DXFEngine as dxf

def get_mat_symbol():
    p1 = 0.5
    p2 = 0.25
    points = [(p1, p2), (p2, p1), (-p2, p1), (-p1, p2), (-p1, -p2),
              (-p2, -p1), (p2, -p1), (p1, -p2)]
    polygon = dxf.polyline(points, color=2)
    attdef = dxf.attdef(text='0', tag='num', height=0.7, color=1,
                        halign=dxfwrite.CENTER, valign=dxfwrite.MIDDLE
    symbolblock = dxf.block('matsymbol')
    return symbolblock

name = 'table.dxf'
dwg = dxf.drawing(name) # create a drawing
table = dxf.table(insert=(0, 0), nrows=20, ncols=10)
# create a new styles
ctext = table.new_cell_style('ctext', textcolor=7, textheight=0.5,
# modify border settings
border = table.new_border_style(color=6, linetype='DOT', priority=51)
ctext.set_border_style(border, right=False)

table.new_cell_style('vtext', textcolor=3, textheight=0.3,
                     rotation=90, # vertical written
# set colum width, first column has index 0
table.set_col_width(1, 7)

#set row height, first row has index 0
table.set_row_height(1, 7)

# create a text cell with the default style
cell1 = table.text_cell(0, 0, 'Zeile1\nZeile2', style='ctext')

# cell spans over 2 rows and 2 cols
cell1.span=(2, 2)

cell2 = table.text_cell(4, 0, 'VERTICAL\nTEXT', style='vtext', span=(4, 1))

# create frames
table.frame(0, 0, 10, 2, 'framestyle')

# because style is defined by a namestring
# style can be defined later
hborder = table.new_border_style(color=4)
vborder = table.new_border_style(color=17)
table.new_cell_style('framestyle', left=hborder, right=hborder,
                     top=vborder, bottom=vborder)
mat_symbol = get_mat_symbol()

                     xscale=0.6, yscale=0.6)

# add table as anonymous block
# dxf creation is only done on save, so all additional table inserts
# which will be done later, also appear in the anonymous block.

dwg.add_anonymous_block(table, insert=(40, 20))

# if you want different tables, you have to deepcopy the table
newtable = deepcopy(table)
newtable.new_cell_style('57deg', textcolor=2, textheight=0.5,
                     rotation=57, # write
newtable.text_cell(6, 3, "line one\nline two\nand line three",
                   span=(3,3), style='57deg')
dwg.add_anonymous_block(newtable, basepoint=(0, 0), insert=(80, 20))

# a stacked text: Letters are stacked top-to-bottom, but not rotated
table.new_cell_style('stacked', textcolor=6, textheight=0.25,
table.text_cell(6, 3, "STACKED FIELD", span=(7, 1), style='stacked')

for pos in [3, 4, 5, 6]:
    blockcell = table.block_cell(pos, 1, mat_symbol,
                                attribs={'num': pos},

print("drawing '%s' created.\n" % name)