最近在做一个生成文档的需求。通过先制作一个包含各字段占位符的文档模板,导入这个模板并填写内容替换掉占位符,再输出成最终文件。

由于版式固定,安全性更好,业务上常用Pdf作为最终标准化的格式, 在.Net平台下,可以使用PdfSharp导入,,导出Pdf文档。这次做一个生成电子处方Pdf的小示例:

制作模板

使用一个Pdf器(如福昕PDF器)创建模板RecipeTemplate

用[形状]绘制表格框体,用[文本]工具,先插入好固定的内容,比如标题、和各栏目冒号之前的内容。

绘制完成如下图

再用[表单 - 文本域] 工具,在各个需要生成内容的地方插入表单项。

文本域名称中,填入占位符

假定占位符规则为:

  1. 图片占位符: #{字段名称}#
  2. 文字占位符: ${字段名称}$

那么“医院名称”展位符则设置如下:

完成所有字段的占位符,如下图:

编写代码

用visual studio新建一个PdfGenerator的项目,保存RecipeTemplate.pdf至Assets目录并设置复制输出目录方式为“始终复制”

项目引用PdfSharp库

dotnet add package PdfSharp --version 1.50.5147

创建模型类RecipeDocInfo,此类用于承载业务数据

    public class RecipeDocInfo
{
public int Id { get; set; }
public string HospitalName { get; set; }
public string DepartmentName { get; set; }
public string ClientName { get; set; }
public string ClientAge { get; set; }
public string ClientSex { get; set; }
public string Rps { get; set; }
public string DraftEmployeeName { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Status { get; set; }
public string AuditEmployeeName { get; set; }
public string DraftEmployeeSignature { get; set; }
public string AuditEmployeeSignature { get; set; }
public string StartTimeString { get; set; }
}

Exporter.cs中,创建ExportDocxByObject方法,使用PdfReader.Open()可以获取PdfDocument对象

public static PdfDocument ExportDocxByObject(string templatePath, object data)
{
var doc = PdfReader.Open(templatePath, PdfDocumentOpenMode.Modify);
return doc;
}

PdfDocument.AcroForm()方法可以拿到Pdf文档中的表单对象,该对象中的Fields存储表单项目集合,遍历Key值获取每个表单项

PdfAcroForm form = doc.AcroForm;
foreach (var fieldName in form.Fields.Names)
{
var run = form.Fields[fieldName] as PdfTextField;
text = run.Name; //获取每一个占位符名称 }

表单项的Name属性为我们设置的表单名称,即占位符。

接下来处理数据对象,通过反射方式获取对象成员名称,并与占位符作匹配,若占位符包含(string.Contains())该成员名称,则将值写入这个表单项的Value中,这里注意一个多行处理的情况。

foreach (PropertyInfo p in pi)
{
string key = $"${p.Name}$";
if (text.Contains(key))
{
var value = "";
try
{
value = p.GetValue(model, null).ToString();
}
catch (Exception ex)
{
} if (value.Contains('\n'))
{
run.MultiLine = true; } run.Value = new PdfString(value);
run.ReadOnly = true;
}
}

readOnly设置为true,以防止Pdf表单中的值被随意修改。

同理我们处理图片:

首先数据对象中的内容,应为图片的本地路径或者网络Url

var filePath = p.GetValue(model, null) as string;

然后读取,绘制图片,注意图片的大小以及位置坐标显示,与表单所对应的框架(/Rect)一致

详细的绘图方式,请参考官方文档:PDFsharp Sample: Graphics - PDFsharp and MigraDoc Wiki

var rectangle = run.Elements.GetRectangle("/Rect");
var xForm = new XForm(doc, rectangle.Size);
using (var xGraphics = XGraphics.FromPdfPage(doc.Pages[0]))
{
var image = XImage.FromStream(fileStream);
xGraphics.DrawImage(image, rectangle.ToXRect() +new XPoint(0, 400));
var state = xGraphics.Save();
xGraphics.Restore(state);
}

完成Exporter.cs之后,在Main函数中使用

public class Program
{
public static async Task Main(string[] args)
{
Console.WriteLine("Generator begin");
var docinfo = GetRecipeDocInfo() { ... };
var result = Exporter.ExportDocxByObject(/*template path*/, docinfo);
result.Save(/*output path*/);
}
}

测试

至此完成了所有工作,运行程序,待程序执行完毕后,打开output目录下生成的文档,看看最后效果:

项目地址:

jevonsflash/PdfGenerator (github.com)

结束语

根据这一思想,我们可以直观地我们想要的最终文件,无论这个文档多么复杂,我们只用关心占位符和最终的值。

同样,这一思想也可以应用到NPOI库来生成Word文档。

使用PdfSharp从模板生成Pdf文件的更多相关文章

  1. 根据PDF模板生成PDF文件(基于iTextSharp)

    根据PDF模板生成PDF文件,这里主要借助iTextSharp工具来完成.场景是这样的,假如要做一个电子协议,用过通过在线填写表单数据,然后系统根据用户填写的数据,生成电子档的协议.原理很简单,但是每 ...

  2. 使用word模板生成pdf文件

    使用word模板生成pdf文件 源码:UserWord

  3. itextsharp利用模板生成pdf文件笔记

    iTextSharp是一款开源的PDF操作类库,使用它可以快速的创建PDF文件. 中文参考网站:http://hardrock.cnblogs.com/ http://pdfhome.hope.com ...

  4. Android根据pdf模板生成pdf文件

    我们需要生成一些固定格式的pdf文件或者一些报表数据,那么我们可以用 iText包去做. 需要包含的jar包:iText-5.0.6.jar    iTextAsian.jar ,怎样jar包导入工程 ...

  5. Itext生成pdf文件

    来源:https://my.oschina.net/lujianing/blog/894365 1.背景 在某些业务场景中,需要提供相关的电子凭证,比如网银/支付宝中转账的电子回单,签约的电子合同等. ...

  6. 通过pdf模板,填充内容,生成pdf文件---JAVA

    1 概述 我们通常会遇到需要生成某些固定格式,但是内容不同的文件,那么我们就可以使用⽤Adobe Acrobat DC来创建pdf模块,然后通过代码对模板进行填充,生成pdf文件 2 创建一个pdf模 ...

  7. java调用wkhtmltopdf生成pdf文件,美观,省事

    最近项目需要导出企业风险报告,文件格式为pdf,于是搜了一大批文章都是什么Jasper Report,iText ,flying sauser ,都尝试了一遍,感觉不是我想要的效果, 需要自己调整好多 ...

  8. JavaWeb项目生成PDF文件添加水印图片并导出

    一.前言 首先需要在Maven中添加相应的jar包依赖,若项目没用到Maven,也可自行下载相应所需的jar包(itextpdf.jar 与 itext-asian.jar),如下图所示.点此下载 M ...

  9. 在spring boot 中使用itext和itextrender生成pdf文件

    转载请注明出处 https://www.cnblogs.com/majianming/p/9539376.html 项目中需要对订单生成pdf文件,在第一版本其实已经有了比较满意的pdf文档,但是还是 ...

  10. 结合模板导出PDF文件

    @Action("report_exportJasperPdf")    public String exportJasperPdf() throws Exception{     ...

随机推荐

  1. 剪粘板增强小工具(可多次Ctrl+V)

    前言 windows的剪贴板中存储是的最新一次的复制结果,比如先复制A,再复制B,C,在按下粘贴键时粘贴的是最后一次的结果C,在工作时有时候会遇到需要多次复制粘贴的情景,我就在思考有没有一款工具可以保 ...

  2. 我为什么从Windows转到Linux?

    本文来自读者投稿! 大家好!我是 Guide 哥,Java 后端开发.一个会一点前端,喜欢烹饪的自由少年. 如果文章有任何需要改善和完善的地方,欢迎在评论区指出,共同进步! 喔,看到这个标题千万不要以 ...

  3. 如何在 Linux 上使用 NPOI

    由于 NPOI 使用 System.Drawing.Common,因此在 Linux 系统上必须安装 libgdiplus 和 libc6. Ubuntu 16.04+ apt-get install ...

  4. PaddleNLP基于ERNIR3.0文本分类以CAIL2018-SMALL数据集罪名预测任务为例【多标签】

    相关项目链接: Paddlenlp之UIE模型实战实体抽取任务[打车数据.快递单] Paddlenlp之UIE分类模型[以情感倾向分析新闻分类为例]含智能标注方案) 应用实践:分类模型大集成者[Pad ...

  5. 深度学习应用篇-计算机视觉-语义分割综述[6]:DeepLab系列简介、DeepLabV3深入解读创新点、训练策略、主要贡献

    深度学习应用篇-计算机视觉-语义分割综述[6]:DeepLab系列简介.DeepLabV3深入解读创新点.训练策略.主要贡献 0.DeepLabV3深入解读 1.DeepLab系列简介 1.1.Dee ...

  6. 【四】AI Studio 项目详解【VisualDL工具、环境使用说明、脚本任务、(四)图形化任务、在线部署及预测】PARL

    相关文章 [一]-环境配置+python入门教学 [二]-Parl基础命令 [三]-Notebook.&pdb.ipdb 调试 [四]-强化学习入门简介 [五]-Sarsa&Qlear ...

  7. React核心概念与JSX

    React概况 React是一个只用来写HTML的UI页面的JS库,在MVC设计模式中它只相当于View,故:它并不是一个框架(MVC架构角色设计). React组件内数据改动会自动更新到屏幕上. R ...

  8. Go语言实现八大排序|排序算法|超详细保姆级别注释

    前言 那么这里博主先安利一些干货满满的专栏了! 首先是博主的高质量博客的汇总,这个专栏里面的博客,都是博主最最用心写的一部分,干货满满,希望对大家有帮助. 高质量博客汇总https://blog.cs ...

  9. MySQL的四种分区方式

    1. 什么是表分区? mysql数据库中的数据是以文件的形势存在磁盘上的,默认放在/mysql/data下面(可以通过my.cnf中的datadir来查看),一张表主要对应着三个文件,一个是frm存放 ...

  10. 快速上手typescript(基础篇)

    壹 ❀ 引 在javascript开发中,你可能也遇到过我这样的苦恼,在维护某段几年前的老旧代码时,我发现了某个数据加工方法fn,而且根据现有逻辑来看fn的某个参数是一个数组,因为新需求我需要对数组做 ...