Doclingdocling 2.127.0 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
26 small wins to finish your pathNext lesson

A table you can calculate with

Lesson 2 printed a table as Markdown, which is fine to read and useless to add up. The table piece itself is a grid, and a grid goes straight into pandas.

Example
from docling.document_converter import DocumentConverter

document = DocumentConverter().convert("refunds.html").document
table = document.tables[0]
print(table.self_ref, table.label)
print(table.data.num_rows, "rows,", table.data.num_cols, "columns")

Three rows and two columns: the header row is a row. That is worth remembering when you slice one.

Into pandas

Example
frame = table.export_to_dataframe()
print(frame.to_string())

The header row became the column names and the two data rows became rows. Docling worked out which row was the header from the <th> cells; for a PDF the table model decides it.

Everything is a string

The numbers in that frame are not numbers.

Example
print(frame["Working days"].tolist())
print(frame["Working days"].sum())

Adding them glued them together instead. Docling extracts text and does not guess types, which is the right call on documents where a column holds 5, n/a and about 8. Convert the column yourself when you need arithmetic.

Example
days = frame["Working days"].astype(int)
print(days.sum(), "days in total")

The cells underneath

The frame is built from a grid of cells, and each cell knows more than its text.

Example
cell = table.data.grid[0][0]
print(repr(cell.text), "| header:", cell.column_header)
print("spans", cell.row_span, "rows and", cell.col_span, "columns")

Spans are why the grid exists. A cell covering two columns appears once with a span of two, and the positions it covers are kept alongside it. Lesson 10 shows what happens to that information when the table is written out as Markdown.

A CSV file is a document with one table in it. So convert("orders.csv").document.tables[0].export_to_dataframe() reads a spreadsheet through the same door as a table found inside a PDF.
Try it yourself
  • Do exactly that with orders.csv and print the frame.
  • Print table.data.grid[1][0].column_header and compare it with the header cell.
  • Add a row to refunds.html and check num_rows again.

Slow is fine. Stopping is the only problem.