读excel
简单读
excel
实体
@Datapublic class DemoData {// 生成get set 或者 构造方法 或者使用注解private String name;private Double age;private String address;private Double sal;}
实现接口
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去public class DemoDataListener extends AnalysisEventListener<DemoData> {List<DemoData> list = new ArrayList<DemoData>();/*** 这个每一条数据解析都会来调用** @param data* @param context*/@Overridepublic void invoke(DemoData data, AnalysisContext context) {list.add(data);}/*** 所有数据解析完成了 都会来调用** @param context*/@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {System.out.println(JSON.toJSONString(list));}}
读
@org.junit.Testpublic void simpleRead() {String fileName = "C:/Users/Administrator/Desktop/learnEasyExcel.xls";EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();}
@org.junit.Testpublic void simpleRead2() {String fileName = "C:/Users/Administrator/Desktop/learnEasyExcel.xls";ExcelReader excelReader = null;try {excelReader = EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).build();ReadSheet readSheet = new ReadSheet(0);excelReader.read(readSheet);}finally {if (excelReader != null) {excelReader.finish();}}}
指定列的下标或者列名
实体
@Datapublic class DemoData {// index和value 二选一,不要两个都一起使用@ExcelProperty(index = 0)private String name;@ExcelProperty(value = "年龄")private Double age;@ExcelProperty(index = 2,value = "地址")private String address;@ExcelProperty(index = 3)private Double sal;}
读多个sheet
全读
@org.junit.Testpublic void readAllSheet(){String fileName = "C:/Users/Administrator/Desktop/learnEasyExcel.xls";EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).doReadAll();}
DemoDataListener的doAfterAllAnalysed 会在每个sheet读取完毕后调用一次。然后所有sheet都会往同一个DemoDataListener里面写[{},{},{},{},{},{},{},{},{},{}][{},{},{},{},{},{},{},{},{},{},{"address":"汉阳","age":45,"name":"利好","sal":78}]
部分读
@org.junit.Testpublic void readMoreSheet(){String fileName = "C:/Users/Administrator/Desktop/learnEasyExcel.xls";ExcelReader excelReader = null;try {excelReader = EasyExcel.read(fileName).build();ReadSheet readSheet1 = EasyExcel.readSheet(0).head(DemoData.class).registerReadListener(new DemoDataListener1()).build();ReadSheet readSheet2 = EasyExcel.readSheet(1).head(DemoData.class).registerReadListener(new DemoDataListener2()).build();excelReader.read(readSheet1,readSheet2);}finally {if (excelReader != null) {excelReader.finish();}}}
[{},{},{},{},{},{},{},{},{},{}][{"address":"汉阳","age":45,"name":"利好","sal":78}]
日期、数字或者自定义格式转换
实体
@Datapublic class MoreTypeData {@ExcelProperty(converter = CustomStringStringConverter.class)private String name;@DateTimeFormat("yyyy年MM月dd日")private String date;@NumberFormat("#.##%")private String sal;}
自定义转换器
public class CustomStringStringConverter implements Converter<String> {@Overridepublic Class supportJavaTypeKey() {return String.class;}@Overridepublic CellDataTypeEnum supportExcelTypeKey() {return CellDataTypeEnum.STRING;}@Overridepublic String convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {return "自定义"+cellData.getStringValue();}@Overridepublic CellData convertToExcelData(String s, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {return new CellData(s);}}
使用
@org.junit.Testpublic void readMoreTypeData(){String fileName = "C:/Users/Administrator/Desktop/learnEasyExcel.xls";// 这里 需要指定读用哪个class去读,然后读取第一个sheetEasyExcel.read(fileName, MoreTypeData.class, new MoreTypeDataListener())// 这里注意 我们也可以registerConverter来指定自定义转换器, 但是这个转换变成全局了, 所有java为string,excel为string的都会用这个转换器。// 如果就想单个字段使用请使用@ExcelProperty 指定converter// .registerConverter(new CustomStringStringConverter())// 读取sheet.sheet(2).doRead();}
多行头
@org.junit.Testpublic void readMoreHeader(){String fileName = "C:/Users/Administrator/Desktop/learnEasyExcel.xls";// 这里 需要指定读用哪个class去读,然后读取第一个sheetEasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().headRowNumber(1).doRead();// 这里可以设置1,因为头就是一行。如果多行头,可以设置其他值。不传入也可以,因为默认会根据DemoData 来解析,他没有指定头,也就是默认1行}
同步的返回
@org.junit.Testpublic void synchronousRead() {String fileName = "C:/Users/Administrator/Desktop/learnEasyExcel.xls";// 这里 需要指定读用哪个class去读,然后读取第一个sheet 同步读取会自动finishList<DemoData> list = EasyExcel.read(fileName).head(DemoData.class).sheet().doReadSync();for (DemoData data : list) {System.out.println(data);}// 这里 也可以不指定class,返回一个list,然后读取第一个sheet 同步读取会自动finishList<Map<Integer, String>> listMap = EasyExcel.read(fileName).sheet().doReadSync();for (Map<Integer, String> data : listMap) {// 返回每条数据的键值对 表示所在的列 和所在列的值System.out.println(data);}}
读取表头数据
监听器
里面多实现一个方法即可
@Overridepublic void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {System.out.println(headMap);}
@org.junit.Testpublic void headerRead() {String fileName = "C:/Users/Administrator/Desktop/learnEasyExcel.xls";// 这里 需要指定读用哪个class去读,然后读取第一个sheetEasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();}
额外信息(批注、超链接、合并单元格)
excel
实体
@Datapublic class DemoExtraData {private String row1;private String row2;}
监听器
@Overridepublic void extra(CellExtra extra, AnalysisContext context) {LOGGER.info("读取到了一条额外信息:{}", JSON.toJSONString(extra));switch (extra.getType()) {case COMMENT:LOGGER.info("额外信息是批注,在rowIndex:{},columnIndex;{},内容是:{}", extra.getRowIndex(), extra.getColumnIndex(),extra.getText());break;case HYPERLINK:if ("Sheet1!A1".equals(extra.getText())) {LOGGER.info("额外信息是超链接,在rowIndex:{},columnIndex;{},内容是:{}", extra.getRowIndex(),extra.getColumnIndex(), extra.getText());} else if ("Sheet2!A1".equals(extra.getText())) {LOGGER.info("额外信息是超链接,而且覆盖了一个区间,在firstRowIndex:{},firstColumnIndex;{},lastRowIndex:{},lastColumnIndex:{},"+ "内容是:{}",extra.getFirstRowIndex(), extra.getFirstColumnIndex(), extra.getLastRowIndex(),extra.getLastColumnIndex(), extra.getText());} else {Assert.fail("Unknown hyperlink!");}break;case MERGE:LOGGER.info("额外信息是超链接,而且覆盖了一个区间,在firstRowIndex:{},firstColumnIndex;{},lastRowIndex:{},lastColumnIndex:{}",extra.getFirstRowIndex(), extra.getFirstColumnIndex(), extra.getLastRowIndex(),extra.getLastColumnIndex());break;default:}}
/*** 额外信息(批注、超链接、合并单元格信息读取)* <p>* 由于是流式读取,没法在读取到单元格数据的时候直接读取到额外信息,所以只能最后通知哪些单元格有哪些额外信息** <p>* 1. 创建excel对应的实体对象 参照{@link DemoExtraData}* <p>* 2. 由于默认异步读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoExtraListener}* <p>* 3. 直接读即可** @since 2.2.0-beat1*/@Testpublic void extraRead() {String fileName = TestFileUtil.getPath() + "demo" + File.separator + "extra.xlsx";// 这里 需要指定读用哪个class去读,然后读取第一个sheetEasyExcel.read(fileName, DemoExtraData.class, new DemoExtraListener())// 需要读取批注 默认不读取.extraRead(CellExtraTypeEnum.COMMENT)// 需要读取超链接 默认不读取.extraRead(CellExtraTypeEnum.HYPERLINK)// 需要读取合并单元格信息 默认不读取.extraRead(CellExtraTypeEnum.MERGE).sheet().doRead();}
