Java使用FreeMarker导出word

最近好多项目都有word导出功能,觉得有必要整理一下知识点
wps可以兼容office,所以最好要用offfice建的doc文件转xml。两边的格式是不一样的。
标签含义感觉html的有点相似,当然还有许多坑需要自己摸索

正文

依赖

主要是freemark

 <!--word模板-->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.31</version>
        </dependency>

制作ftl模板

制作ftl文件

另存为word 2003 xml格式的xml,然后xmll文件改后缀,xxx.xml->xxx.ftl
在这里插入图片描述

ftl文件模板内容
文字
  • word 样式:
    在这里插入图片描述
  • 转成ftl

正文在w:body 标签下
在这里插入图片描述

其中${},是占位符,world是属性名

  • 代码
    在这里插入图片描述
/**
引入的包
**/
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.apache.commons.codec.binary.Base64;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

  //文字
    public void createWord(){
    //输出的文件
        File file = new File( "E:\\data\\image\\word\\world.doc" );
        Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        // 设置编码
        configuration.setDefaultEncoding("UTF-8");
        // 设置处理空值
        configuration.setClassicCompatible(true);
        // 设置ftl模板文件加载方式(我是将ftl模板文件放在项目中/resources/templates包下的)
        configuration.setClassForTemplateLoading(this.getClass(), "/templates");
        // 将模板和数据模型合并生成文件
        try {
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
            // 获取模板
            // wps转的
//            Template template = configuration.getTemplate("wold.ftl");
            Template template = configuration.getTemplate("wold-office.ftl");

            // 映射数据
            Map<String, Object> report = new HashMap<>();
            report.put("world","测试");
            template.process(report,out);
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
  • 结果
    在这里插入图片描述
列表
  • word
    在这里插入图片描述

注意:属性名上莫名被加了红色波浪,这个转xml的时候,要把多余的去掉

  • ftl
    在这里插入图片描述

w:tab 是表格标签,w:tr是列

在这里插入图片描述
在这里插入图片描述

用#list 标签循环

在这里插入图片描述

 //表格
    public void createTable(){
        File file = new File( "E:\\data\\image\\word\\table.doc" );
        Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        // 设置编码
        configuration.setDefaultEncoding("UTF-8");
        // 设置处理空值
        configuration.setClassicCompatible(true);
        // 设置ftl模板文件加载方式(我是将ftl模板文件放在项目中/resources/templates包下的)
        configuration.setClassForTemplateLoading(this.getClass(), "/templates");
        // 将模板和数据模型合并生成文件
        try {
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
            // 获取模板
            Template template = configuration.getTemplate("table-office.ftl");
            // 映射数据
            Map<String, Object> report = new HashMap<>();
            report.put("tableName","测试表格");
            ArrayList<Map> maps = new ArrayList<>();
            HashMap hashMap = new HashMap();
            hashMap.put("id","112312");
            hashMap.put("name","王大双");
            hashMap.put("age","11");
            hashMap.put("sex","男");
            maps.add(hashMap);

            HashMap hashMap1 = new HashMap();
            hashMap1.put("id","19371");
            hashMap1.put("name","王小双");
            hashMap1.put("age","13");
            hashMap1.put("sex","男");
            maps.add(hashMap1);
            report.put("table",maps);
            template.process(report,out);
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
  • 结果
    在这里插入图片描述
图片
  • ftl
    在这里插入图片描述
  //图片
    public void createImage(){
        File file = new File( "E:\\data\\image\\word\\image.doc" );
        Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        // 设置编码
        configuration.setDefaultEncoding("UTF-8");
        // 设置处理空值
        configuration.setClassicCompatible(true);
        // 设置ftl模板文件加载方式(我是将ftl模板文件放在项目中/resources/templates包下的)
        configuration.setClassForTemplateLoading(this.getClass(), "/templates");
        // 将模板和数据模型合并生成文件
        try {
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
            // 获取模板
//            Template template = configuration.getTemplate("image.ftl");
            Template template = configuration.getTemplate("image-office.ftl");
            // 映射数据
            Map<String, Object> report = new HashMap<>();

            ArrayList<Map> maps = new ArrayList<>();

//            for (int i = 10; i < 15; i++) {
//                HashMap hashMap = new HashMap();
//                hashMap.put("title",i);
//                hashMap.put("name","cesimage"+i);
//                hashMap.put("id",i);
//                hashMap.put("base64Url",getImgBase("E:\\data\\image\\word\\nkt.jpg"));
//                maps.add(hashMap);
//            }

            HashMap hashMap = new HashMap();
            hashMap.put("title",1111);
            hashMap.put("name","图一1");
            hashMap.put("id",12121);
            hashMap.put("base64Url",getImgBase("E:\\data\\image\\word\\nkt.jpg"));
            maps.add(hashMap);
            HashMap hashMap1 = new HashMap();
            hashMap1.put("title",2211);
            hashMap1.put("name","cesimagea");
            hashMap1.put("id",8);
            hashMap1.put("base64Url",getImgBase("E:\\data\\image\\word\\U001.jpg"));
            maps.add(hashMap1);
            report.put("images",maps);
            report.put("iamgeName","ssssssfsf");
            template.process(report,out);
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }



    /**
     * 将图片转换成Base64编码
     * @param imgFile 待处理图片地址
     * @return
     */
    public   String getImgBase(String imgFile) {

        // 将图片文件转化为二进制流
        InputStream in = null;
        byte[] data = null;
        // 读取图片字节数组
        try {
            in = new FileInputStream(imgFile);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 图片头
        //String imghead = "data:image/jpeg;base64,";
        return  Base64.encodeBase64String(data);
    }

  • 结果
    在这里插入图片描述
附录
  • 异常
    For “#{…}” content: Expected a number, but this has evaluated to a string

    ${…},而不是 #{…}

  • image-office.ftl
<w:body>
        <wx:sect>

            <#list images as image>
            <w:p wsp:rsidR="001861B0" wsp:rsidRDefault="001861B0" wsp:rsidP="0089750E">

                <w:r>
                    <w:rPr>
                        <w:rFonts w:hint="fareast"/>
                    </w:rPr>
                    <w:t>${image.name}</w:t>
                </w:r>
            </w:p>
            <w:p wsp:rsidR="001861B0" wsp:rsidRDefault="001861B0" wsp:rsidP="0089750E"/>
            <w:p wsp:rsidR="0089750E" wsp:rsidRDefault="001861B0" wsp:rsidP="0089750E">
                <w:r>
                    <w:pict>
                        <w:binData w:name="wordml://${image.id}.jpg" xml:space="preserve">
                           ${image.base64Url}
                        </w:binData>

                        <v:shape id="${image.id}" type="#_x0000_t75" style="width:415.5pt;height:199.5pt">
                            <v:imagedata src="wordml://${image.id}.jpg" o:title="${image.id}"/>
                        </v:shape>
                    </w:pict>
                </w:r>
            </w:p>
            </#list>

            <w:p wsp:rsidR="0089750E" wsp:rsidRDefault="0089750E" wsp:rsidP="0089750E"/>
            <w:p wsp:rsidR="001861B0" wsp:rsidRDefault="001861B0" wsp:rsidP="0089750E"/>

            <w:p wsp:rsidR="0089750E" wsp:rsidRDefault="0089750E" wsp:rsidP="0089750E">
                <w:pPr>
                    <w:rPr>
                        <w:rFonts w:hint="fareast"/>
                    </w:rPr>
                </w:pPr>
            </w:p>
            <w:p wsp:rsidR="0072263A" wsp:rsidRDefault="0072263A"/>
            <w:sectPr wsp:rsidR="0072263A" wsp:rsidSect="0012095E">
                <w:pgSz w:w="11906" w:h="16838"/>
                <w:pgMar w:top="1440" w:right="1800" w:bottom="1440" w:left="1800" w:header="851" w:footer="992"
                         w:gutter="0"/>
                <w:cols w:space="425"/>
                <w:docGrid w:type="lines" w:line-pitch="312"/>
            </w:sectPr>
        </wx:sect>
    </w:body>
``
* table-office.ftl
```java
   <w:body>
        <wx:sect>
            <w:p wsp:rsidR="00010FCD" wsp:rsidRDefault="00010FCD" wsp:rsidP="00010FCD">
                <w:r>
                    <w:rPr>
                        <w:rFonts w:hint="fareast"/>
                        <wx:font wx:val="宋体"/>
                    </w:rPr>
                    <w:t>表格</w:t>
                </w:r>
            </w:p>
            <w:p wsp:rsidR="00010FCD" wsp:rsidRDefault="00010FCD" wsp:rsidP="00010FCD">
                <w:r>
                    <w:rPr>
                        <w:rFonts w:hint="fareast"/>
                    </w:rPr>
                    <w:t></w:t>
                </w:r>
                <w:r>
                    <w:rPr>
                        <w:rFonts w:hint="fareast"/>
                        <wx:font wx:val="宋体"/>
                    </w:rPr>
                    <w:t>表格</w:t>
                </w:r>
                <w:r>
                    <w:rPr>
                        <w:rFonts w:hint="fareast"/>
                    </w:rPr>
                    <w:t>${tableName}</w:t>
                </w:r>
            </w:p>
            <w:tbl>
                <w:tblPr>
                    <w:tblW w:w="0" w:type="auto"/>
                    <w:tblBorders>
                        <w:top w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
                        <w:left w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
                        <w:bottom w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
                        <w:right w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
                        <w:insideH w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
                        <w:insideV w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
                    </w:tblBorders>
                    <w:tblLook w:val="04A0"/>
                </w:tblPr>
                <w:tblGrid>
                    <w:gridCol w:w="1704"/>
                    <w:gridCol w:w="1704"/>
                    <w:gridCol w:w="1704"/>
                    <w:gridCol w:w="1705"/>
                </w:tblGrid>
                <w:tr wsp:rsidR="00000000" wsp:rsidTr="00010FCD">
                    <w:tc>
                        <w:tcPr>
                            <w:tcW w:w="1704" w:type="dxa"/>
                            <w:shd w:val="clear" w:color="auto" w:fill="auto"/>
                        </w:tcPr>
                        <w:p wsp:rsidR="00010FCD" wsp:rsidRPr="00010FCD" wsp:rsidRDefault="00010FCD"
                             wsp:rsidP="00B761A6">
                            <w:pPr>
                                <w:rPr>
                                    <w:kern w:val="0"/>
                                    <w:sz w:val="20"/>
                                </w:rPr>
                            </w:pPr>
                            <w:r wsp:rsidRPr="00010FCD">
                                <w:rPr>
                                    <w:rFonts w:hint="fareast"/>
                                    <wx:font wx:val="宋体"/>
                                    <w:kern w:val="0"/>
                                    <w:sz w:val="20"/>
                                </w:rPr>
                                <w:t>序号</w:t>
                            </w:r>
                        </w:p>
                    </w:tc>
                    <w:tc>
                        <w:tcPr>
                            <w:tcW w:w="1704" w:type="dxa"/>
                            <w:shd w:val="clear" w:color="auto" w:fill="auto"/>
                        </w:tcPr>
                        <w:p wsp:rsidR="00010FCD" wsp:rsidRPr="00010FCD" wsp:rsidRDefault="00010FCD"
                             wsp:rsidP="00B761A6">
                            <w:pPr>
                                <w:rPr>
                                    <w:kern w:val="0"/>
                                    <w:sz w:val="20"/>
                                </w:rPr>
                            </w:pPr>
                            <w:r wsp:rsidRPr="00010FCD">
                                <w:rPr>
                                    <w:rFonts w:hint="fareast"/>
                                    <wx:font wx:val="宋体"/>
                                    <w:kern w:val="0"/>
                                    <w:sz w:val="20"/>
                                </w:rPr>
                                <w:t>姓名</w:t>
                            </w:r>
                        </w:p>
                    </w:tc>
                    <w:tc>
                        <w:tcPr>
                            <w:tcW w:w="1704" w:type="dxa"/>
                            <w:shd w:val="clear" w:color="auto" w:fill="auto"/>
                        </w:tcPr>
                        <w:p wsp:rsidR="00010FCD" wsp:rsidRPr="00010FCD" wsp:rsidRDefault="00010FCD"
                             wsp:rsidP="00B761A6">
                            <w:pPr>
                                <w:rPr>
                                    <w:kern w:val="0"/>
                                    <w:sz w:val="20"/>
                                </w:rPr>
                            </w:pPr>
                            <w:r wsp:rsidRPr="00010FCD">
                                <w:rPr>
                                    <w:rFonts w:hint="fareast"/>
                                    <wx:font wx:val="宋体"/>
                                    <w:kern w:val="0"/>
                                    <w:sz w:val="20"/>
                                </w:rPr>
                                <w:t>年龄</w:t>
                            </w:r>
                        </w:p>
                    </w:tc>
                    <w:tc>
                        <w:tcPr>
                            <w:tcW w:w="1705" w:type="dxa"/>
                            <w:shd w:val="clear" w:color="auto" w:fill="auto"/>
                        </w:tcPr>
                        <w:p wsp:rsidR="00010FCD" wsp:rsidRPr="00010FCD" wsp:rsidRDefault="00010FCD"
                             wsp:rsidP="00B761A6">
                            <w:pPr>
                                <w:rPr>
                                    <w:kern w:val="0"/>
                                    <w:sz w:val="20"/>
                                </w:rPr>
                            </w:pPr>
                            <w:r wsp:rsidRPr="00010FCD">
                                <w:rPr>
                                    <w:rFonts w:hint="fareast"/>
                                    <wx:font wx:val="宋体"/>
                                    <w:kern w:val="0"/>
                                    <w:sz w:val="20"/>
                                </w:rPr>
                                <w:t>性别</w:t>
                            </w:r>
                        </w:p>
                    </w:tc>
                </w:tr>
                <#list table as item>
                    <w:tr wsp:rsidR="00000000" wsp:rsidTr="00010FCD">
                        <w:tc>
                            <w:tcPr>
                                <w:tcW w:w="1704" w:type="dxa"/>
                                <w:shd w:val="clear" w:color="auto" w:fill="auto"/>
                            </w:tcPr>
                            <w:p wsp:rsidR="00010FCD" wsp:rsidRPr="00010FCD" wsp:rsidRDefault="00010FCD"
                                 wsp:rsidP="00B761A6">
                                <w:pPr>
                                    <w:rPr>
                                        <w:kern w:val="0"/>
                                        <w:sz w:val="20"/>
                                    </w:rPr>
                                </w:pPr>
                                <w:r wsp:rsidRPr="00010FCD">
                                    <w:rPr>
                                        <w:rFonts w:hint="fareast"/>
                                        <w:kern w:val="0"/>
                                        <w:sz w:val="20"/>
                                    </w:rPr>
                                    <w:t>${item.id}</w:t>
                                </w:r>
                            </w:p>
                        </w:tc>
                        <w:tc>
                            <w:tcPr>
                                <w:tcW w:w="1704" w:type="dxa"/>
                                <w:shd w:val="clear" w:color="auto" w:fill="auto"/>
                            </w:tcPr>
                            <w:p wsp:rsidR="00010FCD" wsp:rsidRPr="00010FCD" wsp:rsidRDefault="00010FCD"
                                 wsp:rsidP="00B761A6">
                                <w:pPr>
                                    <w:rPr>
                                        <w:kern w:val="0"/>
                                        <w:sz w:val="20"/>
                                    </w:rPr>
                                </w:pPr>
                                <w:r wsp:rsidRPr="00010FCD">
                                    <w:rPr>
                                        <w:rFonts w:hint="fareast"/>
                                        <w:kern w:val="0"/>
                                        <w:sz w:val="20"/>
                                    </w:rPr>
                                    <w:t>${item.name}</w:t>
                                </w:r>
                            </w:p>
                        </w:tc>
                        <w:tc>
                            <w:tcPr>
                                <w:tcW w:w="1704" w:type="dxa"/>
                                <w:shd w:val="clear" w:color="auto" w:fill="auto"/>
                            </w:tcPr>
                            <w:p wsp:rsidR="00010FCD" wsp:rsidRPr="00010FCD" wsp:rsidRDefault="00010FCD"
                                 wsp:rsidP="00B761A6">
                                <w:pPr>
                                    <w:rPr>
                                        <w:kern w:val="0"/>
                                        <w:sz w:val="20"/>
                                    </w:rPr>
                                </w:pPr>
                                <w:r wsp:rsidRPr="00010FCD">
                                    <w:rPr>
                                        <w:rFonts w:hint="fareast"/>
                                        <w:kern w:val="0"/>
                                        <w:sz w:val="20"/>
                                    </w:rPr>
                                    <w:t>${item.age}</w:t>
                                </w:r>
                            </w:p>
                        </w:tc>
                        <w:tc>
                            <w:tcPr>
                                <w:tcW w:w="1705" w:type="dxa"/>
                                <w:shd w:val="clear" w:color="auto" w:fill="auto"/>
                            </w:tcPr>
                            <w:p wsp:rsidR="00010FCD" wsp:rsidRPr="00010FCD" wsp:rsidRDefault="00010FCD"
                                 wsp:rsidP="00B761A6">
                                <w:pPr>
                                    <w:rPr>
                                        <w:kern w:val="0"/>
                                        <w:sz w:val="20"/>
                                    </w:rPr>
                                </w:pPr>
                                <w:r wsp:rsidRPr="00010FCD">
                                    <w:rPr>
                                        <w:rFonts w:hint="fareast"/>
                                        <w:kern w:val="0"/>
                                        <w:sz w:val="20"/>
                                    </w:rPr>
                                    <w:t>${item.sex}</w:t>
                                </w:r>
                            </w:p>
                        </w:tc>
                    </w:tr>
                </#list>

            </w:tbl>
            <w:p wsp:rsidR="0072263A" wsp:rsidRDefault="0072263A"/>
            <w:sectPr wsp:rsidR="0072263A">
                <w:pgSz w:w="11906" w:h="16838"/>
                <w:pgMar w:top="1440" w:right="1800" w:bottom="1440" w:left="1800" w:header="851" w:footer="992"
                         w:gutter="0"/>
                <w:cols w:space="425"/>
                <w:docGrid w:type="lines" w:line-pitch="312"/>
            </w:sectPr>
        </wx:sect>
    </w:body>
  • word-office.ftl
  <w:body>
        <wx:sect>
            <w:p wsp:rsidR="00B4513D" wsp:rsidRDefault="00B4513D" wsp:rsidP="00B4513D">
                <w:pPr>
                    <w:listPr>
                        <w:ilvl w:val="0"/>
                        <w:ilfo w:val="1"/>
                        <wx:t wx:val="1,"/>
                        <wx:font wx:val="Times New Roman"/>
                    </w:listPr>
                </w:pPr>
                <w:r>
                    <w:rPr>
                        <w:rFonts w:hint="fareast"/>
                        <wx:font wx:val="宋体"/>
                    </w:rPr>
                    <w:t>文字展示</w:t>
                </w:r>
            </w:p>
            <w:p wsp:rsidR="00B4513D" wsp:rsidRDefault="00B4513D" wsp:rsidP="00B4513D">
                <w:r>
                    <w:rPr>
                        <w:rFonts w:hint="fareast"/>
                        <wx:font wx:val="宋体"/>
                    </w:rPr>
                    <w:t>一段固定,一段动态</w:t>
                </w:r>
                <w:r>
                    <w:rPr>
                        <w:rFonts w:hint="fareast"/>
                    </w:rPr>
                    <w:t>${world}</w:t>
                </w:r>
            </w:p>
            <w:p wsp:rsidR="0072263A" wsp:rsidRDefault="0072263A"/>
            <w:sectPr wsp:rsidR="0072263A">
                <w:pgSz w:w="11906" w:h="16838"/>
                <w:pgMar w:top="1440" w:right="1800" w:bottom="1440" w:left="1800" w:header="851" w:footer="992"
                         w:gutter="0"/>
                <w:cols w:space="425"/>
                <w:docGrid w:type="lines" w:line-pitch="312"/>
            </w:sectPr>
        </wx:sect>
    </w:body>
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值