java通过word模板生成导出word

2023-11-19

java通过word模板生成导出word


#生成word方法类

public class BokeWordUtils {
    /**
     * 根据模板生成新word文档
     * 判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入
     *
     * @param inputUrl  模板存放地址
     * @param outputUrl 新文档存放地址
     * @param textMap   需要替换的信息集合
     * @param tableList 需要插入的表格信息集合
     */
    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.trim()));
            //解析替换文本段落对象
            BokeWordUtils.changeText(document, textMap);
            //解析替换表格对象
            BokeWordUtils.changeTable(document, textMap, tableList);
            //生成新的word
            File file = new File(outputUrl);
            FileOutputStream stream = new FileOutputStream(file);
            document.write(stream);
            stream.close();
            System.out.println("成功生成!");
        } catch (IOException e) {
            e.printStackTrace();
            changeFlag = false;
        }

        return changeFlag;

    }

    /**
     * 根据模板生成新word文档
     * 判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入
     *
     * @param inputStream  模板存放地址
     * @param outputUrl 新文档存放地址
     * @param textMap   需要替换的信息集合
     * @param tableList 需要插入的表格信息集合
     */
    public static boolean changWord(InputStream inputStream, String outputUrl,
                                    Map<String, String> textMap, List<String[]> tableList) {
        //模板转换默认成功
        boolean changeFlag = true;
        try {
            //获取docx解析对象
            XWPFDocument document = new XWPFDocument(inputStream);
            //解析替换文本段落对象
            BokeWordUtils.changeText(document, textMap);
            //解析替换表格对象
            BokeWordUtils.changeTable(document, textMap, tableList);
            //生成新的word
            File file = new File(outputUrl);
            FileOutputStream stream = new FileOutputStream(file);
            document.write(stream);
            stream.close();
            inputStream.close();
            System.out.println("成功生成!");
        } catch (IOException 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();
        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);
                    String textValue = changeValue(run.toString(), textMap);
                    run.setText(textValue, 0);
                }
            }
        }
    }

    /**
     * 替换表格对象方法
     *
     * @param document  docx解析对象
     * @param textMap   需要替换的信息集合
     * @param tableList 需要插入的表格信息集合
     */
    public static void changeTable(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);
            if (table.getRows().size() > 1) {
                //判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入
                if (checkText(table.getText())) {
                    List<XWPFTableRow> rows = table.getRows();
                    //遍历表格,并替换模板
                    eachTable(rows, textMap);
                } else {
//                  System.out.println("插入"+table.getText());
                    insertTable(table, tableList);
                }
            }
        }
    }


    /**
     * 遍历表格
     *
     * @param rows    表格行对象
     * @param textMap 需要替换的信息集合
     */
    public 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 插入数据集合
     */
    public 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
     */
    public static boolean checkText(String text) {
        boolean check = false;
        if (text.indexOf("$") != -1) {
            check = true;
        }
        return check;
    }

    /**
     * 匹配传入信息集合与模板
     *
     * @param value   模板需要替换的区域
     * @param textMap 传入信息集合
     * @return 模板需要替换区域信息集合对应值
     */
    public static String changeValue(String value, Map<String, String> textMap) {
        Set<Entry<String, String>> textSets = textMap.entrySet();
        for (Entry<String, String> textSet : textSets) {
            //匹配模板与替换值 格式${key}
            String key = "${" + textSet.getKey() + "}";
            if (value.indexOf(key) != -1) {
                // value = textSet.getValue();//全部参数替换
                value = value.replace(key, textSet.getValue());//仅替换参数
            }
        }
        //模板未匹配到区域替换为空
        if (checkText(value)) {
            value = "";
        }
        return value;
    }
    /**
     * 合并docx文件
     *
     * @param srcDocxs 需要合并的目标docx文件
     * @param destDocx 合并后的docx输出文件
     */
    public static void mergeDoc(List<String> srcDocxs, String destDocx) {
        OutputStream dest = null;
        List<OPCPackage> opcpList = new ArrayList<OPCPackage>();
        int length = null == srcDocxs ? 0 : srcDocxs.size();
        /**
         * 循环获取每个docx文件的OPCPackage对象
         */
        for (int i = 0; i < length; i++) {
            String doc = srcDocxs.get(i);
            OPCPackage srcPackage = null;
            try {
                srcPackage = OPCPackage.open(doc);
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (null != srcPackage) {
                opcpList.add(srcPackage);
            }
        }
        int opcpSize = opcpList.size();
        //获取的OPCPackage对象大于0时,执行合并操作
        if (opcpSize > 0) {
            try {
                dest = new FileOutputStream(destDocx);
                XWPFDocument src1Document = new XWPFDocument(opcpList.get(0));
                CTBody src1Body = src1Document.getDocument().getBody();
                //OPCPackage大于1的部分执行合并操作
                if (opcpSize > 1) {
                    for (int i = 1; i < opcpSize; i++) {
                        OPCPackage src2Package = opcpList.get(i);
                        XWPFDocument src2Document = new XWPFDocument(src2Package);
                        CTBody src2Body = src2Document.getDocument().getBody();
                        appendBody(src1Body, src2Body);
                    }
                }
                //将合并的文档写入目标文件中
                src1Document.write(dest);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //关闭流
                IOUtils.closeQuietly(dest);
            }
        }
    }

    /**
     * 合并文档内容
     *
     * @param src    目标文档
     * @param append 要合并的文档
     * @throws Exception
     */
    private static void appendBody(CTBody src, CTBody append) throws Exception {
        XmlOptions optionsOuter = new XmlOptions();
        optionsOuter.setSaveOuter();
        String appendString = append.xmlText(optionsOuter);
        //替换word中得空行、根据自己需求来选择需不需要
        //word文档其实是由xml文件合成得,一下替换得是作者对应得xml文件中得空行标签
        appendString = appendString.replaceAll("<w:p><w:pPr><w:spacing w:line=\\\"360\\\" w:lineRule=\\\"auto\\\"/><w:jc w:val=\\\"right\\\"/><w:rPr><w:rFonts w:ascii=\\\"仿宋\\\" w:eastAsia=\\\"仿宋\\\" w:hAnsi=\\\"仿宋\\\"/><w:sz w:val=\\\"24\\\"/></w:rPr></w:pPr></w:p>","");
        appendString = appendString.replaceAll("<w:p><w:pPr xsi:nil=\\\"true\\\" xmlns:xsi=\\\"xsi\\\"/></w:p>","");
        appendString = appendString.replaceAll("<w:p><w:pPr><w:ind w:firstLineChars=\\\"200\\\" w:firstLine=\\\"600\\\"/><w:jc w:val=\\\"right\\\"/><w:rPr><w:rFonts w:ascii=\\\"仿宋\\\" w:eastAsia=\\\"仿宋\\\" w:hAnsi=\\\"仿宋\\\"/><w:sz w:val=\\\"30\\\"/><w:szCs w:val=\\\"30\\\"/></w:rPr></w:pPr></w:p>","");
        appendString = appendString.replaceAll("<w:spacing w:line=\\\"360\\\" w:lineRule=\\\"auto\\\"/>","");;
        String srcString = src.xmlText();
        srcString = srcString.replaceAll("<w:p><w:pPr><w:ind w:firstLineChars=\\\"200\\\" w:firstLine=\\\"600\\\"/><w:jc w:val=\\\"right\\\"/><w:rPr><w:rFonts w:ascii=\\\"仿宋\\\" w:eastAsia=\\\"仿宋\\\" w:hAnsi=\\\"仿宋\\\"/><w:sz w:val=\\\"30\\\"/><w:szCs w:val=\\\"30\\\"/></w:rPr></w:pPr></w:p>","");
        srcString = srcString.replaceAll("<w:spacing w:line=\\\"360\\\" w:lineRule=\\\"auto\\\"/>","");
        srcString = srcString.replaceAll("<w:p><w:pPr><w:spacing w:line=\\\"360\\\" w:lineRule=\\\"auto\\\"/><w:jc w:val=\\\"right\\\"/><w:rPr><w:rFonts w:ascii=\\\"仿宋\\\" w:eastAsia=\\\"仿宋\\\" w:hAnsi=\\\"仿宋\\\"/><w:sz w:val=\\\"24\\\"/></w:rPr></w:pPr></w:p>","");
        srcString = srcString.replaceAll("<w:p><w:pPr xsi:nil=\\\"true\\\" xmlns:xsi=\\\"xsi\\\"/></w:p>","");
        String prefix = srcString.substring(0, srcString.indexOf(">") + 1);
        String mainPart = srcString.substring(srcString.indexOf(">") + 1,
                srcString.lastIndexOf("<"));
        String sufix = srcString.substring(srcString.lastIndexOf("<"));
        String addPart = appendString.substring(appendString.indexOf(">") + 1,
                appendString.lastIndexOf("<"));
        CTBody makeBody = CTBody.Factory.parse(prefix + mainPart + addPart
                + sufix);
        src.set(makeBody);
    }

}

#方法调用

//获取项目内模板
InputStream url = this.getClass().getClassLoader().getResourceAsStream("xxx.docx");
//生成后的文件路径
String outPutUrl = "export/xxx.docx";
//文本填充
Map<String, String> testMap = new HashMap<String, String>();
testMap.put("name", "123");
testMap.put("age", "12");
testMap.put("sex", "女");
//表格填充
List<String[]> tableList= new ArrayList<String[]>();
tableList.add(new String[]{"1","张三","12","男"});
tableList.add(new String[]{"2","李四","33","男"});
tableList.add(new String[]{"3","王麻子","22","男"});
tableList.add(new String[]{"4","孙二娘","44","女"});
//生成
BokeWordUtils.changWord(url, outPutUrl, testMap, tableList);

#文本模板配置
模板设置
#表格模板配置
表格模板配置i
#最终呈现效果
最终呈现效果

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java通过word模板生成导出word 的相关文章

  • 最快的高斯模糊实现

    如何以最快的速度实施高斯模糊 http en wikipedia org wiki Gaussian blur算法 我要用Java来实现它 所以GPU http en wikipedia org wiki Graphics processi
  • 使用 Spring 控制器处理错误 404

    I use ExceptionHandler处理我的网络应用程序抛出的异常 在我的例子中我的应用程序返回JSON回应HTTP status用于对客户端的错误响应 但是 我正在尝试弄清楚如何处理error 404返回与处理的类似的 JSON
  • 在哪里保存选项值、重要文件的路径等[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我正在创建一个程序 需要设置一些选项值以及图像文件的一些路径 SQLite 数据库的路径 有关各种按钮上文本的一些信息 有关要使用哪个数据库的信
  • Spring boot 中特定包的自定义日志文件

    我有一个带有专门操作的java包 专业化是因为它们很少被使用 并且我不想将它们与普通日志记录混合在一起 我知道添加logging file myapplication log会将日志记录重定向到此文件 但有没有办法指定仅从特定包记录到另一个
  • 如何将 Java 地图转换为在 Scala 中使用?

    我正在开发一个 Scala 程序 该程序调用 Java 库中的函数 处理结果并生成 CSV 有问题的 Java 函数如下所示 Map
  • Java:SortedMap、TreeMap、可比较?如何使用?

    我有一个对象列表 需要根据其中一个字段的属性进行排序 我听说 SortedMap 和 Comparator 是实现此目的的最佳方法 我是否要与正在排序的类实现 Comparable 还是创建一个新类 如何实例化 SortedMap 并传入
  • 纱线上的火花,连接到资源管理器 /0.0.0.0:8032

    我正在我的开发机器 Mac 上编写 Spark 程序 hadoop的版本是2 6 spark的版本是1 6 2 hadoop集群有3个节点 当然都在linux机器上 我在idea IDE中以spark独立模式运行spark程序 它运行成功
  • 在尝试使用 GPS 之前如何检查 GPS 是否已启用

    我有以下代码 但效果不好 因为有时 GPS 需要很长时间 我该如何执行以下操作 检查GPS是否启用 如果启用了 GPS 请使用 GPS 否则请使用网络提供商 如果 GPS 时间超过 30 秒 请使用网络 我可以使用时间或 Thread sl
  • 正确签名的 JNLP 应用程序无法在 Java 7 中运行

    我有一个 JNLP 应用程序 由于证书过期需要更新 我有一个经过 CA 验证的新证书 我已将新证书导入到我的密钥库中 我已导入完整的证书链 我的构建文件对构建中的 jar 进行签名和时间戳
  • 嵌套字段的 Comparator.comparing(...)

    假设我有一个这样的域模型 class Lecture Course course getters class Course Teacher teacher int studentSize getters class Teacher int
  • 如何从intellij项目视图中隐藏不必要的文件?

    给定一个示例 gradle 项目 其项目结构如下所示 正如你所看到的 有很多东西你实际上不需要在想法中看到 但你需要它们存在 我知道下面被忽略的文件 文件夹类型Editor File Types但这些正在影响库和项目 idea 会在各处忽略
  • 删除 JFX 中选项卡后面的灰色背景

    So is there any way to remove the gray area behind the tab s 我尝试过用 CSS 来做到这一点 但没有找到方法 要设置 tabpane 标题的背景颜色 请在 CSS 文件中写入 t
  • javax.media.jai 类的公共下载?

    这是一个非常简单的问题 我一直在寻找可以下载 javax media jai 库的地方 我找到了 jai imageio 库 但是我发现的所有其他 jai 内容要么已经过时 2008 年及之前 然后我遇到了登录屏幕 是否有 javax me
  • java中使用多线程调用同一类的不同方法

    我有一个类 如下所示 具有三种方法 public class MyRunnable implements Runnable Override public void run what code need to write here to c
  • 使用 PC/SC 读卡器验证 Ultralight EV1

    我在尝试使用 Java 中的 PC SC 读卡器 特别是 ACR1222L 验证 Ultralight EV1 卡时遇到问题 我能够使用 ISO 14443 3 标签的相应 APDU 在不受保护的标签上进行写入和读取 但是 我找不到运行 P
  • java.lang.IllegalStateException - 提交响应后无法创建会话

    我在我的项目中使用 JSF PrimeFaces 我为此准备了一个Maven项目 当我编译项目并加载主页后 我收到以下异常 java lang IllegalStateException Cannot create a session af
  • 如何使用自定义 JDK 构建 Jenkins 项目?

    我有一个常规的 Jenkins 实例 运行一些多分支管道 该实例在 JDK 11 上运行 因为 Jenkins 并不真正支持更高版本 没关系 但不好的是 我的所有管道似乎也都受到 Java 11 的限制 Jenkins 仅使用它自己也使用的
  • 如何建立与 FileZilla Server 1.2.0 的 FTPS 数据连接

    使用 Apache commons net 的 Java FTPSClient 进行会话恢复是一个已知问题 会话恢复是 FTPS 服务器数据连接所需的一项安全功能 Apache FTPSClient 不支持会话恢复 并且 JDK API 使
  • 决策树和规则引擎 (Drools)

    In the application that I m working on right now I need to periodically check eligibility of tens of thousands of object
  • Java中单例的其他方式[重复]

    这个问题在这里已经有答案了 只是我在考虑编写单例类的其他方法 那么这个类是否被认为是单例类呢 public class MyClass static Myclass myclass static myclass new MyClass pr

随机推荐

  • matlab读入从文件中读取大量的数据

    将文件导入matlab中 除了对利用菜单的操作 我们也可以使用matlab代码 这个是一个函数 这个函数我们提供所读文件的基础的名字 然后返回一个矩阵 function z readOneD basename readOneD BASENA
  • 我认为最好用的网页解析模块Parsel

    前言 众所周知 网页解析4大模块 1 正则表达式 re 2 bs4 BeautifulSoup 3 xpath lxml 4 css选择器 pyquery 大家一定都很熟悉 很多都是从这几个模块入手 本文不对这4个模块评价它们的优略 因为每
  • 攻防世界fileinclude题解

    目录 解题思路 file get contents 函数 PHP伪协议 解题思路续 解题思路 先看题目 打开题目场景 我们看到用了file get contents 函数 这里我忘了这个函数是什么意思了 于是又去翻了翻文档 file get
  • IDEA卡顿怎么办?快来用用这个办法

    IDEA卡顿解决方法 亲测有效 1 找到IDEA安装位置 打开这两个配置 2 修改配置 3 保存配置 重启IDEA 先介绍一下我电脑的情况 华硕dx80 8g运行 电脑配置一般 在跟同等价位的拯救者同时打开IDEA时 打开速度都差好多 为了
  • 分布式缓存数据库面试题redis

    redis和memcached什么区别 为什么高并发下有时单线程的redis比多线程的memcached效率要高 区别 1 mc可缓存图片和视频 rd支持除k v更多的数据结构 2 rd可以使用虚拟内存 rd可持久化和aof灾难恢复 rd通
  • Day 2 – 布尔值,字符串插值

    如何创建布尔值 布尔值是一种数据类型 用于存储逻辑真假值 在Swift中 布尔值用true和false表示 布尔值通常用于控制程序的流程和逻辑 let goodDogs true let gameOver false let isMulti
  • Active Directory 与域

    1工作场景导入 工作场景 XYZ公司是一家大型制造企业 公司有许多内设部门 车间和分厂 在全国各地有许多分公司 该公司总部信息中心有各类服务器30余台 各车间 分厂和分公司都有自己的服务器 客户机近千台 目前 该公司的各类应用大多基于Win
  • linux 查看JVM默认参数 (centos7)

    情景 之前学习过 深入了解JVM虚拟机 习得了一些JVM方面的一些知识 但是并没有相应的实战 虽然没有相应的实战 但是 咱们也得知道如何查看JVM默认参数 以及如何修改相应的JVM参数 查看命令 1 显示出JVM初始化完毕后所有跟最初的默认
  • C语言:递归实现输出一个整数的逆序

    任务描述 题目描述 编写一个递归函数 将一个整数n逆序输出 比如 n 12345 输出54321 相关知识 略 编程要求 请仔细阅读右侧代码 结合相关知识 在Begin End区域内进行代码补充 输入 一个整数n 输出 该整数的逆序 测试说
  • 蓝桥杯.卡片(模拟)

    Question Result 3181 Solve 直接模拟暴力 初始化卡片数量为2021 去模拟拼数的过程 注意点的话 我是先去判断卡片还有没有 再去减一 所以输出结果也有一个减一 因为一旦说卡片没有了 就意味着当前这个数字拼不成了 C
  • chmod 777 权限恢复问题 /etc/sudoers.d

    etc sudoers d问题 2016年07月27日 15 09 45 阅读数 1130 下述问题是由于我更改了整个 etc文件夹的权限后产生的 问题描述 sudo etc sudoers 可被任何人写 sudo no valid sud
  • tpcc mysql下载_TPCC安装和压测数据库数据表创建生成

    下载TPCC mysql root cnbugs1 git clone https github com Percona Lab tpcc mysql git 配置TPCC mysql root cnbugs1 mv tpcc mysql
  • C语言常见问题

    问题1 sizeof与strlen区别 1 sizeof sizeof 是一种单目操作符 是用来计算你所使用的操作数所占的空间字节大小 可以以类型 指针 数组和函数等作为参数 返回值类型为unsigned int 2 strlen strl
  • 面向对象高级特性

    static的含义 继承的规则 子类实例化的过程 方法的覆盖 final关键字 抽象类的特性 接口的规范 静态修饰符static static可以修饰的元素 属性 共享 方法 访问的方式 块 执行的时机 只能修饰类成员 不能修饰局部变量 静
  • vue聊天页面在进入之后信息滑动到底部位置

    这是需要实现的目标 怎么做到进入到页面之后就滑动到底部 借助两个属性 scrollHeigh 该属性是指 元素中内容 的高度 图中的意思就是全部信息所占用的总高度 scrollTop 指的是 元素中的内容 超出 元素上边界 的那部分的高度
  • Python数据可视化详解(3/5)--------patch,饼图,柱状图和点图

    水平或垂直的单条柱状图 如图 上代码 import matplotlib pyplot as plt import numpy as np fig axes plt subplots 2 1 x 1 2 3 4 5 6 data 5 4 1
  • Redis高级客户端Lettuce详解

    前提 Lettuce是一个Redis的Java驱动包 初识她的时候是使用RedisTemplate的时候遇到点问题Debug到底层的一些源码 发现spring data redis的驱动包在某个版本之后替换为Lettuce Lettuce翻
  • 测试用例的基本要素 && properties配置文件 && 测试用例的基本要素 && SpringMVC背景知识 && 按照开发阶段划分测试类型

    第 1 题 简答题 题目名称 设计测试用例 登陆页面 题目内容 请你针对登陆场景来设计测试用例 记得用脑图哦 第 2 题 简答题 题目名称 测试用例设计 淘宝购物车 题目内容 设计淘宝购物车的测试用例 尽可能多的来设计测试用例 若想不出来了
  • DataGrip配置设定

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 下载安装 二 使用步骤 1 配置成中文 2 导入旧的设定 3 常用操作 总结 前言 提示 这里可以添加本文要记录的大概内容 更换电脑 重装DataGrip
  • java通过word模板生成导出word

    java通过word模板生成导出word 生成word方法类 public class BokeWordUtils 根据模板生成新word文档 判断表格是需要替换还是需要插入 判断逻辑有 为替换 表格无 为插入 param inputUrl