TemplateFrame.Word 2.3.1

dotnet add package TemplateFrame.Word --version 2.3.1
                    
NuGet\Install-Package TemplateFrame.Word -Version 2.3.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="TemplateFrame.Word" Version="2.3.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="TemplateFrame.Word" Version="2.3.1" />
                    
Directory.Packages.props
<PackageReference Include="TemplateFrame.Word" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add TemplateFrame.Word --version 2.3.1
                    
#r "nuget: TemplateFrame.Word, 2.3.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package TemplateFrame.Word@2.3.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=TemplateFrame.Word&version=2.3.1
                    
Install as a Cake Addin
#tool nuget:?package=TemplateFrame.Word&version=2.3.1
                    
Install as a Cake Tool

TemplateFrame.Word

NuGet NuGet Downloads

中文 · English

TemplateFrame 的 MS Word 插件:把基础包的"契约 + 数据形状"翻译成 .docx。 基于内容控件(SDT / Structured Document Tag)实现生成 → 定位 → 填充 → 回读 → 校验全链路, 只支持 Microsoft Office 的 .docx(WPS 兼容性见设计文档 §1.4)。

核心能力

组件 职责
WordTemplateBuilder 组装带 SDT 的 .docx:页面设置、页眉/页脚、布局表格、明细表、文本/图片元素、页码域
SdtLocator 按 tag 定位内容控件(正文/页眉/页脚,tag 全局唯一)
WordTemplateFiller 填充:文本(保留 run 格式)、图片(换包内 part + 关系)、表格行克隆(重发唯一 w:id);填充前软校验
WordTemplateParser 回读:按契约把已填充模板读回 FillData(文本按 ValueType 转换、表格多行、图片字节)
WordTemplateValidator 校验:Missing / WrongType / Ambiguous / Extra(可选字段缺失只告警)

快速开始

业务服务声明所用插件构建器类型,BuildInitialTemplate() 无参数、直接用 Builder 实例组装:

public sealed class DeliveryOrderTemplateService : TemplateService<DeliveryOrderData, WordTemplateBuilder>
{
    public DeliveryOrderTemplateService() : base(new WordTemplateEngine()) { }

    protected override TemplateContract DefineContract() => /* 元素清单 */;

    protected override void BuildInitialTemplate()
    {
        Builder.SetPageSetup(new PageSetup { Size = PageSize.A5, Orientation = PageOrientation.Landscape });
        Builder.AddHeader(BuildHeader);   // 页眉(可加 LOGO/标题/二维码+页码)
        Builder.AddFooter(BuildFooter);   // 页脚(可加日期/收货人/页码)
        Builder.AddTable("Lines", ["序号", "物料名称", "数量", "单位"],
            new TableFormat
            {
                HeaderFormat = new TextFormat { FontName = "宋体", SizePt = 12, Bold = true, Alignment = TextAlignment.Center },
                CellFormat = new TextFormat { FontName = "宋体", SizePt = 12, Alignment = TextAlignment.Center },
                Alignment = TextAlignment.Center,
                ColumnWidthsCm = [1.2, 6.0, 2.5, 2.0],
            });
    }

    protected override FillData MapToData(DeliveryOrderData data) => /* 手写映射 */;
    protected override DeliveryOrderData MapFromData(FillData data) => /* 手写反向映射 */;
}

WordTemplateBuilder 能力(即类型方法)

  • 页面SetPageSetup(PageSetup) — A4/A5、横/纵、毫米边距
  • 页眉/页脚AddHeader(Action<WordTemplateBuilder>) / AddFooter(...) — 内容与正文同一套能力
  • 布局表AddLayoutTable(rows, cols, TableFormat?) + AddCell(compose, columnSpan) — 页眉"左中右/平分/四份"(gridSpan 跨列)
  • 文本AddParagraph(text[, style|TextFormat]) / AddText / AddElement(key[, TextFormat])(元素=内容控件,占位文本按语言:默认 zh "待填充" / en "To be filled",经 ITemplateLocalizer 解析,业务可覆盖)
  • 表格AddTable(key, columns, TableFormat?, headerStyle?) — 表头 + 示例行(每格一个 SDT);TableFormat 支持表头/单元格字体、有无边框、表格对齐、列宽(cm)、垂直对齐
  • 图片AddImage(key, placeholder?, widthIn?, heightIn?) — 占位图外包 SDT,填充时换 byte[]
  • 页码AddPageNumber(pattern? = null, TextFormat?) — PAGE/NUMPAGES 域;pattern 为 null 时按语言取默认(zh "第{page}页,总{total}页" / en "Page {page} of {total}")
  • TextFormatFontName(黑体/宋体)/ SizePt / Bold / Alignment / Underline

填充行为要点

  • 文本:改 sdtContent 内第一个 w:r/w:t(保留 run 格式),首尾空格补 xml:space="preserve"
  • 图片:往包内加图片 part + 关系拿新 rId,替换 SDT 内 <a:blip r:embed>;尺寸/位置/环绕继承占位图;页眉/页脚里的图片 part 归属对应 Header/Footer rels
  • 表格行:deepcopy 示例行 N 次,逐行按 tag 填值;克隆后每个 SDT 重发唯一 w:id
  • 软校验(填充前跑 Validate):Drifted/Extra 只记告警继续;Missing 必填按策略(默认抛错,可配 MissingElementPolicy.SkipAndWarn);WrongType/Ambiguous/Invalid 视为硬错误。
  • 告警出口WordTemplateFiller.Fill 返回 TemplateFillResult(输出流 + Warnings);引擎/服务层可用 FillDetailedITemplateEngine.FillDetailed / TemplateService<TData, TBuilder>.FillDetailed)拿到同样的软校验告警,Fill 保持只返回输出流。
  • ParseDetailed(2.3.0):导入方向对称出口——值转换失败的字段保留原始文本,并以 ConversionFailed(Warning,表格列带数据行号)随 TemplateParseResult 返回;null 仍专指未填充,Parse 行为不变。
  • 收货前/收货后:同一模板两次填充——收货前空字段传 null(显示为空),收货后补齐。
  • 0 行数据:示例行占位符被清空(保留表头 + 空白行结构),导出单据不留"待填充"。
  • 二次填充Fill 假定输入是未填充的原始模板——对已填充文档再次 Fill 时表格区域已指向整个数据块、首行会被当作示例行,会得到错位结果;需要重新生成请从原始模板 Fill。

回读行为要点

  • 文本按 TextElement.ValueType 转换(string/decimal/int/DateTime/bool);表格找到示例行克隆区逐行读回;图片读回字节。
  • Parse 规范化:未填充模板回读已知占位符(默认 zh "待填充" / en "To be filled",不依赖模板语言)规范化为 null(null=未填充、""=有意留空)。

依赖与测试

  • 目标框架 netstandard2.0 / net462 / net8.0(NuGet 按运行时自动选择)。
  • 依赖 DocumentFormat.OpenXml(3.3.x)。
  • 测试 test/TemplateFrame.Word.Tests:生成 → 校验 → 填充 → 回读 → 断言(含页眉页脚、多表、批量、跨列布局、页眉图片 part 归属等边界)。
  • 性能(普通开发机实测,随行数线性伸缩):千行明细填充 ~150ms、回读 ~125ms、构建 <1ms;快照见仓库 docs/PERFORMANCE.md,基准项目 test/TemplateFrame.Benchmarks

完整示例

见仓库 samples/TemplateFrame.Demo.Word送货单(双层页眉 + 9 列明细 + 两行页脚 + 收货前/后两次填充):

dotnet run --project samples/TemplateFrame.Demo.Word

设计文档见 docs/DESIGN.md,使用说明见仓库根 README.md

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 is compatible.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.3.1 49 8/27/2026
2.3.0 49 8/27/2026
2.2.0 48 8/27/2026
2.1.0 88 8/25/2026
2.0.0 90 8/24/2026
1.0.7 100 8/17/2026
1.0.6 107 8/11/2026
1.0.5 104 8/8/2026
1.0.4 100 8/7/2026
1.0.3 85 8/7/2026
1.0.2 88 8/7/2026
1.0.1 84 8/7/2026
1.0.0 96 8/6/2026