Skip to content

document-data-automation/pdf-table-extractor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pdf-table-extractor

Pull tables out of PDFs into clean CSV / Excel / JSON — with a preview-and-confirm step so you can eyeball what will be extracted before anything is written. Built for people who just need the data, not a parsing project. It puts the extraction stage of the PDF pipeline walkthrough into one command.

Why

A table in a PDF isn't really a table. On the page it's just scattered glyphs at fixed x/y coordinates — the "rows" and "columns" you see are an illusion your eye assembles from alignment and whitespace. There's no grid stored anywhere. Reconstructing which glyphs belong to which cell, stitching a table that runs across page breaks, and filling the blanks left by merged label cells is fiddly work that doesn't scale past a handful of pages. pdf-table-extractor does that reconstruction for you and hands back clean, tabular data — the extraction stage of the larger PDF automation pipeline.

Install

Not on PyPI — clone this repo and install from the clone:

git clone https://github.com/document-data-automation/pdf-table-extractor
cd pdf-table-extractor
pip install .
  • pdfplumber is required to read PDFs and is installed automatically.
  • Excel output needs openpyxl — install the extra when you want --format xlsx:
pip install ".[xlsx]"

You can also run it straight from a clone without installing:

python -m pdf_table_extractor preview sample.pdf

Workflow: preview, then extract

1. Preview — detect tables and print each as a compact grid with its page, table index, and rows×cols shape, so you can decide which ones you want:

pdf-table-extractor preview report.pdf --pages 1-3
[1] page 1, table 1  (5x4)
Region  Product  Units  Revenue
Europe  Widget   120    1199.00
        Gadget   45     899.55
Asia    Widget   80     799.20
        Gadget   60     1199.40

[2] page 2, table 1  (5x4)
Region  Product  Units  Revenue
...

The number in brackets ([1], [2], …) is a global table number you can pass to --table.

2. Extract — write the tables you want:

# every table, one CSV per table, into ./out
pdf-table-extractor extract report.pdf --out ./out --format csv

# just table 2
pdf-table-extractor extract report.pdf --out ./out --table 2

# stitch the multi-page table and forward-fill merged cells, as Excel
pdf-table-extractor extract report.pdf --out ./out --format xlsx --combine --fill-down

By default you get one file per table, named report__p<page>_t<index>.csv. For --format xlsx you get a single workbook (report.xlsx) with one sheet per table.

Flags

Flag Command Description
--pages RANGE both Pages to look at: 1-5, 1,3,7, or 2- (page 2 to the end).
--strip both Trim leading/trailing whitespace from every cell.
--out DIR extract Output directory (created if missing; default .).
--format csv|xlsx|json extract Output format (default csv).
--table N extract Extract only table number N from the preview listing.
--combine extract Stitch tables that share a header into one dataset.
--fill-down extract Forward-fill blank cells beneath merged label cells.
--version Print the version and exit.

Exit codes: 0 success, 1 a runtime problem (file missing, no tables found, a needed dependency absent), 2 a usage error (bad flags or --pages value).

Multi-page tables and merged cells

Multi-page stitching (--combine). When a table continues onto the next page, PDF viewers repeat the header row and the tool detects each fragment as a separate table. --combine groups tables by their header signature (the normalized, case-insensitive header cells) and concatenates their rows into one dataset — so a table spread over five pages becomes a single CSV/sheet with one header and all the rows.

Merged-cell fill-down (--fill-down). A label cell that visually spans several rows (a merged cell) leaves the rows beneath it blank in the raw data:

Region  Product  Units
Europe  Widget   120
        Gadget   45      <- "Europe" is blank here
Asia    Widget   80
        Gadget   60      <- "Asia" is blank here

--fill-down propagates each value downward into the blanks below it, so every row is self-contained (Europe, Gadget, 45). Headers are always normalized too: whitespace trimmed, embedded newlines collapsed, and blank/duplicate header cells given stable names.

As a library

from pdf_table_extractor import extract_tables

tables = extract_tables(
    "report.pdf",
    pages="1-3",     # optional page spec
    fill_down=True,  # forward-fill merged cells
    strip=True,      # trim whitespace
    combine=True,    # stitch multi-page tables
)

for table in tables:
    print(table.page, table.shape)   # e.g. 1 (41, 4)
    print(table.header)              # ['Region', 'Product', 'Units', 'Revenue']
    for row in table.rows:           # list[list[str]], header excluded
        print(row)

extract_tables() returns Table objects with .page, .index, .header, .rows, .number, and convenience .shape / .all_rows. Writers live in pdf_table_extractor.formats (write_csv, write_json, write_xlsx).

See examples/ for a runnable script and a helper that generates a sample PDF.

Development

git clone https://github.com/document-data-automation/pdf-table-extractor
cd pdf-table-extractor
pip install -e ".[dev]"
pytest

The pure logic — page-range parsing, header normalization, fill-down, multi-page stitching, the writers, and the preview formatter — is unit-tested offline with no PDF needed. A single integration test generates a one-page PDF at runtime and skips cleanly when pdfplumber/reportlab aren't installed, so CI (Python 3.9–3.12) stays green either way.

License

MIT — see LICENSE.


Built by document-data-automation.com — Python workflows for document & data automation.

About

Extract tables from PDFs into clean CSV, Excel, or JSON — with a preview-and-confirm step, multi-page table stitching, and merged-cell handling.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages