一、需求概述
1、报表拆分
(1)用户手动输入信息
人工启动流程后,会弹出输入框,用户需要根据输入框的提示输入相应的数据。这些数据会被RPA机器人获取到,为后面的流程执行提供条件,所需要输入的条件有:
1)字段表头所在行:意思是机器人根据获取的行数到报表的第几行,也是对这一行往下的数据进行拆分
2)拆分字段名称:意思是机器人根据人工输入的字段名称去第几行的哪个字段进行拆分
3)拆分Sheet页名称:意思是机器人根据人工输入的名称去哪个Sheet页对其的表格进行拆分(如果输入的Sheet名称在文档里不存在,那么默认去第一个Sheet页对其进行拆分)
4)拆分后追加文件名:意思是在拆分出来的文件名后面追加说明
注:启动流程后,必须在所有的输入框内输入内容
(2)根据用户输入的数据对报表进行拆分 注:仅支持Excel文件类型的报表
被RPA机器人获取到的数据会作为拆分报表的依据。机器人会到指定的文件目录,对文件目录下的所有Excel文件进行读取并根据条件去到每个Excel文件下指定的Sheet页对其表格进行拆分。拆分后获得文件会保存到指定文件路径中
(注:拆分后的报表除了拆分的维度不一样之外,表头和说明的内容需均一致)
(3)发送邮件通知业务人员拆分结果
当对文件目录下的所有Excel文件拆分完毕时,机器人就会将发邮件给业务人员,通知文件已经拆分完毕。邮件主题和内容可自定
2、自动化发送邮件
(1)用户手动输入信息
人工启动流程后,会弹出输入框,用户需要根据输入框的提示输入相应的数据。这些数据会被RPA机器人获取到,为后面的流程执行提供条件,所需要输入的条件有:
指定工作表名:意思是机器人所去Sheet页面的名称
注:启动流程后,必须在所有的输入框内输入内容
(2)根据条件打开文件中的指定的Sheet页
机器人打开指定文件目录获取邮件报表并跳转到指定Sheet页
邮件报表:该报表由人工维护,该报表包含的字段含义如下作出说明
邮箱地址:即需发送的邮箱地址,可支持多个地址
邮件主题:由人工维护
收件人名称:即邮件内容的开头称呼
邮件内容:由人工维护
附件1:至少有一个附件,所有附件都存放到同一个文件目录(文件路径待定),RPA根据附件名称去模糊匹配,如下图所示,需要获取北京0路或者北京分公司或北京门头沟分支机构等二级单位来模糊匹配(注:每次需要发送时需清空文件夹,避免将旧的附件进行发送)
附件2:规则与附件1一致,如果为空则不用获取附件
附件3:规则与附件1一致,如果为空则不用获取附件
附件4:规则与附件1一致,如果为空则不用获取附件
附件5:规则与附件1一致,如果为空则不用获取附件
备注栏:人工备注便于查看,RPA无需处理
是否发送:如果为“是”则此条内容需要邮件发送,如果为“否”,则无需邮件发送
(3)根据表格的内容发送邮件以及附件
邮件发送完毕后,RPA通过邮件反馈表将自动发送邮件的结果给业务人员,在邮件报表后新增一列“是否发送成功”的字段,如发送成功则回填“是”,如发送异常则回填“否”,如不发送则回填“不发送”
表格:
二、项目实现思路
虽然该需求看起来要求比较多但实现起来基本就两三个组件即可
1、报表拆分
(1)获取用户输入的数据,并判断用户输入的数据是否存在空值。如果为空就中断。
(2)检查和创建目录
获取入参_需拆分文件目录和入参_拆分后文件保存目录,并判断这两个地址的末尾字符串是否为‘/’,不是就加一个上去。在拆分后文件保存目录下再创建一个目录用来保存拆分后的文件
(3)遍历需拆分文件
遍历需拆分文件目录下的所有Excel文件,将每个文件都进行拆分处理。
S_扩展名 = '*.xls*'
sList = 创建字符串列表()
获取文件列表(入参_S_需拆分文件目录, S_扩展名, sList)
trace('当天需拆分文件数量:' + inttostr(sList.count))
可通过上述脚本获取到指定目录中excel文件存在个数
(4)拆分前的检查
检查 需拆分文件 是否被打开,并关闭Excel与WPS进程
检查指定文件是否已经打开,如果打开就提示用户手动关闭,如果用户在指定时间内未能手动关闭,就终止组件。在用户手动关闭后再次对程序进行关闭,以免手动关闭没有完全关闭程序
中文脚本模板:
for I_Fileused_Count = 1 to 3
[
B_文件使用结果 = 文件是否被使用(S_需拆分文件)
if B_文件使用结果
[
trace('-----检测到已打开的Excel文件,请先关闭Excel')
B_用户确认结果 = 等待用户确认('请先关闭Excel', '检测到文件”' + S_需拆分文件 + '“已被打开,请先手工关闭,并点击”确定“按钮', ['确定', '取消'], '流程执行用户', 600, 返回)
if not B_用户确认结果
[
返回 = 设置指标('严重', '取消或超时,10分钟内未关闭Excel,请重新执行流程', '')
Trace(返回)
Exit
]
if (返回 = '确定') and (I_Fileused_Count <> 3)
[
continue
] else if (返回 = '取消')
[
返回 = 设置指标('严重', '已取消,请根据需要是否重新执行流程', '')
Trace(返回)
Exit
]
] else
[
break
]
//检查是否已达三次打开的未关闭Excel
if (I_Fileused_Count = 3)
[
返回 = 设置指标('严重', '未及时关闭Excel文件,请人工关闭Excel后重新执行流程', '')
Trace(返回)
Exit
]
]
trace('----检查Excel是否被占用,完成')
//关闭WPS进程
for I_进程 = 1 to 10
[
I_Excel进程 = 获取进程('et.exe')
if (I_Excel进程 > 0)
[
关闭进程(I_Excel进程, 5)
sleep(3000)
] else
[
break
]
]
//关闭office进程
for I_进程 = 1 to 10
[
I_Excel进程 = 获取进程('EXCEL.EXE')
if (I_Excel进程 > 0)
[
关闭进程(I_Excel进程, 5)
sleep(3000)
] else
[
break
]
]
(5)拆分处理
1)打开需拆分文件
2)判断用户输入的数据是否正确或存在
- 检查用户输入的Sheet页名称是否存在在拆分文件中,如果不存在,默认设置页签为1;如果存在就获取当前页签
- 判断客户输入的起始行是否为表头所在行
- 判断拆分字段名称所在列
实现代码:
//判断需要查找的字段在哪一列
I_行数 = Com获取行数(工作簿, I_页签)
I_列数 = Com获取列数(工作簿, I_页签)
//判断客户输入的起始行是否为表头所在行
//判断拆分字段名称所在列
for I_起始行 = 1 to I_行数
[
B_mark = False
for I_列索引 = 1 to I_列数
[
S_内容 = Com获取单元格内容(工作簿, I_起始行, I_列索引, I_页签)
S_内容 = 去除不可见字符(S_内容)
if(TRIM(S_内容) = TRIM(S_拆分字段名称))
[
S_字段表头所在行 = inttostr(I_起始行)
I_拆分字段所在列 = I_列索引
B_mark = True
break
]
]
if(B_mark)
[
break
]
if (I_起始行 = I_行数)
[
返回 = 设置指标('严重', '文件“' + S_需拆分文件 + '”,获取拆分字段所在行索引失败', '')
Trace(返回)
Exit
]
]
- 检查 需拆分文件的有效行列
实现代码:
//判断有效内容行
for I_有效内容行 = I_行数 downto 1
[
S_内容 = Com获取单元格内容(工作簿, I_有效内容行, I_拆分字段所在列, I_页签)
if (S_内容 <> '')
[
I_行数 = I_有效内容行
break
]
if (I_有效内容行 = 1)
[
S_返回 = 设置指标('严重','文件“' + S_需拆分文件 + '”,获取有内容行数失败,请检查文件是否为空', '')
trace(S_返回)
Exit
]
]
//判断有效内容列
for I_有效内容列 = I_列数 downto 1
[
S_内容 = Com获取单元格内容(工作簿, strtoint(S_字段表头所在行), I_有效内容列, I_页签)
if (S_内容 <> '')
[
I_列数 = I_有效内容列
break
]
if (I_有效内容列 = 1)
[
S_返回 = 设置指标('严重','文件“' + S_需拆分文件 + '”,获取有内容列数失败,请检查文件是否为空', '')
trace(S_返回)
Exit
]
]
3)获取指定字段列的数据,并对该列的字符串列进行去重,然后获取该字符串列的个数
4)拆分处理
遍历字符串列里的字符,在循环中先将表头复制粘贴到一个新建的工作表中,然后对需拆分工作表进行筛选处理,筛选条件为字符串列里的字符串,筛选前记得先清理筛选条件,以免以前的筛选操作影响现在的筛选操作。将筛选后的内容复制到新的工作表中,再新建一个工作簿,将新的工作表的内容复制到新的工作簿中,保存关闭工作簿,最后删除新的工作表,执行这些操作后才执行下一次循环。
S_列字母 = Excel_数字转对应字母(I_列数)
//将根据获得的字符串进行逐个筛选
for k = 0 to I_字符串列数 - 1
[
//新建用来储存分割内容的工作表
I_Sheet页个数 = Com获取页签个数(工作簿)
I_新建页签 = I_Sheet页个数 + 1
结果 = Com增加Sheet页(工作簿, I_新建页签)
if (结果<> '')
[
返回 = 设置指标('严重', 结果, '')
Trace(返回)
Exit
]
//将表头复制到新工作表中
结果 = Com复制范围2(工作簿, I_页签, 'A1:' + S_列字母 + S_字段表头所在行, 工作簿, I_新建页签, 'A1', -4104, -4142)
S_内容 = 获取字符串行列(S_列数据,';',0,k)
日志(S_内容)
//对源文件进行筛选
Com清除筛选器(工作簿, I_页签)
Com设置筛选器3(工作簿, I_页签, 'A' + S_字段表头所在行 + ':' + S_列字母 + InttoStr(I_行数),I_拆分字段所在列, '='+ S_内容, 7, '')
//将筛选出来的数据复制粘贴到新工作表中
结果 = Com复制范围2(工作簿, I_页签, 'A' + inttostr(strtoint(S_字段表头所在行) + 1) + ':' + S_列字母 + InttoStr(I_行数), 工作簿, I_新建页签, 'A' + inttostr(strtoint(S_字段表头所在行) + 1), -4104, -4142)
S_文件名 = S_拆分后文件保存目录模板 + S_内容 + '_' + S_拆分后追加文件名 + '.xlsx'
信息 = 创建文件(S_文件名,3,是)
信息 = Com打开工作簿(ExcelApp, S_文件名, 目标工作簿)
结果 = Com复制Sheet页3(工作簿, I_新建页签, 目标工作簿, 1, '', -4104 , -4142)
Com保存工作簿(目标工作簿, S_文件名)
Com关闭工作簿(目标工作簿)
Com清除筛选器(工作簿, I_页签)
结果 = Com删除Sheet页(工作簿, I_新建页签)
]
(6)发送邮件
拆分文件完成后发送邮件给业务人员,通知业务人员文件已经拆分完毕
2、自动化发送邮件
(1)用户在弹出的对话框中输入需要根据哪个表格数据发送邮件的sheet页名
(2)打开邮件报表,切换指定sheet页
(3)获得发送邮件所需的数据所在的列名的字母
(4)在表头的最后新加一个为“是否成功发送”列名
(5)循环读取“是否发送”这一列的数据,当内容为“是”时就进行发送邮件操作,否则就不执行。
(6)发送邮件
将当前行的数据填入【发送邮件2】函数中
在获取附件名时,需要判断当前单元格的内容是否".xls",如果没有就中断当前行数据的读取;如果有就将各个附件名称里的文件名进行拼接并转换成字符串数组。
循环获取文件路径名结束后,把储存文件名的属性进行清空,以免下一次拼接文件名时出现多个不属于当前行数据的文件名
(7)发送邮件结果
在【发送邮件2】执行过后会返回发送结果,根据发送结果在“是否发送成功”列填入数据。如果发送成功就填入“是”;如果发送失败就填入“否”;如果不发送邮件就填入“不发送”
三、项目总结
1、自己写存在的缺陷
(1)只考虑到了单一场景,并没有往多方面考虑
如:
1)只考虑到只拆分一个文档的场景,并没有考虑到需要拆分多个文档的场景
2)没有考虑到拆分后的文档存放的目录的创建以及如果目录不存在是否该创建目录
3)没考虑到对目录进行处理
4)需拆分的工作表所在的页签太过固定
5)没考虑到当前文件是否已经打开
2、参考组件思路
(1)判断客户是否已经输入数据并去除空格
(2)目录处理,若目录末尾不是以'\'结尾,则加上'\',再创建一个当期文件夹——>需拆分文件目录和拆分后文件目录
(3)遍历 当天需拆分报表存放目录 下的.xls or .xlsx文件
1)读取目录里需要拆分的文件,并跳过临时文件
2)检查 需拆分文件 是否被打开,并关闭Excel与WPS进程
3)打开WPS,默认取第1个页签,获取行列数
4)判断起始行包含有效内容,并记录有内容列数量
5)遍历文件表头,找出拆分字段所在行索引,从而避免人工填入的字段所在行索引不正确
6)遍历文件表头,找出拆分字段所在列索引
7)比对人工输入的 “S_字段表头所在行数” 和 脚本遍历读取到的 “I_拆分字段所在行索引” 值
8)获取有内容行数,获取指定拆分列含多少不同的单项集合,对需要拆分的字段列进行去重
9)复制去重后数据至辅助的模板中,获取模板中的行数,并读取指定列中的每一行的单元格并对其进行拼接。
10)筛选集合获取完成,关闭辅助工作簿,释放该资源
11)用for循环获取筛选集合中的筛选条件,然后将在从源文件筛选出来的数据复制粘贴到拆分后的文件中
然后清除源文件的筛选条件,再把源文件的备注再复制粘贴到拆分后文件中
12)每次复制粘贴完后,对拆分后文件进行保存,for循环完成后再对源文件进行清除筛选条件处理
注意点:
当Excel文件不存在时,可只创建对象来实行excel操作,然后再进行保存就可以创建一个新的excel文件,但是当Excel文件存在时,需要先创建对象再进行打开操作才能对该文件进行excel相关操作