前言
在项目开发中,我们会遇到各种文件导出的开发场景,但是这种情况并都不常用,于是本人将自己工作中所用的代码封装成工具类,旨在记录工具类使用方法和技术分享。
一、Jxls的简介
Jxls是一个简单的、轻量级的excel导出库,使用特定的标记在excel模板文件中来定义输出格式和布局。Java中成熟的excel导出工具备Pol、Jxl,但他们都是使用java代码的方式来导出Excel,编码效率很低且不方便维护。
二、快速开始
1、导入依赖
org.jxls jxls 2.4.6 org.jxls jxls-poi 1.0.12 org.jxls jxls-jexcel 1.0.6
2、定义导出的模板
导入依赖后,我们导出需要使用到模板,我们要先用word建立一个xlsx的模板(切记:新建excel工作表要使用xlsx格式,不要使用xls格式,因为使用xls导出的时候xlsx表格数据有可能会有问题)
建立好xlsx工作表了就根据实际需求的页面在xlsx表格上把需要的导出的框架画出来就可,赋值就要使用表达式了,表达式可以查看官网也可以查看我下方写的。官方网址,模板弄好之后,需要放在resource目录下,在Java中进行读取,下面代码中有具体实现。
如何写表达式,在工作表中右键插入批注,office中添加批注快捷键(Shit + F2)
jx:each(items="${collection}" var="item" lastCell="A3")
其中items是你传入的集合的名称,var是集合中每个对象的别名,lastCell是循环最后的位置
jx:area(lastCell="H3")
这里设置标题范围,最宽到H3
模板表达式
简单列举常用的几个表达式
(1)单个值的注入:
${variable},variable是你传入的参数的key
(2)迭代循环注入:
jx:each(items="${collection}" var="item" lastCell="A3")
其中items是你传入的集合的名称,var是集合中每个对象的别名,lastCell是循环最后的位置
(3)条件判断:
jx:if test="${condition}" 条件为真时执行的内容
(4)合并单元格:
jx:mergeCells(lastCell="合并单元格范围" [, cols="合并的列数"] [, rows="合并的行数"] [, minCols="要合并的最小列数"] [, minRows="要合并的最小行数"])
3、使用工具类
package com.sansint.industry.utils; import org.jxls.common.Context; import org.jxls.expression.JexlExpressionEvaluator; import org.jxls.transform.Transformer; import org.jxls.transform.poi.PoiTransformer; import org.jxls.util.JxlsHelper; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; /** * @author DongJiYong * jxls工具类 */ public class JxlsUtils { /** * 模板导出 * * @param is * @param os * @param model * @throws IOException */ public static void exportExcel(InputStream is, OutputStream os, Map model) throws IOException { Context context = PoiTransformer.createInitialContext(); if (model != null) { for (Map.Entry Entry : model.entrySet()) { context.putVar(Entry.getKey(), Entry.getValue()); } } JxlsHelper jxlsHelper = JxlsHelper.getInstance(); Transformer transformer = jxlsHelper.createTransformer(is, os); //获得配置 JexlExpressionEvaluator evaluator = (JexlExpressionEvaluator) transformer.getTransformationConfig().getExpressionEvaluator(); //设置静默模式,不报警告 evaluator.getJexlEngine().setSilent(true); //函数强制,自定义功能 Map funcs = new HashMap(); funcs.put("utils", new JxlsUtils()); evaluator.getJexlEngine().setFunctions(funcs); //必须要这个,否则表格函数统计会错乱 jxlsHelper.setUseFastFormulaProcessor(false).processTemplate(context, transformer); } /** * 导出excel * * @param templatePath * @param os * @param model * @throws Exception */ public static void exportExcel(String templatePath, OutputStream os, Map model) throws Exception { File template = getTemplate(templatePath); if (template != null) { exportExcel(new FileInputStream(template), os, model); } else { throw new Exception("Excel 模板未找到。"); } } /** * 获取jxls模板 * * @param path * @return */ public static File getTemplate(String path) { File template = new File(path); if (template.exists()) { return template; } return null; } /** * 设置响应头、文件名 * * @param response * @param fileName * @throws UnsupportedEncodingException */ public static void setResponse(HttpServletResponse response, String fileName) throws UnsupportedEncodingException { fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20"); response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding("UTF-8"); } }
4、Controller层代码
使用该工具类主要在Controller层或者Service层封装好导出的数据和导出流即可,本人是在Controller层进行封装的数据。
/*** * excel导出 * @param request * @param sanSintUser */ @GetMapping("/excel") public void excelDownload(ParamRequest request, SanSintUser sanSintUser, HttpServletResponse response) { try { //根据定义的excel模板 构建导出的数据 Map map = buildData(request, sanSintUser); //设置导出流 JxlsUtils.setResponse(response, "能源档案信息"); // 获取excel模版路径 InputStream tplIs = Thread.currentThread().getContextClassLoader().getResourceAsStream("template/档案列表.xlsx"); JxlsUtils.exportExcel(tplIs, response.getOutputStream(), map); } catch (IOException e) { throw new RuntimeException(e); } } private Map buildData(ParamRequest request, SanSintUser sanSintUser) { Map map = new HashMap(); List energyFileExcelList = new ArrayList(); //从数据库查询出的数据集合 List list = new ArrayList(); if (!CollectionUtils.isEmpty(request.getIds())) { //如果有id,则查询id对应的能源档案信息 list = energyFileService.selectEnergyFileByIds(request.getIds()); } else { //如果没有id,则查询全部能源档案信息 EnergyFile energyFile = new EnergyFile(); energyFile.setTenantId(sanSintUser.getTenantId()); list = energyFileService.selectEnergy(energyFile); } //构建excel数据 for (int i = 0; i