Files
xls_doc/HOWTO.md
2026-06-24 09:45:35 +08:00

20 KiB
Raw Blame History

docfill HOWTO

本文档说明如何使用 docfill 完成本地文档自动填充。文档分为两部分:

  • “最小实践”用于快速完成一次可验证运行。
  • “详细说明”用于理解任务配置、运行变量、筛选、模板、输出、错误和日志。

一、最小实践

1. 进入项目目录

cd /Users/zhaoyilun/Documents/xls_doc

2. 构建命令行工具

bash scripts/build.sh

输出示例:

/Users/zhaoyilun/Documents/xls_doc/dist/docfill-darwin-arm64

构建后的可执行文件是:

dist/docfill-darwin-arm64

3. 准备测试素材

仓库中已经包含 manual_tests/ 测试素材。如果需要重新生成,可执行:

/Users/zhaoyilun/.cache/codex-runtimes/codex-primary-runtime/dependencies/python/bin/python3 scripts/make-manual-test-materials.py

输出示例:

/Users/zhaoyilun/Documents/xls_doc/manual_tests

测试素材包含四类任务:

  • manual_tests/01_excel_to_word: Excel 源数据生成 Word 日报。
  • manual_tests/02_sqlite_to_excel: SQLite 源数据生成 Excel 汇总表。
  • manual_tests/03_excel_to_excel: Excel 源数据生成 Excel 质检表。
  • manual_tests/04_filter_work_order_to_word: 按日期和工单编号筛选一条工单,再生成 Word。

4. 运行筛选工单案例

命令:

dist/docfill-darwin-arm64 run -c manual_tests/04_filter_work_order_to_word/task.json --var date=2026-06-18 --var ticket_no=GD-002 --verbose

输出示例:

log: load config path=manual_tests/04_filter_work_order_to_word/task.json
log: read data type=excel path=/Users/zhaoyilun/Documents/xls_doc/manual_tests/04_filter_work_order_to_word/source_work_orders.xlsx
log: read data type=excel path=/Users/zhaoyilun/Documents/xls_doc/manual_tests/04_filter_work_order_to_word/source_work_orders.xlsx rows=3
log: filter rows=3 matched=1 expect=one
log: render row=1 output=/Users/zhaoyilun/Documents/xls_doc/manual_tests/04_filter_work_order_to_word/out/work_order_2026-06-18_GD-002.docx
generated 1 file(s)
- /Users/zhaoyilun/Documents/xls_doc/manual_tests/04_filter_work_order_to_word/out/work_order_2026-06-18_GD-002.docx

查看输出目录:

open manual_tests/04_filter_work_order_to_word/out

输入 Excel 内容示例:

日期          工单编号   客户名称  系统来源   处理结果  下一步
2026-06-18   GD-001    A 公司   PMS3.0   已派单   等待现场反馈
2026-06-18   GD-002    B 公司   D5000    已完成   归档并同步日报
2026-06-19   GD-001    C 公司   风控平台  待复核   补充截图

本次命令传入:

date = 2026-06-18
ticket_no = GD-002

所以工具会筛选:

日期 = 2026-06-18并且 工单编号 = GD-002

最终只生成 GD-002 对应的 Word 文件。

二、详细说明

1. task.json 与 --var 的关系

task.json 是某一种业务报表的固定任务说明书。它通常由开发人员或维护人员准备好,普通运行时不需要频繁修改。

命令行 --var 是本次运行传入的具体条件,例如日期、工单编号、人员、批次。

可以这样理解:

不同业务 = 不同 task.json
本次运行的具体条件 = --var
真实业务数据 = Excel 或 SQLite
输出模板 = Word 或 Excel

例如不同业务可以分别维护:

工单日报.json
部门汇总.json
质检报告.json

运行时只传本次变化的信息:

dist/docfill-darwin-arm64 run -c 工单日报.json --var date=2026-06-18 --var ticket_no=GD-002

变量优先级:

数据表里的字段 > 命令行 --var > task.json 里的 vars

示例:

"vars": {
  "date": "2026-06-18"
}

如果运行时执行:

dist/docfill-darwin-arm64 run -c task.json --var date=2026-06-19

实际使用的是:

date = 2026-06-19

也就是命令行 --var 会覆盖 task.json 中的同名默认变量。

2. 命令格式

docfill 当前只提供一个核心命令:

dist/docfill-darwin-arm64 run -c <task.json> [--var key=value] [--verbose]

参数说明:

参数 作用 示例
run 执行一次填充任务 dist/docfill-darwin-arm64 run -c task.json
-c 指定任务配置文件 -c manual_tests/04_filter_work_order_to_word/task.json
--config -c 的完整写法 --config task.json
--var 传入运行时变量,可以重复使用 --var date=2026-06-18 --var ticket_no=GD-002
--verbose 输出诊断日志到 stderr --verbose

命令行参数错误示例:

dist/docfill-darwin-arm64 run --var date

输出示例:

docfill: [CLI_USAGE] invalid value "date" for flag -var: invalid --var "date", want key=value
hint: Check command flags and use key=value for --var.

3. 任务配置结构

典型的筛选任务配置如下:

{
  "vars": {
    "date": "2026-06-18"
  },
  "data": {
    "type": "excel",
    "path": "./source_work_orders.xlsx",
    "sheet": "工单",
    "header_row": 1
  },
  "filter": {
    "equals": {
      "日期": "{{date}}",
      "工单编号": "{{ticket_no}}"
    },
    "expect": "one"
  },
  "template": {
    "path": "./work_order_template.docx"
  },
  "output": {
    "path": "./out/work_order_{{日期}}_{{工单编号}}.docx",
    "overwrite": true
  }
}

配置字段说明:

字段 必填 说明
vars 默认变量。适合放日期、批次、班次等默认值。
data.type 数据源类型。支持 excelxlsxsqlite
data.path 数据源路径。支持 .xlsx 或 SQLite .db
data.sheet Excel 可选 Excel 工作表名称。未填写时读取第一个工作表。
data.header_row Excel 可选 Excel 表头行号,从 1 开始。未填写时默认为 1
data.query SQLite 必填 SQLite 查询语句。查询结果列名作为字段名。
data.params SQLite 可选 SQL ? 参数列表,支持 {{变量名}}
filter.equals 等值筛选条件。左侧是数据字段,右侧是匹配值。
filter.expect 筛选结果数量要求。支持 onemany,默认 one
template.path Word 或 Excel 模板路径。支持 .docx.xlsx
output.path 输出文件路径模板。可以使用 {{字段名}}
output.overwrite 是否覆盖已存在文件。默认是 false

相对路径规则:

task.json 所在目录就是相对路径的基准目录。

4. 业务筛选 filter

filter 的作用是从数据表中筛选出本次要使用的数据行。它的目标不是提供数据库查询能力,而是提供符合表格使用习惯的简单筛选。

配置示例:

"filter": {
  "equals": {
    "日期": "{{date}}",
    "工单编号": "{{ticket_no}}"
  },
  "expect": "one"
}

含义:

找到 日期 等于 date并且 工单编号 等于 ticket_no 的数据行。

命令:

dist/docfill-darwin-arm64 run -c task.json --var date=2026-06-18 --var ticket_no=GD-002

实际筛选:

日期 = 2026-06-18
工单编号 = GD-002

筛选规则:

  • filter.equals 左侧必须是 Excel 表头或 SQLite 查询结果列名。
  • filter.equals 右侧可以写固定值,也可以写 {{变量名}}
  • 多个条件之间是“全部满足”关系。
  • 比较前会去掉单元格值和筛选值两侧的空格。
  • 只支持等值匹配。
  • 不支持模糊匹配、范围查询、OR、排序表达式或复杂条件。

filter.expect 支持两个值:

含义 适用场景
one 必须只匹配一行 工单、单份日报、单个报表。
many 允许匹配多行 按日期批量生成多个人或多个部门的报表。

未填写 filter.expect 时,默认按 one 处理。

如果没有配置 filter,工具会沿用旧行为:读取到的每一行都会生成一个输出文件。

复杂情况的处理建议:

  • 如果多个字段才能确定一条数据,就在 filter.equals 中写多个条件。
  • 如果表格本身不容易筛选,建议在 Excel 中新增辅助列,例如 填报批次业务唯一标识筛选日期
  • 不建议把复杂业务规则写进 docfill,复杂规则应在数据准备阶段完成。

5. Excel 数据源

Excel 数据源配置示例:

{
  "data": {
    "type": "excel",
    "path": "./source_work_orders.xlsx",
    "sheet": "工单",
    "header_row": 1
  }
}

运行示例:

dist/docfill-darwin-arm64 run -c manual_tests/04_filter_work_order_to_word/task.json --var date=2026-06-18 --var ticket_no=GD-002

Excel 读取规则:

  • header_row 指定表头行,表头单元格内容就是字段名。
  • 表头下方的每一行是候选数据。
  • 配置了 filter 时,先筛选,再生成输出。
  • 未配置 filter 时,每一行都会生成一个输出文件。
  • 空行会被跳过。
  • 空表头列会被忽略。

表头在第 1 行的输入示例:

日期          工单编号   客户名称  系统来源   处理结果  下一步
2026-06-18   GD-001    A 公司   PMS3.0   已派单   等待现场反馈
2026-06-18   GD-002    B 公司   D5000    已完成   归档并同步日报
2026-06-19   GD-001    C 公司   风控平台  待复核   补充截图

表头在第 2 行的配置示例:

{
  "data": {
    "type": "excel",
    "path": "./source_audit_data.xlsx",
    "sheet": "Audit",
    "header_row": 2
  }
}

对应输入示例:

日报质检导出

employee  date        item        score  comment
王五       2026-06-18  日报完整性    92     字段齐全,说明清楚
赵六       2026-06-18  系统截图一致性  87     缺少 1 张截图,需要补充

6. SQLite 数据源

SQLite 数据源配置示例:

{
  "vars": {
    "date": "2026-06-18"
  },
  "data": {
    "type": "sqlite",
    "path": "./source_summary.db",
    "query": "select department, report_date, total_count, abnormal_count, owner from department_summary order by department",
    "params": []
  },
  "filter": {
    "equals": {
      "report_date": "{{date}}"
    },
    "expect": "many"
  }
}

运行示例:

dist/docfill-darwin-arm64 run -c manual_tests/02_sqlite_to_excel/task.json --var date=2026-06-18

SQLite 读取规则:

  • data.query 的查询结果列名就是模板字段名。
  • data.params 按顺序对应 SQL 中的 ?
  • data.params 可以引用 vars 或命令行 --var
  • 配置了 filterSQL 查询结果还会再经过业务筛选。
  • 查询结果的每一行或筛选后的每一行生成一个输出文件。

输入数据示例:

department  report_date  total_count  abnormal_count  owner
营销部        2026-06-17   115          2               张三
客服部        2026-06-18   76           0               李四
营销部        2026-06-18   128          3               张三

SQLite 可以继续使用 SQL 参数:

"data": {
  "type": "sqlite",
  "path": "./source_summary.db",
  "query": "select department, report_date, total_count, abnormal_count, owner from department_summary where report_date = ? order by department",
  "params": ["{{date}}"]
}

这适合由开发人员维护的 SQLite 数据源。面向表格使用习惯时,优先使用 filter.equals 表达业务筛选。

7. Word 模板

Word 模板使用 .docx 文件,模板中写入 {{字段名}}

日期:{{日期}}
工单编号:{{工单编号}}
客户名称:{{客户名称}}
系统来源:{{系统来源}}
处理结果:{{处理结果}}
下一步:{{下一步}}

运行示例:

dist/docfill-darwin-arm64 run -c manual_tests/04_filter_work_order_to_word/task.json --var date=2026-06-18 --var ticket_no=GD-002

生成结果示例:

日期2026-06-18
工单编号GD-002
客户名称B 公司
系统来源D5000
处理结果:已完成
下一步:归档并同步日报

Word 支持同一段落内被 Word 拆分的文本占位符。例如模板内部可能把 {{name}} 拆成相邻文本节点 {{name}},工具会按同一段落进行最小兼容处理。

这种兼容会把同一段落内的拆分文本合并后再写回,渲染结果会写入该段落第一个文本节点的位置,后续拆分节点的独立格式不再体现。建议模板中每个占位符使用同一种字体、颜色和加粗状态,不要在 {{、字段名、}} 之间混用格式。

当前不支持复杂模板语法,例如表格循环、条件判断、图片插入、跨段落拼接占位符。

8. Excel 模板

Excel 模板使用 .xlsx 文件,单元格中写入 {{字段名}}

B2: {{department}}
B3: {{report_date}}
B4: {{owner}}
B5: {{total_count}}
B6: {{abnormal_count}}

运行示例:

dist/docfill-darwin-arm64 run -c manual_tests/02_sqlite_to_excel/task.json --var date=2026-06-18

生成结果示例:

B2: 营销部
B3: 2026-06-18
B4: 张三
B5: 128
B6: 3

Excel 模板会遍历所有工作表,替换单元格文本中的占位符。当前不支持公式重算、透视表刷新、复杂样式模板语法。

9. 输出路径

输出路径可以使用字段占位符:

{
  "output": {
    "path": "./out/work_order_{{日期}}_{{工单编号}}.docx",
    "overwrite": true
  }
}

运行示例:

dist/docfill-darwin-arm64 run -c manual_tests/04_filter_work_order_to_word/task.json --var date=2026-06-18 --var ticket_no=GD-002

输出文件示例:

work_order_2026-06-18_GD-002.docx

文件名清理规则:

/ \ : * ? " < > |

以上字符会在输出路径字段值中替换为 _。例如:

张三/测试 -> 张三_测试

覆盖规则:

  • output.overwrite 未设置或为 false 时,输出文件已存在会失败。
  • output.overwritetrue 时,允许覆盖同名输出文件。

10. 日志、标准输出和退出码

成功时stdout 输出生成文件清单:

generated 1 file(s)
- /path/to/out/work_order_2026-06-18_GD-002.docx

启用 --verbosestderr 输出诊断日志:

log: load config path=task.json
log: read data type=excel path=/path/data.xlsx
log: read data type=excel path=/path/data.xlsx rows=3
log: filter rows=3 matched=1 expect=one
log: render row=1 output=/path/out/work_order_2026-06-18_GD-002.docx

退出码:

退出码 含义 适用场景
0 成功 可以读取 stdout 中的生成文件清单。
1 执行失败 配置、数据、模板、输出等处理失败。
2 命令行错误 参数缺失、命令错误、--var 格式错误。

数字员工或调度脚本建议:

  • 判断退出码确认任务是否成功。
  • 成功时读取 stdout 获取生成文件路径。
  • 失败时记录 stderr用于定位错误码、提示和上下文。
  • 仅在诊断或审计时启用 --verbose

11. 错误格式与错误码

错误输出格式:

docfill: [ERROR_CODE] message
hint: repair suggestion
context: key=value

配置文件不存在示例:

dist/docfill-darwin-arm64 run -c manual_tests/not-exist.json

输出示例:

docfill: [CONFIG_READ] read config: open manual_tests/not-exist.json: no such file or directory
hint: Check that the config file exists and is readable.
context: config=manual_tests/not-exist.json

筛选无匹配示例:

dist/docfill-darwin-arm64 run -c manual_tests/04_filter_work_order_to_word/task.json --var date=2026-06-18 --var ticket_no=GD-999 --verbose

输出示例:

log: load config path=manual_tests/04_filter_work_order_to_word/task.json
log: read data type=excel path=/Users/zhaoyilun/Documents/xls_doc/manual_tests/04_filter_work_order_to_word/source_work_orders.xlsx
log: read data type=excel path=/Users/zhaoyilun/Documents/xls_doc/manual_tests/04_filter_work_order_to_word/source_work_orders.xlsx rows=3
docfill: [DATA_FILTER_NO_MATCH] filter matched no rows
hint: Check filter.equals, --var values, or source table contents.
context: expect=one filter=工单编号=GD-999,日期=2026-06-18

错误码说明:

错误码 含义 常见处理方式
CLI_USAGE 命令行参数错误 检查命令、-c--var key=value
CONFIG_READ 配置文件读取失败 检查路径、文件是否存在、读权限。
CONFIG_PARSE 配置 JSON 解析失败 检查 JSON 语法。
CONFIG_VALIDATE 配置字段缺失或不支持 检查 data.typedata.pathtemplate.pathoutput.pathfilter.expect
DATA_EXCEL Excel 数据读取失败 检查 .xlsx 文件、工作表名、表头行。
DATA_SQLITE SQLite 数据读取或查询失败 检查 .db 文件、SQL、参数。
DATA_EMPTY 数据源没有返回可生成的数据行 检查源数据是否为空。
DATA_FILTER_FIELD 筛选字段不在数据中 检查 Excel 表头或 SQLite 查询列名。
DATA_FILTER_VALUE 筛选条件引用的变量没有提供 补充 --varvars
DATA_FILTER_NO_MATCH 筛选后没有符合条件的数据行 检查筛选条件,或整理源表。
DATA_FILTER_MULTI_MATCH 期望一行但匹配多行 增加筛选条件,或整理重复数据。
TEMPLATE_OPEN 模板读取失败 检查模板路径和文件格式。
TEMPLATE_FIELD_MISSING 模板字段缺失 在数据源、vars--var 中补充字段。
TEMPLATE_UNRESOLVED 渲染后仍残留占位符 检查模板占位符拼写和字段值。
OUTPUT_EXISTS 输出文件已存在 修改输出路径或设置 output.overwrite: true
OUTPUT_WRITE 输出写入失败 检查输出目录权限、文件占用状态。
INTERNAL 未分类内部错误 保留 stderr 和输入文件,开启 --verbose 复现。

12. 自动化调用示例

以下示例展示数字员工或调度脚本如何调用 docfill。该脚本只做最小封装,不承担模板解析或业务逻辑。

#!/usr/bin/env bash
set -euo pipefail

DOCFILL="/Users/zhaoyilun/Documents/xls_doc/dist/docfill-darwin-arm64"
CONFIG="/Users/zhaoyilun/Documents/xls_doc/manual_tests/04_filter_work_order_to_word/task.json"
DATE="${1:?date is required, example: 2026-06-18}"
TICKET_NO="${2:?ticket_no is required, example: GD-002}"

"$DOCFILL" run -c "$CONFIG" --var date="$DATE" --var ticket_no="$TICKET_NO" --verbose

执行:

bash run-docfill.sh 2026-06-18 GD-002

预期结果:

generated 1 file(s)
- /Users/zhaoyilun/Documents/xls_doc/manual_tests/04_filter_work_order_to_word/out/work_order_2026-06-18_GD-002.docx

集成建议:

  • 把业务系统接口采集结果先落成 Excel 或 SQLite。
  • 为每类报表维护一个 task.json
  • 数字员工只负责准备运行变量并执行命令。
  • 复杂筛选优先通过整理 Excel 表解决,例如新增辅助列。
  • 不要把账号密码、审批状态、业务系统访问逻辑写入 docfill 配置。

13. 开发与验证

运行全部 Go 测试:

go test -count=1 ./...

运行冒烟测试:

bash scripts/smoke.sh

构建发布用本机二进制:

bash scripts/build.sh

重新生成手工测试素材:

/Users/zhaoyilun/.cache/codex-runtimes/codex-primary-runtime/dependencies/python/bin/python3 scripts/make-manual-test-materials.py

冒烟测试覆盖内容:

  • Go 单元测试。
  • 临时构建 docfill
  • 生成临时 Excel、Word、SQLite 示例数据。
  • 执行无筛选 Excel 到 Word 示例。
  • 执行筛选 Excel 到 Word 示例。
  • 执行 SQLite 到 Excel 示例。
  • 检查输出文件是否生成。

14. 当前边界

为了保持工具小型、稳定、便于自动化调用,当前明确不包含以下能力:

  • 不提供 Web 界面。
  • 不提供模板设计器。
  • 不直接登录业务系统。
  • 不管理账号、密码或权限。
  • 不实现审批流。
  • 不实现 Word 表格循环或条件语法。
  • 不实现 Excel 公式重算和透视表刷新。
  • 不实现复杂筛选语法。
  • 不实现复杂任务编排。

如需扩展,应优先通过外部脚本准备数据,再交给 docfill 执行单次文档填充。