zoukankan      html  css  js  c++  java
  • Word动态替换文本

     1 public class WordTest2 {
     2     public static void main(String[] args) {
     3 
     4         /** 此Map存放动态替换的内容,key-Word中定义的变量,value-要替换的内容 **/
     5         Map map = Maps.newHashMap();
     6         map.put("CL_XT_zlContractNo", "55555556444444888544");
     7         map.put("LOAN_memberName", "小赵");
     8         map.put("LOAN_certNo", "1234568524545");
     9         map.put("LOAN_address", "重庆市沙坪坝积极");
    10         map.put("LOAN_mobileNo", "110110110");
    11         map.put("LOAN_memberName", "张三");
    12         map.put("LOAN_certNo", "510254545488445");
    13         map.put("LOAN_address", "四川省锦州达到");
    14         map.put("LOAN_mobileNo", "023-5854555");
    15         map.put("GUARANTEE_guaPersonName", "李四");
    16 
    17         /** 此Map存放动态 批量生产Word中表格的内容 **/
    18         List<String[]> tableDataList = new ArrayList<String[]>();
    19         tableDataList.add(new String[] { "应还款日", "应还本金", "应付利息", "应还(付)总额" });
    20         tableDataList.add(new String[] { "2018-01-01", "23", "0.2", "111" });
    21         tableDataList.add(new String[] { "2018-01-02", "233", "0.2", "123" });
    22         tableDataList.add(new String[] { "2018-01-03", "2333", "0.2", "321" });
    23         tableDataList.add(new String[] { "2018-01-04", "2333", "0.2", "321" });
    24         tableDataList.add(new String[] { "2018-01-05", "2333", "0.2", "321" });
    25         tableDataList.add(new String[] { "2018-01-06", "2333", "0.2", "321" });
    26         tableDataList.add(new String[] { "2018-01-07", "2333", "0.2", "321" });
    27 
    28         String localTemplateTmpPath = "E:\new\TestWord.docx";
    29         String newContractLocalPath = "E:\new\TestWord2.docx";
    30 
    31         WordUtil.changWord(localTemplateTmpPath, newContractLocalPath, map, tableDataList);
    32 
    33     }
    34 }
    View Code

    核心代码:

    public class WordUtil {
        /**
         * 根据模板生成新word文档
         * 判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入
         *
         * @param inputUrl  模板存放地址
         * @param outputUrl 新文档存放地址
         * @param textMap   需要替换的信息集合
         * @param tableList 需要插入的表格信息集合
         * @return 成功返回true, 失败返回false
         */
        public static boolean changWord(String inputUrl, String outputUrl, Map<String, String> textMap, List<String[]> tableList) {
    
            // 模板转换默认成功
            boolean changeFlag = true;
            try {
                // 获取docx解析对象
                XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(inputUrl));
                // 解析替换文本段落对象
                WordUtil.changeText(document, textMap);
                // 解析替换表格对象
                WordUtil.changeTable2(document, textMap, tableList);
    
                // 生成新的word
                File file = new File(outputUrl);
                FileOutputStream stream = new FileOutputStream(file);
                document.write(stream);
                stream.close();
            } catch (Exception e) {
                e.printStackTrace();
                changeFlag = false;
            }
            return changeFlag;
        }
    
        /**
         * 替换段落文本
         *
         * @param document docx解析对象
         * @param textMap  需要替换的信息集合
         */
        public static void changeText(XWPFDocument document, Map<String, String> textMap) {
            // 获取段落集合
            List<XWPFParagraph> paragraphs = document.getParagraphs();
            Set<String> keySet = textMap.keySet();
            changeParagraph(textMap, paragraphs, keySet);
            // 获取表格对象集合
            List<XWPFTable> tables = document.getTables();
            for (XWPFTable table : tables) {
                List<XWPFParagraph> paras;
                int rcount = table.getNumberOfRows();
                for (int j = 0; j < rcount; j++) {
                    XWPFTableRow row = table.getRow(j);
                    List<XWPFTableCell> cells = row.getTableCells();
                    for (XWPFTableCell cell : cells) {
                        paras = cell.getParagraphs();
                        changeParagraph(textMap, paras, keySet);
                    }
                }
            }
        }
    
        private static void changeParagraph(Map<String, String> textMap, List<XWPFParagraph> paragraphs, Set<String> keySet) {
            reBuildParagraph2(textMap, paragraphs, keySet);
        }
    
        private static void reBuildParagraph2(Map<String, String> textMap, List<XWPFParagraph> paragraphs, Set<String> keySet) {
            for (XWPFParagraph paragraph : paragraphs) {
    
                /**
                 * 此处For循环的思路:
                 * 将原来的XWPFParagraph中的多个XWPFRun转化成一个XWPFRun,如此做的好处是不会改变原Word的格式
                 * 如果直接通过XWPFParagraph获取文本内容,再进行赋值,会改变原有的Word的格式
                 */
                String paragraphText = paragraph.getText();
                for (String key : keySet) {
                    String regex = "\$\{" + key + "\}";
                    Pattern pattern = Pattern.compile(regex);
                    Matcher matcher = pattern.matcher(paragraphText);
                    while (matcher.find()) {
                        List<XWPFRun> runs = paragraph.getRuns();
                        StringBuffer sb = new StringBuffer("");
                        for (XWPFRun run : runs) {
                            int testPosition = run.getTextPosition();
                            String text = run.getText(testPosition);
                            if (StringUtils.isNotBlank(text)) {
                                sb.append(text);
                            }
                        }
                        String newText = sb.toString();
                        int runLength = runs.size();
                        for (int i = runLength - 1; i >= 0; i--) {
                            if (i == 0) {
                                runs.get(i).setText(newText, 0);
                            } else {
                                paragraph.removeRun(i);
                                if (runLength > 1) {
                                    runLength = runLength - 1;
                                }
                            }
                        }
                    }
                }
    
                /**
                 * 此处的思路:
                 * 转换后的XWPFParagraph只会存在一个XWPFRun,并保留了原Word的格式
                 * 将XWPFRun按照正则进行截取成多个XWPFRun;(具体实现是,将原有的XWPFRun拆分成多个,删除原有的XWPFRun,再将拆分后的XWPFRun创建到原XWPFParagraph)
                 * 如此做的目的是:对Word中定义的变量(例如:${abc})进行格式操作,比如添加下划线
                 */
                List<XWPFRun> runs = paragraph.getRuns();
                List<String> list = Lists.newArrayList();
                if (runs.size() > 0) {
                    XWPFRun run = runs.get(0);
                    int testPosition = run.getTextPosition();
                    String text = run.getText(testPosition);
                    String regex2 = "\$\{\w*\}";
                    String[] strs = text.split(regex2);
                    String totalStr = "";
                    if (strs.length == 1) {
                        if (text.contains("${")) {
                            list.add(strs[0]);
                            String regexStr = text.substring(strs[0].length());
                            list.add(regexStr);
                            paragraph.removeRun(0);
                        }
                    } else {
                        if (strs.length > 1) {
                            for (int i = 0; i < strs.length; i++) {
                                String splitStr = strs[i];
                                totalStr = totalStr + splitStr;
                                String regexStr = "";
                                list.add(strs[i]);
                                if (i + 1 < strs.length) {
                                    regexStr = text.substring(totalStr.length(), text.indexOf(strs[i + 1], totalStr.length()));
                                }
                                list.add(regexStr);
                                totalStr = totalStr + regexStr;
                            }
                            paragraph.removeRun(0);
                        }
                    }
    
                    for (int i = 0; i < list.size(); i++) {
                        XWPFRun newRun = paragraph.createRun();
                        newRun.setText(list.get(i));
                    }
                    /**
                     * 此处的思路:
                     * 获取转换后的XWPFParagraph上的多个XWPFRun
                     * 将XWPFRun按照正则进行文本内容替换(动态替换)
                     */
                    List<XWPFRun> newRuns = paragraph.getRuns();
                    for (XWPFRun newRun : newRuns) {
                        int position = newRun.getTextPosition();
                        String newText = newRun.getText(position);
                        for (String key : keySet) {
                            String regex = "\$\{" + key + "\}";
                            Pattern pattern = Pattern.compile(regex);
                            if (null != pattern && StringUtil.isNotBlank(newText)) {
                                Matcher matcher = pattern.matcher(newText);
                                while (matcher.find()) {
                                    String replaceText = newText.replaceAll(regex, textMap.get(key));
                                    replaceText = "  " + replaceText + "  ";
                                    newRun.setText(replaceText, 0);
                                    newRun.setUnderline(UnderlinePatterns.SINGLE);
                                }
                            }
                        }
                    }
                }
    
            }
        }
    
        /**
         * 替换表格对象方法
         *
         * @param document  docx解析对象
         * @param textMap   需要替换的信息集合
         * @param tableList 需要插入的表格信息集合
         */
        public static void changeTable2(XWPFDocument document, Map<String, String> textMap, List<String[]> tableList) {
            // 获取表格对象集合
            List<XWPFTable> tables = document.getTables();
            for (int i = 0; i < tables.size(); i++) {
                // 只处理行数大于等于2的表格,且不循环表头
                XWPFTable table = tables.get(i);
    
                // 表头
                String[] tableHeads = tableList.get(0);
                String tableHead = "";
                for (int a = 0; a < tableHeads.length; a++) {
                    tableHead = tableHead + tableHeads[a];
                }
                String templateTableHead = table.getText().replaceAll("	", "").replaceAll("
    ", "");
                System.out.println(templateTableHead.contains(tableHead));
                if (templateTableHead.contains(tableHead)) {
                    // 创建20行7列
                    int rows = tableList.size();
                    int cols = tableList.get(0).length;
    
                    for (int l = 1; l < rows; l++) {
                        XWPFTableRow targetRow = table.insertNewTableRow(l + 1);
                        targetRow.getCtRow().setTrPr(table.getRow(l).getCtRow().getTrPr());
                        List<XWPFTableCell> cellList = table.getRow(l).getTableCells();
                        XWPFTableCell targetCell = null;
                        for (XWPFTableCell sourceCell : cellList) {
                            targetCell = targetRow.addNewTableCell();
                            targetCell.getCTTc().setTcPr(sourceCell.getCTTc().getTcPr());
                            targetCell.getParagraphs().get(0).getCTP().setPPr(sourceCell.getParagraphs().get(0).getCTP().getPPr());
                        }
                        XWPFTableRow row = table.getRow(l);
                        for (int j = 0; j < cols; j++) {
                            // 设置单元格内容
                            row.getCell(j).setText(tableList.get(l)[j]);
                        }
                    }
                }
            }
        }
    
    }
  • 相关阅读:
    C#?和??运算符以及合并条件表达式
    Nhibernate Batch update returned unexpected row count from update; actual row count: 0 解决方案
    js根据ClassName来删除元素(有坑误入)
    C#正则表达式(通俗易懂)
    AngularJs自定义表单验证
    基于angularJs坐标转换指令(经纬度中的度分秒转化为小数形式 )
    网页乱码问题
    交换两个数值(值类型,引用类型)
    不用临时变量,交换二个变量的值
    PDF在线预览 (flexpaper+swftools+saveaspdfandxps)
  • 原文地址:https://www.cnblogs.com/swugogo/p/8578117.html
Copyright © 2011-2022 走看看