Excel导出功能是业务系统比较常见的功能,我们可以使用POI、Jexcel等来进行Excel的操作,然后再结合Spring MVC对两者的支持进行导出。但此方法的不足之处在于我们需要不厌其烦的进行Excel表格的操作。经过一番寻觅,发现了Jxls开源框架,使用模版生成导出文件。
如下为制作好的模版,【A1:D1】处的注解用来标识模版的边界,使用${}来标识我们需要填充的数据。【A4】处理的注解来用遍历一个集合,我们对集合的每个元素取名为item,每个元素的又可以使用${item.属性}来进行获取
我们使用Maven来进行包依赖管理
org.jxls
jxls
2.2.7
org.jxls
jxls-poi
1.0.6
org.apache.poi
poi
3.13
注意
使用Maven的 maven-resources-plugin
插件管理 resources
时,Maven会对模版进行转码处理,因此需要对xls格式的文件进行过滤,使其不处理。
org.apache.maven.plugins
maven-resources-plugin
2.6
pdf
swf
data
xls
try (InputStream is = Demo.class.getClassLoader().getResourceAsStream("template.xls")) {
try (OutputStream os = new FileOutputStream("output.xls")) {
Context context = new Context();
context.putVar("report_year", 2015);
context.putVar("report_month", 8);
//queryUser()为数据获取的方法
List userList = queryUser();
context.putVar("users", userList);
JxlsHelper.getInstance().processTemplate(is, os, context);
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
Spring提供了 AbstractExcelView
对提供对Excel导出的支持,继承该类的子类仅需要做Excel的处理。我们来看看Spring官网为我们提供的一个示例:
package excel;
// imports omitted for brevity
public class HomePage extends AbstractExcelView {
protected void buildExcelDocument(Map model,
HSSFWorkbook wb, HttpServletRequest req,
HttpServletResponse resp) throws Exception {
HSSFSheet sheet;
HSSFRow sheetRow;
HSSFCell cell;
// Go to the first sheet
// getSheetAt: only if wb is created from an existing document
// sheet = wb.getSheetAt(0);
sheet = wb.createSheet("Spring");
sheet.setDefaultColumnWidth((short) 12);
// write a text at A1
cell = getCell(sheet, 0, 0);
setText(cell, "Spring-Excel test");
List words = (List) model.get("wordList");
for (int i=0; i < words.size(); i++) {
cell = getCell(sheet, 2+i, 0);
setText(cell, (String) words.get(i));
}
}
}
我们可以看到上面的例子中,我们需要对Excel进行一个个单元格的数据填充,这是一项很烦锁的工作。现在让我们来看下,Jxls与Spring MVC的结合如何优雅的完成Excel的导出。我们依旧使用上面所述的模版。
我们继承Spring提供的 AbstractView
抽象类。
import org.jxls.common.Context;
import org.jxls.util.JxlsHelper;
import org.springframework.web.servlet.view.AbstractView;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;
public class JxlsExcelView extends AbstractView {
private static final String CONTENT_TYPE = "application/vnd.ms-excel";
private String templatePath;
private String exportFileName;
/**
* @param templatePath 模版相对于当前classpath路径
* @param exportFileName 导出文件名
*/
public JxlsExcelView(String templatePath, String exportFileName) {
this.templatePath = templatePath;
if (exportFileName != null) {
try {
exportFileName = URLEncoder.encode(exportFileName, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
this.exportFileName = exportFileName;
setContentType(CONTENT_TYPE);
}
@Override
protected void renderMergedOutputModel(
Map model,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
Context context = new Context(model);
response.setContentType(getContentType());
response.setHeader("content-disposition",
"attachment;filename=" + exportFileName + ".xls");
ServletOutputStream os = response.getOutputStream();
InputStream is = getClass().getClassLoader().getResourceAsStream(templatePath);
JxlsHelper.getInstance().processTemplate(is, os, context);
is.close();
}
}
@RequestMapping(value = "/test")
public ModelAndView export() {
Map model = new HashMap<>();
model.put("report_year", 2015);
model.put("report_month", 8);
//queryUser()为数据获取的方法
List userList = queryUser();
model.put("users", userList);
return new ModelAndView(new JxlsExcelView("template.xls","output"), model);
}
至此一个完整的Excel导出功能完成。是不是相当的简单及清晰?
jx:if
语法以下为本人遇到过的问题,而本人实际使用的模版又较为复杂,有些问题需要跟踪代码来解决,因为错误提示有时不够友好。
Spring 官方文档
Jxls 官网文档