jfinal框架下使用freemaker生成excel报表实践

来源:互联网 发布:r2r梯形网络 编辑:程序博客网 时间:2024/04/29 12:54

jfinal框架提供了对于freemaker模板引擎的支持,freemaker引擎支持后台数据向前台的映射,所在项目中页面展现使用的正是该框架。最近有需求,将数据导出为excel文件。搜集网上利用freemaker生成excel的教程,结合文件下载相关知识,实现了根据模板动态生成excel报表,并调用浏览器自带下载器进行下载的功能。
1. excel下创建如下模板,${}中为遍历数据List得到的单个记录对应的各个字段,由于jfinal中的数据表已通过addMapping映射到数据库,此处字段名为数据库中对应字段名。其中getNum(item.aID)为Model中根据表id获取数量的函数,本文所用的方法同样支持Model中函数结果的显示:
${}中为需要展示数据List下单个item各个字段列名
2. 另存为XML电子表格:
保存会弹出提示,选择是即可
3. 用notepad++等文本编辑器打开新创建的XML文件,修改XML文件如下标示位置,其中ExpandRowCount为数据行数+表头行数(固定值)。修改后保存,另存为ftl格式文件:
需要设定行数、添加freemaker遍历数据表语法
4. 添加通用模板解析类(参考文末链接):

    package util;      /**      * 模板解析实体类      */      import java.io.ByteArrayOutputStream;      import java.io.File;      import java.io.FileOutputStream;      import java.io.IOException;      import java.io.OutputStreamWriter;      import java.io.StringWriter;      import java.io.Writer;      import java.util.Map;      import freemarker.cache.StringTemplateLoader;      import freemarker.template.Configuration;      import freemarker.template.DefaultObjectWrapper;      import freemarker.template.Template;      import freemarker.template.TemplateException;      public class TemplateParseUtil {          /**          * 解析模板生成Excel          * @param templateDir  模板目录          * @param templateName 模板名称          * @param excelPath 生成的Excel文件路径          * @param data 数据参数          * @throws IOException          * @throws TemplateException          */          public static void parse(String templateDir,String templateName,String excelPath,Map<String,Object> data) throws IOException, TemplateException {              //初始化工作              Configuration cfg = new Configuration();              //设置默认编码格式为UTF-8              cfg.setDefaultEncoding("UTF-8");               //全局数字格式              cfg.setNumberFormat("0.00");              //设置模板文件位置              cfg.setDirectoryForTemplateLoading(new File(templateDir));              cfg.setObjectWrapper(new DefaultObjectWrapper());              //加载模板              Template template = cfg.getTemplate(templateName,"utf-8");              OutputStreamWriter writer = null;              try{                  //填充数据至Excel                  writer = new OutputStreamWriter(new FileOutputStream(excelPath),"UTF-8");                  template.process(data, writer);                  writer.flush();              }finally{                  writer.close();              }             }          /**          * 解析模板返回字节数组          * @param templateDir  模板目录          * @param templateName 模板名称          * @param data 数据参数          * @throws IOException          * @throws TemplateException          */          public static byte[] parse(String templateDir,String templateName,Map<String,Object> data) throws TemplateException, IOException{              Configuration cfg = new Configuration();              cfg.setDefaultEncoding("UTF-8");              cfg.setNumberFormat("0.00");              cfg.setDirectoryForTemplateLoading(new File(templateDir));              cfg.setObjectWrapper(new DefaultObjectWrapper());              Template template = cfg.getTemplate(templateName,"utf-8");              ByteArrayOutputStream outStream = new ByteArrayOutputStream();              Writer out = new OutputStreamWriter(outStream,"UTF-8");              template.process(data, out);              return outStream.toByteArray();          }          /**          * 自定义模板字符串解析          * @param templateStr  模板字符串          * @param data 数据            * @return 解析后的字符串          * @throws IOException          * @throws TemplateException          */          public static String parse(String templateStr, Map<String, Object> data)                  throws IOException, TemplateException {              Configuration cfg = new Configuration();              cfg.setNumberFormat("#.##");              //设置装载模板              StringTemplateLoader stringLoader = new StringTemplateLoader();               stringLoader.putTemplate("myTemplate", templateStr);                  cfg.setTemplateLoader(stringLoader);              //加载装载的模板              Template temp = cfg.getTemplate("myTemplate", "utf-8");              Writer out = new StringWriter();              temp.process(data, out);              return out.toString();          }      }  

5 对应AController中添加excel导出Action,使用类名_时间戳作为输出文件名,使用文件输出流调用浏览器自带下载器进行下载:

    /**     * @author zhangt      * 导出为excel(使用文件输出流)     */    public void exportExcel(){        List<A> aList = AService.service.listAll("*");        Map<String,Object> data = new HashMap<String, Object>();          data.put("dataList", aList);        String path = PathKit.getWebRootPath() + "/template";        Date now = new Date();        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");        String filename = "a_" + sdf.format(now) + ".xls";        HttpServletResponse response = this.getResponse();        response.addHeader("Content-disposition", "inline; filename=" + filename);        response.setContentType("application/vnd.ms-excel");        try {             ServletOutputStream out = response.getOutputStream();            out.write(TemplateParseUtil.parse(path, "test.ftl", data));            out.flush();            out.close();            renderNull();        } catch (IOException e) {              // TODO Auto-generated catch block              e.printStackTrace();          } catch (TemplateException e) {             // TODO Auto-generated catch block              e.printStackTrace();         }     }

也可以在服务器端生成报表,再使用jfinal框架提供的renderFile进行excel文件下载:

    /**     * @author zhangt      * 导出为excel(使用renderFile进行下载)     */    public void exportExcel(){        List<A> aList = AService.service.listAll("*");        Map<String,Object> data = new HashMap<String, Object>();          data.put("dataList", aList);        String path = PathKit.getWebRootPath() + "/template";        try {              TemplateParseUtil.parse(path, "test.ftl", path + "/a.xls", data);            renderFile("/template/a.xls");         } catch (IOException e) {              // TODO Auto-generated catch block              e.printStackTrace();          } catch (TemplateException e) {             // TODO Auto-generated catch block              e.printStackTrace();          }     }

6 ARoutes.java中进行路由配置,配置路径/a对应controller:

public class ARoutes extends Routes {    @Override    public void config() {        add("/a",AController.class);    }}

7 前端页面添加导出excel按钮:

<a href="javascript:;" onclick="Common.Redirect('${base}/a/exportExcel')" class="btn btn-primary radius"><i class="icon-plus"></i>导出excel</a>

参考文章:http://blog.csdn.net/u010722643/article/details/41732607

0 0
原创粉丝点击