模板
生成效果
实现代码
官方文档
引入word依赖
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.10.3</version>
</dependency>
数据准备
Map<String, Object> dataObj = new HashMap<>();
// 水质折线图
if (wqDataMap != null && !wqDataMap.isEmpty()) {
Set<Long> keySet = wqDataMap.keySet();
if (keySet != null && keySet.size() > 0) {
int index = 0;
String wqTitle = "";
// 区块对
List<Map<String, Object>> wqSections = new ArrayList<Map<String, Object>>();
// totalWqCod totalWqNhn
ChartMultiSeriesRenderData totalCodLine = new ChartMultiSeriesRenderData();
totalCodLine.setChartTitle("cod");
ChartMultiSeriesRenderData totalNhnLine = new ChartMultiSeriesRenderData();
totalNhnLine.setChartTitle("nhn");
List<SeriesRenderData> codSeriesRenderDatas = new ArrayList<SeriesRenderData>();
List<SeriesRenderData> nhnSeriesRenderDatas = new ArrayList<SeriesRenderData>();
for (Long sid : keySet) {
Map<String, Object> data = new HashMap<String, Object>();
index++;
wqTitle = stationMap.get(sid);
List<StandardWaterQualityVo> wqlist = wqDataMap.get(sid);
ArrayList<String> timeList = new ArrayList<String>();
ArrayList<Double> nhnList = new ArrayList<Double>();
ArrayList<Double> codList = new ArrayList<Double>();
for (StandardWaterQualityVo vo : wqlist) {
timeList.add(sdf.format(vo.getCollectTime()));
nhnList.add(vo.getNhn());
codList.add(Double.valueOf(String.valueOf(vo.getCod())));
}
// 总图
if (index == 1 || timeList.size() > wqTimeListSize) {
totalCodLine.setCategories(timeList.toArray(new String[wqTimeListSize]));// 类别
totalNhnLine.setCategories(timeList.toArray(new String[wqTimeListSize]));// 类别
}
codSeriesRenderDatas
.add(new SeriesRenderData(wqTitle, codList.toArray(new Double[wqTimeListSize])));
nhnSeriesRenderDatas
.add(new SeriesRenderData(wqTitle, nhnList.toArray(new Double[wqTimeListSize])));
// 分图
ChartMultiSeriesRenderData codLine = new ChartMultiSeriesRenderData();
codLine.setChartTitle(wqTitle + "cod");
codLine.setCategories(timeList.toArray(new String[timeList.size()]));// 类别
List<SeriesRenderData> seriesRenderDatas1 = new ArrayList<SeriesRenderData>();
seriesRenderDatas1.add(new SeriesRenderData("cod", codList.toArray(new Double[codList.size()])));
codLine.setSeriesDatas(seriesRenderDatas1);
ChartMultiSeriesRenderData nhnLine = new ChartMultiSeriesRenderData();
nhnLine.setChartTitle(wqTitle + "nhn");
nhnLine.setCategories(timeList.toArray(new String[timeList.size()]));// 类别
List<SeriesRenderData> seriesRenderDatas2 = new ArrayList<SeriesRenderData>();
seriesRenderDatas2.add(new SeriesRenderData("nhn", nhnList.toArray(new Double[nhnList.size()])));
nhnLine.setSeriesDatas(seriesRenderDatas2);
data.put("wqCod", codLine);
data.put("wqNhn", nhnLine);
data.put("wqTitle", "1." + index + "." + wqTitle);
wqSections.add(data);
}
totalCodLine.setSeriesDatas(codSeriesRenderDatas);
totalNhnLine.setSeriesDatas(nhnSeriesRenderDatas);
dataObj.put("wqTimeStr", wqTimeStr);
dataObj.put("wqSections", wqSections);
dataObj.put("totalWqNhn", totalNhnLine);
dataObj.put("totalWqCod", totalCodLine);
}
}
// 污水图像识别
if (monitorDataMap != null && !monitorDataMap.isEmpty()) {
Set<Long> mKeySet = monitorDataMap.keySet();
if (mKeySet != null && mKeySet.size() > 0) {
int mIndex = 0;
String monitorTitle = "";
// 区块对
List<Map<String, Object>> monitorSections = new ArrayList<Map<String, Object>>();
for (Long mId : mKeySet) {
Map<String, Object> data = new HashMap<String, Object>();
List<Map<String, Object>> monitorPhotoSections = new ArrayList<Map<String, Object>>();
List<RecordDatasVo> monitorList = monitorDataMap.get(mId);
mIndex++;
monitorTitle = stationMap.get(mId);
if (monitorList != null && monitorList.size() > 0) {
for (RecordDatasVo vo : monitorList) {
String propName = vo.getPropName();
String propValue = vo.getPropValue();
if (propName.equals("photo")) {
try {
Map<String, Object> data0 = new HashMap<String, Object>();
Date collectTime = vo.getCollectTime();
// 获取图片
String bucket = minioProperties.getBucketName();
String dir = propValue;
if (dir.length() > 0 && dir.startsWith("/")) {
dir = dir.substring(1);
log.info(dir);
}
S3Object object = minioTemplate.getObject(bucket, dir);
// minioTemplate.getSingleObjectStream(bucket, dir, fileInputStream);
// data0.put("monitorPhoto", Pictures.ofStream(new FileInputStream("temp" +
// propValue))
// .size(528, 297).create());
data0.put("monitorPhoto",
Pictures.ofStream(object.getObjectContent()).size(528, 297).create());
monitorPhotoSections.add(data0);
} catch (Exception e) {
// TODO Auto-generated catch block
log.info("@monitorPhotoError:" + propValue + "{}", e);
e.printStackTrace();
}
}
}
data.put("monitorTitle", "2." + mIndex + "." + monitorTitle);
data.put("monitorPhotoSections", monitorPhotoSections);
monitorSections.add(data);
}
}
dataObj.put("monitorSections", monitorSections);
}
导出
String path = "";
// 第一种:获取类加载的根路径
path = this.getClass().getResource("/").getPath();
System.out.println(path);
XWPFTemplate template = XWPFTemplate.compile(path + "temp\\template.docx").render(dataObj);
FileOutputStream out;
try {
out = new FileOutputStream("I:/template0.docx");
template.write(out);
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition",
"attachment;filename=" + new SimpleDateFormat("yyyyMMddHHmm").format(new Date()) + ".docx");
response.setContentType("application/octet-stream;charset=utf-8");
OutputStream ouputStream = response.getOutputStream();
template.write(ouputStream);
ouputStream.flush();
ouputStream.close();
template.close();
踩坑
- 生成图表只出现打印地址
如:com.deepoove.poi.data.ChartMultiSeriesRenderData.对象地址
解决:图表为引用标签,需要在模板文件中提前插入图表并且设置 可替换文字为{{String}}格式的引用标签即可 - 生成图片不显示没效果
控制台打印以下信息:The data [null] of the template {{@monitorPhoto}} is illegal, will apply
解决:
模板文档中图表标签要以@开头作为标识,但代码中组织数据结构是不需要加@符,只需要后面的文字 标识
-
多系列图表中categories和seriesDatas子集数组长度需要一致否则会报错
错误信息:TemplateRenderPolicy render error
Category and values must have the same point count. -
模板文档中部分标题文字的自定义的格式,可能会使生成的文档格式错乱。列表标题或是自动生成目录都可能存在格式错乱。建议{{标签}}暂时先别使用格式,效果实现后再添加word格式。
-
区块对标签:{{?sections}}{{/sections}},存在多重循环时数据可以嵌套叠加使用