2. 银行流水 Excel 多表合并与字段对齐
任务说明
银行导出的流水常分散在多个 Excel 工作表(或文件)中,列名不一致(如“交易金额”“金额(元)”“发生额”),金额单位也可能混用(元/万元)。本案例用 pandas 把多表纵向合并为一张表,完成列名对齐与金额单位统一(全部换算为“元”),并输出合并结果供后续审计分析。
环境与依赖
pip install pandas openpyxl
实现代码
import pandas as pd
# 1. 列名对齐映射:不同来源列名 -> 统一标准列名
COLUMN_MAP = {
"交易日期": "date", "日期": "date",
"交易金额": "amount", "金额(元)": "amount", "发生额": "amount",
"摘要": "summary", "备注": "summary",
"对方户名": "counterparty", "对方账户": "counterparty",
}
# 2. 各表金额单位:'yuan' 表示已是元,'wan' 表示万元需 *10000
UNIT_MAP = {"Sheet1": "yuan", "Sheet2": "wan", "Sheet3": "yuan"}
def normalize(df: pd.DataFrame, unit: str) -> pd.DataFrame:
"""对齐列名并统一金额单位为元。"""
df = df.rename(columns=COLUMN_MAP)
# 只保留标准列,缺失列补空
for col in ["date", "amount", "summary", "counterparty"]:
if col not in df.columns:
df[col] = pd.NA
df = df[["date", "amount", "summary", "counterparty"]].copy()
# 金额转数值并统一单位
df["amount"] = pd.to_numeric(df["amount"], errors="coerce")
if unit == "wan":
df["amount"] = df["amount"] * 10000
df["date"] = pd.to_datetime(df["date"], errors="coerce")
return df
def merge_sheets(path: str) -> pd.DataFrame:
"""读取 Excel 所有工作表,合并为一张对齐后的表。"""
sheets = pd.read_excel(path, sheet_name=None) # dict: {表名: DataFrame}
frames = []
for name, df in sheets.items():
unit = UNIT_MAP.get(name, "yuan")
df = normalize(df, unit)
df["source_sheet"] = name # 保留来源,便于审计追溯
frames.append(df)
merged = pd.concat(frames, ignore_index=True)
return merged
if __name__ == "__main__":
result = merge_sheets("bank_flow.xlsx")
result.to_excel("merged_flow.xlsx", index=False)
print(result)
print("总记录数:", len(result))
运行与验证
准备一个 bank_flow.xlsx,包含 Sheet1/Sheet2/Sheet3 三个工作表,列名与单位按上面 COLUMN_MAP、UNIT_MAP 设置(例如 Sheet2 的“发生额”以万元计)。运行脚本后:
- 控制台打印合并后的表,列应为
date, amount, summary, counterparty, source_sheet; - 生成
merged_flow.xlsx,行数等于三张表数据行数之和; - 抽查 Sheet2 的记录,其
amount应等于原值 ×10000,与 Sheet1/Sheet3 的元值口径一致。
判定通过:合并表列名统一、金额单位一致(均为元)、来源可追溯,且无因列名不匹配导致的整列丢失。
关键点
sheet_name=None 一次性读入全部工作表;rename 完成列名对齐,缺失列补 NA 保证结构一致;单位换算在数值化之后进行,避免字符串参与乘法;source_sheet 列保留数据来源,满足审计可追溯要求。