#yyds干货盘点#愚公系列2023年03月 .NET CORE工具案例-.NET Core使用QuestPDF

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#yyds干货盘点#愚公系列2023年03月 .NET CORE工具案例-.NET Core使用QuestPDF相关的知识,希望对你有一定的参考价值。

前言

QuestPDF是一个用于生成PDF文档的open-source.NET库。

它提供了一个布局引擎,设计时考虑了完整的分页支持。文档由许多简单元素组成(例如边框、背景、图像、文本、填充、表格、网格等),这些元素组合在一起以创建更复杂的结构。这样,作为一名开发人员,您可以理解每个元素的行为,并满怀信心地使用它们。此外,文档及其所有元素都支持分页功能。例如,一个元素可以移动到下一页(如果没有足够的空间),甚至可以像表的行一样在页面之间拆分。

与其他库不同,它不依赖html-to-PDF转换,在许多情况下,这种转换不可靠。相反,它实现了自己的布局引擎,该引擎经过优化以覆盖所有paging-related需求。

github文档地址:https://github.com/QuestPDF/QuestPDF

API文档地址:https://www.questpdf.com/api-reference/index

一、.NET Core使用QuestPDF

1.Nuget安装包

Install-Package QuestPDF

2.官方案例

using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;

// code in your main method
Document.Create(container =>

    container.Page(page =>
    
        page.Size(PageSizes.A4);
        page.Margin(2, Unit.Centimetre);
        page.PageColor(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");

3.发票案例

3.1 定义模型类InvoiceModel

//发票类
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; 

3.2 InvoiceDocumentDataSource数据生成

public static class InvoiceDocumentDataSource

    private static Random Random = new Random();
    
    public static InvoiceModel GetInvoiceDetails()
    
        var items = Enumerable
            .Range(1, 25)
            .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 = Placeholders.Paragraph()
        ;
    

    private static OrderItem GenerateRandomOrderItem()
    
        return new OrderItem
        
            Name = Placeholders.Label(),
            Price = (decimal) Math.Round(Random.NextDouble() * 100, 2),
            Quantity = Random.Next(1, 10)
        ;
    

    private static Address GenerateRandomAddress()
    
        return new Address
        
            CompanyName = Placeholders.Name(),
            Street = Placeholders.Label(),
            City = Placeholders.Label(),
            State = Placeholders.Label(),
            Email = Placeholders.Email(),
            Phone = Placeholders.PhoneNumber() 
        ;
    

3.3 InvoiceDocument 发票文档

using System.Linq;
using QuestPDF.Drawing;
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;

namespace QuestPDF.ExampleInvoice

    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.Margin(50);
                    //页面头
                    page.Header().Element(ComposeHeader);
                    // 页面内容
                    page.Content().Element(ComposeContent);
                    //1 / 2
                    page.Footer().AlignCenter().Text(text =>
                    
                        //当前页数
                        text.CurrentPageNumber();
                        //分割
                        text.Span(" / ");
                        //总页数
                        text.TotalPages();
                    );
                );
        
        //发票头
        void ComposeHeader(IContainer container)
        
            container.Row(row =>
            
                //其实row相当于列,Column相当于行
                row.RelativeItem().Column(Column =>
                
                    Column
                        .Item().Text($"Invoice #Model.InvoiceNumber")
                        .FontSize(20).SemiBold().FontColor(Colors.Blue.Medium);
                    
                    Column.Item().Text(text =>
                    
                        text.Span("Issue date: ").SemiBold();
                        text.Span($"Model.IssueDate:d");
                    );
                    
                    Column.Item().Text(text =>
                    
                        text.Span("Due date: ").SemiBold();
                        text.Span($"Model.DueDate:d");
                    );
                );
                //宽100,高50的图片
                row.ConstantItem(100).Height(50).Placeholder();
            );
        
        //发票体
        void ComposeContent(IContainer container)
        
            //其实row相当于列,Column相当于行
            container.PaddingVertical(40).Column(column => 
            
                column.Spacing(20);
                //交易方信息
                column.Item().Row(row =>
                
                    row.RelativeItem().Component(new AddressComponent("From", Model.SellerAddress));
                    row.ConstantItem(50);
                    row.RelativeItem().Component(new AddressComponent("For", Model.CustomerAddress));
                );
                //表格
                column.Item().Element(ComposeTable);
                //价格汇总
                var totalPrice = Model.Items.Sum(x => x.Price * x.Quantity);
                column.Item().PaddingRight(5).AlignRight().Text($"Grand total: totalPrice$").SemiBold();

                if (!string.IsNullOrWhiteSpace(Model.Comments))
                    column.Item().PaddingTop(25).Element(ComposeComments);
            );
        
        //发票表格
        void ComposeTable(IContainer container)
        
            var headerStyle = TextStyle.Default.SemiBold();
            
            container.Table(table =>
            
                table.ColumnsDefinition(columns =>
                
                    columns.ConstantColumn(25);
                    columns.RelativeColumn(3);
                    columns.RelativeColumn();
                    columns.RelativeColumn();
                    columns.RelativeColumn();
                );
                
                table.Header(header =>
                
                    header.Cell().Text("#");
                    header.Cell().Text("Product").Style(headerStyle);
                    header.Cell().AlignRight().Text("Unit price").Style(headerStyle);
                    header.Cell().AlignRight().Text("Quantity").Style(headerStyle);
                    header.Cell().AlignRight().Text("Total").Style(headerStyle);
                    
                    header.Cell().ColumnSpan(5).PaddingTop(5).BorderBottom(1).BorderColor(Colors.Black);
                );
                
                foreach (var item in Model.Items)
                
                    table.Cell().Element(CellStyle).Text(Model.Items.IndexOf(item) + 1);
                    table.Cell().Element(CellStyle).Text(item.Name);
                    table.Cell().Element(CellStyle).AlignRight().Text($"item.Price$");
                    table.Cell().Element(CellStyle).AlignRight().Text(item.Quantity);
                    table.Cell().Element(CellStyle).AlignRight().Text($"item.Price * item.Quantity$");
                    
                    static IContainer CellStyle(IContainer container) => container.BorderBottom(1).BorderColor(Colors.Grey.Lighten2).PaddingVertical(5);
                
            );
        
        //发票评论
        void ComposeComments(IContainer container)
        
            container.ShowEntire().Background(Colors.Grey.Lighten3).Padding(10).Column(column => 
            
                column.Spacing(5);
                column.Item().Text("Comments").FontSize(14).SemiBold();
                column.Item().Text(Model.Comments);
            );
        
    
    //地址组件
    public class AddressComponent : IComponent
    
        private string Title  get; 
        private Address Address  get; 

        public AddressComponent(string title, Address address)
        
            Title = title;
            Address = address;
        
        
        public void Compose(IContainer container)
        
            container.ShowEntire().Column(column =>
            
                column.Spacing(2);
                //公司方向(销售和客户)
                column.Item().Text(Title).SemiBold();
                //画线
                column.Item().PaddingBottom(5).LineHorizontal(1); 
                //地址信息
                column.Item().Text(Address.CompanyName);
                column.Item().Text(Address.Street);
                column.Item().Text($"Address.City, Address.State");
                column.Item().Text(Address.Email);
                column.Item().Text(Address.Phone);
            );
        
    

3.4 生成发票

class Program

    static void Main(string[] args)
    
        var model = InvoiceDocumentDataSource.GetInvoiceDetails();
        var document = new InvoiceDocument(model);

        // 生成PDF文件并在默认查看器中显示
        GenerateDocumentAndShow(document);
        //或者nuget安装QuestPDF Previewer预览器并尝试文档的设计
        //在每次代码更改后,无需重新编译即可实时执行
        //document.ShowInPreviewer();
    

    static void GenerateDocumentAndShow(InvoiceDocument document)
    
        const string filePath = "invoice.pdf";
        
        document.GeneratePdf(filePath);
        //执行进程查看发票
        var process = new Process
        
            StartInfo = new ProcessStartInfo(filePath)
            
                UseShellExecute = true
            
        ;

        process.Start();
    

以上是关于#yyds干货盘点#愚公系列2023年03月 .NET CORE工具案例-.NET Core使用QuestPDF的主要内容,如果未能解决你的问题,请参考以下文章

#yyds干货盘点#愚公系列2023年02月 微信小程序-获取WIFI信息

#yyds干货盘点#愚公系列2023年02月 微信小程序-Page页面扩展

#yyds干货盘点#愚公系列2023年02月 .NET/C#知识点-程序运行计时的总结

#yyds干货盘点#愚公系列2023年02月 微信小程序-电商项目-商品详情页面的标题及价格功能实现

#yyds干货盘点#愚公系列2023年02月 .NET/C#知识点-区块链概念和实现

#yyds干货盘点#愚公系列2023年02月 .NET/C#知识点-List转成字符串的总结