jxls2.3-简明教程
jxls是一个简单的、轻量级的excel导出库,使用特定的标记在excel模板文件中来定义输出格式和布局。java中成熟的excel导出工具有pol、jxl,但他们都是使用java代码的方式来导出excel,编码效率很低且不方便维护。
另外,jxls2.3的运行效率也相当不错,经过测试,在禁用日志输出的情况下,导出excel单表66535条记录仅仅3000毫秒,与poi几乎没什么大的差距。
demo工程源码下载:https://files.cnblogs.com/files/klguang/jxls-demo.zip
springboot-demo下载:https://files.cnblogs.com/files/klguang/jxls-springboot.zip
excel模板示例:
Excel模板标记在jxls中的作用分为三部分:
- bean属性标记
- XLS Area定义标记
- XLS Command表示标记
bean属性标记
jxls使用 Apache JEXL表达式语言来解析定义在excel模板中的表达式。JEXL与JSTL相似,并对JSTL进行了扩展。eg:
${department.chief.age} //属性可以是无限深度
${utils:dateFmt(date,"yyyy-MM-dd")} //自定义工具函数
XLS Area定义标记
XLS Area 是JxlsPlus中的一个重要概念,它代表excel模板中需要被解析的矩形区域,由A1到最后一个单元格表示,有利于加快解析速度。
XLS Area 使用excel注释标注表示,它需要被定义在excel 模板的第一个单元格(A1):
jx:area(lastCell = "<AREA_LAST_CELL>")
这个标记定义了excel模板需要被解析的矩形区域为:A1到<AREA_LAST_CELL>。
XLS Command表示标记
XLS Command 使用excel注释标注表示,命令格式如下:
jx:<command_name>(attr1='val1' attr2='val2' ... attrN='valN' lastCell=<last_cell> areas=["<command_area1>", "<command_area2", ... "<command_areaN>"])
<command_name> 是库自带的命名或是用户自定义并注册到XlsCommentAreaBuilder的命令。
each 命令是最常用的XLS命令,形如:
jx:each(items="employees" var="employee" lastCell="D4")
each 可以有如下一些属性:
- items 上下文中集合的变量名;
- var 在遍历集合的时候每一条记录的变量名;
- area 该XLS Command的解析区域;
- direction 数据在excel中填充的方向,默认(DOWN)向下;
- select 其值为一个表达式,用来过滤数据。
jexl自定义工具函数
如果你需要自定jexl来处理数据,你可以从Transformer对象获取JexlEngine引用,并对其配置。
下面的例子实现了将一个自定义jexl函数注册到utils命名空间下:
1 2 3 4 5 6 | 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 JxlsUtils()); //添加自定义功能 evaluator.getJexlEngine().setFunctions(funcs); |
demo
工程目录:
Employee.java
1 2 3 4 5 6 7 8 | public class Employee { private String name; private Date birthDate; private BigDecimal payment; private BigDecimal bonus; // getter and setter } |
建立excel模板:
工具类JxlsUtils.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | public class JxlsUtils { public static void exportExcel(InputStream is, OutputStream os, Map<String, Object> model) throws IOException { 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 JxlsUtils()); // 添加自定义功能 evaluator.getJexlEngine().setFunctions(funcs); jxlsHelper.processTemplate(context, transformer); } // 日期格式化 public String dateFmt(Date date, String fmt) { if (date == null ) { return "" ; } try { SimpleDateFormat dateFmt = new SimpleDateFormat(fmt); return dateFmt.format(date); } catch (Exception e) { e.printStackTrace(); } return "" ; } // if判断 public Object ifelse( boolean b, Object o1, Object o2) { return b ? o1 : o2; } } |
入口ObjectCollectionDemo.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | public class ObjectCollectionDemoXlsx { static Logger logger = LoggerFactory.getLogger(ObjectCollectionDemoXlsx. class ); public static void main(String[] args) throws ParseException, IOException { logger.info( "Running Object Collection demo" ); List employees = generateSampleEmployeeData(); OutputStream os = new FileOutputStream( "target/object_collection_output.xlsx" ); Map model= new HashMap(); model.put( "employees" , employees); model.put( "nowdate" , new Date()); InputStream inputStream = ObjectCollectionDemoXlsx. class .getClassLoader() .getResourceAsStream( "jxls-template/object_collection_template.xlsx" ); JxlsUtils.exportExcel(inputStream, os, model); os.close(); } public static List generateSampleEmployeeData() throws ParseException { List employees = new ArrayList(); SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyy-MMM-dd" , Locale.US); employees.add( new Employee( "Elsa" , dateFormat.parse( "1970-Jul-10" ), 1500 , 0.15 ) ); employees.add( new Employee( "Oleg" , dateFormat.parse( "1973-Apr-30" ), 2300 , 0.25 ) ); employees.add( new Employee( "Neil" , dateFormat.parse( "1975-Oct-05" ), 2500 , 0.00 ) ); employees.add( new Employee( "Maria" , dateFormat.parse( "1978-Jan-07" ), 1700 , 0.15 ) ); employees.add( new Employee( "John" , dateFormat.parse( "1969-May-30" ), 2800 , 0.20 ) ); return employees; } } |
生成效果:
【推荐】FlashTable:表单开发界的极速跑车,让你的开发效率一路狂飙
【推荐】Flutter适配HarmonyOS 5知识地图,实战解析+高频避坑指南
【推荐】博客园的心动:当一群程序员决定开源共建一个真诚相亲平台
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· JavaScript中如何遍历对象?
· 领域模型应用
· 记一次 ADL 导致的 C++ 代码编译错误
· MySQL查询执行顺序:一张图看懂SQL是如何工作的
· 为什么PostgreSQL不自动缓存执行计划?
· 从被喷“假开源”到登顶 GitHub 热榜,这个开源项目上演王者归来!
· Stack Overflow,轰然倒下!
· 35+程序员的转型之路:经济寒冬中的希望与策略
· 2025年推荐6个好用的 Postman 替代工具
· 全球首位 AI 程序员 Devin 诞生了,对于程序员的影响到底多大?