需求:导出表格数据到pdf
实现:通过word 模板,设置word 标签,然后word 转pdf 导出
代码:
1.需要的jar包
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.0</version>
</dependency>
<!--doc4j-->
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j</artifactId>
<version>6.1.1</version>
</dependency>
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j-export-fo</artifactId>
<version>6.1.0</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.1</version>
</dependency>
2.创建工具类
package com.gctl.bpm.utils;
import com.gctl.bpm.constant.Constants;
import com.gctl.bpm.vo.PaymentFormTaskVo;
import lombok.experimental.UtilityClass;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBookmark;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@UtilityClass
public class WordTemplate {
public XWPFDocument resolve(InputStream inputStream, Map<String,Object> paramMap) throws Exception {
XWPFDocument doc = new XWPFDocument(OPCPackage.open(inputStream));
for (XWPFTable tbl : doc.getTables()) {
for (XWPFTableRow row : tbl.getRows()) {
for (XWPFTableCell cell : row.getTableCells()) {
for (XWPFParagraph p : cell.getParagraphs()) {
final List<CTBookmark> bookmarkStartList = p.getCTP().getBookmarkStartList();
if(!CollectionUtils.isEmpty(bookmarkStartList)){
final CTBookmark ctBookmark = bookmarkStartList.get(0);
final String bookMarkStartName = ctBookmark.getName();
if(!ObjectUtils.isEmpty(bookMarkStartName)){
XWPFRun run = p.createRun();
run.setFontFamily("宋体");
if(!ObjectUtils.isEmpty(bookMarkStartName)){
run.setText(String.valueOf(paramMap.get(bookMarkStartName)));
}
}
}
}
}
}
}
List<PaymentFormTaskVo> vos = (List<PaymentFormTaskVo>)paramMap.get("tasks");
for (PaymentFormTaskVo taskVo : vos) {
if(Constants.SUBMIT.equalsIgnoreCase(taskVo.getTypeName())){
taskVo.setActivityName(Constants.SUBMIT);
}
}
List<PaymentFormTaskVo> vos2 = vos.stream().filter(vo -> !(ObjectUtils.isEmpty(vo.getActivityName()) || Constants.OVER.equalsIgnoreCase(vo.getActivityName()))).collect(Collectors.toList());
List<String[]> dataList = new ArrayList<>();
vos2.forEach(vo -> {
String[] data = new String[5];
data[0] = vo.getActivityName();
data[1] = vo.getPersonalName();
data[2] = vo.getTypeName();
data[3] = vo.getMessage();
data[4] = DateUtils.formatDate(vo.getCreateTime(),DateUtils.FORMAT_TIME);
dataList.add(data);
});
XWPFTable table = doc.getTables().get(0);
insertTableData(table,dataList);
return doc;
}
public static void insertTableData(XWPFTable table, List<String[]> dataList) throws XmlException, IOException {
for (int i = 15; i < dataList.size() + 15; i++) {
CTRow ctrow = CTRow.Factory.parse(table.getRow(14).getCtRow().newInputStream());
XWPFTableRow newRow = new XWPFTableRow(ctrow, table);
List<XWPFTableCell> cells = newRow.getTableCells();
for (int j = 0; j < cells.size(); j++) {
XWPFTableCell cell = cells.get(j);
XWPFRun run = cell.getParagraphs().get(0).createRun();
run.setText(dataList.get(i - 15)[j]);
run.setFontFamily("宋体");
}
table.addRow(newRow);
}
//删除空白行
table.removeRow(14);
}
}
3.controller
@GetMapping("/pdf")
public void query(HttpServletResponse response,@RequestParam Long paymentId) {
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Disposition", "attachment; fileName=" + URLEncoder.encode(CommonUtils.filePrefix("文件") + ".pdf", StandardCharsets.UTF_8));
response.setHeader("content-Type", "application/pdf");
try {
long start = System.currentTimeMillis();
PaymentFormVo paymentFormVo = paymentService.getPaymentFormVo(paymentId);
XWPFDocument doc = paymentService.buildDoc(paymentFormVo, Constants.TEMPLATE_PATH);
try (OutputStream out = response.getOutputStream()){
ByteArrayOutputStream b = new ByteArrayOutputStream();
doc.write(b);
InputStream inputStream = new ByteArrayInputStream(b.toByteArray());
WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(inputStream);
// 创建字体映射
Mapper fontMapper = new IdentityPlusMapper();
Resource resourceSun = new ClassPathResource("/fonts/simsun.ttc");
String fontPathSun = resourceSun.getURL().toString();
URL urlSun = new URL(fontPathSun);
PhysicalFonts.addPhysicalFonts("SimSun", urlSun);
Resource resourceHei = new ClassPathResource("/fonts/simhei.ttf");
String fontPathHei = resourceHei.getURL().toString();
URL urlHei = new URL(fontPathHei);
PhysicalFonts.addPhysicalFonts("SimHei", urlHei);
fontMapper.put("宋体", PhysicalFonts.get("SimSun"));
fontMapper.put("黑体", PhysicalFonts.get("SimHei"));
mlPackage.setFontMapper(fontMapper);
// 将字体映射设置到PDF转换器中
Docx4J.toPDF(mlPackage, out);
doc.close();
inputStream.close();
out.close();
b.close();
log.info("docx 文档转pdf 耗时:{}" , (System.currentTimeMillis() - start));
} catch (Exception e) {
log.error("docx文档转换为PDF失败", e);
throw new RuntimeException("导出失败");
} finally {
doc.close();
}
} catch (Exception e) {
log.error("导出失败", e);
throw new RuntimeException("导出失败");
}
}