java利用freemarker导出含有list的数据到word,有demo可供下载

java利用freemarker导出含有list的数据到word,有demo可供下载

前言

	FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据,	并用来生成输出文本(HTML网页、电子邮件、配置文件、源代码等)的通用工具。	它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。
	java导出数据到文档的方式有很多,为什么选择freemarker?还不是人家免费呗,而且体积小,资源占用可忽略不计,使用也还算简单。

如何使用?

	1.下载freemarker.jar包,官网有,但是资源很差,点击几十次都不一定能成功下载一次。
	你可以点击我的下载资源,内含freemarker.jar和demo:点击下载
	2.把freemarker.jar放到到java项目的lib文件夹中。
	3.准备你需要导出word的模板,模板中需要植入数据的地方,都用${字段名}填充。然后转换成xml格式。这里切记注意word版本,只限于2007版本一下,否则wps用不了。当然,我用的office2010,没这限制。(因为2007版本以前,WPS都是抄office的,之后的版本wps才开始独立起来成为真正意义上的国产,版本高了别人用WPS打开就有问题了)
	![处理word模板](https://www.icode9.com/i/ll/?i=20200304091958423.png?,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zOTQ0MjUwNg==,size_16,color_FFFFFF,t_70)
	4.把转换后的xml文档放到eclipse中,先Ctrl+SHIFT+F格式化一下,再处理模板。
	**xml处理第一步**:删除多余格式内容,保证字段标记正常如${type},每个你需要的字段都得这样处理好。
	![处理xml模板](https://www.icode9.com/i/ll/?i=2020030409224020.png?,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zOTQ0MjUwNg==,size_16,color_FFFFFF,t_70)
	**xml处理第二步**:有list数据的(即word中的子表),需要使用<#list list as list></#list>标签包括起来,只需要包括数据部分就行,表头不需要包括。至于怎么在xml中找到你的字表数据内容,只能用最笨的办法:先找到其中一个字段名,然后根据这个字段所在的标签<>一直往外找最大的标签<>,直到这个最大标签中只有你的字表字段时,这个位置就对了。你先拿demo练练手就知道了。
	![开始标签<#list list as list>所在位置](https://www.icode9.com/i/ll/?i=20200304093625264.png?,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zOTQ0MjUwNg==,size_16,color_FFFFFF,t_70)
	![结束标签</#list>所在位置](https://www.icode9.com/i/ll/?i=20200304092922897.png?,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zOTQ0MjUwNg==,size_16,color_FFFFFF,t_70)
	5.xml文档处理好之后,修改文件后缀名为.ftl,放到你的java项目中的某个文件夹内。
	![ftl文件放置位置](https://www.icode9.com/i/ll/?i=20200304093100721.png?,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zOTQ0MjUwNg==,size_16,color_FFFFFF,t_70)
	6.创建类并实现业务,这里简单写个demo。你根据自己业务情况嵌入到自己代码即可!
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
/**
 * freemarker导出list多列数据到word文档
 * @author 钟三
 */
public class ExportWord {

    private Configuration configuration = null;
    
    public ExportWord() {
        configuration = new Configuration();
        //设置编码
        configuration.setDefaultEncoding("UTF-8");
    }
//测试一下
     public static void main(String[] args) {
    	 String ftlName = "购销合同模板.ftl";
	     ExportWord test = new ExportWord();
	     test.createWord(getData(),ftlName);
     }
     /**
      * 	创建word文档,植入数据,并输出。(实际项目中应该输出到response*用户下载)
      * @param dataMap 需要打印的数据
      * @param ftlName 模板名称,实际业务肯定会有多个模板的,应该传入。地址就不需要那么麻烦传入了,直接名字就好
      */
    public void createWord(Map<String, Object> dataMap,String ftlName) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
      
        configuration.setClassForTemplateLoading(this.getClass(), ""); // FTL文件所存在的位置,这里我跟当前类ExportWord放在了同一目录下,所以是空
        Template t = null;
        try {
            t = configuration.getTemplate(ftlName); // 模板文件名
        } catch (IOException e) {
            e.printStackTrace();
        }
        File outFile = new File("D:/测试打印多列到word-" + sdf.format(new Date()) + ".doc"); // 输出的word文档的存放位置
        Writer out = null;
        try {
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile)));
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        }
        try {
            t.process(dataMap, out);
        } catch (TemplateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
//获取测试数据,这里应该调用自己的业务方法拿真实数据存放到Map<String, Object> dataMap对象中即可
    private static Map<String, Object> getData(){
    	Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("totalAmount", "100000.00");
        dataMap.put("unitName", "湖南XX信息科技有限公司");

        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        
        Map<String, Object> map1 = new HashMap<String, Object>();
        map1.put("xh", "1");
        map1.put("name", "货品名称1");
        map1.put("type", "型号规格1");
        map1.put("unitPrice", "单价1");
        map1.put("num", "数量1");
        map1.put("total", "合计金额1");
        map1.put("remark", "备注1");
        list.add(map1);
        
        Map<String, Object> map2 = new HashMap<String, Object>();
        map2.put("xh", "2");
        map2.put("name", "货品名称2");
        map2.put("type", "型号规格2");
        map2.put("unitPrice", "单价2");
        map2.put("num", "数量2");
        map2.put("total", "合计金额2");
        map2.put("remark", "备注2");
        list.add(map2);

        dataMap.put("list", list);
        System.out.println(dataMap.toString());
		return dataMap;
    }
}


7.测试成功展示
java利用freemarker导出含有list的数据到word,有demo可供下载

上一篇:freemarker自定义分页(springboot、bootstrap4)


下一篇:springboot2.x与钉钉集成及开发(三)(一)群消息推送