2022/08 更新
我根据文章内容製作了 Nuget 套件。
PM> Install-Package PdfTemplate.iTextSharp.LGPLv2
这个套件内部使用 iTextSharp.LGPLv2 生成 pdf 文件,因此它的授权较 iTextSharp 和 iText 7 更宽鬆。
iTextSharp.LGPLv2 -> (LGPL v2.0)iTextSharp-> (AGPL)iText 7 -> (AGPL)用法可以参考 Github 内容。
https://github.com/fysh711426/PdfTemplate.iTextSharp.LGPLv2
前言
做报表常会用到 PDF 套版,套版的类型很多,文字、颜色、图片、Radio、CheckBox、等等...,有时候还要分页,所以想把这些需求整理起来。
範本製作
範本一般会用 Word
画出表格后 汇出成 PDF
,再用 Adobe Acrobat
将需要填入资料的地方加入表格元件。
下图为 Word 製作的基本资料表格。
将其汇出成 PDF,再用 Adobe Acrobat 开启,点选右上角的 工具
开启选单,然后选择 表格
内的 编辑
。
第一次编辑会询问 是否自动侦测表格
,这里选 是
可以让 Acrobat 自动侦测并建立表格,剩下的再手动调整。
点击栏位两下开启 内容视窗
,将 名称
改成给程式对应的栏位名称。
RadioButton
性别栏位只有男或女且单选,所以用 RadioButton
,点选右上角新增栏位
,选择选项按钮
。
RadioButton 为同群组单选的元件,其 名称
为群组,选项按钮选择
为被选取的值,这里新增男女两个 RadioButton,将名称改为 SexGroup
,选项按钮选择分别改为 Male
和 Female
。
CheckBox
兴趣栏位可多选,所以用 CheckBox
,点选右上角 新增栏位
,选择 核取框
。
CheckBox 不像 RadioButton 有 群组
概念,每个 CheckBox 都有自己的名称,判断是否被勾选,要看内容视窗里的 转存值
,预设为 是
,只要程式丢过来的值等于 转存值
,CheckBox 就会被勾选。
Image
图片套版会使用 按钮
元件,将背景色设为 白色
,利用按钮的 icon
来替换图片。
开启内容视窗改变背景色。
Barcode
Barcode 部分不用更改,使用 文字栏位
即可。
结果
完整程式太长就不贴上来,下方分享常用功能。
第一页
第二页
常用功能程式码
会用到 iTextSharp
可用 Nuget 安装。
//可以是任何 Stream 类型 (MemoryStream、FileStream、OutputStream)var stream = new MemoryStream();//建立文件using (var doc = new Document()){ using (var writer = PdfWriter.GetInstance(doc, stream)) { doc.Open(); //操作 PDF ... doc.Close(); }}
文字using (var ms = new MemoryStream()){ using (var reader = new PdfReader("範本档路径")) { using (var stamper = new PdfStamper(reader, ms)) { //取得表单 var form = stamper.AcroFields; //套入文字 form.SetField("Name", "王小明"); } }}
文字颜色using (var ms = new MemoryStream()){ using (var reader = new PdfReader("範本档路径")) { using (var stamper = new PdfStamper(reader, ms)) { //取得表单 var form = stamper.AcroFields; //套入文字 form.SetField("Name", "王小明"); //套入颜色 var color = "#FF0000"; //红色 var baseColor = new BaseColor(System.Drawing.ColorTranslator.FromHtml(color)); form.SetFieldProperty("Name", "textcolor", baseColor, null); } }}
RadioButton 和 CheckBoxusing (var ms = new MemoryStream()){ using (var reader = new PdfReader("範本档路径")) { using (var stamper = new PdfStamper(reader, ms)) { //取得表单 var form = stamper.AcroFields; //RadioButton form.SetField("Group", "男", true); //CheckBox form.SetField("Name", "是", true); } }}
图片using (var ms = new MemoryStream()){ using (var reader = new PdfReader("範本档路径")) { using (var stamper = new PdfStamper(reader, ms)) { //取得表单 var form = stamper.AcroFields; //取得图片 var image = iTextSharp.text.Image.GetInstance("图片档路径"); //取得按钮元件 var pushbuttonField = form.GetNewPushbuttonFromField("Name"); //指定为 ICON pushbuttonField.Layout = PushbuttonField.LAYOUT_ICON_ONLY; //图片等比缩放 pushbuttonField.ProportionalIcon = true; pushbuttonField.Image = image; //取代原按钮 form.ReplacePushbuttonField("Name", pushbuttonField.Field); } }}
Barcode39using (var ms = new MemoryStream()){ using (var reader = new PdfReader("範本档路径")) { using (var stamper = new PdfStamper(reader, ms)) { //取得表单 var form = stamper.AcroFields; //取得栏位位置资讯 var fieldPosition = form.GetFieldPositions("Name")[0]; var pdfContentByte = stamper.GetOverContent(fieldPosition.page); var barcode = new Barcode39(); //barcode 内容 barcode.Code = "123456789"; //显示文字是否前后加上星号 barcode.StartStopText = false; //条码线最小宽度 barcode.X = 0.8f; //设置墨水扩散量,从每个条码线中减去该值 barcode.InkSpreading = 0f; //为某些类型保留条码线的乘数 barcode.N = 2f; //字体大小 barcode.Size = 10f; //文本和条形码之间的距离 barcode.Baseline = 10f; //barcode 高度 barcode.BarHeight = 20f; barcode.GenerateChecksum = false; barcode.ChecksumText = false; //产生 barcode 图片 var image = barcode.CreateImageWithBarcode(pdfContentByte, BaseColor.BLACK, BaseColor.BLACK); var rect = fieldPosition.position; //设定图片座标,以栏位的左下角为原点 image.SetAbsolutePosition(rect.Left, rect.Bottom); pdfContentByte.AddImage(image); } }}
插入段落using (var ms = new MemoryStream()){ using (var reader = new PdfReader("範本档路径")) { using (var stamper = new PdfStamper(reader, ms)) { //取得表单 var form = stamper.AcroFields; //新增段落 var paragraph = new Paragraph("abc"); //取得栏位位置资讯 var fieldPositions = form.GetFieldPositions("Name"); //设定行距 paragraph.Leading = 30; //设定第一列缩排 paragraph.FirstLineIndent = 24; //设定对齐方式 paragraph.Alignment = iTextSharp.text.Element.ALIGN_JUSTIFIED; foreach (var position in fieldPositions) { var pdfContentByte = stamper.GetOverContent(position.page); var columnText = new ColumnText(pdfContentByte); //ColumnText 呼叫 AddElement 后,自动由 Text 模式转为 Composite 模式 columnText.AddElement(paragraph); //设定 ColumnText 边界 columnText.SetSimpleColumn(position.position.Left, position.position.Bottom, position.position.Right, position.position.Top); columnText.Go(); } } }}
插入浮水印using (var ms = new MemoryStream()){ using (var reader = new PdfReader("範本档路径")) { using (var stamper = new PdfStamper(reader, ms)) { //取得表单 var form = stamper.AcroFields; //取得栏位位置资讯 var fieldPositions = form.GetFieldPositions(""); foreach (var position in fieldPositions) { var pdfContentByte = stamper.GetUnderContent(position.page); pdfContentByte.BeginText(); var baseFont = BaseFont.CreateFont("字型档路径", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); //设定字型和字体大小 pdfContentByte.SetFontAndSize(baseFont, 120); //设定字体颜色 pdfContentByte.SetRGBColorFill(210, 210, 210); //设定浮水印透明度 pdfContentByte.SetGState(new PdfGState { FillOpacity = 0.6f, //背景 StrokeOpacity = 0.6f //文字 }); //取得当前页面的位置资讯 var rect = reader.GetPageSizeWithRotation(position.page); var x = (rect.Right + rect.Left) / 2; //取得页面 x 轴中心座标 var y = (rect.Bottom + rect.Top) / 2; //取得页面 y 轴中心座标 //设定浮水印 pdfContentByte.ShowTextAligned(PdfContentByte.ALIGN_CENTER, "浮水印", x, y, 45); pdfContentByte.EndText(); } } }}
防止表单编辑using (var ms = new MemoryStream()){ using (var reader = new PdfReader("範本档路径")) { using (var stamper = new PdfStamper(reader, ms)) { //表单扁平化,防止表单编辑 stamper.FormFlattening = true; } }}
设定字型var baseFont1 = BaseFont.CreateFont("字型档1路径", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);var baseFont2 = BaseFont.CreateFont("字型档2路径", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);//表单设定字型stamper.AcroFields.AddSubstitutionFont(baseFont1);stamper.AcroFields.AddSubstitutionFont(baseFont2);//段落设定字型var font1 = new Font(baseFont1, 12f, Font.NORMAL);var font2 = new Font(baseFont2, 12f, Font.NORMAL);var selector = new iTextSharp.text.pdf.FontSelector();selector.AddFont(font1);selector.AddFont(font2);var paragraph = new iTextSharp.text.Paragraph();paragraph.Add(selector.Process("abc一二三"));
合併 PDF 产生分页//要合併的多个 PDF 文件var files = new List<byte[]>();using (var doc = new Document()){ using (var writer = PdfWriter.GetInstance(doc, stream)) { doc.Open(); var contentByte = writer.DirectContent; foreach(var file in files) { using (var reader = new PdfReader(file)) { for (var i = 1; i <= reader.NumberOfPages; i++) { //设定页面大小为当前範本的页面的大小 doc.SetPageSize(reader.GetPageSize(i)); //产生新页面 doc.NewPage(); //将 Reader 转为 PdfImportedPage var newPage = writer.GetImportedPage(reader, i); //插入新页面 contentByte.AddTemplate(newPage, 0, 0); } //释放 reader writer.FreeReader(reader); } } doc.Close(); }}
参考文章
使用ASP .NET (C#) 产生PDF档的好帮手—iTextSharp library (上)
c#使用itextsharp输出pdf(动态填充表单内容,显示中文)
How to change the text color of an AcroForm field?
使用iTextSharp进行PDF档案套版
iTextSharp Fill Pdf Form Image Field
Code 39/128 Barcode Image Generator
[iTextSharp学习笔记]在指定的位置上添加文本
CSharp - 在每个页面上,使用水印创建 C# itextsharp PDF
如何使用itextsharp将表单字段添加到现有的pdf中?
Missing character in custom font
itextsharp - 如何使用iTextSharp组合多个不包括分页符的PDF文件?