每月初都要做的一件事:把银行流水和收费系统对一遍。人工核对几百条,眼花的代价就是错账。于是写了个脚本。
#思路
- 读取银行导出的回执表(列名不稳定,需要做映射)
- 读取系统导出的应收名单
- 按"姓名 + 金额"匹配,允许金额有 0.01 的误差
- 输出三类结果:已缴、金额不符、未缴
#核心代码
import pandas as pd
from decimal import Decimal
bank = pd.read_excel("bank.xlsx")
expect = pd.read_excel("expect.xlsx")
bank["name"] = bank["姓名"].astype(str).str.strip()
bank["amt"] = bank["交易金额"].apply(lambda x: Decimal(str(x)).quantize(Decimal("0.01")))
expect["amt"] = expect["应收金额"].apply(lambda x: Decimal(str(x)).quantize(Decimal("0.01")))
paid = set()
diff = []
for _, row in expect.iterrows():
hit = bank[(bank["name"] == row["姓名"]) &
((bank["amt"] - row["amt"]).abs() <= Decimal("0.01"))]
if len(hit):
paid.add(row["姓名"])
else:
near = bank[bank["name"] == row["姓名"]]
diff.append({**row.to_dict(), "实际": near["amt"].tolist()})
unpaid = expect[~expect["姓名"].isin(paid)]
pd.DataFrame(diff).to_excel("金额不符.xlsx", index=False)
unpaid.to_excel("未缴名单.xlsx", index=False)
print(f"已缴 {len(paid)} 人,金额不符 {len(diff)} 人,未缴 {len(unpaid)} 人")#三个必须处理的细节
- 金额用 Decimal 不用 float:
0.1 + 0.2 != 0.3在核对场景下是致命的 - 姓名去空格、去全角空格:
str.strip()不够,还要处理\u3000 - 重复交易:同月同名多笔要单独列出,不要自动合并
def norm(s):
return str(s).replace("\u3000", "").replace(" ", "").strip()#效果
原来半小时的活现在 3 秒出结果,而且不会再漏。人只负责复核脚本标出的异常项,这才是自动化该有的样子。