java操作world文档学习,poi-tl技术实现

前言

java操作world文档,实现world内容的新增、替换、模板合并等操作。


提示:本项目使用springboot进行开发

一、poi-tl介绍?

poi-tl是基于Apache POI的一套拥有简洁API的跨平台的模板引擎,纯Java组件,是Java Word的模板引擎,对docx格式的文档增加模板语法,支持对段落、页眉、页脚、表格等模板替换,并且提供了插件机制,在文档的任何地方做任何事情。

所有的语法结构都是以 { { 开始,以 }} 结束。

{ {template}} 普通文本

{ {@template}} 图片

{ {#template}} 表格

{ {*template}} 列表

{ {+template}} Word文档合并

说白了就是把你要替换、新增的东西用{ {xxx}}进行补充,然后通过代码自动给你实现替换。这样做的目的就是通过代码去解决实际中需要批量录入的一些问题,当然也支持对world文档进行美化、合并、页眉页脚等等操作。

官方git:https://github.com/Sayi/poi-tl

二、使用步骤

1.需要提前准备好要操作的world文档

需要对模板world文档提前进行替换准备

2.需要提前准备好springboot框架

3.开始进行maven的pom引入

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.17.1</version>
        </dependency>
        <dependency>
            <groupId>com.deepoove</groupId>
            <artifactId>poi-tl</artifactId>
            <version>1.12.1</version>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.logging.log4j</groupId>
                    <artifactId>log4j-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

这里补充说明一下,因为poi-tl内部引用的log4j版本过低,导致我项目启动有报错,所以外部新引入了log4j的依赖。

4.读入word模板

我是通过流读取的文件,然后自定义一个实体,实现了{ {xxx}}的字段填充。这只是一种做法,可以通过查阅它的API借助其他方式,也有通过文件路径的等等方式。
如果你需要操作的world文档比较多,可以借助循环调用实现多文档的操作,具体就根据业务来就行呢。

    private static NiceXWPFDocument autoFullText(String path, TemplateUser templateUser) throws Exception {
    
    
        InputStream inputStream = Files.newInputStream(Paths.get(path));
        NiceXWPFDocument document = XWPFTemplate.compile(inputStream).render(templateUser).getXWPFDocument();
        IOUtils.closeQuietly(inputStream);
        return document;
    }

补充说明:{ {xxx}}这里面可以通过一个实体,去控制我们要填充的具体字段,比如你要录入name、sex、age等信息,完全可以通过面向对象,定义一个Student实体类,然后设置这些属性,poi-tl会自动去匹配你实体里面的各个属性,很方便快捷。
但是有一点需要注意,实体中的属性名字最好都是小写,我在测试的时候发现如果按照驼峰命名,可能会报错格式不正确,无法正常解析的问题!

5.合并多份world为一份world模板

有的时候,需要对一些模板进行合并操作,比如将2份world合并为1份整体world.这个poi-tl也是支持的。
这里我贴出了一个static方法,参数就是多份world文档,NiceXWPFDocument这个就是poi-tl识别的world文档格式,然后我们通过取出里面的主模板,然后追加其他world模板在这个模板之后就可以了。

    private static NiceXWPFDocument mergeTemplates(List<NiceXWPFDocument> templates) throws Exception {
    
    

        NiceXWPFDocument document = templates.get(0);
        templates.remove(document);
        log.info("主模板需要合并的其他模板数:{}", templates.size());
        for (NiceXWPFDocument template : templates) {
    
    
            document.getXWPFDocument().createParagraph().createRun().addBreak(BreakType.PAGE);
            document = document.merge(template);
            template.close();
        }
        log.info("主模板合并完毕");
        return document;
    }

补充说明:在for循环里面,设置了一个addBreak(BreakType.PAGE),这个就是分页的作用,因为多份world文档,需要在合并的时候,都是从新的一页开始追加的,做到互不影响。

6.响应前端下载以及前端上传代码

考虑到有些朋友可能用到文件的下载,我也就一并贴出代码了。
前端用的vue2+axios,纯html的,不是vue-cli脚手架哈,请求的地址是你后端自己的接口,具体的接收那些就不赘述了。
vue js中的methods调用

methods: {
    
    
            async submitForm(formName) {
    
    
                this.fullscreenLoading = true;
                //获取模板节点id
                this.ruleForm.department = this.$refs.tree.getCheckedKeys();
                const result = await axiosPostRequest('/templates/autoFill', this.ruleForm);
                if (result !== '') {
    
    
                    this.fullscreenLoading = false;
                    this.$message.success('模板制作成功');
                    let binaryData = [];
                    binaryData.push(result.data);
                    const objectUrl = window.URL.createObjectURL(new Blob(binaryData))
                    const link = document.createElement("a");
                    link.href = objectUrl;
                    link.setAttribute("download", '模板文件.docx');
                    document.body.appendChild(link);
                    link.click();
                    document.body.removeChild(link);
                } else {
    
    
                    this.fullscreenLoading = false;
                    this.$message.error('生成模板失败');
                }
            }
        }

axios调用

    //axios封装post请求
    function axiosPostRequest(url, data) {
    
    
        return axios.post(url, data, {
    
    responseType: 'blob'})
            .then(res => {
    
    
                return res;
            })
            .catch(err => {
    
    
                console.log(err)
                return ''
            })
    }

后端完成模板解析后,响应前端的代码。这里只是贴了一部分,不是完整的function,仅供参考,也是为大家提供一下响应头的一些信息。HttpServletResponse response。

            response.setContentType("application/octet-stream");
            String format = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmm"));
            response.setHeader("Content-disposition", "attachment;filename=\"" + "Document" + format + ".docx" + "\"");
            out = response.getOutputStream();
            bos = new BufferedOutputStream(out);
            worlds.write(bos);
            bos.flush();
            out.flush();

            PoitlIOUtils.closeQuietlyMulti(worlds, bos, out);

总结

本次讲述,只是针对poi-tl的一些功能点进行了讲解,其实它的功能也是很强大的,基于poi进行了增强,基本的操作world也就足够了。有兴趣的小伙伴可以直接去官网查阅更详细的功能,比如生成table表单。设置images图片,填充页眉页脚等等。

以上文章可以给大家提供学习思路与解决问题的办法,作为分享,欢迎大家阅读点赞,如有问题也欢迎批评指正,一起学习进步。

猜你喜欢

转载自blog.csdn.net/qq_38653981/article/details/130039032