package com.zy.crm.manager.utils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import org.apache.poi.xwpf.usermodel.*; import org.apache.xmlbeans.XmlCursor; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge; import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import java.io.*; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; //Word操作工具类 public class WordUtils { //生成word合同 public static ResponseEntity generate(String fileName, HashMap map, List> tabParam) throws IOException { // 读取 Word 模板文件 File file = new File(fileName); FileInputStream inputStream = new FileInputStream(file); XWPFDocument document = new XWPFDocument(inputStream); insertTab("{{table}}", document, tabParam); map.put("{{table}}", ""); processParagraphs(map, document); // 将文档写入输出流 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); document.write(outputStream); outputStream.close(); // 创建响应实体,将输出流作为文件内容返回 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.setContentDispositionFormData("attachment", "output.docx"); InputStreamResource resource = new InputStreamResource(new ByteArrayInputStream(outputStream.toByteArray())); return ResponseEntity.ok() .headers(headers) .body(resource); } /** * 处理段落中文本,替换文本中定义的变量; * @param param 需要替换的变量及变量值 * @param document 需要替换的DOC */ public static void processParagraphs(HashMap param, XWPFDocument document) { // 遍历所有段落 for (XWPFParagraph paragraph : document.getParagraphs()) { for (Map.Entry entry : param.entrySet()) { String key = entry.getKey(); String value = entry.getValue().toString(); // 替换段落文本 replaceTextInParagraph(paragraph, key, value); } } // 遍历所有表格 for (XWPFTable table : document.getTables()) { // 遍历表格中的每个单元格 for (XWPFTableRow row : table.getRows()) { for (XWPFTableCell cell : row.getTableCells()) { for (Map.Entry entry : param.entrySet()) { String key = entry.getKey(); String value = entry.getValue().toString(); // 替换表格单元格的文本 replaceTextInParagraph(cell.getParagraphs().get(0), key, value); } } } } } private static void replaceTextInParagraph(XWPFParagraph paragraph, String searchString, String replacementString) { for (XWPFRun run : paragraph.getRuns()) { // 获取段落中的文本 String text = run.getText(0); if (text != null && text.contains(searchString)) { // 使用正则表达式进行替换 Pattern pattern = Pattern.compile(Pattern.quote(searchString)); Matcher matcher = pattern.matcher(text); if (matcher.find()) { String replacedText = matcher.replaceAll(replacementString); // 替换文本 run.setText(replacedText, 0); } } } } /** * 在定位的位置插入表格 */ public static void insertTab(String key, XWPFDocument document, List> param) { List paragraphList = document.getParagraphs(); if (paragraphList != null && paragraphList.size() > 0) { for (XWPFParagraph paragraph : paragraphList) { List runs = paragraph.getRuns(); for (XWPFRun run : runs) { String text = run.getText(0); if (text != null) { if (text.indexOf(key) >= 0) { XmlCursor cursor = paragraph.getCTP().newCursor(); XWPFTable tableOne = document.insertNewTbl(cursor);// ---这个是关键 // String test = "[\n" + // " [\"序号\",\"品名\",\"数量\",\"单位\",\"单价(元)\",\"合计(元)\",\"备注\"],\n" + // " [\"1\",\"自动化立体仓库设备\",\"1\",\"套\",\"130000\",\"130000\",\"备注\"],\n" + // " [\"合计(大写金额):\",\"\",\"\",\"\",\"合计:\",\"\",\"\"]\n" + // "]"; // // JSONArray row = JSON.parseArray(test); // ArrayList> list = new ArrayList<>(); // for (Object o : row) { // ArrayList arrayList = new ArrayList<>(); // JSONArray objects = JSON.parseArray(o.toString()); // for (Object object : objects) { // arrayList.add(object.toString()); // } // list.add(arrayList); // } int rows = param.size(); int cols = param.get(0).size(); for (int i = 0; i < rows; i++) { XWPFTableRow tableRow = null; if (i == 0) { tableRow = tableOne.getRow(i); } else { tableRow = tableOne.createRow(); } for (int j = 0; j < cols; j++) { if (i == 0 && j == 0) { tableRow.getCell(j).setText(param.get(i).get(j)); } else { XWPFTableCell cell = tableRow.getCell(j); if (cell == null) { tableRow.addNewTableCell().setText(param.get(i).get(j)); } else { cell.setText(param.get(i).get(j)); } } } } //合并最后一行单元格 tableOne.getRow(rows - 1).getCell(0).getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART); tableOne.getRow(rows - 1).getCell(1).getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE); tableOne.getRow(rows - 1).getCell(2).getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE); tableOne.getRow(rows - 1).getCell(4).getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART); tableOne.getRow(rows - 1).getCell(5).getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE); } } } } } } public static String formatNumberForAccounting(double number) { if (number == 0) { return "0.00"; } NumberFormat formatter = new DecimalFormat("#,###.00"); return formatter.format(number); } }