Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
ArthurYang
Product and Topic Expert
Product and Topic Expert

本文档内容是基于我个人对SPA的理解产生的,目的是帮助您进一步了解SAP流程自动化 (SAP Build Process Automation 简称SPA) 的开发方式,阅读时间约为1小时。

 

 

 

本文档面向的人群是拥有1年及以上代码开发经验的开发者。


 

本文档主要基于初步练习的结果来分享实战调优方面的内容,包括:


1.如何更好的抓取Screen/Element;

2.如何应对网页/SAP系统可能的卡顿;

3.如何利用脚本从字符串中提取数据;

4.如何将文件在不同日期以不同名字保存;

5.常见优化方式的经验分享;

6.一次读取Excel内的大量数据;

 

 

 

 

如果您对BTP感兴趣,BTP个人精选内容目录 | SAP Blogs 可能有更多你需要的内容


 

这里是上一篇中流程搭建的结果


全过程包括了:

打开一个新的excel,再打开外汇管理局网址

抓取汇率列表,并遍历所有汇率的LI控件,先获取text,再将text推入当前的excel内

最后保存excel

 

但这样一个简单的汇率抓取流程,要真正用到实战中还存在很多问题,

1.稳定性上:网页加载可能会卡顿;网页出现了但是元素加载卡顿;现在读取到的数据是一整行的文字而非可以直接录入系统的数据;Excel文件另存为时可能遇到文件已存在的情况

2.易用性上:每天运行的Excel是否需要分别以不同的名字存储起来?

 

这里分享一些我自己常用的方法来解决这些问题,其实还有很多控件都可以辅助解决,只是我个人用这些方式比较顺手,给大家做一些参考。


 

 

1.如何更好的抓取Screen/Element;

 

1.1抓取容易消失的弹窗等页面元素


因为我们在抓取页面元素时需要将其打开,再切换到开发界面来进行抓取,而有些元素在切换页面时就会发生变化,这个时候我们可以借助手动的捕获工具来抓取这类元素

在添加屏幕的弹窗中,选择”捕获工具”这个页签

 

等待捕获工具的小弹窗出现之后,切换到需要捕获的页面,打开需要捕捉的元素后马上 按住Ctrl并将鼠标移动至目标元素上,等待红框出现后松开Ctrl,此时开发界面就会开始捕捉红框内的元素


和标准的“捕捉已检测到的屏幕”方式比较,最大的区别就是可以捕捉那些转瞬即逝的页面元素。

 

1.2当元素完全无法抓取,如何使用坐标的方式去点击


SPA识别元素的方法很多,除了直接利用其属性来识别,还可以利用其父结构识别(在先前的练习已经演示过)

SPA支持通过坐标去点击界面上的某个点,如果存在实在无法抓取的元素A,最后可以考虑通过定位A附近的元素B,通过Get Rectangle获取到B的坐标后,去通过Mouse Left Click等控件去点击A

整个屏幕的最左上角为坐标轴的原点,其坐标为(X:0,Y:0)

Get Rectangle会获取到目标元素最左上角坐标的X和Y值,同时会获取到元素的宽cx和高cy,这样我们就可以利用数值组合来点击到目标元素,但是该方法不够稳定,一般只在万不得已的情况下使用

 

1.3 当Screen难以区分时如何识别


首先,有些时候,如果两个Screen的Attribute基本完全一致,那么他们就应该被认为是同一个Screen,应该作为同一个Screen的两个捕获来抓取

其次,如果需要分开,可以利用A,B两个Screen中不同的元素来区分,例如将A中必然存在,B中必然不存在的某个元素在A中识别出来,将其标记为"必须存在",再将其拖入B屏幕中,标记为"必须不存在",这样机器人就可以更好的识别Screen

 

1.4 实时测试元素是否被识别,以及测试控件对元素的操作效果

 

在应用程序页面内,左上角的开始键可以打开页面测试器,测试当前电脑打开的页面是否被识别,进而查看该页面内识别除了多少元素,以及这些元素包含哪些属性

 

最后还可以对这些元素尝试不同的控件操作并查看结果,这样可以实地检验控件选择的合理性


 

2.如何应对网页/SAP系统可能的卡顿


无论网页卡顿或是元素卡顿,机器人这种无侵入性的技术都无法加快这个进度,我们只能模拟人再遇到这种情况下的操作:等待。

而等到什么时候呢? 那只需要等到这个页面出现,并且我们需要操作的元素也出现就可以继续流程了,一般网页出现但元素加载缓慢这个现象比较常见,所以这里以此为例,通过加入Wait Element控件,来让机器人等到汇率元素出现再继续操作:


将控件纳入流程后,点击该控件,在右侧编辑其属性


这样,机器人会在识别到汇率元素集合中的第一个元素时,才继续运行,这样就避免了元素加载过慢导致机器人抓不到数据的问题

 

在开发SAP GUI流程时遇到页面卡顿,可以通过控件获取GUI的状态是否卡顿,如果卡顿则持续进行等待,直到session恢复正常再继续流程,大体上如下图所示


 

 

3.如何利用脚本从字符串中提取数据


 

机器人现在抓取到的数据是类似这样的:


而这样的字符串显然不适合直接填入系统,我们需要从整体的字符串中提取出数据该怎么做呢?首先可以直接去声明更深层次的元素,以抓取到目标数据,其次呢,我们还可以利用脚本从这样固定格式的字符串中提取出我们需要的数据,

放到流程中,就是在获取到字符串之后,将其传入自定义脚本控件,再将解析完的结果传出,送给Push Value用以放入Excel中


接下来双击流程中的脚本控件,来编辑细节,先添加脚本中要使用的输入输出变量:


这里涉及到Javascript的编程内容,对于没有代码基础的同学可能比较晦涩,我们只需要知道这个脚本接收一段文字,然后将其分割成4段后输出就可以了:

return input.split((/[\s]/));

 

再点击流程空白处,将脚本的输入设置为Get Element的输出


现在我们获得了分割后的数组,就不需要Push原字符串到Excel内了,将脚本的输出Push进去即可:


此时再运行流程,Excel内的数据就会变成这样:


我们甚至可以在Excel刚创建出来的时候就将字段名称Push进去,这样可读性会更高。

 

4.如何将文件在不同日期以不同名字保存


 

现在的流程结尾会将Excel文件存储为固定的名字,这样重复运行机器人时会遇到“该文件已存在”的错误,针对这个问题有多种解决方案:可以在流程初始阶段检查文件是否存在,若存在则删除;可以将文件存储到新创建的当日文件夹等等,

这里选择简单的将文件根据时间存储为不同的名字来解决这个问题:

 

首先我们需要获取到流程运行当时的时间,那么在Save As Workbook之前加入一个脚本控件用以获取该信息,该脚本不需要输入,输出一个now的字符串变量:

 

var temp=new Date();

var temp2=temp.getFullYear()+'-'+String(temp.getMonth()+1)+'-'+temp.getDate()+'-'+temp.getHours()+'-'+temp.getMinutes();

return temp2;

 


 

然后利用这个now变量来组成被保存的Excel的名字:

"C:\\Users\\Public\\" + Step9.now + ".xlsx"

 


这样最后存储的Excel文件名就会是流程运行的当前时间。

 

5.更多优化方式的经验分享


 

 

优化到这里,该流程已经基本能用了,简单的修改一些命名之后,流程长这样:


 

当然了,为了让流程更加鲁棒,在各种不同情况下都能运行,我们还可以快速的添加许多功能,例如:

为防止保存文件时遇到重名文件,可以在流程的最前端添加文件检查;

要存储多个文件时,可以创建当日文件夹,并将所有文件都存进该文件夹;

需要用户自定义流程参数时,可以在本地Excel文件或者代理内存储一些变量,然后在流程最前端读取;

为防止流程启动前应用已打开并停留在不同页面,可以在流程最前端检查应用是否存在,若存在则关闭应用,这样保证应用都是从头打开的;

6.读取Excel内的大量数据


当我们要读取的Excel在数十行的程度时,还可以使用控件来操作,但如果内容超过数十行,我们可能就要借助专门的控件Excel Cloud Link来一次性读取大量数据了:

首先搜索并拉出一个Excel Cloud Link到流程中:


双击它之后,会发现配置内容比较多,我们一个一个来,首先将要读取的文件Sample拖进左侧方框(我们先前保存的汇率结果Excel是不含第一列表头的,之后我们可以在创建Excel的时候直接将表头Push进Excel)


我这里使用的是含表头的汇率结果:


拖入后的界面如下:


其中,设计参数都是来自Sample Excel文件,只需要选对工作表即可

执行参数相对复杂一点,其中,

    • 范围定义(即要读取的数据范围)目前是一个常数,但是当我们要读取的Excel超过3行时,我们就应该读取一个动态的范围,也就是Excel的每一行,所以应该在Excel Cloud Link之前打开目标Excel,并通过Get UsedRange Row来获取该Excel的行数,这样范围定义就会是[”A1:D”+行数], 也就是会读取新文件第一到四列的所有行内容、

 

    • 工作簿路径,即我们要读取的路径+Excel文件名,和Open Excel需要的一致

 

    • 工作表名称,即我们要读的Sheet名,默认为Sheet1

 

    • 数据参数:在我们确定要读取文件的路径,文件名,工作表,表内的数据范围之后,我们还需要确定这些数据在读取后会变成什么格式,所以我们要先建立起数据格式,点击图中所示的 “+自Excel数据”



 


直接点击创建后,离开流程编辑页面,从左边侧边栏找到 数据类型-刚刚设定的名称,可以看到只包含了一个默认变量叫做varName


然后咱们针对目标数据,来新建字段(点击字段后在右侧编辑其属性),让该数据类型变成这样:


然后回到流程编辑页面,就会看到刚刚创建的数据类型出现在了执行参数右侧


最后将数据参数下的长方形拖到右侧 在此处映射上,就可以建立映射关系,重复四次操作

(如果取消勾选"由标题行名称定义的列",则左侧的excel表头列名就会变成ABCD列,意思是根据列号和目标数据类型匹配,而非根据表头名,但是这个时候Excel Cloud Link不会将第一行视为表头并跳过,所以这个时候如果excel包含表头,范围定义就需要从A2开始)

最后执行该流程,在完成汇率抓取及保存之后,看看Excel Cloud Link读取出来了什么:(右侧显示的输出参数其实是真实输出数据的一个子集,但是在数据量小的时候看上去是全集)


整个Excel Cloud Link的配置如下图:


这样我们就可以继续使用脚本来批量处理这些汇率信息了,例如我们要找出汇率比较超过5的币种,我们又发现所有人民币的金额都是100,那么我们可以将Excel Cloud Link读取出来的变量交给后续的脚本,用以下代码来返回那些汇率超过5的部分:

 

var output=[];

for (var i = 0; i < input.length; i++) {

if(input[i].金额1 > 500 || input[i].金额2 >500){

output.push(input[i]);

}

}

return output;

 

 


 

 

以上都是我个人一些粗浅的经验,实际上基于丰富的控件我们可以实现更多的逻辑来适配更多业务需求,希望这些内容可以对大家有所帮助。


 

其他深度用法在这里就不做赘述了,请在blogs.sap.com上搜索内容和这里的深度用法Template ,关于本文内容有任何问题或见解,欢迎在评论区留下你的想法,如果时间紧迫,也可以直接联系到我 arthuryang1996@foxmail.com,感谢你的时间

1 Comment