DocTemplateTool - 可根据模板生成word或pdf文件的工具
你是否经常遇到这样的场景:产品运营有着大量的报告需求,或者给客户领导展现每周的运营报告?这些文档类的任务可以交给运营同事,他们负责文档排版和样式,你作为开发人员你只需要提供数据源,和一个映射表,告诉制作文档的人哪些字段可供使用。这样一来分工明确,减少了很多不必要的沟通成本。
Document Template Tool
指定一个模板生成word或pdf文件

运行单元测试以查看示例!
功能 & 特点
- 基于占位符的模板,可继承原有样式;
- 支持表格;
- 支持数据集合;
- 支持图片;
- 提供Cli版本程序;
- 可扩展的接口封装和组件。
快速开始
使用Cli
进入可执行文件所在目录,在命令提示符中运行DocTemplateTool.exe
参数列表:
| 参数 | 含义 | 用法 |
|---|---|---|
| -p | PatternFile | 指定一个Object文件(Json), 作为数据源件 |
| -i | Input | 指定一个docx文件作为模板 |
| -o | Output | 指定一个路径,作为导出目标 |
| -s | Source | 值为json |
| -d | Destination | 值为word, pdf |
| -w | WaitAtEnd | 指定时,程序执行完成后,将等待用户输入退出 |
| -h | Help | 查看帮助 |
示例
.\wtt.exe -p .\sample\data.json -i .\sample\template.docx -o .\output\test.docx -s json -d word
使用DocTemplateTool.Word类库
在项目中引用DocTemplateTool.Word
dotnet add package DocTemplateTool.Word
由于Exporter返回的NPOI对象,你需要自行根据业务来处理结果,以及处理IO异常
byte[] docFileContent;var docinfo = GetDocInfo(); // 准备数据
var result = Exporter.ExportDocxByObject("D:\\Template.docx", docinfo); //生成NPOI文档对象//处理结果
using (var memoryStream = new MemoryStream())
{result.Write(memoryStream);memoryStream.Seek(0, SeekOrigin.Begin);docFileContent = memoryStream.ToArray();
}//写入文件或返回接口
File.WriteAllBytes("D:\\Result.docx", docFileContent);
占位符
占位符是指在模板中的一个标记,用于标记需要替换的文本或图片,
文本占位符的格式为:$字段名称[附加属性]$
图片占位符的格式为:#字段名称[附加属性]#
Exporter将扫描文档中所有占位符,然后根据占位符的名称,从数据源中获取对应的文本值或图片内容,替换到文档中。
文本
例如
姓名:$ClientName$
将被替换为
姓名:张三
图片
确认大小
图片占位符支持附加属性,用于指定图片的宽度和高度,格式为:#字段名称[宽度,高度]#
#Graphic[431,266]#
将被替换为一个宽度为431,高度为266的图片,单位为像素。
若不指定宽度和高度,则使用默认图片尺寸556*262。
在Word文档中,因为像素大小是个相对值,页面视图100%时的大小为实际像素尺寸,你可以使用截图工具或标尺工具确认图片的大小。

设置图片
图片源支持本地文件和网络图片以及Base64编码的图片。

从不同图片来源生成文档的示例运行如下:

数据集合
由于NPOI限制,暂不支持表格的嵌套。
数据集合将以表格的形式呈现在文档中,因此你需要在模板中预留一个表格,Exporter将根据表中单元格的占位符,填充表格各列的内容。
包含占位符的行称之为模板行。
定义
public class HealthReportDocInfo
{...public List<DetailList> BloodPressureList { get; set; }
}public class DetailList
{public string Name { get; set; }public string Dept { get; set; }public string Value { get; set; }public string Result { get; set; }
}
配置模板表格:

默认以第二行作为模板行(通常第一行为表头),你也可以根据实际情况跳过表头,
例如在工资登记表示例中,表头占两行的情况下,第三行为模板行,那么你需要在配置中指定模板行的索引为2(索引从0开始)。
$Details[2]$
模板行的样式将决定表格的样式,因此你可以在模板行中设置表格的样式,例如设置表格的字体,颜色,大小等。
示例运行如下图:

其他示例
企业员工健康管理周报

心电图报告

数据源
数据源支持从哈希表(字典)或对象中获取数据。
Exporter提供了ExportDocxByDictionary和ExportDocxByObject两个方法,分别用于从哈希表和对象中获取数据。
从哈希表中获取数据:
var docinfo = new Dictionary<string, object>()
{{"Dept", "XX科技股份有限公司" },{"Date", DateTime.Now },{"Number", "凭 - 202301111" },{"Details", new List<Dictionary<string, object>>(){new Dictionary<string, object>(){{ "Type","销售收款"},{ "Name","应收款"},{ "DeptorAmount",0},{ "LenderAmount",50000}},new Dictionary<string, object>(){{ "Type","销售收款"},{ "Name","预收款"},{ "DeptorAmount",30000},{ "LenderAmount",0}},new Dictionary<string, object>(){{ "Type","销售收款"},{ "Name","现金"},{ "DeptorAmount",20000},{ "LenderAmount",0}},}},{ "DeptorSum", 50000 },{ "LenderSum", 50000 },{ "ClientName", "XX科技股份有限公司" },{ "Teller", "张三" },{ "Maker", "李四" },{ "Auditor", "王五" },{ "Register", "赵六" },
};
var result = Word.Exporter.ExportDocxByDictionary(Path.Combine(templatePath_Doc, $"AccountingTemplate.docx"), docinfo, (s) => s);
从匿名对象中获取数据:
var docinfo = new
{Dept = "XX科技股份有限公司",Date = DateTime.Now,Number = "凭 - 202301111",Details = new List<dynamic>() {new{Type = "销售收款",Name = "应收款",DeptorAmount = 0,LenderAmount = 50000},new{Type = "销售收款",Name = "预收款",DeptorAmount = 30000,LenderAmount = 0},new{Type = "销售收款",Name = "现金",DeptorAmount = 20000,LenderAmount = 0},},DeptorSum = 50000,LenderSum = 50000,ClientName = "XX科技股份有限公司",Teller = "张三",Maker = "李四",Auditor = "王五",Register = "赵六",
};var result = Word.Exporter.ExportDocxByObject(Path.Combine(templatePath_Doc, $"AccountingTemplate.docx"), docinfo, (s) => s);
它们将得到同样的结果:

已知问题
作者信息
作者:林小
邮箱:jevonsflash@qq.com
License
The MIT License (MIT)
项目地址
Github:DocTemplateTool
相关文章:
DocTemplateTool - 可根据模板生成word或pdf文件的工具
你是否经常遇到这样的场景:产品运营有着大量的报告需求,或者给客户领导展现每周的运营报告?这些文档类的任务可以交给运营同事,他们负责文档排版和样式,你作为开发人员你只需要提供数据源,和一个映射表&…...
Python+reuqests自动化接口测试
1.最近自己在摸索Pythonreuqests自动化接口测试,要实现某个功能,首先自己得有清晰的逻辑思路!这样效率才会很快! 思路--1.通过python读取Excel中的接口用例,2.通过python的函数调用,get/Post 进行测试&…...
【Java 进阶篇】保护你的应用:Java 过滤器实现敏感词汇过滤
在开发 Web 应用程序时,安全性是至关重要的一环。保护用户免受恶意内容的侵害是开发者义不容辞的责任之一。在这篇博客中,我们将深入研究如何使用 Java 过滤器来过滤敏感词汇,确保用户输入的内容不包含不良信息。我们将采用简单而实用的方法&…...
目标检测网络系列——YOLO V4
文章目录 目标检测技术总结两种优化方向Bag of freebiesBag of specialsYOLO4网络结构网络架构(architecture)的选择基础网络结构的选择网络"插件"的选择。BoF和BoS的选择(Selection of BoF and BoS)YOLO4的其他改进点对比实验不同的特征(数据增强方法)之间的对比det…...
如何在Linux上部署1Panel运维管理面板并远程访问内网进行操作
文章目录 前言1. Linux 安装1Panel2. 安装cpolar内网穿透3. 配置1Panel公网访问地址4. 公网远程访问1Panel管理界面5. 固定1Panel公网地址 前言 1Panel 是一个现代化、开源的 Linux 服务器运维管理面板。高效管理,通过 Web 端轻松管理 Linux 服务器,包括主机监控、…...
CentOS系统安装vsftpd
下载并安装vsftpd apt-get install vsftpd 安装后检查 service vsftpd status 修改配置文件(被动/匿名用户模式) vi /etc/vsftpd.conf anonymous_enableNO listenYES listen_port21 ascii_upload_enableYES ascii_download_enableYES local_enableYES guest_enable…...
手握“发展密钥”,TCL科技或迎价值重估?
在高度竞争且快速变化的泛半导体产业,每一次周期性或结构性的变化,都会对企业经营策略带来深远的影响。 2023年前三季度,泛半导体产业迎来结构性复苏。其中,主流显示领域供需关系趋向健康化,半导体显示行业整体上量价…...
A star算法
1. 算法的理解 1.2 a 星算法的基本的原理 a 星 是一种启发式搜索算法, 用于在地图中的两个目标点之间寻找最短的路径,它结合了最优先搜索和Dijkstra算法的特点,通过考虑从起点到当前点的距离(或者代价 g(n) ) 和估算…...
node插件MongoDB(四)—— 库mongoose 操作文档使用(新增、删除、更新、查看文档)(二)
文章目录 前言(1)问题:安装的mongoose 库版本不应该过高导致的问题(2)重新安装低版本 一、插入文档1. 代码2. node终端效果3. 使用mongo.exe查询数据库的内容 二、删除文档1. 删除一条2. 批量删除3. 代码 三、修改文档…...
JavaFX入门和网格布局面板的使用,Dao层交互,舞台与场景切换以及其他控件的使用
网格布局 将整个面板划分为若干个格子 , 每个格子的大小是一样的 , 每个格子中可以放置一个控件(布局) , 类似于表格的方式。在网格布局 中放入控件的时候 , 还需要指定位置。 GridPane gridPane new GridPane(); 我们将要排出这个布局 , 也就是登陆页…...
数据中台之数据分析
效果界面 技术方案 Notebook集成 在您的数据平台上,创建一个能够与Jupyter Notebook通讯的服务。通过Jupyter Notebook的HTTP API与Notebook实例进行交互,执行代码、获取输出等。用户界面 在数据开发/数据分析的代码框右上方,添加一个机器人样式的图标,用户点击后可以调起…...
龙芯loongarch64服务器编译安装scipy
前言 根据我之前的文章介绍,龙芯loongarch64服务器中的很多python依赖包安装有问题,发现其中安装的"scikit-learn"就无法正常使用,所有这里在 pip3 install scikit-learn -U -i https://pypi.tuna.tsinghua.edu.cn/simple 的时候发现"scipy"就无法正常…...
ubuntu(18.04)中安装open babel docker镜像并在php项目中调用容器中的obabel命令解析结果使用
使用软件: obabel镜像:informaticsmatters/obabel docker:http:// https://www.docker.com/ 安装docker #卸载旧版本sudo apt-get remove docker docker-engine docker-ce docker.io#更新索引包sudo apt-get update#安装 apt 依赖包&…...
02-PostgreSQL的基本使用
一、数据库操作 ①: 登录到数据库 psql -U postgres -d postgres -h 127.0.0.1②:查看所有数据库 \l③: 创建数据库 # 创建一个名为 mydb 的数据库 create database mydb;④:切换数据库 # \c 数据库名 \c mydb⑤:删除数据库 # 删除前 先确保数据库没有被连接 drop databa…...
uniapp 实现路线规划
UniApp是一个跨平台的应用开发框架,可以帮助开发者快速地在多个平台上构建应用程序。其中,实现路线规划是一个常见的需求,特别是对于地图类应用或者出行类应用来说,路线规划功能是非常重要的。 首先引入QQMapWX; impo…...
C语言C位出道心法(五):内存管理
C语言C位出道心法(一):基础语法 C语言C位出道心法(二):结构体|结构体指针|链表 C语言C位出道心法(三):共用体|枚举 C语言C位出道心法(四):文件操作 C语言C位出道心法(五):内存管理 一:C语言内存管理认知 二:C语言中内存堆|栈认知 三:C语言中引用内存丢失认知...
Flink之SQL客户端与DDL操作
SQL客户端与DDL操作 Flink SQLSQL客户端1.启动Flink2.启动Flink的SQL客户端3.HELP命令4.验证连接5.结果显示模式6.执行配置 数据库操作1.创建数据库2.查询数据库3.修改数据库4.删除数据库 表操作1.创建表表列属性表Watermark属性列PRIMARY KEY属性列PARTITIONED BY属性列WITH选…...
记录第一次银行测试岗面试【总结几点面试不要犯得错误】
LZ在一个18线小城市做测试,近来想走出自己的舒适区,去做一点不一样的测试工作。 18线地区,测试工作并不多。最好的差不多就是LZ目前待着的公司了。遂决定去魔都闯荡几年,对一个在魔都无房无车无户口的人来讲,这意味着…...
一篇带你精通php
华子目录 什么是phpphp发展史平台支持和数据库支持网站静态网站和动态网站的区别静态网站动态网站的特点 关键名词解析服务器概念IP的概念域名DNS端口 web程序的访问流程静态网站访问流程动态网站访问流程 php标记脚本标记标准标记(常用) php注释 什么是…...
Go 语言函数
文章目录 Go 语言函数1. **函数的定义**:2. **参数和返回值**:3. **函数调用**:4. **多返回值**:5. **匿名函数**:6. **函数作为值**:7. **变参函数**:8. **递归函数**:9. **函数方法…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...
go 里面的指针
指针 在 Go 中,指针(pointer)是一个变量的内存地址,就像 C 语言那样: a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10,通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...
