SAP系统定位动态元素
场景介绍
在项目中我们会遇到SAP客户端,在某个项目中需要抓取到SAP系统查出来的金额值,但是此SAP界面是根据位置来得到元素,所以位置变化,相应元素也会发生变化,且每个查询的结果位置都不在同一个坐标,如下图所示:
基于上图使用Creator操作发现以下几点问题:
此SAP页面元素是根据坐标来获取的,因为每次所在的位置不一值,所以元素也会跟着变化。
某些部门数据行数不一致,需要滑动鼠标才可见”过量吸收/不足“,并获取旁边的金额。
这些问题导致无法灵活获取目标值,此案例用来解决该类问题。
解决方案
分析目标
在Creator中通过“目标选择器”选定金额值所在的元素,该元素会有一个明显特征,ID参数上会有类似坐标的两维参数。在这里我们为了简单起见,采用第一个参数,第二个参数来描述。
第一个参数:查询到元素ID的第一个参数
第二个参数:查询到元素ID的第二个参数
根据观测SAP元素,发现"第二个参数"会根据滑动产生变化,而"第一个参数"总是不变,如下图所示。
流程思路
详细的流程思路图如下:
从以上流程思路得知采用屏幕文本查找方式来获取“金额”的相对元素。根据"第一个参数"不变,并获取同行“过量/吸收不足正常”的"第二个参数",从而来得到目标金额。
疑问:
为什么鼠标滚动是2下,不是3下,4下? 答:鼠标滚动幅度,需要根据开发者分辨率情况来定,笔者在此采用的是1920x1080分辨率,使用滚动幅度2下最佳。
流程图中是否已执行20次,为什么是20次,这个标准是哪里来的? 答:目标框3-5次滚动就可以到底,20次完成是为了保证稳定,避免后续数据增加导致无法使用
实现步骤
1.移动到目标查询结果框获取改框焦点
//移动到数据界面,确保可以进行鼠标下滑
Mouse.Move(880, 500, false,{"iDelayAfter":300,"iDelayBefore":200})
2.鼠标滚动
//鼠标滚动2下,滚动2下是为了滚动幅度大一点
Mouse.Wheel(2,"down", [],{"iDelayAfter":300,"iDelayBefore":200})
3.判断目标元素的相对元素是否存在
//判断 “过量/吸收不足正常 文本是否存在”
#icon("@res:36pat1m0-4slj-9pbm-tclq-jq5o3tsvsoun.png")
bRet = Text.Exists({"wnd":[{"cls":"SAP_FRONTEND_SESSION","title":"成本中心: 实际/计划/差异","app":"saplogon"}],"sap":{"id":"/app/con[0]/ses[0]/wnd[0]/usr"}},"过量","instr",1,10000,{"bContinueOnError":false,"iDelayAfter":300,"iDelayBefore":200,"bSetForeground":true})
结果不存在则向下循环滚动鼠标,直到出现文本“过量/吸收不足正常”
4.结果存在查找界面文本获取“过量/吸收不足正常”的元素
//存在的话获取“过量/吸收不足正常”的元素
#icon("@res:asu7tjeb-7orb-kv4c-jtmh-4h3rqmon7rml.png")
objUiElement = Text.Find({"wnd":[{"cls":"SAP_FRONTEND_SESSION","title":"成本中心: 实际/计划/差异","app":"saplogon"}],"sap":{"id":"/app/con[0]/ses[0]/wnd[0]/usr"}},"过量","instr",1,10000,{"bContinueOnError":false,"iDelayAfter":300,"iDelayBefore":200,"bSetForeground":true})
TracePrint objUiElement
5.单独拿出 id
//单独拿出 id
oldId=objUiElement["sap"]["id"]
6.拼装目标元素id
//把逗号出现的位置拿出来
iRet = InStr(oldId,",",1,false)
//因目标金额“第一个值”是36,将36替换进查找的元素中
newId = SubStr(oldId,1,iRet-2)&"36"&SubString(oldId,iRet,Len(oldId)+1)
说明:根据每个部门的元素分析,发现金额栏的“第一个参数”全是36,这时就可将“第一个参数”替换为固定值36
SubStr(oldId,1,iRet-2)&"36"
+1)
7.将新赋值的元素id放入到objUiElement
objUiElement["sap"]["id"]=newId
8.通过GetValue获取文本值
compareValue=UiElement.GetValue(objUiElement)
打印结果发现金额已经获取到了
TracePrint compareValue)

//鼠标滚动2下
Mouse.Wheel(2,"down", [],{"iDelayAfter":300,"iDelayBefore":200})
//判断 “过量/吸收不足正常 文本是否存在”
#icon("@res:36pat1m0-4slj-9pbm-tclq-jq5o3tsvsoun.png")
bRet = Text.Exists({"wnd":[{"cls":"SAP_FRONTEND_SESSION","title":"成本中心: 实际/计划/差异","app":"saplogon"}],"sap":{"id":"/app/con[0]/ses[0]/wnd[0]/usr"}},"过量","instr",1,10000,{"bContinueOnError":false,"iDelayAfter":300,"iDelayBefore":200,"bSetForeground":true})
TracePrint(bRet)
If bRet
//存在的话获取“过量/吸收不足正常”的元素
#icon("@res:asu7tjeb-7orb-kv4c-jtmh-4h3rqmon7rml.png")
objUiElement = Text.Find({"wnd":[{"cls":"SAP_FRONTEND_SESSION","title":"成本中心: 实际/计划/差异","app":"saplogon"}],"sap":{"id":"/app/con[0]/ses[0]/wnd[0]/usr"}},"过量","instr",1,10000,{"bContinueOnError":false,"iDelayAfter":300,"iDelayBefore":200,"bSetForeground":true})
TracePrint objUiElement
//单独拿出 id
oldId=objUiElement["sap"]["id"]
//把逗号出现的位置拿出来
iRet = InStr(oldId,",",1,false)
//因目标固定列是36行,将36替换进查找的元素中
newId = SubStr(oldId,1,iRet-2)&"36"&SubString(oldId,iRet,Len(oldId)+1)
objUiElement["sap"]["id"]=newId
compareValue=UiElement.GetValue(objUiElement)
TracePrint compareValue
If compareValue=""
TracePrint "过量/吸收不足正常"
Else
//发送邮件提醒
TracePrint "发送邮件提醒"
End If
Break
Else
count=count+1
If count=20
count=1
Break
Else
TracePrint "没有查到“过量/吸收不足正常,继续进行下一次循环”"
count=1
End If
End If
Loop