NDocxTemplater 1.8.1

dotnet add package NDocxTemplater --version 1.8.1
                    
NuGet\Install-Package NDocxTemplater -Version 1.8.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="NDocxTemplater" Version="1.8.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="NDocxTemplater" Version="1.8.1" />
                    
Directory.Packages.props
<PackageReference Include="NDocxTemplater" />
                    
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 NDocxTemplater --version 1.8.1
                    
#r "nuget: NDocxTemplater, 1.8.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 NDocxTemplater@1.8.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=NDocxTemplater&version=1.8.1
                    
Install as a Cake Addin
#tool nuget:?package=NDocxTemplater&version=1.8.1
                    
Install as a Cake Tool

NDocxTemplater

一个基于 OpenXML 的模板渲染库,当前支持 .docx + JSON.xlsx + JSON.pptx + JSON,目标是提供类似 docxtemplater 的 .NET 替代方案。

目标框架

  • netstandard2.0
  • netstandard2.1

测试工程使用 net10.0 + xUnit

已实现能力

  • 基础标签替换:{a.b[0].c}
  • 条件分支:{?expr} ... {/?expr}
  • 循环:{#expr} ... {/expr}
  • 表格循环:把循环标记放在表格行中,可按行复制输出列表数据
  • .xlsx 工作表行循环:把循环/条件标记放在工作表行中,可按行复制输出列表数据,并保留模板行样式
  • .xlsx 工作表媒体占位符:在单元格中使用图片/条形码占位符,渲染为 worksheet drawing
  • .xlsx 模板行复制时支持合并单元格重建,以及公式中的相对行引用修正
  • .pptx slide 级循环/条件:在单个 slide 上使用 {:expr},数组会复制 slide,falsy 会移除 slide,truthy 会保留一次
  • .pptx 幻灯片文本占位符:在文本框/形状文字中使用与 .docx 相同的路径和格式表达式
  • 支持 Word 将标签拆分到多个 Run/Text 节点后的渲染(包含表格单元格内格式表达式)
  • 图片标签(参考 docxtemplater image tag 风格)
    • inline:{%imagePath}
    • block/居中:{%%imagePath}
    • 数据支持:base64 data URI、base64 字符串、文件路径
    • 支持缩放参数(图片数据对象):
      • width / height:目标尺寸(像素)
      • maxWidth / maxHeight:最大边界(像素)
      • scale:缩放倍率(如 0.25
      • preserveAspectRatio(或 keepAspectRatio):是否保持宽高比,避免拉伸变形
    • 当前约束:图片标签需独占一个段落(单独一行)
  • 条形码标签(inline/block 与图片标签一致)
    • inline:{%barcode:expr;type=code128;width=360;height=96}
    • block/居中:{%%barcode:expr;type=ean13;width=280;height=100}
    • expr 为数据源路径(应解析为字符串/数字)
    • 支持参数:
      • type / formatcode128code39code93codabarean13ean8upcaitf
      • width / height:输出尺寸(像素)
      • margin:条码边距(像素)
      • pure:是否仅输出条码图形(true/false
    • 实现基于 NetBarcodenetstandard2.0 资产),避免运行时加载 PresentationCore 的问题
  • 表达式扩展(管道语法)
    • 排序:|sort:key:asc|sort:key:desc
    • 截断:|take:10
    • 计数(可直接用于 inline 文本):|count
    • inline 友好聚合/取值:
      • 首项/末项:|first|last
      • 位次取项:|nth:N(1-based,如第3名)、|at:index(0-based,支持负数如 -1
      • 按字段取最大/最小项:|maxby:key|minby:key
      • 从当前值继续取字段:|get:path(别名:|pick:path
    • inline 条件分支:
      • |if:trueText:falseText
      • |if:trueText(false 时输出空字符串)
    • 格式化:
      • 数值:|format:number:0.00
      • 百分比(原始值为小数):|format:percent:0.001.23%
      • 千分比(原始值为小数):|format:permille:0.0012.30‰
      • 日期:|format:date:yyyy-MM-dd

模板语法示例

患者: {patient.name}

{?patient.isVip}
VIP 客户
{/?patient.isVip}

{#orders|sort:amount:desc|take:2}
{id} -> {amount|format:number:0.00}
{/orders|sort:amount:desc|take:2}

{%logo}
{%%cover}
{%barcode:barcodes.code128;type=code128;width=360;height=96}

图片数据对象示例(路径 / data URI + 等比缩放):

{
  "fromPath": {
    "src": "chart.png",
    "maxWidth": 376,
    "preserveAspectRatio": true
  },
  "fromDataUri": {
    "src": "data:image/png;base64,...",
    "scale": 0.25,
    "preserveAspectRatio": true
  }
}

Inline 文本段落友好写法

在报告正文段落里,通常希望用单行模板直接表达“区间 + 最大值/最小值”这类语句。可以组合 sort/first/last/maxby/minby/get/format 来完成,而不需要额外的块标签换行。

统计数据包括了从{financeMonthly|sort:month:asc|first|get:month|format:date:yyyy年M月}
到{financeMonthly|sort:month:asc|last|get:month|format:date:yyyy年M月}的财务数据,
其中营收最高的是{financeMonthly|maxby:revenue|get:month|format:date:M月},
营收为{financeMonthly|maxby:revenue|get:revenue|format:number:#,##0}元

在这些机构的对比数据中,其中营收最高的为{institutions|maxby:revenue|get:name},
收入为{institutions|maxby:revenue|get:revenue|format:number:#,##0}元,
营收最低的为{institutions|minby:revenue|get:name},
收入为{institutions|minby:revenue|get:revenue|format:number:#,##0}元

前10名机构中,第3名为{institutions|sort:revenue:desc|take:10|nth:3|get:name},
收入为{institutions|sort:revenue:desc|take:10|nth:3|get:revenue|format:number:#,##0}元,
前10名末位为{institutions|sort:revenue:desc|take:10|at:-1|get:name}

本次样本共{institutions|count}家机构,状态:{flags.includeRates|if:包含比率指标:不包含比率指标},
环比增长率{metrics.growthRate|format:percent:0.00},
坏账率{metrics.badDebtRate|format:permille:0.00}

说明:

  • |count 已支持 inline 文本(例如 共有{items|count}项
  • |format:number:0.00% / |format:number:0.00‰ 也仍然可用;percent/permille 只是更直观的别名

XLSX 模板行语法

.xlsx 目前遵从现有“表格部分”的控制标记语法,只是把载体换成了工作表行:

第 1 行: Item | Qty | Amount
第 2 行: {#report.lines|sort:amount:desc|take:2} | | 
第 3 行: {name} | {qty} | {amount|format:number:0.00}
第 4 行: {/report.lines|sort:amount:desc|take:2} | |
第 5 行: {?showFooter} | |
第 6 行: Count | {report.lines|count} |
第 7 行: {/?showFooter} | |

规则:

  • 控制标记行应只有一个非空单元格包含完整标记,其他单元格留空
  • 循环块会复制中间模板行,并保留模板行/单元格样式
  • 普通单元格内联表达式与 .docx 使用同一套路径和管道语法
  • 图片/条形码占位符可放在单元格中,建议独占一个单元格:
    • 图片:{%pathImage}{%%pathImage}
    • 条形码:{%barcode:barcodes.ean13;type=ean13;width=220;height=80}
  • 模板行被循环复制时:
    • 行内公式会按最终行号重写相对引用
    • 模板中的合并单元格区域会随复制后的行块一起展开重建
    • 位于循环块之后的汇总公式,若引用了循环块行范围,也会按最终输出行范围扩展

PPTX Slide 语法

.pptx 采用接近 docxtemplater slides module 的 slide 级语法:

Slide 1:
  Title {report.title}

Slide 2:
  {:users}
  User {name}
  Amount {amount|format:number:0.00}

Slide 3:
  {:showSummary}
  Summary {summaryText}

规则:

  • {:expr} 是 slide 级标签,通常单独放在一个文本框或段落里
  • expr 解析为数组时,该 slide 会按数组元素逐个复制
  • expr 为 falsy 时,该 slide 会被删除
  • expr 为 truthy 且不是数组时,该 slide 保留一次
  • slide 内其他 {path|format} 文本占位符继续按当前 slide 上下文渲染
  • 当前版本聚焦 slide 级重复/条件和文本替换,不在 .pptx 中复用 .docx 的段落块循环语法

快速使用

using NDocxTemplater;

var engine = new DocxTemplateEngine();
var templateBytes = File.ReadAllBytes("template.docx");
var json = File.ReadAllText("data.json");

var outputBytes = engine.Render(templateBytes, json);
File.WriteAllBytes("output.docx", outputBytes);

.xlsx 用法:

using NDocxTemplater;

var engine = new XlsxTemplateEngine();
var templateBytes = File.ReadAllBytes("template.xlsx");
var json = File.ReadAllText("data.json");

var outputBytes = engine.Render(templateBytes, json);
File.WriteAllBytes("output.xlsx", outputBytes);

.pptx 用法:

using NDocxTemplater;

var engine = new PptxTemplateEngine();
var templateBytes = File.ReadAllBytes("template.pptx");
var json = File.ReadAllText("data.json");

var outputBytes = engine.Render(templateBytes, json);
File.WriteAllBytes("output.pptx", outputBytes);

NuGet Package

  • Package ID: NDocxTemplater
  • Repository: https://github.com/whynpc9/NDocxTemplater

发布由 GitHub Actions 自动完成:

  • CI:build + test + lint(dotnet format)
  • 发布:打 tag(如 v0.1.0)或手动触发 Publish NuGet workflow
  • NuGet API Key 使用仓库 Secret:NUGET_API_KEY

Examples

examples 下每个子目录都是一个独立用例,至少包含:

  • template.docxtemplate.xlsx:模板文件
  • data.json:输入数据
  • output.docxoutput.xlsx:按模板渲染后的结果文档
  • example.cs:最小调用代码

目录如下:

examples/
  01-basic-tags/
  02-condition/
  03-loop/
  04-table-loop/
  05-extensions/
  06-images/
  07-table-date-format-split-runs/
  08-inline-friendly-expressions/
  09-inline-ranking-positions/
  10-inline-conditions-and-rates/
  11-images-file-and-datauri-scaling/
  12-barcodes/
  13-xlsx-row-loop/
  14-xlsx-media-placeholders/
  15-xlsx-merged-cells-and-formulas/
  16-pptx-slide-loop-and-condition/

各示例说明:

  • 01-basic-tags:基础路径替换(包含数组下标)
  • 02-condition:条件分支
  • 03-loop:段落循环
  • 04-table-loop:表格行循环
  • 05-extensions:排序/截断/计数/格式化
  • 06-images:图片标签(inline/block)和循环中的图片渲染
  • 07-table-date-format-split-runs:表格单元格内被拆分 Run 的日期格式表达式渲染
  • 08-inline-friendly-expressions:面向正文段落的 inline 聚合/取值表达式(区间、最大/最小值)
  • 09-inline-ranking-positions:面向“前 N 名中的第 K 名”场景的位次表达式(nth/at
  • 10-inline-conditions-and-rates:inline 条件分支、计数,以及百分比/千分比格式化
  • 11-images-file-and-datauri-scaling:使用真实 PNG 验证文件路径 / data URI 图片插入,以及缩放与等比适配
    • 该示例额外包含 chart.png(用于文件路径模式)
  • 12-barcodes:由模板占位符指定数据源路径与条码参数(类型、尺寸、边距)
  • 13-xlsx-row-loop.xlsx 工作表按行循环、条件行和单元格表达式替换
  • 14-xlsx-media-placeholders.xlsx 工作表中的图片/条形码占位符,包含文件路径、data URI 和条形码参数
    • 该示例额外包含 chart.png(用于文件路径模式)
  • 15-xlsx-merged-cells-and-formulas.xlsx 循环块中的跨行合并单元格,以及模板复制后的公式引用修正
  • 16-pptx-slide-loop-and-condition.pptx slide 级循环/条件,以及幻灯片文本占位符渲染

如需重新生成示例资产:

dotnet run --project tools/ExampleGenerator/ExampleGenerator.csproj --disable-build-servers

测试

dotnet test NDocxTemplater.sln --disable-build-servers -m:1

当前测试覆盖了:基础替换、条件、循环、表格映射、.xlsx 工作表行循环/条件/样式保留、.xlsx 图片/条形码占位符、.xlsx 合并单元格与公式引用修正、.pptx slide 级循环/条件与文本渲染、图片渲染(含文件路径/data URI真实 PNG、缩放与等比适配)、条形码渲染(类型/尺寸参数)、排序/截断/计数/格式化、inline 聚合/位次表达式、inline 条件分支、百分比/千分比格式化、表格内拆分 Run 标签格式化。

Acknowledgements

  • 本项目受 docxtemplater 启发,感谢原项目作者与社区在文档模板化领域的工作。
  • NDocxTemplater 为独立的 .NET 实现,不包含对原项目源码的直接移植。

Code Provenance

  • 本仓库的初始版本由 OpenAI Codex 协助生成,并由仓库维护者进行审阅、修改与测试。

License

本项目使用 MIT License,详见 LICENSE

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 was computed.  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 is compatible. 
.NET Framework net461 was computed.  net462 was computed.  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
1.8.1 76 3/26/2026
1.8.0 81 3/26/2026
1.7.0 88 3/18/2026
1.6.0 86 3/18/2026
1.5.1 99 3/3/2026
1.5.0 87 3/3/2026
1.4.0 99 2/26/2026
1.3.0 103 2/24/2026
1.2.0 94 2/24/2026
1.1.0 97 2/24/2026
1.0.2 97 2/24/2026
1.0.1 102 2/24/2026
1.0.0 98 2/15/2026