Java使用itext5實(shí)現(xiàn)PDF表格文檔導(dǎo)出
最近拿到一個需求,需要導(dǎo)出PDF文檔,市面上可以實(shí)現(xiàn)的方法有很多,經(jīng)過測試和調(diào)研決定使用itext5來實(shí)現(xiàn),話不多說,說干就干。
1.依賴導(dǎo)入
<!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf --> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.13.1</version> </dependency> <!-- https://mvnrepository.com/artifact/com.itextpdf/itext-asian --> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext-asian</artifactId> <version>5.2.0</version> </dependency>
這里說明下:上面的依賴就是主要實(shí)現(xiàn)PDF生成的,下面的依賴是中文字體相關(guān)依賴;
2.PDF表格導(dǎo)出實(shí)現(xiàn)
1.導(dǎo)出PDF
// 1.打開文檔并設(shè)置基本屬性
Document document = new Document();
// 2.設(shè)置請求頭,encode文件名
response.setContentType("application/pdf;charset=UTF-8");
response.setHeader("Content-Disposition",
"attachment; filename=" + java.net.URLEncoder.encode("" +
recordDto.getTitle() + ".pdf", "UTF-8"));
// 3.通過流將pdf實(shí)例寫出到瀏覽器
PdfWriter writer = PdfWriter.getInstance(document, response.getOutputStream());
至此導(dǎo)出PDF已經(jīng)實(shí)現(xiàn)了,只是這個PDF中什么內(nèi)容都沒有,明白這一點(diǎn),接下來做的就是給這個文檔“加料”咯(這里的response就是HttpServletResponse)。
2.頁面美化
// 這里的wirter就是上文的writer writer.setViewerPreferences(PdfWriter.PageModeUseThumbs); writer.setPageSize(PageSize.A4);
這里設(shè)置了文檔的顯示縮略圖以及文檔大小為A4;
3.中文字體設(shè)置
public static Font getPdfChineseFont() throws Exception {
BaseFont bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H",
BaseFont.NOT_EMBEDDED);
Font fontChinese = new Font(bfChinese, 12, Font.NORMAL);
fontChinese.setColor(BaseColor.BLACK);
fontChinese.setSize(11);
return fontChinese;
}
這個方法設(shè)置了中文字體樣式,感興趣的同學(xué)可以試試其他的樣式,例如:字體顏色,大小,字體都可以修改;
4.輸出表格內(nèi)容到文檔
// 首先打開文檔
document.open();
// 向文檔中添加表格數(shù)據(jù)
private static void printBasicInfo(ShopApplyRecordDto recordDto, Document document, Font font) throws DocumentException {
// 表格中的數(shù)據(jù)
Object[][] basicDatas = {
{"標(biāo)題","xxx申請", "審批編號","1234"},
{"申請人","小明", "申請商鋪","xxx商場"},
{"申請日期","2020/1/16", "審批結(jié)果","同意")}};
// 每個cell的寬度
float[] widthss = {50, 200, 50, 200};
// 創(chuàng)建一個表格,每一行有四個cell
PdfPTable basicTable = new PdfPTable(widthss);
// 外層循環(huán)表格的行
for (int i = 0; i < basicDatas.length; i++) {
// 內(nèi)層循環(huán)每一行具體數(shù)據(jù)
for (int j = 0; j < basicDatas[i].length; j++) {
// 新建一個cell
PdfPCell cell = new PdfPCell();
// 這個方法是統(tǒng)一設(shè)置表格和cell的樣式,下面會寫
setTableStyle(basicTable, cell);
// cell中需要填充數(shù)據(jù)的格式
Paragraph paragraph =
new Paragraph(StrUtil.toString(basicDatas[i][j]), font);
// 設(shè)置cell的值
cell.setPhrase(paragraph);
// 將cell添加到表格中
basicTable.addCell(cell);
}
}
// 將表格添加到文檔中
document.add(basicTable);
}
// 結(jié)束時要關(guān)閉文檔
document.close();
大功告成,現(xiàn)在導(dǎo)出的PDF中已經(jīng)有了類似這樣的表格了:

當(dāng)然你的樣式會很丑,接下來我們來設(shè)置下樣式。
5.表格和cell樣式設(shè)置
public static void setTableStyle(PdfPTable table, PdfPCell cell) {
// 設(shè)置表格樣式
table.setLockedWidth(true);
table.setTotalWidth(500);
table.setHorizontalAlignment(Element.ALIGN_LEFT);
// 設(shè)置單元格樣式
cell.setMinimumHeight(35);
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setBackgroundColor(BaseColor.WHITE);
cell.setBorder(0);
cell.setBorderWidthTop(0.1f);
cell.setBorderWidthBottom(0.1f);
cell.setBorderWidthLeft(0.1f);
cell.setBorderWidthRight(0.1f);
cell.setBorderColorBottom(BaseColor.BLACK);
cell.setBorderColorLeft(BaseColor.BLACK);
cell.setBorderColorRight(BaseColor.BLACK);
cell.setBorderColorTop(BaseColor.BLACK);
cell.setPadding(3);
}
api方法還是比較易懂的,這里就不多贅述了,不明白的自己設(shè)置試試就可以做出自己喜歡的樣式咯。
6.頁眉和頁碼的設(shè)置
這里說明下,itext2和itext5的api有很大不同,2的版本有一個專門的HeaderFooter類來設(shè)置樣式,5的版本沒有這樣的類,取而代之的是PdfPageEventHelper這樣一個事件處理類,這里大家千萬別弄混了,這兩個版本的api互相不兼容;
這里首先寫一個PdfPageEventHelper的子類來實(shí)現(xiàn)頁眉頁碼的打?。?/p>
public class HeaderFooter extends PdfPageEventHelper {
// 這里是業(yè)務(wù)相關(guān)的屬性可以無視
private ShopApplyRecordDto recordDto;
private SysUserInfo userInfo;
// 大部分情況下頁眉的值是動態(tài)的,這里可以在初始化的時候進(jìn)行參數(shù)傳遞
public HeaderFooter(ShopApplyRecordDto recordDto, SysUserInfo userInfo) {
this.recordDto = recordDto;
this.userInfo = userInfo;
}
public HeaderFooter() {
}
public ShopApplyRecordDto getRecordDto() {
return recordDto;
}
public void setRecordDto(ShopApplyRecordDto recordDto) {
this.recordDto = recordDto;
}
public SysUserInfo getUserInfo() {
return userInfo;
}
public void setUserInfo(SysUserInfo userInfo) {
this.userInfo = userInfo;
}
// 這個方法就是實(shí)現(xiàn)頁眉和頁碼的關(guān)鍵:它的含義是每當(dāng)頁面結(jié)束會執(zhí)行該方法
@Override
public void onEndPage(PdfWriter writer, Document document) {
Font font = null;
try {
font = getPdfChineseFont();
} catch (Exception e) {
e.printStackTrace();
}
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm");
// 設(shè)置頁眉:這里圖省事就用空格來實(shí)現(xiàn)左中右三個位置的頁眉,其實(shí)可以寫三個,通過Element.ALIGN_LEFT來控制頁眉的位置,document.left()/document.top()這兩個可以設(shè)置頁眉具體位置類似于html的上下調(diào)整,大家可以多試試
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_LEFT,
new Phrase("所屬項(xiàng)目:" + recordDto.getMallName() + " 打印時間:" + format.format(new Date()) + " 打印人:" + userInfo.getUserName(), font),
document.left(),
document.top() + 3, 0);
// 獲得一個名為“art”的盒子
Rectangle rect = writer.getBoxSize("art");
// 設(shè)置頁碼:這里的頁碼位置已經(jīng)設(shè)置好,大家可直接使用,至于1/20這種效果的頁碼實(shí)現(xiàn)則十分復(fù)雜,如有需求請自行百度/谷歌
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_CENTER,
new Phrase(String.format("%d", writer.getPageNumber())),
(rect.getLeft() + rect.getRight()) / 2,
rect.getBottom() - 18, 0);
}
public static Font getPdfChineseFont() throws Exception {
BaseFont bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H",
BaseFont.NOT_EMBEDDED);
Font fontChinese = new Font(bfChinese, 12, Font.NORMAL);
fontChinese.setColor(BaseColor.BLACK);
fontChinese.setSize(11);
return fontChinese;
}
}
接下來就很簡單了,將我們的HeaderFooter設(shè)置給PdfWriter對象即可:
// 新建HeaderFooter并傳遞需要的參數(shù)
HeaderFooter headerFooter = new HeaderFooter(recordDto, userInfo);
// 新建一個盒子
Rectangle rect = new Rectangle(36, 54, 559, 788);
// 設(shè)置名稱為“art”,上面get的就是這個盒子了
writer.setBoxSize("art", rect);
writer.setPageEvent(headerFooter);
// 這個可以設(shè)置內(nèi)容的margin
document.setMargins(45f, 45f, 65f, 50f);
7.效果展示

8.總結(jié)
好了,到這里打印PDF文檔就完全實(shí)現(xiàn)了,其實(shí)itext5還有很多功能,比如:文本,圖片,鏈接都可以實(shí)現(xiàn),大家如果有需求可以去官方文檔看看,也可以留言問我,小弟第一篇博客,有什么錯誤希望大家在留言中提出,我好及時改正,免得誤人子弟哈哈。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java web實(shí)現(xiàn)賬號單一登錄,防止同一賬號重復(fù)登錄(踢人效果)
這篇文章主要介紹了Java web實(shí)現(xiàn)賬號單一登錄,防止同一賬號重復(fù)登錄,有點(diǎn)類似于qq登錄踢人效果,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2019-10-10
Java如何將Excel數(shù)據(jù)導(dǎo)入到數(shù)據(jù)庫
這篇文章主要為大家詳細(xì)介紹了Java將Excel數(shù)據(jù)導(dǎo)入到數(shù)據(jù)庫的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-10-10
windows 部署JAVA環(huán)境安裝iDea的詳細(xì)步驟
這篇文章主要介紹了windows 部署JAVA環(huán)境安裝iDea的詳細(xì)步驟,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-08-08
Java中的java.lang.reflect.Type簡介
在 Java 中,java.lang.reflect.Type 是一個接口,代表所有類型的通用超類型,它包括原始類型、參數(shù)化類型、數(shù)組類型、類型變量和基本類型,本文給大家講解Java中的java.lang.reflect.Type是什么,需要的朋友可以參考下2024-06-06

