sap系统作为客户常用的系统,经常在不同客户的业务场景中遇到,但其中有一些操作是共用的,在这里整理出一些常见操作的模块化代码,以便之后直接调用。
1.选择sap环境
登录SAP系统前需要选定环境,但是名称是可以随意编辑的,如果按照名称来选定,万一发生更改或者环境太多重名的情况,可能会导致流程运行失败,所以最好的方式是根据环境的IP去定位,然后进行选择。
| 模块化代码: / 获取环境ip对应的目标元素 env:环境ip / Function GetEnvIP(env) //初始化 Dim sRet =”” Dim arrElement =”” Dim Elements=[] Dim element //行列展开 //获取每一列的列头元素(如果父元素有变更,可以根据某一列头元素获取父元素) #icon(“@res:default.png”) arrElement =UiElement.GetChildren({ “ctrl”: [ { “aid”:”Header”,”name”:”标头控件”,”role”:”ROLE_SYSTEM_LIST” } ],”wnd”: [ { “app”:”saplogon”,”cls”:”#“,”title”:”SAP Logon “ }, { “cls”:”AfxOleControl110” }, { “cls”:”AfxMDIFrame110” }, { “cls”:”AfxFrameOrView110”,”idx”:1 }, { “aaname”:”myContainer”,”cls”:”Afx:“,”title”:”myContainer” }, { “cls”:”SysListView32” }, { “aaname”:”标头控件”,”cls”:”SysHeader32” } ] },{“bContinueOnError”:False,”iDelayAfter”:300,”iDelayBefore”:200}) //遍历元素,左键双击展开 For Each val In arrElement #icon(“@res:default.png”) Mouse.Action(val,”left”,”dbclick”,10000,{“bContinueOnError”:False,”iDelayAfter”:300,”iDelayBefore”:200,”bSetForeground”:True,”sCursorPosition”:”TopRight”,”iCursorOffsetX”:0,”iCursorOffsetY”:0,”sKeyModifiers”:[],”sSimulate”:”message”,”bMoveSmoothly”:False}) Next //获取整个表格的每一行元素(如果父元素有变更,通过获取父元素命令重新获取) #icon(“@res:default.png”) arrElement =UiElement.GetChildren( { “ctrl”: [ { “role”:”ROLE_SYSTEM_LIST” } ],”wnd”: [ { “app”:”saplogon”,”cls”:”#“,”title”:”SAP Logon “ }, { “cls”:”AfxOleControl110” }, { “cls”:”AfxMDIFrame110” }, { “cls”:”AfxFrameOrView110”,”idx”:1 }, { “aaname”:”myContainer”,”cls”:”Afx:“,”title”:”myContainer” }, { “cls”:”SysListView32” } ] },{“bContinueOnError”:False,”iDelayAfter”:300,”iDelayBefore”:200}) //根据name值剔除表头行元素 ForEach val In arrElement If val[“ctrl”][0][“name”]<>”标头控件” push(Elements,val) EndIf Next arrElement=Elements //遍历行元素,对每个行元素,通过获取文本的方式,获取所有值。 ForEach val In arrElement //获取文本 #icon(“@res:default.png”) sRet =Text.Get(val,10000,{“bContinueOnError”:False,”iDelayAfter”:300,”iDelayBefore”:200,”bSetForeground”:True}) //筛选ip ip=Regex.FindStr(sRet,”[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+”) If ip=env element=val Break EndIf Next //返回目标ip所在的行元素。 Return element EndFunction |
|---|
获取到目标ip所在行元素后,通过点击目标的命令即可选定环境。
| //获取目标ip所在行元素 element=公共函数.GetEnvIP(g_information[“SAPEnv”]) //点击行元素 #icon(“@res:default.png”) Mouse.Action(element,”left”,”dbclick”,10000,{“bContinueOnError”:False,”iDelayAfter”:10,”iDelayBefore”:10,”bSetForeground”:True,”sCursorPosition”:”Center”,”iCursorOffsetX”:0,”iCursorOffsetY”:0,”sKeyModifiers”:[],”sSimulate”:”simulate”,”bMoveSmoothly”:False}) |
|---|
2.输入事务代码
我们在sap系统中每一步都要执行一个事务代码,这里把输入事务代码做模块化
| 模块化代码: / 执行事务代码 command:事务代码 / Function EntryCommand(command) //设置事务代码 UiElement.SetValue({“wnd”:[{“cls”:”SAP_FRONTEND_SESSION”,”title”:”“,”app”:”saplogon”}],”sap”:[{“id”:”/app/con[0]/ses[0]/wnd[0]/tbar[0]/okcd”}]},command,{“bContinueOnError”:False,”iDelayAfter”:10,”iDelayBefore”:10}) //回车执行 Keyboard.PressKey({“wnd”:[{“cls”:”SAP_FRONTEND_SESSION”,”title”:”“,”app”:”saplogon”}],”sap”:[{“id”:”/app/con[0]/ses[0]/wnd[0]/tbar[0]/okcd”}]},”Enter”,20,30000,{“bContinueOnError”:False,”iDelayAfter”:300,”iDelayBefore”:200,”bSetForeground”:True,”sKeyModifiers”:[],”sSimulate”:”message”,”bClickBeforeInput”:False}) End Function |
|---|
具体操作如下:
| 公共函数.EntryCommand(“/nOX02”) |
|---|
调用函数,输入/n+事务代码即可。
3.读取excel表
在很多场景下,需要读取excel表获取源数据,这里也做了一些模块化处理:
| 模块化代码:
/
读取Excel表
path:excel表路径
sheet:sheet表名称
startcell:起始单元格
/
Function ReadExcel(path,sheet,startcell)
//后台打开excel表
objExcelWorkBook = Excel.OpenExcel(path,False,”Excel”,””,””)
//获取行数
rRet = Excel.GetRowsCount(objExcelWorkBook,sheet)
//获取列数
cRet = Excel.GetColumsCount(objExcelWorkBook,sheet)
//判断列数大小
If cRet<26
//小于26转换为A-Z
cRet=Chr(cRet+65)
Else
//大于26,转换成AA-ZZ
//获取第一位字符
cRet1=Chr(Math.Int(cRet/26)+64)
//获取第二位字符
cRet2=Chr((cRet-Math.Int(cRet/26)*26)+65)
//如果列数大于ZZ,需要添加新的逻辑
cRet=cRet1&cRet2
End If
//读取区域
arrayRet = Excel.ReadRange(objExcelWorkBook,sheet,startcell&”:”&cRet&rRet)
Excel.CloseExcel(objExcelWorkBook,True)
//返回结果
Return arrayRet
End Function |
| —- |
具体代码操作如下:
| comdata=公共函数.ReadExcel(g_information[“数据存储路径”]&”\\公司大区对应表.xlsx”,0,”A2”) |
|---|
4.根据公司代码对相应数据处理
这里我们先举个例子:
有这样一个场景,输入事务代码后,要获取代码为1100的公司的”建议的会计年度”勾选状态(可能有多条),然后定位到目标公司代码行,设置”建议的会计年度”的勾选状态。
这里涉及到根据公司代码定位目标元素的问题,在这里,我对这一块做了模块化处理,具体分为以下这几个模块:
| 模块化代码:
/
获取表格对应的目标元素id
index:表格在父元素中的索引位置。
/
Function GetTableId(index)
//根据表格的父元素获取子元素(所有这样的表格的父元素一般保持不变,只有目标表的索引会变化,如果父元素发生变化,通过ui分析器等方式重新获取父元素)
#icon(“@res:default.png”)
arrElement =UiElement.GetChildren({ “sap”: [ { “id”:”/app/con[0]/ses[0]/wnd[0]/usr” } ],”wnd”: [ { “app”:”saplogon”,”cls”:”SAP_FRONTEND_SESSION”,”title”:”“ } ] },{“bContinueOnError”:False,”iDelayAfter”:300,”iDelayBefore”:200})
//根据index获取表的id
id =arrElement[index][“sap”][0][“id”]
//返回id
Return id
EndFunction
/
获取公司代码对应行的指定元素
parentid:表id
locatenum:点击定位按钮后,公司代码所在单元格索引
infoarr:包含元素特殊字段的列表
companycode:公司代码
reskey:包含元素特殊字段的返回值列表
/
Function ChooseRow(parentid,locatenum,infoarr,companycode,reskey)
Dim arrElement =””
Dim tabledict={}
Dim resArr=[]
//点击定位按钮
#icon(“@res:341ggsi7-susi-u8gp-4p40-ivmf0h4mn0iv.png”)
Mouse.Action({“wnd”:[{“cls”:”SAP_FRONTEND_SESSION”,”title”:”“,”app”:”saplogon”}],”sap”:[{“id”:”/app/con[0]/ses[0]/wnd[0]/usr/btnVIM_POSI_PUSH”,”aaname”:”定位“}]},”left”,”click”,30000,{“bContinueOnError”:False,”iDelayAfter”:10,”iDelayBefore”:10,”bSetForeground”:True,”sCursorPosition”:”Center”,”iCursorOffsetX”:0,”iCursorOffsetY”:0,”sKeyModifiers”:[],”sSimulate”:”uia”,”bMoveSmoothly”:False})
//判断公司代码索引,确定公司代码所在单元格
If locatenum>0
For i=1To locatenum
Keyboard.Press(“Tab”,”press”, [],{“iDelayAfter”:300,”iDelayBefore”:200,”sSimulate”:”simulate”})
Next
EndIf
//输入公司代码,查找
Keyboard.Input(companycode,{“iDelayAfter”:300,”iDelayBefore”:200,”sSimulate”:”message”})
Keyboard.Press(“Enter”,”press”, [],{“iDelayAfter”:300,”iDelayBefore”:200,”sSimulate”:”simulate”})
//遍历infoarr,初始化tabledict
ForEach info In infoarr
tabledict[info]=[]
Next
//根据表id,获取表的子元素
#icon(“@res:default.png”)
arrElement =UiElement.GetChildren({ “sap”: [ { “id”: parentid } ],”wnd”: [ { “app”:”saplogon”,”cls”:”SAP_FRONTEND_SESSION”,”title”:”*” } ] },{“bContinueOnError”:False,”iDelayAfter”:10,”iDelayBefore”:10})
//遍历表中元素,筛选包含特殊字段的元素,并插入tabledict中
ForEach val In arrElement
id = val[“sap”][0][“id”]
ForEach info In infoarr
IfRegex.FindStr(id,info)<>””
push(tabledict[info],val)
Break
EndIf
Next
Next
//目标添加到数组
For i=0 To Ubound(tabledict[infoarr[0]])
//获取公司代码文本信息
#icon(“@res:default.png”)
sRet =UiElement.GetValue(tabledict[infoarr[0]][i],{“bContinueOnError”:False,”iDelayAfter”:10,”iDelayBefore”:10})
//如果符合,就添加进数组
If sRet=companycode
reslist=[]
ForEach val In reskey
push(reslist,tabledict[val][i])
Next
push(resArr,reslist)
EndIf
Next
//返回结果
Return resArr
EndFunction |
| —- |
具体代码操作如下:
| id=公共函数.GetTableId(0)
target=公共函数.ChooseRow(id,0,[“BUKRS”,”XCOS”],g_information[“companyinfo”][“SAP编码”],[“BUKRS”,”XCOS”])
|
| —- |
其中特殊字段通过以下方式获取:
取最后一级的”-“后面的内容,这里的特殊字段一般是每个表字段特有的部分,不会重复,当然,如果有其他的不重复的字段,也是可以的,在infoarr里面,要将公司代码的特殊字段放在第一位,reskey中,只需要填入需要返回元素的特殊字段即可
如果需要返回的是文本,只需要将最后的添加内容改为文本即可。
如果大家有sap系统中其他的可重复模块,欢迎补充
