Tablas Word (.docx) (II)
Conversión a Excel (xlsx)
Una vez que obtenemos las tablas de un documento .docx, una de las opciones de prosecución del procedimiento es transformar dichas tablas en un archivo .xlsx. Otra es hacerlo como.csv, pero la primera opción presenta ventajas sustantivas, como la de crear una estructura tabular clara, incluso en visualización directa, y directamente manejable como hoja de cálculo; al ser esto segundo, estamos incluyendo una ventaja significativa: los datos se almacenan como tipos de datos con formatos específicos (string, numéricos, fecha...), dado que así han sido procesados en el script (ver entrada anterior). Por todo esto, esta entrada es mera continuación de la precedente y aparta a aquella el archivo de las tablas y sus contenidos como hoja de cálculo .xlsx. Este es el script que lo hace posible:
# 0. Importamos la bibliotecas necesarias
import pandas as pd
from docx import Document
import os
import unicodedata
import warnings #Importamos avisos para controlar...
warnings.simplefilter(action='ignore', category=FutureWarning) # ... que los ocultamos explícitamente
# 1. Función para normalizar las cabeceras de las tablas y facilitar su tratamiento posterior
def normalizar_cabeceras(lista_cabeceras):
nuevas_cabeceras = []
for i, nombre in enumerate(lista_cabeceras):
nombre = str(nombre).strip().lower()
nombre = "".join(c for c in unicodedata.normalize('NFD', nombre) if unicodedata.category(c) != 'Mn') # Limpieza básica
nombre = nombre.replace(" ", "_").replace("/", "_") or f"columna_{i}"
count = 0 # Código para evitar duplicados (y el error 'duplicate keys') en el nombre de los campos
temp_nombre = nombre
while temp_nombre in nuevas_cabeceras:
temp_nombre = f"{nombre}_{count}"
count += 1
nuevas_cabeceras.append(temp_nombre)
return nuevas_cabeceras
# 2. Función para extraer los datos de las tablas evitando alteraciones previsibles (celdas combinadas)
def extraer_matriz_segura(tabla):
matriz = []
for fila in tabla.rows: # Extraer contenidos de las tablas evitando errores de celdas combinadas repetidas
fila_datos = []
for celda in fila.cells:
fila_datos.append(celda.text.strip())
matriz.append(fila_datos)
if not matriz: return [] # Equilibrado de filas, dado que Pandas exige que todas midan lo mismo
max_cols = max(len(f) for f in matriz)
for f in matriz:
while len(f) < max_cols:
f.append("") # Rellenar huecos por celdas combinadas
return matriz
# 3. Función para obtener las tablas del documento y su contenido
def extractor_universal(ruta_docx):
try:
doc = Document(ruta_docx)
nombre_base = os.path.splitext(ruta_docx)[0]
ruta_excel = f"{nombre_base}_DB.xlsx"
lista_dfs = []
print(f"=== ANALIZANDO: {ruta_docx} ===")
for i, tabla in enumerate(doc.tables):
matriz = extraer_matriz_segura(tabla) # Llamada a función 2
if len(matriz) < 1: continue
cabeceras = normalizar_cabeceras(matriz[0]) # Normalizar cabeceras con función 1
cuerpo = matriz[1:] if len(matriz) > 1 else []
df = pd.DataFrame(cuerpo, columns=cabeceras) # Crear el DataFrame de forma más segura
for col in df.columns: # Convertir los datos numéricos
df[col] = pd.to_numeric(df[col], errors='ignore')
lista_dfs.append(df)
print(f"Tabla {i+1}: Extraída con éxito ({df.shape[0]} registros).")
print(df.head(3).to_string(index=False))
if lista_dfs: # Exportar a Excel, formato xlsx
with pd.ExcelWriter(ruta_excel, engine='openpyxl') as writer:
for idx, df in enumerate(lista_dfs):
df.to_excel(writer, sheet_name=f"Tabla_{idx+1}", index=False)
print(f"\n[OK] Guardado en: {ruta_excel}")
except Exception as e:
print(f"\n[ERROR]: {e}")
# 4. Llamada a función principal
extractor_universal("tablas.docx")
Además de mostrar los datos por CMD, este script crea una hoja de cálculo Excel en formato .xlsx y almacena en ella las tablas en formato filas-coumnas y los datos que contienen, respetando el tipo de dato supuesto (string, numérico...). Esto tiene varias consecuencias para el tratamiento posterior:
- se puede acceder a las tablas directamente desde la hoja de cálculo, pero también desde script mediante
Pandastrabajando con los datos en función de su tipología. - el acceso se hace directamente a datos estructurados, dada la configuración de las tablas resultantes como tales, lo que facilita la manipulación de los datos mediante funciones asociadas a la biblioteca
Pandas(y otras)
Además, mediante la función 1 (def normalizar_cabeceras():) evitamos posibles errores en el posterior tratamiento de las tablas. La segunda función (def extraer_matriz_segura()) permite extraer el contenido evitando los errores que derivan de la combinación de tablas.
Pero el núcleo del script sigue siendo la función principal (la 3, def extractor_universal(), que...
- es a la que llamamdos desde el segmento de ejecución (4,
extractor_universal("tablas.docx")), instrucción donde se pasa por parámetro el archivo .docx con el que trabajamos. - Esta función principal ejecuta el recorrido del documento, obtiene las tablas que contiene y sus datos...
- ... asegurando su viabilidad mediante llamada a funciones auxiliares...
matriz = extraer_matriz_segura(tabla)ycabeceras = normalizar_cabeceras(matriz[0]))
- ... generando el dataframe (
df = pd.DataFrame(cuerpo, columns=cabeceras))... - ... y crea el archivo .xlsx (
with pd.ExcelWriter(ruta_excel, engine='openpyxl') as writer:)
El resultado es un .xlsx plenamente operativo, estructurado en hojas (una por tabla) que contienen tablas organizadas para que sus datos puedan ser tratados directamente como datos estructurados y que sea posible trabajar con ellos (consultar y manejo) manualmente, mediante lenguajes de macros o mediante python y sus bibliotecas.
Dada la simplicidad de contenido, pero sobre todo de organización de las tablas, el procedimiento de acceso a tablas y extracción de su contenido ha resultado satisfactorio, haciendo innecesario un tratamiento posterior para que sea posible trabajar directamente con el archivo resultante (.xlsx) y con las tablas que contiene.