/pdf - Extract Structured Data from PDFs

Extract structured data from PDFs into JSON and Excel format efficiently.

Universal skill for batch-processing PDF documents into structured JSON and a merged Excel file. Works from any project directory.

Do NOT ask for confirmation — just execute and report results at the end.

Step 0: Detect input

  1. Find PDF source folder: Check for a pdf/ directory in the current working directory. If it doesn't exist, check for pdfs/, documents/, or docs/ (in that order). If none found, ask the user to specify the path.
  2. List all .pdf files in the source folder (non-recursive by default). Print the count: Found N PDFs in <folder>/.
  3. Create output directory: mkdir -p ./output in the current working directory.
  4. If no PDFs are found, STOP and report: No PDF files found in <folder>/.

Step 1: Parallel extraction — spawn sub-agents

For EACH PDF file, launch an independent sub-agent (using the Agent tool). Launch ALL sub-agents in a SINGLE message so they run in parallel — do NOT process sequentially.

Each sub-agent receives this task:

Read the PDF file at: <absolute_path_to_pdf>

Extract ALL structured data and write a JSON file to: <absolute_path_to_output>/<filename_without_ext>.json

The JSON schema MUST be exactly:
{
  "source_file": "<original filename>",
  "title": "<document title — from metadata, first heading, or first prominent text>",
  "sections": [
    {
      "heading": "<section heading or 'Introduction' if none>",
      "content": "<full text content of this section>",
      "page_numbers": [1, 2]
    }
  ],
  "key_entities": [
    {
      "name": "<entity name>",
      "type": "<person|organization|date|location|amount|product|other>",
      "context": "<short sentence where entity appears>"
    }
  ],
  "metadata": {
    "page_count": <number>,
    "language": "<detected language code, e.g. cs, en>",
    "extracted_at": "<ISO 8601 timestamp>"
  },
  "raw_text": "<complete raw text of the entire document>"
}

Rules:
- Read the PDF using the Read tool (it supports PDFs). For large PDFs (>10 pages), read in chunks of 20 pages at a time.
- Extract entities: names of people, organizations, dates, monetary amounts, locations, products — anything notable.
- Split into sections based on headings, page breaks, or logical content boundaries.
- If the PDF has no clear sections, create a single section with heading "Content".
- Write the JSON to disk IMMEDIATELY after extraction — do not hold it in memory.
- Use JSON.stringify with 2-space indentation.
- Report back: filename, title found, number of sections, number of entities, page count.

Important: If there are more than 10 PDFs, batch them into groups of 10 sub-agents at a time. Wait for each batch to complete before launching the next. This prevents overwhelming the system.

Step 2: Verify extraction

After all sub-agents complete:

  1. List all .json files in ./output/.
  2. Compare against the original PDF list — report any missing extractions.
  3. For each JSON, verify it parses correctly and has the required schema fields.
  4. Report: Successfully extracted N/M PDFs.

If any extractions failed, note them but continue with the successful ones.

Step 3: Merge into Excel

Before generating the Excel file, present the proposed structure to the user and wait for approval.

Show the user a preview like this:

Navrhovaná struktura výstupního Excel souboru:

📊 final_output.xlsx
├── Sheet 1: "Summary"
│   └── Columns: File | Title | Language | Pages | Sections | Entities | Extracted At
│   └── (jeden řádek per dokument)
│
├── Sheet 2: "<název souboru 1>"
│   ├── Tabulka "Sections": Section Heading | Content | Pages
│   └── Tabulka "Entities": Entity | Type | Context
│
├── Sheet 3: "<název souboru 2>"
│   └── (stejná struktura)
└── ...

Celkem: N listů (1 summary + N dokumentů)
Výstup: ./final_output.xlsx

Wait for the user to confirm or request changes (e.g., different columns, different sheet layout, additional sheets). Adjust the structure accordingly before proceeding.

Once approved, create ./final_output.xlsx using a Python script:

  1. Check if openpyxl is available: python3 -c "import openpyxl". If not, install it: pip3 install openpyxl.
  2. Generate and execute a Python script that:
    • Reads all JSON files from ./output/
    • Creates a workbook with the approved structure (default below if user confirms without changes):
      • Summary sheet (first sheet): columns = File | Title | Language | Pages | Sections | Entities | Extracted At. One row per document.
      • One sheet per document (sheet name = first 31 chars of filename): columns = Section Heading | Content | Pages. Below the sections table, add an "Entities" table: Entity | Type | Context.
    • Sheet names must be truncated to 31 characters (Excel limit) and deduplicated if needed.
    • Saves to ./final_output.xlsx.

Step 4: Report results

Print a single summary:

## 📄 PDF Processing Report

### Source: <folder> (N files)
### Extraction: ✅ N/N successful / ⚠️ N failed
### Output JSON: ./output/ (N files)
### Excel: ./final_output.xlsx

### Per-file summary:
| File | Title | Pages | Sections | Entities |
|------|-------|-------|----------|----------|
| doc1.pdf | ... | 12 | 5 | 23 |
| doc2.pdf | ... | 3 | 2 | 8 |

### Failures (if any):
- doc3.pdf: <error reason>

Notes

  • This skill works with any PDF content: contracts, reports, invoices, research papers, etc.
  • Entity extraction is best-effort — it identifies prominent named entities, not an exhaustive NER.
  • The raw_text field preserves the complete document text for downstream use.
  • All intermediate JSON files are kept in ./output/ for inspection or re-processing.