做報表常會用到 PDF 套版,套版的類型很多,文字、顏色、圖片、Radio、CheckBox、等等...,有時候還要分頁,所以想把這些需求整理起來。
範本一般會用 Word
畫出表格後 匯出成 PDF
,再用 Adobe Acrobat
將需要填入資料的地方加入表格元件。
下圖為 Word 製作的基本資料表格。
將其匯出成 PDF,再用 Adobe Acrobat 開啟,點選右上角的 工具
開啟選單,然後選擇 表格
內的 編輯
。
第一次編輯會詢問 是否自動偵測表格
,這裡選 是
可以讓 Acrobat 自動偵測並建立表格,剩下的再手動調整。
點擊欄位兩下開啟 內容視窗
,將 名稱
改成給程式對應的欄位名稱。
性別欄位只有男或女且單選,所以用 RadioButton
,點選右上角新增欄位
,選擇選項按鈕
。
RadioButton 為同群組單選的元件,其 名稱
為群組,選項按鈕選擇
為被選取的值,這裡新增男女兩個 RadioButton,將名稱改為 SexGroup
,選項按鈕選擇分別改為 Male
和 Female
。
興趣欄位可多選,所以用 CheckBox
,點選右上角 新增欄位
,選擇 核取框
。
CheckBox 不像 RadioButton 有 群組
概念,每個 CheckBox 都有自己的名稱,判斷是否被勾選,要看內容視窗裡的 轉存值
,預設為 是
,只要程式丟過來的值等於 轉存值
,CheckBox 就會被勾選。
圖片套版會使用 按鈕
元件,將背景色設為 白色
,利用按鈕的 icon
來替換圖片。
開啟內容視窗改變背景色。
Barcode 部分不用更改,使用 文字欄位
即可。
完整程式太長就不貼上來,下方分享常用功能。
第一頁
第二頁
本來做好了漂亮的 GIF 結果圖,沒想到 IT邦不能上傳 GIF 格式的圖片,所以默默的換成了 2張 JPG。 QQ
會用到 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);
}
}
}
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);
}
}
}
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.FontSelect();
selector.AddFont(font1);
selector.AddFont(font2);
var paragraph = new iTextSharp.text.Paragraph();
paragraph.Add(selector.Process("abc一二三"));
//要合併的多個 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文件?
這套件我也有用過,
還不錯用,
不過我是拿來做表格的。
表格也可以套板
學號 | 姓名 |
---|---|
Id1 | Name1 |
Id2 | Name2 |
... | ... |
在範本裡面先把整個表格排滿,哈哈。
因為很懶所以都會想用範本做,可以省很多工。
前提是你會常用到那些範本,
要不然做範本只在一個地方用到也沒有意義 @@
恩恩,還是要看需求使用。
大大的文章真是幫助極大,目前接手的案子就是需要用到填表格的功能,過去是使用讀取excel表填寫再轉PDF輸出,看到這篇之後終於有其他解法啦,謝謝分享
表單如果欄位固定很適合用此方法,不怕客戶改樣式、開發快速
缺點是欄位無法動態、產生的檔案較大
不過我覺得優點還是更多些
請問如果用這種方式,是不是需要使用Acrobat Pro DC才能規劃表格呢?
只要支援表格編輯的 PDF 軟體都可以
最近專案也有將資料讀入PDF匯出的需求,除了iTextSharp還有搜尋到一款ironpdf,好像也蠻好用的版主有使用過嗎??
這套看起來偏 Html 轉 PDF
以前試過的 Html 轉 PDF 套件一般都會跑版
所以還是喜歡套版或用刻的