前言
在项目开发中,我们会遇到各种文件导出的开发场景,但是这种情况并都不常用,于是本人将自己工作中所用的代码封装成工具类,旨在记录工具类使用方法和技术分享。
一、Jxls的简介
Jxls是一个简单的、轻量级的excel导出库,使用特定的标记在excel模板文件中来定义输出格式和布局。Java中成熟的excel导出工具备Pol、Jxl,但他们都是使用java代码的方式来导出Excel,编码效率很低且不方便维护。
二、快速开始
1、导入依赖
<dependency> <groupId>org.jxls</groupId> <artifactId>jxls</artifactId> <version>2.4.6</version></dependency><dependency> <groupId>org.jxls</groupId> <artifactId>jxls-poi</artifactId> <version>1.0.12</version></dependency><dependency> <groupId>org.jxls</groupId> <artifactId>jxls-jexcel</artifactId> <version>1.0.6</version></dependency>
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<String, Object> model) throws IOException { Context context = PoiTransformer.createInitialContext(); if (model != null) { for (Map.Entry<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> buildData(ParamRequest request, SanSintUser sanSintUser) { Map<String, Object> map = new HashMap<>(); List<Map<String, Object>> energyFileExcelList = new ArrayList<>(); //从数据库查询出的数据集合 List<EnergyFile> 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 < list.size(); i++) { EnergyFile energyFile = list.get(i); Map<String, Object> dataMap = new LinkedHashMap<>(); dataMap.put("num", i + 1); dataMap.put("categoryName", energyFile.getCategoryName()); dataMap.put("itemName", energyFile.getItemName()); dataMap.put("fileName", energyFile.getFileName()); String fileType = buildFileType(energyFile); dataMap.put("fileType", fileType); String createUserName = energyFileService.selectCreateUserNameByUserId(energyFile.getCreateUser()); dataMap.put("createUserStr", createUserName); dataMap.put("createTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(energyFile.getCreateTime())); dataMap.put("deptName", energyFile.getDeptName()); dataMap.put("jobName", energyFile.getJobName()); dataMap.put("fileUrl", energyFile.getFileUrl()); energyFileExcelList.add(dataMap); }