CONTROLLING Y AUTOMATIZACIÓN ADMINISTRATIVA

Automatización de facturas en Windows con OCR, clasificación y exportación a Excel

Informe ejecutivo y diseño técnico de una aplicación orientada a procesar documentos PDF y JPG de facturas de proveedores y clientes, extraer datos clave, sugerir cuentas contables del Plan General Contable y generar un libro Excel con múltiples hojas.

Tabla de contenido

  1. Resumen ejecutivo
  2. Objetivo del sistema
  3. Alcance funcional
  4. Arquitectura propuesta
  5. Flujo operativo
  6. Extracción OCR y lectura documental
  7. Clasificación proveedor / cliente
  8. Asignación de cuentas PGC
  9. Exportación a Excel
  10. Estructura de carpetas en Windows
  11. Diseño técnico por módulos
  12. Controles, validaciones y errores
  13. Roadmap evolutivo
  14. Ventajas para administración y controlling
  15. Conclusión

1. Resumen ejecutivo

La propuesta consiste en desarrollar una aplicación para entorno Windows capaz de revisar automáticamente una carpeta donde se depositan facturas en formato PDF, JPG, JPEG o PNG. El sistema extrae texto directamente del documento cuando es posible y, si se trata de un documento escaneado o una imagen, aplica OCR. A partir de ese contenido identifica datos relevantes como fecha, número de factura, emisor, receptor, CIF/NIF, base imponible, IVA, total y descripción del producto o servicio.

Una vez extraída la información, la aplicación clasifica cada documento como factura de proveedor o factura de cliente, en función de la posición de la empresa propia dentro del documento. Posteriormente analiza la descripción facturada y propone una cuenta del Plan General Contable según reglas configurables. Finalmente consolida los resultados en un archivo Excel con varias hojas, separando proveedores, clientes, incidencias, resúmenes y reglas contables.

El objetivo no es solo ahorrar tiempo administrativo, sino también crear una base reutilizable para contabilidad, controlling, auditoría interna, conciliación documental y futura integración con ERP como Odoo.

2. Objetivo del sistema

El sistema pretende automatizar la lectura y estructuración de facturas recibidas y emitidas, reduciendo la intervención manual en tareas repetitivas. La meta es disponer de un flujo donde el usuario simplemente copie los documentos en una carpeta de entrada y la aplicación procese, clasifique, organice y exporte la información de forma trazable.

En términos operativos, el sistema debe ser sencillo de desplegar en un terminal Windows, tolerante a formatos heterogéneos y fácilmente ampliable con nuevas reglas por proveedor, por concepto contable o por estructura documental.

3. Alcance funcional

La solución cubre la lectura de archivos PDF y de imágenes, la extracción de texto, el reconocimiento OCR, la identificación de campos principales, la clasificación entre facturas de proveedor y cliente, la propuesta de cuenta PGC mediante reglas y la exportación consolidada a Excel.

También contempla una estructura de carpetas para separar documentos pendientes, procesados, revisables y erróneos. Además, deja preparada una capa evolutiva para incorporar detección de duplicados, validación fiscal, tratamiento por proveedor, interfaz gráfica y conexión con bases de datos o ERP.

Quedan fuera de esta primera fase la contabilización automática definitiva, la validación jurídica completa del documento y el tratamiento inteligente avanzado basado en modelos entrenados específicamente por sector.

4. Arquitectura propuesta

La arquitectura recomendada se basa en Python sobre Windows por su flexibilidad, rapidez de desarrollo, bajo coste de implantación y amplio ecosistema de librerías documentales. El sistema puede operar desde una consola, un archivo por lotes o más adelante desde una interfaz gráfica sencilla.

Capa Función Tecnología sugerida
Entrada documental Lectura de PDFs e imágenes os, pathlib, Pillow
Extracción de texto Texto embebido y OCR PyMuPDF / pdfplumber / pytesseract
Normalización Limpieza y homogeneización re, unicodedata, pandas
Clasificación Proveedor / cliente / revisar Reglas heurísticas
Motor contable Sugerencia cuenta PGC CSV de reglas + matching
Salida Libro Excel con hojas pandas + openpyxl

5. Flujo operativo

El usuario deposita facturas en la carpeta de entrada. El sistema recorre todos los documentos compatibles y decide, según el tipo de archivo, si debe leer el texto embebido o aplicar OCR. Después limpia el texto, intenta localizar los datos principales y compara los CIF y nombres detectados con la configuración de la empresa propia. En función de ello determina si se trata de una factura emitida o recibida.

Una vez identificada la naturaleza de la factura, el sistema analiza la descripción, busca coincidencias con el catálogo de reglas contables y propone una cuenta PGC. Finalmente registra todo en un Excel y mueve el documento a la carpeta correspondiente. Si el contenido es ambiguo o incompleto, el archivo pasa a revisión o a error.

Secuencia simplificada:
Entrada → Lectura → OCR si procede → Extracción de campos → Clasificación → Reglas PGC → Excel → Archivo procesado / revisar / error

6. Extracción OCR y lectura documental

El sistema debe priorizar primero la extracción de texto nativo de PDF, ya que es más rápida y precisa que el OCR. Cuando el documento sea una imagen o un PDF escaneado, se activará Tesseract OCR. Para mejorar resultados conviene aplicar preprocesado básico como conversión a escala de grises, aumento de resolución, binarización y corrección de inclinación cuando sea posible.

En esta fase es recomendable usar idioma español, y en entornos donde haya facturas en catalán, francés o inglés, ampliar el OCR multilingüe. La calidad del OCR condiciona toda la cadena posterior, por lo que esta capa es crítica.

7. Clasificación proveedor / cliente

La clasificación se basa en identificar si la empresa propia actúa como emisora o receptora del documento. Para ello se utiliza un archivo de configuración donde figuran el nombre fiscal, las variantes de razón social y el CIF/NIF de la empresa. Si el emisor coincide con la empresa propia, el documento se interpreta como factura de cliente. Si el receptor coincide con la empresa propia, se considera factura de proveedor.

Cuando el texto no ofrece suficiente claridad, la clasificación se apoya en palabras clave, plantillas conocidas o listas de terceros recurrentes. Si persiste la duda, el sistema no fuerza una decisión y remite el caso a revisión.

Este enfoque evita errores de sentido contable y permite escalar el sistema gradualmente con más reglas específicas.

8. Asignación de cuentas PGC

La propuesta de cuenta contable se apoya en reglas simples y transparentes. Cada regla vincula palabras clave o nombres de proveedor con una cuenta del Plan General Contable. De esta forma, si la descripción incluye términos como alquiler, asesoría, seguro, transporte, electricidad o publicidad, el sistema propone la cuenta correspondiente.

La lógica está diseñada como un mecanismo de sugerencia y no como un asiento automático definitivo. Esto es importante porque una misma descripción puede tener tratamientos contables distintos según la actividad, el importe, el criterio interno o la naturaleza del gasto.

Palabra clave Cuenta PGC Descripción
alquiler 621 Arrendamientos y cánones
asesoría / abogado / gestoría 623 Servicios profesionales independientes
transporte 624 Transportes
seguro 625 Primas de seguros
publicidad / ads 627 Publicidad, propaganda y RRPP
electricidad / agua / gas 628 Suministros

9. Exportación a Excel

El resultado debe consolidarse en un único libro Excel con varias hojas. La separación recomendada incluye una hoja para proveedores, otra para clientes, otra para errores o revisión y una hoja resumen con agregados económicos. Este enfoque facilita tanto la explotación administrativa como el filtrado posterior por auditoría o controlling.

Hoja Contenido
Proveedores Facturas recibidas clasificadas
Clientes Facturas emitidas clasificadas
Resumen Totales por tipo, cuenta y tercero
Errores Documentos incompletos o dudosos
Reglas_PGC Catálogo editable de asignación contable

10. Estructura de carpetas en Windows

Para garantizar orden documental, trazabilidad y facilidad de uso, se propone una jerarquía simple de carpetas. Todos los documentos entran por una carpeta común y el sistema los redistribuye tras el procesamiento.

C:\Facturas\ │ ├── entrada ├── procesados ├── revisar ├── error ├── salida │ └── Facturas_Procesadas.xlsx ├── config.json └── reglas_pgc.csv

11. Diseño técnico por módulos

La aplicación puede estructurarse de forma modular para facilitar mantenimiento y evolución. Un primer módulo se encarga de localizar archivos y gestionar carpetas. Un segundo módulo lee documentos y ejecuta OCR cuando corresponde. Un tercer módulo limpia y normaliza el texto. Un cuarto módulo intenta identificar campos mediante expresiones regulares y reglas. Un quinto módulo clasifica el documento como proveedor, cliente o revisar. Un sexto módulo aplica las reglas PGC. Finalmente, un módulo de salida construye el libro Excel y gestiona el movimiento de archivos.

Esta organización separa responsabilidades y permite que en fases posteriores se sustituyan heurísticas simples por lógica más avanzada sin reescribir el conjunto.

12. Controles, validaciones y errores

El sistema debe registrar qué documentos han sido procesados, cuáles no han podido interpretarse y cuáles requieren revisión humana. Conviene almacenar también el nombre del archivo, la ruta, el estado del documento y un nivel de confianza en la clasificación.

Entre las validaciones recomendadas destacan la coherencia entre base imponible, IVA y total, la existencia de fecha y número de factura, la presencia de CIF y la detección de archivos potencialmente duplicados.

En facturas de mala calidad o fotografías mal tomadas el OCR puede degradarse mucho. En esos casos la lógica correcta no es inventar datos, sino desviar el documento al circuito de revisión.

13. Roadmap evolutivo

La primera fase debe centrarse en un producto mínimo viable funcional: lectura documental, OCR, clasificación básica, reglas contables simples y exportación a Excel. La segunda fase puede añadir un motor de reglas por proveedor, validación de CIF, detección de duplicados, parametrización avanzada y panel de revisión. La tercera fase puede incorporar interfaz gráfica para Windows, base de datos local, histórico de correcciones y aprendizaje a partir de decisiones del usuario. En una cuarta fase ya tendría sentido la integración con Odoo u otros sistemas de gestión, así como el tratamiento de formatos estructurados como Facturae o UBL.

14. Ventajas para administración y controlling

El sistema reduce tiempo administrativo, mejora la homogeneidad del dato, facilita la trazabilidad de documentos y prepara la información para reporting, conciliación y análisis. Desde el punto de vista del controlling, disponer de una capa previa de estructuración documental permite explotar gastos por cuenta, tercero, periodo y tipología sin tener que reconstruir la información desde documentos dispersos.

Además, la solución es escalable y de bajo coste en comparación con suites cerradas, por lo que resulta especialmente interesante para pymes, asesorías, departamentos administrativos internos y proyectos de transformación digital con enfoque open source.

15. Conclusión

La automatización de lectura de facturas en Windows mediante OCR y reglas contables es una solución realista, rentable y técnicamente abordable. No sustituye por completo la supervisión humana en la primera fase, pero sí elimina una parte sustancial del trabajo repetitivo y prepara un terreno sólido para una contabilidad más rápida, mejor trazada y mejor integrada con sistemas de gestión.

La clave del éxito no está en prometer perfección documental desde el primer día, sino en construir un sistema robusto, transparente, auditable y evolutivo. Precisamente ahí Python, el OCR y la exportación estructurada a Excel ofrecen una base excelente para crecer.

Autor

Ryan KHOUJA

Disclaimer

Documento de carácter informativo y técnico-conceptual. Puede contener simplificaciones, aproximaciones y elementos que requieren adaptación al entorno real de uso, a la casuística documental y a los criterios contables de cada organización. No se permite la reproducción total o parcial sin permiso explícito del autor.

Primer script funcional para Windows: OCR de facturas, clasificación y exportación a Excel

Script base en Python para procesar PDFs e imágenes de facturas, aplicar OCR, clasificar documentos como proveedor o cliente y exportar los resultados a un libro Excel con varias hojas.

Tabla de contenido

  1. Qué hace este script
  2. Estructura esperada de carpetas
  3. Dependencias
  4. Archivo de configuración
  5. Script principal en Python
  6. Ejemplo de reglas PGC
  7. Archivo BAT para Windows
  8. Observaciones y mejoras futuras

1. Qué hace este script

Este script revisa automáticamente una carpeta de entrada en Windows y localiza archivos PDF, JPG, JPEG y PNG. Si el PDF tiene texto embebido, lo lee directamente. Si es una imagen o un PDF escaneado, aplica OCR mediante Tesseract. Después intenta extraer campos relevantes como número de factura, fecha, CIF, importes y descripción, clasifica el documento como factura de proveedor o de cliente y propone una cuenta PGC según reglas simples.

Finalmente genera un archivo Excel con varias hojas y mueve cada documento a una carpeta de procesados, revisar o error.

2. Estructura esperada de carpetas

C:\Facturas\ │ ├── entrada ├── procesados ├── revisar ├── error ├── salida ├── config.json └── reglas_pgc.csv

3. Dependencias

Debes instalar Python y Tesseract OCR en Windows. Además, el script utiliza librerías habituales del ecosistema Python para PDF, OCR y Excel.

pip install pandas openpyxl pillow pytesseract pymupdf

También deberás instalar Tesseract OCR y ajustar la ruta en el archivo de configuración si fuese necesario.

4. Archivo de configuración

Este archivo permite indicar el nombre fiscal de tu empresa, el CIF y las rutas de carpetas. También puede incluir variantes del nombre para facilitar la clasificación proveedor o cliente.

{ "empresa_nombre": "MI EMPRESA SL", "empresa_cif": "B12345678", "empresa_alias": [ "MI EMPRESA", "MI EMPRESA S.L.", "MIEMPRESA SL" ], "ruta_entrada": "C:\\Facturas\\entrada", "ruta_procesados": "C:\\Facturas\\procesados", "ruta_revisar": "C:\\Facturas\\revisar", "ruta_error": "C:\\Facturas\\error", "ruta_salida_excel": "C:\\Facturas\\salida\\Facturas_Procesadas.xlsx", "tesseract_cmd": "C:\\Program Files\\Tesseract-OCR\\tesseract.exe", "ocr_lang": "spa" }

5. Script principal en Python

A continuación se muestra una primera versión funcional del script. Está pensada como base realista y ampliable. No pretende resolver todos los formatos posibles del mercado, pero sí ofrecer una estructura sólida para empezar.

import os import re import json import shutil from pathlib import Path import pandas as pd import fitz import pytesseract from PIL import Image SUPPORTED_EXTENSIONS = {".pdf", ".jpg", ".jpeg", ".png"} def load_config(config_path="config.json"): with open(config_path, "r", encoding="utf-8") as f: return json.load(f) def ensure_directories(cfg): Path(cfg["ruta_entrada"]).mkdir(parents=True, exist_ok=True) Path(cfg["ruta_procesados"]).mkdir(parents=True, exist_ok=True) Path(cfg["ruta_revisar"]).mkdir(parents=True, exist_ok=True) Path(cfg["ruta_error"]).mkdir(parents=True, exist_ok=True) Path(Path(cfg["ruta_salida_excel"]).parent).mkdir(parents=True, exist_ok=True) def load_pgc_rules(csv_path="reglas_pgc.csv"): if not Path(csv_path).exists(): return pd.DataFrame(columns=["keyword", "cuenta", "descripcion"]) return pd.read_csv(csv_path, dtype=str).fillna("") def normalize_text(text): if not text: return "" text = text.replace("\n", " ") text = re.sub(r"\s+", " ", text) return text.strip() def extract_text_from_pdf(pdf_path): text = "" try: doc = fitz.open(pdf_path) for page in doc: text += page.get_text("text") + "\n" doc.close() except Exception: return "" return normalize_text(text) def extract_text_from_image(image_path, lang="spa"): try: img = Image.open(image_path) text = pytesseract.image_to_string(img, lang=lang) return normalize_text(text) except Exception: return "" def extract_text(file_path, lang="spa"): ext = Path(file_path).suffix.lower() if ext == ".pdf": text = extract_text_from_pdf(file_path) if text: return text try: doc = fitz.open(file_path) all_text = [] for page_index in range(len(doc)): page = doc.load_page(page_index) pix = page.get_pixmap(dpi=200) temp_img = f"temp_page_{page_index}.png" pix.save(temp_img) page_text = extract_text_from_image(temp_img, lang=lang) all_text.append(page_text) os.remove(temp_img) doc.close() return normalize_text(" ".join(all_text)) except Exception: return "" elif ext in {".jpg", ".jpeg", ".png"}: return extract_text_from_image(file_path, lang=lang) return "" def find_first(patterns, text): for pattern in patterns: match = re.search(pattern, text, flags=re.IGNORECASE) if match: return match.group(1).strip() return "" def extract_fields(text): fecha = find_first([ r"\b(\d{2}/\d{2}/\d{4})\b", r"\b(\d{2}-\d{2}-\d{4})\b", r"\b(\d{4}-\d{2}-\d{2})\b" ], text) numero_factura = find_first([ r"(?:factura|invoice|n[ºo°]\s*factura|num\.?\s*factura)\s*[:#-]?\s*([A-Z0-9\-\/]+)" ], text) cif = find_first([ r"\b([A-Z]\d{8})\b", r"\b(\d{8}[A-Z])\b" ], text) total = find_first([ r"(?:total\s*(?:factura)?|importe\s*total)\s*[:\-]?\s*([0-9\.,]+)" ], text) base = find_first([ r"(?:base\s*imponible)\s*[:\-]?\s*([0-9\.,]+)" ], text) iva = find_first([ r"\b(?:iva)\s*[:\-]?\s*([0-9\.,]+)" ], text) descripcion = find_first([ r"(?:concepto|descripci[oó]n|detalle)\s*[:\-]?\s*(.{10,200})" ], text) if not descripcion: descripcion = text[:200] return { "fecha": fecha, "numero_factura": numero_factura, "cif_detectado": cif, "base_imponible": base, "iva": iva, "total": total, "descripcion": descripcion } def classify_invoice(text, cfg): text_upper = text.upper() empresa_nombre = cfg.get("empresa_nombre", "").upper() empresa_cif = cfg.get("empresa_cif", "").upper() empresa_alias = [x.upper() for x in cfg.get("empresa_alias", [])] markers = [empresa_nombre, empresa_cif] + empresa_alias hits = sum(1 for m in markers if m and m in text_upper) if hits == 0: return "revisar", 0.20 if any(x in text_upper for x in ["FACTURA EMITIDA", "CLIENTE", "DESTINATARIO"]): return "cliente", 0.70 if any(x in text_upper for x in ["FACTURA RECIBIDA", "PROVEEDOR", "ACREEDOR"]): return "proveedor", 0.70 emisor_words = ["EMISOR", "EXPEDIDOR", "REMITENTE"] receptor_words = ["RECEPTOR", "CLIENTE", "DESTINATARIO"] score_cliente = 0 score_proveedor = 0 for word in emisor_words: if word in text_upper and empresa_nombre in text_upper: score_cliente += 1 for word in receptor_words: if word in text_upper and empresa_nombre in text_upper: score_proveedor += 1 if score_cliente > score_proveedor: return "cliente", 0.60 elif score_proveedor > score_cliente: return "proveedor", 0.60 return "revisar", 0.40 def assign_pgc_account(description, rules_df): if not description: return "", "" desc = description.lower() for _, row in rules_df.iterrows(): keyword = str(row.get("keyword", "")).strip().lower() cuenta = str(row.get("cuenta", "")).strip() descripcion = str(row.get("descripcion", "")).strip() if keyword and keyword in desc: return cuenta, descripcion return "", "" def move_file(file_path, target_folder): Path(target_folder).mkdir(parents=True, exist_ok=True) target_path = Path(target_folder) / Path(file_path).name shutil.move(str(file_path), str(target_path)) return str(target_path) def process_files(): cfg = load_config() ensure_directories(cfg) pytesseract.pytesseract.tesseract_cmd = cfg.get("tesseract_cmd", "") lang = cfg.get("ocr_lang", "spa") rules_df = load_pgc_rules() proveedores = [] clientes = [] errores = [] entrada = Path(cfg["ruta_entrada"]) files = [f for f in entrada.iterdir() if f.is_file() and f.suffix.lower() in SUPPORTED_EXTENSIONS] for file in files: try: text = extract_text(str(file), lang=lang) if not text: errores.append({ "archivo": file.name, "motivo": "No se pudo extraer texto", "ruta_original": str(file) }) move_file(file, cfg["ruta_error"]) continue fields = extract_fields(text) tipo, confianza = classify_invoice(text, cfg) cuenta_pgc, cuenta_desc = assign_pgc_account(fields["descripcion"], rules_df) record = { "archivo": file.name, "tipo": tipo, "confianza": confianza, "fecha": fields["fecha"], "numero_factura": fields["numero_factura"], "cif_detectado": fields["cif_detectado"], "base_imponible": fields["base_imponible"], "iva": fields["iva"], "total": fields["total"], "descripcion": fields["descripcion"], "cuenta_pgc": cuenta_pgc, "cuenta_pgc_desc": cuenta_desc } if tipo == "proveedor": proveedores.append(record) move_file(file, cfg["ruta_procesados"]) elif tipo == "cliente": clientes.append(record) move_file(file, cfg["ruta_procesados"]) else: errores.append({ "archivo": file.name, "motivo": "Clasificación ambigua o pendiente de revisión", "ruta_original": str(file), "texto_resumido": text[:400] }) move_file(file, cfg["ruta_revisar"]) except Exception as e: errores.append({ "archivo": file.name, "motivo": f"Error general: {str(e)}", "ruta_original": str(file) }) move_file(file, cfg["ruta_error"]) export_to_excel(cfg["ruta_salida_excel"], proveedores, clientes, errores, rules_df) def export_to_excel(output_path, proveedores, clientes, errores, rules_df): df_prov = pd.DataFrame(proveedores) df_cli = pd.DataFrame(clientes) df_err = pd.DataFrame(errores) resumen = pd.DataFrame([ {"tipo": "proveedores", "cantidad": len(df_prov)}, {"tipo": "clientes", "cantidad": len(df_cli)}, {"tipo": "errores_o_revision", "cantidad": len(df_err)} ]) with pd.ExcelWriter(output_path, engine="openpyxl") as writer: df_prov.to_excel(writer, sheet_name="Proveedores", index=False) df_cli.to_excel(writer, sheet_name="Clientes", index=False) resumen.to_excel(writer, sheet_name="Resumen", index=False) df_err.to_excel(writer, sheet_name="Errores", index=False) rules_df.to_excel(writer, sheet_name="Reglas_PGC", index=False) if __name__ == "__main__": process_files() print("Proceso finalizado.")

6. Ejemplo de reglas PGC en CSV

El archivo de reglas permite asociar palabras clave con cuentas contables. Se puede ampliar y afinar según proveedores recurrentes o según tu política contable.

keyword,cuenta,descripcion alquiler,621,Arrendamientos y cánones asesoria,623,Servicios profesionales independientes abogado,623,Servicios profesionales independientes gestoria,623,Servicios profesionales independientes transporte,624,Transportes seguro,625,Primas de seguros publicidad,627,Publicidad propaganda y relaciones públicas google ads,627,Publicidad propaganda y relaciones públicas electricidad,628,Suministros agua,628,Suministros gas,628,Suministros telefono,629,Otros servicios internet,629,Otros servicios mercancia,600,Compras de mercaderías

7. Archivo BAT para Windows

Este pequeño archivo por lotes permite ejecutar el script con doble clic desde Windows.

@echo off cd /d C:\Facturas python procesar_facturas.py pause

8. Observaciones y mejoras futuras

Esta versión inicial es útil como primera base operativa, pero conviene verla como un punto de partida. En la práctica, las facturas presentan formatos muy heterogéneos, por lo que la precisión mejorará mucho cuando añadas reglas por proveedor, múltiples expresiones regulares, detección de CIF de emisor y receptor por separado, tratamiento de importes con más validación y un histórico de decisiones del usuario.

También será recomendable incorporar una interfaz gráfica sencilla para Windows, un control de duplicados, mayor trazabilidad de logs y una revisión manual asistida antes de consolidar datos en el Excel definitivo.

En una segunda iteración, este mismo núcleo puede evolucionar hacia una solución mucho más robusta e incluso integrarse con Odoo, SQLite o un flujo documental más amplio.

Conclusión

Este script proporciona una base funcional y realista para comenzar a automatizar el tratamiento de facturas en Windows. La combinación de OCR, reglas heurísticas y exportación estructurada a Excel permite pasar rápidamente de un archivo documental caótico a una salida organizada y explotable por administración, contabilidad y controlling.

Disclaimer

Este contenido es técnico y orientativo. La precisión del sistema dependerá de la calidad del OCR, de la variedad de formatos de factura y de la parametrización concreta de reglas. Requiere adaptación al entorno real y validación antes de uso contable o fiscal en producción. No se permite reproducción total o parcial sin permiso explícito del autor.

Comments