前言
作為開發人員,工作中難免會遇到復雜表單的導出,接下來介紹一種通過Java利用模板便捷導出Pdf表單的方式
模擬需求
需求:按照下面格式導出pdf格式的學生成績單
准備工作
- Excel軟件
- Adobe Acrobat XI Pro軟件
模板制作
第一步:利用Excel制作出上述表單,設置好字體、行高、列寬等,如下:
第二步:按照給定模板做好Excel表單后,刪除需要后期填充的數據
第三步:打開Adobe Acrobat XI Pro軟件,開始依據Excel模板制作PDF模板
1、單擊創建、選擇創建表單按鈕
2、選擇從現有文檔創建,選擇前面制作的Excel模板
3、點擊工具,編輯表單
4、此時表單中只有一個文本域,我們可以點擊添加新的文本域的形式來添加表頭和結尾。也可以在pdf上添加一些其他控件。制作完成后如下:
5、可以通過鼠標在域中右鍵和屬性中修改域的位置,字體、顏色、換行等
6、將制作好的表單保存
項目實現
第一步:創建基於maven的Java項目
第二步:引入itext的pom依賴
<!-- itextpdf依賴 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.10</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
第六步:將上面制作的pdf模板放到Resources目錄下,編寫PdfUtils工具類
package com.whw.pdf;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.*;
import java.io.*;
import java.util.ArrayList;
public class PdfUtils {
public static void exportMapMZydPdf(String templatePath,String savePath,String fileName) throws DocumentException {
ByteArrayOutputStream byteArrayOutputStream = null;
PdfReader pdfReader = null;
FileOutputStream fileOutputStream=null;
try {
fileOutputStream=new FileOutputStream(savePath+"//"+fileName);
byteArrayOutputStream = new ByteArrayOutputStream();
pdfReader = new PdfReader(templatePath);
PdfStamper pdfStamper = new PdfStamper(pdfReader, byteArrayOutputStream);
//獲取模板所有域參數
AcroFields acroFields = pdfStamper.getAcroFields();
//解決中文字體不顯示的問題
BaseFont baseFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
ArrayList<BaseFont> fontArrayList = new ArrayList<BaseFont>();
fontArrayList.add(baseFont);
acroFields.setSubstitutionFonts(fontArrayList);
acroFields.setField("head", "xxx同學成績單");
acroFields.setField("yuwen", "116");
acroFields.setField("shuxue", "115");
acroFields.setField("yingyu", "110");
acroFields.setField("zhengzhi", "89");
acroFields.setField("lishi", "90");
acroFields.setField("shengwu", "85");
acroFields.setField("dili", "83");
acroFields.setField("yinyue", "78");
acroFields.setField("tiyu", "88");
acroFields.setField("meishu", "80");
acroFields.setField("xiguan", "優秀");
acroFields.setField("nengli", "優秀");
acroFields.setField("xuexi", "優秀");
acroFields.setField("jl", "優秀");
acroFields.setField("weisheng", "良好");
acroFields.setField("pingyu", " 在校表現優秀。你關心同學,有很強的集體榮譽感,對待工作細致負責,學習上也比較踏實。老師相信你還有很大潛力沒有挖掘出來,你要相信自己,不斷挑戰自我,加油!");
acroFields.setField("jc", "三號學生");
acroFields.setField("school", "xx市第一高級中學");
pdfStamper.setFormFlattening(true);//如果為false那么生成的PDF文件還能編輯,一定要設為true
pdfStamper.flush();
pdfStamper.close();
//設置紙張,可以在Excel制作是設定好紙張大小
Document doc = new Document(PageSize.A5);
PdfCopy copy = new PdfCopy(doc,fileOutputStream);
doc.open();
PdfImportedPage importPage = copy.getImportedPage(new PdfReader(byteArrayOutputStream.toByteArray()), 1);
try {
copy.addPage(importPage);
} catch (BadPdfFormatException e) {
e.printStackTrace();
}
doc.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (byteArrayOutputStream != null) {
try {
byteArrayOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (pdfReader != null) {
pdfReader.close();
}
}
}
public static void main(String[] args) throws IOException {
try {
String savePath="C://Users//hua//Desktop//";
String fileName="xxx同學成績單.pdf";
exportMapMZydPdf("/成績單模板.pdf",savePath,fileName);
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
第三步:運行main方法進行測試,並查看導出后的文件
項目文件:鏈接:https://pan.baidu.com/s/1xvrtd1HdXuImafMfrFcGrA 提取碼:l0qh
寫在最后
1、此種方式對Pdf居中自動換行支持性不好,可以根據文本域的寬度所能容納的字數,創建多個文本域,對值進行手動分割填充到多個文本域。
2、C#開發時處理Excel文件可用NPOI插件進行數據導入導出,處理PDF文件可用ITextSharp插件。
上述介紹只是導出pdf表單的一種方式,也可以直接利用itext進行手動創作pdf表單或者導出Excel或World后台轉換為pdf格式等。如有其它更好的方式或建議,歡迎留言一塊交流!