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

1514366c1497e80fa6b677dc8c441a07.png

QuestPDF

QuestPDF是一個開源的工具庫,可以在.NET或者.Net Core中生成pdf文檔

它提供了一個布局引擎,設計時考慮到了完整的分頁支持以及靈活性要求!比市面上常見的Aspose和iTextSharp好用太多了!GitHub地址

安裝

Install-Package QuestPDF

657b899653e7ae63c49c7ad0a9da78be.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");

29d87342efbb5f91f6675212ce6bda29.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頁面總是有三個元素:頁眉,頁腳,內容。查看一下我們生成的文檔

4a5724285c86a700be17fe8d39e003d8.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");});});});}

1c2f13b2514bb7720ddab5585505e0d6.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);

326542a9d0362c2e7fe881830cebd4fc.png

當然還有很多好玩的功能,今天就給大家講個概念,讓大家對這個東西有個印象,后面我會繼續輸出該庫的相關功能。如果你們對該庫感興趣,可以持續關注我!微信公眾號【黑哥聊dotNet】

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/284410.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/284410.shtml
英文地址,請注明出處:http://en.pswp.cn/news/284410.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ASP.NET vs MVC vs WebForms

許多ASP.NET開發人員開始接觸MVC認為MVC與ASP.NET完全沒有關系&#xff0c;是一個全新的Web開發&#xff0c;事實上ASP.NET是創建WEB應用的框架而MVC是能夠用更好的方法來組織并管理代碼的一種更高級架構體系&#xff0c;所以可以稱之為ASP.NET MVC。 我們可將原來的ASP.NET稱為…

產品經理有哪些類型?

不知道大家是如何給產品經理這個職業進行分類&#xff0c; 按負責的產品&#xff1f;按等級&#xff1f;按工作年限&#xff1f;按工作方向等&#xff1f; 一、按工作內容分 1. 功能設計產品經理 最常見的了&#xff0c;負責的工作就是設計出功能來。從 APP 的界面&#xff0…

在Blazor 中自定義權限驗證

Blazor是什么Blazor 是微軟在 .NET 里推出的一個 WEB 客戶端 UI 交互的框架&#xff0c;使用 Blazor 你可以代替 JavaScript 來實現自己的頁面交互邏輯&#xff0c;可以很大程度上進行 C# 代碼的復用&#xff0c;Blazor 對于 .NET 開發人員來說是一個不錯的選擇。需求背景其實我…

看出每個應用程序最高可用內存是多少

int maxMemory (int) (Runtime.getRuntime().maxMemory() / 1024); Log.d("TAG", "Max memory is " maxMemory "KB"); 轉載于:https://www.cnblogs.com/coderwjq/p/6501639.html

中文分詞之HMM模型詳解

文章轉載自: http://yanyiwu.com/work/2014/04/07/hmm-segment-xiangjie.html HMM(Hidden Markov Model): 隱式馬爾科夫模型。 HMM模型可以應用在很多領域&#xff0c;所以它的模型參數描述一般都比較抽象&#xff0c;以下篇幅針對HMM的模型參數介紹直接使用它在中文分詞中的實…

【ArcGIS微課1000例】0035:地圖面狀符號設計教程

地圖符號是表示地圖內容的基本手段,它由形狀不同、大小不一、色彩有別的圖形和文字組成。 地圖符號是地圖的語言,是一種圖形語言。它與文字語言相比較,最大的特點是形象直觀,一目了然。 本文講解ArcGIS中面狀符號設計方法。 文章目錄 一、新建符號樣式二、面狀符號設計1. 斜…

MySQL奪命15問,你能堅持到第幾問?

前言 MySQL在面試中經常被問到&#xff0c;本文總結了面試中的經典問題。 1. 數據庫三大范式是什么&#xff1f; 第一范式&#xff1a;每個列都不可以再拆分。 第二范式&#xff1a;在第一范式的基礎上&#xff0c;非主鍵列完全依賴于主鍵&#xff0c;而不能是依賴于主鍵的一部…

ios元素定位

原文地址http://www.cnblogs.com/meitian/p/7373460.html 第一種&#xff1a;通過Appium1.6的Inspector來查看 具體安裝方式前面的隨筆已經介紹了&#xff1a;http://www.cnblogs.com/meitian/p/7360017.html可以通過定位找到元素xpath或name個人不推薦用這個方法&#xff0c;實…

分治法——循環賽日程表

1、問題描述&#xff1a;有n2^k個遠動員選手&#xff0c;設計比賽日程表實現&#xff1a;&#xff08;1&#xff09;每個選手必須與n-1個選手比賽&#xff08;2&#xff09;每個選手一天只比賽一場&#xff08;3&#xff09;比賽共進行n-1天輸入&#xff1a;n人輸出&#xff1a…

使用 LSM-Tree 思想基于.NET 6.0 C# 寫個 KV 數據庫(案例版)

文章有點長&#xff0c;耐心看完應該可以懂實際原理到底是啥子。這是一個KV數據庫的C#實現&#xff0c;目前用.NET 6.0實現的&#xff0c;目前算是屬于雛形&#xff0c;骨架都已經完備&#xff0c;畢竟剛完工不到一星期。當然&#xff0c;這個其實也算是NoSQL的雛形&#xff0c…

35.使用攔截器實現權限驗證

轉自&#xff1a;https://wenku.baidu.com/view/84fa86ae360cba1aa911da02.html 為了說明此問題&#xff0c;我們建立struts2auth項目&#xff0c;流程圖如下&#xff1a; 簡短說明&#xff1a;當我們訪問main.jsp頁面&#xff0c;并試圖通過此頁面中的鏈接地址&#xff1a;not…

如何保證緩存和數據庫的一致性?

1. 問題分析 2. Cache-Aside 2.1 讀緩存 2.2 寫緩存 2.3 延遲雙刪 2.4 如何確保原子性 3. Read-Through/Write-Through 3.1 Read-Through 3.2 Write-Through 4. Write Behind 很多小伙伴在面試的時候&#xff0c;應該都遇到過類似的問題&#xff0c;如何確保緩存和數據庫…

Pressed狀態和clickable,duplicateParentState的關系

做Android開發的人都用過Selector,可以方便的實現View在不同狀態下的背景。不過&#xff0c;相信大部分開發者遇到過和我一樣的問題&#xff0c;本文會從源碼角度&#xff0c;解釋這些問題。 首先&#xff0c;這里簡單描述一下&#xff0c;我遇到的問題&#xff1a; 界面上有個…

Hbase筆記4 java操作Hbase

暫無轉載于:https://www.cnblogs.com/mrxiaohe/p/6512481.html

【招聘(南京)】 慧咨環球南京研發中心 .NET和Blazor 前端

主要的亮點快速增長的、產品導向型的全球性科技公司設計和開發市場領先的軟件解決方案WLB — 工作生活相平衡澳洲排名前五的軟件公司混合辦公 — 3天在家辦公&#xff0c;2天在辦公室辦公在C#和.NET開發&#xff0c;企業級系統研發&#xff0c;軟件工程方面有長期的優秀實踐和技…

用Python+Django在Eclipse環境下開發web網站【轉】

一、創建一個項目如果這是你第一次使用Django&#xff0c;那么你必須進行一些初始設置。也就是通過自動生成代碼來建立一個Django項目--一個Django項目的設置集&#xff0c;包含了數據庫配置、Django詳細選項設置和應用 特性配置&#xff0c;具體操作步驟如下所示。 1.新建Djan…

[轉]數據結構KMP算法配圖詳解(超詳細)

KMP算法配圖詳解 前言 KMP算法是我們數據結構串中最難也是最重要的算法。難是因為KMP算法的代碼很優美簡潔干練&#xff0c;但里面包含著非常深的思維。真正理解代碼的人可以說對KMP算法的了解已經相當深入了。而且這個算法的不少東西的確不容易講懂&#xff0c;很多正規的書本…

BGP-MED-2

BGP-MED-2如圖&#xff1a;當AS100去往AS300的60、10的網絡時&#xff0c;60走R3&#xff0c;10走R1!使用MED屬性影響選路&#xff01; R2的配置 bgp 200peer 1.1.1.1 as-number 100 peer 1.1.1.1 ebgp-max-hop 255 peer 1.1.1.1 connect-interface LoopBack0peer 4.4.4.4 as-n…

WPF 實現 Gitee 氣泡菜單(一)

WPF 實現 Gitee 氣泡菜單&#xff08;一&#xff09;氣泡菜單&#xff08;一&#xff09;作者&#xff1a;WPFDevelopersOrg原文鏈接&#xff1a; https://github.com/WPFDevelopersOrg/WPFDevelopers框架使用大于等于.NET40&#xff1b;Visual Studio 2022;項目使用 MIT 開…

[轉]LVS負載均衡(LVS簡介、三種工作模式、十種調度算法)

一、LVS簡介 LVS&#xff08;Linux Virtual Server&#xff09;即Linux虛擬服務器&#xff0c;是由章文嵩博士主導的開源負載均衡項目&#xff0c;目前LVS已經被集成到Linux內核模塊中。該項目在Linux內核中實現了基于IP的數據請求負載均衡調度方案&#xff0c;其體系結構如圖1…