1 # pdf_to_html.py 2 ### PDF Invoice → HTML Table Converter 3 4 --- 5 6 ## What Is It? 7 8 `pdf_to_html.py` is a command-line Python script that reads an invoice-style PDF file and produces a clean, styled HTML file containing the same table — faithfully reproducing every row, column, header block, and grand total exactly as they appear in the original document. 9 10 It is designed for PDFs that have no embedded table grid lines (i.e. the table is plain text laid out with spaces). The script uses a regex parser tuned to the column order of the invoice rather than relying on pdfplumber's automatic table detector. 11 12 --- 13 14 ## Requirements 15 16 ### Python Version 17 18 Python **3.10 or newer** is required (uses the built-in `list[...]` type hint syntax). 19 20 ### Python Libraries 21 22 Install both libraries with pip: 23 24 ```bash 25 pip install pdfplumber pypdf 26 ``` 27 28 | Package | Purpose | 29 |---|---| 30 | `pdfplumber` | Extracts raw text from each PDF page with layout awareness. Also attempts automatic table detection as a primary strategy. | 31 | `pypdf` | Reads PDF metadata (title, author, creation date) from the file header. | 32 33 ### No Other Dependencies 34 35 The script uses only Python's built-in modules (`sys`, `os`, `re`) alongside the two packages above. No OCR engine, no browser, no external tools required. 36 37 --- 38 39 ## Installation 40 41 No installation step is needed. Simply download the script and run it directly: 42 43 ```bash 44 # 1. Download / save the script 45 46 # 2. Install dependencies 47 pip install pdfplumber pypdf 48 49 # 3. Run 50 python pdf_to_html.py your_invoice.pdf 51 ``` 52 53 --- 54 55 ## Usage 56 57 ### Basic — auto-named output 58 59 ```bash 60 python pdf_to_html.py input.pdf 61 ``` 62 63 Saves the result as `input_table.html` in the same directory. 64 65 ### Custom output path 66 67 ```bash 68 python pdf_to_html.py input.pdf output.html 69 ``` 70 71 Saves the result to the path you specify. 72 73 ### Examples 74 75 ```bash 76 python pdf_to_html.py examples.pdf 77 python pdf_to_html.py invoices/march.pdf reports/march_table.html 78 ``` 79 80 --- 81 82 ## Output 83 84 The generated HTML file contains: 85 86 - A header block with Auftraggeber, date range, Baustellenname, Teilrechnung number, and Kst.Nr. 87 - A full data table with all rows extracted from the PDF. 88 - Right-aligned, monospace numeric columns (Menge, Einheitspreis, Betrag). 89 - A bold **Summe** footer row with the grand total. 90 - Hover highlighting on rows for easy reading. 91 92 Open the `.html` file in any web browser to view or print it. No internet connection is needed — all styling is self-contained. 93 94 --- 95 96 ## How It Works 97 98 ### Step 1 — `extract_metadata()` 99 100 Reads the first page of the PDF as plain text and uses regular expressions to locate the Auftraggeber line (splitting off the date range), Baustellenname, Teilrechnung number, and Kst.Nr. 101 102 ### Step 2 — `extract_rows()` 103 104 Reads every page's text and applies a single multi-group regex that matches the invoice row format: 105 106 ``` 107 01 Positionstext description 1,00 Stk € 500,00 € 500,00 Address note 108 ``` 109 110 > **Important:** the `€` symbol appears *before* each number in this PDF (`€ 500,00`), not after. The regex is written to match that exact format. 111 112 ### Step 3 — `extract_total()` 113 114 Scans the full text for the `Summe` line and extracts the euro total. 115 116 ### Step 4 — `build_html()` 117 118 Assembles the metadata, rows, and total into a complete, self-contained HTML document with embedded CSS. Numeric columns are detected by index and rendered right-aligned in a monospace font. 119 120 --- 121 122 ## Terminal Output 123 124 When you run the script you will see: 125 126 ``` 127 📄 Reading: examples.pdf 128 Rows found : 27 129 Total : € 12 325,00 130 ✅ Saved: examples.html 131 ``` 132 133 If no rows are found the script prints a warning and exits with code `1`. This typically means the PDF uses scanned/image-based text and would require OCR to process. 134 135 --- 136 137 ## Limitations 138 139 - **Scanned PDFs:** Image-based PDFs cannot be parsed. An OCR library such as `pytesseract` would be needed. 140 - **Different formats:** The regex is tuned to the column order and `€` placement of this specific invoice format. Different invoice layouts may need regex adjustments. 141 - **Multi-page tables:** The script reads all pages and combines the text, so multi-page tables are handled correctly as long as the row format is consistent. 142 143 --- 144 145 ## Quick Reference 146 147 | Task | Command | 148 |---|---| 149 | Install dependencies | `pip install pdfplumber pypdf` | 150 | Run (auto output name) | `python pdf_to_html.py file.pdf` | 151 | Run (custom output) | `python pdf_to_html.py file.pdf out.html` | 152 | Open result | Open the `.html` file in any browser | 153 | Python version | 3.10 or newer |