TemplateFrame 2.3.1
dotnet add package TemplateFrame --version 2.3.1
NuGet\Install-Package TemplateFrame -Version 2.3.1
<PackageReference Include="TemplateFrame" Version="2.3.1" />
<PackageVersion Include="TemplateFrame" Version="2.3.1" />
<PackageReference Include="TemplateFrame" />
paket add TemplateFrame --version 2.3.1
#r "nuget: TemplateFrame, 2.3.1"
#:package TemplateFrame@2.3.1
#addin nuget:?package=TemplateFrame&version=2.3.1
#tool nuget:?package=TemplateFrame&version=2.3.1
TemplateFrame
中文 · English
一个"模板 ⇄ 数据"契约引擎:导出和导入是同一个契约的两个方向——
- 导出(Fill) = 模板 + 强类型数据 → 文件
- 导入(Parse) = 文件 → 按契约解析 → 强类型数据
模板由代码生成、用户只改样式;上传时校验模板与契约匹配(缺什么、多什么、哪里错,一行行列得清清楚楚)。
选哪个包
| 你的需求 | 安装 | 说明 |
|---|---|---|
| 列表数据导入 / 导出(标题行 + 数据行) | TemplateFrame.Excel.Simple |
一个 List<T> 进出 xlsx,最简路径 |
| Word 单据打印(页眉页脚 / 表格 / 图片 / A5 横版) | TemplateFrame.Word |
内容控件(SDT)定位,用户随便改样式不影响回读 |
| Excel 复杂表单(合并单元格 / 图片 / 自由版式) | TemplateFrame.Excel |
命名区域定位,网格规整型版式 |
三个插件都依赖基础包 TemplateFrame(契约模型 + 强类型服务基类),装插件即自动引入。只想手写 Excel 表格、不要契约?TemplateFrame.Excel.Simple 里的 SimpleExcel.Write / Read 静态类可以单独用。
目标框架
四包统一 netstandard2.0 / net462 / net8.0 多目标,NuGet 按运行时自动选择:
| 你的运行时 | 命中资产 |
|---|---|
| .NET Framework 4.6.2+ | net462 |
| .NET 5 – 7 | netstandard2.0 |
| .NET 8+ | net8.0(net9 / net10 向下兼容消费) |
唯一第三方依赖 DocumentFormat.OpenXml(net462 资产另带 System.ValueTuple)。
快速开始:3 分钟跑通导入导出
以物料清单为例(TemplateFrame.Excel.Simple):
dotnet add package TemplateFrame.Excel.Simple
① 定义数据与服务——声明契约(有哪些列),版式与映射全部省掉:
using TemplateFrame.Contract;
using TemplateFrame.Excel.Simple;
public sealed record MaterialLine
{
public string Code { get; init; } = string.Empty;
public string Name { get; init; } = string.Empty;
public string? Unit { get; init; }
}
public sealed record MaterialsData
{
public IReadOnlyList<MaterialLine> Items { get; init; } = [];
}
public sealed class MaterialsService : SimpleExcelTemplateService<MaterialsData>
{
protected override TemplateContract DefineContract() => new()
{
Name = "Materials",
Version = "1.0",
Elements =
[
new TableElement
{
Key = "Materials",
DataPath = "Items", // 指向 MaterialsData.Items,自动映射
Columns =
[
new TextElement { Key = "Code", DisplayName = "编码", DataPath = "Code", Required = true },
new TextElement { Key = "Name", DisplayName = "名称", DataPath = "Name", Required = true },
new TextElement { Key = "Unit", DisplayName = "基本单位", DataPath = "Unit" },
],
},
],
};
}
② 四个操作:
var service = new MaterialsService();
using var template = service.BuildTemplate(); // 生成模板(仅表头的 xlsx,发给用户)
using var filled = service.Fill(data); // 强类型数据 → 填充后的 xlsx(导出)
var validation = service.Validate(template); // 校验上传的模板与契约匹配(缺列/错位列清单)
var parsed = service.Parse(filled); // 读回文件 → 强类型 MaterialsData(导入)
// BuildTemplate / Fill 返回内存流,需要落盘时:
using var file = File.Create("filled.xlsx");
filled.CopyTo(file);
TData 甚至可以直接是 List<MaterialLine>(根集合,契约表格的 DataPath 留空)——Fill(list) / Parse(stream) 不用包一层容器对象。
核心模型
- 契约 = 元素清单:
TemplateContract描述场景有哪些元素(TextElement/ImageElement/TableElement),可序列化、可版本化。表头列名、校验规则、导入导出的键,都从这一份声明来。 - 模板归业务应用:契约不产出版式。业务服务在
BuildInitialTemplate()里用插件的类型化构建器组装版式(标题、表格、图片占位、页眉页脚);也可以让设计师直接用 Word 做,Validate统一兜底。 - 数据形状
FillData:与插件无关的弱类型容器。契约元素声明DataPath后由DataPathMapper自动映射(默认),或手写MapToData/MapFromData完全掌控。 - 软校验分级:
Validate上传时强校验(Missing / WrongType / Ambiguous 报错,可选字段缺失只告警);Fill前软校验(Drifted/Extra记告警继续;必填缺失默认抛错,可配MissingElementPolicy.SkipAndWarn)。需要拿到告警清单:导出用FillDetailed(输出流 + Warnings),导入用ParseDetailed(数据 + 转换告警,失败字段保留原始文本、null 仍专指未填充)。
Word / Excel 灵活版式
单据打印这类复杂版式用 TemplateService<TData, TBuilder>——继承时声明插件构建器类型,版式能力就是构建器的方法:
public sealed class DeliveryOrderService : TemplateService<DeliveryOrderData, WordTemplateBuilder>
{
public DeliveryOrderService() : base(new WordTemplateEngine()) { }
protected override TemplateContract DefineContract() => /* 元素清单 */;
protected override void BuildInitialTemplate()
{
Builder.SetPageSetup(new PageSetup { Size = PageSize.A5, Orientation = PageOrientation.Landscape });
Builder.AddHeader(BuildHeader);
Builder.AddTable("Lines", ["序号", "物料名称", "数量"],
new TableFormat { ColumnWidthsCm = [1.8, 8.5, 3.2] });
Builder.AddImage("QrCode", widthInches: 1.0, heightInches: 1.0);
}
}
WordTemplateBuilder:SetPageSetup/AddHeader/AddFooter/AddParagraph/AddText/AddElement/AddTable/AddImage/AddPageNumber/AddLayoutTable/AddCell……ExcelTemplateBuilder:SetSheetName/AddText(单元格, 文本)/AddElement/AddTable/AddImage/MergeCells/SetColumnWidth……- 定位不靠位置靠标记:Word 用内容控件 tag,Excel 用命名区域(
TF_<Key>)——用户移动元素、改样式都不影响填充与回读;表格按"示例行"克隆填充,克隆后自动重发唯一 id / 重指区域。
多语言:版式文本 / 表头可用 i18n 键方法(AddParagraphKey / AddTableKeys 等),BuildInitialTemplateFile(CultureInfo?) 按语言出模板;运行时消息(校验 / 异常)中英双语按 CurrentUICulture 自动。详见设计文档。
示例
samples/ 提供 8 个控制台 Demo(Word / Excel / Excel.Simple × 手写映射 / 自动映射 / i18n),运行命令与输出说明见 docs/DEMOS.md。比如送货单 Word 版:
dotnet run --project samples/TemplateFrame.Demo.Word
文档
| 文档 | 内容 |
|---|---|
| docs/DESIGN.md | 架构与设计决策(三层拆分、定位机制、校验模型、决策记录) |
| docs/DEMOS.md | 8 个 Demo 的运行命令与输出说明 |
| docs/ROADMAP.md | 迭代路线图(已归档 + 规划) |
| docs/PUBLISHING.md | 发布流程(打 v* tag 自动发 GitHub Release + nuget.org) |
| docs/PERFORMANCE.md | 性能快照(三插件吞吐/分配实测 + 基准复现) |
| CHANGELOG.md | 变更日志 |
| 插件 README | Word · Excel · Excel.Simple |
构建与测试
dotnet build TemplateFrame.slnx
dotnet test TemplateFrame.slnx
打包
dotnet pack src/TemplateFrame/TemplateFrame.csproj -c Release -o artifacts
dotnet pack src/TemplateFrame.Word/TemplateFrame.Word.csproj -c Release -o artifacts
dotnet pack src/TemplateFrame.Excel/TemplateFrame.Excel.csproj -c Release -o artifacts
dotnet pack src/TemplateFrame.Excel.Simple/TemplateFrame.Excel.Simple.csproj -c Release -o artifacts
包内置 XML 文档与 README,符号包(snupkg)一并输出;版本号统一写在 src/Directory.Build.props,发布流程见 docs/PUBLISHING.md。
| Product | Versions 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. |
-
.NETFramework 4.6.2
- System.ValueTuple (>= 4.5.0)
-
.NETStandard 2.0
- No dependencies.
-
net8.0
- No dependencies.
NuGet packages (3)
Showing the top 3 NuGet packages that depend on TemplateFrame:
| Package | Downloads |
|---|---|
|
TemplateFrame.Word
TemplateFrame 的 MS Word 插件:内容控件(SDT)生成 / 定位 / 填充 / 回读 / 校验 |
|
|
TemplateFrame.Excel.Simple
TemplateFrame 的简化 Excel 插件:只支持「标题行 + 数据行」的表格导入/导出(无命名区域/合并/图片/页面设置) |
|
|
TemplateFrame.Excel
TemplateFrame 的 MS Excel 插件:命名区域(defined names)定位的生成 / 校验 / 填充 / 回读 |
GitHub repositories
This package is not used by any popular GitHub repositories.