QuestPDF

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

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

安装

Install-Package QuestPDF

例子

  • 简单例子

生成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");

  • 模板生成

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

  • 文档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页面总是有三个元素:页眉,页脚,内容。查看一下我们生成的文档

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

接下来我们来填充他的页眉,我们把数据源整理好了之后,就可以调用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");});});});}

最后我们来实现内容,

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);

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

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

  1. C#不要再使用Npoi啦,使用MiniExcel操作Excel文件更快更高效!

    1.简介 MiniExcel简单.高效避免OOM的.NET处理Excel查.写.填充数据工具. 目前主流框架如Npoi 需要将数据全载入到内存方便操作,但这会导致内存消耗问题. MiniExcel 尝 ...

  2. itextsharp c# asp.net 生成 pdf 文件

    一切的开始必须要有2个dll, 可以通过nuget 包xiazai, 关键字是itextsharp. using iTextSharp.text; using iTextSharp.text.pdf; ...

  3. iTextSharp 使用详解 读写PDF

    iTextSharp 使用详解 PDF文件是目前比较流行的电子文档格式,在办公自动化(OA)等软件的开发中,经常要用到该格式,但介绍如何制作PDF格式文件的资料非常少,在网上搜来搜去,都转贴的是同一段 ...

  4. .net 使用 Aspose.Words 进行 Word替换操作

    .net 使用 Aspose.Words 进行 Word替换操作 原文 http://www.cnblogs.com/codealone/archive/2013/04/02/2995224.html ...

  5. c# 使用 itextsharp 实现生成Pdf报表

    由于项目需要,所以学习Itextsharp   此项目需求是   某一角色提交申请,然后从后台查出数据生成pdf报表 打印出来用于查看 以下是代码: string sql = "select ...

  6. OpenCV 4.x 中请别再用HAAR级联检测器检测人脸!有更好更准的方法

    点击我爱计算机视觉标星,更快获取CVML新技术 本文转载自OpenCV学堂. 引言 我写这篇文章是因为我很久以前写过一些文章,用了人脸检测,我当时用的都是HAAR级联检测器,导致最近几个人问我说这个H ...

  7. Aspose.Words操作Word.PDF,让图片和文本垂直居中,水平居中解决方案

    Aspose.Words操作Word.PDF,让图片和文本垂直居中,水平居中解决方案 参考文章: (1)Aspose.Words操作Word.PDF,让图片和文本垂直居中,水平居中解决方案 (2)ht ...

  8. 利用iTextSharp把DataTable导出为PDF和RTF(Rich Text Format)文件

    相信每个业务系统都有报表输出的需要,一般采用第三方报表工具,如水晶报表等等.我们也可以直接采用PDF生成类库类实现,不过代码要写多些. 使用.NET开发的生成PDF文件的类库不少,我之前也介绍过开源代 ...

  9. iTextSharp,将多张图片合并生成PDF文件

    首先添加NuGet引用 /// <summary>/// 根据图片生成PDF/// </summary>/// <param name="sender" ...

最新文章

  1. objdump与readelf
  2. jsp:include page= /路径
  3. MVP介绍以及优化封装
  4. 什么是机器学习:一次权威定义之旅
  5. 网页中自动换行问题〔zz〕
  6. 加仓减仓口诀_做短线必备口诀
  7. Ribbon的权重负载均衡策略
  8. extundelete安装_Linux下高效数据恢复软件extundelete应用实战
  9. 使用windows2008R2自带磁盘管理进行分区
  10. 详解语音识别的技术原理
  11. 1061 判断题 (15 分)—PAT (Basic Level) Practice (中文)
  12. 常见的射频同轴连接器(N型/TNC型/BNC型/SMA型等)
  13. 简单一招能让你的浏览器下载速度提升几十倍,从此弃用IDM等下载器
  14. Electron编译报错:include: could not find: ****StdUtils.nsh“的解决
  15. 使用 SkyEye 模拟 ARM Linux
  16. 工厂制造业ai人工智能应用_人工智能与金融服务业转型的未来
  17. 研发高频软件,工具,网站,体验飞一般的感觉。
  18. windows 防止屏保锁屏脚本工具
  19. html 自适应模板 (webview)
  20. 简单jquery下拉菜单流畅版

热门文章

  1. 《UVM实战卷Ⅰ》学习笔记 第七章 UVM中的寄存器模型(2)
  2. 美军的AI发展计划研究(2)
  3. MySQL标准差和方差函数使用
  4. UnityShader学习——内置时间变量及其应用
  5. 数据结构课程设计-班级考勤管理系统
  6. 毕业设计(论文)排版要求、时间安排、解决方案与建议
  7. TENER: Adapting Transformer Encoder for Named Entity Recognition 论文详解
  8. 小电流选线装置的研制之
  9. js如何精确判断是否是数组?
  10. kettle bat文件运行失败