Extract PDF Tables with Docling: Check CSV Columns and Merged Cells

Export structural JSON, Markdown and per-table CSV from a two-page quotation sample. Includes a no-overwrite Python script, an AI comparison prompt and checks for columns, totals, units and partial failures.

A PDF has two price columns. After extraction, the grand total still matches, but unit prices have landed in the quantity column. Asking AI to polish the CSV can make the mistake look more official. With Docling, build a review package that can be traced back to the source pages, rather than feeding extraction straight into a product or accounting system.

This Windows exercise processes one two-page PDF and exports Markdown, structural JSON and separate CSV tables. It suits operations staff handling quotations or product catalogs, and developers preparing knowledge-base data. We checked the documented interfaces and ran 14 in-memory stub checks on our script. We did not install Docling, run OCR or convert a real PDF; these checks establish no recognition-accuracy result.

Make a sample that exposes shifted columns

In your own document editor, create a non-sensitive two-page sample and export it as sample.pdf. On page one, use columns SKU, Item, Quantity, Unit price and Amount: AX001, Cup, 3, 19.90, 59.70; AX002, Plate, 2, 45.00, 90.00. The total is 149.70. On page two write “Currency CNY; tax included; preserve identifiers.” These are deliberately specified reference values, not results extracted by this site.

Add a merged title, “Sample quotation,” above the table to expose export changes around spanning cells. Keep the original and page numbers. Do not practice on the only copy of a document or an unauthorized client quotation. Currency and tax notes matter even when outside the table.

Docling provides detected document structure and per-table exports rather than a chatbot's guess. Open-source local processing has no vendor page-credit charge, but compute, storage and model downloads still cost resources, and model licenses need separate checks. For an occasional page, careful manual copying may be simpler.

Use an isolated Windows environment

Prepare a compatible Python version, 3.10 or later, and open PowerShell in a new exercise folder. We pin Docling 2.145.0 to avoid future default releases changing the interface. This does not guarantee installation on every Python, GPU and driver combination; check the official installation guidance for your environment.

python -m venv .venv
& .\.venv\Scripts\python.exe -m pip install "docling==2.145.0" pandas

Calling the environment's interpreter directly avoids changing PowerShell execution policy or global dependencies. If installation fails, record the Python version and full error instead of following AI advice to reinstall system packages as administrator. Follow workplace software policies.

Models may download on first execution: local processing is not an assurance of offline first startup. Prepare dependencies and weights using the offline guidance for isolated networks. This exercise does not enable remote services or third-party plugins, or require a cloud API key. Reassess data destinations if adding remote models, plugins or URL inputs.

Export three review formats without overwriting a directory

Save this as export_review.py beside sample.pdf. It processes pages 1–2, raises an error if no tables are detected, and refuses an existing output directory. It performs initial extraction, not business-field interpretation.

import json
from pathlib import Path
from docling.document_converter import DocumentConverter

def export_review(source=Path("sample.pdf"), out=Path("export-review")):
    if not source.is_file() or source.suffix.lower() != ".pdf":
        raise ValueError("Provide a local sample.pdf")
    if out.exists():
        raise FileExistsError("Output already exists; choose a new directory")
    result = DocumentConverter().convert(source, page_range=(1, 2))
    doc = result.document
    if not doc.tables:
        raise RuntimeError("No tables detected; inspect the source pages")
    out.mkdir()
    (out / "document.json").write_text(
        json.dumps(doc.export_to_dict(), ensure_ascii=False, indent=2),
        encoding="utf-8",
    )
    (out / "preview.md").write_text(
        doc.export_to_markdown(), encoding="utf-8"
    )
    for number, table in enumerate(doc.tables, start=1):
        table.export_to_dataframe(doc=doc).to_csv(
            out / f"table-{number:02d}.csv",
            index=False,
            encoding="utf-8-sig",
        )
    print(f"Exported {len(doc.tables)} detected tables. Review required.")

if __name__ == "__main__":
    export_review()

Run & .\.venv\Scripts\python.exe .\export_review.py in that folder. On success, export-review should contain preview.md, document.json and numbered CSV files. Numbers follow detection order, not PDF page numbers or business table names. Detected table counts may differ from visual expectations; the script promises neither exactly one table nor automatic cross-page merging.

The 14 checks cover syntax, control flow, filenames, export options and refusal paths using in-memory stubs. Actual imports, model downloads, detection and conversion still require validation in your environment. “Exported” means the export flow finished, not that the data passed acceptance.

Investigate empty Markdown cells against structure and source pages

Markdown tables cannot represent merged cells. Docling's serialization guidance explains that row and column spans are flattened, with covered positions potentially rendered empty. JSON or HTML is better for inspecting detected spans. An empty cell is not necessarily missed recognition, nor permission to fill it from the preceding row.

Compare AX001 and AX002 with the original PDF: item, quantity, unit price, amount, currency and tax note. Check 3×19.90=59.70, 2×45.00=90.00 and total149.70. A matching total alone cannot establish correct columns: shifted columns, duplicate rows and omissions can occasionally cancel out.

The JSON preserves what Docling detected, not guaranteed source truth. OCR may confuse O with 0 or different dash characters, while spreadsheet software may later alter leading zeros. UTF-8 BOM CSV encoding helps common software read Chinese; it does not repair semantic errors.

Ask AI to compare evidence, not complete the table

Share only authorized sample rows together with manually checked source values. An existing tool such as Claude can list differences. Check its actual account limits and upload policy; no new paid plan is required by this exercise, and an entire commercial document is not the default input.

Compare only the supplied information. Do not browse or fill missing fields.
Manually checked source:
AX001, Cup, quantity3, unit price19.90, amount59.70;
AX002, Plate, quantity2, unit price45.00, amount90.00;
total149.70, currencyCNY, tax included.
The extracted result follows separately.
Compare item, quantity, unit price, amount, omissions and duplicate rows by SKU.
Report source value, extracted value, match/conflict and location needing review.
Do not infer blanks, page continuations or merged cells; mark missing evidence pending.
Do not produce a corrected file for direct production import.

Return to the source page to validate each finding. If the original is unclear, leave it pending rather than inventing a plausible price. Save approved corrections separately, keeping the raw extraction and reasons so another reviewer can trace the changes.

Handle missing tables, existing output and text problems differently

If no table is detected, verify that the selected pages contain the target and the file is neither damaged nor encrypted, then inspect logs and OCR settings. For Chinese scans, choose a suitable engine and language model using the OCR documentation. Changing a prompt alone does not establish a fix. Even selectable-text PDFs can have incorrect reading order.

An existing-directory error shows the overwrite guard worked. Inspect whether the folder contains successful output or partial failure artifacts and retain debugging material. Choose a new output name rather than asking AI to recursively delete it. Mid-export failures can leave partial files; do not mark the whole set successful.

If a CSV displays incorrectly, check encoding and import column types. Treat SKUs and long identifiers as text; inspect amounts, dates and thousands separators separately. A double-click preview is not definitive evidence of the underlying data. Do not fill every blank or deduplicate every repeated SKU automatically.

Include an acceptance-status sheet in the handover

  • Record source version, page range, Docling version and processing date.
  • Keep the original PDF, structural JSON, preview and raw CSV; do not overwrite business records.
  • Map every table to source pages and record checks of headers, units, spans, missing rows and duplicates.
  • Separate verified, conflicting and pending data; advance only explicitly approved results.
  • Make sure recipients understand these are extraction results, not business-approved import files.

Consult the official table-export example and serialization guidance. When a table cannot be explained, a pending status is more useful than a complete-looking CSV.

Independently prepared by AI Islands using official product pages and public sources. Features and pricing may change; check official sites for current information.