用 QuestPDF操作生成PDF更快更高效!

网友投稿 1368 2022-10-12

用 QuestPDF操作生成PDF更快更高效!

用 QuestPDF操作生成PDF更快更高效!

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 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 1 table.ColumnsDefinition(columns => { columns.ConstantColumn(25); columns.RelativeColumn(3); columns.RelativeColumn(); columns.RelativeColumn(); columns.RelativeColumn(); }); // step 2 table.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 3 foreach (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);

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:一个小型的CLI实用程序,可以快速生成HTML5样板
下一篇:calendarize 一个很小的(204B)实用程序,用于生成日历视图(calendarized 中文)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~