Java POI导出word模板,POI转化word为html代码

需求起因

做项目的时候按照客户需求在系统上填写一些数据,这些数据最后要导出为word文档存档,文档有严格的样式,主要是表格构成。参考相关代码后github上找到了一个POI操作word并导出的开源项目,github地址点击前往。话不多说看结果。

源文档

java html转word样式 java html转word 图片_html


模板文档

对照源文档修改自己的模板,后面会详细介绍模板的构造。

java html转word样式 java html转word 图片_Java文档导出_02


系通填写界面

java html转word样式 java html转word 图片_word转html代码_03


最终导出的文档

java html转word样式 java html转word 图片_word转html代码_04


具体实现

首先这功能分三部分,1.要导出的模板,2.代码 获取数据,对数据封装,填充到模板文件。3.导出要下载的文档。

1.要导出的模板

拿到源文档后,找到要改变的地方,这里拿一个测试文档test.docx举例。比如说我们要导出各个地区的气象数据,每个地区都可以导出,这时候就可以抽出一个模板来(有做过短信模板的这里一目了然,一模一样)。

java html转word样式 java html转word 图片_word模板导出_05


这个文档里红色的部分要改成可变的,可能是浙江省,江苏省等其他省份信息,这时候抽取要改变的地方用双大括号加变量名代替。eg:{{value}}。

这份文档就可以改为如下样式

java html转word样式 java html转word 图片_html_06


2.代码实现

这里用的是spring boot框架,maven管理依赖包,首先导入需要的依赖包

<dependency>
  <groupId>com.deepoove</groupId>
  <artifactId>poi-tl</artifactId>
  <version>1.5.0</version>
</dependency>

下面是核心的代码

@RequestMapping("/word")
    @ResponseBody
    public ResultJson uploadImg() {
        Map<String, Object> data = new HashMap<>();//通过map存放要填充的数据
        data.put("province","浙江省");//把每项数据写进map,key的命名要与word里面的一样
        data.put("temp",27.8);
        data.put("shidu",33.3);
        
        data.put("water",220);
        data.put("windir","西北风");
        data.put("winforce","7-8");
        data.put("chuanyi","天气热,适合T恤短裤");
        data.put("chuxing","太阳光强,宜做好防晒");
        data.put("advice1","适合海边游玩降温");
        data.put("advice2","适合洗车");
        data.put("advice3","不宜长时间吹空调");
        data.put("date", DateUtils.getCurDate());
        XWPFTemplate template = XWPFTemplate.compile("D:\\test.docx").render(data);//调用模板,填充数据
        try {
            FileOutputStream out = new FileOutputStream("D:\\天气预报.docx");//要导出的文件名
            template.write(out);
            out.flush();
            out.close();
            template.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

代码非常简单,就一个map搞定,这里我只是在controller里面随便测试的,真正要用当然要把这些字段放到实体来然后通过反向映射解析对象,循环填充。

用postman请求一下,看一下导出的效果。

java html转word样式 java html转word 图片_word转html代码_07


java html转word样式 java html转word 图片_html_08


以上就是全部过程,如果要下载直接通过response把数据流返给前端就OK了。

原本到这里就结束了,但是用户有来了一个需求,需要预览文档,这里大家就会说了,直接转成json扔给前端处理就好了。如果说文档规则的话其实前端通过table很简单就画出来了,就怕样式很复杂,画起来非常麻烦。这里在提供一个直接将word转为html代码的方法。(做后端的我就是这么心疼前端)
引入依赖包

<!--poi转化-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.14</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>3.14</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.14</version>
        </dependency>
        <dependency>
            <groupId>fr.opensagres.xdocreport</groupId>
            <artifactId>fr.opensagres.poi.xwpf.converter.xhtml</artifactId>
            <version>2.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>3.14</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>ooxml-schemas</artifactId>
            <version>1.3</version>
        </dependency>

好像包有点多。。。。。。。。。

实现代码

try {
        InputStream in = new FileInputStream(new File("D:\\天气预报.docx"));//要转化的word
        XWPFDocument document = new XWPFDocument(in);
        OutputStream baos = new ByteArrayOutputStream();
        XHTMLConverter xhtmlConverter = (XHTMLConverter) XHTMLConverter.getInstance();
        xhtmlConverter.convert(document, baos,null);
        String content = baos.toString();//转化好的html代码
        baos.close();
        return ResultJson.returnRightObj(content);
    } catch (IOException e) {
        e.printStackTrace();
    }

最终效果

java html转word样式 java html转word 图片_java html转word样式_09


代码返给前端展示就好了,跟word一模一样。

END