首页 > 其他分享 >使用PdfSharp从模板生成Pdf文件

使用PdfSharp从模板生成Pdf文件

时间:2022-10-25 15:56:50浏览次数:85  
标签:set string get PdfSharp 占位 var Pdf public 模板

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

由于版式固定,安全性更好,业务上常用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文档。

标签:set,string,get,PdfSharp,占位,var,Pdf,public,模板
From: https://www.cnblogs.com/jevonsflash/p/16825107.html

相关文章

  • 下载模板,从前端到后端
    前端Vue:vartempType="application/msexcel";   this.SearchForm.Type="2";   this.tableHeader.forEach((element)=>{    this.SearchForm.se......
  • 模板库
    2022.10.25:模板库迁移至cnblogs。1.离散化//unordered_map<int,int>b;intb(intx){returnlower_bound(a+1,a+n+1,x)-a;//返回1~r的数}voiddisc......
  • fcpx插件:Stupid raisins show pop for Mac(20个标题展示模板)
    mac哪款fcpx标题展示插件好用呢?StupidrAIsinsshowpopforMac是一款运行在MacOS平台,搭配FinalCutPro x软件一起使用的标题展示模板。StupidrAIsinsshowpop有20个......
  • 02Vue模板语法
    一、插值语法功能:用于解析标签体内容。写法:{{xxx}},xxx是js表达式,且可以读取到data中的所有属性。二、指令语法功能:用于解析标签(包括:标签属性、标签体内容、绑定事件......
  • 类的编写模板之简单Java类
    简单Java类是初学java时的一个重要的类模型,一般由属性和getter.setter方法组成,该类不涉及复杂的逻辑运算,仅仅是作为数据的储存,同时该类一般都有明确的实物类型。如:定义一个......
  • vscode 设置vue的用户片段-- vue文件 httpget httppost 请求 模板
      文件->首选项->用户片段{"生成vue模板":{"prefix":"vue","body":["<!--$1-->","<template>","<div......
  • C++ 模板LNK2019报错的问题
    在自定义类的头文件中使用了模板。在模板实例化时,编译器无法找到模板的实现。【法一】在使用了模板类或模板函数的文件中#include与放入了类定义的.h文件同名的.cpp......
  • springmvc中web.xml模板
    myweborg.springframework.web.servlet.DispatcherServlet<init-param><param-name>contextConfigLocation</param-name><param-value>classpat......
  • Java Apache POI 小记(读取Word通过模板创建PPT)
    @目录起因过程确定工具功能拆分读取Word文件通过PPT模板创建PPT并填充内容将PPT转为图片总结起因近期身边的一位朋友来寻求帮助,她在日常工作时,总是需要做一些重复的事情,......
  • 人脸识别/安全帽识别AI智能分析网关微信端告警推送如何配置模板消息?
    智能分析网关设备内置多种AI算法,可对实时视频中的人脸、人体、物体等进行检测、跟踪与抓拍,支持口罩佩戴检测、安全帽佩戴检测、人体检测、区域入侵检测等,可支持拓展多种AI......