diff --git a/pom.xml b/pom.xml index 51f6323..e50cf45 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.alibaba easyexcel - 2.2.0-beta2 + 2.2.1 jar easyexcel diff --git a/src/main/java/com/alibaba/excel/ExcelReader.java b/src/main/java/com/alibaba/excel/ExcelReader.java index 6cd0f78..7af49eb 100644 --- a/src/main/java/com/alibaba/excel/ExcelReader.java +++ b/src/main/java/com/alibaba/excel/ExcelReader.java @@ -136,6 +136,8 @@ public class ExcelReader { readWorkbook.setReadCache(new MapCache()); readWorkbook.setConvertAllFiled(Boolean.FALSE); readWorkbook.setDefaultReturnMap(Boolean.FALSE); + // The previous logic was that Article 0 started reading + readWorkbook.setHeadRowNumber(0); excelAnalyser = new ExcelAnalyserImpl(readWorkbook); } diff --git a/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java b/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java index 2b92253..bda4f53 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java @@ -138,11 +138,6 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor { } catch (IOException e) { throw new ExcelAnalysisException(e); } - // Sometimes tables lack the end record of the last column - if (!xlsReadContext.xlsReadSheetHolder().getCellMap().isEmpty()) { - // Forge a termination data - processRecord(new LastCellOfRowDummyRecord(xlsReadContext.xlsReadSheetHolder().getRowIndex() + 1, -1)); - } } @Override diff --git a/src/main/java/com/alibaba/excel/analysis/v03/handlers/EofRecordHandler.java b/src/main/java/com/alibaba/excel/analysis/v03/handlers/EofRecordHandler.java index 0ca7313..32b5b88 100644 --- a/src/main/java/com/alibaba/excel/analysis/v03/handlers/EofRecordHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v03/handlers/EofRecordHandler.java @@ -1,9 +1,16 @@ package com.alibaba.excel.analysis.v03.handlers; +import java.util.LinkedHashMap; + +import org.apache.poi.hssf.eventusermodel.dummyrecord.LastCellOfRowDummyRecord; import org.apache.poi.hssf.record.Record; import com.alibaba.excel.analysis.v03.IgnorableXlsRecordHandler; import com.alibaba.excel.context.xls.XlsReadContext; +import com.alibaba.excel.enums.RowTypeEnum; +import com.alibaba.excel.metadata.Cell; +import com.alibaba.excel.read.metadata.holder.ReadRowHolder; +import com.alibaba.excel.read.metadata.holder.xls.XlsReadSheetHolder; /** * Record handler @@ -14,8 +21,21 @@ public class EofRecordHandler extends AbstractXlsRecordHandler implements Ignora @Override public void processRecord(XlsReadContext xlsReadContext, Record record) { - if (xlsReadContext.readSheetHolder() != null) { - xlsReadContext.analysisEventProcessor().endSheet(xlsReadContext); + if (xlsReadContext.readSheetHolder() == null) { + return; + } + // Sometimes tables lack the end record of the last column + if (!xlsReadContext.xlsReadSheetHolder().getCellMap().isEmpty()) { + XlsReadSheetHolder xlsReadSheetHolder = xlsReadContext.xlsReadSheetHolder(); + // Forge a termination data + xlsReadContext.readRowHolder(new ReadRowHolder(xlsReadContext.xlsReadSheetHolder().getRowIndex() + 1, + xlsReadSheetHolder.getTempRowType(), + xlsReadContext.readSheetHolder().getGlobalConfiguration(), xlsReadSheetHolder.getCellMap())); + xlsReadContext.analysisEventProcessor().endRow(xlsReadContext); + xlsReadSheetHolder.setCellMap(new LinkedHashMap()); + xlsReadSheetHolder.setTempRowType(RowTypeEnum.EMPTY); } + + xlsReadContext.analysisEventProcessor().endSheet(xlsReadContext); } } diff --git a/src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java b/src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java index 61f3873..329b224 100644 --- a/src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java +++ b/src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java @@ -25,15 +25,13 @@ public class RowTagHandler extends AbstractXlsxTagHandler { int rowIndex = PositionUtils.getRowByRowTagt(attributes.getValue(ExcelXmlConstants.ATTRIBUTE_R), xlsxReadSheetHolder.getRowIndex()); Integer lastRowIndex = xlsxReadContext.readSheetHolder().getRowIndex(); - if (lastRowIndex != null) { - while (lastRowIndex + 1 < rowIndex) { - xlsxReadContext.readRowHolder(new ReadRowHolder(lastRowIndex + 1, RowTypeEnum.EMPTY, - xlsxReadSheetHolder.getGlobalConfiguration(), new LinkedHashMap())); - xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext); - xlsxReadSheetHolder.setColumnIndex(null); - xlsxReadSheetHolder.setCellMap(new LinkedHashMap()); - lastRowIndex++; - } + while (lastRowIndex + 1 < rowIndex) { + xlsxReadContext.readRowHolder(new ReadRowHolder(lastRowIndex + 1, RowTypeEnum.EMPTY, + xlsxReadSheetHolder.getGlobalConfiguration(), new LinkedHashMap())); + xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext); + xlsxReadSheetHolder.setColumnIndex(null); + xlsxReadSheetHolder.setCellMap(new LinkedHashMap()); + lastRowIndex++; } xlsxReadSheetHolder.setRowIndex(rowIndex); } diff --git a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java index 8465cbd..0af631c 100644 --- a/src/main/java/com/alibaba/excel/context/WriteContextImpl.java +++ b/src/main/java/com/alibaba/excel/context/WriteContextImpl.java @@ -111,7 +111,14 @@ public class WriteContextImpl implements WriteContext { if (selectSheetFromCache(writeSheet)) { return; } + + initCurrentSheetHolder(writeSheet); + + // Workbook handler need to supplementary execution + WriteHandlerUtils.beforeWorkbookCreate(this, true); + WriteHandlerUtils.afterWorkbookCreate(this, true); + // Initialization current sheet initSheet(writeType); } @@ -201,8 +208,8 @@ public class WriteContextImpl implements WriteContext { if (currentWriteHolder.automaticMergeHead()) { addMergedRegionToCurrentSheet(excelWriteHeadProperty, newRowIndex); } - for (int relativeRowIndex = 0, i = newRowIndex; i < excelWriteHeadProperty.getHeadRowNumber() + newRowIndex; - i++, relativeRowIndex++) { + for (int relativeRowIndex = 0, i = newRowIndex; i < excelWriteHeadProperty.getHeadRowNumber() + + newRowIndex; i++, relativeRowIndex++) { WriteHandlerUtils.beforeRowCreate(this, newRowIndex, relativeRowIndex, Boolean.TRUE); Row row = WorkBookUtil.createRow(writeSheetHolder.getSheet(), i); WriteHandlerUtils.afterRowCreate(this, row, relativeRowIndex, Boolean.TRUE); @@ -227,7 +234,7 @@ public class WriteContextImpl implements WriteContext { Cell cell = row.createCell(columnIndex); WriteHandlerUtils.afterCellCreate(this, cell, head, relativeRowIndex, Boolean.TRUE); cell.setCellValue(head.getHeadNameList().get(relativeRowIndex)); - WriteHandlerUtils.afterCellDispose(this, (CellData)null, cell, head, relativeRowIndex, Boolean.TRUE); + WriteHandlerUtils.afterCellDispose(this, (CellData) null, cell, head, relativeRowIndex, Boolean.TRUE); } } @@ -251,7 +258,15 @@ public class WriteContextImpl implements WriteContext { } return; } + initCurrentTableHolder(writeTable); + + // Workbook and sheet handler need to supplementary execution + WriteHandlerUtils.beforeWorkbookCreate(this, true); + WriteHandlerUtils.afterWorkbookCreate(this, true); + WriteHandlerUtils.beforeSheetCreate(this, true); + WriteHandlerUtils.afterSheetCreate(this, true); + initHead(writeTableHolder.excelWriteHeadProperty()); } @@ -322,7 +337,7 @@ public class WriteContextImpl implements WriteContext { try { Workbook workbook = writeWorkbookHolder.getWorkbook(); if (workbook instanceof SXSSFWorkbook) { - ((SXSSFWorkbook)workbook).dispose(); + ((SXSSFWorkbook) workbook).dispose(); } } catch (Throwable t) { throwable = t; diff --git a/src/main/java/com/alibaba/excel/converters/NullableObjectConverter.java b/src/main/java/com/alibaba/excel/converters/NullableObjectConverter.java new file mode 100644 index 0000000..43b1cb2 --- /dev/null +++ b/src/main/java/com/alibaba/excel/converters/NullableObjectConverter.java @@ -0,0 +1,11 @@ +package com.alibaba.excel.converters; + +/** + * When implementing convertToExcelData method, pay attention to the reference value may be + * null + * + * @author JiaJu Zhuang + **/ +public interface NullableObjectConverter extends Converter { + +} diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadSheetHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadSheetHolder.java index 87185dc..7a5272a 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadSheetHolder.java +++ b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadSheetHolder.java @@ -15,6 +15,7 @@ import com.alibaba.excel.read.metadata.ReadSheet; * @author Jiaju Zhuang */ public class ReadSheetHolder extends AbstractReadHolder { + /** * current param */ @@ -59,6 +60,7 @@ public class ReadSheetHolder extends AbstractReadHolder { this.sheetNo = readSheet.getSheetNo(); this.sheetName = readSheet.getSheetName(); this.cellMap = new LinkedHashMap(); + this.rowIndex = -1; } public ReadSheet getReadSheet() { diff --git a/src/main/java/com/alibaba/excel/util/ClassUtils.java b/src/main/java/com/alibaba/excel/util/ClassUtils.java index 64bc29d..20b30e3 100644 --- a/src/main/java/com/alibaba/excel/util/ClassUtils.java +++ b/src/main/java/com/alibaba/excel/util/ClassUtils.java @@ -109,11 +109,12 @@ public class ClassUtils { + "' and '" + field.getName() + "' must be inconsistent"); } customFiledMap.put(excelProperty.index(), field); - allFieldList.add(field); } + List allWriteFieldList = new ArrayList(customFiledMap.values()); + allWriteFieldList.addAll(allFieldList); FIELD_CACHE.put(clazz, - new SoftReference(new FieldCache(defaultFieldList, customFiledMap, allFieldList, ignoreMap))); + new SoftReference(new FieldCache(defaultFieldList, customFiledMap, allWriteFieldList, ignoreMap))); } private static class FieldCache { diff --git a/src/main/java/com/alibaba/excel/util/WriteHandlerUtils.java b/src/main/java/com/alibaba/excel/util/WriteHandlerUtils.java index 06dcc72..57f0c49 100644 --- a/src/main/java/com/alibaba/excel/util/WriteHandlerUtils.java +++ b/src/main/java/com/alibaba/excel/util/WriteHandlerUtils.java @@ -2,6 +2,7 @@ package com.alibaba.excel.util; import java.util.ArrayList; import java.util.List; +import java.util.Map; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; @@ -24,66 +25,82 @@ public class WriteHandlerUtils { private WriteHandlerUtils() {} + public static void beforeWorkbookCreate(WriteContext writeContext) { - List handlerList = - writeContext.writeWorkbookHolder().writeHandlerMap().get(WorkbookWriteHandler.class); + beforeWorkbookCreate(writeContext, false); + } + + public static void beforeWorkbookCreate(WriteContext writeContext, boolean runOwn) { + List handlerList = getHandlerList(writeContext, WorkbookWriteHandler.class, runOwn); if (handlerList == null || handlerList.isEmpty()) { return; } for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof WorkbookWriteHandler) { - ((WorkbookWriteHandler)writeHandler).beforeWorkbookCreate(); + ((WorkbookWriteHandler) writeHandler).beforeWorkbookCreate(); } } } public static void afterWorkbookCreate(WriteContext writeContext) { - List handlerList = - writeContext.writeWorkbookHolder().writeHandlerMap().get(WorkbookWriteHandler.class); + afterWorkbookCreate(writeContext, false); + } + + public static void afterWorkbookCreate(WriteContext writeContext, boolean runOwn) { + List handlerList = getHandlerList(writeContext, WorkbookWriteHandler.class, runOwn); if (handlerList == null || handlerList.isEmpty()) { return; } for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof WorkbookWriteHandler) { - ((WorkbookWriteHandler)writeHandler).afterWorkbookCreate(writeContext.writeWorkbookHolder()); + ((WorkbookWriteHandler) writeHandler).afterWorkbookCreate(writeContext.writeWorkbookHolder()); } } } public static void afterWorkbookDispose(WriteContext writeContext) { List handlerList = - writeContext.writeWorkbookHolder().writeHandlerMap().get(WorkbookWriteHandler.class); + writeContext.currentWriteHolder().writeHandlerMap().get(WorkbookWriteHandler.class); if (handlerList == null || handlerList.isEmpty()) { return; } for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof WorkbookWriteHandler) { - ((WorkbookWriteHandler)writeHandler).afterWorkbookDispose(writeContext.writeWorkbookHolder()); + ((WorkbookWriteHandler) writeHandler).afterWorkbookDispose(writeContext.writeWorkbookHolder()); } } } public static void beforeSheetCreate(WriteContext writeContext) { - List handlerList = writeContext.writeSheetHolder().writeHandlerMap().get(SheetWriteHandler.class); + beforeSheetCreate(writeContext, false); + } + + public static void beforeSheetCreate(WriteContext writeContext, boolean runOwn) { + List handlerList = getHandlerList(writeContext, SheetWriteHandler.class, runOwn); if (handlerList == null || handlerList.isEmpty()) { return; } for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof SheetWriteHandler) { - ((SheetWriteHandler)writeHandler).beforeSheetCreate(writeContext.writeWorkbookHolder(), + ((SheetWriteHandler) writeHandler).beforeSheetCreate(writeContext.writeWorkbookHolder(), writeContext.writeSheetHolder()); } } } + public static void afterSheetCreate(WriteContext writeContext) { - List handlerList = writeContext.writeSheetHolder().writeHandlerMap().get(SheetWriteHandler.class); + afterSheetCreate(writeContext, false); + } + + public static void afterSheetCreate(WriteContext writeContext, boolean runOwn) { + List handlerList = getHandlerList(writeContext, SheetWriteHandler.class, runOwn); if (handlerList == null || handlerList.isEmpty()) { return; } for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof SheetWriteHandler) { - ((SheetWriteHandler)writeHandler).afterSheetCreate(writeContext.writeWorkbookHolder(), + ((SheetWriteHandler) writeHandler).afterSheetCreate(writeContext.writeWorkbookHolder(), writeContext.writeSheetHolder()); } } @@ -102,7 +119,7 @@ public class WriteHandlerUtils { } for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof CellWriteHandler) { - ((CellWriteHandler)writeHandler).beforeCellCreate(writeContext.writeSheetHolder(), + ((CellWriteHandler) writeHandler).beforeCellCreate(writeContext.writeSheetHolder(), writeContext.writeTableHolder(), row, head, columnIndex, relativeRowIndex, isHead); } } @@ -117,7 +134,7 @@ public class WriteHandlerUtils { } for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof CellWriteHandler) { - ((CellWriteHandler)writeHandler).afterCellCreate(writeContext.writeSheetHolder(), + ((CellWriteHandler) writeHandler).afterCellCreate(writeContext.writeSheetHolder(), writeContext.writeTableHolder(), cell, head, relativeRowIndex, isHead); } } @@ -132,7 +149,7 @@ public class WriteHandlerUtils { } for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof CellWriteHandler) { - ((CellWriteHandler)writeHandler).afterCellDataConverted(writeContext.writeSheetHolder(), + ((CellWriteHandler) writeHandler).afterCellDataConverted(writeContext.writeSheetHolder(), writeContext.writeTableHolder(), cellData, cell, head, relativeRowIndex, isHead); } } @@ -156,7 +173,7 @@ public class WriteHandlerUtils { } for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof CellWriteHandler) { - ((CellWriteHandler)writeHandler).afterCellDispose(writeContext.writeSheetHolder(), + ((CellWriteHandler) writeHandler).afterCellDispose(writeContext.writeSheetHolder(), writeContext.writeTableHolder(), cellDataList, cell, head, relativeRowIndex, isHead); } } @@ -173,7 +190,7 @@ public class WriteHandlerUtils { } for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof RowWriteHandler) { - ((RowWriteHandler)writeHandler).beforeRowCreate(writeContext.writeSheetHolder(), + ((RowWriteHandler) writeHandler).beforeRowCreate(writeContext.writeSheetHolder(), writeContext.writeTableHolder(), rowIndex, relativeRowIndex, isHead); } } @@ -186,7 +203,7 @@ public class WriteHandlerUtils { } for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof RowWriteHandler) { - ((RowWriteHandler)writeHandler).afterRowCreate(writeContext.writeSheetHolder(), + ((RowWriteHandler) writeHandler).afterRowCreate(writeContext.writeSheetHolder(), writeContext.writeTableHolder(), row, relativeRowIndex, isHead); } } @@ -200,7 +217,7 @@ public class WriteHandlerUtils { } for (WriteHandler writeHandler : handlerList) { if (writeHandler instanceof RowWriteHandler) { - ((RowWriteHandler)writeHandler).afterRowDispose(writeContext.writeSheetHolder(), + ((RowWriteHandler) writeHandler).afterRowDispose(writeContext.writeSheetHolder(), writeContext.writeTableHolder(), row, relativeRowIndex, isHead); } } @@ -208,4 +225,15 @@ public class WriteHandlerUtils { writeContext.writeWorkbookHolder().getWriteWorkbook().getWriteHandler().row(row.getRowNum(), row); } } + + private static List getHandlerList(WriteContext writeContext, Class clazz, + boolean runOwn) { + Map, List> writeHandlerMap; + if (runOwn) { + writeHandlerMap = writeContext.currentWriteHolder().ownWriteHandlerMap(); + } else { + writeHandlerMap = writeContext.currentWriteHolder().writeHandlerMap(); + } + return writeHandlerMap.get(WorkbookWriteHandler.class); + } } diff --git a/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java b/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java index 4eb115c..12250f1 100644 --- a/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java +++ b/src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java @@ -10,6 +10,7 @@ import org.apache.poi.ss.usermodel.Sheet; import com.alibaba.excel.context.WriteContext; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.converters.ConverterKeyBuild; +import com.alibaba.excel.converters.NullableObjectConverter; import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.exception.ExcelDataConvertException; import com.alibaba.excel.metadata.CellData; @@ -32,11 +33,10 @@ public abstract class AbstractExcelWriteExecutor implements ExcelWriteExecutor { protected CellData converterAndSet(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value, ExcelContentProperty excelContentProperty, Head head, Integer relativeRowIndex) { - if (value == null) { - return new CellData(CellDataTypeEnum.EMPTY); - } - if (value instanceof String && currentWriteHolder.globalConfiguration().getAutoTrim()) { - value = ((String)value).trim(); + boolean needTrim = + value != null && (value instanceof String && currentWriteHolder.globalConfiguration().getAutoTrim()); + if (needTrim) { + value = ((String) value).trim(); } CellData cellData = convert(currentWriteHolder, clazz, cell, value, excelContentProperty); if (cellData.getFormula() != null && cellData.getFormula()) { @@ -70,9 +70,6 @@ public abstract class AbstractExcelWriteExecutor implements ExcelWriteExecutor { protected CellData convert(WriteHolder currentWriteHolder, Class clazz, Cell cell, Object value, ExcelContentProperty excelContentProperty) { - if (value == null) { - return new CellData(CellDataTypeEnum.EMPTY); - } // This means that the user has defined the data. if (value instanceof CellData) { CellData cellDataValue = (CellData)value; @@ -110,6 +107,9 @@ public abstract class AbstractExcelWriteExecutor implements ExcelWriteExecutor { new CellData(CellDataTypeEnum.EMPTY), excelContentProperty, "Can not find 'Converter' support class " + clazz.getSimpleName() + "."); } + if (value == null && !(converter instanceof NullableObjectConverter)) { + return new CellData(CellDataTypeEnum.EMPTY); + } CellData cellData; try { cellData = diff --git a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java index 51d7d3a..1a42fde 100644 --- a/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java +++ b/src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java @@ -48,28 +48,28 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { /** * Fields to replace in the template */ - private Map> templateAnalysisCache = new HashMap>(8); + private final Map> templateAnalysisCache = new HashMap>(8); /** * Collection fields to replace in the template */ - private Map> templateCollectionAnalysisCache = + private final Map> templateCollectionAnalysisCache = new HashMap>(8); /** * Style cache for collection fields */ - private Map> collectionFieldStyleCache = + private final Map> collectionFieldStyleCache = new HashMap>(8); /** * Row height cache for collection */ - private Map collectionRowHeightCache = new HashMap(8); + private final Map collectionRowHeightCache = new HashMap(8); /** * Last index cache for collection fields */ - private Map> collectionLastIndexCache = + private final Map> collectionLastIndexCache = new HashMap>(8); - private Map relativeRowIndexMap = new HashMap(8); + private final Map relativeRowIndexMap = new HashMap(8); /** * The data prefix that is populated this time */ @@ -94,7 +94,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { Object realData; if (data instanceof FillWrapper) { - FillWrapper fillWrapper = (FillWrapper)data; + FillWrapper fillWrapper = (FillWrapper) data; currentDataPrefix = fillWrapper.getName(); realData = fillWrapper.getCollectionData(); } else { @@ -106,7 +106,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { // processing data if (realData instanceof Collection) { List analysisCellList = readTemplateData(templateCollectionAnalysisCache); - Collection collectionData = (Collection)realData; + Collection collectionData = (Collection) realData; if (CollectionUtils.isEmpty(collectionData)) { return; } @@ -156,9 +156,23 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { return; } sheet.shiftRows(maxRowIndex + 1, lastRowIndex, number, true, false); - for (AnalysisCell analysisCell : templateAnalysisCache.get(currentUniqueDataFlag)) { - if (analysisCell.getRowIndex() > maxRowIndex) { - analysisCell.setRowIndex(analysisCell.getRowIndex() + number); + + // The current data is greater than unity rowindex increase + String tablePrefix = tablePrefix(currentUniqueDataFlag); + increaseRowIndex(templateAnalysisCache, number, maxRowIndex, tablePrefix); + increaseRowIndex(templateCollectionAnalysisCache, number, maxRowIndex, tablePrefix); + } + + private void increaseRowIndex(Map> templateAnalysisCache, int number, int maxRowIndex, + String tablePrefix) { + for (Map.Entry> entry : templateAnalysisCache.entrySet()) { + if (!tablePrefix.equals(tablePrefix(entry.getKey()))) { + continue; + } + for (AnalysisCell analysisCell : entry.getValue()) { + if (analysisCell.getRowIndex() > maxRowIndex) { + analysisCell.setRowIndex(analysisCell.getRowIndex() + number); + } } } } @@ -167,7 +181,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { Integer relativeRowIndex) { Map dataMap; if (oneRowData instanceof Map) { - dataMap = (Map)oneRowData; + dataMap = (Map) oneRowData; } else { dataMap = BeanMap.create(oneRowData); } @@ -384,8 +398,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { int startIndex = 0; int length = value.length(); int lastPrepareDataIndex = 0; - out: - while (startIndex < length) { + out: while (startIndex < length) { int prefixIndex = value.indexOf(FILL_PREFIX, startIndex); if (prefixIndex < 0) { break out; @@ -515,4 +528,8 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor { return prefix + "-" + wrapperName; } + private String tablePrefix(String uniqueDataFlag) { + return uniqueDataFlag.substring(0, uniqueDataFlag.indexOf("-") + 1); + } + } diff --git a/src/main/java/com/alibaba/excel/write/metadata/holder/AbstractWriteHolder.java b/src/main/java/com/alibaba/excel/write/metadata/holder/AbstractWriteHolder.java index 00f2ef7..77d5d06 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/holder/AbstractWriteHolder.java +++ b/src/main/java/com/alibaba/excel/write/metadata/holder/AbstractWriteHolder.java @@ -64,9 +64,14 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ */ private ExcelWriteHeadProperty excelWriteHeadProperty; /** - * Write handler for workbook + * Write handler */ private Map, List> writeHandlerMap; + /** + * Own write handler.Created in the sheet in the workbook interceptors will not be executed because the workbook to + * create an event long past. So when initializing sheet, supplementary workbook event. + */ + private Map, List> ownWriteHandlerMap; /** * Use the default style.Default is true. */ @@ -177,21 +182,22 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ List handlerList = new ArrayList(); // Initialization Annotation - initAnnotationConfig(handlerList); + initAnnotationConfig(handlerList, writeBasicParameter); if (writeBasicParameter.getCustomWriteHandlerList() != null && !writeBasicParameter.getCustomWriteHandlerList().isEmpty()) { handlerList.addAll(writeBasicParameter.getCustomWriteHandlerList()); } + this.ownWriteHandlerMap = sortAndClearUpHandler(handlerList); + Map, List> parentWriteHandlerMap = null; if (parentAbstractWriteHolder != null) { parentWriteHandlerMap = parentAbstractWriteHolder.getWriteHandlerMap(); } else { handlerList.addAll(DefaultWriteHandlerLoader.loadDefaultHandler(useDefaultStyle)); } - - this.writeHandlerMap = sortAndClearUpHandler(handlerList, parentWriteHandlerMap); + this.writeHandlerMap = sortAndClearUpAllHandler(handlerList, parentWriteHandlerMap); // Set converterMap if (parentAbstractWriteHolder == null) { @@ -215,13 +221,13 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ switch (holderType()) { case SHEET: compatibleOldCodeCreateRowCellStyleStrategy(writeBasicParameter, - ((WriteSheet)writeBasicParameter).getTableStyle()); + ((WriteSheet) writeBasicParameter).getTableStyle()); compatibleOldCodeCreateHeadColumnWidthStyleStrategy(writeBasicParameter, - ((WriteSheet)writeBasicParameter).getColumnWidthMap()); + ((WriteSheet) writeBasicParameter).getColumnWidthMap()); return; case TABLE: compatibleOldCodeCreateRowCellStyleStrategy(writeBasicParameter, - ((WriteTable)writeBasicParameter).getTableStyle()); + ((WriteTable) writeBasicParameter).getTableStyle()); return; default: } @@ -279,10 +285,13 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ }); } - protected void initAnnotationConfig(List handlerList) { + protected void initAnnotationConfig(List handlerList, WriteBasicParameter writeBasicParameter) { if (!HeadKindEnum.CLASS.equals(getExcelWriteHeadProperty().getHeadKind())) { return; } + if (writeBasicParameter.getClazz() == null) { + return; + } Map headMap = getExcelWriteHeadProperty().getHeadMap(); boolean hasColumnWidth = false; boolean hasStyle = false; @@ -308,7 +317,6 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ dealRowHigh(handlerList); dealOnceAbsoluteMerge(handlerList); - } private void dealStyle(List handlerList) { @@ -376,9 +384,9 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ handlerList.add(columnWidthStyleStrategy); } - protected Map, List> sortAndClearUpHandler( - List handlerList, Map, List> parentHandlerMap) { + protected Map, List> sortAndClearUpAllHandler( + List handlerList, Map, List> parentHandlerMap) { // add if (parentHandlerMap != null) { List parentWriteHandler = parentHandlerMap.get(WriteHandler.class); @@ -386,13 +394,17 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ handlerList.addAll(parentWriteHandler); } } + return sortAndClearUpHandler(handlerList); + } + protected Map, List> sortAndClearUpHandler( + List handlerList) { // sort Map> orderExcelWriteHandlerMap = new TreeMap>(); for (WriteHandler handler : handlerList) { int order = Integer.MIN_VALUE; if (handler instanceof Order) { - order = ((Order)handler).order(); + order = ((Order) handler).order(); } if (orderExcelWriteHandlerMap.containsKey(order)) { orderExcelWriteHandlerMap.get(order).add(handler); @@ -408,7 +420,7 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ for (Map.Entry> entry : orderExcelWriteHandlerMap.entrySet()) { for (WriteHandler handler : entry.getValue()) { if (handler instanceof NotRepeatExecutor) { - String uniqueValue = ((NotRepeatExecutor)handler).uniqueValue(); + String uniqueValue = ((NotRepeatExecutor) handler).uniqueValue(); if (alreadyExistedHandlerSet.contains(uniqueValue)) { continue; } @@ -480,6 +492,15 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ this.writeHandlerMap = writeHandlerMap; } + public Map, List> getOwnWriteHandlerMap() { + return ownWriteHandlerMap; + } + + public void setOwnWriteHandlerMap( + Map, List> ownWriteHandlerMap) { + this.ownWriteHandlerMap = ownWriteHandlerMap; + } + public ExcelWriteHeadProperty getExcelWriteHeadProperty() { return excelWriteHeadProperty; } @@ -554,6 +575,11 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ return getWriteHandlerMap(); } + @Override + public Map, List> ownWriteHandlerMap() { + return getOwnWriteHandlerMap(); + } + @Override public boolean needHead() { return getNeedHead(); diff --git a/src/main/java/com/alibaba/excel/write/metadata/holder/WriteHolder.java b/src/main/java/com/alibaba/excel/write/metadata/holder/WriteHolder.java index 2aa2066..4896b03 100644 --- a/src/main/java/com/alibaba/excel/write/metadata/holder/WriteHolder.java +++ b/src/main/java/com/alibaba/excel/write/metadata/holder/WriteHolder.java @@ -28,6 +28,13 @@ public interface WriteHolder extends ConfigurationHolder { */ Map, List> writeHandlerMap(); + /** + * create your own write handler. + * + * @return + */ + Map, List> ownWriteHandlerMap(); + /** * Is to determine if a field needs to be ignored * diff --git a/src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java b/src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java index 4790ab1..06a596f 100644 --- a/src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java +++ b/src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java @@ -11,6 +11,7 @@ import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; import com.alibaba.excel.write.handler.CellWriteHandler; import com.alibaba.excel.write.handler.SheetWriteHandler; +import com.alibaba.excel.write.handler.WorkbookWriteHandler; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteTableHolder; import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; @@ -20,7 +21,7 @@ import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; * * @author Jiaju Zhuang */ -public abstract class AbstractCellStyleStrategy implements CellWriteHandler, SheetWriteHandler, NotRepeatExecutor { +public abstract class AbstractCellStyleStrategy implements CellWriteHandler, WorkbookWriteHandler, NotRepeatExecutor { boolean hasInitialized = false; @Override @@ -60,16 +61,21 @@ public abstract class AbstractCellStyleStrategy implements CellWriteHandler, She } @Override - public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { + public void beforeWorkbookCreate() { } @Override - public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { + public void afterWorkbookCreate(WriteWorkbookHolder writeWorkbookHolder) { initCellStyle(writeWorkbookHolder.getWorkbook()); hasInitialized = true; } + @Override + public void afterWorkbookDispose(WriteWorkbookHolder writeWorkbookHolder) { + + } + /** * Initialization cell style * diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java b/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java index 6c9bd8d..c801077 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java @@ -32,7 +32,7 @@ public class Lock2Test { @Test public void test() throws Exception { - File file = new File("D:\\test\\headt1.xlsx"); + File file = TestFileUtil.readUserHomeFile("test/t3.xls"); List list = EasyExcel.read(file).sheet().headRowNumber(0).doReadSync(); LOGGER.info("数据:{}", list.size()); diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadListener.java b/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadListener.java new file mode 100644 index 0000000..31875fe --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadListener.java @@ -0,0 +1,42 @@ +package com.alibaba.easyexcel.test.temp.read; + +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import com.alibaba.fastjson.JSON; + +/** + * 模板的读取类 + * + * @author Jiaju Zhuang + */ +public class HeadListener extends AnalysisEventListener { + private static final Logger LOGGER = LoggerFactory.getLogger(HeadListener.class); + /** + * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收 + */ + private static final int BATCH_COUNT = 5; + + @Override + public void invokeHeadMap(Map headMap, AnalysisContext context) { + LOGGER.info("HEAD:{}", JSON.toJSONString(headMap)); + LOGGER.info("total:{}", context.readSheetHolder().getTotal()); + + } + + @Override + public void invoke(HeadReadData data, AnalysisContext context) { + LOGGER.info("index:{}", context.readRowHolder().getRowIndex()); + LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data)); + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + LOGGER.info("所有数据解析完成!"); + } + +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadData.java b/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadData.java index 538e266..62d5e31 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadData.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadData.java @@ -11,10 +11,9 @@ import lombok.experimental.Accessors; * @author Jiaju Zhuang **/ @Data -@Accessors(chain = true) public class HeadReadData { - @ExcelProperty("头1") + @ExcelProperty({"主标题","数据1"}) private String h1; - @ExcelProperty({"头", "头2"}) + @ExcelProperty({"主标题", "数据2"}) private String h2; } diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadTest.java index b046d14..40aa4b8 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadTest.java @@ -1,14 +1,18 @@ package com.alibaba.easyexcel.test.temp.read; import java.io.File; +import java.io.FileInputStream; import org.junit.Ignore; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelReader; import com.alibaba.excel.cache.Ehcache; +import com.alibaba.excel.support.ExcelTypeEnum; /** * 临时测试 @@ -18,11 +22,18 @@ import com.alibaba.excel.cache.Ehcache; @Ignore public class HeadReadTest { private static final Logger LOGGER = LoggerFactory.getLogger(HeadReadTest.class); + @Test + public void testread() throws Exception { + FileInputStream fileInputStream = new FileInputStream("D://test/t1.xlsx"); + + ExcelReader excelReader = new ExcelReader(fileInputStream, ExcelTypeEnum.XLSX, null, new TestListener()); + excelReader.read(); + } @Test public void test() throws Exception { - File file = new File("D:\\test\\headt1.xls"); - EasyExcel.read(file, HeadReadData.class, new HDListener()).sheet(0).doRead(); + File file = TestFileUtil.readUserHomeFile("test/t2.xlsx"); + EasyExcel.read(file, HeadReadData.class, new HeadListener()).ignoreEmptyRow(false).sheet(0).doRead(); } diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/read/TestListener.java b/src/test/java/com/alibaba/easyexcel/test/temp/read/TestListener.java new file mode 100644 index 0000000..fb80a9a --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/read/TestListener.java @@ -0,0 +1,27 @@ +package com.alibaba.easyexcel.test.temp.read; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.event.AnalysisEventListener; +import com.alibaba.fastjson.JSON; + +import lombok.extern.slf4j.Slf4j; + +/** + * TODO + * + * @author JiaJu Zhuang + * @date 2020/4/9 16:33 + **/ +@Slf4j +public class TestListener extends AnalysisEventListener { + + @Override + public void invoke(Object o, AnalysisContext analysisContext) { + log.info("解析一条:{}", JSON.toJSONString(o)); + } + + @Override + public void doAfterAllAnalysed(AnalysisContext analysisContext) { + + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/simple/DemoData1.java b/src/test/java/com/alibaba/easyexcel/test/temp/simple/DemoData1.java new file mode 100644 index 0000000..40b454e --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/simple/DemoData1.java @@ -0,0 +1,27 @@ +package com.alibaba.easyexcel.test.temp.simple; + +import java.util.Date; + +import org.apache.poi.ss.usermodel.FillPatternType; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.HeadStyle; + +import lombok.Data; + +@Data +public class DemoData1 { + @ExcelProperty("字符串标题") + @HeadStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 42) + private String string; + @ExcelProperty("日期标题") + private Date date; + @ExcelProperty("数字标题") + private Double doubleData; + /** + * 忽略这个字段 + */ + @ExcelIgnore + private String ignore; +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/simple/DemoData2.java b/src/test/java/com/alibaba/easyexcel/test/temp/simple/DemoData2.java new file mode 100644 index 0000000..a57af8f --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/simple/DemoData2.java @@ -0,0 +1,27 @@ +package com.alibaba.easyexcel.test.temp.simple; + +import java.util.Date; + +import org.apache.poi.ss.usermodel.FillPatternType; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.alibaba.excel.annotation.write.style.HeadStyle; + +import lombok.Data; + +@Data +public class DemoData2 { + @ExcelProperty("字符串标题") + @HeadStyle(fillPatternType = FillPatternType.SOLID_FOREGROUND, fillForegroundColor = 42) + private String string; + @ExcelProperty("日期标题") + private Date date; + @ExcelProperty("数字标题") + private Double doubleData; + /** + * 忽略这个字段 + */ + @ExcelIgnore + private String ignore; +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/simple/Wirte.java b/src/test/java/com/alibaba/easyexcel/test/temp/simple/Wirte.java index 6157181..e31e74b 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/simple/Wirte.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/simple/Wirte.java @@ -14,6 +14,9 @@ import com.alibaba.easyexcel.test.core.large.LargeData; import com.alibaba.easyexcel.test.demo.write.DemoData; import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.alibaba.excel.write.metadata.WriteTable; import com.alibaba.fastjson.JSON; import net.sf.cglib.beans.BeanMap; @@ -53,7 +56,7 @@ public class Wirte { String fileName = TestFileUtil.getPath() + "t22" + System.currentTimeMillis() + ".xlsx"; // 这里 需要指定写用哪个class去读,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 // 如果这里想使用03 则 传入excelType参数即可 - EasyExcel.write(fileName, WriteData.class).sheet("模板").doWrite(data1()); + EasyExcel.write(fileName, WriteData.class).sheet("模板").registerWriteHandler(new WriteHandler()).doWrite(data1()); } @Test @@ -75,6 +78,23 @@ public class Wirte { } + @Test + public void tableWrite() { + String fileName = TestFileUtil.getPath() + "tableWrite" + System.currentTimeMillis() + ".xlsx"; + // 这里直接写多个table的案例了,如果只有一个 也可以直一行代码搞定,参照其他案例 + // 这里 需要指定写用哪个class去写 + ExcelWriter excelWriter = EasyExcel.write(fileName).build(); + // 把sheet设置为不需要头 不然会输出sheet的头 这样看起来第一个table 就有2个头了 + WriteSheet writeSheet = EasyExcel.writerSheet("模板").build(); + // 这里必须指定需要头,table 会继承sheet的配置,sheet配置了不需要,table 默认也是不需要 + WriteTable writeTable0 = EasyExcel.writerTable(0).head(DemoData1.class).build(); + // 第一次写入会创建头 + excelWriter.write(data(), writeSheet, writeTable0); + // 第二次写如也会创建头,然后在第一次的后面写入数据 + /// 千万别忘记finish 会帮忙关闭流 + excelWriter.finish(); + } + private List> head() { List> list = new ArrayList>(); List head0 = new ArrayList(); diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteData.java b/src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteData.java index b8ff14d..b9de59b 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteData.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteData.java @@ -1,5 +1,7 @@ package com.alibaba.easyexcel.test.temp.simple; +import com.alibaba.excel.annotation.write.style.ContentStyle; + import lombok.Data; /** @@ -9,5 +11,6 @@ import lombok.Data; **/ @Data public class WriteData { + @ContentStyle(locked = true) private float f; } diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteHandler.java b/src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteHandler.java new file mode 100644 index 0000000..1420b2b --- /dev/null +++ b/src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteHandler.java @@ -0,0 +1,21 @@ +package com.alibaba.easyexcel.test.temp.simple; + +import com.alibaba.excel.write.handler.AbstractSheetWriteHandler; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; + +import lombok.extern.slf4j.Slf4j; + +/** + * @author Jiaju Zhuang + */ +@Slf4j +public class WriteHandler extends AbstractSheetWriteHandler { + + @Override + public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, + WriteSheetHolder writeSheetHolder) { + log.info("锁住"); + writeSheetHolder.getSheet().protectSheet("edit"); + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/util/TestFileUtil.java b/src/test/java/com/alibaba/easyexcel/test/util/TestFileUtil.java index 2031e70..d4665b4 100644 --- a/src/test/java/com/alibaba/easyexcel/test/util/TestFileUtil.java +++ b/src/test/java/com/alibaba/easyexcel/test/util/TestFileUtil.java @@ -5,6 +5,7 @@ import java.io.InputStream; public class TestFileUtil { + public static InputStream getResourcesFileInputStream(String fileName) { return Thread.currentThread().getContextClassLoader().getResourceAsStream("" + fileName); } @@ -29,4 +30,7 @@ public class TestFileUtil { return new File(getPath() + pathName); } + public static File readUserHomeFile(String pathName) { + return new File(System.getProperty("user.home") + File.separator + pathName); + } } diff --git a/update.md b/update.md index b075a26..fe4b1ae 100644 --- a/update.md +++ b/update.md @@ -1,3 +1,12 @@ +# 2.2.1 +* 发布正式版 +* 修复第一行为空不会调用`invokeHeadMap`的bug [Issue #993](https://github.com/alibaba/easyexcel/issues/993) +* 当类的属性没有按照ExcelProperty的属性index顺序排序的时候,写数据出现错乱 [Issue #1046](https://github.com/alibaba/easyexcel/issues/1046) +* 新增支持自定义转换器 入参可以为空 实现`NullableObjectConverter` 即可 [Issue #1084](https://github.com/alibaba/easyexcel/issues/1084) +* 修复xls丢失结束标记的情况下 会漏读最后一行 +* 修复填充的时候 多次`forceNewRow` 空指针的bug [Issue #1201](https://github.com/alibaba/easyexcel/issues/1201) +* 修复`table`、`sheet`中创建的拦截器不执行`workbook`事件的bug [Issue #1202](https://github.com/alibaba/easyexcel/issues/1202) + # 2.2.0-beta2 * 修复最长匹配策略不同表格会有影响的bug [Issue #1010](https://github.com/alibaba/easyexcel/issues/1010) * `LinkedList`写入的性能问题 #1121 @@ -20,6 +29,9 @@ * 修复读取转换器的并发问题 * 填充支持多个List对象 +# 2.1.7 +* 修复使用1+版本的写法,第1条开始读修改为第0条开始读 + # 2.1.6 * 修复写入只有`sheetName`会抛异常