最近公司有需求,需要实现数据打印功能。需要将数据填充到对应的模板文件数据,并将word转成pdf流传给前端。其中呢数据的渲染使用了 poi-tl Java Word 的模板引擎,转pdf使用到了Free Spire.Doc for Java 产品(免费java word组件)
poi-tl Word 模板引擎
poi-tl 是一个Word 模板引擎,基于 Microsoft Word 模板和数据生成新的文档,并且支持用户自定义函数,函数可以在 Word 模板的任何位置执行。
导入依赖:
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.10.0</version>
</dependency>
具体的使用可以去查相关的文档,比较简单,只需定义要你的模板,查询对应的数据出来
1、简单的测试代码
public static void main(String[] args) throws IOException {
Map<String, Object> map = new HashMap<>();
//销售门店
map.put("storeName", "销售门店AAA");
//手机号码
map.put("phone","15880919255");
//委托书.docx是模板路径
XWPFTemplate.compile("D://委托书.docx",config)
.render(map)
//A委托书.docx是写入的路径
.writeToFile("D://A委托书.docx");
}
委托书.docx模板设置如下图
2、如果模板中有需要打印多行list的 则需要像以下这样设置
public static void main(String[] args) throws IOException {
/*文本*/
Map<String, Object> map = new HashMap<>();
//销售门店
map.put("storeName", "销售门店AAA");
//手机号码
map.put("phone","15880919255");
//定义一个list去存数据
List<Map<String, Object>> list= Lists.newArrayList();
for (int i = 0; i < 39; i++) {
Map<String, Object> data = new HashMap<>();//通过map存放要填充的数据
data.put("Xh", i + 1);
data.put("name", "四川有限公司" + i);
data.put("time", i + 10 + "小时");
data.put("size", "800" + i);
list.add(data);
}
//将list设置到模板的数据中 list为模板中的值
map.put("list", list);
//设置了一个自定义的表格渲染策
HackLoopTableRenderPolicy policy = new HackLoopTableRenderPolicy();
//将上面创建的 HackLoopTableRenderPolicy 对象与字符串标识符 "list" 绑定
Configure config = Configure.newBuilder().bind("list", policy).build();
//委托书.docx是模板路径
XWPFTemplate.compile("D://委托书.docx",config)
.render(map)
//A委托书.docx是写入的路径
.writeToFile("D://A委托书.docx");
}
创建一个名为 HackLoopTableRenderPolicy 的实例,这是一个自定义实现的表格渲染策略类。这个类可能用于处理循环列表或其他迭代结构在渲染成文档时的行为,例如控制表格样式、布局或者处理复杂的数据结构。
导出list的模板如下:
2、Word转pdf
使用Free Spire.Doc for Java 工具
对应文档链接:https://www.e-iceblue.cn/Downloads/Free-Spire-Doc-JAVA.html
导入依赖:
可以通过maven仓库安装,也可以自行下载安装
<repositories>
<repository>
<id>com.e-iceblue</id>
<name>e-iceblue</name>
<url>https://repo.e-iceblue.cn/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.doc.free</artifactId>
<version>5.2.0</version>
</dependency>
</dependencies>
示例:
public static void main(String[] args) {
//加载Word示例文档
Document document =new Document();
document.loadFromFile("D://A委托书.docx");
//保存结果文档
document.saveToFile("D://最终委托书.pdf", FileFormat.PDF);
}
以下是对应开发的接口代码如下:
package com.yzqc.erp.controller.web;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.plugin.table.HackLoopTableRenderPolicy;
import com.google.common.collect.Lists;
import com.spire.doc.*;
import com.yzqc.common.core.enums.MinioBucketsEnum;
import com.yzqc.common.core.utils.SecurityUtils;
import com.yzqc.common.core.web.controller.BaseController;
import com.yzqc.erp.config.properties.ApplicationProperties;
import com.yzqc.erp.model.mtOrderItemTime.MtOrderItemTimeExport;
import com.yzqc.erp.model.mtOrderTime.MtOrderExportInfo;
import com.yzqc.erp.service.IMtOrderTimeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@Api(value = "/mtPdf", tags = "打印")
@RequestMapping("/mtPdf")
public class MtPdfController extends BaseController {
@Autowired
private ApplicationProperties applicationProperties;
@DubboReference(version = "${dubbo.application.version}")
private IMtOrderTimeService mtOrderTimeService;
@ApiOperation(value = "导出委托书Word模板")
@GetMapping(value = "/exportDocx/{id}")
public void exportDocx(HttpServletResponse response, @PathVariable("id") String id, Date createTime) throws Exception {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
String fileName = URLEncoder.encode("委托书", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
//获取模板
//获取模板
String FileName = "委托书.docx";
// 获取到文件服务器上面的文件
String path = applicationProperties.getDomain() + "/" + MinioBucketsEnum.SYSTEM.getBucketName() + "/" + SecurityUtils.getGroupId() + "/" + FileName;
//临时文件存放路径
String filePath = System.getProperty("user.dir") + File.separator + SecurityUtils.getUserId() + "temp.docx";
//获取到http的文件流
URL url = new URL(path);
Resource resource = new UrlResource(url);
try (InputStream inputStream = resource.getInputStream();
OutputStream outputStream = response.getOutputStream()) {
//定义两个list数据
HackLoopTableRenderPolicy policy = new HackLoopTableRenderPolicy();
Configure config = Configure.newBuilder().bind("itemList", policy)
.bind("goodsList",policy)
.build();
//获取本次模板需要用到的数据信息
MtOrderExportInfo exportInfo = mtOrderTimeService.selectExportInfo(id, createTime, SecurityUtils.getGroupId(), SecurityUtils.getUserId());
//将数据信息的实体类转成map数据
Map<String, Object> map = convert(exportInfo);
//获取施工项目list
List<MtOrderItemTimeExport> itemInfoList = exportInfo.getItemInfoList();
List<Map<String, Object>> itemList= Lists.newArrayList();
if(CollectionUtils.isNotEmpty(itemInfoList)){
itemInfoList.forEach(u->{
Map<String, Object> dataMap = convert(u);
itemList.add(dataMap);
});
}
//获取商品项目list
List<MtOrderItemTimeExport> goodsItemInfoList = exportInfo.getGoodsItemInfoList();
List<Map<String, Object>> goodsList= Lists.newArrayList();
if(CollectionUtils.isNotEmpty(goodsItemInfoList)){
goodsItemInfoList.forEach(u->{
Map<String, Object> dataMap = convert(u);
goodsList.add(dataMap);
});
}
//将两个list 传入数据集合中
map.put("itemList",itemList);
map.put("goodsList",goodsList);
//处理模板
XWPFTemplate template = XWPFTemplate.compile(inputStream,config)
.render(map);
//写入到临时文件中
template.writeToFile(filePath);
template.close();
// 创建一个新的Word文档
Document document = new Document();
//加载要处理的文件
document.loadFromFile(filePath);
//将其转换成pdf流 并传给接口中
document.saveToStream(outputStream,FileFormat.PDF);
//临时文件需要删除掉
File file = new File(filePath);
if (file.exists()) {
file.delete();
}
} catch (Exception e) {
e.printStackTrace();
}
}
//实体类转map
public static Map<String, Object> convert(Object entity) {
Map<String, Object> map = new HashMap<>();
Field[] fields = entity.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
try {
map.put(field.getName(), field.get(entity));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return map;
}
}
模板如图:
最终效果: