@Override
public void downloadStatisticDataWithEasyPOI(Map<String, Object> query, HttpServletResponse response) {
try {
// 1. 加载classpath下的模板为输入流(兼容JAR内资源)
ClassPathResource templateResource = new ClassPathResource("data_template.docx");
InputStream templateIs = templateResource.getInputStream();
List<DataVO> data = dataDao.statisticData(query);
if (data.isEmpty()) {
log.error("没有数据可导出");
return;
}
data.forEach(dataVO -> {
String computeValueStr = dataVO.getComputeValue();
// 若字符串以“.0”结尾,则去掉末尾的“.0”
if (computeValueStr != null && computeValueStr.endsWith(".0")) {
computeValueStr = computeValueStr.substring(0, computeValueStr.length() - 2);
dataVO.setComputeValue(computeValueStr);
}
});
// 分组并保持原始顺序
Map<String, Map<String, Map<String, List<DataVO>>>> collect = data.stream()
.collect(Collectors.groupingBy(
DataVO::getUnitType, // 第一层:按unitType分组
LinkedHashMap::new, // 第一层Map用LinkedHashMap保持顺序
Collectors.groupingBy(
DataVO::getUnitName, // 第二层:按unitName分组
LinkedHashMap::new, // 第二层Map用LinkedHashMap保持顺序
Collectors.groupingBy(
// 第三层:按组合字段分组
dataVO -> dataVO.getItemZhName() + dataVO.getComputeValue() + dataVO.getItemUnit(),
LinkedHashMap::new, // 第三层Map用LinkedHashMap保持顺序
Collectors.toList() // 最终收集为List<DataVO>
)
)
));
Map<String, Object> params = new HashMap<String, Object>();
String queryTime = formatDateRange(query.get("startDate").toString(), query.get("endDate").toString());
params.put("queryTime", queryTime);
// 2. 用InputStream构建XWPFDocument(核心:把流转成EasyPOI支持的XWPFDocument)
MyXWPFDocument xwpfDocument = new MyXWPFDocument(templateIs);
WordExportUtil.exportWord07(xwpfDocument , params);
// ========== 核心新增:手动添加带样式的文本(替代模板标签) ==========
// 1. 可选:先添加一个标题(比如“用户信息列表”)
XWPFParagraph titlePara = xwpfDocument.createParagraph();
XWPFRun titleRun = titlePara.createRun();
titleRun.setText("一、数据监测情况"); // 标题文本
titleRun.setBold(true); // 标题加粗
titleRun.setFontSize(16); // 标题字号
titleRun.setFontFamily("宋体"); // 中文宋体,避免乱码
titlePara.setSpacingAfter(10); // 标题和内容间距
// 2. 遍历数据,逐个添加带样式的文本行
// 按单位类型 酒店,景区等
collect.forEach((unitType, unitNameList) -> {
addText(xwpfDocument, unitType, "");
//按单位名称
unitNameList.forEach((unitName, itemDataList) -> {
StringBuilder stringBuilderItem = new StringBuilder();
// 填报数据项
itemDataList.forEach((itemName, dataList) -> {
// 数据项名称
stringBuilderItem.append(itemName).append(",");
// 填报数项目子项目
for (DataVO dataVO : dataList) {
String cItemZhName = dataVO.getCItemZhName();
//hotel_loding_ratio入住率,yoy_growth_edit-同比增
String cItemEnName = dataVO.getCItemEnName();
if ("hotel_loding_ratio".equals(cItemEnName)) {
// 直接拼接,不判断数值是否为空
stringBuilderItem.append(cItemZhName)
.append(dataVO.getHotelLoadingRatio()).append("%").append(",");
} else if ("yoy_growth_edit".equals(cItemEnName)) {
// 不判断yoyChangeDesc是否为空,直接拼接(即使为空也会加逗号)
String yoyGrowthEdit = dataVO.getYoyGrowthEdit();
String yoyChangeDesc = getYoyChangeDesc(yoyGrowthEdit, true);
if (StrUtil.isNotBlank(yoyChangeDesc)) {
stringBuilderItem.append(cItemZhName)
.append(yoyChangeDesc).append(",");
}
}
}
});
// 仅处理「末尾逗号→替换为句号」的核心逻辑
String finalContent = "";
if (stringBuilderItem.length() > 0) {
// 删除最后一个逗号(即使中间有连续逗号,也只删末尾)
stringBuilderItem.deleteCharAt(stringBuilderItem.length() - 1);
// 末尾加句号
stringBuilderItem.append("。");
finalContent = stringBuilderItem.toString();
}
addText(xwpfDocument, unitName, finalContent);
});
});
// ==============================================================
// 3. 原有响应逻辑(完全不变)
String filename = "经开区假期旅游市场情况.docx";
response.setHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes(), "ISO8859-1"));
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
ServletOutputStream outputStream = response.getOutputStream();
xwpfDocument.write(outputStream);
// 关闭流,避免泄漏
outputStream.flush();
outputStream.close();
xwpfDocument.close();
templateIs.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
EasyPOI导出Word以及获取classpath
最新推荐文章于 2026-06-05 15:53:11 发布

1万+

被折叠的 条评论
为什么被折叠?



