EasyPOI模板导出
原文链接:
https://blog.csdn.net/u013374164/article/details/78292194
https://blog.csdn.net/lovexiaotaozi/article/details/85598424
https://www.jianshu.com/p/9f82e6630a37
https://blog.csdn.net/hzygcs/article/details/85100608
从原生的POI转到使用EasyPOI的人深有感触,就是代码效率提高了不少,EasyPOI作为POI的封装,有其优点,但是也有一定“坑”,本人近期踩了多坑,所以在这里进行一下总结
坑1.
EasyPOI模板导出不支持输入流,仔细看一下TemplateExportParams这个类,说明一下,该类主要是读取模板的,在模板的style基础之上可以定义导出的一些参数,观察一下这个类中的templateUrl,也就是到读取你本地的路径,当然我们在实际开发过程中,一般都会使用到文件服务器比如FastDFS,这个时候你就傻逼了,因为不支持流嘛,当然呢也可以做一些转换,也就是先将文件服务器中的模板读出来然后将该流写到本地磁盘上,再通过本地磁盘上的路径读取模板,这个方案笨了一些,但是是可以解决这个问题的,不知道高的版本改进了这个问题没,我目前用的是3.2.0版本,希望这个社区不断的壮大,后期版本可以解决此问题
TemplateExportParams模板类
package cn.afterturn.easypoi.excel.entity;
import cn.afterturn.easypoi.excel.export.styler.ExcelExportStylerDefaultImpl;
/**
* 模板导出参数设置
*
* @author JueYue
* 2013-10-17
* @version 1.0
*/
public class TemplateExportParams extends ExcelBaseParams {
/**
* 输出全部的sheet
*/
private boolean scanAllsheet = false;
/**
* 模板的路径
*/
private String templateUrl;
/**
* 需要导出的第几个 sheetNum,默认是第0个
*/
private Integer[] sheetNum = new Integer[] { 0 };
/**
* 设置sheetName 不填就使用原来的
*/
private String[] sheetName;
/**
* 表格列标题行数,默认1
*/
private int headingRows = 1;
/**
* 表格列标题开始行,默认1
*/
private int headingStartRow = 1;
/**
* 设置数据源的NUM
*/
private int dataSheetNum = 0;
/**
* Excel 导出style
*/
private Class<?> style = ExcelExportStylerDefaultImpl.class;
/**
* FOR EACH 用到的局部变量
*/
private String tempParams = "t";
private boolean colForEach = false;
/**
* 默认构造器
*/
public TemplateExportParams() {
}
/**
* 构造器
* @param templateUrl 模板路径
* @param scanAllsheet 是否输出全部的sheet
* @param sheetName sheet的名称,可不填
*/
public TemplateExportParams(String templateUrl, boolean scanAllsheet, String... sheetName) {
this.templateUrl = templateUrl;
this.scanAllsheet = scanAllsheet;
if (sheetName != null && sheetName.length > 0) {
this.sheetName = sheetName;
}
}
/**
* 构造器
* @param templateUrl 模板路径
* @param sheetNum sheet 的位置,可不填
*/
public TemplateExportParams(String templateUrl, Integer... sheetNum) {
this.templateUrl = templateUrl;
if (sheetNum != null && sheetNum.length > 0) {
this.sheetNum = sheetNum;
}
}
/**
* 单个sheet输出构造器
* @param templateUrl 模板路径
* @param sheetName sheet的名称
* @param sheetNum sheet的位置,可不填
*/
public TemplateExportParams(String templateUrl, String sheetName, Integer... sheetNum) {
this.templateUrl = templateUrl;
this.sheetName = new String[] { sheetName };
if (sheetNum != null && sheetNum.length > 0) {
this.sheetNum = sheetNum;
}
}
}
坑2.
EasyPOI读取的模板有特定的语法规则,新人直接用的时候很容易踩坑
关于模版使用语法如下:
下面列举下EasyPoi支持的指令以及作用,最主要的就是各种fe的用法
- 三目运算 {{test ? obj:obj2}}
- n: 表示 这个cell是数值类型 {{n:}}
- le: 代表长度{{le:()}} 在if/else 运用{{le:() > 8 ? obj1 : obj2}}
- fd: 格式化时间 {{fd:(obj;yyyy-MM-dd)}}
- fn: 格式化数字 {{fn:(obj;###.00)}}
- fe: 遍历数据,创建row
- !fe: 遍历数据不创建row
- $fe: 下移插入,把当前行,下面的行全部下移.size()行,然后插入
- #fe: 横向遍历
- v_fe: 横向遍历值
- !if: 删除当前列 {{!if:(test)}}
- 单引号表示常量值 ‘’ 比如’1’ 那么输出的就是 1
- &NULL& 空格
- ]] 换行符 多行遍历导出
- sum: 统计数据
一般用的多的就是{{n:}}以及{{fe: list t.XXX}},一个的普通的替换,一个是纵向的循环,本次案例即将讲到
案例:
1.先看看模板
2.导入EasyPOI的jar支持
<!-- easypoi的支持 -->
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>3.2.0</version>
</dependency>
3.测试
package com.Day5;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import org.apache.poi.ss.usermodel.Workbook;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author
* @create 2020-07-08 10:53
*/
public class EasyPOITest
{
public static void main(String[] args) throws IOException
{
//读取模板,注意EasyPOI只能支持路径,不支持流,这个EasyPOI的缺点
TemplateExportParams templateExportParams = new TemplateExportParams("G:\\模板.xlsx");
// templateExportParams.setColForEach(true);
// 标题开始行
// templateExportParams.setHeadingStartRow(0);
// 标题行数
// templateExportParams.setHeadingRows(2);
// 设置sheetName,若不设置该参数,则使用得原本得sheet名称
templateExportParams.setSheetName("班级体检信息");
Map<String,Object> map = new HashMap<>();
map.put("provinceName","浙江省");
map.put("cityName","杭州市");
map.put("areaName","江干区");
map.put("schoolName","杭州第一中学");
map.put("grade","初一");
map.put("nowDate","2020-7-8");
List<Map<String,Object>> mapList = new ArrayList<>();
for (int i = 0; i <10 ; i++)
{
Map<String,Object> ml = new HashMap<>();
ml.put("id",i+1);
ml.put("className","一班");
ml.put("studentName","张三");
ml.put("code","10000011");
ml.put("odVision","4.8");
ml.put("osVision","5.3");
ml.put("odSph","+0.3");
ml.put("odCyl","+0.3");
ml.put("odAxial","0.0");
ml.put("osSph","+0.5");
ml.put("osCyl","+0.3");
ml.put("osAxial","-0.2");
ml.put("odSeriesMirror","5");
ml.put("osSeriesMirror","4");
ml.put("odAmetropia","3");
ml.put("osAmetropia","2");
mapList.add(ml);
}
map.put("maplist",mapList);
Workbook workbook = ExcelExportUtil.exportExcel(templateExportParams, map);
System.out.println(workbook);
workbook.write(new FileOutputStream(new File("G:\\test.xlsx")));
workbook.close();
}
}
4. 结果:
5.总结:
1.我们在模板里面写到了{{fe:mapList t.id }},这个mapList不用多说就是我们的数据列表,t主要是来源于TemplateExportParams的 tempParams参数,默认是t ,当然你看到不爽也可以修改的
/**
* FOR EACH 用到的局部变量
*/
private String tempParams = "t";
2.此处的循环用到的模板语法是{{fe:}},是遍历数据,创建row,也就是向下创建行,一定不能错了,我之前用成{{$fe:}}报了ExcelExportOfTemplateUtil.createExcleByTemplate - firstMovedIndex,lastMovedIndex out of order异常,我后来改成{{fe:}}就正常了
了解这些,我觉得对模板的简单使用还是可以的