点下面,不迷路
前言
最近,接触的项目需要自动化操作SAP,所以对SAP的自动化脚本进行调查了。整理了一些函数,用于创建SAP Session和自动化登录。
实用函数
项目中使用的是Python语言,如果需要其他语言的版本可参考这里的函数。
创建SAP Session实用函数
import time
from contextlib import contextmanager
import pythoncom
import pywintypes
import win32com.client as client
LANGUAGES_WINDOW_TITLES = {
"EN": {
"MULTIPLE_LOGONS": "License Information for Multiple Logons",
"COPYRIGHT": "Copyright",
"CHANGE_PASSWORD": "SAP"
},
"ZH": {
"MULTIPLE_LOGONS": "多次登录许可证信息",
"COPYRIGHT": "版权",
"CHANGE_PASSWORD": "SAP"
},
"JA": {
"MULTIPLE_LOGONS": "多重ログオンに関するライセンス情報",
"COPYRIGHT": "著作権",
"CHANGE_PASSWORD": "SAP"
}
}
def create_connection(*, description="", mandt="", name="", password="", language="EN"):
"""
创建一个新的SAP服务器连接,并打开一个客户端窗口。
:param description: 登录描述字符串
:param mandt: 集团
:param name: 用户名
:param password: 密码
:param language: 客户端语言
:return: 返回SAP GuiConnection对象
"""
pythoncom.CoInitialize()
try:
sapgui = client.GetObject("SAPGUI")
except pywintypes.com_error as _:
pythoncom.CoUninitialize()
raise RuntimeError("检测到SAP客户端没有启动, 请启动SAP客户端后重试。")
try:
application = sapgui.GetScriptingEngine
connection = application.OpenConnection(description, True)
except pywintypes.com_error as _:
pythoncom.CoUninitialize()
raise RuntimeError("连接SAP服务器失败, 请确认连接参数和服务器状态正常后重试。")
try:
# 使用第一个未登录的Session创建一个登录的Session
session = connection.Sessions(0)
active_window = session.ActiveWindow
active_window.findById("usr/txtRSYST-MANDT").text = mandt
active_window.findById("usr/txtRSYST-BNAME").text = name
active_window.findById("usr/pwdRSYST-BCODE").text = password
active_window.findById("usr/txtRSYST-LANGU").text = language
active_window.sendVKey(0)
# 有模态窗口, Session的Children.Count表示是窗口数量
while session.ActiveWindow.Type == "GuiModalWindow":
wnd = session.ActiveWindow
title = wnd.Text # 临时保存窗口标题
# 关闭多用登录提示窗口
if title == LANGUAGES_WINDOW_TITLES[language]["MULTIPLE_LOGONS"]:
# 多用户登录是的确认选择。
wnd.findById("usr/radMULTI_LOGON_OPT2").select()
wnd.findById("tbar[0]/btn[0]").press()
# 关闭版权提示窗口
elif title == LANGUAGES_WINDOW_TITLES[language]["COPYRIGHT"]:
wnd.findById("tbar[0]/btn[0]").press()
# 修改密码窗口
elif title == LANGUAGES_WINDOW_TITLES[language]["CHANGE_PASSWORD"]:
print("自动登录失败,系统密码过期,请手动修改密码后重试。")
break
else:
# 不识别的识别的窗口
print(f"自动登录失败,遇到不识别的窗口({title}),请联系技术支持人员")
# 不关闭窗口,保持出错窗口。
# wnd.Close()
break
except Exception as ex:
raise ex
finally:
pythoncom.CoUninitialize()
return connection
def remove_session(session):
"""
关闭SAP客户端窗口。
:param session: SAP Session对象
"""
if session:
connection = session.Parent
connection.CloseSession(session.Id)
def create_session():
"""
为SAP操作任务创建独立的Session对象。
使用第一个连接的创建脚本执行的Session,如果Session的数据大于一个时,表示有脚本正在执行。
如果是用户打开有多个Session或由于执行失败导致多个Session残留时,需手动关闭多余的Session。
也可以提供接口,关闭多余的Session。
这里一个Session就是一个SAP客户端窗口。
:return: 返回SAP GuiSession对象
"""
try:
sapgui = client.GetObject("SAPGUI")
except pywintypes.com_error as _:
raise RuntimeError("检测到SAP客户端没有启动, 请启动SAP客户端后重试。")
application = sapgui.GetScriptingEngine
# 连接数等于0时,表示没有用户登录SAP客户端
if application.Connections.Count == 0:
session = None
else:
# 仅使用第一个连接的Session
session_count = application.Connections(0).Sessions.Count
# Session数量大于一则表明有脚本正在执行(后面在尝试是否可以开更多的脚本)
if session_count > 1:
raise ValueError("有脚本正在执行,请稍后重试。如果确认没有脚本在执行,请关闭多余的窗口后重试。")
else:
# 创建一个新的Session,用于执行脚本
application.Connections(0).Sessions(0).CreateSession()
# 等待新创建的Session可以访问。
# 设置超时时间
timeout = 3
while timeout > 0 and application.Connections(0).Sessions.Count <= 1:
timeout -= 0.1
time.sleep(0.1)
# 判断是否已经超时
if timeout < 0:
TimeoutError("创建执行脚本的Session失败")
session = application.Connections(0).Sessions(1)
return session
@contextmanager
def create_sap_session():
"""
创建Sap Session,即打开一个SAP GUI客户端窗口,以备执行后续的SAP操作。
"""
session = None
try:
# 在CoInitialize的范围内使用session,否则将会抛出异常
pythoncom.CoInitialize()
session = create_session()
if session is None:
raise RuntimeError("没有登录的SAP客户端,请登录后重试")
session.ActiveWindow.Maximize()
yield session
# 捕获异常可以明确判断出错原因
except Exception as ex:
print(ex)
raise ex
finally:
remove_session(session)
pythoncom.CoUninitialize()
@contextmanager
def create_sap_transaction(session, transaction_code):
"""
开启一个SAP事务。
"""
try:
session.StartTransaction(transaction_code)
yield
finally:
session.EndTransaction()
def sap_executor(handler):
"""
在SAP客户端中,自动执行SAP操作,包括执行多个事务操作。
"""
def wrapper(*args, **kwargs):
with create_sap_session() as session:
return handler(session, *args, **kwargs)
return wrapper
测试
def do_cji3(layout, *wbs_list):
@sap_executor
def executor(session, *args, **kwargs):
with create_sap_transaction(session, 'CJI3'):
try:
session.findById("wnd[1]/usr/ctxtTCNT-PROF_DB").text = "000000000001"
session.findById("wnd[1]/tbar[0]/btn[0]").press()
except:
pass
# 输入检索条件
session.findById("wnd[0]/usr/ctxtCN_PSPNR-LOW").text = ""
session.findById("wnd[0]/usr/ctxtR_BUDAT-LOW").text = ""
if layout:
session.findById("wnd[0]/usr/ctxtP_DISVAR").text = layout
session.findById("wnd[0]/usr/btnBUT1").press()
session.findById("wnd[1]/usr/txtKAEP_SETT-MAXSEL").text = "999999999"
session.findById("wnd[1]/tbar[0]/btn[0]").press()
session.findById("wnd[0]/usr/btn%_CN_PSPNR_%_APP_%-VALU_PUSH").press()
session.findById("wnd[1]/usr/tabsTAB_STRIP/tabpSIVA").select()
text = '\r\n'.join(wbs_list)
clipboard_copy(text) # 自动定义的剪贴板拷贝函数
session.findById("wnd[1]/tbar[0]/btn[24]").press()
session.findById("wnd[1]/tbar[0]/btn[8]").press()
session.findById("wnd[0]/tbar[1]/btn[8]").press()
return executor(layout, *wbs_list)
def login():
import login_info
import sys
# 自动登录,
create_connection(**login_info.get_login_info(sys.argv[1]))
def task():
# 执行SAP操作。
do_cji3(None, None)
总结
使用上的函数方便测试和其他SAP脚本的作成。
仅供参考,如有帮助不胜荣幸,请关注,点赞。
如需转载请注明出处。
本文介绍了如何使用Python进行SAP自动化操作,特别是创建SAP Session和实现自动登录的功能。文中提供了实用的Python函数,并进行了测试,旨在方便SAP自动化脚本的开发和测试。
3512

被折叠的 条评论
为什么被折叠?



