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…

linux shell之IFS分割字符串

1 问题 我们有段字符串data"chenyu:chenzixuan:chenzi",我们需要通过&#xff1a;分割&#xff0c;我们可以采用IFS 我们可以采用下面的模板 oldIFS$IFSIFS":"for item in $data; do******* doneIFS$oldIFS2 代码实现 #/bin/bashdata"chenyu, che…

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…

轻松搞定各版本IE兼容问题,IE6,IE7,IE8,IE9,IE10,IE11

轻松搞定各版本IE兼容问题,IE6,IE7,IE8,IE9,IE10,IE11 在网站开发中不免因为各种兼容问题苦恼&#xff0c;针对兼容问题&#xff0c;其实IE给出了解决方案,Google也给出了解决方案,百度也应用了这种方案去解决IE的兼容问题。解决这种兼容问题只需要一行代码就可以了&#xff0c…

linux shell之通过标识测试文件系统属性

1 通过标识测试文件系统属性 [ -f $file_var ] :如果给定的变量包含正常的文件路径或文件名,则返回真。 [ -x $var ] :如果给定的变量包含的文件可执行,则返回真。 [ -d $var ] :如果给定的变量包含的是目录,则返回真。 [ -e $var ] :如果给定的变量包含的文件存在,则返回真。…

python中变量类型在程序中可以改变_详细解析Python当中的数据类型和变量

数据类型计算机顾名思义就是可以做数学计算的机器&#xff0c;因此&#xff0c;计算机程序理所当然地可以处理各种数值。但是&#xff0c;计算机能处理的远不止数值&#xff0c;还可以处理文本、图形、音频、视频、网页等各种各样的数据&#xff0c;不同的数据&#xff0c;需要…

php输出二维数组中指定内容,HP将MYSQL内容读到二维数组并按指定列输出

&#xff1c;?$host "localhost"; //主机名$user "root"; //mysql用户名$password ""; //mysql密码$database "doc"; //mysql数据库名$tables "mclass"; //表名$connmysql_connect("$host",&…

利用Excel VBA批量计算长时间序列植被物候动态阈值(逐像元)

本文演示利用Excel VBA编程实现多期栅格数据,逐像元计算物候参数:生长季始期(SOS)、生长季末期(EOS)和生长季长度(LOS),计算过程速度快! 说明: (1)利用Raster to Point工具将栅格数据转换为点图层,结果为38998个点,由于每年有24个数据(半月合成),所以得到的…

linux shell之字符串的比较

1 字符串常用的比较 字符串相等 [[ $str1 $str2 ]] 字符串不相等 [[ $str1 ! $str2 ]] 字符串大小比较 [[ $str1 > $str2 ]] 字符串等于空 [[ -z $str2 ]] 字符串不等于空 [[ -n $str2 ]] 用test代替[] if test $str1 $str2 2 测试代码 #/bin/bashstr1&quo…

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

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

表联接

表1&#xff1a;teacher------------| id | name |------------| 1 | 刘德华 || 2 | 张学友 || 4 | 黎明 |------------表2&#xff1a;student------------------| id | name | tea_id |------------------| 1 | 张三 | 1 || 2 | 李四 | 1 || 3 | 王五 | …

sql 之as(Aliases)别名(mysql)

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

C语言发展史(The development of the C language)-BCPL、B与C【转】

The Development of the C Language*Dennis M. RitchieBell Labs/Lucent TechnologiesMurray Hill, NJ 07974 USA 概要在1970s早期&#xff0c;C编程语言是作为新生的Unix操作系统的系统实现语言而设计的。衍生于无类型(typeless)语言BCPL&#xff0c;它进化出了一个类型结构【…