前言
有些时侯我们需要根据Excel模板,导出Excel数据,主要是通过java中替换报表变量部分,然后其它如汇总求和等还是借用原来的Excel函数进行运算。
目前有如下方案可以解决我们的需求,一种是通过国内的easyPOI,还有国外的JXLS。
我们本节主要通过JXLS实现我们的基本需求。
LXLS 2.4.0 简介
jxls2.4 是java对excel操作的工具包,可以很方便的实用模板输出excel,根据xml配置读取excel内容。
对比jxls1 现在的版本使用批注的模式运行指令,可以支持excel中使用公式,07的excel。官方地址
官方DEMO
本节基础来源于meijm0103
业务实现
引入依赖
<dependency>
<groupId>org.jxls</groupId>
<artifactId>jxls</artifactId>
<version>2.4.5</version>
</dependency>
<dependency>
<!-- 可以使用poi的实现也可以用jexcelapi的 -->
<groupId>org.jxls</groupId>
<artifactId>jxls-poi</artifactId>
<version>1.0.15</version>
</dependency>
<dependency>
<groupId>org.jxls</groupId>
<artifactId>jxls-jexcel</artifactId>
<version>1.0.7</version>
</dependency>
工具类
package com.joery.hlutils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.jxls.common.Context;
import org.jxls.expression.JexlExpressionEvaluator;
import org.jxls.transform.Transformer;
import org.jxls.transform.poi.PoiTransformer;
import org.jxls.util.JxlsHelper;
public class JxlsUtils{
public static void exportExcel(InputStream is, OutputStream os, Map<String, Object> model) throws IOException{
Context context = PoiTransformer.createInitialContext();
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();
//设置静默模式,不报警告
//evaluator.getJexlEngine().setSilent(true);
//函数强制,自定义功能
Map<String, Object> funcs = new HashMap<String, Object>();
funcs.put("utils", new JxlsUtils()); //添加自定义功能
evaluator.getJexlEngine().setFunctions(funcs);
//必须要这个,否者表格函数统计会错乱
jxlsHelper.setUseFastFormulaProcessor(false).processTemplate(context, transformer);
}
public static void exportExcel(File xls, File out, Map<String, Object> model) throws FileNotFoundException, IOException {
exportExcel(new FileInputStream(xls), new FileOutputStream(out), model);
}
public static void exportExcel(String templatePath, OutputStream os, Map<String, Object> model) throws Exception {
File template = getTemplate(templatePath);
if(template != null){
exportExcel(new FileInputStream(template), os, model);
} else {
throw new Exception("Excel 模板未找到。");
}
}
//获取jxls模版文件
public static File getTemplate(String path){
File template = new File(path);
if(template.exists()){
return template;
}
return null;
}
// 日期格式化
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;
}
}
有两点需要讲一下:
1.静默模式是在导出excel模板时候,如果模板中标签名没有在传入的map中找到数值,会打印报告某某某标签没有赋值。如果开启静默模式后则不会报告。放心,出现严重异常还是会报错的。
2.函数统计错乱,这个必须设置(setUseFastFormulaProcessor(false)),要不后续文章中会写到怎么做excel分sheet输出,如果不设置成false,以后用excel自带函数统计相加会加错地方。
创建ScoreItem实体
package com.joery.hlutils;
import lombok.Data;
@Data
public class ScoreItem {
private String name;
private String desc;
private double score;
}
编写main函数测试:
public static void main(String[] args) {
// 模板路径和输出流
try {
String templatePath = "E:/template.xlsx";
OutputStream os = null;
os = new FileOutputStream("E:/out.xlsx");
// 定义一个Map,往里面放入要在模板中显示数据
List<ScoreItem> scoreItems = new ArrayList<>();
scoreItems.add(new ScoreItem("工作态度","对平时的工作态度进行评价",2));
scoreItems.add(new ScoreItem("工作能力","对技术能力进行评价",5));
scoreItems.add(new ScoreItem("团队合作能力","对团队合作能力进行评价",1));
//调用之前写的工具类,传入模板路径,输出流,和装有数据Map
Map<String,Object> models = new HashMap<>();
models.put("scoreitems",scoreItems);
JxlsUtils.exportExcel(templatePath, os, models);
os.close();
System.out.println("完成");
} catch (Exception e) {
e.printStackTrace();
}
}
1、运行前先建Excel模板,如下要求:
我们需要以上的模板导出,其中第2-4行都是后台动态生成出来的。则Excel模板如下:
运行main函数,在E盘生成out的Excel文件,结果即为我们需要显示的结果信息。
示例代码