SAP Scripting Tracker 是一款实用工具,该工具能记录在 SAP 系统中的操作,并根据所选择的编程语言 (支持 PowerShell, VB.Net ,C#, Python JShell for Java 等多种语言),以脚本的方式进行回放,从而提升工作效率。SAP 曾经提供过基于 COM 技术的 SAP GUI Scripting, 但因为微软从 Windows 7 之后停止了代理(agent, 也称向导)的发布,所以 SAP GUI Scripting 也不能使用,因为 SAP GUI Scripting 依赖该技术 (详见 oss note 1633639)。所以 SAP Scripting Tracker 就成为 SAP GUI Scripting 的一个很好的替代品。
软件下载和安装
SAP Scripting Tracker 是一款自由软件,可以自由使用,软件可以在 https://tracker.stschnell.de 下载。
使用前的环境配置
软件 解压后,在根目录下面有一篇 Tracker.pdf 文档,是对该软件使用的详细说明,可以仔细研读一遍。我根据自己的理解,将最基本的使用要求说明如下:
SAP GUI 前台配置
允许使用脚本
注意,在安装 SAP GUI 的时候,要安装 SAP GUI Scripting,在 SAP GUI 中配置允许使用脚本,但取消消息提示:
设置F1和F4帮助提示框的类型
需要将 F1 和 F4 帮助提示框的样式都改成 dialog,进入系统在菜单 【Help】- 【Settings】进行设置:
SAP服务器端设置
设置 sapgui/user_scripting 参数,将 Current Value 设置为 TRUE:
点击 Display 按钮,进入下一屏幕更改。
SAP 操作的录制和回放
打开 Tracker.exe,通过 SAP GUI 进入 SAP Easy Access 界面。点击 Scripting Tracker 左上角 Scan Scripting objects 按钮 ,可以看到 SAP 登录信息已经被记录,包括 SID, Session,User 等。
切换到 Recorder 页签,点击红色的圆形按钮,开始录制。假设我们想用 F.08 查看总账科目余额的清单。当我们在 SAP 中操作的时候,我们发现软件已经将操作以脚本的方式进行了记录:
操作完成后,点击黄色的按钮,停止记录。此时,我们将 SAP 的界面重新退回到 SAP Easy Access 界面(/n),然后点击 Tracker 最左边的绿色按钮进行运行,可以看到,刚才的操作自动像录像一样回放。
通过脚本实现自动化
Tracker 默认使用的是 Antimalware scan,这个软件的方便之处就是支持多种编程语言,接下来我演示如何通过 Python 来记录脚本。如果想使用 Python 环境,在 PC 上需要安装 Python 解释器,并且需要安装 pywin32 模块。
框架代码 (Frame)
和刚才脚本稍微不同的是,并不是所有语言都是能自动回放的,如果是 C#, Python 这样的语言,Tracker 只记录在 session 中的操作,对于 session 中控件的识别需要有额外的框架代码。这些框架代码 tracker.pdf 已经帮我们写好了,对于 Python 来说,代码在帮助文件的 130 页。
为了方便后续使用,我将 Frame 的代码封装在 SapSession 模块中的 getSession函数中,代码如下:
import sys, win32com.client
def getSession():
try:
SapGuiAuto = win32com.client.GetObject("SAPGUI")
application = SapGuiAuto.GetScriptingEngine
application.HistoryEnabled = False
connection = application.Children(0)
if connection.DisabledByServer == True:
print("Scripting is disabled by server")
application = None
SapGuiAuto = None
return
session = connection.Children(0)
if session.Busy == True:
print("Session is busy")
session = None
connection = None
application = None
SapGuiAuto = None
return
if session.Info.IsLowSpeedConnection == True:
print("Connection is low speed")
session = None
connection = None
application = None
SapGuiAuto = None
return
return session
except Exception as e:
print(e)
print(sys.exc_info()[0])
finally:
application.HistoryEnabled = True
session = None
connection = None
application = None
SapGuiAuto = None
然后再回到 Tracker.exe,将脚本语言选择为 Python,用刚才同样的方法录制一遍。
在录制的过程中,tracker 已经用 python 语言记录了操作的脚本:
在 Python 编辑器中,新建一个 f08.py 文件,将刚才的代码拷贝到文件中,代码如下:
from SapSession import getSession
def runF08():
session = getSession()
session.findById("wnd[0]").maximize()
session.findById("wnd[0]/tbar[0]/okcd").text = "f.08"
session.findById("wnd[0]").sendVKey(0)
session.findById("wnd[0]/usr/ctxtSD_KTOPL-LOW").text = "Z900"
session.findById("wnd[0]/usr/ctxtSD_BUKRS-LOW").text = "z900"
session.findById("wnd[0]/usr/txtSD_GJAHR-LOW").text = "2022"
session.findById("wnd[0]/usr/txtB_MONATE-LOW").text = "01"
session.findById("wnd[0]/usr/txtB_MONATE-HIGH").text = "01"
session.findById("wnd[0]/tbar[1]/btn[8]").press()
if __name__ == '__main__':
runF08()
然后我们就可以以 Python 脚本的方式来运行了。
做一个可以录入会计凭证的脚本
录入的数据放在 excel 中 (importfile.xlsx):
因为只是一个简单的示意,所以字段比较少。有了基础的数据准备之后,我们使用 Python 的 pandas 来读取数据,并转化为由 dict 组成的列表:
def uploadData():
df = pd.read_excel("importfile.xlsx")
return df.to_dict("records")
打印的数据如下:
[{'凭证号码': 1, '凭证日期': '2022.09.05', '过账日期': '2022.09.05', '币别': 'CNY', '行': 1, '过
账码': 40, '科目': 10010100, '金额': 700}, {'凭证号码': 1, '凭证日期': '2022.09.05', '过账日期': '2022.09.05', '币别': 'CNY', '行': 2, '过账码': 50, '科目': 10020100, '金额': 700}]
通过录屏的方法生成脚本,然后对脚本稍作改造。为了防止屏幕的错误,在 SapSession 模块中增加一个函数,让屏幕回到 Easy Access 界面
def returnEasyAccess(session):
session.findById("wnd[0]/tbar[0]/okcd").text = "/n"
session.findById("wnd[0]").sendVKey(0)
以下是录入会计凭证的完整代码:
from SapSession import getSession, returnEasyAccess
import pandas as pd
def uploadData():
df = pd.read_excel("importfile.xlsx")
return df.to_dict("records")
def fiDocumentEntry():
# 获取数据
data = uploadData()
session = getSession()
returnEasyAccess(session)
# F-02 事务码
session.findById("wnd[0]").maximize()
session.findById("wnd[0]/tbar[0]/okcd").text = "F-02"
session.findById("wnd[0]").sendVKey(0)
# 会计凭证抬头
session.findById("wnd[0]/usr/ctxtBKPF-BLDAT").text = data[0].get("凭证日期")
session.findById("wnd[0]/usr/ctxtBKPF-BUKRS").text = "Z900"
session.findById("wnd[0]/usr/ctxtBKPF-BUDAT").text = data[0].get("过账日期")
session.findById("wnd[0]/usr/ctxtBKPF-WAERS").text = data[0].get("币别")
# 循环录入每一行
for row in data:
session.findById("wnd[0]/usr/ctxtRF05A-NEWBS").text = row["过账码"]
session.findById("wnd[0]/usr/ctxtRF05A-NEWKO").text = row["科目"]
session.findById("wnd[0]/usr/ctxtRF05A-NEWKO").setFocus()
session.findById("wnd[0]/usr/ctxtRF05A-NEWKO").caretPosition = 8
session.findById("wnd[0]").sendVKey(0) # 回车
session.findById("wnd[0]/usr/txtBSEG-WRBTR").text = row["金额"]
if str(row["科目"]) == "10020100": # 银行科目需要起息日
session.findById("wnd[0]/usr/ctxtBSEG-VALUT").text = row["过账日期"]
# 模拟后过账
session.findById("wnd[0]/mbar/menu[0]/menu[3]").select()
session.findById("wnd[0]/tbar[0]/btn[11]").press()
if __name__ == '__main__':
fiDocumentEntry()
参考
Tip: An Effective Way to use SAP GUI Scripting Recording | Community Chat (blueprism.com)