关于java对于导出excel的工具有很多,如Apache poi、alibaba的easyexcel、jxl、hutool等,但是对于表头的映射,比较麻烦,如果数据是Map,通过注解的方法就没法处理表头。
在不关注如何映射表头是,想到有模板的方式,那就是用 jxls 工具。
各种工具的效率问题先不讨论。
JXLS
jxls是一个简单的、轻量级的excel导出库,使用特定的标记在excel模板文件中来定义输出格式和布局。
jxls是通过预制excel模板,然后通过jxls相应API将我们应用程序的数据结合模板格式输出到相应的excel文件中,从而形成报表。
示例如下:
1、导出如下报表数据
2、excel模板
说明:其中C列和H列,使用了自定义方法;C列方法的作用是将字典code转换为name文字值,H列方法的作用是计算D->G列的和。
数据如下:
{ "list": [ { "saleId": 1347929495306274, "saleName": "测试业绩目标-教务", "schoolId": 31, "schoolName": "绍兴本部校", "svList": [ { "data": { "1": 2, "2": 0, "3": 0, "4": 0 }, "svType": 1 }, { "data": { "1": 1, "2": 0, "3": 0, "4": 0 }, "svType": 2 }, { "data": { "1": 1, "2": 0, "3": 0, "4": 0 }, "svType": 4 }, { "data": { "1": 0.50, "2": 0, "3": 0, "4": 0 }, "svType": 3 }, { "data": { "1": 0.50, "2": 0, "3": 0, "4": 0 }, "svType": 5 } ] }, { "schoolName": "总计", "svList": [ { "data": { "1": 37, "2": 0, "3": 2, "4": 0 }, "svType": 1 }, { "data": { "1": 33, "2": 0, "3": 2, "4": 0 }, "svType": 2 }, { "data": { "1": 38, "2": 0, "3": 2, "4": 0 }, "svType": 4 }, { "data": { "1": 0.89, "2": 0, "3": 1.00, "4": 0 }, "svType": 3 }, { "data": { "1": 1.03, "2": 0, "3": 1.00, "4": 0 }, "svType": 5 } ] } ] }
3、导出方法代码片段
项目引入jxls
<!-- jxls --> <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.15</version> </dependency>
该示例以HttpServletResponse response返回文件流,前端直接下载
controller方法:
@RequestMapping("/record/clue/saler") public void exportSalerResource(HttpServletRequest request, HttpServletResponse response, @RequestBody Map<String, Object> reqMap) { //获取数据 PageInfo<Map<String, Object>> pageInfo = clueRecordService.querySalerClueReport(reqMap); List<Map<String, Object>> dataList = pageInfo.getList(); Map<String , Object> model=new HashMap<String , Object>(); model.put("dataList", dataList); //模板 String templatePath = "classpath:temp/resource_saler.xlsx"; //导出文件名称 String exportFileName = "咨询师资源报表.xlsx"; //导出 JxlsExportUtils.doExcelExport(request, response, model, templatePath, exportFileName); }
JxlsExportUtils:
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.ObjectUtils; import org.jxls.common.Context; import org.jxls.expression.JexlExpressionEvaluator; import org.jxls.transform.Transformer; import org.jxls.util.JxlsHelper; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.util.ResourceUtils; import com.sy.common.conts.CommonConts.BillStateEnum; import com.sy.common.conts.CommonConts.ClueFromTypeEnum; import com.sy.common.conts.CommonConts.ClueSV; import com.sy.common.conts.CommonConts.ClueSourceEnum; import com.sy.common.conts.CommonConts.OrderStateEnum; import com.sy.common.conts.CommonConts.PayTypeEnum; import com.sy.common.conts.CommonConts.UserTypeEnum; import cn.hutool.core.io.IoUtil; @Slf4j public class JxlsExportUtils { /** * 导出执行方法 * @param request * @param response * @param model * @param templatePath 模板 * @param selfFileName 导出文件名 */ public static void doExcelExport(HttpServletRequest request, HttpServletResponse response, Map<String, Object> model, String templatePath, String exportFileName) { //导出文件名重编码 String fileName = FileExportProcess.processFileName(exportFileName, request, response); response.reset(); response.setContentType("application/vnd.ms-excel;charset=utf-8"); //设置文件类型 response.setHeader("Content-Disposition", "attachment;filename=" + fileName); OutputStream outputStream = null; InputStream inputStream = null; try { //输出流为请求响应 outputStream = response.getOutputStream(); //模板文件流 inputStream = getTemplateInputStream(templatePath); //getTemplateStream(templatePath); //模板数据构建 exportExcel(inputStream, outputStream, model); } catch (IOException e) { log.info("模板填充异常:{}", e); } finally { //释放资源 if (outputStream != null) { IoUtil.flush(outputStream); IoUtil.close(outputStream); } if (inputStream != null) { IoUtil.close(inputStream); } } } /** * 模板处理方法 * @param is * @param os * @param model * @throws IOException */ public static void exportExcel(InputStream is, OutputStream os, Map<String, Object> model) throws IOException { if (is == null) { log.info("获取模板异常,模板文件流为空!"); } Context context = new Context(); if (model != null) { for (String key : model.keySet()) { context.putVar(key, model.get(key)); } } JxlsHelper jxlsHelper = JxlsHelper.getInstance(); Transformer transformer = jxlsHelper.createTransformer(is, os); JexlExpressionEvaluator evaluator = (JexlExpressionEvaluator)transformer.getTransformationConfig().getExpressionEvaluator(); Map<String, Object> funcs = new HashMap<String, Object>(); funcs.put("utils", new JxlsExportUtils()); // 添加自定义功能,可在excel模板中,可直接使用该自定义对象的方法 evaluator.getJexlEngine().setFunctions(funcs); jxlsHelper.processTemplate(context, transformer); } public static InputStream getTemplateInputStream(String path) throws IOException { log.info("模板路径为:{}", path); Resource resource = new ClassPathResource(path); InputStream templateInputStream = resource.getInputStream(); return templateInputStream; } /* 统计量(应该使用枚举) */ public String descResourceSV(Integer code) { String str = ""; if (code == 1) { str = "新增资源量"; } else if (code == 2) { str = "新增成交量"; } else if (code == 3){ str = "新增转化率"; } else if (code == 4){ str = "总成交量"; } else { str = "总转化率"; } return str; } /* map中value求和 */ public BigDecimal doSum(Map<String, Object> items) { BigDecimal sum = BigDecimal.ZERO; if (items != null) { for (Entry<String, Object> entry : items.entrySet()) { String value = ObjectUtils.toString(entry.getValue()); sum = sum.add(new BigDecimal(value)); } } return sum; } }
注意:模板中使用的自定义方法
Map<String, Object> funcs = new HashMap<String, Object>();
funcs.put("utils", new JxlsExportUtils()); // 添加自定义功能,可在excel模板中,可直接使用该自定义对象的方法
evaluator.getJexlEngine().setFunctions(funcs);
4、导出结果
标签语法逻辑还可参考:https://yq.aliyun.com/articles/628239