Home

Table

A structured representation of a tabular block — its cells with grid positions, spans, and roles, plus a ready-made Markdown rendering. result.tables is a list of these, in document order.

The structured cells are always the source of truth, independent of table_representation — that setting only changes how a table is serialised into chunk text, not the Table object you get here.

result = docslicer.parse_document("report.pdf")
 
for table in result.tables:
    print(table.caption, "— page", table.page_number)
    print(table.markdown)

Fields

FieldTypeDescription
idstrUnique identifier for this table within the result. Referenced by chunk.table_ids and block.table_ids.
captionstr | NoneThe table's caption or title, when one was detected. None otherwise.
page_numberint1-based physical page number the table appears on.
page_labelstr | NonePrinted page label, e.g. "iv", "A-6". Differs from page_number for Roman-numeral, lettered, or custom numbering. None when no label was detected.
chunk_idstrID of the chunk this table belongs to.
bboxBBox | NoneBounding box of the table — the union of all its cell bounding boxes. Populated for PDF and for HTML rendered via Playwright; None for DOCX, PPTX, and HTML parsed without Playwright.
markdownstrThe full table rendered as Markdown — a convenience for display or embedding, always produced regardless of table_representation.
cellslist[TableCell]The structured cells. See TableCell below.

TableCell

Each entry in table.cells is a TableCell describing one cell of the grid:

FieldTypeDescription
rowint0-indexed row position in the grid.
colint0-indexed column position in the grid.
rowspanintNumber of rows this cell spans (>= 1).
colspanintNumber of columns this cell spans (>= 1).
rolestrWhat the cell is: header, row_label, value_numeric, value_text, or footnote.
textstrThe cell's text.
bboxBBox | NoneBounding box of the cell. Populated for PDF and Playwright-rendered HTML; None otherwise.

Cell-level structure is the finest granularity a table can have — every value keeps its position, its spans, and its role, with nothing flattened. That means the table is yours to render however your pipeline needs: a DataFrame via to_dataframe() (and onward to CSV or Excel), the markdown field for prompts, or your own JSON shape built straight from the cells. Parsers that emit only Markdown have already collapsed this structure — merged cells, header levels, and the numeric-vs-text distinction are gone and can't be recovered downstream. Keeping the cells means every lossy rendering is one you derive, not the only thing you're handed.


Examples

Render as Markdown

print(table.markdown)

Work with the cells as a DataFrame

to_dataframe() returns one row per cell, with the row, col, rowspan, colspan, role, text, and bbox columns:

df = table.to_dataframe()
headers = df[df["role"] == "header"]

Pull just the header cells

headers = [c for c in table.cells if c.role == "header"]

Find tables by heading or page

node = result.find_heading("Financial Statements")[0]
tables = result.tables_under(node)
 
result.tables_by_page(14)        # by physical page number
result.tables_by_page("F-3")     # by printed page label

See ParseResult for the full set of navigation methods.

Resolve a chunk's or block's tables

chunk.table_ids and block.table_ids hold Table IDs — look them up against result.tables:

tables_by_id = {t.id: t for t in result.tables}
 
for chunk in result.chunks:
    for table_id in chunk.table_ids:
        print(tables_by_id[table_id].markdown)

Methods

to_dataframe()

Return the cells as a pandas DataFrame, one row per cell.

df = table.to_dataframe()

to_dict()

Serialize the table — including its cells — to a plain dict.

d = table.to_dict()

Table.from_dict(d)

Reconstruct a Table from a dict produced by to_dict().

table = Table.from_dict(d)