Foreword
This article will focus on the use of iTextSharp and some pitfalls that are easy to step on. By the way, it will introduce the simple, fast and efficient method of converting json to DataTable and the method of online instant download of binary stream conversion files. After testing, it only takes 1 second to generate a 40-page pdf, and the size does not exceed 200k. The performance and compression ratio are relatively good.
Recently, I received a request to export the front-end table data in the form of PDF. Plugins used:
- Newtonsoft.Json
- iTextSharp
The above plug-ins can be downloaded and referenced in nuget
1. json to DataTable
The front-end table is as follows:
The front-end json data structure is as follows:
Description: Hearder is an array, which contains the parameters of each column, such as column width, whether to hide columns (hidden columns are not exported), etc.; DataList is an array, which stores table data; Title stores the name of the table
1. Define the receiving class
First introduce Newtonsoft.Json, the purpose is to convert the json data from the front end into DataTable.
This article uses DeserializeObject
, which is to deserialize JSON into an object, where T is the type of object to be deserialized, and the parameter str is the JSON to be deserialized string.
After understanding the above methods, we first define the object type JsonObj of T according to the above Json format, the code is as follows:
class JsonObj {<!-- --> public DataTable Header {<!-- --> get; set; } public DataTable DataList {<!-- --> get; set; } public string Title {<!-- --> get; set; } public string Code {<!-- --> get; set; } }
2. Convert json
Then use the JsonConvert.DeserializeObject
method to convert, the code is as follows:
JsonObj jsonObj = JsonConvert. DeserializeObject<JsonObj>(jsonText);
3. Complete code
using System. Data; using Newtonsoft.Json; using SIE.Common.Helper.Tools; using Newtonsoft.Json.Linq; namespace SIE.Common.Web.Helper.File { ////// File export--Word, Pdf /// public class FileExport { ////// json data processing /// /// public static string JsonToDataTable(string jsonText) { JsonObj jsonObj = JsonConvert. DeserializeObject<JsonObj>(jsonText); DataTable headerDt = jsonObj.Header; DataTable dataDt = jsonObj. DataList; string title = jsonObj.Title; //Call the method ExportPDF in the second section return ConvertPdf. ExportPDF(headerDt, dataDt, title); } class JsonObj { public DataTable Header { get; set; } public DataTable DataList { get; set; } public string Title { get; set; } } } }
2. DataTable to PDF
In this step, I used iTextSharp. This plug-in corresponds to the Java version of iText, which is open source and free. In fact, in the process of my actual measurement, iTextSharp has powerful PDF operation capabilities, and is also capable of some complex typesetting. Its typesetting statements are similar to CSS typesetting. I use iTextSharp version 5.5. A few things to note are:
1. PDF header and footer:
Most pdf files have headers and footers. The pdf generated by iTextSharp has no headers and footers by default. We can rewrite PdfPageEventHelper
to customize the settings. After rewriting OnStartPage
method sets the header, rewrites the OnEndPage method to set the footer, the code is as follows:
/// <summary> /// Inherit PdfPageEventHelper, rewrite header and footer /// </summary> public class ItextPdfHeaderFooter : PdfPageEventHelper {<!-- --> PdfContentByte cb; PdfTemplate template; // Chinese font BaseFont bf = BaseFont.CreateFont(@"C:\Windows\Fonts\simsun.ttc,0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); // Print Time DateTime PrintTime = DateTime. Now; float fontSize = 10; //font size float leftMargins = 14;//left margin float rightMargins = 14;//right margin float bottomMargins = 12;//bottom margin float topMargins = 12;//top margin #region header basic properties private string _Title; public string Title {<!-- --> get {<!-- --> return _Title; } set {<!-- --> _Title = value; } } public PdfPTable_Table; public PdfPTable Table {<!-- --> get {<!-- --> return _Table; } set {<!-- --> _Table=value; } } private string _HeaderLeft; public string HeaderLeft {<!-- --> get {<!-- --> return _HeaderLeft; } set {<!-- --> _HeaderLeft = value; } } private string _HeaderRight; public string HeaderRight {<!-- --> get {<!-- --> return _HeaderRight; } set {<!-- --> _HeaderRight = value; } } #endregion // Override the onOpenDocument method public override void OnOpenDocument(PdfWriter writer, Document document) {<!-- --> try {<!-- --> PrintTime = DateTime. Now; cb = writer. DirectContent; template = cb.CreateTemplate(50, 50); } catch (DocumentException de) {<!-- --> } catch (System.IO.IOException ioe) {<!-- --> } } /// <summary> /// Header--header /// </summary> /// <param name="writer"></param> /// <param name="document"></param> public override void OnStartPage(PdfWriter writer, Document document) {<!-- --> base.OnStartPage(writer, document); Rectangle pageSize = document. PageSize; if (Title != null) {<!-- --> cb. BeginText(); cb. SetFontAndSize(bf, fontSize); cb. SetRGBColorFill(50, 50, 200); cb.SetTextMatrix(pageSize.GetLeft(leftMargins), pageSize.GetTop(topMargins)); cb.ShowText(Title); cb. EndText(); } iTextSharp.text.Font font = new Font(bf, 10, Font.NORMAL, new BaseColor(110, 84, 40));//title PdfPTable HeaderTable = new PdfPTable(2); HeaderTable.DefaultCell.VerticalAlignment = Element.ALIGN_MIDDLE; HeaderTable.TotalWidth = pageSize.Width - 28; HeaderTable.SetWidthPercentage(new float[] {<!-- --> 45, 45 }, pageSize); PdfPCell HeaderLeftCell = new PdfPCell(new Phrase(8, "xxxx company", font)); HeaderLeftCell. BorderWidthLeft = 0; HeaderLeftCell.BorderWidthTop = 0; HeaderLeftCell. BorderWidthRight = 0; HeaderTable.AddCell(HeaderLeftCell); PdfPCell HeaderRightCell = new PdfPCell(new Phrase(8, "xxxx Co., Ltd", font)); HeaderRightCell.HorizontalAlignment = PdfPCell.ALIGN_RIGHT; HeaderRightCell. BorderWidthLeft = 0; HeaderRightCell. BorderWidthRight = 0; HeaderRightCell.BorderWidthTop = 0; HeaderTable.AddCell(HeaderRightCell); cb. SetRGBColorFill(0, 0, 0); HeaderTable.WriteSelectedRows(0, -1, pageSize.GetLeft(14), pageSize.GetTop(8), cb); } /// <summary> /// Footer--page number /// </summary> /// <param name="writer"></param> /// <param name="document"></param> public override void OnEndPage(PdfWriter writer, Document document) {<!-- --> base.OnEndPage(writer, document); int pageN = writer. PageNumber; String text = "第" + pageN + "page,"; float len = bf. GetWidthPoint(text, fontSize); Rectangle pageSize = document. PageSize; cb.SetRGBColorFill(100, 100, 100); cb. BeginText(); cb. SetFontAndSize(bf, fontSize); cb.SetTextMatrix(pageSize.GetLeft(leftMargins), pageSize.GetBottom(bottomMargins)); cb.ShowText(text); cb. EndText(); cb.AddTemplate(template, pageSize.GetLeft(leftMargins) + len, pageSize.GetBottom(bottomMargins)); cb. BeginText(); cb. SetFontAndSize(bf, fontSize); cb.ShowTextAligned(PdfContentByte.ALIGN_RIGHT, "Generation time: " + PrintTime.ToString(), pageSize. GetRight(rightMargins), pageSize. GetBottom(bottomMargins), 0); cb. EndText(); } public override void OnCloseDocument(PdfWriter writer, Document document) {<!-- --> base.OnCloseDocument(writer, document); template.BeginText(); template. SetFontAndSize(bf, fontSize); template. SetTextMatrix(0, 0); template.ShowText("total" + (writer.PageNumber - 1) + "page"); template. EndText(); } }
The effect of the generated pdf is as follows: header and footer
2. PDF page header
When we output a table, when the table exceeds one page, iTextSharp only displays the header on the first page by default, and the other pages do not display the header but only the data. If we need to display the header on every page, we can set it The following statement:
table.HeaderRows = 1;//For example, if there are two rows of headers, you can set 2
3. PDF generation download
We can use the form of MemoryStream
when creating a file, and then convert the MemoryStream
file stream into base64 character encoding, and return it to the front end for direct download. See three for details.
4. Complete code:
using iTextSharp.text; using iTextSharp.text.pdf; using System; using System.Data; using System.IO; using System. Linq; namespace SIE.Common.Helper.Tools {<!-- --> public class ConvertPdf {<!-- --> public static float _fontSize= 12; //font size public static float _fontSize2 = 10; public static Rectangle _pageSize = PageSize.A4;//Set pdf document paper size //The font is read in Windows system Arial, public static BaseFont basefont = BaseFont.CreateFont(@"C:\Windows\Fonts\simsun.ttc,0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); /// <summary> /// DataTable exported to Excel's MemoryStream /// </summary> /// <param name="dtStru">Header</param> /// <param name="dtSource">data</param> /// <param name="title"></param> /// <returns></returns> public static string ExportPDF(DataTable dtStru, DataTable dtSource, string title) {<!-- --> MemoryStream mspdf = new MemoryStream(); string base64Code = null; iTextSharp.text.Font font = new Font(basefont, _fontSize2, Font.BOLD);//Title iTextSharp.text.Font font2 = new Font(basefont, _fontSize2);//Common column Document document = new Document(_pageSize, 14, 14, 28, 24); PdfWriter pdfWriter= PdfWriter. GetInstance(document, mspdf); ItextPdfHeaderFooter headerFooter = new ItextPdfHeaderFooter(); pdfWriter. PageEvent = headerFooter; document. Open(); document. AddTitle(title); Paragraph element = new Paragraph(title, new Font(basefont, 14)); element.SpacingAfter = 10; //Set the spacing from the content behind element.Alignment = Element.ALIGN_CENTER; document. Add(element); PdfPTable table = new PdfPTable(dtStru.Rows.Count); table.WidthPercentage = 100;//Set the table width percentage var width = (from dt in dtStru.AsEnumerable() select float.Parse(dt["width"].ToString())).ToArray(); table. SetTotalWidth(width); #region header foreach (DataRow item in dtStru.Rows) {<!-- --> PdfPCell cell = new PdfPCell(new Paragraph(item["value"].ToString(), font)); //cell.Colspan = 2; //Define the span of a table cell cell.Rowspan = 2; cell.BackgroundColor = new BaseColor(142,229,238); cell.VerticalAlignment = PdfPCell.ALIGN_MIDDLE; //vertically centered cell.HorizontalAlignment = PdfPCell.ALIGN_CENTER;//horizontal center table.AddCell(cell); } #endregion var i = 0; #region Data Loading foreach (DataRow item in dtSource.Rows) {<!-- --> i + + ; foreach (DataRow item2 in dtStru.Rows) {<!-- --> var fldname = item2["name"].ToString(); var df_value = item[fldname].ToString(); PdfPCell cell_data = new PdfPCell(new Paragraph(df_value, font2)); //interlaced color if (i % 2 == 0) {<!-- --> cell_data.BackgroundColor = new BaseColor(253, 245, 230); } cell_data.VerticalAlignment = PdfPCell.ALIGN_MIDDLE; //vertically centered cell_data.HorizontalAlignment = PdfPCell.ALIGN_CENTER;//horizontal center table.AddCell(cell_data); } } #endregion //Set the number of headers so that it can be displayed on every page if (dtSource. Rows. Count == 0) {<!-- --> table.HeaderRows = 1; }else {<!-- --> table.HeaderRows = 2; } document. Add(table); document. Close(); //Convert base64 encoding base64Code = Convert.ToBase64String(mspdf.ToArray()); return base64Code; } } /// <summary> /// Inherit PdfPageEventHelper, rewrite header and footer /// </summary> public class ItextPdfHeaderFooter : PdfPageEventHelper {<!-- --> PdfContentByte cb; PdfTemplate template; // Chinese font BaseFont bf = BaseFont.CreateFont(@"C:\Windows\Fonts\simsun.ttc,0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); // Print Time DateTime PrintTime = DateTime. Now; float fontSize = 10; //font size float leftMargins = 14;//left margin float rightMargins = 14;//right margin float bottomMargins = 12;//bottom margin float topMargins = 12;//top margin #region header basic properties private string _Title; public string Title {<!-- --> get {<!-- --> return _Title; } set {<!-- --> _Title = value; } } public PdfPTable_Table; public PdfPTable Table {<!-- --> get {<!-- --> return _Table; } set {<!-- --> _Table=value; } } private string _HeaderLeft; public string HeaderLeft {<!-- --> get {<!-- --> return _HeaderLeft; } set {<!-- --> _HeaderLeft = value; } } private string _HeaderRight; public string HeaderRight {<!-- --> get {<!-- --> return _HeaderRight; } set {<!-- --> _HeaderRight = value; } } #endregion // Override the onOpenDocument method public override void OnOpenDocument(PdfWriter writer, Document document) {<!-- --> try {<!-- --> PrintTime = DateTime. Now; cb = writer. DirectContent; template = cb.CreateTemplate(50, 50); } catch (DocumentException de) {<!-- --> } catch (System.IO.IOException ioe) {<!-- --> } } /// <summary> /// Header--header /// </summary> /// <param name="writer"></param> /// <param name="document"></param> public override void OnStartPage(PdfWriter writer, Document document) {<!-- --> base.OnStartPage(writer, document); Rectangle pageSize = document. PageSize; if (Title != null) {<!-- --> cb. BeginText(); cb. SetFontAndSize(bf, fontSize); cb. SetRGBColorFill(50, 50, 200); cb.SetTextMatrix(pageSize.GetLeft(leftMargins), pageSize.GetTop(topMargins)); cb.ShowText(Title); cb. EndText(); } iTextSharp.text.Font font = new Font(bf, 10, Font.NORMAL, new BaseColor(110, 84, 40));//title PdfPTable HeaderTable = new PdfPTable(2); HeaderTable.DefaultCell.VerticalAlignment = Element.ALIGN_MIDDLE; HeaderTable.TotalWidth = pageSize.Width - 28; HeaderTable.SetWidthPercentage(new float[] {<!-- --> 45, 45 }, pageSize); PdfPCell HeaderLeftCell = new PdfPCell(new Phrase(8, "xxxx company", font)); HeaderLeftCell. BorderWidthLeft = 0; HeaderLeftCell.BorderWidthTop = 0; HeaderLeftCell. BorderWidthRight = 0; HeaderTable.AddCell(HeaderLeftCell); PdfPCell HeaderRightCell = new PdfPCell(new Phrase(8, "xxxx department", font)); HeaderRightCell.HorizontalAlignment = PdfPCell.ALIGN_RIGHT; HeaderRightCell. BorderWidthLeft = 0; HeaderRightCell. BorderWidthRight = 0; HeaderRightCell.BorderWidthTop = 0; HeaderTable.AddCell(HeaderRightCell); cb. SetRGBColorFill(0, 0, 0); HeaderTable.WriteSelectedRows(0, -1, pageSize.GetLeft(14), pageSize.GetTop(8), cb); } /// <summary> /// Footer--page number /// </summary> /// <param name="writer"></param> /// <param name="document"></param> public override void OnEndPage(PdfWriter writer, Document document) {<!-- --> base.OnEndPage(writer, document); int pageN = writer. PageNumber; String text = "第" + pageN + "page,"; float len = bf. GetWidthPoint(text, fontSize); Rectangle pageSize = document. PageSize; cb.SetRGBColorFill(100, 100, 100); cb. BeginText(); cb. SetFontAndSize(bf, fontSize); cb.SetTextMatrix(pageSize.GetLeft(leftMargins), pageSize.GetBottom(bottomMargins)); cb.ShowText(text); cb. EndText(); cb.AddTemplate(template, pageSize.GetLeft(leftMargins) + len, pageSize.GetBottom(bottomMargins)); cb. BeginText(); cb. SetFontAndSize(bf, fontSize); cb.ShowTextAligned(PdfContentByte.ALIGN_RIGHT, "Generation time: " + PrintTime.ToString(), pageSize. GetRight(rightMargins), pageSize. GetBottom(bottomMargins), 0); cb. EndText(); } public override void OnCloseDocument(PdfWriter writer, Document document) {<!-- --> base.OnCloseDocument(writer, document); template.BeginText(); template. SetFontAndSize(bf, fontSize); template. SetTextMatrix(0, 0); template.ShowText("total" + (writer.PageNumber - 1) + "page"); template. EndText(); } } }
3. Front-end JS download PDF file
Get the base64 string from the backend, convert it to Uint8Array type, then convert it to blob type, and finally download it.
1. JS function:
/*res returned string*/ function (res) {<!-- --> var base64 = JSON. parse(res. Result); base64 = base64.replace(/[\ \r]/g, ''); var raw = window.atob(base64); let rawLength = raw. length; //Convert to Uint8Array type that pdf.js can directly parse let uInt8Array = new Uint8Array(rawLength); for (let i = 0; i < rawLength; + + i) {<!-- --> uInt8Array[i] = raw. charCodeAt(i); } // convert character content to blob var blob = new Blob([uInt8Array], {<!-- --> type: 'application/pdf' });//Convert to pdf type // Create a hidden downloadable link var eleLink = document. createElement('a'); eleLink.download = title + '.pdf'; eleLink.style.display = 'none'; eleLink.href = URL.createObjectURL(blob); // trigger click document.body.appendChild(eleLink); eleLink.click(); // then remove document.body.removeChild(eleLink); }
2. Final effect:
ps: It’s not easy to create, please like it! ! !