關於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