动态生成word文档的靠谱方式

需求:将数据生成到word模板文件
实现方式:使用ftl做模板文件,将数据写到word文档中
1、导包

<dependency>
	<groupId>org.freemarker</groupId>
	<artifactId>freemarker</artifactId>
	<version>2.3.28</version>
</dependency>

2、将做好的word模板文件另存为xml;再将xml文件的后缀改成ftl。然后就可以使用ftl的表达式写需要替换的内容(和写jsp类似)注意:word 模板最好用03版的,如果不是的话 先另存为03版的再另存为03版的模板(为了兼容,避免低版本的office无法打开高版本)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3、使用ftl表达式,取数据

//循环
<#list infos as info > 
	//嵌套的循环
	<#list info.values  as value > </#list>
</#list>
//if判断 ?? 表示非空 ?表示调用方法 
<#if value.disPersonnel??>
//取值
${value.disPersonnel}
<#else> 
</#if>
//调用日期格式化的方法
${workExp.startTime?string('yyyy-MM')}
//还有更多的ftl表达式 可根据需要单独百度ftl表达式

4、使用(代码很简单)

/**
 * @Author xxx
 * @Date 2020/4/19 - 15:52
 **/
public class Data2Word {
    public static void main(String[] args) throws Exception{
        Configuration configuration = new Configuration(new Version("2.3.28"));
        configuration.setDefaultEncoding("utf-8");
        //模板文件存放目录
        configuration.setDirectoryForTemplateLoading(new File("D:xxxx\\xxx"));
        //模板文件名称
        Template t = configuration.getTemplate("xxxx.ftl");
        // 模拟数据
        Map<String,Object> map = new HashMap<>();
        List<Map> list = new ArrayList<>();
        List<Integer> values = null;
        for(int i = 0 ; i < 3 ; i ++){
            values = new ArrayList<>();
            for(int j = 0 ; j < 60; j ++){
                values.add(j);
            }
            Map<String,Object> vMap =  new HashMap<>();
            vMap.put("values",values);
            list.add(vMap);
        }
        //此处是字节输出流、也可以用文件输出流输出到指定目录、
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        map.put("infos",list);
        t.process(map, new OutputStreamWriter(out));
        System.out.println("end");
    }

    /**
     *
     * @param data 数据源
     * @param dir 模板文件存放的目录
     * @param fileName 模板文件( 文件名 + 后缀)
     * @param dst 输出目录
     * @throws Exception
     */
    public static void dataToWord(Object data,String dir, String fileName,String dst) throws Exception{
        Configuration configuration = new Configuration(new Version("2.3.28"));
        configuration.setDefaultEncoding("utf-8");
        configuration.setDirectoryForTemplateLoading(new File(dir));
        Template  t = configuration.getTemplate(fileName);
        t.process(data, new OutputStreamWriter(new FileOutputStream(dst)));
    }

    /**
     *
     * @param data 数据源
     * @param dir 模板文件存放的目录
     * @param fileName 文件名 + 后缀
     * @return 字节输出流
     * @throws Exception
     */
    public static OutputStream dataToWord(Object data, String dir,String fileName) throws Exception{
        Configuration configuration = new Configuration(new Version("2.3.28"));
        configuration.setDefaultEncoding("utf-8");
        configuration.setDirectoryForTemplateLoading(new File(dir));
        Template  t = configuration.getTemplate(fileName);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        OutputStreamWriter outputWriter = new OutputStreamWriter(out, "UTF-8");
        BufferedWriter writer = new BufferedWriter(outputWriter);
        t.process(data, writer);
        return out;
    }

    /**
     *
     * @param data 数据源
     * param dir 模板文件存放的目录
     * @param fileName 文件名 + 后缀
     * @param outputStream 一般用作浏览器输出(response.getOutputStream())
     * @throws Exception
     */
    public static void dataToWord(Object data,String dir, String fileName,OutputStream outputStream) throws Exception{
        Configuration configuration = new Configuration(new Version("2.3.28"));
        configuration.setDefaultEncoding("utf-8");
        configuration.setDirectoryForTemplateLoading(new File(dir));
        Template  t = configuration.getTemplate(fileName);
        t.process(data, new OutputStreamWriter(outputStream));
    }

}

5、效果(文件太大了,拆成小文件,拆文件的方法未提供)
在这里插入图片描述
最后1、如果需求是每份表单结束后要分页,可在</#list> 循环标签结束前插入分页符,需要注意的是,有时分页不起效果,可以在做模板文件的时候,写几个特殊的字符,比如“aaaa”,找到对应的位置,在再插入分页符。反正都是些office的标签 多调试几次就能找到正确的位置。(因为不是专业搞office软件的,只能说些摸索的方式)

<wx:sect>
        <w:p>
            <w:pPr>
                <w:rPr>
                    <w:rFonts w:fareast="宋体" w:hint="default"/>
                    <w:lang w:val="EN-US" w:fareast="ZH-CN"/>
                </w:rPr>
            </w:pPr>
            <w:r>
                <w:rPr>
                    <w:rFonts w:ascii="微软雅黑" w:eastAsia="微软雅黑" w:hAnsi="Calibri" w:cs="Times New Roman"/>
                    <w:b/>
                    <w:bCs/>
                    <w:kern w:val="44"/>
                    <w:sz w:val="28"/>
                    <w:szCs w:val="28"/>
                </w:rPr>
                <w:br w:type="page"/>
            </w:r>
            <w:r w:rsidRPr="00A77B55">
                <w:rPr>
                    <w:rFonts w:ascii="微软雅黑" w:eastAsia="微软雅黑" w:hAnsi="微软雅黑" w:cs="Times New Roman"/>
                    <w:b/>
                    <w:noProof/>
                    <w:spacing w:val="40"/>
                    <w:sz w:val="28"/>
                    <w:szCs w:val="28"/>
                </w:rPr>
                <w:lastRenderedPageBreak/>
                <w:t xml:space="preserve"></w:t>
            </w:r>
        </w:p>
        <w:sectPr>
            <w:ftr w:type="odd">
                <w:p>
                    <w:pPr>
                        <w:pStyle w:val="a13"/>
                        <w:rPr>
                            <w:rFonts w:fareast="宋体" w:hint="default"/>
                        </w:rPr>
                    </w:pPr>
                </w:p>
            </w:ftr>
            <w:pgSz w:w="11905" w:h="16837"/>
            <w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="720" w:footer="720" w:gutter="0"/>
            <w:cols w:space="720"/>
        </w:sectPr>
    </wx:sect>

最后2、如果需求需要插入图片也简单,在模板中找到图片标签的位置,然后将图片转成base64的字符串 使用ftl标签替换就好了,和取普通数据一样,关键是找到图片标签的位置
在这里插入图片描述
总之使用ftl生成word文档会遇到一些奇奇怪怪的问题,代码很简单,主要是心细。假如遇到打开报“很抱歉,无法打开xxxx.doc,因为文件内容有问题”可能是因为字符串有特殊符号,组装值的时候把字符串转译一下,有好多类似的工具类,可自行百度。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值