springBoot結合itext pdf實現自定義PDF文件格式導出
背景需求:
????????使用PDF導出指定人員對應周次的打卡記錄,每周對應星期幾打卡過就打“√”。
????????如下圖:
1、導入依賴
? ? ? ? 導入itextpdf依賴
<!-- itex PDF -->
<dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13.3</version>
</dependency>
2、使用代碼自定義導出
? ? ? ?2.1 定義pdf數據vo對象
// vo對象@Dataclass DataVo {/*** 周次*/private String week;/*** 打卡次數*/private int count;/*** 周幾*/private List<Integer> days;}
2.2 itextpdf相關代碼
定義表格的列數,同時定義每列的大小或者格式,然后再依次填充每個單元格數據
注意:需要保證填充每個單元格,即使沒數據也要填充空的數據,否則出現文件格式不對
// itext pdf文件構建@PostMapping("/pdfExport")public void exportPdf(HttpServletResponse response, MyAttendanceStatisticsDto dto) {// 封裝好的業務數據List<DataVo> vos = new ArrayList<>();for (int i = 1; i <= 5; i++) {DataVo vo = new DataVo();vo.setWeek("第"+i+"周");vo.setCount(3);vo.setDays(CollUtil.newArrayList(i,6,7));vos.add(vo);}if(CollUtil.isNotEmpty(vos)) {Rectangle pageSize = PageSize.A4.rotate();Document document = new Document(pageSize);try {String title = "文件名"+ RandomUtil.randomString(5);String fileName = URLEncoder.encode("文件名"+ RandomUtil.randomString(5), "UTF-8");// 設置響應文件類型PDFresponse.setContentType("application/pdf");response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".pdf");// 創建 PdfWriter 實例,將 PDF 內容寫入 HTTP 響應流,1.7版本PdfWriter writer = PdfWriter.getInstance(document, response.getOutputStream());writer.setPdfVersion(PdfWriter.PDF_VERSION_1_7);document.open();// 中文字體BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);Font font = new Font(baseFont, 12);// 添加文檔標題,居中,間距20,添加到文檔中Paragraph pdfTitle = new Paragraph(title, font);pdfTitle.setAlignment(Element.ALIGN_CENTER);pdfTitle.setSpacingAfter(20f);document.add(pdfTitle);// 9 列的表格,寬度占滿整個頁面PdfPTable table = new PdfPTable(9);table.setWidthPercentage(100);// 單獨設置前兩2寬度float[] columnWidths = new float[9];columnWidths[0] = 3f;columnWidths[1] = 2f;for (int i = 2; i < 9; i++) {columnWidths[i] = 1f;}table.setTotalWidth(columnWidths);// 添加帶斜線的單元格PdfPCell splitCell = new PdfPCell();// 綁定斜線事件splitCell.setCellEvent(new DiagonalLineEvent());// 設置單元格高度splitCell.setFixedHeight(30f);Paragraph day = new Paragraph("日", font);day.setAlignment(Element.ALIGN_RIGHT);splitCell.addElement(day);Paragraph month = new Paragraph("周", font);month.setAlignment(Element.ALIGN_LEFT);month.setSpacingBefore(-15f);splitCell.addElement(month);table.addCell(splitCell);// 添加第二列表頭“周打卡數”PdfPCell cell2 = new PdfPCell(new Phrase("周打卡數", font));cell2.setHorizontalAlignment(Element.ALIGN_CENTER);cell2.setVerticalAlignment(Element.ALIGN_MIDDLE);table.addCell(cell2);for (int i = 1; i <= 7; i++) {PdfPCell cell = new PdfPCell(new Phrase(String.valueOf(i), font));cell.setHorizontalAlignment(Element.ALIGN_CENTER);cell.setVerticalAlignment(Element.ALIGN_MIDDLE);table.addCell(cell);}for (DataVo vo : vos) {PdfPCell monthCell = new PdfPCell(new Phrase(vo.getWeek(), font));monthCell.setFixedHeight(20f);monthCell.setHorizontalAlignment(Element.ALIGN_CENTER);monthCell.setVerticalAlignment(Element.ALIGN_MIDDLE);table.addCell(monthCell);PdfPCell totalCell = new PdfPCell(new Phrase(String.valueOf(vo.getCount()), font));totalCell.setHorizontalAlignment(Element.ALIGN_CENTER);totalCell.setVerticalAlignment(Element.ALIGN_MIDDLE);table.addCell(totalCell);List<Integer> days = vo.getDays();for (int i = 1; i <= 7; i++) {PdfPCell cell = null;if (days.contains(i)) {cell = new PdfPCell(new Phrase("√", font));} else {cell = new PdfPCell(new Phrase("", font));}cell.setHorizontalAlignment(Element.ALIGN_CENTER);cell.setVerticalAlignment(Element.ALIGN_MIDDLE);table.addCell(cell);}}document.add(table);} catch (Exception e) {log.error("導出pdf文件"+e);} finally {if (document.isOpen()) {document.close();}}}}
3、測試結果
????????調用接口測試,響應pdf文件打開如下: