1. 程式人生 > 程式設計 >Java使用itext5實現PDF表格文件匯出

Java使用itext5實現PDF表格文件匯出

最近拿到一個需求,需要匯出PDF文件,市面上可以實現的方法有很多,經過測試和調研決定使用itext5來實現,話不多說,說幹就幹。

1.依賴匯入

<!-- 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>

這裡說明下:上面的依賴就是主要實現PDF生成的,下面的依賴是中文字型相關依賴;

2.PDF表格匯出實現

1.匯出PDF

//   1.開啟文件並設定基本屬性
   Document document = new Document();
//   2.設定請求頭,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例項寫出到瀏覽器
   PdfWriter writer = PdfWriter.getInstance(document,response.getOutputStream());
 

至此匯出PDF已經實現了,只是這個PDF中什麼內容都沒有,明白這一點,接下來做的就是給這個文件“加料”咯(這裡的response就是HttpServletResponse)。

2.頁面美化

//    這裡的wirter就是上文的writer
   writer.setViewerPreferences(PdfWriter.PageModeUseThumbs);
   writer.setPageSize(PageSize.A4);
 

這裡設定了文件的顯示縮圖以及文件大小為A4;

3.中文字型設定

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;
 }
 

這個方法設定了中文字型樣式,感興趣的同學可以試試其他的樣式,例如:字型顏色,大小,字型都可以修改;

4.輸出表格內容到文件

// 首先開啟文件
document.open();
// 向文件中新增表格資料
private static void printBasicInfo(ShopApplyRecordDto recordDto,Document document,Font font) throws DocumentException {
// 表格中的資料
  Object[][] basicDatas = {
    {"標題","xxx申請","審批編號","1234"},{"申請人","小明","申請商鋪","xxx商場"},{"申請日期","2020/1/16","審批結果","同意")}};
// 每個cell的寬度
  float[] widthss = {50,200,50,200};
//   建立一個表格,每一行有四個cell
  PdfPTable basicTable = new PdfPTable(widthss);
// 外層迴圈表格的行
  for (int i = 0; i < basicDatas.length; i++) {
// 內層迴圈每一行具體資料
   for (int j = 0; j < basicDatas[i].length; j++) {
//   新建一個cell
    PdfPCell cell = new PdfPCell();
// 這個方法是統一設定表格和cell的樣式,下面會寫 
    setTableStyle(basicTable,cell);
// cell中需要填充資料的格式
    Paragraph paragraph = 
    new Paragraph(StrUtil.toString(basicDatas[i][j]),font);
// 設定cell的值
    cell.setPhrase(paragraph);
// 將cell新增到表格中
    basicTable.addCell(cell);
   }
  }
// 將表格新增到文件中
  document.add(basicTable);
 }
// 結束時要關閉文件
document.close();
 

大功告成,現在匯出的PDF中已經有了類似這樣的表格了:

當然你的樣式會很醜,接下來我們來設定下樣式。

5.表格和cell樣式設定

public static void setTableStyle(PdfPTable table,PdfPCell cell) {
// 設定表格樣式
  table.setLockedWidth(true);
  table.setTotalWidth(500);
  table.setHorizontalAlignment(Element.ALIGN_LEFT);
// 設定單元格樣式
  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方法還是比較易懂的,這裡就不多贅述了,不明白的自己設定試試就可以做出自己喜歡的樣式咯。

6.頁首和頁碼的設定

這裡說明下,itext2和itext5的api有很大不同,2的版本有一個專門的HeaderFooter類來設定樣式,5的版本沒有這樣的類,取而代之的是PdfPageEventHelper這樣一個事件處理類,這裡大家千萬別弄混了,這兩個版本的api互相不相容;
這裡首先寫一個PdfPageEventHelper的子類來實現頁首頁碼的列印:

public class HeaderFooter extends PdfPageEventHelper {
// 這裡是業務相關的屬性可以無視
 private ShopApplyRecordDto recordDto;
 private SysUserInfo userInfo;
// 大部分情況下頁首的值是動態的,這裡可以在初始化的時候進行引數傳遞
 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;
 }
// 這個方法就是實現頁首和頁碼的關鍵:它的含義是每當頁面結束會執行該方法
 @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");
// 設定頁首:這裡圖省事就用空格來實現左中右三個位置的頁首,其實可以寫三個,通過Element.ALIGN_LEFT來控制頁首的位置,document.left()/document.top()這兩個可以設定頁首具體位置類似於html的上下調整,大家可以多試試
  ColumnText.showTextAligned(writer.getDirectContent(),Element.ALIGN_LEFT,new Phrase("所屬專案:" + recordDto.getMallName() + "             列印時間:" + format.format(new Date()) + "         列印人:" + userInfo.getUserName(),font),document.left(),document.top() + 3,0);
// 獲得一個名為“art”的盒子 
  Rectangle rect = writer.getBoxSize("art");
// 設定頁碼:這裡的頁碼位置已經設定好,大家可直接使用,至於1/20這種效果的頁碼實現則十分複雜,如有需求請自行百度/谷歌
  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",Font.NORMAL);
  fontChinese.setColor(BaseColor.BLACK);
  fontChinese.setSize(11);
  return fontChinese;
 }
}
 
接下來就很簡單了,將我們的HeaderFooter設定給PdfWriter物件即可:

// 新建HeaderFooter並傳遞需要的引數
HeaderFooter headerFooter = new HeaderFooter(recordDto,userInfo);
// 新建一個盒子
Rectangle rect = new Rectangle(36,54,559,788);
// 設定名稱為“art”,上面get的就是這個盒子了
writer.setBoxSize("art",rect);
writer.setPageEvent(headerFooter);
// 這個可以設定內容的margin
document.setMargins(45f,45f,65f,50f);
 

7.效果展示

8.總結

好了,到這裡列印PDF文件就完全實現了,其實itext5還有很多功能,比如:文字,圖片,連結都可以實現,大家如果有需求可以去官方文件看看,也可以留言問我,小弟第一篇部落格,有什麼錯誤希望大家在留言中提出,我好及時改正,免得誤人子弟哈哈。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。