JAVA实现Freemarker生成动态数据的Word文档下载到浏览器

使用的jar包版本:freemarker-2.3.28.jar
使用开发工具:idea

1. 创建模板:

新建一个word文档,打开后编辑成想要的格式
在这里插入图片描述

动态数据替换成${xxx},如果是多条集合用${xx.xxx};
如果没有对应数据会报错。可以替换成${(xx.xxx)?if_exists}  (这里表示内容为空不显示)就不会报错了
姓名性别
${zsxm?if_exists}${zsxb?if_exists}

然后在word里面点击另存为 ——xml格式文件
在这里插入图片描述
然后把这个xml文件后缀改成.ftl 得到:
在这里插入图片描述
然后把文件拖到idea编译器里格式化一下代码格式

拉到下面大概看到一堆这样的代码 先不管
在这里插入图片描述

2.创建WordUtil工具类

WordUtil.java代码:


import java.io.*;
import java.net.URLEncoder;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.gsgy.utils.DateUtil;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.springframework.util.ResourceUtils;

public class WordUtil {
    private static Configuration configuration = null;
    //模板文件的位置
    private static String templateFolder ="";

    static {
        try {
            //这个是获取到项目里的路径(对应resources文件夹下的template目录)
            templateFolder = ResourceUtils.getURL("classpath:").getPath()+ "template/";
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
    //或者注释上面的 选择这个固定的地址
    //    private static final String templateFolder = "D:/wzy/template";
    static {
        configuration = new Configuration();
        configuration.setDefaultEncoding("utf-8");
        try {
            configuration.setDirectoryForTemplateLoading(new File(templateFolder));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private WordUtil() {
        throw new AssertionError();
    }

    public static void exportMillCertificateWord(HttpServletRequest request, HttpServletResponse response, Map map, String title, String ftlFile) throws IOException {
        Template freemarkerTemplate = configuration.getTemplate(ftlFile);
        File file = null;
        InputStream fin = null;
        ServletOutputStream out = null;
        try {
            // 调用工具类的createDoc方法生成Word文档
            file = createDoc(map,freemarkerTemplate);
            fin = new FileInputStream(file);

            response.setCharacterEncoding("utf-8");
            response.setContentType("application/msword");
            // 设置浏览器以下载的方式,处理该文件名
            String fileName = title+ "自定义名称" + ".doc";
            response.setHeader("Content-Disposition", "attachment;filename="
                    .concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));

            out = response.getOutputStream();
            byte[] buffer = new byte[512];
            int bytesToRead = -1;
            // 通过循环将读入的Word文件的内容输出到浏览器中
            while((bytesToRead = fin.read(buffer)) != -1) {
                out.write(buffer, 0, bytesToRead);
            }

        } finally {
            if(fin != null) fin.close();
            if(out != null) out.close();    //关闭对应流
            if(file != null) file.delete(); // 删除临时文件
        }
    }

    private static File createDoc(Map<?, ?> dataMap, Template template) {
        String name =  "sellPlan.doc";
        File f = new File(name);
        Template t = template;
        try {
            // 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
            Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");
            t.process(dataMap, w);
            w.close();
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex);
        }
        return f;
    }
}

建一个Controller类写调用接口:

@RestController
@RequestMapping("test")
public class testController{

 	@Autowired
    private YwXsRyxxService ywXsRyxxService;


	@RequestMapping("/getWord")
    @ResponseBody
    public void getWord(HttpServletRequest request,HttpServletResponse response) {

        //---------------这里开始调用自己需要的数据(粘过去替换成自己的数据方法)--------------------
        Page page = new Page();
        //人员
        List<YwXsRyxx> ryList = ywXsRyxxService.selectlistPage(page);
		//-----------------------------结束------------------------------------------


        //封装数据
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("ryList", ryList);
        try {
        //这里设置文档的名称 和模板的名字
            WordUtils.exportMillCertificateWord(request, response, map, "文档名称", "ypbg.ftl");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

3.回到模板哪里

这里我们封装了ryListwlList两个集合

在这里插入图片描述
在模板里CTRL+F 搜索 人员信息
在这里插入图片描述
然后慢慢往下 会看到 姓名性别 ~~~ 等名称(不熟悉这个文档的小白可以大致看一眼结构)

继续往下看到第一个动态数据姓名的替换符哪里(下图1处)
在这里插入图片描述
然后看上图2处 的

<#list ryList as ry> 这里的ryList 是我们后台封装过来的数据
ry是别名  
就是模板里定义的变量名ry.xxxx

找到<#list ryList as ry> 下面 <w:tr> 这个标签的结尾处 如图:
在这里插入图片描述
在</:tr>后面加上 </#list>

以下二选一
(1)然后将模板放在项目的 resources/template目录下 (没有就建一个)
(2)本地找个文件夹下新建一个template文件夹 把路径考到代码里下面图片位置把2处的值替换了。然后注释1处代码

在这里插入图片描述
项目下路径图
在这里插入图片描述

4.启动项目

启动项目 在浏览器输入对应的请求路径
我这是: http://localhost:8088/test/getWord
然后浏览器会下载一个word

在这里插入图片描述
一个简单的文档就生成了,复杂的继续摸索延伸。希望能帮到大家 (代码部分有参考网上的文章,自己学习整理了下)

最后加一些Freemarker中用到的判断的语法供参考:
${(xxx)!''}  //判断xxx为null 输出'' 或者用${xxx?if_exists} 
<#list ryList as ry></#list>  //循环遍历集合
<#if xxx?? ></#if>  //判断xxx变量是否存在,存在执行里面内容;同java里if判断
<#if type??> 
	<#if type == 1></#if>
	<#if type == 0></#if>
</#if>
${(dateTime?string('yyyy-MM-dd HH:mm:ss'))!''}  //实体类Date类型会报错 这样转换一下(替换dateTime为自己的变量名)
  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值