使用Jxls1.0导出Excel文件

Jxls2
placeholder image
admin 发布于:2017-08-08 16:57:23
阅读:loading

很早很早就想写这么一篇文章了,但是觉得太简单了,就一直没写,直到昨天一个紧急的功能调整用到了此功能中的某项,由于时间太长记不大清楚了,随补上。在实现一些小型数据报表的时候,jxls是一个非常方便的实现方案,如果你还不了解,那正好就跟着我来熟悉一下吧。有人说我直接就用POI就可以实现,实际上jxls就是在poi的基础之上做的封装,它采用Excel模板的方式实现,配合el表达式来处理逻辑,也就是说我们的报表实现是基于事先创建一个最终效果的模板文件,在模板的基础上按照el规范去填充数据,最终显示效果。

组件优势

基本模板实现,Excel的报表易于维护

如果想修改某个单元格的显示样式,比如文本颜色、背景颜色、文本各种显示位置、边框、字体大小、千分位显示、百分百显示等等,都可以只需要修改模板,而不需要调整后台代码,也就省去了升级部署的一些问题。

API调用简单,表达式规范学习成本较低

生成报表时的API比较简单,传递数据集、模板文件、输出目录等参数即可,采用el表达式规范处理数据逻辑,可以不用在后台处理数据,比如本例中要实现的数据列表使用<jx:forEach items="${dataList}" var="item" varStatus="in" >和<jx:if test="${in.index % 2 == 0}">标签实现,分别为循环、判断标签,与jstl中的c标签用法完全一致。同样可以数据循环嵌套,依赖由后台的数据结构。

部分Excel自带的功能可用

以本例来说,虚拟了用户的一些数据,其中有个工资字段,将所有工资大于10000的数据格子文本显示红色、背景显示黄色,我们就不用后台那么复杂的去实现,只需要使用Excel自带的条件格式实现即可,功能丰富强大。

模板与规则.png

新建规则.png

Excel自带计算公式使用

在使用公式时有两种情况使用到得最多,1、单元格值为某个属性乘以某个数字(某个属性乘以某个属性);2、单元格值为引用了一些格子的公式 ,如: 格子A + 格子B + 格子C,其中各个格子也都可以自带其它的公式,支持数据循环的公式模式。统计汇总的公式引用等,打开生成的报表文件,其中的单元格是包含有公式的。

组件不足

适合小型数据量的报表

由于是采用后台数据填充的模式,所以对于大数据量时的处理就会略显鸡肋。

适合数据报表,对于图形化报表模板略显鸡肋

其他问题

1、对于下拉列表的样式循环,采用模板时发现下拉框并未跟着数据循环,参考如下图:

下拉框.png

2、单元格合并未找到如何处理;

3、某些时候发现一些单元格的公式未自动执行;

4、如果某些格子想使用excel自带的金额、数字格子类的公式或样式时,后台返回的属性又为文本,此时可使用让该文本*1的方式进行类型转换;

解决办法

使用jxls的API填充完数据后,可以返回POI的Workbook对象,所有的处理如:单元格的下拉列表、合并单元格等需要二次使用。

实现知识点

表头样式(加粗、居中、表格宽高)、隔行换色、汇总、基于数字的单元格公式计算、基于单元格引用的公式计算、条件格式等。参考模板图片为:

模板样式.png

参考代码

JavaBean

/**

 *

 */

package cn.chendd.example.vo;

 

/**

 * 用户信息

 * @author chendd

 */

public class User {

 

   private Integer id;// id

   private String name;// 姓名

   private Double salary;// 工资(元),大于10000的标绿色,大于20000的标红色

   private Double rate;// 税率

 

   public User() {

      super();

   }

 

   public User(Integer id, String name, Double salary,Double rate) {

      super();

      this.id = id;

      this.name = name;

      this.salary = salary;

      this.rate = rate;

   }

 

   public Integer getId() {

      return id;

   }

 

   public void setId(Integer id) {

      this.id = id;

   }

 

   public String getName() {

      return name;

   }

 

   public void setName(String name) {

      this.name = name;

   }

 

   public Double getSalary() {

      return salary;

   }

 

   public void setSalary(Double salary) {

      this.salary = salary;

   }

 

   public Double getRate() {

      return rate;

   }

 

   public void setRate(Double rate) {

      this.rate = rate;

   }

 

}

测试类

package cn.chendd.example;

 

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

 

import net.sf.jxls.transformer.XLSTransformer;

import cn.chendd.example.vo.User;

 

public class Test {

 

   public static void main(String[] args) throws Exception {

 

      String srcFilePath = Test.class.getResource("user.xlsx").getPath();

      String destFilePath = "d:\\tt\\员工.xlsx";

      List<User> dataList = getDataList();

      Map<String, Object> dataAll = new HashMap<String, Object>();

      dataAll.put("dataList", dataList);

      XLSTransformer transformer = new XLSTransformer();

      transformer.transformXLS(srcFilePath, dataAll, destFilePath);

      System.out.println("Test.main()");

   }

 

   private static List<User> getDataList() {

      List<User> dataList = new ArrayList<User>();

      dataList.add(new User(101, "曹*", 8000D, 0.20D, 0D));

      dataList.add(new User(102, "曹昂", 12000D, 0.25D, 0D));

      dataList.add(new User(103, "曹丕", 23000D, 0.40D, 0D));

      dataList.add(new User(104, "曹植", 36000D, 0.50D, 0D));

      dataList.add(new User(105, "曹冲", 7500D, 0.20D, 0D));

      dataList.add(new User(106, "曹仁", 8000D, 0.20D, 0D));

      dataList.add(new User(107, "曹彰", 8000D, 0.20D, 0D));

      dataList.add(new User(108, "曹髦", 8000D, 0.20D, 0D));

      dataList.add(new User(109, "曹休", 8000D, 0.20D, 0D));

      dataList.add(new User(110, "小鬼", 8000D, 0.20D, 0D));

      return dataList;

   }

 

}

相关Jar

commons-beanutils-1.8.2.jar

commons-collections-3.2.1.jar

commons-digester-2.0.jar

commons-jexl-2.0.1.jar

commons-logging-1.1.1.jar

dom4j-1.6.1.jar

jxls-core-1.0.6.jar

poi-3.9.jar

poi-ooxml-3.9.jar

poi-ooxml-schemas-3.9.jar

xml-apis-1.0.b2.jar

xmlbeans-2.3.0.jar

运行效果

运行效果.jpg

相关下载

模板文件.xlsx

之前在找jxls的时候有新版2.0了,稍微看了一下是基于备注来实现的,感觉好复杂,也没怎么深入。

@20180308 补充

突然想起来了就在补充一下,

1、使用jxls做多sheet导出时与单个sheet一样,把标签写在其它sheet里面即可。

2、在循环嵌套时,与jstl的循环嵌套类似,有varStatus属性;

3、jxls的标签较少,可以在打开jxls-core-1.0.xxx.jar中的net.sf.jxls.tag.JxTaglib类中查看,总共只是有4个标签类,也可以在jxls-core-1.0-rc-2-sources.jar中的同级目录的jx-core.xml中印证;

4、有一些表格循环行高的问题等,如果在xlsx中出现了,不妨将xlsx转换为xls试试;

5、除了上文中提到的下拉框,还有一些图片导出、超链接导出、更改sheet名称、循环数据的单元格合并等等,如果实现不了,在jxls导出excel后,使用poi进行二次处理;

6、数字金额类型转换的问题,有时候在后台返回的字符串类型的数字,实际上你想要的是数字,而excel会在格子的左上角给显示一个绿色的小三角,此时的两种解决办法,

①在后台将数字字符串转换为数字类型;

②在${item.name}处添加数字的计算,比如我们知道一个数在乘以1或者加上0之后还是等于它本身,即${item.name*1},excel会将这只字符串转换成数字类型;

@20180611 补充

有个List类型在返回数据集中不存在报错的问题

假如模板中存在一个对List集合循环显示的表格,但是Java后台又由于某些逻辑而又没给模板中参数集合绑定对应的参数,即对Map参数中不存在的变量进行循环,此时是会报错的,解决办法常规的有两种:

1、从Java后台判定,如果集合为空则进行new ArrayList给个empty集合数据;

2、模板中添加一个if判断标签,即满足条件时才执行forEach循环语句,参见判断的写法为 {not empty dataList},一定是使用 not empty 去判断,不能直接s还有 == null 之类的判断,因为这样的判断会使用String类型的判断,而非集合类型的判断。

@20180829 补充

补充一下标签的相关:

1、循环标签,js:forEach,有varStatus属性,可获取下标实现第一次循环或最后一次循环的逻辑等;

2、判断标签,js:if,字符串判断<js:if test="item.prop == 'value'">;当判断集合是否为空时使用not empty的方式判断(同jstl);



 点赞


 发表评论

当前回复:作者

 评论列表


留言区