[C#][iTextSharp] PDF 套版

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 製作的基本资料表格。

http://img2.58codes.com/2024/20106865Yk61Swu64U.jpg

将其汇出成 PDF,再用 Adobe Acrobat 开启,点选右上角的 工具 开启选单,然后选择 表格 内的 编辑

http://img2.58codes.com/2024/20106865E9ITqxgxpZ.jpg

第一次编辑会询问 是否自动侦测表格,这里选 可以让 Acrobat 自动侦测并建立表格,剩下的再手动调整。

http://img2.58codes.com/2024/201068650Hx9pxNz5p.jpg

点击栏位两下开启 内容视窗,将 名称 改成给程式对应的栏位名称。

http://img2.58codes.com/2024/20106865089ltqzrkB.jpg

RadioButton

性别栏位只有男或女且单选,所以用 RadioButton,点选右上角新增栏位,选择选项按钮

http://img2.58codes.com/2024/201068659W0AdxK3hG.jpg

RadioButton 为同群组单选的元件,其 名称 为群组,选项按钮选择 为被选取的值,这里新增男女两个 RadioButton,将名称改为 SexGroup,选项按钮选择分别改为 MaleFemale

http://img2.58codes.com/2024/20106865IZ24MVzILf.jpg

CheckBox

兴趣栏位可多选,所以用 CheckBox,点选右上角 新增栏位,选择 核取框

http://img2.58codes.com/2024/20106865eiW5NP5TGC.jpg

CheckBox 不像 RadioButton 有 群组 概念,每个 CheckBox 都有自己的名称,判断是否被勾选,要看内容视窗里的 转存值,预设为 ,只要程式丢过来的值等于 转存值,CheckBox 就会被勾选。

http://img2.58codes.com/2024/20106865EXCczhGJIg.jpg

Image

图片套版会使用 按钮 元件,将背景色设为 白色,利用按钮的 icon 来替换图片。

http://img2.58codes.com/2024/201068650SCkAsRivY.jpg

开启内容视窗改变背景色。

http://img2.58codes.com/2024/20106865EoMItEdUq8.jpg

Barcode

Barcode 部分不用更改,使用 文字栏位 即可。

结果

完整程式太长就不贴上来,下方分享常用功能。

第一页
http://img2.58codes.com/2024/20106865PFE6eusNaP.jpg

第二页
http://img2.58codes.com/2024/20106865Mrnv9FL8Of.jpg


常用功能程式码

会用到 iTextSharp 可用 Nuget 安装。

iTextSharp 主结构
//可以是任何 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 和 CheckBox
using (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);        }    }}
Barcode39
using (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文件?


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章