具体看notifyAfterAllAnalysed的代码,我们实现的DemoDataListener监听器继承AnalysisEventListener,而AnalysisEventListener实现ReadListener接口
@Override public void notifyAfterAllAnalysed(AnalysisContext analysisContext) { for (ReadListener readListener : readListenerList) { readListener.doAfterAllAnalysed(analysisContext); } } 1.3. Excel写 1.3.1. 例子如下例子,使用还是简单的,和读比较类似
/** * 最简单的写 * <p>1. 创建excel对应的实体对象 参照{@link com.alibaba.easyexcel.test.demo.write.DemoData} * <p>2. 直接写即可 */ @Test public void simpleWrite() { String fileName = TestFileUtil.getPath() + "write" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去读,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 // 如果这里想使用03 则 传入excelType参数即可 EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data()); } private List<DemoData> data() { List<DemoData> list = new ArrayList<DemoData>(); for (int i = 0; i < 10; i++) { DemoData data = new DemoData(); data.setString("字符串" + i); data.setDate(new Date()); data.setDoubleData(0.56); list.add(data); } return list; } 1.3.2. 源码解析 1.3.2.1. doWrite和读一样doWrite才是实际做事的,这次我们从这个入口跟进
public void doWrite(List data) { if (excelWriter == null) { throw new ExcelGenerateException("Must use 'EasyExcelFactory.write().sheet()' to call this method"); } excelWriter.write(data, build()); excelWriter.finish(); } 1.3.2.2. write很明显,write是核心,继续进入ExcelWriter类,看名字addContent就是添加数据了,由excelBuilderExcel建造者来添加,这是ExcelBuilderImpl类
public ExcelWriter write(List data, WriteSheet writeSheet, WriteTable writeTable) { excelBuilder.addContent(data, writeSheet, writeTable); return this; } 1.3.2.3. addContent可以看到如下,显示封装和实例化一些数据,创建了ExcelWriteAddExecutor写数据执行器,核心就是add方法了
@Override public void addContent(List data, WriteSheet writeSheet, WriteTable writeTable) { try { if (data == null) { return; } context.currentSheet(writeSheet, WriteTypeEnum.ADD); context.currentTable(writeTable); if (excelWriteAddExecutor == null) { excelWriteAddExecutor = new ExcelWriteAddExecutor(context); } //核心 excelWriteAddExecutor.add(data); } catch (RuntimeException e) { finish(); throw e; } catch (Throwable e) { finish(); throw new ExcelGenerateException(e); } } 1.3.2.4. add可以看到很明显在遍历数据addOneRowOfDataToExcel插入到Excel表了
public void add(List data) { if (CollectionUtils.isEmpty(data)) { return; } WriteSheetHolder writeSheetHolder = writeContext.writeSheetHolder(); int newRowIndex = writeSheetHolder.getNewRowIndexAndStartDoWrite(); if (writeSheetHolder.isNew() && !writeSheetHolder.getExcelWriteHeadProperty().hasHead()) { newRowIndex += writeContext.currentWriteHolder().relativeHeadRowIndex(); } // BeanMap is out of order,so use fieldList List<Field> fieldList = new ArrayList<Field>(); for (int relativeRowIndex = 0; relativeRowIndex < data.size(); relativeRowIndex++) { int n = relativeRowIndex + newRowIndex; addOneRowOfDataToExcel(data.get(relativeRowIndex), n, relativeRowIndex, fieldList); } } 1.3.2.5. addOneRowOfDataToExcel这里先是做创建Excel行的准备,包括行的一些属性处理器需不需要处理,之后我们的例子是插入java对象,进入addJavaObjectToExcel方法
private void addOneRowOfDataToExcel(Object oneRowData, int n, int relativeRowIndex, List<Field> fieldList) { if (oneRowData == null) { return; } WriteHandlerUtils.beforeRowCreate(writeContext, n, relativeRowIndex, Boolean.FALSE); Row row = WorkBookUtil.createRow(writeContext.writeSheetHolder().getSheet(), n); WriteHandlerUtils.afterRowCreate(writeContext, row, relativeRowIndex, Boolean.FALSE); if (oneRowData instanceof List) { addBasicTypeToExcel((List)oneRowData, row, relativeRowIndex); } else { addJavaObjectToExcel(oneRowData, row, relativeRowIndex, fieldList); } WriteHandlerUtils.afterRowDispose(writeContext, row, relativeRowIndex, Boolean.FALSE); } 1.3.2.6. addJavaObjectToExcel在ExcelWriteAddExecutor执行器类中执行addJavaObjectToExcel,在这里进行了数据的解析,将数据解析成标题和内容,封装成适合Excel的格式CellData,数据类型等,经过这步我们还没看到文件流的生成,那么下一步了
private void addJavaObjectToExcel(Object oneRowData, Row row, int relativeRowIndex, List<Field> fieldList) { WriteHolder currentWriteHolder = writeContext.currentWriteHolder(); BeanMap beanMap = BeanMap.create(oneRowData); Set<String> beanMapHandledSet = new HashSet<String>(); int cellIndex = 0; // If it's a class it needs to be cast by type if (HeadKindEnum.CLASS.equals(writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadKind())) { Map<Integer, Head> headMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadMap(); Map<Integer, ExcelContentProperty> contentPropertyMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getContentPropertyMap(); for (Map.Entry<Integer, ExcelContentProperty> entry : contentPropertyMap.entrySet()) { cellIndex = entry.getKey(); ExcelContentProperty excelContentProperty = entry.getValue(); String name = excelContentProperty.getField().getName(); if (writeContext.currentWriteHolder().ignore(name, cellIndex)) { continue; } if (!beanMap.containsKey(name)) { continue; } Head head = headMap.get(cellIndex); WriteHandlerUtils.beforeCellCreate(writeContext, row, head, cellIndex, relativeRowIndex, Boolean.FALSE); Cell cell = WorkBookUtil.createCell(row, cellIndex); WriteHandlerUtils.afterCellCreate(writeContext, cell, head, relativeRowIndex, Boolean.FALSE); Object value = beanMap.get(name); CellData cellData = converterAndSet(currentWriteHolder, excelContentProperty.getField().getType(), cell, value, excelContentProperty); WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, head, relativeRowIndex, Boolean.FALSE); beanMapHandledSet.add(name); } } // Finish if (beanMapHandledSet.size() == beanMap.size()) { return; } if (cellIndex != 0) { cellIndex++; } Map<String, Field> ignoreMap = writeContext.currentWriteHolder().excelWriteHeadProperty().getIgnoreMap(); initFieldList(oneRowData.getClass(), fieldList); for (Field field : fieldList) { String filedName = field.getName(); boolean uselessData = !beanMap.containsKey(filedName) || beanMapHandledSet.contains(filedName) || ignoreMap.containsKey(filedName) || writeContext.currentWriteHolder().ignore(filedName, cellIndex); if (uselessData) { continue; } Object value = beanMap.get(filedName); if (value == null) { continue; } WriteHandlerUtils.beforeCellCreate(writeContext, row, null, cellIndex, relativeRowIndex, Boolean.FALSE); Cell cell = WorkBookUtil.createCell(row, cellIndex++); WriteHandlerUtils.afterCellCreate(writeContext, cell, null, relativeRowIndex, Boolean.FALSE); CellData cellData = converterAndSet(currentWriteHolder, value.getClass(), cell, value, null); WriteHandlerUtils.afterCellDispose(writeContext, cellData, cell, null, relativeRowIndex, Boolean.FALSE); } } 1.3.2.7. finishdoWrite中之后还有一步finish
public void finish() { excelBuilder.finish(); }深入ExcelBuilderImpl类
@Override public void finish() { if (context != null) { context.finish(); } }