Java通过word模板导出word

3,493 阅读2分钟

Java通过word模板导出word

1.创建word模板文件,注意调整好格式,后期修改较为麻烦
2.打开创建好的word模板,点击文件另存为,选择xml格式

3.将生成的模板xml文件后缀改成ftl,例如:模板.xml-->模板.ftl
4.在项目中引入freemarker依赖
5.将模板.ftl文件放入项目resources下面的templates(自定义文件夹)
6.编写代码程序。 示例如下:

public void exportReport(HttpServletResponse response)              throws IOException, TemplateException {
    //map存储word需要的数据
    Map<String, Object> dataMap = new HashMap<>();
    //封装好的数据
    ReportDataDto dataForWord = getDataForWord(taskNo, isExport);
    //将数据指定key存储到map中
    dataMap.put("reportData", dataForWord);
    //配置对象
    Configuration configuration = new Configuration();
    //设置配置的字符编码为utf-8,避免字符集问题
    configuration.setDefaultEncoding("UTF-8");
    //获取resources下指定的文件夹路径,如果项目需要打成jar包,
    //此举很重要,别的方式可能无法获取到模板文件夹的相对路径
    configuration.setClassForTemplateLoading(this.getClass(), "/templates");
    // 获取模板实例,上行配置了模板文件所在路径
    Template t = configuration.getTemplate("模板.ftl", "utf-8");//以utf-8的编码读取ftl文件
    //设置响应类型为word
    response.setContentType("application/msword");
    //设置响应头,注意如果导出的word名含有汉字则需要将文件名
    //变成byte并且指定字符集为gbk,表示将GBK汉字转为byte
    //然后将其转为iso8859-1的字符串
    response.setHeader("Content-Disposition", "attachment;filename=\""
            + new String(("导出报告").getBytes("GBK"), "iso8859-1") + "\"");
    //此句非常关键,不然word文档全是乱码
    response.setCharacterEncoding("utf-8");
    PrintWriter out = response.getWriter();
    //使用数据填充模板
    t.process(dataMap, out);
    //以流的输出到浏览器,即下载
    out.close();
}

7.使用freemarker标签对模板.ftl文件进行数据渲染,例如:

tip:
1.<w:p>代表xml的段落,<w:r>代表行,<w:t>代表文本内容 2.对于word中存在图片的情况,生成的模板.ftl将有这样一部分:

找到<w:binData w:name="wordml://1.png"> ${photo.zposs}</w:binData> 标签,将里面的base64替换为${图片的base64}
需要先将图片转为base64,下面提供一种方式

public class Base64Util {
    /**
    *通过图片的URL转为base64
    */
    public static String getBase64ByImgUrl(String url){
        String suffix = url.substring(url.lastIndexOf(".") + 1);
        try {
            URL urls = new URL(url);
            ByteArrayOutputStream  baos = new ByteArrayOutputStream();
            Image image = Toolkit.getDefaultToolkit().getImage(urls);
            BufferedImage  biOut = toBufferedImage(image);
            ImageIO.write(biOut, suffix, baos);
            String base64Str = encodeImage(baos.toByteArray());
            return base64Str;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 图片转字符串
     * @param image
     * @return
     */
    public static String encodeImage(byte[] image){
        BASE64Encoder decoder = new BASE64Encoder();
        return replaceEnter(decoder.encode(image));
    }
}
</br>

注意:
1.使用frermarker标签时,尽量对数据做非空判断,避免出错
2.如果模板一开始样式不对,可以在后来在模板中修改好样式,重新另存为xml文件,然后到ftl文件中找到此内容,替换