C#/.Net 不要再使用Aspose和iTextSharp啦!QuestPDF操作生成PDF更快更高效!

49063d6036483099fd2dfc184668b38c.png

QuestPDF

QuestPDF是一个开源的工具库,可以在.NET或者.Net Core中生成pdf文档

它提供了一个布局引擎,设计时考虑到了完整的分页支持以及灵活性要求!比市面上常见的Aspose和iTextSharp好用太多了!GitHub地址

安装

Install-Package QuestPDF

24af0030bac7143c561d178dcbc24543.png

例子

  • 简单例子

生成Pdf文档一共分为三部分,Header(页眉),Content(内容),Footer(页脚)

Document.Create(container =>
{container.Page(page =>{page.Size(PageSizes.A4);page.Margin(2, Unit.Centimetre);page.Background(Colors.White);page.DefaultTextStyle(x => x.FontSize(20));page.Header().Text("Hello PDF!").SemiBold().FontSize(36).FontColor(Colors.Blue.Medium);page.Content().PaddingVertical(1, Unit.Centimetre).Column(x =>{x.Spacing(20);x.Item().Text(Placeholders.LoremIpsum());x.Item().Image(Placeholders.Image(200, 100));});page.Footer().AlignCenter().Text(x =>{x.Span("Page ");x.CurrentPageNumber();});});
})
.GeneratePdf("hello.pdf");

2e0fa8787516b8dafe0c60d7cbc3a72c.png

  • 模板生成

使用模板生成一共设计三个应用层的工作:

  • 文档Model(一组描述 PDF 文档内容的类)

  • 数据源(将域实体映射到文档模型的层)

  • 模板(描述如何可视化信息并将其转换为 PDF 文件的表示层)

比如我们设计一个基本的发票信息 要设计一个购物清单,一个卖家买家的地址,以及发票编号等等 我们设计这样的3个Model类

public class InvoiceModel{public int InvoiceNumber { get; set; }public DateTime IssueDate { get; set; }public DateTime DueDate { get; set; }public Address SellerAddress { get; set; }public Address CustomerAddress { get; set; }public List<OrderItem> Items { get; set; }public string Comments { get; set; }}public class OrderItem{public string Name { get; set; }public decimal Price { get; set; }public int Quantity { get; set; }}public class Address{public string CompanyName { get; set; }public string Street { get; set; }public string City { get; set; }public string State { get; set; }public object Email { get; set; }public string Phone { get; set; }}

Model定义好了之后我们就定义一些假数据来填充pdf

public static class InvoiceDocumentDataSource{private static Random Random = new Random();public static InvoiceModel GetInvoiceDetails(){var items = Enumerable.Range(1, 8).Select(i => GenerateRandomOrderItem()).ToList();return new InvoiceModel{InvoiceNumber = Random.Next(1_000, 10_000),IssueDate = DateTime.Now,DueDate = DateTime.Now + TimeSpan.FromDays(14),SellerAddress = GenerateRandomAddress(),CustomerAddress = GenerateRandomAddress(),Items = items,Comments ="测试备注"};}private static OrderItem GenerateRandomOrderItem(){return new OrderItem{Name = "商品",Price = (decimal)Math.Round(Random.NextDouble() * 100, 2),Quantity = Random.Next(1, 10)};}private static Address GenerateRandomAddress(){return new Address{CompanyName = "测试商店",Street = "测试街道",City = "测试城市",State = "测试状态",Email = "测试邮件",Phone = "测试电话"};}}

然后搭建我们的模板脚手架 我们要使用模板脚手架,就要定义一个实现IDocument接口的新类开始。该接口包含两个方法

  • DocumentMetadata GetMetadata();

  • void Compose(IDocumentContainer container);

第一个是模板文档的一些基础信息 第二个是模板的容器 基于这些原则我们设计一个模板层类

public class InvoiceDocument : IDocument{public InvoiceModel Model { get; }public InvoiceDocument(InvoiceModel model){Model = model;}public DocumentMetadata GetMetadata() => DocumentMetadata.Default;public void Compose(IDocumentContainer container){container.Page(page =>{page.PageColor(Colors.Red.Lighten1);page.Size(PageSizes.A4);page.Margin(10);//外边距page.Header().Height(100).Background(Colors.LightBlue.Lighten1);page.Content().Background(Colors.Grey.Lighten3);page.Footer().Height(50).Background(Colors.Grey.Lighten1);});}
}

pdf的page页面总是有三个元素:页眉,页脚,内容。查看一下我们生成的文档

cfff5346e2f0342593191ffd435e59d7.png

到目前为止,我们已经搭建了一个非常简单的页面,其中每个部分都有不同的颜色或大小

接下来我们来填充他的页眉,我们把数据源整理好了之后,就可以调用Element方法填充

public void Compose(IDocumentContainer container){container.Page(page =>{page.PageColor(Colors.Red.Lighten1);page.Size(PageSizes.A4);page.Margin(10);//外边距page.Header().Height(100).Background(Colors.LightBlue.Lighten1).Element(ComposeHeader);page.Content().Background(Colors.Grey.Lighten3);page.Footer().Height(50).Background(Colors.Grey.Lighten1);});}void ComposeHeader(IContainer container){var titleStyle = TextStyle.Default.FontSize(20).SemiBold().FontColor(Colors.Blue.Medium);container.Row(row =>{row.RelativeItem().Column(column =>{column.Item().Text($"发票 #{Model.InvoiceNumber}").FontFamily("simhei").Style(titleStyle);column.Item().Text(text =>{text.Span("发行日期: ").SemiBold().FontFamily("simhei");text.Span($"{Model.IssueDate:d}").FontFamily("simhei");});column.Item().Text(text =>{text.Span("支付日期: ").FontFamily("simhei").SemiBold();text.Span($"{Model.DueDate:d}").FontFamily("simhei");});});});}

4d303bf11b5737537c6dd04e87ba7bc1.png

最后我们来实现内容,

public void Compose(IDocumentContainer container){container.Page(page =>{page.PageColor(Colors.Red.Lighten1);page.Size(PageSizes.A4);page.Margin(10);//外边距page.Header().Height(100).Background(Colors.LightBlue.Lighten1).Element(ComposeHeader);page.Content().Background(Colors.Grey.Lighten3).Element(ComposeContent);page.Footer().Height(50).Background(Colors.Grey.Lighten1);});}void ComposeHeader(IContainer container){var titleStyle = TextStyle.Default.FontSize(20).SemiBold().FontColor(Colors.Blue.Medium);container.Row(row =>{row.RelativeItem().Column(column =>{column.Item().Text($"发票 #{Model.InvoiceNumber}").FontFamily("simhei").Style(titleStyle);column.Item().Text(text =>{text.Span("发行日期: ").SemiBold().FontFamily("simhei");text.Span($"{Model.IssueDate:d}").FontFamily("simhei");});column.Item().Text(text =>{text.Span("支付日期: ").FontFamily("simhei").SemiBold();text.Span($"{Model.DueDate:d}").FontFamily("simhei");});});});}void ComposeContent(IContainer container){container.Table(table =>{// step 1table.ColumnsDefinition(columns =>{columns.ConstantColumn(25);columns.RelativeColumn(3);columns.RelativeColumn();columns.RelativeColumn();columns.RelativeColumn();});// step 2table.Header(header =>{header.Cell().Text("#").FontFamily("simhei");header.Cell().Text("商品").FontFamily("simhei");header.Cell().AlignRight().Text("价格").FontFamily("simhei");header.Cell().AlignRight().Text("数量").FontFamily("simhei");header.Cell().AlignRight().Text("总价").FontFamily("simhei");header.Cell().ColumnSpan(5).PaddingVertical(5).BorderBottom(1).BorderColor(Colors.Black);});// step 3foreach (var item in Model.Items){table.Cell().Element(CellStyle).Text(Model.Items.IndexOf(item) + 1).FontFamily("simhei");table.Cell().Element(CellStyle).Text(item.Name).FontFamily("simhei");table.Cell().Element(CellStyle).AlignRight().Text($"{item.Price}$").FontFamily("simhei");table.Cell().Element(CellStyle).AlignRight().Text(item.Quantity).FontFamily("simhei");table.Cell().Element(CellStyle).AlignRight().Text($"{item.Price * item.Quantity}$").FontFamily("simhei");static IContainer CellStyle(IContainer container){return container.BorderBottom(1).BorderColor(Colors.Grey.Lighten2).PaddingVertical(5);}}});}

在这些准备工作做完了之后我们就可以生成Pdf文档了

var filePath = "invoice.pdf";var model = InvoiceDocumentDataSource.GetInvoiceDetails();var document = new InvoiceDocument(model);document.GeneratePdf(filePath);

7f143e68b9eb8a2d83001e87ee095aef.png

当然还有很多好玩的功能,今天就给大家讲个概念,让大家对这个东西有个印象,后面我会继续输出该库的相关功能。如果你们对该库感兴趣,可以持续关注我!微信公众号【黑哥聊dotNet】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/288653.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#创建桌面快捷方式

1、添加引用Windows Script Host Object Model,并引用命名空间using IWshRuntimeLibrary; 2、代码 using System; using IWshRuntimeLibrary; using System.Windows.Forms;namespace WindowsFormsApplication1 {public partial class Form1 : Form{public Form1(){InitializeC…

Java报表工具FineReport导出EXCEL的四种API

在实际的应用中会经常需要将数据导出成excel&#xff0c;导出的方式除原样导出还有分页导出、分页分sheet导出和大数据量导出。对于excel 2003版&#xff0c;由于限制了每个sheet的最大行数和列数&#xff0c;大数据量导出时会默认时分多个sheet&#xff0c;而excel2007不会出现…

sql in 用法(mysql)

我们先看一个如下数据库表&#xff1a; 我们如果想查询这张表里面age为11和1的人该怎么办呢&#xff1f; 那么我们的 in 操作符就起作用了&#xff1a; SELECT * FROM table1 WHERE age1 IN(11,1); 查询来自表哥table1的数据&#xff0c;条件为age1 在(11,1)这两个数之中…

matlab的循环语句裁图,[MATLAB图像处理] 多幅图片处理的循环语句

多幅图片处理的循环语句 小弟毕业设计关于视频去雾处理&#xff0c;将视频截取为图片后对每张图片进行处理&#xff0c;其中需要用到循环语句来减少工作量&#xff0c;但自己对循环语句不怎么会&#xff0c;希望哪位大大能够给予帮助&#xff0c;谢谢了程序如下block_size 15;…

开源社·读书播客第一期:《大教堂与集市》

点击蓝字&#xff0c;关注我们&#xff5c;作者&#xff1a;许银&#xff5c;编辑&#xff1a;Corrie&#xff5c;设计&#xff1a;朱亿钦Hi&#xff0c;各位开源爱好者&#xff0c;在世界读书日这个特殊的日子里&#xff0c;我们开源社踩着潮流来了&#xff0c;近一年来&#…

LeetCode:Count Primes

Problem: Description: Count the number of prime numbers less than a non-negative number, n. Credits:Special thanks to mithmatt for adding this problem and creating all test cases. Solution:采用的为埃拉托斯特尼筛法 算法描述&#xff1a;&#xff08;来自百度…

华为交换机查看端口流量_华为交换机限速及流量统计配置

配置交换机限速时&#xff0c;cir和cbs的关系是什么配置交换机限速时&#xff0c;cir和cbs的关系如下&#xff1a;cbs要大于报文的最大长度。在连续流量的情况下对于cbs没有特殊的要求&#xff0c;保证平均速率是cir的速率。在突发流量需要保证的情况下&#xff0c;如果cbs换算…

利用Matlab拟合时序植被生长季曲线,并求解物候参数

研究表明,一元六次曲线比一元二次曲线更好地模拟植被生长季的整个生长周期,表征植被的生长特性。matlab软件功能强大,在遥感模型研究方面有很大的优势特点,对数学模型模拟轻而易举,也可直接对栅格数据进行运算。因此本文采用matlab软件,采用一元6次曲线来拟合植被生长季曲…

sql between...and 用法(mysql)

首先我们看如下数据库表&#xff1a; 如果我们想查询如上表中的age1的值在0到5的数据该如何查询&#xff1f; 那么在这里我们用到我们的sql操作符between…adn。 SELECT * FROM table1 WHERE age1 BETWEEN 0 AND 5 其中between后面的0 and 5 意思就是 查询寻数据&#xf…

如何在JavaScript中运行.NET Core代码

前言在.NET Core中运行JavaScript代码&#xff0c;目前已经有很多实现方案。但是&#xff0c;如果你希望在纯JavaScript环境中运行.NET Core代码呢&#xff1f;那么&#xff0c;DotNetJS可能对你有所帮助。DotNetJSDotNetJS可以将C#项目编译为与任何环境兼容的单文件JavaScript…

sql 之as(Aliases)别名(mysql)

使用别名主要原因是因为如果在很多表的时候&#xff0c;我们的表名可能会混淆&#xff0c;导致语句不清晰&#xff0c;那么我们使用别名就可以让我们操作数据库表的时候更加清晰明了&#xff0c;那么我们假设有如下表&#xff1a; 那么我们查找我们age1的值为11的数据&#…

sqlserver建表语句_重新认识MySQL中的COUNT语句

在数据库的增删改查操作中&#xff0c;使用最频繁的就是查询操作。而在所有查询操作中&#xff0c;统计数量操作更是经常被用到。关于数据库中行数统计&#xff0c;无论是MySQL还是Oracle亦或者是SqlServer&#xff0c;都有一个函数可以使用&#xff0c;那就是COUNT。而对于COU…

sql INNER JOIN 取得两个表中存在连接匹配关系的记录(mysql)

首先&#xff1a;JOIN 通常与 ON 关键字搭配使用 其次我们来看我们的两个表格&#xff1a; table1: table2: 在这里&#xff0c;INNER JOIN&#xff08;内连接,或等值连接&#xff09;&#xff1a;取得两个表中存在连接匹配关系的记录。 例如我要取到table1和table2之…

【Linux】IPC-消息队列

问题 消息队列id 和键值KEY区别&#xff1f; 首先要注意一个概念&#xff1a;IPC结构都是内核的结构。也就是说IPC结构由内核维护&#xff0c;对于每个进程都是公共的&#xff0c;不属于某个特定进程。只有这样&#xff0c;IPC结构才能支持它们“进程间通信”的功能。 有两个东…

Blazor University (14)渲染树

原文链接&#xff1a;https://blazor-university.com/components/render-trees/渲染树当浏览器呈现内容时&#xff0c;它不仅绘制 HTML 中定义的元素&#xff0c;还必须根据页面大小&#xff08;元素流&#xff09;计算绘制它们的位置。例如&#xff0c;以下 Bootstrap HTML 将…

思科加强生成树性能的属性(Portfast /Uplinkfast/BackboneFast)与RSTP的关系

思科加强生成树性能的属性&#xff08;Portfast/Uplinkfast/BackboneFast&#xff09;与RSTP的关系本文截自于博主CCNP交换技术稿件内容4.2.6思科加强生成树性能的属性&#xff08;Portfast/Uplinkfast/BackboneFast&#xff09;与RSTP的关系首先说明一下&#xff0c;为什么笔者…

sql LEFT JOIN RIGHT JOIN(左连接)(mysql)

我们首先来看我们的两个表&#xff1a; table1: table2: 在这里&#xff0c;LEFT JOIN&#xff08;内连接,或等值连接&#xff09;&#xff1a;取得左表&#xff08;table1&#xff09;完全记录&#xff0c;即是右表&#xff08;table2&#xff09;并无对应匹配记录。 …

php的_auto,AutoPHPCheck下载

AutoPHPCheck官方版是一款相当优秀的php开发人员专用PHP验证工具&#xff0c;AutoPHPCheck官方版功能全面&#xff0c;便捷好用&#xff0c;支持执行快速验证来帮助您确保代码的安全性&#xff0c;并且软件还附带了一个基本的语法检查器&#xff0c;可以查找并帮助您处理错误。…

【ArcGIS遇上Python】Python实现点转栅格(PointToRaster)

在ArcGIS中提供了点转栅格(PointToRaster)的工具,如下所示: 参数说明: (1)file:点图层(.shp) (2)data:值字段 (3)outFile:转换后的栅格图层 (4)9660.848118:空间分辨率 python批处理代码: import arcpy arcpy.gp.overwriteOutput=1 arcpy.env.workspace=&…

ASP.NET Core认证授权方案

前言在前面我讲过基于token的权限认证&#xff0c;然后前几天有小伙伴私信我&#xff0c;怎么做一个身份认证也就是授权。在Asp.net Core常见的授权方式有:基于角色的授权&#xff0c;有基于声明的授权&#xff0c;有基于策略的授权&#xff0c; 这三种授权我就不做过多介绍了,…