EasyPOI导出Word以及获取classpath

@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);
        }

    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yzhSWJ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值