当前位置:网站首页>用 QuestPDF操作生成PDF更快更高效!
用 QuestPDF操作生成PDF更快更高效!
2022-07-26 19:18:00 【biyusr】

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

当然还有很多好玩的功能,今天就给大家讲个概念,让大家对这个东西有个印象,后面我会继续输出该库的相关功能。如果你们对该库感兴趣,可以持续关注我!微信公众号【黑哥聊dotNet】
边栏推荐
猜你喜欢
![[Android] the black technology behind kotlin's rapid compilation. Learn about it~](/img/d6/ae107f75c158e97913e6d75eac5b84.png)
[Android] the black technology behind kotlin's rapid compilation. Learn about it~

MySQL 子查询使用方式
![[internship experience] exception handling and URL result response data processing](/img/ed/05622fad0d3d8dcf17ce7069340669.jpg)
[internship experience] exception handling and URL result response data processing

win11 edge怎么卸载?win11 edge浏览器彻底卸载的方法教程

2022年下半年(软考高级)信息系统项目管理师报名条件

Training embedded representation of large categories using triple loss and twin neural networks

Leetcode daily practice - 26. Delete duplicates in an ordered array

猎聘问卷星,成为微信「寄生虫」

浅析接口测试

计算机组成原理常见面试题目总结,含答案
随机推荐
What is a knowledge management system? You need to know this
金仓数据库 KingbaseES SQL 语言参考手册 (15. SQL语句:CREATE MATERIALIZED VIEW 到 CREATE SCHEMA)
Kingbasees SQL language reference manual of Jincang database (12. SQL statement: alter language to alter subscription)
Student‘s t分布
数据库笔记(来自老社)
2022年下半年(软考高级)信息系统项目管理师报名条件
Leetcode daily practice - 189. Rotation array
Zhongtian steel uses tdengine in GPS and AIS scheduling
MySQL subquery usage
Svn - detailed documentation
[PHP] MySQL native PHP operation - Tianlong eight steps
2022 极术通讯-安谋科技开启商业化新篇章
DOM case: 10 second countdown - write jump page related knowledge
Kingbasees SQL language reference manual of Jincang database (20. SQL statements: merge to values)
three.js 给地球加标签和弹窗
Linux regularly backs up the database and deletes the data n days ago
Collection of original IOS interview questions
中天钢铁在 GPS、 AIS 调度中使用 TDengine
一年卖7亿,德州扒鸡赶考IPO
Analysis of interface testing