springBoot结合itext pdf实现自定义PDF文件格式导出
背景需求:
使用PDF导出指定人员对应周次的打卡记录,每周对应星期几打卡过就打"√"。
如下图:

1、导入依赖
导入itextpdf依赖
XML
<!-- itex PDF -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.3</version>
</dependency>
2、使用代码自定义导出
2.1 定义pdf数据vo对象
java
// vo对象
@Data
class DataVo {
/**
* 周次
*/
private String week;
/**
* 打卡次数
*/
private int count;
/**
* 周几
*/
private List<Integer> days;
}
2.2 itextpdf相关代码
定义表格的列数,同时定义每列的大小或者格式,然后再依次填充每个单元格数据
注意:需要保证填充每个单元格,即使没数据也要填充空的数据,否则出现文件格式不对
java
// 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");
// 设置响应文件类型PDF
response.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文件打开如下:
