您的位置:首页 > 编程语言 > Java开发

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

2016-12-29 20:22 357 查看
jfinal框架提供了对于freemarker模板引擎的支持,freemarker引擎支持后台数据向前台的映射,所在项目中页面展现使用的正是该框架。最近有需求,将数据导出为excel文件。搜集网上利用freemarker生成excel的教程,结合文件下载相关知识,实现了根据模板动态生成excel报表,并调用浏览器自带下载器进行下载的功能。

1. excel下创建如下模板,${}中为遍历数据List得到的单个记录对应的各个字段,由于jfinal中的数据表已通过addMapping映射到数据库,此处字段名为数据库中对应字段名。其中getNum(item.aID)为Model中根据表id获取数量的函数,本文所用的方法同样支持Model中函数结果的显示:



2. 另存为XML电子表格:



3. 用notepad++等文本编辑器打开新创建的XML文件,修改XML文件如下标示位置,其中ExpandRowCount为数据行数+表头行数(固定值)。修改后保存,另存为ftl格式文件:



4. 添加通用模板解析类(参考文末链接):

package util
4000
;
/**
* 模板解析实体类
*/
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  excel freemaker jfinal java