订单流水对账机器人
上一项练"生成文档",这一项练"比对数据"。财务、审计、运营每天都在做这种事。
项目目标
- 会比较两张 Excel 表,找出金额不一致、系统有银行无、银行有系统无三类差异
- 会用双层
For Each遍历,并正确使用标志变量记录"找到没找到" - 能把差异结果攒成二维数组,并写出一个新的 Excel 报告文件
- 会把对账结论用邮件发出去
- 初步了解用字典替代内层循环的性能优化思路
- 能对"0.1 + 0.2 不等于 0.3"这类浮点误差做金额容差处理
预计用时:4–6 小时(分 6 关,第 6 关为进阶选做) | 前置知识:建议先完成综合项目 1;本项依赖第 3 课(变量)、第 4 课(判断)、第 5 课(循环)、第 6 课(数组与字典)、第 7 课(Excel)、第 9 课(邮件)、第七部分(网页) | 本课性质:综合项目(第二个能力轴:交叉比对与差异报告)
同样分 6 关,逐关回报。这一项第 2 关的"标志变量"是零基础最容易写错的地方,做完第 2 关先发我。
知识地图
这是第二个综合项目,与项目 1 互补:项目 1 练"一行数据 → 一份文档",是流水线;项目 2 练"两张表互相找",是交叉比对。整套课程里第一次出现"双层循环 + 标志变量"的组合,它也是认证里比对类题目的通用套路。
一、需求说明
背景:月底财务要核对"业务系统流水"和"银行流水"是否一致,人工一条条对,几百条能对到眼花。
这类任务的核心不是"算数",而是"两边互查":以其中一张表为基准,逐条去另一张表里找同一条记录——找到了再比金额,找不到就是单边账。把这句话翻译成代码,就是"外层循环一行、内层循环找一遍"的双层循环。
| 项 | 内容 |
|---|---|
| 输入① | 系统流水.xlsx:订单号、金额(6 条) |
| 输入② | 银行流水.xlsx:订单号、金额(6 条) |
| 输出① | 对账结果.xlsx:订单号、差异类型、系统金额、银行金额 |
| 输出② | 一封汇总邮件:共几处差异、各是什么类型 |
差异类型定义(对账的标准三类)
| 类型名 | 含义 |
|---|---|
| 金额不一致 | 两边都有这个订单号,但金额不同 |
| 系统有银行无 | 系统里有,银行流水里找不到 |
| 银行有系统无 | 银行流水里有,系统里找不到 |
为什么要先定死"三类差异"?因为对账的结论必须可枚举、可统计。只有分类标准统一,第 5 关发出去的邮件才能说清"共几处差异、各是什么类型",而不是一堆零散记录。
样例数据(已为你准备)
直接复制到 res/:系统流水.csv · 银行流水.csv(用 Excel 打开后另存为 .xlsx)。
系统流水 银行流水 D001 100.00 D001 100.00 D002 250.50 D002 250.50 D003 80.00 D003 88.00 ← 金额不一致 D004 999.99 ←系统有 D005 45.00 D005 45.00 D006 320.00 D006 320.00 D007 500.00 ← 银行有
正确答案先剧透给你(用来验收,不要提前写进流程):差异共 3 处——D003 金额不一致、D004 系统有银行无、D007 银行有系统无;一致的 4 笔是 D001、D002、D005、D006。
二、关卡地图
六关层层递进:先是"读进来",再"正向查一遍",再"反向查一遍",然后"写报告、发邮件",最后是进阶优化。
在你的流程文件夹下建好:
你的流程/
└── res/
├── 系统流水.xlsx
├── 银行流水.xlsx
└── 对账结果.xlsx ← 不用先建,第 4 关会自动新建
准备步骤
- 建
res文件夹,把 系统流水.csv 和 银行流水.csv 用 Excel 打开后,分别另存为res\系统流水.xlsx、res\银行流水.xlsx。期望:每张表第一行表头,下面 6 行数据。 - 打开两张表核对左下角对照图:D003 金额不同、D004 系统独有、D007 银行独有。期望:你能人工看出这 3 处差异,作为后面机器人结果的验收基准。
- 常见报错:若流程报"找不到文件",检查扩展名是否真为
.xlsx(Windows 可能隐藏扩展名),以及文件名里有无多余空格。
三、逐关实现
第 1 关 · 把两张表都读进来
分别打开两张表,各读 "A1:B7",得到两个二维数组,各自打印确认。
- 新建变量
objSys、objBank、系统rows、银行rows。 - 拖入
打开Excel打开res\系统流水.xlsx,输出到objSys;再拖读取区域读"Sheet1"、"A1:B7"存入系统rows;随后关闭Excel工作簿(objSys)。 - 对银行流水重复同样三步,结果存入
银行rows。期望:两个数组都读到了,含表头共 7 行。 - 用
输出调试信息打印两个数组长度。提示:想取数组长度,用数据处理 ▸ 数组里的"获取数组长度"命令;不确定名字就翻命令手册。 - 常见报错:工作表名不对 → 试填
0;行数偏少 → 检查区域是否A1:B7。
打开Excel(res\系统流水.xlsx) → objSys
读取区域(objSys, "Sheet1", "A1:B7") → 系统rows
关闭Excel工作簿(objSys)
打开Excel(res\银行流水.xlsx) → objBank
读取区域(objBank, "Sheet1", "A1:B7") → 银行rows
关闭Excel工作簿(objBank)
输出调试信息("系统行数:" & 系统rows 的长度)
输出调试信息("银行行数:" & 银行rows 的长度)
提示:想取数组长度,用数据处理 ▸ 数组里的"获取数组长度"命令;不确定名字就翻命令手册。
第 2 关 · 遍历系统流水,找出两类差异
找到 = False,内层找到了就设 找到 = True,内层结束后再看它——不是在内层里直接判断。
- 在外层用
For Each遍历系统rows,循环体先序号 = 序号 + 1;用If 序号 > 1跳过表头。 - 取本行订单号和系统金额:
订单号 = 系统行[0]、系统金额 = 系统行[1]。 - 进内层之前先重置:
找到 = False、银行金额 = ""。期望:这两句写在For Each 银行行的外面、外层循环体的里面。 - 内层用
For Each遍历银行rows:若银行行[0] = 订单号,则找到 = True、银行金额 = 银行行[1]。 - 内层结束后才判断:
If 找到 = False→ 输出"系统有银行无";ElseIf 银行金额 <> 系统金额→ 输出"金额不一致"。 - 常见报错:结果多出或少出 → 九成是
找到 = False放错位置(放到循环外了),或把变量定义在循环体里导致每轮被重新声明。
Dim 序号 = 0
For Each 系统行 In 系统rows
序号 = 序号 + 1
If 序号 > 1 // 跳过表头(BotScript 不写 Then)
Dim 订单号 = 系统行[0]
Dim 系统金额 = 系统行[1]
Dim 找到 = False // ← 每行重新置为 False
Dim 银行金额 = ""
For Each 银行行 In 银行rows
If 银行行[0] = 订单号
找到 = True
银行金额 = 银行行[1]
End If
Next
If 找到 = False
输出调试信息(订单号 & " 系统有银行无(" & 系统金额 & ")")
ElseIf 银行金额 <> 系统金额
输出调试信息(订单号 & " 金额不一致:系统 " & 系统金额 & " / 银行 " & 银行金额)
End If
End If
Next
D003 金额不一致、D004 系统有银行无。如果多输出或少输出:九成是
找到 = False 放错位置(放到循环外面了),或 Dim 写进了循环体导致变量没重置。第 3 关 · 反向再查一遍:银行有系统无
再遍历一遍银行流水,去系统流水里找;找不到的就是"银行有系统无"。同样用标志变量。
- 照抄第 2 关的结构,把"外层
系统rows/ 内层银行rows"换成"外层银行rows/ 内层系统rows"。 - 标志变量依旧在外层每轮开头重置为
False;内层命中则记为True。 - 内层结束后,若
找到 = False,输出"银行有系统无"。注意:这一轮只输出单边差异,不需要再比金额。 - 常见报错:若把方向写反或忘了重置标志,会漏掉 D007 或多报一堆假差异。
D007 银行有系统无(500.00),此时三类差异各一条,共 3 条。第 4 关 · 写出对账结果.xlsx
把结果先攒成一个二维数组(第一行是表头),再一次性 写入区域。
- 流程一开始先建结果数组并放表头:
Dim 结果 = [["订单号", "差异类型", "系统金额", "银行金额"]]。 - 在发现差异的每一处,往数组尾部追加一行:
结果 = 在数组尾部添加元素(结果, [订单号, "金额不一致", 系统金额, 银行金额])。三类差异各追加一次。 - 全部比完后打开(不存在会自动新建)
res\对账结果.xlsx,用写入区域把整个数组写到"A1:D4"(表头 + 3 条差异),立即保存=是,最后关闭。 - 常见坑:区域写成
"A1:D4"但结果有 5 行 → 报错或写错位。结果行数 = 1(表头)+ 差异条数。
// 一开始先放表头 Dim 结果 = [["订单号", "差异类型", "系统金额", "银行金额"]] // 发现差异时,往数组尾部追加一行 结果 = 在数组尾部添加元素(结果, [订单号, "金额不一致", 系统金额, 银行金额]) // 全部比完,写出到新文件(不存在会自动新建) 打开Excel(res\对账结果.xlsx, 可见=True) → objOut 写入区域(objOut, "Sheet1", "A1:D4", 结果, 立即保存=是) 关闭Excel工作簿(objOut)
对账结果.xlsx 里有 4 行:表头 + D003/D004/D007 三条差异,列与含义对应正确。常见坑:区域写成
"A1:D4" 但结果有 5 行 → 报错或写错位。结果行数 = 1 + 差异条数。第 5 关 · 发汇总邮件
& 拼接)把"共发现 3 处差异"和每条的简要描述拼成正文,发给自己。
- 循环开始前定义正文头:
Dim 正文 = "本月对账完成。\n共发现 " & 差异条数 & " 处差异:\n"。 - 在发现差异时逐条追加:
正文 = 正文 & 订单号 & " - " & 差异类型 & "\n"。 - 循环结束后拖入
发送邮件,SMTP 参数照第 9 课填,登录密码用授权码变量,收信邮箱填自己,标题"月度对账报告",正文传正文,结果存入成功与否。 - 常见报错:登录失败 → 授权码错或未开 SMTP;正文没有换行 → 检查字符串里的
\n有没有被拼进变量。
Dim 正文 = "本月对账完成。\n共发现 " & 差异条数 & " 处差异:\n"
// 循环中逐条追加:正文 = 正文 & 订单号 & " - " & 差异类型 & "\n"
发送邮件(SMTP服务器="smtp.qq.com", 服务器端口=465, SSL加密=True,
邮箱帐号=..., 登录密码=<授权码变量>, 收信邮箱=...,
邮件标题="月度对账报告", 邮件正文=正文) → 成功与否
想练更规范的写法:差异条数不用单独计数,用数组长度减 1 也算得出来。
第 6 关 · 进阶(三选一,至少做一个)
现在每比对一行,都要把另一张表整扫一遍(双层循环)。数据一多就慢。做法:先把银行流水装进一个字典(订单号 → 金额),之后直接用
银行字典[订单号] 一次查到。这就是第 6 课字典的实战价值。
(空字典怎么写、用哪条字典命令,去命令手册搜"字典"确认你的版本;不确定就先做 B 或 C。)
浮点数比较常有微小误差(
0.1 + 0.2 不等于 0.3)。改成"两边差额的绝对值小于 0.01 就算一致",避免把一分钱的误差报成差异。
用练习场里的 虚拟台账:用
启动新的浏览器 打开它,选一个单元格元素,用 获取元素文本 读出内容,再把网页上的数与你本地 Excel 的某个数比对。这一步专门练元素选取和漏选/错选的修法。
- 选做 A:先建空字典,遍历银行流水把"订单号 → 金额"装进去;把内层
For Each换成一次字典查找,再跑第 2、3 关的验证。期望:结论与原来完全一致,但代码更快、更短。 - 选做 B:把金额比较改成"两边差额的绝对值 < 0.01 视为一致"。期望:D003(80 vs 88)仍被报为不一致;如果把某笔改成只差 0.005,则不再报差异。
- 选做 C:启动浏览器打开练习页,选一个单元格用
获取元素文本读出数值。常见报错:"找不到元素" → 元素选错或页面没加载完,重新选取并加等待。
四、两个项目一起看
把项目 1 和项目 2 放在一起,你会看到 RPA 的通用骨架:读数据 → 逻辑处理 → 产出 + 通知。区别只在于"逻辑处理"这一段的形状。
| 能力 | 项目 1(绩效通知) | 项目 2(对账) |
|---|---|---|
| 主结构 | 单层循环 + 生成文件 | 双层循环 + 标志变量 |
| 核心难点 | Word 标记填充、路径拼接 | 变量作用范围、比对逻辑 |
| 数据结构 | 二维数组遍历 | 二维数组 + 字典(进阶) |
| 产出 | 一叠 Word | 一张差异报告 + 邮件 |
| 共同点 | 都是"读 Excel → 逻辑处理 → 产出 + 通知",这正是 RPA 的通用骨架 | |
五、卡住时怎么办
- 把流程缩小到这个最小例子:只有 2 行系统数据、2 行银行数据,手工算一遍预期输出。
- 在关键位置加
输出调试信息,打印订单号、找到的值——看它是不是你以为的那样。 - 比较金额时若结果诡异,先把两边都
输出调试信息出来,确认读到的到底是数字还是文字。 - 还是不通,把代码 + 实际输出 + 你的预期三样发我。
对账类逻辑的两个致命坑:① 标志变量 找到 没有在外层每轮重置,导致"上一行找到过"污染"这一行";② 金额一边是数字一边是文字,<> 比较永远为真,把每笔都报成不一致。
六、技术点索引
| 用到的东西 | 复习哪节 |
|---|---|
| 二维数组、数组追加、长度 | 第 6 课 |
| 双层 For Each、标志变量 | 第 5 课 |
| If / ElseIf、比较运算符 | 第 4 课 |
| 读取区域 / 写入区域 / 新建文件 | Excel 命令速查 |
| SMTP 发邮件、授权码 | Email 命令速查 |
| 元素选取、漏选/错选 | 网页自动化速查 |
项目复盘
你真正学会的能力
- 用双层 For Each 让两张表互查,并说出外层、内层各自在做什么
- 用标志变量记录"找到没找到",并知道它必须每轮重置(这是零基础到能写逻辑的关键一步)
- 把差异按三类标准分类输出,让结论可统计、可汇报
- 把结果攒成二维数组,用
写入区域生成一份新的差异报告 - 用 SMTP 把对账结论发出去
- 了解字典查找与金额容差两种让比对更专业的手法
结课自测
不看上面,凭记忆作答。答错不要紧,解析会告诉你为什么。
精读一手来源
对账里涉及的命令细节以官方文档为准:《来也开发者指南》与命令手册。 建议按需回查——Excel 的读写与新建看"表格/Excel"分类,字典看"数据处理/字典",网页核对看"浏览器"分类;命令名或参数不确定时,一律以命令手册当前版本为准。第 6 关 C 的练习页见练习场 · 虚拟台账。