jxls最新版本的ExcelUtil导出工具类
jXLS 的功能是:只使用几行代码就可以建立极端复杂的 Excel 报表。你所需要实现的大部分工作是建立 XLS 模板文件,完成所需要的格式,公式和宏等等,使用注释来指示出数据需要填入的位置。接着写几行代码调用 jXLS 引擎解析 XLS 模板文件并将数据作为参数输入到报表文件中。相对于POI,可以更加方便的设计出表结构比较复杂的excel.
1. jxls-core功能相对简单,无法提供自定义函数增强。但是相应的excel的模板设定中,可以不适用批注。本人不推荐使用
推荐使用第二种依赖 :jxls-api依赖 推荐
<!-- jxls-api依赖 功能较弱,无法提供自定义方法--> <!-- <dependency> <groupId>net.sf.jxls</groupId> <artifactId>jxls-core</artifactId> <version>1.0.3</version> </dependency>--> <!-- jxls-api依赖 推荐--> <dependency> <groupId>org.jxls</groupId> <artifactId>jxls-poi</artifactId> <version>${jxls-poi.version}</version> </dependency> <dependency> <groupId>org.jxls</groupId> <artifactId>jxls</artifactId> <version>${jxls-poi.version}</version> </dependency>
2. ExcelUtil的工具类封装 提供了一些方法重载和一个默认的函数增强。
package com.common.base.utils; import org.apache.commons.jexl3.JexlBuilder; import org.apache.commons.lang3.time.DateFormatUtils; import org.jxls.common.Context; import org.jxls.expression.JexlExpressionEvaluator; import org.jxls.transform.Transformer; import org.jxls.transform.poi.PoiTransformer; import org.jxls.transform.poi.WritableCellValue; import org.jxls.transform.poi.WritableHyperlink; import org.jxls.util.JxlsHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; import java.lang.reflect.Field; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Optional; /** * jxls2.6以上版本适用 * Excel 导出工具类 * @Auther: tony_t_peng * @Date: 2020-10-27 13:35 * @Description: */ public class ExcelUtil { public static Logger logger = LoggerFactory.getLogger(ExcelUtil.class); /** * 导出excel * @param template 模板文件 * @param targetFile 目标文件 * @param model jxls表达式数据 * @Author tony_t_peng * @Date 2020-10-28 11:54 */ public static void exportExcel(File template, File targetFile, Map<String, Object> model) throws IOException { exportExcel(template, targetFile, model,buildFuncs()); } /** * 导出excel * @param template 模板文件 * @param targetFile 目标文件 * @param t jxls表达式数据 * @Author tony_t_peng * @Date 2020-10-28 11:54 */ public static <T> void exportExcel(File template, File targetFile, T... t) throws IOException, IllegalAccessException { exportExcel(template, targetFile, buildFuncs(),t); } /** * 导出excel * @param template 模板文件 * @param targetFile 目标文件 * @param t jxls表达式数据 * @param funcs 自定义函数增强 * @Author tony_t_peng * @Date 2020-10-28 11:54 */ public static <T> void exportExcel(File template, File targetFile,Map<String, Object> funcs, T... t) throws IOException, IllegalAccessException { FileOutputStream fileOutputStream = null; try{ fileOutputStream = new FileOutputStream(targetFile); exportExcel(new FileInputStream(template), fileOutputStream, buildContext(t),buildFuncs(funcs)); }finally { if(fileOutputStream!=null){ fileOutputStream.close(); } } } /** * 导出excel * @param template 模板文件 * @param targetFile 目标文件 * @param model jxls表达式数据 * @param funcs 自定义函数增强 * @Author tony_t_peng * @Date 2020-10-28 11:54 */ public static void exportExcel(File template, File targetFile, Map<String, Object> model,Map<String, Object> funcs) throws IOException { FileOutputStream fos = null; FileInputStream fis=null; try{ fos = new FileOutputStream(targetFile); fis = new FileInputStream(template); exportExcel(fis, fos, buildContext(model),buildFuncs(funcs)); }finally { if(fos!=null){ fos.close(); } if(fis!=null){ fis.close(); } } } /** * 导出excel * @param is 输入流 * @param os 输出流 * @param model jxls表达式数据 * @Author tony_t_peng * @Date 2020-10-28 11:54 */ public static void exportExcel(InputStream is, OutputStream os, Map<String, Object> model) throws IOException { exportExcel(is, os, buildContext(model),buildFuncs()); } /** * 导出excel * @param is 输入流 * @param os 输出流 * @Author tony_t_peng * @Date 2020-10-28 11:54 */ public static <T> void exportExcel(InputStream is, OutputStream os, T... t) throws IOException, IllegalAccessException { exportExcel(is, os, buildContext(t),buildFuncs()); } /** * 导出excel * @param is 输入流 * @param os 输出流 * @param context jxls表达式数据源 * @param funcs 自定义函数增强 * @Author tony_t_peng * @Date 2020-10-28 11:54 */ public static void exportExcel(InputStream is, OutputStream os,Context context,Map<String, Object> funcs) throws IOException { JxlsHelper jxlsHelper = JxlsHelper.getInstance(); Transformer transformer = jxlsHelper.createTransformer(is, os); //获得配置 JexlExpressionEvaluator evaluator = (JexlExpressionEvaluator)transformer.getTransformationConfig().getExpressionEvaluator(); //函数增强 if(funcs!=null){ evaluator.setJexlEngine(new JexlBuilder().namespaces(funcs).create()); } //必须要这个,否者表格函数统计会错乱 jxlsHelper.setUseFastFormulaProcessor(false).processTemplate(context, transformer); } /*** * 组装context * @Author tony_t_peng * @Date 2020-10-28 16:02 */ private static Context buildContext(Map<String, Object> model){ Context context = PoiTransformer.createInitialContext(); if (model != null) { for (String key : model.keySet()) { context.putVar(key, model.get(key)); } } return context; } /*** * 组装context * @Author tony_t_peng * @Date 2020-10-28 16:02 */ private static <T> Context buildContext(T... t) throws IllegalAccessException { Context context = PoiTransformer.createInitialContext(); if(t!=null){ for(T t1:t){ Field[] declaredFields = t1.getClass().getDeclaredFields(); for (Field field : declaredFields) { field.setAccessible(true); context.putVar(field.getName(), field.get(t1)); } } } return context; } /** * 默认自定义函数增强 * @Author tony_t_peng * @Date 17:37 */ private static Map<String, Object> buildFuncs(Map<String, Object> funcs){ if(funcs==null){ funcs = new HashMap<>(); } funcs.put("excelUtil",new ExcelUtil()); return funcs; } /** * 默认自定义函数增强 * @Author tony_t_peng * @Date 17:37 */ private static Map<String, Object> buildFuncs(){ Map<String, Object> funcs = new HashMap<>(); funcs.put("excelUtil",new ExcelUtil()); return funcs; } //超链接 public WritableCellValue myHyperlink(String address, String title) { return new WritableHyperlink(address, title); } /** * 日期转换 */ public String dateToString(Date date, String pattern) { return DateFormatUtils.format(date, pattern); } }
3.excel模板定义:
在最新版本jxls(jxls2.6以上版本适用)的模板定义中,需要增加批注以确定excle模板数据加载的范围.
注:A1的栏位上需要加上批注,该批注用于确定模板数据加载范围。 批注格式为 jx:area(lastCell="F5")
如果需要循环加载数据也可以使用批注 jx:each(items="data" var="item" lastCell="E3")
查看源码:JXLS中加载模板的代码中,会去那批注确定的范围。所以A1上面一定要加上批注,否则JXL表达式不会被解析