jXLS的Excel标记分为3种:
- Bean属性标记
- 区域标记
- 命令标记
jXLS提供XlsCommentAreaBuilder类从Excel单元格注释读取标记。XlsCommentAreaBuilder实现通用AreaBuilder接口。AreaBuilder接口如下所示:
public interface AreaBuilder {
List<Area> build();
}
这是一个单方法简单接口,返回一个Area对象列表。因此,如果你想要定义自己的标记,可以创建自己的AreaBuilder实现,解释输入Excel模板或任意其它输入。
1 Bean属性标记
jXLS使用Apache JEXL表达式语言处理Bean属性标记。在未来版本中,可以配置表达式语言引擎,以便在需要时可以用任何其他表达式引擎替换JEXL。默认,jXLS期望JEXL表达式放在模板文件中的${和}之间。例如,以下单元格内容${department.chief.age} years告诉jXLS,假设,在Context中有一个department对象有一个chief对象有一个age属性,使用JEXL计算department.chief.age。如果表达式department.getChief().getAge()计算等于35,jXLS将放置35 years在单元格中。
2 区域标记
jXLS区域标记用于定义jXLS引擎处理的根XlsArea。XlsCommentAreaBuilder支持的Excel单元格注释区域定义语法如下所示:
jx:area(lastCell="<LAST_CELL>")
<LAST_CELL>定义矩形区域右下角单元格。第一个单元格是定义Excel注释的单元格。因此,假设我们有一个注释jx:area(lastCell="G12")在单元格A1中,根区域将读取A1:G12。
XlsCommentAreaBuilder应该用于从模板文件读取所有区域。例如,以下代码读取所有区域到xlsAreaList,然后保存第一个区域到xlsArea变量:
AreaBuilder areaBuilder = new XlsCommentAreaBuilder(transformer);
List<Area> xlsAreaList = areaBuilder.build();
Area xlsArea = xlsAreaList.get(0);
大多数情况下,定义一个根区域就足够了。
3 命令标记
命令应该定义在XlsArea中。XlsCommentAreaBuilder接收以下命令符创建Excel单元格注释:
jx:<command_name>(attr1='val1' attr2='val2' ... attrN='valN' lastCell=<last_cell> areas=["<command_area1>", "<command_area2", ... "<command_areaN>"])
<command_name>是在XlsCommentAreaBuilder中预注册或手动注册的命令名称。当前,预注册了以下命令:
- each
- if
- image
使用XlsCommentAreaBuilder的static void addCommandMapping(String commandName, Class clazz)方法注册自定义命令。
attr1, attr2,…, attrN是命令属性。
例如,if命令有condition属性设置条件表达式。
<last_cell>定义命令区域的右下角单元格。右上角由注释所在单元格决定。
<command_area1>, <command_area2>, … <command_areaN>——区域作为参数传递给命令。
例如,if命令期望以下区域被定义:
- ifArea:当if条件计算为true时,输出区域的引用。
- elseArea(可选):当if条件计算为false时,输出区域的引用。
if命令的区域属性定义如下所示:
areas=["A8:F8","A13:F13"]
一个单元格注释可以定义多个命令。例如,Each和If命令:
jx:each(items="department.staff", var="employee", lastCell="F8")
jx:if(condition="employee.payment <= 2000", lastCell="F8", areas=["A8:F8","A13:F13"])
4 表达式语言
默认,jXLS使用Apache JEXL表达式语言计算Excel模板文件中的属性表达式。
4.1 自定义JEXL处理
如果你需要自定义JEXL处理,可以从Transformer获取JexlEngine引用并设置必须的配置。
例如,以下代码在demo命名空间注册一个自定义JEXL函数:
Transformer transformer = TransformerFactory.createTransformer(is, os);
// ...
JexlExpressionEvaluator evaluator = (JexlExpressionEvaluator) transformer
.getTransformationConfig()
.getExpressionEvaluator();
Map<String, Object> functionMap = new HashMap<>();
functionMap.put("demo", new JexlCustomFunctionDemo());
evaluator.getJexlEngine()
.setFunctions(functionMap);
下面是JexlCustomerFunctionDemo类:
public Integer mySum(Integer x, Integer y){
return x + y;
}
因此,模板中可以这样使用函数:
${demo:mySum(x,y)}
x和y是Context中的参数。
4.2 改变表达式引擎
你可能不喜欢使用Apache JEXL,而想要使用其它表达式处理引擎,例如,SpEL。jXLS允许你使用喜欢的计算引擎替代默认的计算引擎。
你只需要实现ExpressionEvaluator接口的一个方法委托表达式计算处理给你想要的引擎:
public interface ExpressionEvaluator {
Object evaluate(String expression, Map<String,Object> context);
}
然后,传入你的ExpressionEvaluator实现给TransformationConfig:
ExpressionEvaluator evaluator = new MyCustomEvaluator(); // 基于SpEL的自定义实现
transformer.getTransformationConfig().setExpressionEvaluator(evaluator);