@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"
]
]
}