I'm trying to login to SAPGUI with Python in order to create a script to run a transaction automatically and I'm running into an issue. Whenever I try to login I get a <class 'pywintypes.com_error'>
error. I'm not sure why I'm getting this error. This is my first time trying to navigate into SAP GUI so I'm not sure if I am missing an important line to establish a successful logon or not.
We've utilized VBA previously but my coworkers have expressed interest into possibly moving our automation scripts from Excel to Python and since I'm the most experience with Python I've been tasked in getting it working.
# Importing the Libraries
import win32com.client
import sys
import subprocess
import time
# This function will Login to SAP from the SAP Logon window
def saplogin():
try:
path = r"C:\Program Files (x86)\SAP\FrontEnd\SAPgui\saplogon.exe"
subprocess.Popen(path)
time.sleep(10)
SapGuiAuto = win32com.client.GetObject("SAPGUI")
if not type(SapGuiAuto) == win32com.client.CDispatch:
return
application = SapGuiAuto.GetScriptingEngine
if not type(application) == win32com.client.CDispatch:
SapGuiAuto = None
return
connection = application.Children(0)
if not type(connection) == win32com.client.CDispatch:
application = None
SapGuiAuto = None
return
session = connection.Children(1)
if not type(session) == win32com.client.CDispatch:
connection = None
application = None
SapGuiAuto = None
return
session.findById("wnd[0]/usr/txtRSYST-BNAME").text = "USER"
session.findById("wnd[0]/usr/pwdRSYST-BCODE").text = "PASS"
session.findById("wnd[0]").sendVKey(0)
except:
print(sys.exc_info()[0])
finally:
session = None
connection = None
application = None
SapGuiAuto = None
saplogin()
Probably I'll answer more than one question. I assume that people automate SAP for long repeatable operations. Anyway the information below will be useful. Tested on SAP Client 7.20 and 7.50, Python 3.8.3.
First, you may use a config.py:
import os # for path join
SAP_SID = 'SID'
SAP_MANDANT = '1000'
SAP_USER = 'login'
SAP_PASS = 'secret'
SAP_EXE = "C:\Program Files (x86)\SAP\FrontEnd\SAPgui\sapshcut.exe"
# minimize SAP window, enable it after debugging is completed; unfortunately small windows still appear with this setting
ICONIFY = False
# screenshots for debug and visual logging
SCR_ERR = os.path.join('path', 'err_screen.png')
Second, the main script, which performs a connection, then opens a transations:
import config
import pyautogui as pya # for screenshots
import time # for count seconds for approx. measuring
import subprocess
import win32com.client
from win32gui import GetWindowText, GetForegroundWindow
def saplogin():
try:
# 1.1. Connect to SAP
subprocess.check_call([config.SAP_EXE,
'-user=%s' % config.SAP_USER,
'-pw=%s' % config.SAP_PASS,
'-system=%s' % config.SAP_SID,
'-client=%s' % config.SAP_MANDANT])
time.sleep(10) # need to ensure SAP created a session
# Get session
sap_gui_auto = win32com.client.GetObject('SAPGUI').GetScriptingEngine
session = sap_gui_auto.findById("con[0]/ses[0]") # 1 - to run the second session comment this line and uncomment the next, with con[1] and so on; probably it may work with a param stored in config
# session = sap_gui_auto.findById("con[1]/ses[0]") # 2
# session = sap_gui_auto.findById("con[2]/ses[0]") # 3
# session = sap_gui_auto.findById("con[3]/ses[0]") # 4
# 1.2. Check if dialog window appears
if session.children.count > 1:
try:
# 1.2.1 License window (this code was written for different PCs with the same ses[0];
# to run this code on the same machine it shoild be modified by adding a check for ses[1] and so on)
# Open new session if the title equals to <your title>
if (GetWindowText(GetForegroundWindow())) == "<Информация по лицензии при многократной регистрации>":
print("Title: %s" % session.children(1).text) # you may use this instead of GetWindowText in the line above
# Choose an option to create additional session
try:
session.findById("wnd[1]/usr/radMULTI_LOGON_OPT2").select()
session.findById("wnd[1]/usr/radMULTI_LOGON_OPT2").setFocus()
session.findById("wnd[0]").sendVKey(0)
except Exception as ex:
print("Cannot perform an operation (%s)" % ex)
pya.screenshot(config.SCR_ERR)
exit(1)
time.sleep(1) # for case if new dialog window appears
try:
# Now we are about to be logged. Often at this moment the system message is shown
if session.children(1).text == "<Системные сообщения>": # replace to your text
print("Title: %s" % session.children(1).text)
# in my case this window always has two lines of text; you may safely delete these two lines of code
print("%s | %s" % (session.findById("wnd[1]/usr/lbl[4,1]").text,
session.findById("wnd[1]/usr/lbl[17,1]").text))
print("%s | %s" % (session.findById("wnd[1]/usr/lbl[4,3]").text,
session.findById("wnd[1]/usr/lbl[17,3]").text))
print("The window is closed '%s', please wait..." % session.children(1).text)
session.findById("wnd[1]").sendVKey(0)
else:
# Exit if the window has unknown title
print("Title: %s. Exit." % session.children(1).text)
pya.screenshot(config.SCR_ERR)
exit(1)
except Exception as ex:
# Exit for unknown window
print("Unknown window: %s. Exit (%s)" % (session.children(1).text, ex))
pya.screenshot(config.SCR_ERR)
exit(1)
except Exception as ex:
# Finally, exit for unknown reason
print("Unknown error: %s. Exit (%s)" % (session.children(1).text, ex))
pya.screenshot(config.SCR_ERR)
exit(1)
print("Logged to SAP.")
return session
except Exception as ex:
print("Error. Cannot create session. Exit (%s)" % ex)
pya.screenshot(config.SCR_ERR)
exit(1)
def export_npp(session, params):
# 2.1. Start counter (for those who cares about statistics and measuring)
start = time.time()
if config.ICONIFY:
# minimize main window
session.findById("wnd[0]").iconify()
else:
# or resize it
session.findById("wnd[0]").resizeWorkingPane(84, 40, 0)
# 2.2. Open transation
session.findById("wnd[0]/tbar[0]/okcd").text = 'transaction'
session.findById("wnd[0]").sendVKey(0)
"""
startx = time.time()
'doing some repeatable stuff'
finish = time.time()
total_time = finish - startx
print("Time %02d seconds added to dict" % total_time)
"""
total_finish = time.time()
total_time = total_finish - start
print("Total: %02d seconds" % total_time)
# Begin, start session
ses = saplogin()
# Use params of session to use it in transaction 'export_npp' and so on
npp = export_npp(ses, params)