Invoice Field Regex Generator in Python for OCR Text
For suppliers with stable layouts, a few well tested regular expressions beat a heavy model: they are fast, explainable and easy to audit. This generator builds a Python parser for the four fields every AP team needs, with a basic total check.
Fill in
Alternatives separated by |
Patterns
import re
from datetime import datetime
CUR = re.escape("$")
INVOICE_NO = re.compile(r"(?:Invoice No|Invoice #|Inv No)\s*[:#.]?\s*([A-Z0-9][A-Z0-9\-/]{3,24})", re.I)
PO_NO = re.compile(r"(?:PO Number|Purchase Order|P.O. No)\s*[:#.]?\s*([A-Z0-9][A-Z0-9\-/]{3,24})", re.I)
DATE_TXT = re.compile(r"(?:Invoice Date|Date)\s*[:.]?\s*(\d{4}-\d{2}-\d{2}|\d{1,2}[/.-]\d{1,2}[/.-]\d{2,4})", re.I)
TOTAL = re.compile(r"(?:Total Due|Amount Due|Grand Total|Total)\s*[:.]?\s*" + CUR + r"?\s*([0-9]{1,3}(?:,[0-9]{3})*(?:\.[0-9]{2})|[0-9]+(?:\.[0-9]{2})?)", re.I)
LINE_AMT = re.compile(r"^.*?" + CUR + r"?\s*([0-9]{1,3}(?:,[0-9]{3})*\.[0-9]{2})\s*$", re.M)Parser
def first(pattern, text):
m = pattern.search(text)
return m.group(1).strip() if m else None
def parse_date(raw):
if not raw:
return None
for fmt in ("%Y-%m-%d", "%d/%m/%Y", "%d-%m-%Y", "%d.%m.%Y", "%m/%d/%Y", "%d/%m/%y"):
try:
return datetime.strptime(raw, fmt).date().isoformat()
except ValueError:
continue
return None
def parse_amount(raw):
return float(raw.replace(",", "")) if raw else None
def parse_invoice(text):
result = {
"invoice_number": first(INVOICE_NO, text),
"po_number": first(PO_NO, text),
"invoice_date": parse_date(first(DATE_TXT, text)),
"total": parse_amount(first(TOTAL, text)),
}
result["flags"] = []
for key in ("invoice_number", "invoice_date", "total"):
if result[key] is None:
result["flags"].append("missing_" + key)
return resultTotal check against line amounts
def check_total(text, parsed, tolerance=0.01):
amounts = [parse_amount(a) for a in LINE_AMT.findall(text)]
if not amounts or parsed["total"] is None:
return "cannot_check"
# the last amount on a page is usually the total, so exclude it from the sum
body = amounts[:-1]
if abs(sum(body) - parsed["total"]) <= tolerance:
return "ok"
return "review"
if __name__ == "__main__":
sample = open("invoice.txt", encoding="utf-8").read()
data = parse_invoice(sample)
data["total_check"] = check_total(sample, data)
print(data)This is a starting point for text-based extraction, not a complete product. It assumes decimal point amounts, so adapt the amount pattern and parse_amount for decimal comma locales. The total check is a heuristic that ignores tax and freight lines; replace it with line level logic that matches your invoice layouts. Test on real supplier samples before relying on it.
Outgrowing regex?
Optional: an expert can assess your invoice layouts and suggest where regex ends and a model should start.
Optional. The tool and every export work without this. No spam.
How to use the generator
List the labels your suppliers print, separated by a vertical bar, then set the currency symbol and total tolerance. Copy the script, save OCR text from your engine into invoice.txt, and run it. The output is a dictionary with the invoice number, PO number, ISO date and total, plus flags for missing mandatory fields. Extend the label lists as you meet new supplier layouts, and keep one test text file per supplier so changes do not break old ones.
Design of the patterns
Each pattern looks for a label, an optional separator such as a colon or hash, and then a value shaped like the field. Invoice and PO numbers allow letters, digits, hyphens and slashes, with a minimum length to avoid matching words. The date pattern accepts ISO dates and numeric day, month and year forms. The amount pattern accepts thousands commas and two decimals.
- Labels are case-insensitive alternatives
- Longer labels should come before shorter ones, so Total Due matches before Total
- Dates are normalized to ISO format
- Missing mandatory fields raise flags rather than silent blanks
Where regex stops working
Regex works when the label and value sit on the same line. It struggles with tables, labels above values, multi column layouts, handwritten notes and scans with heavy noise. Ambiguous dates such as 04/05/2026 cannot be resolved by pattern alone, so decide the order per supplier or country. When the number of layouts grows, move to a layout-aware extraction approach and keep regex for validation.
Common mistakes
A pattern that matches the first Total in the text may pick up a subtotal. Prefer the last match on the page, or anchor to the words Amount Due. Another mistake is skipping validation: pair every extracted value with a check such as date range, duplicate invoice detection by supplier and number, and the total comparison.
Frequently Asked Questions
Can regex extract data from any invoice?
No. It suits invoices where the label and value appear on one line in a consistent form. For varied layouts, tables and noisy scans you need layout-aware extraction, with regex kept for validating the results.
How do I handle dates like 04/05/2026?
Pattern matching cannot tell whether that is April 5 or May 4. Store the expected date order per supplier or country, and apply that order first. Reject dates that fall outside a plausible range around the receipt date.
How do I support decimal comma amounts?
Change the amount pattern to use dots for thousands and a comma for decimals, and update parse_amount to remove dots and replace the comma with a dot. Select the pattern per supplier locale rather than guessing from the text.
Why is my total picking up the subtotal?
The word Total also appears inside Subtotal. List the more specific labels first, use word boundaries, and prefer the last match in the text, since final totals usually appear at the end of the page.
If you need extraction that handles many layouts and writes validated results back to your ERP, Netray can build it as a private service on your infrastructure.
Related Tools
Invoice Extraction JSON Schema Generator
Create a JSON Schema that defines and validates the structure of extracted invoice data, including header fields, line items, confidence scores and review flags.
Quality & InspectionOCR Confusable Characters Reference for AP Validation
A lookup of look-alike characters (0 and O, 1 and l, 5 and S and more) with the fields where they cause errors and a validation rule for each.
Developer ToolsTesseract OCR Command Line Generator
Build the exact tesseract command for a single file and a PowerShell loop for a whole folder, with language, page segmentation mode, resolution and output format set from a form.
Supply Chain & InventoryInvoice Document Type Codes Reference (UNTDID 1001, X12, EDIFACT)
Look up what invoice type codes such as 380, 381 and 389 mean, and map them to the X12 transaction sets and EDIFACT messages used for purchasing, shipping, invoicing and payment.
More Developer Tools tools
See all- SAP Sales Order ABAP SELECT Generator (VBAK, VBAP, VBFA)
- SAP Sales Order Create BAPI ABAP Generator (BAPI_SALESORDER_CREATEFROMDAT2)
- SAP ABAP Open Items SELECT Generator
- SAP ACDOCA SQL Query Generator
- SAP QM Inspection Lot ABAP SELECT Generator
- SAP Quality Notification Pareto SQL Query Generator
- SAP QM Usage Decision BAPI Skeleton
- ABAP Custom Exception Class Generator
- ABAP Unit Test Class Generator
Keep exploring
Free tools
- Acumatica REST API Python Script GeneratorProduce a ready-to-run Python script for the Acumatica contract-based REST API: login, PUT a record, then logout.
- X-bar and R Control Limits Python Script GeneratorSet subgroup size, spec limits and file name and get a short Python script that computes control limits, Cpk and Ppk from CSV data.
- Gage R&R Python Script Generator (Average and Range)Fill in the file name, tolerance, and get a plain Python script that computes the average and range gage R&R.
ERP fixes and how-tos
- Calling SAP APIs from Python: OData with requests, Authentication and PyRFCCall SAP from Python with the requests library: authentication, filtering, paging and CSRF tokens for OData, plus when PyRFC and RFC make sense.
- How to Print or Reprint a Customer Invoice in SyteLineHow to print, reprint or save a customer invoice as PDF in SyteLine/CSI: the invoice printing form, reprint option, report options and what to check when it fails.
- SyteLine Customer Order to Invoice: Step by StepWalk a SyteLine customer order from entry through shipment to invoice: pick and pack, confirm the shipment, then run Auto Invoice or enter it manually.
Runs with your ERP
- Infor Service Mobile with Infor SyteLine Field ServiceInfor Service Mobile is a field technician app listed as a CloudSuite Industrial add-on. What it connects to in SyteLine service, setup steps, pitfalls, FAQ.
- AI Invoice Management and SAP S/4HANA Cloud: OCR capture and AP processingHow the AI Invoice Management SAP Store app captures invoice data with OCR and imports it into S/4HANA Cloud, plus setup steps, pitfalls and alternatives.
Guides
- AI Invoice Matching: An Implementation GuideImplement AI invoice matching in your ERP: 2-way and 3-way match automation, exception handling patterns, and how to keep AP control intact under audit.
- AP Invoice Automation in ERP: The Complete Guide for ManufacturersAP invoice automation in ERP explained: touchless capture, 3-way matching, approval routing, and AI agents that cut invoice processing costs by up to 80%.
- Field Service Management and ERP Integration: Patterns That Actually WorkField service ERP integration guide: master data ownership, work order to service order mapping, parts consumption, billing, and Infor ION patterns.
Software
- Oracle Field ServiceOracle Field Service schedules, routes and equips mobile workers within Oracle cloud applications. Modules, integrations, AI uses and alternatives.
- Dynamics 365 Field ServiceDynamics 365 Field Service handles work orders, resource scheduling and mobile technicians on Microsoft Dataverse. Modules, integrations and alternatives.