Excel导出功能是业务系统比较常见的功能,我们可以使用POI、Jexcel等来进行Excel的操作,然后再结合Spring MVC对两者的支持进行导出。但此方法的不足之处在于我们需要不厌其烦的进行Excel表格的操作。经过一番寻觅,发现了Jxls开源框架,使用模版生成导出文件。
初识Jxls
模版制作
如下为制作好的模版,【A1:D1】处的注解用来标识模版的边界,使用${}来标识我们需要填充的数据。【A4】处理的注解来用遍历一个集合,我们对集合的每个元素取名为item,每个元素的又可以使用${item.属性}来进行获取
包依赖
我们使用Maven来进行包依赖管理
<dependency>
<groupId>org.jxls</groupId>
<artifactId>jxls</artifactId>
<version>2.2.7</version>
</dependency>
<dependency>
<groupId>org.jxls</groupId>
<artifactId>jxls-poi</artifactId>
<version>1.0.6</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.13</version>
</dependency>
注意
使用Maven的 maven-resources-plugin
插件管理 resources
时,Maven会对模版进行转码处理,因此需要对xls格式的文件进行过滤,使其不处理。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<configuration>
<nonFilteredFileExtensions>
<nonFilteredFileExtension>pdf</nonFilteredFileExtension>
<nonFilteredFileExtension>swf</nonFilteredFileExtension>
<nonFilteredFileExtension>data</nonFilteredFileExtension>
<nonFilteredFileExtension>xls</nonFilteredFileExtension>
</nonFilteredFileExtensions>
</configuration>
</plugin>
</plugins>
</build>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
数据填充
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);
List<User> userList = queryUser();
context.putVar("users", userList);
JxlsHelper.getInstance().processTemplate(is, os, context);
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
效果展示
与Spring MVC结合
Spring提供了 AbstractExcelView
对提供对Excel导出的支持,继承该类的子类仅需要做Excel的处理。我们来看看Spring官网为我们提供的一个示例:
package excel;
public class HomePage extends AbstractExcelView {
protected void buildExcelDocument(Map model,
HSSFWorkbook wb, HttpServletRequest req,
HttpServletResponse resp) throws Exception {
HSSFSheet sheet;
HSSFRow sheetRow;
HSSFCell cell;
sheet = wb.createSheet("Spring");
sheet.setDefaultColumnWidth((short) 12);
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));
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
我们可以看到上面的例子中,我们需要对Excel进行一个个单元格的数据填充,这是一项很烦锁的工作。现在让我们来看下,Jxls与Spring MVC的结合如何优雅的完成Excel的导出。我们依旧使用上面所述的模版。
编写View
我们继承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<String, Object> 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();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
请求处理
@RequestMapping(value = "/test")
public ModelAndView export() {
Map<String, Object> model = new HashMap<>();
model.put("report_year", 2015);
model.put("report_month", 8);
List<User> userList = queryUser();
model.put("users", userList);
return new ModelAndView(new JxlsExcelView("template.xls","output"), model);
}
至此一个完整的Excel导出功能完成。是不是相当的简单及清晰?
相关及其它
其它支持
- 支持
jx:if
语法 - 支持Excel 公式
- Jxls同时还提供了对Excel读取封装
坑
以下为本人遇到过的问题,而本人实际使用的模版又较为复杂,有些问题需要跟踪代码来解决,因为错误提示有时不够友好。
- 数据没办法解析,编写模版时要格外仔细
- 数据遍历时Shift Row的格式问题
- 数据遍历时,集合为空问题