Files
xls_doc/scripts/make-manual-test-materials.py
2026-06-24 09:45:35 +08:00

474 lines
14 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
from __future__ import annotations
import json
import shutil
import sqlite3
from pathlib import Path
from docx import Document
from docx.enum.table import WD_TABLE_ALIGNMENT, WD_CELL_VERTICAL_ALIGNMENT
from docx.shared import Inches, Pt
from openpyxl import Workbook
from openpyxl.styles import Alignment, Font, PatternFill, Border, Side
from openpyxl.utils import get_column_letter
ROOT = Path(__file__).resolve().parents[1]
OUT = ROOT / "manual_tests"
def main() -> None:
if OUT.exists():
shutil.rmtree(OUT)
OUT.mkdir(parents=True)
build_excel_to_word(OUT / "01_excel_to_word")
build_sqlite_to_excel(OUT / "02_sqlite_to_excel")
build_excel_to_excel(OUT / "03_excel_to_excel")
build_filter_work_order_to_word(OUT / "04_filter_work_order_to_word")
write_readme()
print(OUT)
def build_excel_to_word(path: Path) -> None:
path.mkdir(parents=True)
write_daily_source_xlsx(path / "source_daily_data.xlsx")
write_daily_word_template(path / "daily_report_template.docx")
write_json(
path / "task.json",
{
"vars": {"date": "2026-06-18", "batch": "默认班次"},
"data": {
"type": "excel",
"path": "./source_daily_data.xlsx",
"sheet": "Daily",
"header_row": 1,
},
"template": {"path": "./daily_report_template.docx"},
"output": {
"path": "./out/daily_{{date}}_{{name}}_{{_row}}.docx",
"overwrite": True,
},
},
)
def build_sqlite_to_excel(path: Path) -> None:
path.mkdir(parents=True)
write_summary_sqlite(path / "source_summary.db")
write_summary_excel_template(path / "department_summary_template.xlsx")
write_json(
path / "task.json",
{
"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 where report_date = ? order by department",
"params": ["{{date}}"],
},
"template": {"path": "./department_summary_template.xlsx"},
"output": {
"path": "./out/summary_{{department}}_{{_row}}.xlsx",
"overwrite": True,
},
},
)
def build_excel_to_excel(path: Path) -> None:
path.mkdir(parents=True)
write_audit_source_xlsx(path / "source_audit_data.xlsx")
write_audit_excel_template(path / "audit_template.xlsx")
write_json(
path / "task.json",
{
"vars": {"date": "2026-06-18"},
"data": {
"type": "excel",
"path": "./source_audit_data.xlsx",
"sheet": "Audit",
"header_row": 2,
},
"template": {"path": "./audit_template.xlsx"},
"output": {
"path": "./out/audit_{{date}}_{{employee}}_{{_row}}.xlsx",
"overwrite": True,
},
},
)
def build_filter_work_order_to_word(path: Path) -> None:
path.mkdir(parents=True)
write_work_order_source_xlsx(path / "source_work_orders.xlsx")
write_work_order_word_template(path / "work_order_template.docx")
write_json(
path / "task.json",
{
"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,
},
},
)
def write_daily_source_xlsx(path: Path) -> None:
rows = [
["name", "department", "done", "plan", "risk"],
["张三/测试", "营销部", "完成 A 系统订单核对 128 条;同步 B 系统回款 35 笔", "跟进 3 条异常订单并补充截图", ""],
["李四", "客服部", "整理投诉工单 21 条;完成日报提交", "复核高优先级工单并同步主管", "等待业务确认 1 条"],
]
write_table_workbook(path, "Daily", rows, title="日报源数据")
def write_daily_word_template(path: Path) -> None:
doc = Document()
section = doc.sections[0]
section.top_margin = Inches(0.8)
section.bottom_margin = Inches(0.8)
section.left_margin = Inches(0.85)
section.right_margin = Inches(0.85)
title = doc.add_paragraph()
title_run = title.add_run("员工日报(测试模板)")
title_run.bold = True
title_run.font.size = Pt(18)
meta = doc.add_table(rows=4, cols=2)
meta.alignment = WD_TABLE_ALIGNMENT.LEFT
set_table_style(meta)
labels = ["日期", "员工", "部门", "班次"]
values = ["{{date}}", "{{na", "{{department}}", "{{batch}}"]
for i, label in enumerate(labels):
meta.cell(i, 0).text = label
if label == "员工":
p = meta.cell(i, 1).paragraphs[0]
p.add_run(values[i])
p.add_run("me}}")
else:
meta.cell(i, 1).text = values[i]
for heading, placeholder in [
("今日完成", "{{done}}"),
("明日计划", "{{plan}}"),
("风险备注", "{{risk}}"),
]:
doc.add_paragraph()
h = doc.add_paragraph()
r = h.add_run(heading)
r.bold = True
r.font.size = Pt(12)
p = doc.add_paragraph()
p.add_run(placeholder)
doc.save(path)
def write_summary_sqlite(path: Path) -> None:
conn = sqlite3.connect(path)
try:
conn.executescript(
"""
create table department_summary (
department text,
report_date text,
total_count integer,
abnormal_count integer,
owner text
);
insert into department_summary values
('客服部', '2026-06-18', 76, 0, '李四'),
('营销部', '2026-06-18', 128, 3, '张三'),
('营销部', '2026-06-17', 115, 2, '张三');
"""
)
conn.commit()
finally:
conn.close()
def write_summary_excel_template(path: Path) -> None:
wb = Workbook()
ws = wb.active
ws.title = "Summary"
ws.append(["部门日报汇总(测试模板)", ""])
ws.append(["部门", "{{department}}"])
ws.append(["日期", "{{report_date}}"])
ws.append(["负责人", "{{owner}}"])
ws.append(["处理总数", "{{total_count}}"])
ws.append(["异常数", "{{abnormal_count}}"])
style_sheet(ws, title_rows={1})
ws.column_dimensions["A"].width = 18
ws.column_dimensions["B"].width = 32
wb.save(path)
def write_audit_source_xlsx(path: Path) -> None:
rows = [
["日报质检导出"],
["employee", "date", "item", "score", "comment"],
["王五", "2026-06-18", "日报完整性", "92", "字段齐全,说明清楚"],
["赵六", "2026-06-18", "系统截图一致性", "87", "缺少 1 张截图,需要补充"],
]
write_table_workbook(path, "Audit", rows, title=None)
def write_audit_excel_template(path: Path) -> None:
wb = Workbook()
ws = wb.active
ws.title = "AuditReport"
ws.append(["日报质检结果(测试模板)", ""])
ws.append(["日期", "{{date}}"])
ws.append(["员工", "{{employee}}"])
ws.append(["检查项", "{{item}}"])
ws.append(["得分", "{{score}}"])
ws.append(["评语", "{{comment}}"])
style_sheet(ws, title_rows={1})
ws.column_dimensions["A"].width = 16
ws.column_dimensions["B"].width = 42
wb.save(path)
def write_work_order_source_xlsx(path: Path) -> None:
rows = [
["日期", "工单编号", "客户名称", "系统来源", "处理结果", "下一步"],
["2026-06-18", "GD-001", "A 公司", "PMS3.0", "已派单", "等待现场反馈"],
["2026-06-18", "GD-002", "B 公司", "D5000", "已完成", "归档并同步日报"],
["2026-06-19", "GD-001", "C 公司", "风控平台", "待复核", "补充截图"],
]
write_table_workbook(path, "工单", rows, title="工单源数据")
def write_work_order_word_template(path: Path) -> None:
doc = Document()
section = doc.sections[0]
section.top_margin = Inches(0.8)
section.bottom_margin = Inches(0.8)
section.left_margin = Inches(0.85)
section.right_margin = Inches(0.85)
title = doc.add_paragraph()
title_run = title.add_run("工单处理记录(筛选测试模板)")
title_run.bold = True
title_run.font.size = Pt(18)
table = doc.add_table(rows=6, cols=2)
table.alignment = WD_TABLE_ALIGNMENT.LEFT
set_table_style(table)
rows = [
("日期", "{{日期}}"),
("工单编号", "{{工单编号}}"),
("客户名称", "{{客户名称}}"),
("系统来源", "{{系统来源}}"),
("处理结果", "{{处理结果}}"),
("下一步", "{{下一步}}"),
]
for idx, (label, value) in enumerate(rows):
table.cell(idx, 0).text = label
table.cell(idx, 1).text = value
doc.save(path)
def write_table_workbook(path: Path, sheet: str, rows: list[list[str]], title: str | None) -> None:
wb = Workbook()
ws = wb.active
ws.title = sheet
for row in rows:
ws.append(row)
title_rows = {1} if title else set()
style_sheet(ws, title_rows=title_rows)
for idx, width in enumerate([18, 16, 44, 36, 28], start=1):
ws.column_dimensions[get_column_letter(idx)].width = width
wb.save(path)
def style_sheet(ws, title_rows: set[int]) -> None:
header_fill = PatternFill("solid", fgColor="D9EAF7")
title_fill = PatternFill("solid", fgColor="1F4E79")
thin = Side(style="thin", color="D9E2F3")
border = Border(top=thin, left=thin, right=thin, bottom=thin)
for row in ws.iter_rows():
for cell in row:
cell.alignment = Alignment(vertical="center", wrap_text=True)
cell.border = border
if cell.row in title_rows:
cell.font = Font(bold=True, color="FFFFFF", size=13)
cell.fill = title_fill
elif cell.row == min(title_rows or {1}) + 1 or (not title_rows and cell.row == 1):
cell.font = Font(bold=True)
cell.fill = header_fill
ws.freeze_panes = "A2"
def set_table_style(table) -> None:
for row in table.rows:
for cell in row.cells:
cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER
for paragraph in cell.paragraphs:
for run in paragraph.runs:
run.font.size = Pt(10.5)
def write_json(path: Path, data: dict) -> None:
path.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")
def write_readme() -> None:
text = """# docfill 手工测试素材
本目录提供四组可直接运行的本地测试素材,用于验证 `docfill` 对筛选、Word、Excel、Excel 数据源和 SQLite 数据源的支持情况。
运行前进入项目根目录:
```bash
cd /Users/zhaoyilun/Documents/xls_doc
```
构建工具:
```bash
bash scripts/build.sh
```
## 案例 1Excel 数据生成 Word 日报
目录:
```text
manual_tests/01_excel_to_word
```
运行命令:
```bash
dist/docfill-darwin-arm64 run -c manual_tests/01_excel_to_word/task.json --var batch=早班 --verbose
```
输出示例:
```text
generated 2 file(s)
- /Users/zhaoyilun/Documents/xls_doc/manual_tests/01_excel_to_word/out/daily_2026-06-18_张三_测试_1.docx
- /Users/zhaoyilun/Documents/xls_doc/manual_tests/01_excel_to_word/out/daily_2026-06-18_李四_2.docx
```
## 案例 2SQLite 数据生成 Excel 汇总表
目录:
```text
manual_tests/02_sqlite_to_excel
```
运行命令:
```bash
dist/docfill-darwin-arm64 run -c manual_tests/02_sqlite_to_excel/task.json --var date=2026-06-18 --verbose
```
输出示例:
```text
generated 2 file(s)
- /Users/zhaoyilun/Documents/xls_doc/manual_tests/02_sqlite_to_excel/out/summary_客服部_1.xlsx
- /Users/zhaoyilun/Documents/xls_doc/manual_tests/02_sqlite_to_excel/out/summary_营销部_2.xlsx
```
## 案例 3Excel 数据生成 Excel 质检表
目录:
```text
manual_tests/03_excel_to_excel
```
运行命令:
```bash
dist/docfill-darwin-arm64 run -c manual_tests/03_excel_to_excel/task.json --var date=2026-06-18 --verbose
```
输出示例:
```text
generated 2 file(s)
- /Users/zhaoyilun/Documents/xls_doc/manual_tests/03_excel_to_excel/out/audit_2026-06-18_王五_1.xlsx
- /Users/zhaoyilun/Documents/xls_doc/manual_tests/03_excel_to_excel/out/audit_2026-06-18_赵六_2.xlsx
```
## 案例 4按日期和工单编号筛选一条工单并生成 Word
目录:
```text
manual_tests/04_filter_work_order_to_word
```
输入数据内容:
```text
日期 工单编号 客户名称 系统来源 处理结果 下一步
2026-06-18 GD-001 A 公司 PMS3.0 已派单 等待现场反馈
2026-06-18 GD-002 B 公司 D5000 已完成 归档并同步日报
2026-06-19 GD-001 C 公司 风控平台 待复核 补充截图
```
运行命令:
```bash
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
```
输出示例:
```text
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
```
查看结果:
```bash
open manual_tests/04_filter_work_order_to_word/out
```
## 重新生成素材
如需重新生成全部手工测试文件,执行:
```bash
/Users/zhaoyilun/.cache/codex-runtimes/codex-primary-runtime/dependencies/python/bin/python3 scripts/make-manual-test-materials.py
```
输出示例:
```text
/Users/zhaoyilun/Documents/xls_doc/manual_tests
```
"""
(OUT / "README.md").write_text(text, encoding="utf-8")
if __name__ == "__main__":
main()