Todo equipo de calidad de datos tiene una versión de esta tarea: “hay que corregir el mismo campo en estas 400 cuentas”. En SAP eso significa abrir el registro, cambiar el campo, guardar, y repetirlo 399 veces. Es lento, es tedioso y —esto es lo importante— genera errores nuevos mientras corriges los viejos. Tras la segunda tarde así escribí una herramienta. Esto es cómo funciona y lo que le diría a alguien que quiera hacer lo mismo.
Las opciones que no elegí
- LSMW, BAPIs, transacciones de mantenimiento masivo. Las herramientas correctas cuando las tienes. Para estos objetos no teníamos acceso, y conseguirlo era un proyecto en sí mismo.
- RPA (UiPath y compañía). Automatizan exactamente esto, pero una licencia y un servidor de bots para los lotes ocasionales de un equipo era desproporcionado.
- Macros VBS grabadas desde la SAP GUI. La GUI puede grabar tus clics como script. Perfecto para una demo, terrible en la práctica: sin validación, sin gestión de errores, y en cuanto cambia una pantalla la grabación se rompe.
Quería algo intermedio: sin sistemas nuevos ni licencias, pero con código de verdad, con pruebas, validación y registro.
SAP GUI Scripting, manejado desde Python
SAP GUI Scripting es una interfaz de automatización integrada en la SAP GUI para Windows. Cuando los administradores la activan (parámetro de servidor sapgui/user_scripting, más la opción en el cliente), la GUI en ejecución expone un objeto COM que puedes controlar: sesiones, ventanas, campos, botones, tablas. Todo lo que un usuario puede pulsar, un script puede pulsarlo, con los mismos permisos que el usuario conectado, que es justo lo que quieres para la trazabilidad.
Desde Python la única dependencia es pywin32. Un ejemplo mínimo y genérico: abrir una transacción, rellenar un campo, pulsar Intro y leer la barra de estado:
import win32com.client
sap = win32com.client.GetObject("SAPGUI").GetScriptingEngine
session = sap.Children(0).Children(0) # primera conexión, primera sesión
session.findById("wnd[0]/tbar[0]/okcd").text = "/nXD03" # código de transacción
session.findById("wnd[0]").sendVKey(0) # Intro
session.findById("wnd[0]/usr/ctxtRF02D-KUNNR").text = "0000123456"
session.findById("wnd[0]").sendVKey(0)
status = session.findById("wnd[0]/sbar").text # "Cliente 123456 visualizado" o un error
print(status)
Las rutas de findById salen del propio grabador de la GUI o del rastreador de scripting; se leen una vez y se guardan en un pequeño mapa. Esa es toda la “magia”. El trabajo de verdad está en todo lo demás.
Lo que hace que lo puedan usar otros
La primera versión era un script que solo podía ejecutar yo. La versión que usan otros departamentos tiene cuatro cosas que el script no tenía:
- Excel de entrada y de salida. Una plantilla con una fila por registro: clave, campo, valor nuevo. La herramienta la lee, la ejecuta y escribe el resultado junto a cada fila (“cambiado”, “omitido: ya tenía ese valor”, “error: registro bloqueado”). Nadie tiene que leer una consola.
- Simulación primero. El mismo código, pero se detiene antes de guardar: navega, lee el valor actual e informa de lo que cambiaría. Todo lote se simula antes de ejecutarse de verdad, y ese informe es lo que aprueba quien lo pidió.
- Validación fila a fila contra la GUI. Las hojas se quedan viejas. Antes de escribir, la herramienta compara el valor en pantalla con la columna “valor anterior”; si difieren, la fila se omite y se marca. Esta comprobación ha evitado más daños que ninguna otra función.
- Registro de cambios. Valor anterior y nuevo, clave del registro, usuario, hora, id de lote. Hace el lote auditable y, además, reversible: un lote se puede reproducir al revés.
Y la parte aburrida pero decisiva: mensajes de error en lenguaje normal, porque el usuario es un compañero de Revenue o Finanzas, no un desarrollador.
Lo que me enseñó sobre calidad de datos
- Automatizar sin validar es una forma más rápida de equivocarse. Los clics son el 20 % del código; comprobaciones, simulación y registro son el otro 80 %.
- No automatices lo que no puedas deshacer. El registro existía antes del primer lote real. Si un cambio no se puede revertir, pasa por una persona.
- La plantilla es la interfaz. La mayoría de las consultas de soporte eran sobre la hoja, no sobre la herramienta. Nombres de columna claros y una columna de “notas” ahorraron horas.
- Permisos honestos. Ejecutar bajo la sesión del propio usuario significa que la herramienta solo puede hacer lo que esa persona puede hacer. Eso es una ventaja.
Cuándo tiene sentido este enfoque, y cuándo no
Tiene sentido para lotes ocasionales de tamaño medio (de decenas a unos miles de registros) sobre objetos sin un camino de mantenimiento masivo adecuado, en un equipo sin plataforma de RPA. No tiene sentido para cargas recurrentes de alto volumen (usa la integración adecuada), para cambios que tocan apuntes financieros (busca la transacción y las aprobaciones correctas) ni si las pantallas de la GUI cambian a menudo (las rutas se desalinean).
Si estás en ese punto intermedio, unos cientos de líneas de Python y una plantilla de Excel le ahorrarán a tu equipo tardes enteras, siempre que construyas la simulación y el registro antes que los clics.