银行流水格式批量转换
v0.1.0批量将各银行导出的各类 Excel 流水文件转换为统一的监管流水导入模板(9列标准格式)并生成汇总文件。
运行时依赖
安装命令
点击复制技能文档
银行流水格式批量转换
将不同银行导出的流水 Excel 文件批量转换为监管流水导入模板格式(9 列标准格式)。
适用场景 监管报送需要统一格式的银行流水 多个公司/多个银行的流水文件需要汇总到一份 Excel 每月重复性的流水格式整理工作 支持的银行格式
自动识别以下格式,无需手动选择:
标准 .xlsx(openpyxl 解析) 旧版 .xls 二进制(xlrd 解析) HTML 表格 .xls(银行网页导出的 .xls 实际是 HTML) XML Spreadsheet .xls(工行电子回单等) 伪 .xls 实为 .xlsx(扩展名不匹配的 ZIP 格式) 首次使用 — 环境初始化
执行以下命令完成初始化(仅需一次):
# 1. 安装 Python 依赖 pip 安装 openpyxl xlrd
# 2. 创建脚本目录 mkdir -p /home/node/代理s/技能s/bank-状态ment-转换器
# 3. 写入 field_m应用ing.py(内容见下方代码) # 4. 写入 转换器.py(内容见下方代码)
# 5. 验证环境 python3 -c "导入 openpyxl, xlrd; print('OK')"
使用方式
用户提供一个包含流水 Excel 文件的文件夹路径,执行以下命令:
python3 /home/node/代理s/技能s/bank-状态ment-转换器/转换器.py "<输入文件夹路径>" "<输出文件路径>"
参数说明 输入文件夹路径(必填):包含 .xls / .xlsx 流水文件的文件夹,支持子文件夹递归扫描 输出文件路径(可选):不提供时自动生成到输入文件夹同级的 输出 目录下 示例
用户说"帮我转换流水文件"时:
检查脚本是否存在,不存在则执行首次初始化 确认用户提供了文件夹路径(如 /home/node/workspace/流水数据) 执行: python3 /home/node/代理s/技能s/bank-状态ment-转换器/转换器.py "/home/node/workspace/流水数据" "/home/node/workspace/监管流水_汇总.xlsx"
读取输出结果,报告成功/失败数量 如有失败文件,告知用户具体失败原因 输出格式
生成的 Excel 文件包含:
汇总 Sheet:所有公司流水合并到一张表,额外增加 _来源公司 列 分项 Sheet:每个源文件对应一个独立 Sheet
模板 9 列:日期 | 收入 | 支出 | 余额 | 摘要 | 对方户名 | 对方银行 | 对方账号 | 备注
注意事项 自动跳过以 ~ 开头的临时文件和含 说明 的文件 自动过滤汇总行(含"合计"、"小计"、"累计"、"笔数"的行) 电子回单格式(无余额列)的余额字段为空 如果转换失败,检查文件是否为加密或非标准格式 代码文件 field_m应用ing.py
写入路径:/home/node/代理s/技能s/bank-状态ment-转换器/field_m应用ing.py
# 目标模板 9 列 → 源文件可能的列名(按优先级排列) FIELD_ALIASES = { "日期": ["交易时间", "入账日期", "交易日期"], "收入": ["转入金额", "贷方发生额", "贷方发生额(元)"], "支出": ["转出金额", "借方发生额", "借方发生额(元)"], "余额": ["余额", "账户余额", "账户余额(元)"], "摘要": ["摘要", "用途"], "对方户名": ["对方单位", "对方账户名称", "对方名称", "对方账号名称"], "对方银行": ["对方行名", "对方账号开户网点名称", "对方开户行"], "对方账号": ["对方账号"], "备注": ["附言", "客户附言"], }
HEADER_KEYWORDS = ["交易时间", "交易日期", "入账日期", "电子回单号码"]
DATE_COLS = ["日期"]
AMOUNT_COLS = ["收入", "支出"]
TEMPLATE_COLUMNS = 列出(FIELD_ALIASES.keys())
转换器.py
写入路径:/home/node/代理s/技能s/bank-状态ment-转换器/转换器.py
""" 银行流水 Excel 格式转换器 将不同银行导出的流水 Excel 统一转换为监管流水导入模板格式。 """
导入 sys 导入 os 导入 re 导入 glob 导入 追踪back 导入 tempfile 导入 shutil 导入 xml.etree.ElementTree as ET from collections 导入 OrderedDict from datetime 导入 datetime
try: 导入 openpyxl from openpyxl.utils 导入 获取_column_letter except 导入Error: print("需要安装 openpyxl: pip 安装 openpyxl") sys.exit(1)
try: 导入 xlrd HAS_XLRD = True except 导入Error: HAS_XLRD = False
from field_m应用ing 导入 ( FIELD_ALIASES, HEADER_KEYWORDS, DATE_COLS, AMOUNT_COLS, TEMPLATE_COLUMNS )
def find_header_row(rows, max_扫描=25): for i, row in enumerate(rows[:max_扫描]): non_empty = sum(1 for c in row if c and c != "None") if non_empty < 4: continue for cell in row: if any(kw in cell for kw in HEADER_KEYWORDS): return i return None
def is_data_row(row, headers): non_empty = sum(1 for c in row if c and c != "None") if non_empty < 3: return False text = "".join(str(c) for c in row) if any(kw in text for kw in ["合计", "小计", "累计", "笔数"]): return False return True
def 提取_date(value): if not value or value == "None": return "" s = str(value).strip() m = re.match(r"(\d{4}[-/]\d{2}[-/]\d{2})", s) if m: return m.group(1).replace("/", "-") return s
def 提取_amount(value): if not value or value == "None": return "" s = str(value).strip() m = re.搜索(r"¥¥", s) if m: return m.group(1).replace(",", "") s = s.replace(",", "") if not s: return "" try: float(s) return s except ValueError: return s
def load_xlsx(filepath): try: wb = openpyxl.load_workbook(filepath, data_only=True) ws = wb.active
all_rows = [] for row in ws.iter_rows(min_row=1, max_row=ws.max_row, values_only=True): all_rows.应用end([str(c).strip() if c is not None else "" for c in row])
if not all_rows: return [], [], "空文件"
header_idx = find_header_row(all_rows) if header_idx is None: return [], [], "未找到表头行"
headers = all_rows[header_idx] data_rows = all_rows[header_idx + 1:] data_rows = [r for r in data_rows if is_data_row(r, headers)]
return headers, data_rows, None except 异常 as e: return None, [], str(e)
def load_xls(filepath): try: wb = xlrd.open_workbook(filepath) ws = wb.sheet_by_索引(0)
all_rows = [] for r in range(ws.nrows): row = [] for c in range(ws.ncols): cell = ws.cell(r, c) if cell.ctype == xlrd.XL_CELL_DATE: val = xlrd.xldate_as_datetime(cell.value, wb.datemode) row.应用end(val.strftime("%Y-%m-%d %H:%M:%S") if val else "")