Visual basic Script para automatizar tareas

Buenas a tod@s

Una curiosa y extraña especialidad por mi parte en mi experiencia en SAP es que dejen su interfaz visual con posibilidad de interactuar con scripts escritos en Visual Basic.

Es decir, trabajar el script como si fuera un usuario moviendo el ratón.

¿Para qué vale?
Por ejemplo, tienes una lista enorme de lotes de inspección que sabes ya que todos son OK, y tienes que ir uno a uno aceptando los lotes y pasándolos al jefe de área para que los finelice y los deje libre para Almacén.

Pues se genera un script de aceptación masivo y ves como la pantalla va aceptando a gran velocidad cada lote uno a uno como si de un usuario fuera.

Iré recuperando algunos scripts, hice muchos potentes que iban desde listas hasta imprimir etiquetas y los iré poniendo en este tema para automatizar cosas sin necesidad de pedir que te hagan una transacción en abap

7 Me gusta

Por ejemplo, meter resultado OK en un lotes de inspección

If Not IsObject(application) Then
   Set SapGuiAuto  = GetObject("SAPGUI")
   Set application = SapGuiAuto.GetScriptingEngine
End If
If Not IsObject(connection) Then
   Set connection = application.Children(0)
End If
If Not IsObject(session) Then
   Set session    = connection.Children(0)
End If
If IsObject(WScript) Then
   WScript.ConnectObject session,     "on"
   WScript.ConnectObject application, "on"
End If
session.findById("wnd[0]").maximize
session.findById("wnd[0]").sendVKey 4
session.findById("wnd[1]/usr/cntlTREE_CONTROL_AREA/shellcont/shell").selectItem "          5","1"
session.findById("wnd[1]/usr/cntlTREE_CONTROL_AREA/shellcont/shell").ensureVisibleHorizontalItem "          5","1"
session.findById("wnd[1]/usr/cntlTREE_CONTROL_AREA/shellcont/shell").doubleClickItem "          5","1"
session.findById("wnd[0]/usr/tabsEE_DATEN/tabpSISP/ssubSUB_EE_DATEN:SAPLQEEM:0202/subSUB_EE_FCODE:SAPLQEEM:5300/btnCLOSING").press
session.findById("wnd[0]/tbar[0]/btn[11]").press

Como véis, es usar los identificadores de pantalla, y realizar la acción enviándoles el valor.
acciones como: press, doubleClickItem, maximize etc.

Este es solo un ejemplo, luego iré diciendo paso a paso qué son cada cosa y como se obtienen los identificadores del sapgui de la pantalla

8 Me gusta

Muy interesante… pero., podrías explicar mejor como preparar SAP para aceptar estos macros que viajan desde VB hacia SAP?

2 Me gusta

La idea es interesante, la verdad yo automatizo varios procesos pero no con VBS porque me parece poco seguro.
Yo uso un lenguaje basado en BASIC llamado AutoIT el cual te también te permite capturar el windows handle y el ratón

Actualmente tengo una pequeña app que levanta y baja las instancias de SAP cuando inicia o se apaga el Servidor generando un log

Adicionalmente a esta alternativa, ¿porque hacerla por VBS y no por SHDB?

Me parece interesante el tema así que estaré pendiente a ver que mas se comenta (:

2 Me gusta

Me parece muy interesante, aunque actualmente no soy programador, creo q en los inicios uno se mete en todo lo que se presenta… volviendo al tema considero q es un buen aporte… gracias

1 me gusta

Yo mezclaba también algunos eventos que no soporta la gui de sap con el autoit, pero el vbs está más directo sobre la gui por eso sap da permisos para interactuar con él. Tú generas el código en un txt, luego lo renombras a vbs y le das doble click con la ventana de sap abierta, y el script interactua con la gui de SAP

4 Me gusta

Ahí va un ejemplo de una aceptación completa que hice de listas de lotes de inspección, para dar el resultado y luego cerrarlos.

If Not IsObject(application) Then
   Set SapGuiAuto  = GetObject("SAPGUI")
   Set application = SapGuiAuto.GetScriptingEngine
End If
If Not IsObject(connection) Then
   Set connection = application.Children(0)
End If
If Not IsObject(session) Then
   Set session    = connection.Children(0)
End If
If IsObject(WScript) Then
   WScript.ConnectObject session,     "on"
   WScript.ConnectObject application, "on"
End If
session.findById("wnd[0]").maximize
i=0
j= session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").RowCount
Do While (i<j)
	session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").setCurrentCell i,""
	session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").selectedRows = i
	session.findById("wnd[0]/tbar[1]/btn[44]").press
		session.findById("wnd[0]").sendVKey 4
		session.findById("wnd[1]/usr/cntlTREE_CONTROL_AREA/shellcont/shell").selectItem "          5","1"
		session.findById("wnd[1]/usr/cntlTREE_CONTROL_AREA/shellcont/shell").ensureVisibleHorizontalItem "          5","1"
		session.findById("wnd[1]/usr/cntlTREE_CONTROL_AREA/shellcont/shell").doubleClickItem "          5","1"
		session.findById("wnd[0]/usr/tabsEE_DATEN/tabpSISP/ssubSUB_EE_DATEN:SAPLQEEM:0202/subSUB_EE_FCODE:SAPLQEEM:5300/btnCLOSING").press
		session.findById("wnd[0]/tbar[0]/btn[11]").press	

	session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").setCurrentCell i,""
	session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").selectedRows = i
	session.findById("wnd[0]/tbar[1]/btn[41]").press
		session.findById("wnd[0]/usr/tabsUD_DATA/tabpBB").select
		session.findById("wnd[0]/usr/tabsUD_DATA/tabpBB/ssubSUB_UD_DATA:SAPMQEVA:0102/txtRQEVA-VMENGE01").text = session.findById("wnd[0]/usr/tabsUD_DATA/tabpBB/ssubSUB_UD_DATA:SAPMQEVA:0102/txtRQEVA-ZUBUCHMG_F").text
		session.findById("wnd[0]/usr/tabsUD_DATA/tabpBB/ssubSUB_UD_DATA:SAPMQEVA:0102/txtRQEVA-VMENGE01").caretPosition = 1
		session.findById("wnd[0]").sendVKey 0
		session.findById("wnd[0]/usr/tabsUD_DATA/tabpPLMK").select
		session.findById("wnd[0]/mbar/menu[1]/menu[0]").select
		session.findById("wnd[0]/mbar/menu[1]/menu[4]").select
		session.findById("wnd[1]/usr/cntlTREE_CONTROL_AREA/shellcont/shell").expandNode "          2"
		session.findById("wnd[1]/usr/cntlTREE_CONTROL_AREA/shellcont/shell").topNode = "          1"
		session.findById("wnd[1]/usr/cntlTREE_CONTROL_AREA/shellcont/shell").selectItem "          3","1"
		session.findById("wnd[1]/usr/cntlTREE_CONTROL_AREA/shellcont/shell").ensureVisibleHorizontalItem "          3","1"
		session.findById("wnd[1]/usr/cntlTREE_CONTROL_AREA/shellcont/shell").doubleClickItem "          3","1"
		session.findById("wnd[0]/tbar[0]/btn[11]").press
	
	i=i+1
Loop

session.findById("wnd[0]/tbar[1]/btn[14]").press
2 Me gusta

eso referencia a una ventana popup que aparece, y wnd[0] es la ventana principal

1 me gusta

Primero lo que se debe hacer es grabar la operación que debe ser repetitiva y te interesa que se haga automática.

Para eso vas al inicio de la pantalla sap. le dais al botón del menú superior que parece un televisorcito con tres colores llamado “customize local layout”

Aparece un menú y hay una opción que se llama Script Recording and playback

te sale una ventanita con la opción de grabar, pones el fichero vbs a exportar y pulsas en grabar.

IMPORTANTE: ahora realizas la acción que sabes que vas a repetir siempre de la misma forma de una lista. Por ejemplo, poner resultado positivo a un lote de inspección.

Le das a parar y abres el fichero VBS

A partir de ahí, ves los identificadores raros que tienen los botones y eso, pero ya tú, como programador, te vas a cualquier manual de VBS y le añades que realice un bucle, que te muestre un mensaje, pones inputs de control por si quieres que te pregunte si quieres opcion ok o opcion nok, etc.

Resumen, grabas la macro, y luego a partir de ella lo vas mejorando para convertirlo en un script interactivo y repetitivo

3 Me gusta

Gracias Jesus, pero… y en SAP?
SAP acepta directamente por defecto lo que le diga la macro? :thinking: :scream:

2 Me gusta

Exacto, es una herramienta peligrosa, pero SAP se proteje con los permisos. Básicamente es para repetir una acción que ves que tienes que hacer 100 veces al día igual, que es una pérdida de tiempo, pues eso lo logras hacer en segundos.

Piensa que solo es interactuar con la interfaz gráfica de SAP, no es entrar en sus tablas ni su código, entonces es como si fuera un usuario super rápido, jejeje

Yo a algunos scripts, según el estado del lote, le ponía un msgbox con opciones para escribir cosas en los inputs de sap. puedes hacerlo muy interactivo

3 Me gusta

@Jesus_Torres para entender mejor los códigos que nos compartes. Son solo para procedimientos repetitivos, no permiten carga de datos?

Por ejemplo, en caso de querer cargar un listado de usuarios nuevo (no existe ninguna transacción estándar para esto) tengo que agregar un id, nombre, apellido únicos ahi seria usando .text = ??

Hola,
Para mi han sido muy practicos, este es para agregar materiales en la CC01, etiqueta de materiales, ya que el sistema no permite pegar masivamente los mateirales. :slight_smile:

'Llamar archivo de excel -
 
Dim objExcel
Dim objWorkBook
Set objExcel = CreateObject("EXCEL.APPLICATION")
 
 
'Colocar la RUTA
 
Set objWorkBook = objExcel.Workbooks.Open("C:\Users\carabde\Documents\Datos\Script\CC01\Hoja_.xlsx")
 
 
'Colocar la hoja de excel
 
Set Hoja=objWorkBook.Sheets("Hoja1")
objWorkBook.Sheets("Hoja1").Select
objExcel.visible=true
 
 
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Invocar la transaccion.
 
 
If Not IsObject(application) Then
   Set SapGuiAuto  = GetObject("SAPGUI")
   Set application = SapGuiAuto.GetScriptingEngine
End If
If Not IsObject(connection) Then
  Set connection = application.Children(0)
End If
If Not IsObject(session) Then
   Set session    = connection.Children(0)
End If
If IsObject(WScript) Then
   WScript.ConnectObject session,     "on"
   WScript.ConnectObject application, "on"
End If
 
'Se debe reemplazar el código de la transacción
 
 
 
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Inicializar variables. Colocar en intfila la primera fila del excel
 
Hoja.Select
 
intFila=2
 
'Colocar el nombre de la primera variable y que esté en la columna A
 
MATERIAL=Hoja.Range("B" & intFila).value
 
while MATERIAL <> ""
 
'Colocar todas las variables a utilizar y la columna de cada variable
 
	MATERIAL=Hoja.Range("B" & intfila).value
	            
 
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'PEGAR Y REEMPLAZAR LOS PASOS GRABADOS EN EL SCRIPT PROPIO hasta el comando infila=intfila+1.
'Se debe reemplazar los nombres de las variables sin utilizar ""

session.findById("wnd[0]/usr/tabsTS_OBJEKTE/tabpUEMT/ssubDETAIL:SAPMC29C:0240/subBUTTONS:SAPMC29C:0500/btnPUSH_ERFA").press
session.findById("wnd[0]/usr/tabsTS_OBJEKTE/tabpUEMT/ssubDETAIL:SAPMC29C:0240/tblSAPMC29CTCO/ctxtRC29A-MATNR[0,1]").text = MATERIAL
session.findById("wnd[0]/usr/tabsTS_OBJEKTE/tabpUEMT/ssubDETAIL:SAPMC29C:0240/tblSAPMC29CTCO/ctxtRC29A-MATNR[0,1]").setFocus
session.findById("wnd[0]/usr/tabsTS_OBJEKTE/tabpUEMT/ssubDETAIL:SAPMC29C:0240/tblSAPMC29CTCO/ctxtRC29A-MATNR[0,1]").caretPosition = 0
session.findById("wnd[0]").sendVKey 0
 
intFila=intFila+1
 
WEND
5 Me gusta

Hola SidV,
Funciona como una LSMW con la ejecución online, si el usuario tiene permisos para la transacción y los objetos entonces puede ejecutar la macro (que emula la interacción del usuario con SAP)

3 Me gusta

Hola nicolasegp,
Tienes que grabar el script en Sap de cualquier transacción, por ejemplo alta de usuario, y luego te armas un Excel donde vas a cargar toooodos los usuarios que quieras en una hoja (con los datos a completar en SAP) y te creas una macro que vaya leyendo tu Excel y ejecutando el script que grabaste en SAP.
Es buenísimo!

4 Me gusta

Esta macro valdria para lotes con 2 operaciones que a su vez tienen 4 o 5 caracteristicas maestras?

Buenas noches a todos, ¿cómo están?
Estaba leyendo este artículo y me pareció muy interesante, ya que hay muchos procedimientos repetitivos que tornan molestos!
Pero me genera una pequeña duda, ¿por qué no usar batch-input para este proceso?

1 me gusta

Hola, @Reatiga19,
Yo como mucho se hacer macros en visual basic que entiende SAP, pero no se exactamente que es un batch-imput :sob: y menos como hacerlo

Hola @renatondo ¿cómo estás?
Es cierto que ya que manejas la herramienta es una ventaja que tienes con el visual basic. Y te la apoyo, incluso me gustaría aprenderla para tomar provecho también.
Y referente a esto:

El batch-input es una herramienta que tienes en SAP, se usa para realizar una grabación de una acción en específico, por ejemplo, cargar ciertos datos repetidas veces para trabajadores diferentes, o agregar ciertas cosas en algunas transacciones en forma de lotes.

Se que no me daré a entender, ya que soy pésimo explicando, pero haré mi mayor esfuerzo… XD

El batch-input es una carga por lotes, simulando que el usuario (algo así como lo que propones con el VB) está realizando el proceso una y otra vez. Se realiza una grabación del proceso la primera vez, a través de la transacción SM35 y luego se juega un poco con el código en ABAP y se seleccionan los campos a llenar.
Y después por medio de un archivo TXT (grabado con tabulación) se sube a una transacción creada y estos serán los datos que llenara en la grabación cada vez que la ejecute.

Quizás suena enredado y loco (o quizás no sé cómo explicarlo bien jajajaja) pero es algo sumamente sencillo, después del primero los demás son fáciles.

Aunque he leído que no suelen ser tan eficaces porque repite el proceso n veces, siendo n la cantidad de registros que subas en el archivo TXT, y por consiguiente es más recomendable el uso de BAPIs (pero de estás si desconozco).

Un abrazo, espero haber ayudado en vez de haberte confundido más jajajaj

Hola @Reatiga19.
Lo del bath-imput entonces es la herramienta para hacer “macros” al estilo excel, pero desde SAP?.
Si es asi, ya la conozco, aunque no he practicado mucho.
Por mi trabajo en el area de excel tiendo a llamar a casi todo lo que se puede programar como “macros” aunque realmente no se llamen asi. :blush:

1 me gusta