Java自定义生成PDF报告
流程分析
為滿足上述需求,需要通過程序實現自定義生成PDF文件。幸運的是目前已有對應的代碼解決方案可以實現該需求。方案涉及到itextpdf類庫、AdobeAcrobat DC的使用。整體流程如下:
自定義生成PDF文件流程圖
由上圖可知,生成自定義PDF文件流程主要分為三個部分。模板配置,數據映射,數據填充。其中,模板配置需要用到AdobeAcrobat DC軟件(一款PDF編輯器),在模板配置過程中,需要設置好PDF文件各個屬性名稱,方便后續的數據映射。最后通過itextpdf類庫提供的方案,將業務數據填充到PDF模板并生成PDF文件。
步驟介紹
一、PDF模板配置
?????? 配置PDF模板需要用到AdobeAcrobat DC軟件,該軟件的綠色版本請見附件。首先需要創建一個PDF文件,然后使用AdobeAcrobat DC打開,如下圖:
?打開空白PDF文檔
????????選擇右側“準備表單”選項,即可編輯PDF模板。模板中可以添加圖片域、文本域,可以設置各個域的名稱。例如標題的名稱為title。如下圖:
?PDF模板配置
注:上述PDF模板中配置的各個域和預期生成的PDF文件數據要一一對應,例如,如果需要在PDF文件上方居中位置展示標題內容,則需要在PDF模板中創建一個文本域,文本域名稱為title。然后在JAVA代碼中,將標題內容通過title這個key填充到模板中。
?????? 在設置PDF模板時,我們可以自定義各個域的展示效果,包括圖片域、按鈕域中展示的圖片具體如下圖:
添加PDF模板默認圖標?
還可以設置文本域中文字的展示字體、大小。如下圖:
?設置PDF模板文字屬性
按照業務需要配置完PDF模板后需要將模板保存為PDF文件,后續JAVA代碼填充數據時需要向該PDF文件中寫入數據。配置完成的PDF文件如下:
?PDF模板編輯效果
二、數據寫入
?????? 當我們配置好PDF模板以后,我們需要通過JAVA代碼講業務數據填入PDF模板,從而得到最終的PDF文件。
?????? 數據寫入需要用到itextpdf和itext-asian兩個類庫。使用方法也很簡單。只需要在項目pom文件中導入這兩個類庫的maven依賴。
| <dependency> ??????????? <groupId>com.itextpdf</groupId> ??????????? <artifactId>itextpdf</artifactId> ??????????? <version>5.5.13.2</version> ??????? </dependency> ??????? <dependency> ??????????? <groupId>com.itextpdf</groupId> ??????????? <artifactId>itext-asian</artifactId> ??????????? <version>5.2.0</version> ??????? </dependency> |
?????? 依賴引入成功后,我們就可以使用PdfReader 和PdfStamper這兩個類來實現PDF模板的讀取和PDF數據填充功能。
(1)配置文件讀取/寫入
?????? 配置文件的讀取很簡單,首先通過PdfReader讀取PDF模板文件,然后結合數據輸出流,創建PdfStamper即可。如下圖:
| PdfReader reader = new PdfReader("D:\\test.pdf")?? //讀取模板文件 ByteArrayOutputStream bos = new ByteArrayOutputStream();? //創建輸出流 PdfStamper stamper = stamper = new PdfStamper(reader, bos) //創建PDF文件填充對象 |
(2)業務數據映射
?????? 文件填充對象創建成功后,需要向該對象添加數據,常見的數據有兩種,一種是文本數據,一種是圖片數據。接下來我將分別說明兩種數據的填充方式,并分別提供案例。
?????? 第一種文本數據,文本數據相對比較簡單,只需要處理stamper對象中的AcroFields對象即可。處理時需要設置文本字體和文本內容與PDF模板的映射。
| AcroFields form = stamper.getAcroFields();?? //獲取AcroFields對象 BaseFont bf =? com.itextpdf.text.pdf.BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false); Font FontChinese = new Font(bf, 5, Font.NORMAL);?? //創建字體 form.addSubstitutionFont(bf);? //添加字體屬性 Map<String,String> fieldMap = new HashMap<>(); fieldMap.put("name","張三");?? //創建文本映射關系 form.setField(key, fieldMap.get(“name”));?? //填充文本信息 |
注:
Key和PDF模板的映射關系如下圖:
?
第二種圖片數據,圖片數據同樣需要處理AcroFields對象,但是相比于文本數據,圖片數據的處理更加負責,如下代碼:
| Map<String,String> map2 = new HashMap(); map2.put("testimage","D:\\qwqqqq.png");?? //獲取需要填充的圖片 //根據圖片存儲路徑創建圖片對象 String value = map2.get(“testimage”); String imgpath = value; int pageNo = form.getFieldPositions(key).get(0).page; Rectangle signRect = form.getFieldPositions(key).get(0).position;? //此處key與PDF模板對應 float x = signRect.getLeft();? //圖片坐標 float y = signRect.getBottom(); //圖片坐標,默認按照PDF模板設置展示 //根據路徑讀取圖片 Image image = Image.getInstance(imgpath); //獲取圖片頁面 PdfContentByte under = stamper.getOverContent(pageNo); //圖片大小自適應 image.scaleToFit(signRect.getWidth(), signRect.getHeight()); //添加圖片 image.setAbsolutePosition(x, y); under.addImage(image); |
?????? 文本和圖片數據添加完成后,需要執行最后一步,生成PDF文件。
| stamper.setFormFlattening(true);// 如果為false,生成的PDF文件可以編輯,如果為true,生成的PDF文件不可以編輯 FileOutputStream out = new FileOutputStream(filePath+fileName);? //PDF文件最終輸出路徑和PDF文件名稱 stamper.close(); Document doc = new Document(); Font font = new Font(bf, 32); PdfCopy copy = new PdfCopy(doc, out);? //將數據輸出流通過copy輸出 doc.open(); PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1); copy.addPage(importPage); doc.close(); |
總結
以上是生活随笔為你收集整理的Java自定义生成PDF报告的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于 block的一些浅识
- 下一篇: JVM内存结构和Java内存模型别再傻傻