Browse Source

Merge pull request #1265 from alibaba/developing

Developing
developing
Jiaju Zhuang 5 years ago committed by GitHub
parent
commit
245be48ef8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      pom.xml
  2. 2
      src/main/java/com/alibaba/excel/ExcelReader.java
  3. 5
      src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java
  4. 24
      src/main/java/com/alibaba/excel/analysis/v03/handlers/EofRecordHandler.java
  5. 16
      src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java
  6. 23
      src/main/java/com/alibaba/excel/context/WriteContextImpl.java
  7. 11
      src/main/java/com/alibaba/excel/converters/NullableObjectConverter.java
  8. 2
      src/main/java/com/alibaba/excel/read/metadata/holder/ReadSheetHolder.java
  9. 5
      src/main/java/com/alibaba/excel/util/ClassUtils.java
  10. 66
      src/main/java/com/alibaba/excel/util/WriteHandlerUtils.java
  11. 16
      src/main/java/com/alibaba/excel/write/executor/AbstractExcelWriteExecutor.java
  12. 45
      src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java
  13. 52
      src/main/java/com/alibaba/excel/write/metadata/holder/AbstractWriteHolder.java
  14. 7
      src/main/java/com/alibaba/excel/write/metadata/holder/WriteHolder.java
  15. 12
      src/main/java/com/alibaba/excel/write/style/AbstractCellStyleStrategy.java
  16. 2
      src/test/java/com/alibaba/easyexcel/test/temp/Lock2Test.java
  17. 42
      src/test/java/com/alibaba/easyexcel/test/temp/read/HeadListener.java
  18. 5
      src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadData.java
  19. 15
      src/test/java/com/alibaba/easyexcel/test/temp/read/HeadReadTest.java
  20. 27
      src/test/java/com/alibaba/easyexcel/test/temp/read/TestListener.java
  21. 27
      src/test/java/com/alibaba/easyexcel/test/temp/simple/DemoData1.java
  22. 27
      src/test/java/com/alibaba/easyexcel/test/temp/simple/DemoData2.java
  23. 22
      src/test/java/com/alibaba/easyexcel/test/temp/simple/Wirte.java
  24. 3
      src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteData.java
  25. 21
      src/test/java/com/alibaba/easyexcel/test/temp/simple/WriteHandler.java
  26. 4
      src/test/java/com/alibaba/easyexcel/test/util/TestFileUtil.java
  27. 12
      update.md

2
pom.xml

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.0-beta2</version>
<version>2.2.1</version>
<packaging>jar</packaging>
<name>easyexcel</name>

2
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);
}

5
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

24
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<Integer, Cell>());
xlsReadSheetHolder.setTempRowType(RowTypeEnum.EMPTY);
}
xlsReadContext.analysisEventProcessor().endSheet(xlsReadContext);
}
}

16
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<Integer, Cell>()));
xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext);
xlsxReadSheetHolder.setColumnIndex(null);
xlsxReadSheetHolder.setCellMap(new LinkedHashMap<Integer, Cell>());
lastRowIndex++;
}
while (lastRowIndex + 1 < rowIndex) {
xlsxReadContext.readRowHolder(new ReadRowHolder(lastRowIndex + 1, RowTypeEnum.EMPTY,
xlsxReadSheetHolder.getGlobalConfiguration(), new LinkedHashMap<Integer, Cell>()));
xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext);
xlsxReadSheetHolder.setColumnIndex(null);
xlsxReadSheetHolder.setCellMap(new LinkedHashMap<Integer, Cell>());
lastRowIndex++;
}
xlsxReadSheetHolder.setRowIndex(rowIndex);
}

23
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;

11
src/main/java/com/alibaba/excel/converters/NullableObjectConverter.java

@ -0,0 +1,11 @@
package com.alibaba.excel.converters;
/**
* When implementing <code>convertToExcelData</code> method, pay attention to the reference <code>value</code> may be
* null
*
* @author JiaJu Zhuang
**/
public interface NullableObjectConverter<T> extends Converter<T> {
}

2
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<Integer, Cell>();
this.rowIndex = -1;
}
public ReadSheet getReadSheet() {

5
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<Field> allWriteFieldList = new ArrayList<Field>(customFiledMap.values());
allWriteFieldList.addAll(allFieldList);
FIELD_CACHE.put(clazz,
new SoftReference<FieldCache>(new FieldCache(defaultFieldList, customFiledMap, allFieldList, ignoreMap)));
new SoftReference<FieldCache>(new FieldCache(defaultFieldList, customFiledMap, allWriteFieldList, ignoreMap)));
}
private static class FieldCache {

66
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<WriteHandler> handlerList =
writeContext.writeWorkbookHolder().writeHandlerMap().get(WorkbookWriteHandler.class);
beforeWorkbookCreate(writeContext, false);
}
public static void beforeWorkbookCreate(WriteContext writeContext, boolean runOwn) {
List<WriteHandler> 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<WriteHandler> handlerList =
writeContext.writeWorkbookHolder().writeHandlerMap().get(WorkbookWriteHandler.class);
afterWorkbookCreate(writeContext, false);
}
public static void afterWorkbookCreate(WriteContext writeContext, boolean runOwn) {
List<WriteHandler> 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<WriteHandler> 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<WriteHandler> handlerList = writeContext.writeSheetHolder().writeHandlerMap().get(SheetWriteHandler.class);
beforeSheetCreate(writeContext, false);
}
public static void beforeSheetCreate(WriteContext writeContext, boolean runOwn) {
List<WriteHandler> 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<WriteHandler> handlerList = writeContext.writeSheetHolder().writeHandlerMap().get(SheetWriteHandler.class);
afterSheetCreate(writeContext, false);
}
public static void afterSheetCreate(WriteContext writeContext, boolean runOwn) {
List<WriteHandler> 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<WriteHandler> getHandlerList(WriteContext writeContext, Class<? extends WriteHandler> clazz,
boolean runOwn) {
Map<Class<? extends WriteHandler>, List<WriteHandler>> writeHandlerMap;
if (runOwn) {
writeHandlerMap = writeContext.currentWriteHolder().ownWriteHandlerMap();
} else {
writeHandlerMap = writeContext.currentWriteHolder().writeHandlerMap();
}
return writeHandlerMap.get(WorkbookWriteHandler.class);
}
}

16
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 =

45
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<String, List<AnalysisCell>> templateAnalysisCache = new HashMap<String, List<AnalysisCell>>(8);
private final Map<String, List<AnalysisCell>> templateAnalysisCache = new HashMap<String, List<AnalysisCell>>(8);
/**
* Collection fields to replace in the template
*/
private Map<String, List<AnalysisCell>> templateCollectionAnalysisCache =
private final Map<String, List<AnalysisCell>> templateCollectionAnalysisCache =
new HashMap<String, List<AnalysisCell>>(8);
/**
* Style cache for collection fields
*/
private Map<String, Map<AnalysisCell, CellStyle>> collectionFieldStyleCache =
private final Map<String, Map<AnalysisCell, CellStyle>> collectionFieldStyleCache =
new HashMap<String, Map<AnalysisCell, CellStyle>>(8);
/**
* Row height cache for collection
*/
private Map<String, Short> collectionRowHeightCache = new HashMap<String, Short>(8);
private final Map<String, Short> collectionRowHeightCache = new HashMap<String, Short>(8);
/**
* Last index cache for collection fields
*/
private Map<String, Map<AnalysisCell, Integer>> collectionLastIndexCache =
private final Map<String, Map<AnalysisCell, Integer>> collectionLastIndexCache =
new HashMap<String, Map<AnalysisCell, Integer>>(8);
private Map<String, Integer> relativeRowIndexMap = new HashMap<String, Integer>(8);
private final Map<String, Integer> relativeRowIndexMap = new HashMap<String, Integer>(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<AnalysisCell> 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<String, List<AnalysisCell>> templateAnalysisCache, int number, int maxRowIndex,
String tablePrefix) {
for (Map.Entry<String, List<AnalysisCell>> 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);
}
}

52
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<Class<? extends WriteHandler>, List<WriteHandler>> 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<Class<? extends WriteHandler>, List<WriteHandler>> ownWriteHandlerMap;
/**
* Use the default style.Default is true.
*/
@ -177,21 +182,22 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ
List<WriteHandler> handlerList = new ArrayList<WriteHandler>();
// Initialization Annotation
initAnnotationConfig(handlerList);
initAnnotationConfig(handlerList, writeBasicParameter);
if (writeBasicParameter.getCustomWriteHandlerList() != null
&& !writeBasicParameter.getCustomWriteHandlerList().isEmpty()) {
handlerList.addAll(writeBasicParameter.getCustomWriteHandlerList());
}
this.ownWriteHandlerMap = sortAndClearUpHandler(handlerList);
Map<Class<? extends WriteHandler>, List<WriteHandler>> 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<WriteHandler> handlerList) {
protected void initAnnotationConfig(List<WriteHandler> handlerList, WriteBasicParameter writeBasicParameter) {
if (!HeadKindEnum.CLASS.equals(getExcelWriteHeadProperty().getHeadKind())) {
return;
}
if (writeBasicParameter.getClazz() == null) {
return;
}
Map<Integer, Head> 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<WriteHandler> handlerList) {
@ -376,9 +384,9 @@ public abstract class AbstractWriteHolder extends AbstractHolder implements Writ
handlerList.add(columnWidthStyleStrategy);
}
protected Map<Class<? extends WriteHandler>, List<WriteHandler>> sortAndClearUpHandler(
List<WriteHandler> handlerList, Map<Class<? extends WriteHandler>, List<WriteHandler>> parentHandlerMap) {
protected Map<Class<? extends WriteHandler>, List<WriteHandler>> sortAndClearUpAllHandler(
List<WriteHandler> handlerList, Map<Class<? extends WriteHandler>, List<WriteHandler>> parentHandlerMap) {
// add
if (parentHandlerMap != null) {
List<WriteHandler> 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<Class<? extends WriteHandler>, List<WriteHandler>> sortAndClearUpHandler(
List<WriteHandler> handlerList) {
// sort
Map<Integer, List<WriteHandler>> orderExcelWriteHandlerMap = new TreeMap<Integer, List<WriteHandler>>();
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<Integer, List<WriteHandler>> 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<Class<? extends WriteHandler>, List<WriteHandler>> getOwnWriteHandlerMap() {
return ownWriteHandlerMap;
}
public void setOwnWriteHandlerMap(
Map<Class<? extends WriteHandler>, List<WriteHandler>> 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<Class<? extends WriteHandler>, List<WriteHandler>> ownWriteHandlerMap() {
return getOwnWriteHandlerMap();
}
@Override
public boolean needHead() {
return getNeedHead();

7
src/main/java/com/alibaba/excel/write/metadata/holder/WriteHolder.java

@ -28,6 +28,13 @@ public interface WriteHolder extends ConfigurationHolder {
*/
Map<Class<? extends WriteHandler>, List<WriteHandler>> writeHandlerMap();
/**
* create your own write handler.
*
* @return
*/
Map<Class<? extends WriteHandler>, List<WriteHandler>> ownWriteHandlerMap();
/**
* Is to determine if a field needs to be ignored
*

12
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
*

2
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<Object> list = EasyExcel.read(file).sheet().headRowNumber(0).doReadSync();
LOGGER.info("数据:{}", list.size());

42
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<HeadReadData> {
private static final Logger LOGGER = LoggerFactory.getLogger(HeadListener.class);
/**
* 每隔5条存储数据库实际使用中可以3000条然后清理list 方便内存回收
*/
private static final int BATCH_COUNT = 5;
@Override
public void invokeHeadMap(Map<Integer, String> 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("所有数据解析完成!");
}
}

5
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;
}

15
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();
}

27
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) {
}
}

27
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;
}

27
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;
}

22
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<List<String>> head() {
List<List<String>> list = new ArrayList<List<String>>();
List<String> head0 = new ArrayList<String>();

3
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;
}

21
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");
}
}

4
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);
}
}

12
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`会抛异常

Loading…
Cancel
Save