影刀RPA SAP系统自动化入门不用学ABAP也能操控ERP作者林焱写在前面SAP是很多制造业、零售业企业的核心ERP系统。每天有多少人在SAP里手动录入数据、跑报表、对账影刀的桌面应用自动化可以操控SAP GUI客户端不用懂ABAP不用开发接口直接录入数据、抓取报表。这篇文章讲清楚三件事SAP GUI的元素捕获为什么难、如何对付SAP的特殊控件、一个完整的SAP数据录入流程如何搭建。一、SAP GUI的自动化挑战SAP GUI是基于SAP专有协议的客户端和普通Windows程序不同有以下几个坑坑1元素ID不固定SAP GUI的控件ID会根据屏幕布局变化。同样的物料编号输入框不同事务码下ID不一样今天能用的定位明天可能失效。正确做法用影刀的图像识别功能作为备用定位再配合坐标偏移。先用文字识别找到标签文字再计算标签右侧固定偏移位置找到输入框。坑2SAP GUI脚本功能默认关闭SAP默认不允许第三方脚本操控GUI。如果影刀识别不到SAP界面元素先检查是否开启了脚本支持SAP GUI → 菜单 → 自定义 → 选项 → 可访问性与脚本 → 勾选启用脚本店群矩阵自动化突破运营极限如果这个选项是灰色的说明被SAP管理员禁用了需要找IT开通。坑3SAP的等待非常关键SAP事务处理会有明显延迟查询、过账都会有0.5-3秒不等的等待。不加等待就会点击失败。坑4特殊控件无法直接操作SAP的Grid ViewALV报表格、树形控件、导航栏不是标准Windows控件普通点击无效。二、SAP GUI元素捕获方法方法一标准桌面捕获启动影刀元素捕获悬停在SAP界面的输入框上大多数标准SAP输入框可以正常捕获到类型通常是GuiTextField或GuiCTextField属性里有Name就是输入框的字段名如MATNR表示物料号捕获到元素后输入文本指令可以直接用。方法二图像识别定位处理特殊控件# 影刀中使用Python识别SAP截图中的文字标签计算输入框坐标importpyautoguiimporttime# 找到标签物料编号的屏幕位置locationpyautogui.locateOnScreen(label_material.png,confidence0.8)iflocation:# 标签右侧80像素就是输入框![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/921ba89e7cca452db0bf7e9d3b7e2e2c.png#pic_center)input_xlocation.leftlocation.width80input_ylocation.toplocation.height//2pyautogui.click(input_x,input_y)time.sleep(0.3)pyautogui.typewrite(MAT001,interval0.05)方法三SAP GUI脚本录制SAP内置了脚本录制功能需要管理员开启工具 → 脚本录制与回放 → 开始录制录制完成后得到VBScript里面有每个操作的精确控件路径可以在影刀Python中通过COM接口调用importwin32com.client SapGuiAutowin32com.client.GetObject(SAPGUI)applicationSapGuiAuto.GetScriptingEngine connectionapplication.Children(0)sessionconnection.Children(0)# 直接通过路径操作控件session.findById(wnd[0]/usr/ctxtMATNR).textMAT001session.findById(wnd[0]/usr/ctxtWERKS).text1000session.findById(wnd[0]/tbar[0]/btn[0]).press()# 回车确认这是最稳定的SAP操作方式控件路径不受屏幕分辨率影响。三、实战案例SAP采购订单批量录入场景每天有100条采购需求要在SAP ME21N事务码中批量创建采购订单。流程设计读取Excel中的采购需求数据供应商、物料、数量、交货日期启动SAP并导航到ME21N逐行录入数据每录完一条保存记录订单号将订单号写回Excel核心代码影刀Python节点importwin32com.clientimportopenpyxlimporttimedefopen_sap_transaction(session,tcode):打开事务码session.findById(wnd[0]/tbar[0]/okcd).textf/n{tcode}session.findById(wnd[0]).sendVKey(0)# 发送回车time.sleep(1)defcreate_po(session,vendor,material,quantity,delivery_date,plant):创建一条采购订单open_sap_transaction(session,ME21N)# 填写供应商session.findById(wnd[0]/usr/subSUB0:SAPMM06E:0101/subSUB1:SAPMM06E:0111/ctxtEKKO-LIFNR).textvendor# 跳转到行项目区session.findById(wnd[0]/usr/subSUB0:SAPMM06E:0101/subSUB3:SAPMM06E:0120/subSUB0:SAPLMEPO:1111/tblSAPLMEPOTC_1111/ctxtMEPO1111-MATNR[1,0]).textmaterial session.findById(wnd[0]/usr/subSUB0:SAPMM06E:0101/subSUB3:SAPMM06E:0120/subSUB0:SAPLMEPO:1111/tblSAPLMEPOTC_1111/txtMEPO1111-MENGE[2,0]).textstr(quantity)session.findById(wnd[0]/usr/subSUB0:SAPMM06E:0101/subSUB3:SAPMM06E:0120/subSUB0:SAPLMEPO:1111/tblSAPLMEPOTC_1111/ctxtMEPO1111-EINDT[3,0]).textdelivery_date session.findById(wnd[0]/usr/subSUB0:SAPMM06E:0101/subSUB3:SAPMM06E:0120/subSUB0:SAPLMEPO:1111/tblSAPLMEPOTC_1111/ctxtMEPO1111-WERKS[4,0]).textplant# 保存session.findById(wnd[0]/tbar[0]/btn[11]).press()time.sleep(1.5)# 获取订单号状态栏status_barsession.findById(wnd[0]/sbar)messagestatus_bar.text# 从 采购订单 4500001234 已保存 中提取订单号importrematchre.search(r\d{10},message)returnmatch.group()ifmatchelseNone# 连接SAPSapGuiAutowin32com.client.GetObject(SAPGUI)appSapGuiAuto.GetScriptingEngine connapp.Children(0)sessionconn.Children(0)# 读取Excelwbopenpyxl.load_workbook(采购需求.xlsx)wswb.active result_colws.max_column1forrowinws.iter_rows(min_row2,values_onlyFalse):vendorrow[0].value materialrow[1].value quantityrow[2].value daterow[3].value.strftime(%d.%m.%Y)ifhasattr(row[3].value,strftime)elserow[3].value plantrow[4].valuetry:po_numbercreate_po(session,vendor,material,quantity,date,plant)row[result_col-1].valuepo_numberprint(f创建成功{po_number})exceptExceptionase:row[result_col-1].valuef失败{str(e)}print(f创建失败{e})time.sleep(0.5)wb.save(采购需求_已处理.xlsx)四、SAP报表自动导出temu店群自动化报活动案例很多SAP报表需要每天手动跑影刀可以自动化这个过程defexport_alv_report(session,tcode,output_file):从SAP导出ALV报表为Excelopen_sap_transaction(session,tcode)# 点击执行session.findById(wnd[0]/tbar[1]/btn[8]).press()time.sleep(3)# 在ALV Grid中导出系统菜单 → 列表 → 导出 → 电子表格session.findById(wnd[0]/mbar/menu[0]/menu[1]/menu[2]).select()time.sleep(1)# 选择以表格形式session.findById(wnd[1]/usr/subSUB_CONFIGURATION:SAPLSPO5:0200/radSPOPLI-SELFLAG[1,0]).select()session.findById(wnd[1]/tbar[0]/btn[0]).press()# 输入文件名session.findById(wnd[1]/usr/ctxtDY_FILENAME).textoutput_file session.findById(wnd[1]/tbar[0]/btn[0]).press()time.sleep(2)print(f报表已导出{output_file})五、实用踩坑记录坑1SAP超时登出SAP有会话超时设置长时间不操作会自动登出。处理方式每隔5-10分钟发送一个无害的操作如按F5刷新当前页或在流程开始时调整SAP会话超时参数。坑2弹窗拦截SAP频繁弹出确认或警告对话框。在每次关键操作后检查是否有弹窗try:popupsession.findById(wnd[1])ifpopup:# 点击确认按钮popup.findById(tbar[0]/btn[0]).press()except:pass# 无弹窗则忽略坑3中文/英文SAP界面路径不同控件路径如ctxtMATNR是固定的不受语言影响。但菜单路径menu[0]会因语言不同而位置变化。建议通过子ID而非菜单文字来定位。坑4多用户并发操作冲突SAP某些物料、凭证锁定时并发录入会报错记录被其他用户锁定。解决方案加随机延时1-3秒错开操作时间或在非高峰时段运行。总结SAP自动化的核心路径先尝试SAP脚本录制获取精确控件路径用win32com.client直接调用控件最稳处理好等待和弹窗做好异常日志SAP报错信息要记录下来不会ABAP没关系影刀 win32com SAP脚本录制就能搞定大多数SAP自动化需求。署名林焱