阿里EasyExcel
对文件execl的导入操作
<!-- 阿里对execl操作 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.0.4</version>
</dependency>
org.apache.poi.ss.usermodel.Cell.setBlank()V poi的jar版本太低问题
controller
/**
人员绩效 excel文件的上传
*/
@ApiOperation(value = "人员绩效 (导入execl)")
@PostMapping("/uploadPersonExecl")
public ControllerResult<?> uploadPersonExecl(MultipartFile file) {
try {
PersonRecordDataListener pzobj = new PersonRecordDataListener(utilDao.getczyXmAndId(),personRecordDao);
EasyExcel.read(file.getInputStream(), PersonPerformanceRecordDTO.class, pzobj).sheet().doRead();
return new ControllerResult<>(true,pzobj.getSblist());
} catch (IOException | ExcelAnalysisException e) {
log.error("错误消息:{}",e.getMessage(),e);
return new ControllerResult<>(false, "文件上传错误或格式不正确");
} catch (Exception e) {
log.error("错误消息:{}",e.getMessage(),e);
return new ControllerResult<>(false, ErrorCode.SYSTEM_EXCEPTION);
}
}
第二种 没有办法获取对execl操作的结果
/**
人员绩效 excel文件的上传
*/
@ApiOperation(value = "人员绩效 (导入execl)")
@PostMapping("/uploadPersonExecl")
public ControllerResult<?> uploadPersonExecl(MultipartFile file) {
try {
EasyExcel.read(file.getInputStream(), PersonPerformanceRecordDTO.class, personRecordDataListener).sheet().doRead();
return new ControllerResult<>(true, "数据导入成功");
} catch (IOException | ExcelAnalysisException e) {
log.error("错误消息:{}",e.getMessage(),e);
return new ControllerResult<>(false, "文件上传错误或格式不正确");
} catch (Exception e) {
log.error("错误消息:{}",e.getMessage(),e);
return new ControllerResult<>(false, ErrorCode.SYSTEM_EXCEPTION);
}
}
dto
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
* @Author LiGuangLong
* @Date 2021-11-09 10:45
* @Version 1.0
* table(person_performance_record)
**/
@Data
@ApiModel("人员绩效")
public class PersonPerformanceRecordDTO {
@ApiModelProperty("流水号")
private String id;
@ApiModelProperty("操作员代码")
private Integer czydm;
@ExcelProperty(index = 3)
@ApiModelProperty("操作员姓名")
private String czyxm;
@ExcelProperty(index = 0)
@ApiModelProperty("年份")
private String year;
@ExcelProperty(index = 1)
@ApiModelProperty("季度(1-4)")
private Integer quarter;
@ExcelProperty(index = 2)
@ApiModelProperty("站点")
private String department;
@ExcelProperty(index = 4)
@ApiModelProperty("绩效(A-D)")
private String performance;
@ApiModelProperty("更新人员代码")
private Integer updateCzydm;
@ApiModelProperty("更新时间")
private Date updateTime;
}
操作类
package com.eagle.monitor.reportForms.surplus.config;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.eagle.monitor.reportForms.surplus.dao.PersonRecordDao;
import com.eagle.monitor.reportForms.surplus.vo.PersonPerformanceRecordDTO;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @Author LiGuangLong
* @Date 2021-11-11 9:42
* @Version 1.0
**/
@Slf4j
public class PersonRecordDataListener extends AnalysisEventListener<PersonPerformanceRecordDTO> {
private final Map<String,Object> mapList;
private final PersonRecordDao personRecordDao;
private List<String> sblist = new ArrayList();
List<PersonPerformanceRecordDTO> list = new ArrayList<>();
public PersonRecordDataListener(Map<String,Object> mapList,PersonRecordDao personRecordDao) {
this.mapList = mapList;
this.personRecordDao = personRecordDao;
}
/**
* 这个每一条数据解析都会来调用
*
*/
@Override
public void invoke(PersonPerformanceRecordDTO data, AnalysisContext context) {
log.debug("解析到一条数据:");
log.debug(data.toString());
if (mapList.get(data.getCzyxm()) != null){
Map<String,Integer> lsitmap = (Map<String, Integer>) mapList.get(data.getCzyxm());
data.setCzydm(Integer.parseInt(String.valueOf(lsitmap.get("czydm"))));
} else {
sblist.add(data.getCzyxm());
}
list.add(data);
}
/**
* 所有数据解析完成了 都会来调用
*
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
log.debug(list.toString());
personRecordDao.addPerson(list);
list.clear();
}
public List<String> getSblist(){
return this.sblist;
}
}
这种方式没有办法获取导入结果
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.eagle.monitor.reportForms.surplus.dao.PersonRecordDao;
import com.eagle.monitor.reportForms.surplus.dao.UtilDao;
import com.eagle.monitor.reportForms.surplus.vo.PersonPerformanceRecordDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @Author LiGuangLong
* @Date 2021-11-11 9:42
* @Version 1.0
**/
@Component
@Slf4j
public class PersonRecordDataListener extends AnalysisEventListener<PersonPerformanceRecordDTO> {
@Resource
private UtilDao utilDao;
private Map<String,Object> mapList;
@Resource
private PersonRecordDao personRecordDao;
List<PersonPerformanceRecordDTO> list = new ArrayList<>();
/**
* 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
*/
public PersonRecordDataListener() {}
@PostConstruct
public void init() {
this.mapList = utilDao.getczyXmAndId();
}
/**
* 这个每一条数据解析都会来调用
*
* @param data
* @param context
*/
@Override
public void invoke(PersonPerformanceRecordDTO data, AnalysisContext context) {
log.debug("解析到一条数据:");
log.debug(data.toString());
if (mapList.get(data.getCzyxm()) != null){
Map<String,Integer> lsitmap = (Map<String, Integer>) mapList.get(data.getCzyxm());
data.setCzydm(Integer.parseInt(String.valueOf(lsitmap.get("czydm"))));
}
list.add(data);
}
/**
* 所有数据解析完成了 都会来调用
*
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
log.debug(list.toString());
personRecordDao.addPerson(list);
list.clear();
}
}
要点
定义好了表格数据类,就可以开始读取了,该库非常贴心,提供了 同步 和 异步 两种读取方式。
同步读取
// 读取到的数据
List<YupiData> list = EasyExcel.read(fileName)
.head(YupiData.class)
.sheet()
.doReadSync();
异步方式需要定义一个 监听器 ,每读取一行,就要立即去处理该行数据。这样就不需要将所有数据都加载到内存中,算一行读一行,理论上算完了也可以丢弃。
不创建对象的读
如果事先不清楚表格会有哪些列、类型如何(比如让用户自主上传表格),那么可以使用 不创建对象读 的方式,直接用 Map<Integer, String> 泛型类来接收:
List<Map<Integer, String>> list = EasyExcel
.read(fileName)
.sheet()
.doReadSync();
// Map 的 key 为列下标,value 为单元格的值
for (Map<Integer, String> data : list) {
...
}
写入表格
学会读取后,写入表格就更简单了,依然是先定义一个类,用来表示要写入表格的元信息(列名、列数据类型等)。
比如要完成表格列顺序调换的需求,定义表格数据类的时候,把 age 和 name 属性的顺序换一下就好了:
@Data
public class YupiWriteData {
// 年龄 ↑
private Integer age;
// 姓名 ↓
// 该注解设置 列明 列数位置
@ExcelProperty(value = "正确检测数",index = 0)
private String name;
// 出生日期
// 该注解让属性不被导出 默认全部导出
@ExcelIgnore
private Date bornDate;
}
然后执行 Easy Excel 的 write 方法,就完事了,代码如下:
void doWrite() {
// 已读取和处理后的数据列表
List<YupiWriteData> dataList = xxx;
String fileName = "result.xlsx";
EasyExcel.write(fileName, YupiWriteData.class)
.sheet("工作表1")
.doWrite(dataList);
}
搞定
导出格式设置
在字段添加注解
@ContentStyle(dataFormat = 4)
private Double doubleData;
private static final String[] BUILTIN_FORMATS_CN = {
// 0
"General",
// 1
"0",
// 2
"0.00",
// 3
"#,##0",
// 4
"#,##0.00",
// 5
"\"¥\"#,##0_);(\"¥\"#,##0)",
// 6
"\"¥\"#,##0_);[Red](\"¥\"#,##0)",
// 7
"\"¥\"#,##0.00_);(\"¥\"#,##0.00)",
// 8
"\"¥\"#,##0.00_);[Red](\"¥\"#,##0.00)",
// 9
"0%",
// 10
"0.00%",
// 11
"0.00E+00",
// 12
"# ?/?",
// 13
"# ??/??",
// 14
// The official documentation shows "m/d/yy", but the actual test is "yyyy/m/d".
"yyyy/m/d",
// 15
"d-mmm-yy",
// 16
"d-mmm",
// 17
"mmm-yy",
// 18
"h:mm AM/PM",
// 19
"h:mm:ss AM/PM",
// 20
"h:mm",
// 21
"h:mm:ss",
// 22
// The official documentation shows "m/d/yy h:mm", but the actual test is "yyyy-m-d h:mm".
"yyyy-m-d h:mm",
// 23-26 No specific correspondence found in the official documentation.
// 23
null,
// 24
null,
// 25
null,
// 26
null,
// 27
"yyyy\"年\"m\"月\"",
// 28
"m\"月\"d\"日\"",
// 29
"m\"月\"d\"日\"",
// 30
"m-d-yy",
// 31
"yyyy\"年\"m\"月\"d\"日\"",
// 32
"h\"时\"mm\"分\"",
// 33
"h\"时\"mm\"分\"ss\"秒\"",
// 34
"上午/下午h\"时\"mm\"分\"",
// 35
"上午/下午h\"时\"mm\"分\"ss\"秒\"",
// 36
"yyyy\"年\"m\"月\"",
// 37
"#,##0_);(#,##0)",
// 38
"#,##0_);[Red](#,##0)",
// 39
"#,##0.00_);(#,##0.00)",
// 40
"#,##0.00_);[Red](#,##0.00)",
// 41
"_(* #,##0_);_(* (#,##0);_(* \"-\"_);_(@_)",
// 42
"_(\"¥\"* #,##0_);_(\"¥\"* (#,##0);_(\"¥\"* \"-\"_);_(@_)",
// 43
"_(* #,##0.00_);_(* (#,##0.00);_(* \"-\"??_);_(@_)",
// 44
"_(\"¥\"* #,##0.00_);_(\"¥\"* (#,##0.00);_(\"¥\"* \"-\"??_);_(@_)",
// 45
"mm:ss",
// 46
"[h]:mm:ss",
// 47
"mm:ss.0",
// 48
"##0.0E+0",
// 49
"@",
// 50
"yyyy\"年\"m\"月\"",
// 51
"m\"月\"d\"日\"",
// 52
"yyyy\"年\"m\"月\"",
// 53
"m\"月\"d\"日\"",
// 54
"m\"月\"d\"日\"",
// 55
"上午/下午h\"时\"mm\"分\"",
// 56
"上午/下午h\"时\"mm\"分\"ss\"秒\"",
// 57
"yyyy\"年\"m\"月\"",
// 58
"m\"月\"d\"日\"",
// 59
"t0",
// 60
"t0.00",
// 61
"t#,##0",
// 62
"t#,##0.00",
// 63-66 No specific correspondence found in the official documentation.
// 63
null,
// 64
null,
// 65
null,
// 66
null,
// 67
"t0%",
// 68
"t0.00%",
// 69
"t# ?/?",
// 70
"t# ??/??",
// 71
"ว/ด/ปปปป",
// 72
"ว-ดดด-ปป",
// 73
"ว-ดดด",
// 74
"ดดด-ปป",
// 75
"ช:นน",
// 76
"ช:นน:ทท",
// 77
"ว/ด/ปปปป ช:นน",
// 78
"นน:ทท",
// 79
"[ช]:นน:ทท",
// 80
"นน:ทท.0",
// 81
"d/m/bb",
// end
};

浙公网安备 33010602011771号