• Java工具类 (3)------>WordUtils------>利用Poi根据模板生成新的word文档


    1、导入maven依赖

     <!--    引入Poi依赖      -->
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi</artifactId>
                <version>4.0.1</version>
            </dependency>
    
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>4.0.1</version>
            </dependency>
    
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml-schemas</artifactId>
                <version>4.0.1</version>
            </dependency>

    2、WordUtils

    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));
                //解析替换文本段落对象
                changeText(document, textMap);
                //解析替换表格对象
                changeTable(document, textMap, tableList);
    
                //生成新的word
                File file = new File(outputUrl);
                FileOutputStream stream = new FileOutputStream(file);
                document.write(stream);
                stream.close();
    
            } catch (IOException e) {
                e.printStackTrace();
                changeFlag = false;
            }
    
            return changeFlag;
    
        }
    
        /**
         * 替换段落文本
         * @param document docx解析对象
         * @param textMap 需要替换的信息集合
         */
        private static void changeText(XWPFDocument document, Map<String, String> textMap){
            //获取段落集合
            List<XWPFParagraph> paragraphs = document.getParagraphs();
    
            for (XWPFParagraph paragraph : paragraphs) {
                //判断此段落时候需要进行替换
                String text = paragraph.getText();
                if(checkText(text)){
                    List<XWPFRun> runs = paragraph.getRuns();
                    for (XWPFRun run : runs) {
                        //替换模板原来位置
                        run.setText(changeValue(run.toString(), textMap),0);
                    }
                }
            }
    
        }
    
        /**
         * 替换表格对象方法
         * @param document docx解析对象
         * @param textMap 需要替换的信息集合
         * @param tableList 需要插入的表格信息集合
         */
        private static void changeTable(XWPFDocument document, Map<String, String> textMap,
                                       List<String[]> tableList){
            //获取表格对象集合
            List<XWPFTable> tables = document.getTables();
            for (XWPFTable table : tables) {
                //只处理行数大于等于2的表格,且不循环表头
                if (table.getRows().size() > 1) {
                    //判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入
                    if (checkText(table.getText())) {
                        List<XWPFTableRow> rows = table.getRows();
                        //遍历表格,并替换模板
                        eachTable(rows, textMap);
                    } else {
                        insertTable(table, tableList);
                    }
                }
            }
        }
    
        /**
         * 遍历表格
         * @param rows 表格行对象
         * @param textMap 需要替换的信息集合
         */
        private static void eachTable(List<XWPFTableRow> rows ,Map<String, String> textMap){
            for (XWPFTableRow row : rows) {
                List<XWPFTableCell> cells = row.getTableCells();
                for (XWPFTableCell cell : cells) {
                    //判断单元格是否需要替换
                    if(checkText(cell.getText())){
                        List<XWPFParagraph> paragraphs = cell.getParagraphs();
                        for (XWPFParagraph paragraph : paragraphs) {
                            List<XWPFRun> runs = paragraph.getRuns();
                            for (XWPFRun run : runs) {
                                run.setText(changeValue(run.toString(), textMap),0);
                            }
                        }
                    }
                }
            }
        }
    
        /**
         * 为表格插入数据,行数不够添加新行
         * @param table 需要插入数据的表格
         * @param tableList 插入数据集合
         */
        private static void insertTable(XWPFTable table, List<String[]> tableList){
            //创建行,根据需要插入的数据添加新行,不处理表头
            for(int i = 1; i < tableList.size(); i++){
                XWPFTableRow row =table.createRow();
            }
            //遍历表格插入数据
            List<XWPFTableRow> rows = table.getRows();
            for(int i = 1; i < rows.size(); i++){
                XWPFTableRow newRow = table.getRow(i);
                List<XWPFTableCell> cells = newRow.getTableCells();
                for(int j = 0; j < cells.size(); j++){
                    XWPFTableCell cell = cells.get(j);
                    cell.setText(tableList.get(i-1)[j]);
                }
            }
    
        }
    
    
    
        /**
         * 判断文本中时候包含$
         * @param text 文本
         * @return 包含返回true,不包含返回false
         */
        private static boolean checkText(String text){
            boolean check  =  false;
            if(text.indexOf("$")!= -1){
                check = true;
            }
            return check;
    
        }
    
        /**
         * 匹配传入信息集合与模板
         * @param value 模板需要替换的区域
         * @param textMap 传入信息集合
         * @return 模板需要替换区域信息集合对应值
         */
        private static String changeValue(String value, Map<String, String> textMap){
            Set<Map.Entry<String, String>> textSets = textMap.entrySet();
            for (Map.Entry<String, String> textSet : textSets) {
                //匹配模板与替换值 格式${key}
                String key = "${"+textSet.getKey()+"}";
                if(value.indexOf(key)!= -1){
                    value = textSet.getValue();
                }
            }
            //模板未匹配到区域替换为空
            if(checkText(value)){
                value = "";
            }
            return value;
        }
    
    }

    3、测试

     @Test
        void testWord(){
            //模板文件地址
            String inputUrl = "E:\liangd\other\dailyTemplate.docx";
            //新生产的模板文件
            String outputUrl = "E:\liangd\other\daily\demo.docx";
    
            Map<String, String> testMap = new HashMap<String, String>();
            testMap.put("username", "小明");
            testMap.put("dailyTime", "2020-12-31");
            testMap.put("title", "测试");
    
            List<String[]> testList = new ArrayList<String[]>();
            testList.add(new String[]{"1","1AA","1BB","1CC"});
            testList.add(new String[]{"2","2AA","2BB","2CC"});
            testList.add(new String[]{"3","3AA","3BB","3CC"});
            testList.add(new String[]{"4","4AA","4BB","4CC"});
    
           boolean b = WordUtil.changWord(inputUrl, outputUrl, testMap, testList);
           if (b){
               System.out.println("创建成功");
           }else {
               System.out.println("创建失败");
           }
        }

    注:创建模板文件需要另存为docx格式,需要替换的文本地方用 ${} 替换

    作者:donleo123
    本文如对您有帮助,还请多推荐下此文,如有错误欢迎指正,相互学习,共同进步。
  • 相关阅读:
    python 之 数据库(创建表的完整语法、基本数据类型)
    python 之 数据库(数据库安装方法、基本sql语句、存储引擎)
    python 之 并发编程(非阻塞IO模型、I/O多路复用、socketserver的使用)
    python 之 并发编程(线程Event、协程)
    python 之 并发编程(进程池与线程池、同步异步阻塞非阻塞、线程queue)
    python 之 并发编程(守护线程与守护进程的区别、线程互斥锁、死锁现象与递归锁、信号量、GIL全局解释器锁)
    python 之 并发编程(线程理论,开启线程的两种方式,进程与线程的区别,线程对象的其他方法)
    python 之 并发编程(生产者消费者模型、守护进程的应用)
    SAP T CODE : Description (Program)
    SAP SD 信用检查相关
  • 原文地址:https://www.cnblogs.com/donleo123/p/14242117.html
Copyright © 2020-2023  润新知