从“人肉合并”到“机器人看门
我在一家工厂做财务数字化顾问,每到月底,七八张区域销售报表像雪片一样砸下来:XLS、CSV、SAP 导出的 TXT,甚至还有 PDF。五个人通宵合并、透视、标色、发邮件,第二天还得盯着 Excel 看有没有谁家金额跳了 30 %,像极了大型“大家来找茬”现场。
去年,我们用 4 周搭了一套“无人值守”方案:
- UiPath Robot 夜里 2 点自动登录各系统抓数;
- Python 写的合并脚本把格式、币种、税率全部对齐;
- 异常检测模型用历史 36 个月的数据训练,找出“离群门店”;
- 机器人再根据模型结果,自动生成《智能巡检报告》推送给区域经理。
整套流程跑通后,月底合并时间从 9 小时降到 20 分钟,异常漏报率从 7 % 降到 0.6 %。下面把踩过的坑、磨过的刀完整摊开,供同行参考。
1. 需求全景图:五张表看懂业务痛点
| 痛点 | 人工耗时/次 | 出错率 | 业务影响 | 解决思路 |
|---|---|---|---|---|
| 多系统导出格式乱 | 2.5 h | 高 | 延误合并 | UiPath 统一格式 |
| 汇率、税率对齐 | 1.8 h | 中 | 金额失真 | 脚本自动换算 |
| 异常门店识别 | 3 h(人工筛) | 高 | 错失整改窗口 | 异常检测模型 |
| 巡检报告撰写 | 2 h | 低 | 重复劳动 | 模板+自动填充 |
| 邮件分发 | 0.5 h | 低 | 遗漏 | UiPath SMTP |
2. 架构蓝图:三横两纵的“三明治”
┌────────────┐ 智能巡检报告(PowerPoint & E-mail)
│ 展示层 │
├────────────┤ 异常检测模型(Python / ML.NET)
│ 分析层 │
├────────────┤ 报表合并脚本(Python)
│ 数据层 │
├────────────┤ UiPath Robot(无人值守)
│ 执行层 │
└────────────┘
- 执行层:机器人负责“采、传、发”。
- 数据层:把各系统原始文件清洗成结构化 DataFrame。
- 分析层:用无监督算法找异常,输出门店 ID + 异常类型。
- 展示层:读取分析结果,填充 PPT 模板,邮件推送。
3. UiPath 自动化流程拆解
3.1 资产(Asset)与环境变量
| Asset 名称 | 类型 | 用途 |
|---|---|---|
SAP_Password |
Credential | 登录 SAP |
Email_SMTP_Pwd |
Credential | 发件邮箱 |
Folder_RawData |
Text | 原始报表目录 |
Folder_Archive |
Text | 归档目录 |
3.2 关键 Activity 设计
- Trigger:Windows Task Scheduler 每天 02:00 触发
Main.xaml。 - 登录:使用
UiPath.Core.Activities.LoginToSAP(公司自开发组件)。 - 下载:循环
For Each file in Directory.GetFiles(rawFolder),调用Execute Query导出;命名规则Region_yyyyMMdd.csv。 - 校验:调用 Python 脚本
validate_schema.py,若列缺失则发告警邮件给 IT。 - 上传:把校验后的文件扔到
Folder_RawData,供合并脚本读取。
4. 报表合并脚本(核心 28 行)
# merge_reports.py
import pandas as pd, numpy as np, datetime as dt, pathlib, json
cfg = json.load(open('config.json'))
raw_dir = pathlib.Path(cfg['raw_folder'])
cols_std = cfg['std_columns'] # 标准化列名表
def normalize(df: pd.DataFrame) -> pd.DataFrame:
df.columns = df.columns.str.lower().str.replace(' ', '_')
for c in cols_std:
if c not in df.columns:
df[c] = np.nan
return df[cols_std]
frames = [normalize(pd.read_csv(f, thousands=',', dtype={'store_id': str}))
for f in raw_dir.glob('*.csv')]
merged = (pd.concat(frames, sort=False)
.assign(date=lambda x: pd.to_datetime(x['date'], errors='coerce'))
.query('date >= @dt.date.today().replace(day=1)'))
# 汇率换算
fx = pd.read_csv('fx_rates.csv', index_col='currency')
merged['amount_cny'] = merged.apply(
lambda r: r['amount'] * fx.at[r['currency'], 'rate'], axis=1)
merged.to_parquet('merged.parquet', index=False)
脚本跑完后把 merged.parquet 扔到共享盘,供异常检测模型读取。
5. 异常检测模型:孤立森林 + EWMA 双保险
5.1 数据分层
- L1:门店日维度(store_id, date, revenue, qty)
- L2:SKU 日维度(store_id, sku, date, revenue, qty)
5.2 算法组合
| 粒度 | 算法 | 异常类型 | 参数 | 解释 |
|---|---|---|---|---|
| 门店 | 孤立森林 | 突增/突降 | 0.05 污染率 | 无监督,无需标签 |
| SKU | EWMA | 趋势漂移 | span=7 | 捕捉缓慢偏离 |
5.3 训练与推理脚本(伪代码)
from sklearn.ensemble import IsolationForest
from statsmodels.tsa.holtwinters import ExponentialSmoothing
import joblib, pandas as pd
df = pd.read_parquet('merged.parquet')
features = ['amount_cny', 'qty']
# 孤立森林
iso = IsolationForest(contamination=0.05, random_state=42)
df['anomaly_score'] = iso.fit_predict(df[features])
anomaly_stores = df[df['anomaly_score'] == -1]['store_id'].unique()
# EWMA 趋势检测
def detect_drift(ts):
model = ExponentialSmoothing(ts, trend='add', seasonal=None).fit()
residual = ts - model.fittedvalues
return residual.abs().max() > 3 * residual.std()
sku_anomalies = (df.groupby(['store_id', 'sku'])['amount_cny']
.apply(detect_drift)
.reset_index(name='drift'))
joblib.dump(iso, 'iso_model.pkl')
6. 智能巡检报告:模板化生成
使用 python-pptx 填充 .pptx 模板:
from pptx import Presentation
prs = Presentation('template.pptx')
slide = prs.slides[0]
table = slide.shapes[1].table
for idx, row in enumerate(anomaly_stores[:5]):
table.cell(idx+1,0).text = row
table.cell(idx+1,1).text = "收入突增"
table.cell(idx+1,2).text = "已自动通知区域经理"
prs.save('巡检报告.pptx')
UiPath 在脚本执行完后,用 Send Outlook Mail Message 把 PPT 发给相应收件人,主题包含日期。
7. 端到端时序与 SLA
| 阶段 | 触发时间 | 耗时 | 失败补偿 |
|---|---|---|---|
| 数据采集 | 02:00 | 12 min | 重试 3 次,失败后钉钉告警 |
| 合并 & 汇率 | 02:15 | 3 min | 回滚到昨日数据 |
| 异常检测 | 02:20 | 5 min | 跳过,次日补跑 |
| 报告生成 | 02:25 | 1 min | 写空报告并通知 |
| 邮件推送 | 02:26 | <30 s | 写本地日志 |
8. 踩坑日记
-
CSV 编码陷阱
某区域销售系统导出的 CSV 是 GBK,UiPath 默认 UTF-8,导致合并脚本报错。解决:在Read CSV里强制encoding='gbk'。 -
孤立森林误判
节假日门店销量暴增,被模型标红。增加“节假日”特征后误判率下降 70 %。 -
Outlook 安全弹窗
无人值守机器人发邮件时弹窗阻止。用 UiPath 的Send Exchange Mail Message绕过。
9. 未来展望:从“月巡检”到“分钟级”
- 实时流:用 Kafka + Flink 把门店 POS 流水推送到模型,30 秒检测一次。
- 自愈动作:RPA 机器人根据异常类型自动在 ERP 里锁库存、停促销。
- AIOps:把日志、指标、异常分数喂进大模型,生成根因分析摘要。
10. 结语:让机器人成为第二大脑
RPA 不是简单的“脚本搬砖”,当我们把机器学习塞进流程,它就开始思考。报表合并、异常检测、巡检报告,本质是“数据 → 洞察 → 行动”的闭环。只要数据不断电,这个闭环就能 7×24 小时自我进化。
下次月底,当同事们还在 Ctrl+C、Ctrl+V,我们的机器人已经泡好咖啡,把 PPT 发到了老板邮箱——这大概就是科技带来最性感的温柔。
- 点赞
- 收藏
- 关注作者
评论(0)