样例现运行于 .NET 10,构建 SDK 由根目录 global.json 固定;直接使用系统级 dotnet run ...。
仓库提供 8 个控制台 Demo,分三组:
- 手动映射(Word / Excel 各 1):完整送货单版式(A5 横版双层页眉 / 3×9 网格版头 + LOGO 二维码),展示框架能做到的效果;
- 自动映射(Word / Excel / Excel.Simple 各 1):Word / Excel 版式与手动映射版完全一致,仅映射方式不同;Excel.Simple 为物料基础数据(维持现状);
- i18n(Word / Excel / Excel.Simple 各 1):每插件一个整体 i18n 演示——消息层(Validate/Fill 消息中英切换)+ 文档内容(中英模板 / 表头按语言 + 回读,未填充占位符 → null)。
每个 Demo 运行后都留下「模板文件 + 填充后文件」,命令行打印回读值(Parse 强类型结果)——直观看到模板长什么样、填充后长什么样、读回的值是什么。
| Demo 项目 | 插件 | 映射方式 | 内容 | 运行命令 |
|---|---|---|---|---|
samples/TemplateFrame.Demo.Word |
Word | 手写映射(MapToData / MapFromData) |
送货单:A5 横版 / 双层页眉 / 9 列明细 / 两行页脚 / 收货前后两次填充 | dotnet run --project samples/TemplateFrame.Demo.Word |
samples/TemplateFrame.Demo.Excel |
Excel(灵活版式) | 手写映射 | 送货单:3×9 网格版头 / 9 列明细 / LOGO+二维码锚定 | dotnet run --project samples/TemplateFrame.Demo.Excel |
samples/TemplateFrame.Demo.Word.AutoMapping |
Word | 自动映射(契约声明 DataPath,无手写映射) |
送货单:内容与手写映射版完全一致,仅映射方式不同 | dotnet run --project samples/TemplateFrame.Demo.Word.AutoMapping |
samples/TemplateFrame.Demo.Excel.AutoMapping |
Excel(灵活版式) | 自动映射 | 送货单:内容与手写映射版完全一致,仅映射方式不同 | dotnet run --project samples/TemplateFrame.Demo.Excel.AutoMapping |
samples/TemplateFrame.Demo.Excel.Simple |
Excel.Simple(简单表格) | 自动映射(Simple 无手写版) | 物料基础数据:模板(仅表头)→ 填充 → 回读 | dotnet run --project samples/TemplateFrame.Demo.Excel.Simple |
samples/TemplateFrame.Demo.Word.I18n |
Word | 自动映射 | i18n:消息层(Validate/Fill 中英切换)+ 文档内容(zh/en 模板 + 填充 + 回读,未填充→null) | dotnet run --project samples/TemplateFrame.Demo.Word.I18n |
samples/TemplateFrame.Demo.Excel.I18n |
Excel(灵活版式) | 自动映射 | i18n:消息层 + 文档内容(AddTextKey / AddTableKeys 中英模板 + 回读) |
dotnet run --project samples/TemplateFrame.Demo.Excel.I18n |
samples/TemplateFrame.Demo.Excel.Simple.I18n |
Excel.Simple(简单表格) | 自动映射 | i18n:消息层(缺列 Validate 中英)+ 文档内容(中英表头 + 定义名回读,语言无关)+ 根集合 List<T> 直接填充/解析 |
dotnet run --project samples/TemplateFrame.Demo.Excel.Simple.I18n |
所有 Demo 默认输出到系统临时目录(Windows
%TEMP%/ Linux·macOS/tmp)下的<Demo 项目名>子目录,也可用第一个参数指定输出目录,例如:dotnet run --project samples/TemplateFrame.Demo.Word.AutoMapping -- "D:\out"。
同一个契约(送货单)有两种服务写法,内容与输出完全一致,区别只在映射:
// ① 手写映射(samples/TemplateFrame.Demo.Word)
protected override FillData MapToData(DeliveryOrderData data) => /* 手工铺 Values + Tables */;
protected override DeliveryOrderData MapFromData(FillData data) => /* 手工取 + Get* 辅助 */;
// ② 自动映射(samples/TemplateFrame.Demo.Word.AutoMapping)
// 契约元素声明 DataPath 后,无需写任何映射方法:
new TextElement { Key = "供应商", DisplayName = "供应商", DataPath = "Supplier" }
new TableElement { Key = "Lines", DisplayName = "明细行", DataPath = "Lines", Columns = [ … 列声明 DataPath … ] }
new ImageElement { Key = "QRCode", DisplayName = "二维码", DataPath = "QrBytes" }选择建议:
- 新场景 / 字段多:用自动映射——契约元素声明
DataPath即可,Fill/Parse/Validate全部自动完成,代码量最少; - 字段需要加工(如拼接、查表、空值策略特殊):用手写映射——
MapToData/MapFromData仍是虚方法,可随时覆盖; - 自动映射的代价:图片等二进制字段需要数据直接携带字节(
byte[]属性),不能在映射方法里"顺便"读文件 / 生成二维码——这类准备工作移到数据构造处(Demo 里在Program中生成)。
- 生成含 SDT 内容控件的
.docx(19 个 SDT:正文 9 列表格 + 页眉 5 + 页脚 3 + 图片 2); Validate打印 SDT 清单(tag / id / kind / location);- 收货前 → 收货后两次填充:收货前 实收数量/批次号/仓库为空,收货后补齐;
- 回读:
service.Parse→ 强类型DeliveryOrderData(9 列明细多行 + 空字段展示)。
- 生成含 命名区域(
TF_前缀) 的.xlsx:3×9 网格版头(LOGO / 标题 / 二维码)+ 单据头 3 行 + 9 列明细; - 无页面设置(Excel 是"网格规整"型版式);
Validate/Fill/Parse闭环。
- 内容与 Word 手写映射版一致;控制台打印每个元素的
DataPath; - 没有
MapToData/MapFromData——契约声明 DataPath 即自动映射; - 数据构造处准备好
LogoBytes/QrBytes(读资产文件 + QRCoder 生成二维码)。
- 内容与 Excel 手写映射版一致;控制台打印每个元素的
DataPath;无手写映射方法。
- 唯一(且已是自动映射)的 Simple Demo:契约 = 单个
TableElement,列声明 DataPath; BuildTemplate(仅表头)→Fill(强类型数据 → xlsx)→Parse(xlsx → 强类型MaterialsData);- 命名区域默认
TF_Table标记表格位置;Read优先按命名区域定位表头; - i18n(中英表头 + 定义名回读)见独立 Demo
TemplateFrame.Demo.Excel.Simple.I18n。
- 消息层:生成模板故意只放「单据编号」内容控件,让 供应商 / 制单日期 缺失;同一份模板在
zh-CN(中文中性默认)与en(英文卫星)两种文化下分别执行Validate与Fill——校验消息、缺必填元素异常消息随CurrentUICulture自动中英切换;每条校验问题打印MessageKey/MessageArgs(稳定结构,不随语言变)。 - 文档内容:业务注入本地化器(文化限定键
"zh-CN:Doc.Title"/"en:Doc.Title"+ 文化中立兜底),同一版式代码(AddParagraphKey/AddTextKey/AddTableKeys+ 本地化占位符 / 页码)输出中英两份模板(语言由文件名承载,如Word-I18n-DeliveryOrder-en-template.docx);填充后再回读——未填充模板的占位符规范化为 null(null=未填充、""=有意留空),已填充模板数据值原样(不翻译、InvariantCulture)。
- 消息层:与 Word 同模式——缺必填元素模板在
zh-CN/en下Validate与Fill,消息中英切换(MessageKey / MessageArgs)。 - 文档内容:简单版送货单版式(标题 / 单据头 / 明细表),同一版式代码用
AddTextKey/AddTableKeys+ 本地化占位符输出 zh/en 两份模板(如Excel-I18n-DeliveryOrder-en-template.xlsx);填充 → 回读——未填充 → null、已填充数据值原样(不翻译、InvariantCulture)。
- 消息层:用缺「型号」列的模板对完整契约
Validate,Missing 消息随文化中英切换(MessageKey / MessageArgs)。 - 文档内容:中英表头模板 + 填充(en 表头经本地化器,每列定义名
TF_Table_<列Key>→ 表头单元格),无语言回读(service.Parse走定义名定位,不依赖表头文本匹配)——回读与表头语言解耦;zh 文件走表头文本匹配回退。 - 根集合:追加
MaterialListTemplateService : SimpleExcelTemplateService<List<MaterialLine>>——表格 DataPath 留空,TData直接是List<MaterialLine>;同一份列表中英填充 +Parse直接回读List<MaterialLine>(表头按语言、定义名回读语言无关,与容器对象版能力一致)。
- 设计:
docs/DESIGN.md(三层架构 / 契约 = 元素清单 / 数据形状FillData/ 自动映射DataPathMapper) - 路线图:
docs/ROADMAP.md(已归档 + 规划) - 插件 README:
src/TemplateFrame.Word/README.md、src/TemplateFrame.Excel/README.md、src/TemplateFrame.Excel.Simple/README.md