前言
最近拿到一个这样开发需求,每个公司都会有自己的合同模版,模版的内容需要来源于线上数据,也就是我们标题所理解的填充。
一、模版图
二、效果图
特此说明:上述模版内容均为测试数据,不具备任何真实性。
三、代码实现
3.1maven依赖
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.5.7</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-excelant</artifactId>
<version>3.12</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.12</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.8</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.8</version>
</dependency>
3.2核心工具类
public void exportWord(String contractId, String bizId,HttpServletResponse response) throws Exception {
ContractInfoVo contractInfoVo = remoteContractInfoService.getById(contractId).getData();
if (Objects.nonNull(contractInfoVo)){
new ZsqyException("合同数据异常");
}
List<CAttachment> list = attachmentService.list(
new LambdaQueryWrapper<CAttachment>()
.eq(CAttachment::getBizId, bizId));
if (list.size() == 0) {
new ZsqyException("当前模版数据下未上传模版文件");
}
CAttachment attachment = list.get(0);
InputStream inputStream = minioUtil.download(attachment.getFilePath(), attachment.getFileMd5Name());
Map<String, String> pamraMap =getValueMap(contractInfoVo);
XWPFDocument document = new XWPFDocument(inputStream);
Iterator<XWPFParagraph> itPara = document.getParagraphsIterator();
List<XWPFParagraph> paragraphList=new ArrayList<>();
while (itPara.hasNext()) {
XWPFParagraph paragraph = (XWPFParagraph) itPara.next();
List<XWPFRun> runs = paragraph.getRuns();
for (int i = 0; i < runs.size(); i++) {
String oneparaString = runs.get(i).getText(runs.get(i).getTextPosition());
if (StringUtils.isBlank(oneparaString)){
continue;
}
oneparaString=oneparaString.trim();
for (Map.Entry<String, String> entry : pamraMap.entrySet()) {
if (oneparaString.contains(entry.getKey())) {
oneparaString = oneparaString.replace(entry.getKey(), entry.getValue());
}
}
runs.get(i).setText(oneparaString, 0);
}
paragraphList.add(paragraph);
}
replaceWordText(paragraphList,pamraMap);
response.reset();
response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(contractInfoVo.getContractName()+".docx", "UTF-8"));
response.setContentType("application/octet-stream");
OutputStream out = response.getOutputStream();
document.write(out);//将word对象内容写入输出流
}
public Map<String, String> getValueMap(ContractInfoVo contractInfoVo){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Map<String, String> map=new HashMap<>();
map.put("${
{合同简称}}", isEmpty(contractInfoVo.getContractName()));
........
return map
}
代码解读
1.查询业务数据
2.从minio中获取模版文件
3.将文档中的输入流放入XWPFDocument对象中解析,拿到具体的行对象
4.拿到行对象后遍历,匹配占位符(${xx})。
5.占位符内容替换成功,输出流,浏览器下载。