读excel

简单读

excel
image.png
实体

  1. @Data
  2. public class DemoData {
  3. // 生成get set 或者 构造方法 或者使用注解
  4. private String name;
  5. private Double age;
  6. private String address;
  7. private Double sal;
  8. }

实现接口

  1. // 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
  2. public class DemoDataListener extends AnalysisEventListener<DemoData> {
  3. List<DemoData> list = new ArrayList<DemoData>();
  4. /**
  5. * 这个每一条数据解析都会来调用
  6. *
  7. * @param data
  8. * @param context
  9. */
  10. @Override
  11. public void invoke(DemoData data, AnalysisContext context) {
  12. list.add(data);
  13. }
  14. /**
  15. * 所有数据解析完成了 都会来调用
  16. *
  17. * @param context
  18. */
  19. @Override
  20. public void doAfterAllAnalysed(AnalysisContext context) {
  21. System.out.println(JSON.toJSONString(list));
  22. }
  23. }

  1. @org.junit.Test
  2. public void simpleRead() {
  3. String fileName = "C:/Users/Administrator/Desktop/learnEasyExcel.xls";
  4. EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();
  5. }
  1. @org.junit.Test
  2. public void simpleRead2() {
  3. String fileName = "C:/Users/Administrator/Desktop/learnEasyExcel.xls";
  4. ExcelReader excelReader = null;
  5. try {
  6. excelReader = EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).build();
  7. ReadSheet readSheet = new ReadSheet(0);
  8. excelReader.read(readSheet);
  9. }finally {
  10. if (excelReader != null) {
  11. excelReader.finish();
  12. }
  13. }
  14. }

指定列的下标或者列名

实体

  1. @Data
  2. public class DemoData {
  3. // index和value 二选一,不要两个都一起使用
  4. @ExcelProperty(index = 0)
  5. private String name;
  6. @ExcelProperty(value = "年龄")
  7. private Double age;
  8. @ExcelProperty(index = 2,value = "地址")
  9. private String address;
  10. @ExcelProperty(index = 3)
  11. private Double sal;
  12. }

读多个sheet

全读

  1. @org.junit.Test
  2. public void readAllSheet(){
  3. String fileName = "C:/Users/Administrator/Desktop/learnEasyExcel.xls";
  4. EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).doReadAll();
  5. }
  1. DemoDataListenerdoAfterAllAnalysed 会在每个sheet读取完毕后调用一次。然后所有sheet都会往同一个DemoDataListener里面写
  2. [{},{},{},{},{},{},{},{},{},{}]
  3. [{},{},{},{},{},{},{},{},{},{},{"address":"汉阳","age":45,"name":"利好","sal":78}]

部分读

  1. @org.junit.Test
  2. public void readMoreSheet(){
  3. String fileName = "C:/Users/Administrator/Desktop/learnEasyExcel.xls";
  4. ExcelReader excelReader = null;
  5. try {
  6. excelReader = EasyExcel.read(fileName).build();
  7. ReadSheet readSheet1 = EasyExcel.readSheet(0).head(DemoData.class).registerReadListener(new DemoDataListener1()).build();
  8. ReadSheet readSheet2 = EasyExcel.readSheet(1).head(DemoData.class).registerReadListener(new DemoDataListener2()).build();
  9. excelReader.read(readSheet1,readSheet2);
  10. }finally {
  11. if (excelReader != null) {
  12. excelReader.finish();
  13. }
  14. }
  15. }
  1. [{},{},{},{},{},{},{},{},{},{}]
  2. [{"address":"汉阳","age":45,"name":"利好","sal":78}]

日期、数字或者自定义格式转换

实体

  1. @Data
  2. public class MoreTypeData {
  3. @ExcelProperty(converter = CustomStringStringConverter.class)
  4. private String name;
  5. @DateTimeFormat("yyyy年MM月dd日")
  6. private String date;
  7. @NumberFormat("#.##%")
  8. private String sal;
  9. }

自定义转换器

  1. public class CustomStringStringConverter implements Converter<String> {
  2. @Override
  3. public Class supportJavaTypeKey() {
  4. return String.class;
  5. }
  6. @Override
  7. public CellDataTypeEnum supportExcelTypeKey() {
  8. return CellDataTypeEnum.STRING;
  9. }
  10. @Override
  11. public String convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
  12. return "自定义"+cellData.getStringValue();
  13. }
  14. @Override
  15. public CellData convertToExcelData(String s, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
  16. return new CellData(s);
  17. }
  18. }

使用

  1. @org.junit.Test
  2. public void readMoreTypeData(){
  3. String fileName = "C:/Users/Administrator/Desktop/learnEasyExcel.xls";
  4. // 这里 需要指定读用哪个class去读,然后读取第一个sheet
  5. EasyExcel.read(fileName, MoreTypeData.class, new MoreTypeDataListener())
  6. // 这里注意 我们也可以registerConverter来指定自定义转换器, 但是这个转换变成全局了, 所有java为string,excel为string的都会用这个转换器。
  7. // 如果就想单个字段使用请使用@ExcelProperty 指定converter
  8. // .registerConverter(new CustomStringStringConverter())
  9. // 读取sheet
  10. .sheet(2).doRead();
  11. }

多行头

  1. @org.junit.Test
  2. public void readMoreHeader(){
  3. String fileName = "C:/Users/Administrator/Desktop/learnEasyExcel.xls";
  4. // 这里 需要指定读用哪个class去读,然后读取第一个sheet
  5. EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().headRowNumber(1).doRead();
  6. // 这里可以设置1,因为头就是一行。如果多行头,可以设置其他值。不传入也可以,因为默认会根据DemoData 来解析,他没有指定头,也就是默认1行
  7. }

同步的返回

  1. @org.junit.Test
  2. public void synchronousRead() {
  3. String fileName = "C:/Users/Administrator/Desktop/learnEasyExcel.xls";
  4. // 这里 需要指定读用哪个class去读,然后读取第一个sheet 同步读取会自动finish
  5. List<DemoData> list = EasyExcel.read(fileName).head(DemoData.class).sheet().doReadSync();
  6. for (DemoData data : list) {
  7. System.out.println(data);
  8. }
  9. // 这里 也可以不指定class,返回一个list,然后读取第一个sheet 同步读取会自动finish
  10. List<Map<Integer, String>> listMap = EasyExcel.read(fileName).sheet().doReadSync();
  11. for (Map<Integer, String> data : listMap) {
  12. // 返回每条数据的键值对 表示所在的列 和所在列的值
  13. System.out.println(data);
  14. }
  15. }

读取表头数据

监听器
里面多实现一个方法即可

  1. @Override
  2. public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
  3. System.out.println(headMap);
  4. }
  1. @org.junit.Test
  2. public void headerRead() {
  3. String fileName = "C:/Users/Administrator/Desktop/learnEasyExcel.xls";
  4. // 这里 需要指定读用哪个class去读,然后读取第一个sheet
  5. EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();
  6. }

额外信息(批注、超链接、合并单元格)

excel
image.png
实体

  1. @Data
  2. public class DemoExtraData {
  3. private String row1;
  4. private String row2;
  5. }

监听器

  1. @Override
  2. public void extra(CellExtra extra, AnalysisContext context) {
  3. LOGGER.info("读取到了一条额外信息:{}", JSON.toJSONString(extra));
  4. switch (extra.getType()) {
  5. case COMMENT:
  6. LOGGER.info("额外信息是批注,在rowIndex:{},columnIndex;{},内容是:{}", extra.getRowIndex(), extra.getColumnIndex(),
  7. extra.getText());
  8. break;
  9. case HYPERLINK:
  10. if ("Sheet1!A1".equals(extra.getText())) {
  11. LOGGER.info("额外信息是超链接,在rowIndex:{},columnIndex;{},内容是:{}", extra.getRowIndex(),
  12. extra.getColumnIndex(), extra.getText());
  13. } else if ("Sheet2!A1".equals(extra.getText())) {
  14. LOGGER.info(
  15. "额外信息是超链接,而且覆盖了一个区间,在firstRowIndex:{},firstColumnIndex;{},lastRowIndex:{},lastColumnIndex:{},"
  16. + "内容是:{}",
  17. extra.getFirstRowIndex(), extra.getFirstColumnIndex(), extra.getLastRowIndex(),
  18. extra.getLastColumnIndex(), extra.getText());
  19. } else {
  20. Assert.fail("Unknown hyperlink!");
  21. }
  22. break;
  23. case MERGE:
  24. LOGGER.info(
  25. "额外信息是超链接,而且覆盖了一个区间,在firstRowIndex:{},firstColumnIndex;{},lastRowIndex:{},lastColumnIndex:{}",
  26. extra.getFirstRowIndex(), extra.getFirstColumnIndex(), extra.getLastRowIndex(),
  27. extra.getLastColumnIndex());
  28. break;
  29. default:
  30. }
  31. }
  1. /**
  2. * 额外信息(批注、超链接、合并单元格信息读取)
  3. * <p>
  4. * 由于是流式读取,没法在读取到单元格数据的时候直接读取到额外信息,所以只能最后通知哪些单元格有哪些额外信息
  5. *
  6. * <p>
  7. * 1. 创建excel对应的实体对象 参照{@link DemoExtraData}
  8. * <p>
  9. * 2. 由于默认异步读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoExtraListener}
  10. * <p>
  11. * 3. 直接读即可
  12. *
  13. * @since 2.2.0-beat1
  14. */
  15. @Test
  16. public void extraRead() {
  17. String fileName = TestFileUtil.getPath() + "demo" + File.separator + "extra.xlsx";
  18. // 这里 需要指定读用哪个class去读,然后读取第一个sheet
  19. EasyExcel.read(fileName, DemoExtraData.class, new DemoExtraListener())
  20. // 需要读取批注 默认不读取
  21. .extraRead(CellExtraTypeEnum.COMMENT)
  22. // 需要读取超链接 默认不读取
  23. .extraRead(CellExtraTypeEnum.HYPERLINK)
  24. // 需要读取合并单元格信息 默认不读取
  25. .extraRead(CellExtraTypeEnum.MERGE).sheet().doRead();
  26. }

写excel