"""生成网银流水标准导入模板 xlsx — 列: 凭证日期/凭证号/科目编码/科目名称/借方金额/贷方金额/摘要 用法: python scripts/gen_voucher_import_template.py 输出: backend/scripts/templates/网银流水导入模板.xlsx(表头 + 1行示例) """ import os import sys from openpyxl import Workbook from openpyxl.styles import Font, PatternFill, Alignment from openpyxl.utils import get_column_letter OUT_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "templates", "网银流水导入模板.xlsx") HEADERS = ["凭证日期", "凭证号", "科目编码", "科目名称", "借方金额", "贷方金额", "摘要"] # 1行示例(借贷平衡) EXAMPLE = ["2026-08-01", "记-001", "1002", "银行存款-工行", 50000, 0, "收到客户回款"] # 附赠一行结转示例行(注释说明用,不写入数据行) def main(): os.makedirs(os.path.dirname(OUT_PATH), exist_ok=True) wb = Workbook() ws = wb.active ws.title = "网银流水" # 表头样式 header_font = Font(bold=True, color="FFFFFF") header_fill = PatternFill("solid", fgColor="409EFF") for col, h in enumerate(HEADERS, start=1): cell = ws.cell(row=1, column=col, value=h) cell.font = header_font cell.fill = header_fill cell.alignment = Alignment(horizontal="center", vertical="center") for col, val in enumerate(EXAMPLE, start=1): cell = ws.cell(row=2, column=col, value=val) cell.alignment = Alignment(horizontal="center" if col in (1, 3, 5, 6) else "left") # 列宽 widths = [14, 12, 12, 22, 12, 12, 30] for i, w in enumerate(widths, start=1): ws.column_dimensions[get_column_letter(i)].width = w # 说明sheet note = wb.create_sheet("填写说明") notes = [ ["网银流水标准导入模板 — 填写说明"], [""], ["1. 列说明(与凭证明细表 voucher_details 对齐):"], [" 凭证日期: YYYY-MM-DD(必填,用于提取期间period)"], [" 凭证号: 字符串(必填,如 记-001 / 银收-20260801-001)"], [" 科目编码: 必填,如 1001库存现金 / 1002银行存款"], [" 科目名称: 必填,如 银行存款-工行 / 库存现金"], [" 借方金额: 数字,无则留空或0(与贷方二选一)"], [" 贷方金额: 数字,无则留空或0(与借方二选一)"], [" 摘要: 可选,含'结转'或科目名含'本年利润'的行将标记为结转行,不参与现金流计算"], [""], ["2. 三校验规则(导入时自动执行):"], [" ① 借贷平衡: 全文件Σ借方 = Σ贷方(容差0.01),不平衡将提示差额"], [" ② 期间合计: 按期间(YYYY-MM)汇总借贷合计,供对账"], [" ③ 结转行识别: 摘要含'结转' 或 科目名含'本年利润'/'结转' → carry_forward标记"], [""], ["3. 现金流联动:货币资金科目(1001/1002开头)期末余额自动更新现金余额与EXT_现金类KPI、F_CASH_SAFETY现金安全垫"], ["4. 示例行(第2行)请删除后填入真实流水;不要修改表头列名"], ] for row in notes: note.append(row) note.column_dimensions["A"].width = 90 wb.save(OUT_PATH) print(f"模板已生成: {OUT_PATH}") if __name__ == "__main__": sys.exit(main())