ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

UiPath财务RPA如何用Python脚本实现可审计、可扩展的数据处理

UiPath财务RPA如何用Python脚本实现可审计、可扩展的数据处理

简介:本资源是一套专为财务自动化场景设计的UiPath RPA与Python深度集成工具包,面向财务人员、RPA开发初学者及希望提升数据处理能力的自动化实践者,解决UiPath原生功能在复杂财务数据清洗、校验、透视分析及异常识别等环节的局限性。压缩包共16个文件,含7个JSON配置文件(定义流程参数与数据映射)、2个XLSX示例报表(含原始数据与结果模板)、1个核心Python脚本(complex_pivot.py)及对应编译后的PYC文件、1个UiPath工作流XAML、1个NuGet包(UiPath_Python.1.0.1.nupkg)用于环境集成,另有SQLite数据库、PNG结果图及项目元数据文件,整体大小11.58MB。目前已有565人学习下载。用户可直接解压部署至UiPath指定目录,快速调用Python脚本实现财务数据自动清洗、动态透视汇总与异常逻辑判断,无需从零编写环境桥接代码;配套结构清晰,含完整项目配置(project.json、design.json)、元素管理(dataManagerElementsOrder.json)和本地调试支持(.vscode设置),显著降低RPA+Python协同开发门槛。

1. UiPath RPA财务机器人配套Python脚本:不是“胶水代码”,而是财务流程闭环里最关键的那颗螺丝

你花两周用UiPath搭好了一个自动下载银行回单、识别PDF金额、校验付款单号、写入ERP凭证的财务机器人——运行稳定,日均处理300+笔付款。但第三天凌晨2点,它卡在了「解析某家银行新出的加密PDF」上,报错PyPDF2.utils.PdfReadError: EOF marker not found;第五天,财务同事临时要求把所有金额按币种拆成三张Excel分表,你翻遍UiPath Studio的Excel Activities,发现没有原生支持「按列值动态分表+自动命名+保留原始格式」的组件;第七天,审计组要一份带时间戳、操作人、原始文件哈希的全链路执行日志,而UiPath Orchestrator的日志导出是纯文本,没法直接做交叉比对。

这时候,“UiPath RPA财务机器人配套Python脚本”就不是锦上添花的选配项,而是让整个自动化流程真正具备可维护性、可扩展性、可审计性的刚性需求。它不替代UiPath——UiPath负责流程调度、UI交互、异常捕获、权限管控;Python脚本则专攻UiPath不擅长的三件事:复杂非结构化数据解析(PDF/OCR/邮件HTML)、高自由度数据加工(多维分组/动态建模/跨系统映射)、与企业级工具链深度集成(SAP RFC调用/Oracle JDBC/钉钉Webhook)。这不是写几个subprocess.run()调Python.exe的权宜之计,而是把Python作为UiPath工作流中一个可调试、可单元测试、可版本管理、可独立部署的原子能力模块来设计。适合已经跑通基础UiPath流程、正被“最后一公里”数据处理卡住的财务RPA工程师,也适合想用Python能力反向增强UiPath项目交付深度的技术顾问。


2. 把Python脚本嵌入UiPath工作流:从“外部调用”到“原生集成”的三层演进路径

UiPath调用Python的方式不止一种,但90%的财务RPA项目卡在第一层就止步不前——用Run Python Script活动硬塞50行代码,结果报错时连变量名都找不到。真正的配套,必须按能力边界分层设计:底层做数据硬核处理,中层做流程逻辑封装,顶层做UiPath原生交互。下面这三套方案,我按项目阶段推荐使用顺序,每套都附可直接粘贴的实操代码和参数说明。

2.1 第一层:用UiPath原生Python活动做轻量脚本(适合POC验证)

UiPath Studio内置的Run Python Script活动,本质是启动一个临时Python子进程。它适合执行<100行、无外部依赖、纯计算类任务,比如:校验发票号码是否符合GB/T 18769-2002编码规则、生成MD5哈希用于文件防篡改比对、将日期字符串20240520转为2024-05-20。

# 在UiPath的"Run Python Script"活动内直接粘贴此代码 import re import hashlib from datetime import datetime # 输入参数由UiPath传入(需在活动属性中定义In Arguments) invoice_no = "F20240520001" # UiPath传入的字符串 raw_date = "20240520" # UiPath传入的字符串 # 规则校验:发票号必须以F开头,后接8位年月日+3位序号 pattern = r'^F\d{8}\d{3}$' is_valid = bool(re.match(pattern, invoice_no)) # 日期转换 try: formatted_date = datetime.strptime(raw_date, "%Y%m%d").strftime("%Y-%m-%d") except ValueError: formatted_date = "INVALID_DATE" # 生成文件哈希(模拟对原始PDF做摘要) file_hash = hashlib.md5(invoice_no.encode()).hexdigest()[:8] # 输出结果(UiPath通过Out Arguments接收) # 注意:必须用字典返回,key名需与UiPath Out Arguments定义一致 {"is_valid": is_valid, "formatted_date": formatted_date, "file_hash": file_hash}

逻辑说明:这段代码完全在UiPath沙箱内执行,不依赖外部Python环境。UiPath会自动注入json、re、hashlib等标准库。关键点在于返回值必须是字典,且key名严格匹配UiPath活动配置的Out Arguments名称(如is_valid),否则UiPath收不到结果。
参数说明:In Arguments需在UiPath活动属性中手动添加invoice_no(String)、raw_date(String);Out Arguments添加is_valid(Boolean)、formatted_date(String)、file_hash(String)。不要试图在这里import pandas——UiPath默认Python环境不含第三方库。

2.2 第二层:用External Python Script活动调用本地.py文件(适合中等复杂度)

当脚本需要pandas处理Excel、pdfplumber解析PDF、openpyxl写入带样式的报表时,UiPath内置环境就不够用了。此时应切换到External Python Script活动,指向你本地已配置好的Python环境中的.py文件。这是财务RPA最常用的配套方式——既保持UiPath流程主干清晰,又释放Python的数据处理能力。

第一步:准备Python环境(关键!)
不要用UiPath安装包自带的Python。在Windows上,我固定用conda create -n uipath-finance python=3.9创建独立环境,然后装必要库:

conda activate uipath-finance pip install pandas openpyxl pdfplumber PyPDF2 python-docx requests

为什么选conda?财务场景常需openpyxl(写Excel样式)和pdfplumber(精准提取PDF表格),这两个库在pip下容易因lxml编译失败。conda预编译二进制包,一次装完不翻车。

第二步:编写可被UiPath调用的Python脚本(finance_processor.py)

# finance_processor.py —— 存放在UiPath项目目录下的Scripts/子文件夹 import sys import json import pandas as pd from pathlib import Path def main(): # UiPath通过命令行参数传入JSON字符串(含输入文件路径、参数) if len(sys.argv) < 2: print(json.dumps({"error": "Missing input JSON"})) return try: # 解析UiPath传来的参数 input_data = json.loads(sys.argv[1]) input_excel = input_data["input_excel"] output_folder = input_data["output_folder"] currency_col = input_data.get("currency_col", "币种") # 默认列名 # 读取Excel(支持.xlsx和.xls) df = pd.read_excel(input_excel) # 按币种分表(核心财务需求) for currency, group in df.groupby(currency_col): # 清理币种名用于文件名(去掉空格/斜杠) safe_currency = currency.replace(" ", "_").replace("/", "_") output_path = Path(output_folder) / f"付款明细_{safe_currency}.xlsx" # 写入Excel,保留原始格式(openpyxl引擎) with pd.ExcelWriter(output_path, engine='openpyxl') as writer: group.to_excel(writer, index=False, sheet_name="明细") # 自动调整列宽(财务报表刚需) worksheet = writer.sheets["明细"] for column in worksheet.columns: max_length = 0 column_letter = column[0].column_letter for cell in column: try: if len(str(cell.value)) > max_length: max_length = len(str(cell.value)) except: pass adjusted_width = min(max_length + 2, 50) # 限制最大宽度 worksheet.column_dimensions[column_letter].width = adjusted_width print(json.dumps({"status": "success", "output_files": [str(p) for p in Path(output_folder).glob("*.xlsx")]})) except Exception as e: print(json.dumps({"error": str(e), "traceback": ""})) # 简化错误输出,避免UiPath解析失败 if __name__ == "__main__": main()

第三步:在UiPath中配置External Python Script活动

  • Python Interpreter Path: 填入conda环境路径,例如C:\Users\YourName\miniconda3\envs\uipath-finance\python.exe
  • Script Path: 填入finance_processor.py的绝对路径,如C:\RPA\FinanceBot\Scripts\finance_processor.py
  • Arguments: 填入JSON字符串(UiPath用JsonConvert.ToString()生成):
    {"input_excel": "C:\\RPA\\FinanceBot\\Input\\payment_raw.xlsx", "output_folder": "C:\\RPA\\FinanceBot\\Output", "currency_col": "币种"}
  • Result: 接收stdout输出的JSON字符串,再用UiPath的Deserialize Json活动转为字典。

为什么这样设计?

  • 所有业务逻辑在.py文件里,可单独用python finance_processor.py测试,无需启动UiPath;
  • UiPath只负责传参、收结果、处理异常,流程图干净得像财务报表;
  • 错误信息统一JSON输出,UiPath能精准捕获error字段做重试或告警。

2.3 第三层:用UiPath Python Scope活动实现双向变量共享(适合高耦合场景)

当Python脚本需要反复读写UiPath变量(比如循环处理100个PDF,每次把解析结果存入UiPath的DataTable),或者需要在Python中直接调用UiPath的Log Message、Throw等系统活动时,Python Scope是唯一选择。它让Python代码运行在UiPath主线程内,共享同一内存空间。

# 在UiPath的Python Scope活动内编写(注意:此处不能用print,要用UiPath日志) import os import tempfile from datetime import datetime # UiPath传入的变量(已在Scope的In Arguments中定义) pdf_files = ["C:\\RPA\\Input\\inv_001.pdf", "C:\\RPA\\Input\\inv_002.pdf"] # List<String> output_table = [] # UiPath传入的空List<Dictionary<String, Object>> # 用临时目录避免权限问题(财务服务器常禁写C:\) temp_dir = tempfile.mkdtemp() for i, pdf_path in enumerate(pdf_files): try: # 模拟PDF解析(实际用pdfplumber) invoice_no = f"INV-{i+1000}" amount = 12345.67 + i * 100 issue_date = datetime.now().strftime("%Y-%m-%d") # 构造结果字典,字段名必须与UiPath DataTable列名一致 row = { "发票号": invoice_no, "金额": amount, "开票日期": issue_date, "来源文件": os.path.basename(pdf_path) } output_table.append(row) # 直接追加到UiPath传入的列表 # 向UiPath日志写入进度(关键!便于追踪哪份PDF出错) LogMessage(f"✅ 已解析 {os.path.basename(pdf_path)} -> {invoice_no}", "Info") except Exception as e: LogMessage(f"❌ 解析失败 {os.path.basename(pdf_path)}: {str(e)}", "Error") # 可在此处抛出UiPath异常,触发Try Catch块 Throw(f"PDF解析异常: {pdf_path}") # 将Python列表转为UiPath DataTable(需在Scope Out Arguments中定义output_dt) # UiPath会自动完成类型转换 output_dt = output_table

关键约束:Python Scope活动要求UiPath Robot安装时勾选Python Support,且Python解释器路径需在UiPath Studio的Tools > Options > Python中正确配置。它不支持subprocess或threading——因为要保证与UiPath主线程同步。
血泪经验:财务场景中,千万别在Python Scope里做耗时操作(如网络请求、大文件IO)。如果必须,用Invoke Code活动起后台线程,再用Wait For同步结果,否则UiPath界面会假死。


3. 财务RPA专用Python脚本开发规范:让代码经得起审计、换人、升级三重考验

财务流程天生带着强合规属性:每一笔付款都要留痕,每一次数据修改都要可追溯,每一个脚本变更都要走审批。这意味着配套Python脚本不能是“能跑就行”的野路子,必须建立一套面向财务场景的开发规范。以下是我给团队定的四条铁律,每一条都来自真实翻车现场。

3.1 铁律一:所有输入/输出路径必须参数化,禁止硬编码绝对路径

现象:脚本里写死df = pd.read_excel("C:\\Finance\\RawData\\2024Q2.xlsx"),上线后运维把文件夹移到D:\RPA_Data\,脚本直接报错FileNotFoundError,财务付款中断2小时。
原因:UiPath工作流可配置路径参数,但Python脚本若硬编码,就切断了UiPath的参数传递链,变成两个孤岛。
解决:强制所有路径通过sys.argv或函数参数传入,并在脚本开头做存在性校验:

import sys import os from pathlib import Path def validate_paths(input_path: str, output_dir: str): """财务脚本启动时必检:输入文件存在,输出目录可写""" input_file = Path(input_path) output_folder = Path(output_dir) if not input_file.exists(): raise FileNotFoundError(f"❌ 输入文件不存在: {input_file}") if not input_file.is_file(): raise ValueError(f"❌ 输入路径不是文件: {input_file}") if not output_folder.exists(): output_folder.mkdir(parents=True, exist_ok=True) if not os.access(output_folder, os.W_OK): raise PermissionError(f"❌ 输出目录不可写: {output_folder}") return input_file, output_folder # 在main()函数开头调用 if __name__ == "__main__": if len(sys.argv) != 3: print("Usage: python script.py <input_excel> <output_folder>") sys.exit(1) input_file, output_folder = validate_paths(sys.argv[1], sys.argv[2]) # 后续业务逻辑...

提示:UiPath传参时,用Path.Combine拼接路径,避免Windows/Linux路径分隔符差异。例如UiPath中:Path.Combine("C:\RPA\Input", "data.xlsx")。

3.2 铁律二:金额、日期、税率等关键字段必须做类型强校验,拒绝“模糊匹配”

现象:银行回单PDF里金额写成¥12,345.67,脚本用float("12,345.67")直接报错;或者日期是2024/05/20,脚本用datetime.strptime(date_str, "%Y-%m-%d")崩溃。
原因:财务数据格式千奇百怪,但Python的float()、int()、datetime对格式极其敏感,一个逗号、一个空格就全盘崩溃。
解决:写专用清洗函数,用正则兜底,失败时明确报错而非静默跳过:

import re from decimal import Decimal def safe_parse_amount(text: str) -> Decimal: """财务金额安全解析:支持¥、$、逗号分隔、括号负数""" if not isinstance(text, str): raise TypeError(f"金额必须是字符串,得到 {type(text)}") # 移除货币符号、空格、换行 clean = re.sub(r'[^\d\.\-\(\)]', '', text.strip()) # 处理括号负数:"(123.45)" -> "-123.45" if clean.startswith('(') and clean.endswith(')'): clean = '-' + clean[1:-1] try: return Decimal(clean) except (ValueError, InvalidOperation) as e: raise ValueError(f"❌ 无法解析金额 '{text}' -> 清洗后 '{clean}': {e}") def safe_parse_date(text: str, formats: list = None) -> str: """财务日期安全解析,返回ISO格式字符串""" if formats is None: formats = ["%Y-%m-%d", "%Y/%m/%d", "%Y.%m.%d", "%d-%m-%Y", "%d/%m/%Y"] for fmt in formats: try: return datetime.strptime(text.strip(), fmt).strftime("%Y-%m-%d") except ValueError: continue raise ValueError(f"❌ 无法解析日期 '{text}',尝试格式: {formats}") # 使用示例 try: amount = safe_parse_amount("¥12,345.67") date_str = safe_parse_date("2024/05/20") except ValueError as e: LogMessage(f"财务字段校验失败: {e}", "Error") Throw(str(e))

为什么用Decimal不用float?财务计算必须精确到分,float的二进制浮点误差会导致0.1 + 0.2 != 0.3,而Decimal('0.1') + Decimal('0.2') == Decimal('0.3')。这是审计红线。

3.3 铁律三:所有外部依赖库必须锁定版本,用requirements.txt固化

现象:脚本用pandas==1.5.3正常,某天运维更新系统,pip install pandas装了2.0.0,df.to_excel()的index=False参数失效,导出Excel多了一列索引,财务拒收。
原因:未锁定依赖版本,导致环境漂移。
解决:在UiPath项目根目录下放requirements.txt,内容如下:

# 财务RPA专用Python依赖(2024-Q2) pandas==1.5.3 openpyxl==3.1.2 pdfplumber==0.10.2 PyPDF2==3.0.1 python-docx==0.8.11 requests==2.31.0 # 安装命令:pip install -r requirements.txt --force-reinstall

操作指南:

  1. 在conda环境中执行pip freeze > requirements.txt生成初始文件;
  2. 手动删掉pip、setuptools等无关项,只留业务库;
  3. 版本号用==严格锁定,避免>=引入不兼容更新;
  4. UiPath部署时,先执行pip install -r requirements.txt --force-reinstall。

3.4 铁律四:每个脚本必须自带单元测试,覆盖至少3个典型财务异常场景

现象:脚本上线后,某家供应商突然在发票号里加了字母INV-2024-ABC-001,原有正则r'INV-\d{4}-\d{3}'失效,但没人知道——因为没写测试。
原因:财务数据变异是常态,靠人工测100个样本不现实。
解决:用pytest写最小化测试,放在tests/目录下,每次代码提交前必须通过:

# tests/test_finance_utils.py import pytest from finance_utils import safe_parse_amount, safe_parse_date class TestFinanceUtils: def test_safe_parse_amount_normal(self): assert safe_parse_amount("¥12,345.67") == 12345.67 assert safe_parse_amount("(123.45)") == -123.45 def test_safe_parse_amount_edge_cases(self): # 空格、换行、货币符号混合 assert safe_parse_amount(" $ 999.99 ") == 999.99 # 全角字符(常见于OCR识别错误) assert safe_parse_amount("¥123.45") == 123.45 def test_safe_parse_amount_failure(self): with pytest.raises(ValueError) as excinfo: safe_parse_amount("INVALID") assert "无法解析金额" in str(excinfo.value) def test_safe_parse_date_variants(self): assert safe_parse_date("2024-05-20") == "2024-05-20" assert safe_parse_date("2024/05/20") == "2024-05-20" assert safe_parse_date("20/05/2024") == "2024-05-20" # DD/MM/YYYY # 运行命令:pytest tests/ -v

落地技巧:UiPath CI/CD流水线中,在执行Python脚本前,加一步pytest tests/ --tb=short。失败则阻断发布——财务流程不容“差不多”。


4. 财务RPA Python脚本避坑指南:5个让财务总监拍桌子的真实问题

财务场景的特殊性,让很多通用Python技巧在这里变成“玄学陷阱”。以下5个问题,全部来自我陪客户熬过的夜、修过的bug、赔过的咖啡。每一条都按「现象 → 原因 → 解决」展开,拒绝模糊描述。

4.1 现象:pdfplumber解析银行回单PDF,表格内容错位,金额列跑到备注列里

原因:银行PDF用“虚线表格线”或“背景色块”模拟表格,pdfplumber默认的table_settings无法识别,强行按坐标切分导致错行。
解决:关闭自动表格检测,用extract_words()获取所有文字块,再按Y坐标聚类分组:

import pdfplumber def extract_bank_table(pdf_path: str): with pdfplumber.open(pdf_path) as pdf: page = pdf.pages[0] # 获取所有文字块(含坐标) words = page.extract_words( x_tolerance=2, # X方向容差2px y_tolerance=3, # Y方向容差3px keep_blank_chars=True ) # 按Y坐标分组(每行一个list) rows = {} for w in words: y_key = round(w['top'] / 10) * 10 # 每10px为一行 if y_key not in rows: rows[y_key] = [] rows[y_key].append(w) # 每行按X坐标排序,拼接文字 table_data = [] for y_key in sorted(rows.keys()): row_words = sorted(rows[y_key], key=lambda x: x['x0']) row_text = " ".join([w['text'] for w in row_words]) table_data.append(row_text.split()) # 按空格切分字段 return table_data # 使用:table_data = extract_bank_table("bank_statement.pdf")

提示:财务PDF解析没有银弹。先用page.to_image().save("debug.png")保存页面图像,用画图工具量坐标,再调x_tolerance/y_tolerance参数。

4.2 现象:openpyxl写入Excel后,财务同事说“数字变成了文本,SUM公式不生效”

原因:openpyxl默认把所有数据当字符串写入,即使你传的是int或float,Excel也识别为文本格式(左上角绿色小三角)。
解决:显式设置单元格数据类型,并用number_format指定格式:

from openpyxl.styles import numbers def write_with_type(ws, row_idx, col_idx, value): """写入数值并设置Excel数字格式""" cell = ws.cell(row=row_idx, column=col_idx, value=value) if isinstance(value, (int, float)): # 强制设为数值类型 cell.data_type = 'n' # 设置会计格式(带千分位、2位小数) cell.number_format = numbers.FORMAT_NUMBER_COMMA_SEPARATED1 elif isinstance(value, datetime): cell.data_type = 'd' cell.number_format = numbers.FORMAT_DATE_DATETIME else: cell.data_type = 's' # 字符串 # 使用示例 ws = workbook.active write_with_type(ws, 1, 1, 12345.67) # 写入后Excel自动识别为数字

4.3 现象:脚本在UiPath Robot上运行正常,但用Schedule定时启动时报ModuleNotFoundError: No module named 'pandas'

原因:UiPath Studio开发时用的是你的用户环境(conda),但UiPath Robot服务默认以Local System账户运行,找不到你的conda环境。
解决:两种方案任选其一:

  • 推荐:在UiPath Orchestrator中,为该Process配置Runtime Settings→Python Interpreter,填入conda环境的完整路径(如C:\Users\YourName\miniconda3\envs\uipath-finance\python.exe);
  • 备选:在Robot服务器上,用管理员权限运行conda init powershell,然后重启Robot服务,让系统级PowerShell能识别conda。

4.4 现象:处理1000+张发票PDF时,脚本内存暴涨到4GB,Robot直接OOM崩溃

原因:pdfplumber打开PDF后不关闭,对象持续驻留内存;pandas.DataFrame加载大文件未指定dtype,默认用object类型吃内存。
解决:显式资源管理和类型优化:

import gc def process_pdfs_safely(pdf_list: list): results = [] for pdf_path in pdf_list: # 显式控制pdfplumber生命周期 with pdfplumber.open(pdf_path) as pdf: page = pdf.pages[0] text = page.extract_text() # ... 解析逻辑 results.append({"file": pdf_path, "text": text}) # 强制垃圾回收(关键!) gc.collect() # pandas加载时指定dtype,节省50%内存 df = pd.read_excel("large_file.xlsx", dtype={ "发票号": "string", "金额": "float32", # 不用float64 "状态": "category" # 分类变量用category }) return df

4.5 现象:脚本调用requests.post()上传凭证到ERP接口,偶尔超时,UiPath报错后整个流程中断

原因:网络抖动是常态,但脚本没做重试,一次超时就终止。
解决:用urllib3.util.retry.Retry封装重试逻辑,失败时返回结构化错误:

import requests from urllib3.util.retry import Retry from requests.adapters import HTTPAdapter def robust_post_to_erp(url: str, data: dict, timeout: int = 30) -> dict: """带重试的ERP接口调用""" session = requests.Session() retry_strategy = Retry( total=3, # 总共重试3次 status_forcelist=[429, 500, 502, 503, 504], # 遇到这些状态码重试 backoff_factor=1, # 退避因子:1s, 2s, 4s allowed_methods=["POST"] # 只对POST重试 ) adapter = HTTPAdapter(max_retries=retry_strategy) session.mount("http://", adapter) session.mount("https://", adapter) try: response = session.post(url, json=data, timeout=timeout) response.raise_for_status() # 抛出4xx/5xx异常 return {"status": "success", "response": response.json()} except requests.exceptions.RequestException as e: return {"status": "failed", "error": str(e), "url": url} # UiPath中接收返回字典,判断status做分支处理

5. 财务RPA Python脚本的终极验证法:用“三张表”代替口头承诺

写完脚本不等于交付完成。财务流程的严肃性,要求我们用可量化、可存档、可复现的方式证明:“这个脚本真的能扛住生产环境”。我坚持用三张表完成最终验证——它们不是文档,而是直接嵌入UiPath工作流的自动化检查点。

5.1 表一:输入数据质量检查表(Input Health Check)

在Python脚本执行前,先用UiPath的Invoke Code活动跑一段轻量Python,生成输入文件的健康快照。这张表不处理业务,只回答三个问题:文件是否存在?编码是否UTF-8?关键列是否缺失?

# input_health_check.py —— UiPath调用此脚本,传入input_path import sys import chardet import pandas as pd from pathlib import Path def check_input_health(file_path: str) -> dict: p = Path(file_path) if not p.exists(): return {"status": "ERROR", "reason": "File not found"} # 检测文件编码(避免GBK乱码) with open(p, 'rb') as f: raw_data = f.read(10000) # 读前10KB encoding = chardet.detect(raw_data)['encoding'] or 'utf-8' # 检查Excel关键列(财务必有:发票号、金额、日期) try: df = pd.read_excel(p, nrows=5) # 只读前5行,极速检查 missing_cols = [] for col in ["发票号", "金额", "开票日期"]: if col not in df.columns: missing_cols.append(col) return { "status": "OK" if not missing_cols else "WARN", "encoding": encoding, "missing_columns": missing_cols, "row_count": len(df) } except Exception as e: return {"status": "ERROR", "reason": f"Read failed: {e}"} if __name__ == "__main__": if len(sys.argv) != 2: print('{"status": "ERROR", "reason": "Missing file path"}') exit(1) result = check_input_health(sys.argv[1]) print(json.dumps(result))

UiPath集成:将此脚本输出存入UiPath变量health_result,用If活动判断health_result["status"] == "ERROR",则Log Message并Stop Process。这才是真正的“准入检查”,不是靠人眼扫一眼文件名。

5.2 表二:处理过程黄金指标表(Golden Metrics Dashboard)

脚本执行中,实时收集5个财务黄金指标,写入一个metrics.json文件。这不是日志,而是给财务总监看的仪表盘:

指标名计算方式示例值业务意义
processed_count成功解析的PDF数量127日处理量基线
amount_sum所有解析金额总和(Decimal精度)"1234567.89"资金流水总额
currency_distribution各币种金额占比{"CNY": 85.2, "USD": 12.1, "EUR": 2.7}外汇风险分布
avg_process_time_ms单文件平均处理毫秒数342.5系统性能基线
error_rate_percent失败文件数/总文件数*1000.8流程健壮性
# 在主处理循环中埋点 import time import json from pathlib import Path metrics = { "processed_count": 0, "amount_sum": "0.00", "currency_distribution": {}, "avg_process_time_ms": 0.0, "error_rate_percent": 0.0, "start_time": time.time() } # 处理每个PDF时 start_time = time.time() try: result = parse_pdf(pdf_path) metrics["processed_count"] += 1 # 累加金额(用Decimal避免浮点误差) metrics["amount_sum"] = str(Decimal(metrics["amount_sum"]) + result["amount"]) # 统计币种 cur = result["currency"] metrics["currency_distribution"][cur] = metrics["currency_distribution"].get(cur, 0) + result["amount"] except Exception as e: pass # 错误已记录,此处不中断 finally: elapsed = (time.time() - start_time) * 1000 metrics["avg_process_time_ms"] = ( (metrics["avg_process_time_ms"] * (metrics["processed_count"] - 1) + elapsed) / metrics["processed_count"] if metrics["processed_count"] > 0 else elapsed ) # 所有文件处理完后,写入metrics.json metrics["end_time"] = time.time() metrics["error_rate_percent"] = ( (len(error_files) / len(all_files)) * 100 if all_files else 0 ) with open("metrics.json", "w", encoding="utf-8") as f: json.dump(metrics, f, ensure_ascii=False, indent=2)

价值:这张表每天自动生成,财务总监打开metrics.json就能看到:今天处理了多少钱、有没有异常波动、系统慢不慢。把技术指标翻译成财务语言,是RPA工程师的核心竞争力。

5.3 表三:输出数据可审计性表(Audit Trail Manifest)

财务审计最怕“黑匣子”。所以每个脚本必须生成一个audit_manifest.json,记录每一笔输出

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进