只要在实现了AnalysisEventListener接口的监听器中,重写invokeHeadMap方法即可
/** * 这里会一行行的返回头 * * @param headMap * @param context */ @Override public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) { LOGGER.info("解析到一条头数据:{}", JSON.toJSONString(headMap)); } 1.6.5. 转换异常处理只要在实现了AnalysisEventListener接口的监听器中,重写onException方法即可
@Override public void onException(Exception exception, AnalysisContext context) { LOGGER.error("解析失败,但是继续解析下一行:{}", exception.getMessage()); if (exception instanceof ExcelDataConvertException) { ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception; LOGGER.error("第{}行,第{}列解析异常", excelDataConvertException.getRowIndex(), excelDataConvertException.getColumnIndex()); } } 1.6.6. 读取单元格参数和类型将类属性用CellData封装起来
@Data public class CellDataReadDemoData { private CellData<String> string; // 这里注意 虽然是日期 但是 类型 存储的是number 因为excel 存储的就是number private CellData<Date> date; private CellData<Double> doubleData; // 这里并不一定能完美的获取 有些公式是依赖性的 可能会读不到 这个问题后续会修复 private CellData<String> formulaValue; }这样读取到的数据如下,会包含单元格数据类型
解析到一条数据:{"date":{"data":1577811661000,"dataFormat":22,"dataFormatString":"m/d/yy h:mm","formula":false,"numberValue":43831.0423726852,"type":"NUMBER"},"doubleData":{"data":1.0,"formula":false,"numberValue":1,"type":"NUMBER"},"formulaValue":{"data":"字符串01","formula":true,"formulaValue":"_xlfn.CONCAT(A2,C2)","stringValue":"字符串01","type":"STRING"},"string":{"data":"字符串0","dataFormat":0,"dataFormatString":"General","formula":false,"stringValue":"字符串0","type":"STRING"}} 1.6.7. 同步返回不推荐使用,但如果特定情况一定要用,可以如下,主要为doReadSync方法,直接返回List
/** * 同步的返回,不推荐使用,如果数据量大会把数据放到内存里面 */ @Test public void synchronousRead() { String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx"; // 这里 需要指定读用哪个class去读,然后读取第一个sheet 同步读取会自动finish List<Object> list = EasyExcel.read(fileName).head(DemoData.class).sheet().doReadSync(); for (Object obj : list) { DemoData data = (DemoData)obj; LOGGER.info("读取到数据:{}", JSON.toJSONString(data)); } // 这里 也可以不指定class,返回一个list,然后读取第一个sheet 同步读取会自动finish list = EasyExcel.read(fileName).sheet().doReadSync(); for (Object obj : list) { // 返回每条数据的键值对 表示所在的列 和所在列的值 Map<Integer, String> data = (Map<Integer, String>)obj; LOGGER.info("读取到数据:{}", JSON.toJSONString(data)); } } 1.6.8. 无对象的读顾名思义,不创建实体对象来读取Excel数据,那么我们就用Map接收,但这种对日期不友好,对于简单字段的读取可以使用
其它都一样,监听器的继承中泛型参数变为Map即可
public class NoModleDataListener extends AnalysisEventListener<Map<Integer, String>> { ... }结果截取如下
解析到一条数据:{0:"字符串0",1:"2020-01-01 01:01:01",2:"1"} 1.7. 写入技巧 1.7.1. 排除特定字段和只写入特定字段使用excludeColumnFiledNames来排除特定字段写入,用includeColumnFiledNames表示只写入特定字段
/** * 根据参数只导出指定列 * <p> * 1. 创建excel对应的实体对象 参照{@link DemoData} * <p> * 2. 根据自己或者排除自己需要的列 * <p> * 3. 直接写即可 */ @Test public void excludeOrIncludeWrite() { String fileName = TestFileUtil.getPath() + "excludeOrIncludeWrite" + System.currentTimeMillis() + ".xlsx"; // 根据用户传入字段 假设我们要忽略 date Set<String> excludeColumnFiledNames = new HashSet<String>(); excludeColumnFiledNames.add("date"); // 这里 需要指定写用哪个class去读,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 EasyExcel.write(fileName, DemoData.class).excludeColumnFiledNames(excludeColumnFiledNames).sheet("模板") .doWrite(data()); fileName = TestFileUtil.getPath() + "excludeOrIncludeWrite" + System.currentTimeMillis() + ".xlsx"; // 根据用户传入字段 假设我们只要导出 date Set<String> includeColumnFiledNames = new HashSet<String>(); includeColumnFiledNames.add("date"); // 这里 需要指定写用哪个class去读,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 EasyExcel.write(fileName, DemoData.class).includeColumnFiledNames(includeColumnFiledNames).sheet("模板") .doWrite(data()); } 1.7.2. 指定写入列