编注:本文为《59 分钟就上手 Power Automate Desktop》栏目的试读文章。可能是少数派目前最具「信价比」的栏目,介绍 Power Automate Desktop 这款能把你从重复繁琐的软件操作中解脱出来的效率工具。欢迎前往详情页了解栏目的具体内容。
点击链接,下载文章中演示时所用到的文件。
在上一篇文章中,我帮助大家厘清了通过 Power Automate Desktop(下文简称 PAD) 来解决问题的基本思路,那就是「抽象问题 > 确定目标 > 思考解决方案 > 在 PAD 中实现」。同时,我们也简单地了解了 PAD 的工作区以及「数据」「变量」「控制结构」这些概念,通过掌握这些最基础的元素我们已经可以在 PAD 上创建一些简单的流了。
那么,在第二节课程中我会带着大家一步步地创建一个流,通过这个案例让大家快速上手 PAD 的基本操作。另外,在本节课的最后我还为大家准备一份 PAD 的调试指南,可以帮助大家利用一些基本原则来快速定位 bug 以及解决 bug。
流(Flow)是什么?
流(Flow)是 PAD 中工作流的基本度量单位,一个流即是一系列操作的一个组合。在 PAD 的主界面中,我们看到的就是一个流列表,列表中的每一个项目都包含了流的名称、最近一次修改时间和状态。如果选中任意一个流,就会出现快速操作栏,在这里我可以对选中的流进行运行、停止以及编辑等操作。
在 PAD 里帮你完整解决一个问题的流程就是流,至于流是简单还是复杂,那就丰俭由人。用 PAD 逐个打开京东、淘宝的网址,这个操作可以是流;用 PAD 打开商品网址后,复制标题和价格到 Excel,这个操作可以是流;用 PAD 打开商品网址后,复制标题和价格到 Excel,然后把 Excel 作为附件发送给自己,同时抄送给同事,这个操作也可以是流。因此,一个流中的动作数量和复杂程度没有任何限制,只要这个流可以解决预想中的问题,就可以称之为一个完整的流。
怎样创建自己的流
验证需求
一个 PAD 的流从创建、调试到最终可用,都需要时间和精力去实现,这本身也是一种成本。而发明工具的最终目的还是要提高效率、解决问题,因此在动手创建流之前可以先想一想:
- 这项工作是周期性的吗?
- PAD 能为我节省多少时间?
- 根据工作的复杂程度,我想要完成创建一个流需要多长时间?
比如现在你需要把 10 份 Word 文档中的数据汇总到同一个 Excel 中,这份工作可能几个月才需要做一次。这种情况下,用 PAD 去编写一个流就非常不划算。但如果你每天、每周都需要做同样的汇总操作,手工复制粘贴就应该被机器来替代了,节省的时间累积下来会非常可观。
如上文的例子所述,如果评估完成本和收益后还是觉得使用 PAD 更划算,那我们再来认真学习如何创建一个流也不迟。
三步定位
上文提到过,我们可以把 PAD 理解成一种编程工具,而利用编程工具解决问题可以分为三步:
- 抽象问题,确定目标
- 找出解决方案
- 翻译成机器看的懂的语言
那么把这个流程应用到 PAD 上,就可以得到如下步骤:
- 把自己要优化的流程手动多跑几遍,想清楚过程中自己的鼠标键盘做了什么操作,使用了软件内的什么功能,对流程中各处的情况有个基本的认知。
- 画出整个流程的「流程图」。如果工作流比较复杂,可以把工作流切分成不同的模块。前期对 PAD 了解不多的时候,可以抽象的层次放得更低一些,甚至到每一个具体的步骤。这里的「流程图」其实就是把整个流程拆成几个不同的模块并用箭头连接一下,方便逐个击破。
- 参照流程图分模块拼接流并调试。用 PAD 创建流的时候多想想人工操作在这一步会怎么做,然后再看怎么用 PAD 实现它。
案例演示
假如说我有一个需求:给定一批京东商品的网址,逐个在浏览器上访问,然后截图保留快照到本地文件夹,最后把文件夹打包压缩。
https://item.jd.com/100008716820.html
https://item.jd.com/100001644698.html
https://item.jd.com/100015047660.html
按照上面说的三步定位法,我先想清楚这个问题需要怎么来解决,然后构思一个流程图,最后就是分模块构建,完成后再进行拼接。
明确流程
这里的需求相对简单,多体验几次就可以直接生成下面这份流程图。我们大致可以将这个流程分为两个部分:Excel 读取、浏览器循环打开网址并截图。
分模块拼接
获取商品网址列表
首先我们需要做的是把相关的商品网址从 Excel 中提取出来。人工操作的时候,流程是「打开 Excel-选中所有 item - 复制」。我们希望这个流程通用性更强,因为每次 Excel 中的商品的数量应该是不确定的。那我们该怎样确保每次都能选中所有的商品网址列表?
这时我们就需要想想,在人工操作的时候我们是怎么来确定选中区域的范围的?其实很简单,只要找到文字和空白行交界的地方,从第一行到这里就是该选中的位置。
所以在 PAD 里面,我们可以先定位出表格里第一个空白行,然后提取表格里面第一行到「第一个空白行-1」范围之间的内容。
因为不同的模块是靠变量来传递信息的,上一个模块的输出是下一个模块的输入。上一个模块写好了,我们应该检查一下这个模块输出的内容是否满足我们的要求,如果不满足,则下一个模块也无法正常对接运行。
这里我们希望的输出是一个存放着所有需要遍历的网址列表 ExcelData
,所以我们只需要观察在此部分模块结束时,ExcelData
中的数据是否符合我们的需求即可。
点击「运行」,等待流执行完成。完成后在「流变量」区域点击 ExcelData
,发现数据类型的确是「数据表」,并且表中存放着需要遍历的所有网址,这就代表着这个模块我们已经创建成功了。
单条网址打开后截图保存
正常来讲,此处应该直接开始编写循环结构,但这样每次调试都需要运行一次之前的步骤,既耗时又增加了调试的复杂度,和我们「分模块拼接」的思想是相悖的。
因此,在循环这个模块里,我们其实只需要一个存放着网址列表的变量输入。为了方便下面的调试,可以全选上一个模块的动作,然后在右键菜单中选择「禁用操作」。
这样一来,我们可以专心先把循环这个模块搞定。循环的本质是把一项工作重复很多遍,那要想写好循环,其实我们只需要把里面的工作搞清楚就行了,也就是——给定一个网址,浏览器打开网址并截图保存。我们拿 https://item.jd.com/100008716820.html
举例子。
首先是用浏览器打开:
通常浏览器打开一个网址还需要等待网页完全加载,网页加载不全的话截图也没意义,所以我们先人工加载一遍网页,估算网页加载时间大概在 2 秒,保险起见那我们就等 3 秒。
现在网页加载好了,我们该进行截图操作了。PAD 自己提供了三种截图的动作。
- 获取屏幕截图:直接在屏幕的可视范围内截图。
- 获取网页的屏幕截图:会自动下拉完全网页,是网页的长图。
- 获取 UI 元素的屏幕截图:单个元素截图,暂时用不上。
这里我们选择「获取屏幕截图」这个动作,多显示器的用户可以指定要截取的屏幕,单一屏幕可以直接选「所有屏幕」。
我们希望截图能够以文件的形式保存,那么就需要指定一个本地路径。这里的本地路径可以在目标文件夹内随意复制一个文件的地址后粘贴进来,然后修改最后的文件名和文件后缀。等截图完了,我们就可以关闭浏览器。
当循环里的任务编写完后也需要做一次检查,点击「运行」看看目标文件夹内是否生成了对应的屏幕截图。
编写循环任务
我们现在尝试把单项任务放到循环里面。
首先,我们需要一个列表作为循环的输入。按照「分模块调试」的思想,我们应该另外创建一个存放网址的列表作为模块测试的输入源,避免前方动作耗时太长而降低模块测试的效率。不过,在这个案例中前方的动作数量较少,耗时不多,所以权且直接启用上一个模块的输出作为循环模块的输入。
接着,我们对 ExcelData
进行「for each」循环,每次循环到的网址储存到 CurrentItem
里面。
因为循环里每次打开的网址不同,所以我们需要将原来固定的网址 https://item.jd.com/100008716820.html
变更为每次循环里的网址变量 CurrentItem
点击「运行」,我们来看看是否这个模块按照我们的期望输出了三个商品的截图。很遗憾,没有。文件夹最后只有一张截图,这是因为我们所有的截图文件都采用了同一个文件名,每次新的截图把前一个直接覆盖掉了。
因此,我们需要让不同的截图拥有不同的名字。方法有很多,这里我想用网址中的数字编号来做唯一的匹配符。从网址里获取第 20 个字符后 12 个字符长度的内容,赋值为ItemID
,然后放入图片的保存路径。
此时再运行一次,就可以发现文件夹里成功包含了三张商品的截图。
优化步骤
虽然运行成功了,但是我们也能发现每次打开浏览器然后关闭太耗时。当循环次数少时尚能接受,次数增多后则非常难熬。
与开启关闭浏览器相比,在开启的浏览器中跳转新网址则会快很多,所以我们可以在循环外开启和关闭浏览器,循环内只完成不同网址的跳转。
打包文件夹
打包压缩这一步很简单,PAD 有成熟的动作,拖进工作区填表即可。
调试的方法
在编写流的过程中,通常很难一次就直接跑通,多半都会遇到各种问题(Bug)。处理 Bug 经常会占整体编写时间的一半以上,那怎样相对高效地处理 Bug 呢?
很不幸,正因为 Bug 是意料之外的,所以我也很难直接告诉你一个框架性的处理 Bug 的流程。不过处理 Bug 可以拆成找 Bug 和解决 Bug 两个环节,还是有一些基本的原则可以帮助你事半功倍。
找 Bug
通常我们运行一个流,它报错时会直接提示你是在第几个操作上出了什么问题,这个时候你可以直接点开对应的操作看看是不是自己配置上出了什么错误。
比如下图的「提示-图像不存在」,原因在于我们的文件路径少了文件后缀,即文件的路径应该是 D:\我的坚果云\常用模块案例\04-批量提取身份证信息\身份证图片集\身份证.png
,而不是 D:\我的坚果云\常用模块案例\04-批量提取身份证信息\身份证图片集\身份证
。
设置断点
简单的配置错误其实通过报错的信息就可以解决,但有时候我们会发现报错提示的操作的配置并没有问题,这就说明问题出在更前面的操作里。
这个时候我们可以通过设置断点,流运行到断点就会自动停止,只有我们点击「运行下一个操作」流才会继续往下运行,然后通过在变量区观察断点操作前后变量值的变化,就可以验证断点处的操作是否符合我们的要求。
拆分模块
在写一些比较复杂的流时,可能涉及到多个软件,以及数百个操作。这个时候如果想要验证的操作是第 80 个,那从头开始运行就会很耗时。
另外,调试的时候经常会运行数十次才能找到问题,如果每次都需要前面的操作运行几分钟,那整个调试的效率就会非常低。
这种场景下我会更建议大家将一个复杂的流拆成几个模块(通常是根据不同的软件),上一个模块的输出就是下一个模块的输入。然后除了测试模块,其他模块全部禁用,在测试模块前手动设置测试模块里所需变量的值,观察测试模块的输出是否符合预期。
解决 Bug
通常我们定位到 Bug 以后,整个问题其实就解决了一半。解决 Bug 的方法核心其实就是查文档、搜索然后不断修改验证。
PAD 中的每一个操作微软都提供了一个参考文档,可以点击「详细信息」快速直达。对照文档,可以看看自己的配置是否存在问题。
如果不是配置上的问题,那可以直接把报错信息复制到浏览器里查询,看看网络上有没有相关的解决方案。不过目前互联网上 PAD 的中文内容还是比较少,所以搜索时建议使用英文会得到更多相关的结果。
PAD 自身的出错处理
PAD 里任意一个操作下方其实都有一个「出错时」的配置选项,比如第一次出错后间隔一定时间自动重试,或者忽略错误继续流的运行,这其实也是一个帮助我们应对 Bug 的地方。
另一个方法是我们可以设置一个 Warning
变量存放我们想要观察的变量值,然后通过调用子流来输出。这个触发条件可以是报错就触发,也可以指定特定报错类型才触发。
小结
在本节课程中,我带着大家非常详细地创建了 PAD 上的第一个流,从验证需求开始,到明确流程,接着分模块把具体的操作动作编写完成,最后拼接成一个完整的流。在创建第一个流之后,我还向大家介绍了一些基本的 bug 调试方法,可以在最快的时间内找到并解决问题。当然话说回来,处理 Bug 终究不是一个标准化的过程,很多经验还是需要不断实践来积累。从下一节课开始,我将逐个介绍操作中的各个模块和动作,并辅以对应的实战案例,希望通过这些例子可以帮助大家在较短的时间内掌握这些模块,以应用到日常的流创作中。