java中Freemaker模板导出Word(统计图)和Excel详解(附工具类)

      为什么不用jxl、poi的方式进行导出呢?如果模板复杂、又包含一些动态的判断,就要在后台写很多很多判断的代码,费时费力又容易出错,使用freemaker定制模板就方便很多很多。话不多说,一再强调,思路很重要。

使用freemaker思路(相当于mvc模式下的一次请求,便于理解):

 1、定制模板(新建模板里放值的地方先随便写个汉字站位,另存为xml文件类型,最后改为.ftl后缀的文件)。(相当于jsp页面)

 2、后台方法查询要导出的数据,所有的数据都保存到一个map中。(相当于Contrller中获取数据的方法)

 3、将map中的数据填充到模板中的站位的汉字处。(相当于jsp中用el表达式、jstl等赋值变量)

 4、调用freemarker相关的类的方法及下载的方法,实现导出下载。(相当于controller中的方法带着数据响应到jsp页面的过程)

下来图文介绍每一步:

1、定制模板:

汉字"站位"进行站位;保存为xml

java中Freemaker模板导出Word(统计图)和Excel详解(附工具类)java中Freemaker模板导出Word(统计图)和Excel详解(附工具类)

2、后台方法查询要导出的数据,所有的数据都保存到一个map中。

创建Map将要展示的集合,变量,对象等保存进去,如图:

java中Freemaker模板导出Word(统计图)和Excel详解(附工具类)

3、将map中的数据填充到模板中的站位的汉字处。

将xml后缀的文件放入的开发工具中(一般放到web-info下新建的文件夹中),如下进行赋值,赋值完成后修改后缀为ftl;

java中Freemaker模板导出Word(统计图)和Excel详解(附工具类)

扩充:

一.变量后的感叹号是如果变量不存在就给默认值,语法:variable!default_variable,不写默认值就取单元格类型的默认值。

二.<#list listAll as qingAll中取序号:${qingAll_index+1},qingAll是集合中的每一个元素的别名(as后面跟的)

三.if判断如下:s93和s95是单元格字体颜色(可以在<style>中设置)。

java中Freemaker模板导出Word(统计图)和Excel详解(附工具类)

四。还有“??”判空的可以在网上搜索使用。

4、调用freemarker相关的类的方法及下载的方法,实现导出下载。

这里使用工具类:

import freemarker.template.Configuration;
import freemarker.template.Template;

/**
 * 导出 Utils
 * @author Administrator
 *
 */
public class ExcelUtils {
    private static final Logger logger = Logger.getLogger(ExcelUtils.class);
    private static final String ENCODING ="UTF-8";
    private ExcelUtils(){
        throw new AssertionError();
    }
   /**
     * 导出exce
     * @param dataMap 导出的数据Map
     * @param type    一个标识,可以随便写
     * @param valueName web-info下.ftl文件名称(后缀也要写上)
     * @param response 响应到浏览器 用于下载的一些设置
     * @param request  前台请求对象,获取一些路径等
     * @param excelName 导出文件的名称
     * @throws IOException
     */
    public static void createExcel(Map<?, ?> dataMap, String type,String valueName,HttpServletResponse response,HttpServletRequest request,String excelName) throws IOException{
         InputStream inputStream = null;
         ServletOutputStream out = null;
         Map<String, Template> allTemplates = new HashMap<String, Template>();
         String realPath = request.getSession().getServletContext().getRealPath("/");
         Random random = new Random();
        try {
            request.setCharacterEncoding(ENCODING);
            Configuration configuration = new Configuration();
            configuration.setDefaultEncoding(ENCODING);
            configuration.setDirectoryForTemplateLoading(new File(realPath+"WEB-INF/mailtemplate"));
            allTemplates.put(type, configuration.getTemplate(valueName));
        } catch (IOException ex) {
            logger.error("错误信息",ex);
        }
        String name = "temp" + (random.nextInt(100000)) + ".xls";
         File file = new File(name);
         Template template = allTemplates.get(type);
         try {
             Writer w = new OutputStreamWriter(new FileOutputStream(file), ENCODING);
             template.process(dataMap, w);
             w.close();
             inputStream = new FileInputStream(file);
             response.setCharacterEncoding(ENCODING);
             response.setContentType("application/msexcel");
             response.setHeader("content-disposition", "attachment;filename="+ URLEncoder.encode(excelName + ".xls", ENCODING));
             out = response.getOutputStream();
             byte[] buffer = new byte[512]; // 缓冲区
             int bytesToRead = -1;
             // 通过循环将读入的Excel文件的内容输出到浏览器中
             while ((bytesToRead = inputStream.read(buffer)) != -1) {
                 out.write(buffer, 0, bytesToRead);
             }
             out.flush();
        } catch (Exception e) {
            logger.error("错误信息",e);
        }finally {
            if (inputStream != null){
                inputStream.close();
            }
            if (out != null){
                out.close();
            }
            if(file.delete()){  // 删除临时文件
                logger.debug("删除成功");
            }
    }
         
        
    }
   /**
     * 导出exce
     * @param dataMap 导出的数据Map
     * @param type    一个标识,可以随便写
     * @param valueName web-info下.ftl文件名称(后缀也要写上)
     * @param response 响应到浏览器 用于下载的一些设置
     * @param request  前台请求对象,获取一些路径等
     * @param excelName 导出文件的名称
     * @throws IOException
     */
    public static void createWord(Map<?, ?> dataMap, String type,String valueName,HttpServletResponse response,HttpServletRequest request,String wordName) throws IOException{
         InputStream inputStream = null;
         ServletOutputStream out = null;
         Map<String, Template> allTemplates = new HashMap<String, Template>();
         String realPath = request.getSession().getServletContext().getRealPath("/");
        try {
            request.setCharacterEncoding(ENCODING);
            Configuration configuration = new Configuration();
            configuration.setDefaultEncoding(ENCODING);
            configuration.setDirectoryForTemplateLoading(new File(realPath+"WEB-INF/mailtemplate"));
            allTemplates.put(type, configuration.getTemplate(valueName));
        } catch (IOException ex) {
            logger.error("错误信息",ex);
        }
        String name = "temp" + (int) (Math.random() * 100000) + ".doc";
         File file = new File(name);
         Template template = allTemplates.get(type);
         try {
             Writer w = new OutputStreamWriter(new FileOutputStream(file), ENCODING);
             template.process(dataMap, w);
             w.close();
             inputStream = new FileInputStream(file);
             response.setCharacterEncoding(ENCODING);
             response.setContentType("application/msword");
             response.setHeader("content-disposition", "attachment;filename="+ URLEncoder.encode(wordName + ".doc", ENCODING));
             out = response.getOutputStream();
             byte[] buffer = new byte[512]; // 缓冲区
             int bytesToRead = -1;
             // 通过循环将读入的Excel文件的内容输出到浏览器中
             while ((bytesToRead = inputStream.read(buffer)) != -1) {
                 out.write(buffer, 0, bytesToRead);
             }
             out.flush();
        } catch (Exception e) {
            logger.error("错误信息",e);
        }finally {
            if (inputStream != null)
                inputStream.close();
            if (out != null)
                out.close();
    }
         
        
    }
}

 

word下载和excel一样,word中有统计图的思路如下:(将统计图生成变量替换占位符)

1、插入一张图片占位。

2、获取ECharts图形生成的Base64编码格式的数据,保存到Map中。

3、在模板文件中,在占位的位置放入Map中的数据。

具体图文代码如下:

1.word中插入一张图片

2.获取ECharts图形生成的Base64编码格式的数据,保存到Map中。

一:前台获取Base64编码格式的数据如下:图片在word中的大小可在ECharts所在的jsp中调节。(怎样生成echarts和echarts赋值在上一篇中有介绍):下图中是两个ECharts。

 

java中Freemaker模板导出Word(统计图)和Excel详解(附工具类)

二:后台对获得的数据进行特殊处理:

java中Freemaker模板导出Word(统计图)和Excel详解(附工具类)

3、在模板文件中,在占位的位置放入Map中的数据。

java中Freemaker模板导出Word(统计图)和Excel详解(附工具类)

实现效果:点击页面的导出按钮,浏览器下载文件。