Java中实现excel根据模板导出数据的方法有很多,一般简单的可以通过操作POI进行。还可以使用一些工具很轻松的实现模板导出。这些工具现在还在维护,而且做得比较好的国内的有easyPOI,国外的就是这个JXLS了。

  笔者使用jxls 2也有半年的时间了,半年前因项目原因需要导出大量的excel文件,所以找到了jxls2,这是目前我用过最好的excel导出工具,基本可以完全满足所有的项目需要。不使用easypoi的原因是那时候测试时候效果不是很好,项目中有很多复杂的报表(大量单元格合并和单元格样式),easyPOI处理合并单元格时候容易出现残损的情况。

  今天我们着重介绍一下JXLS 2.4.0 ,写文章前我搜索了下JXLS的教程,发现半年前我看到的是什么文章,现在的还是什么文章,大量的文章停留在JXLS1.0时代(作者2.0后重写了代码,使用方法完全不同)。唯一最新的一篇中文文章是klguang 写的《jxls2.3-简明教程》。剩下的就是官方文档了。其实官方文档也很不错,就是系统化不够,值此国庆之际,正好把我的工作中使用JXLS的经验写一下,让更多人接触这款优秀的工具。

  首先,我推荐各位有能力的先上官网下载最新版本和了解下基础功能。(有没有被墙看缘分,公司的电信网络可以直接上,家里联通的要挂VPN)

http://jxls.sourceforge.net/index.html

  其次,推荐各位完整的看完klguang 大神写的《jxls2.3-简明教程》这篇文章。里面提供了klguang 大神的工具类,本文也基于他的工具类进行介绍(部分代码进行修改)。

http://www.cnblogs.com/klguang/p/6425422.html

  好,现在我们开始。

  我这里使用jxls 2.4.0进行教程(不使用最新的2.4.2是因为我懒,教程用的jar包是我直接从公司项目拷的,懒得去测试新版本会不会有什么幺蛾子,不过我看了下更新说明,只是修复了一个bug,应该问题不大)。2.4和2.3在操作上没什么变化,但是在jar包的依赖上发生了变化,所以在使用2.4时候主要看我提供需要依赖的jar包文件。

  除了官方需要的jar包外,还需要加入几个依赖的包(都是必须的,少一个就报错)。文章后我给出依赖包的下载地址。用Maven的朋友我就不说怎么引包了,写上就自动下载依赖了。

接下来,我们在项目中复制util工具类:

package com.test.util;

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; /**
* @author klguang
*/
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;
}
}

  我在klguang 的基础上略作了修改,有两点需要讲一下:

  1.静默模式是在导出excel模板时候,如果模板中标签名没有在传入的map中找到数值,会打印报告某某某标签没有赋值。如果开启静默模式后则不会报告。放心,出现严重异常还是会报错的。

  2.函数统计错乱,这个必须设置(setUseFastFormulaProcessor(false)),要不后续文章中会写到怎么做excel分sheet输出,如果不设置成false,以后用excel自带函数统计相加会加错地方。

  工欲善其事必先利其器,接着我们可以写一个Main方法了。

public class TestMain {
public static void main(String[] args) throws Exception {
// 模板路径和输出流
String templatePath = "E:/template.xls";
OutputStream os = new FileOutputStream("E:/out.xls");
// 定义一个Map,往里面放入要在模板中显示数据
Map<String, Object> model = new HashMap<String, Object>();
model.put("id", "001");
model.put("name", "张三");
model.put("age", 18);
//调用之前写的工具类,传入模板路径,输出流,和装有数据Map
JxlsUtils.exportExcel(templatePath, os, model);
os.close();
System.out.println("完成");
}
}

  

  就这么简单,接下来我们做事写模板。

  在E盘建立一个名字叫template.xls的文件,然后在里面加入以下的内容。

  如果你前面看了klguang的教程,你应该知道里面的注释是什么意思。不过我还是简单讲一下:

  第一步,在报表中最左上角(A1)加入一个注释jx:area(lastCell="D3"),含义为模板的区域由A1(加注释的单元格)到D3。有一点说明:

  区域最好比你设计的模板大一圈就是你的模板内容只到C2,而你要设置区域到D3。理由是在2.3版本中lastCell的值如果在有表达式的单元格或者在合并后的单元格,容易报空指针异常,2.4好像没有这个问题了,不太确定。

  第二步,在你设定的模板区域内写入表达式${ },表达式中写入前面model中put的“键”。

  好了,模板写完,保存,执行java代码,我们就可以看到效果了:

  

  最后说明一下:

  1.jxls会自动根据你model中put的值来判断写入进excel中的是字符串还是数值。

  2.A1单元格这个被注释使用的单元格也是可以写表达式的。

  3.如果你在模板中写了一个model 中找不到对应键的表达式,比如我在A3中写${aaaa},再运行代码,则会报提示:

警告: org.jxls.expression.JexlExpressionEvaluator.evaluate@61![0,4]: 'aaaa;' undefined variable aaaa

  如果不想要提示就在JxlsUtils类中设置静默模式:evaluator.getJexlEngine().setSilent(true);

  jar包下载地址(内有官方2.4.0版本,2.4依赖的jar包,klguang 的demo)这里下载

  接下来我计划写四篇文章,仔细的描述我使用jxls的一些技巧。JXLS是一个很强大的excel操作工具,可以导入导出,模板导出,代码导出,xml导出,导出显示图片,连接数据库等等功能。具体的功能有需要的同学请上官网查询。我只写一些我用到过的功能。

  我附上我计划写的文章的大纲,有需要的同学敬请期待,预计2017年国庆内写完。

最简单应用
需要的包
标签介绍,类介绍
直接输出

循环
容易出现的报错
简单循环,标签介绍

分sheet
如何分sheet

循环嵌套
如何嵌套

高级应用,和bug修复
map
统计
使用工具
静默模式
边距bug

JXLS 2.4.0系列教程(一)——最简单的模板导出的更多相关文章

  1. JXLS 2.4.0系列教程(二)——循环导出一个链表的数据

    请务必先看上一篇文章,本文在上一篇文章的代码基础上修改而成. JXLS 2.4.0系列教程(一)--最简单的模板导出 上一篇文章我们介绍了JXLS和模板导出最简单的应用,现在我们要更进一步,介绍在模板 ...

  2. JXLS 2.4.0系列教程(五)——更进一步的应用和页面边距bug修复

    注:本文代码建立于前面写的代码.不过不看也不要紧. 前面的文章把JXLS 2.4.0 的基本使用写了一遍,现在讲讲一些更进一步的使用方法.我只写一些我用到过的方法,更多的高级使用方法请参考官网. ht ...

  3. JXLS 2.4.0系列教程(四)——多sheet是怎么做到的

    注:本文代码在第一篇文章基础上修改而成,请务必先阅读第一篇文章. http://www.cnblogs.com/foxlee1024/p/7616987.html 本文也不会过多的讲解模板中遍历表达式 ...

  4. JXLS 2.4.0系列教程(六)番外篇——导出图片(完结)

    突然想起来有同学说过能不能导出图片,本来我是想说不懂的,后来我上官网查了查,还挺容易.我就简短的写一写怎么导出图片. 官方提供了导出图片标签: jx:image(lastCell="D10& ...

  5. JXLS 2.4.0系列教程(四)——拾遗 如何做页面小计

    注:阅读本文前,请先阅读第四篇文章. http://www.cnblogs.com/foxlee1024/p/7619845.html 前面写了第四篇教程,发现有些东西忘了讲了,这里补回来. 忘了讲两 ...

  6. JXLS 2.4.0系列教程(三)——嵌套循环是怎么做到的

    注:本文代码在第一篇文章基础上修改而成,请务必先阅读第一篇文章. http://www.cnblogs.com/foxlee1024/p/7616987.html 本文也不会过多的讲解模板中遍历表达式 ...

  7. Enterprise Library 5.0 系列教程

    1. Microsoft Enterprise Library 5.0 系列教程(一) Caching Application Block (初级) 2. Microsoft Enterprise L ...

  8. 黄聪:Microsoft Enterprise Library 5.0 系列教程(六) Security Application Block

    原文:黄聪:Microsoft Enterprise Library 5.0 系列教程(六) Security Application Block 开发人员经常编写需要安全功能的应用程序.这些应用程序 ...

  9. 黄聪:Microsoft Enterprise Library 5.0 系列教程(七) Exception Handling Application Block

    原文:黄聪:Microsoft Enterprise Library 5.0 系列教程(七) Exception Handling Application Block 使用企业库异常处理应用程序模块的 ...

随机推荐

  1. Who Will Win?

    Gautam and Subhash are two brothers. They are similar to each other in all respects except one. They ...

  2. Windows as a Service(1)—— Windows 10服务分支

    前言 作为公司的IT管理员,管理全公司Windows 10操作系统的更新一直是工作中的头疼之处.微软提供了很多方法来帮助我们管理公司的Windows 10更新,比如Windows Server Upd ...

  3. yum 命令详解

    一. yum          作用:                     yum 命令是在Fedora 和RedHat 以及SUSE 中基于rpm 的软件包管理器,它可以使系统管理人员交互和自动 ...

  4. python:发送消息给微信企业号

    # -*- coding:utf-8 -*- import requests import json ''' 基础环境:微信企业号 version:python 2.7 ''' class Send_ ...

  5. centos7 部署dns服务器

    =============================================== 2017/12/6_第2次修改                       ccb_warlock 20 ...

  6. BeanShell断言(一)

    在beanShell中直接可以调用的变量,无需加前缀. 1.log 打印日志 log.info(“在控制台打印日志”); 2.SampleResult 获取SampleResult对象,可以通过这个对 ...

  7. linux svn up 中文显示乱码解决办法

    vi /etc/sysconfig/i18n #LANG="en_US.UTF-8" #LANG=zh_CN.GB18030 #LC_ALL=zh_CN.GB18030 #SYSF ...

  8. Xamarin.Android 怎么定义一个按钮和返回键功能一样回到上一个界面

    https://zhidao.baidu.com/question/570934367.html页面之间的跳转有startActivity 和startActivityForResult两种,star ...

  9. Linux 定时任务不生效的问题

    Linux 中定时任务不生效的问题屡见不鲜, 本质原因是: 登录式 shell & 非登录式 shell. 登录式 shell & 非登录式 shell 登录式 shell 有: su ...

  10. java基础只关键字final

    final关键字简述 final关键字是在编写java程序中出现频率和很高的关键字,如果想要更好的编写java程序,那么掌握final关键字的运用是非常必要的.让我们先看一下final关键字可以修饰的 ...