替换word中的excel

复制代码
@PostMapping("/make/report/target/performance/first")
public AjaxResult makeTargetReportFirst(@RequestBody MakeReportDTO makeReportDTO) {
    Map<String, String> textReplaceMap = new HashMap<>();

    // 替换日期
    LocalDateTime nowData = LocalDateTime.now();
    DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
    textReplaceMap.put("${nowDate}", nowData.format(dateFormatter));

    String templatePath = uploadPklExcelPath + "template1.docx";
    String directoryPath = fileUploadDir;

    try {
        if (!Files.exists(Paths.get(directoryPath))) {
            Files.createDirectories(Paths.get(directoryPath));
        }

        try (InputStream is = new FileInputStream(templatePath);
             XWPFDocument doc = new XWPFDocument(is)) {

            // 替换普通文本占位符(段落和表格内文本)
            replaceTextPlaceholders(doc, textReplaceMap);

            List<List<String>> excelData = makeReportDTO.getExcelData();
            if (excelData == null || excelData.isEmpty()) {
                return AjaxResult.error("excelData不能为空");
            }

            // 替换表格内容,按列替换,且新增行
            replaceTableDataByColumns(doc, excelData);

            // 生成唯一文件名
            String fileName = generateUniqueFileName();
            String outPath = directoryPath + fileName;

            try (OutputStream os = new FileOutputStream(outPath)) {
                doc.write(os);
            }

            return AjaxResult.success(outPath);
        }
    } catch (FileNotFoundException e) {
        return AjaxResult.error("文件未找到:" + e.getMessage());
    } catch (Exception e) {
        e.printStackTrace();
        return AjaxResult.error("报告生成失败:" + e.getMessage());
    }
}

    private void replaceTextPlaceholders(XWPFDocument doc, Map<String, String> replaceMap) {
        // 替换段落中的占位符
        doc.getParagraphs().forEach(paragraph -> {
            paragraph.getRuns().forEach(run -> {
                String text = run.getText(0);
                if (text != null) {
                    for (Map.Entry<String, String> entry : replaceMap.entrySet()) {
                        if (text.contains(entry.getKey())) {
                            run.setText(text.replace(entry.getKey(), entry.getValue()), 0);
                        }
                    }
                }
            });
        });

        // 替换表格中的占位符
        doc.getTables().forEach(table -> {
            table.getRows().forEach(row -> {
                row.getTableCells().forEach(cell -> {
                    cell.getParagraphs().forEach(paragraph -> {
                        paragraph.getRuns().forEach(run -> {
                            String text = run.getText(0);
                            if (text != null) {
                                for (Map.Entry<String, String> entry : replaceMap.entrySet()) {
                                    if (text.contains(entry.getKey())) {
                                        run.setText(text.replace(entry.getKey(), entry.getValue()), 0);
                                    }
                                }
                            }
                        });
                    });
                });
            });
        });
    }

    private void replaceTableDataByColumns(XWPFDocument doc, List<List<String>> excelData) {
        if (doc.getTables().isEmpty()) {
            throw new IllegalArgumentException("模板中没有表格");
        }

        XWPFTable table = doc.getTables().get(0);

        // 求最大行数
        int maxRowCount = excelData.stream()
                .mapToInt(List::size)
                .max()
                .orElse(0);

        int templateRowCount = table.getNumberOfRows();

        // 不够行就新增
        for (int i = templateRowCount; i < maxRowCount; i++) {
            table.createRow();
        }

        for (int col = 0; col < excelData.size(); col++) {
            List<String> colData = excelData.get(col);

            for (int row = 0; row < maxRowCount; row++) {
                XWPFTableRow tableRow = table.getRow(row);

                // 设置固定高度为 5mm(约 284 Twips)
                tableRow.setHeight(284);
                tableRow.setHeightRule(TableRowHeightRule.EXACT);

                // 确保当前行有对应列单元格
                while (tableRow.getTableCells().size() <= col) {
                    tableRow.createCell();
                }

                XWPFTableCell cell = tableRow.getCell(col);

                // 清空旧内容
                cell.removeParagraph(0);

                // 写入新文本并设置字体样式为小四宋体(12pt)
                XWPFParagraph paragraph = cell.addParagraph();
                XWPFRun run = paragraph.createRun();
                String text = row < colData.size() ? colData.get(row) : "";
                run.setText(text);
                run.setFontFamily("宋体");
                run.setFontSize(10); // 小四:12pt
            }
        }
    }

    private String generateUniqueFileName() {
        long timestamp = System.currentTimeMillis();
        int randomNum = new Random().nextInt(10000);
        return timestamp + "_" + randomNum + ".docx";
    }


复制代码
{
	"excelData": [
		[
			"水用量",
			"水泥用量",
			"水泥-种类",
			"水泥-细度",
			"水泥-28天抗压强度",
			"矿粉用量",
			"矿粉-细度",
			"矿粉-28天活性指数",
			"粉煤灰用量",
			"粉煤灰-细度",
			"粉煤灰-28天活性指数",
			"砂用量",
			"砂-细度",
			"砂-石粉含量",
			"石用量",
			"石-含泥量",
			"石-压碎指标值",
			"减水剂用量",
			"减水剂-含固量",
			"减水剂-水泥净浆流动度",
			"增效剂用量",
			"坍落度",
			"3天抗压强度",
			"7天抗压强度",
			"28天抗压强度"
		],
		[
			"150",
			"145",
			"0",
			"1.6",
			"57.7",
			"50",
			"3.9",
			"106",
			"90",
			"32.4",
			"73",
			"895",
			"2.84",
			"9.40",
			"1010",
			"0.92",
			"0",
			"10",
			"11.5",
			"190",
			"1.43",
			"205",
			"22.5",
			"31.8",
			"47.6"
		]

	]
}
相关推荐
灵犀学长25 分钟前
基于 Spring ThreadPoolTaskScheduler + CronTrigger 实现的动态定时任务调度系统
java·数据库·spring
chatexcel2 小时前
AI知识库教程:基于ChatExcel实现规则文档、Excel数据与业务分析联动
人工智能·excel
好家伙VCC2 小时前
【无标题】
java
小碗羊肉3 小时前
【JavaWeb | 第十一篇】文件上传(本地&阿里云OSS)
java·阿里云·servlet
吾疾唯君医3 小时前
Java SpringBoot集成积木报表实操记录
java·spring boot·spring·导出excel·积木报表·数据文件下载
Yana.nice3 小时前
Excel中以当前列的数值作为查找条件,查找匹配的行
excel
Byron Loong3 小时前
【c++】为什么有了dll和.h,还需要包含lib
java·开发语言·c++
hexu_blog4 小时前
vue+java实现图片批量压缩
java·前端·vue.js
头歌实践平台4 小时前
Hadoop开发环境搭建
java·大数据·hadoop
Seven974 小时前
一致性Hash算法:如何实现分布式系统中的高效数据分片?
java