Browse Source

修改测试bug

2.1.x
Jiaju Zhuang 5 years ago
parent
commit
f99c198df7
  1. 3
      src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java
  2. 8
      src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java
  3. 6
      src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java
  4. 2
      src/main/java/com/alibaba/excel/analysis/v03/handlers/DummyRecordHandler.java
  5. 7
      src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java
  6. 19
      src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java
  7. 2
      src/main/java/com/alibaba/excel/read/builder/ExcelReaderBuilder.java
  8. 8
      src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java
  9. 59
      src/main/java/com/alibaba/excel/support/ExcelTypeEnum.java
  10. 149
      src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java
  11. 19
      src/main/java/com/alibaba/excel/write/metadata/fill/AnalysisCell.java
  12. 44
      src/main/java/com/alibaba/excel/write/metadata/fill/FillWrapper.java
  13. 10
      src/test/java/com/alibaba/easyexcel/test/core/dataformat/DateFormatTest.java
  14. 44
      src/test/java/com/alibaba/easyexcel/test/core/fill/FillDataTest.java
  15. 8
      src/test/java/com/alibaba/easyexcel/test/core/head/ListHeadDataListener.java
  16. 33
      src/test/java/com/alibaba/easyexcel/test/demo/fill/FillTest.java
  17. 22
      src/test/java/com/alibaba/easyexcel/test/temp/FillTempTest.java
  18. 15
      src/test/java/com/alibaba/easyexcel/test/temp/TempFillData.java
  19. 4
      src/test/java/com/alibaba/easyexcel/test/temp/read/CommentTest.java
  20. BIN
      src/test/resources/demo/fill/composite.xlsx
  21. BIN
      src/test/resources/fill/composite.xls
  22. BIN
      src/test/resources/fill/composite.xlsx
  23. 2
      update.md

3
src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java

@ -59,8 +59,7 @@ public class ExcelAnalyserImpl implements ExcelAnalyser {
}
private void choiceExcelExecutor(ReadWorkbook readWorkbook) throws Exception {
ExcelTypeEnum excelType =
ExcelTypeEnum.valueOf(readWorkbook.getFile(), readWorkbook.getInputStream(), readWorkbook.getExcelType());
ExcelTypeEnum excelType = ExcelTypeEnum.valueOf(readWorkbook);
switch (excelType) {
case XLS:
POIFSFileSystem poifsFileSystem;

8
src/main/java/com/alibaba/excel/analysis/v03/XlsSaxAnalyser.java

@ -56,6 +56,7 @@ import com.alibaba.excel.analysis.v03.handlers.StringRecordHandler;
import com.alibaba.excel.analysis.v03.handlers.TextObjectRecordHandler;
import com.alibaba.excel.context.xls.XlsReadContext;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.exception.ExcelAnalysisStopException;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.read.metadata.holder.xls.XlsReadWorkbookHolder;
@ -108,10 +109,15 @@ public class XlsSaxAnalyser implements HSSFListener, ExcelReadExecutor {
@Override
public List<ReadSheet> sheetList() {
try {
if (xlsReadContext.readWorkbookHolder().getActualSheetDataList() == null) {
LOGGER.warn("Getting the 'sheetList' before reading will cause the file to be read twice.");
new XlsListSheetListener(xlsReadContext).execute();
}
} catch (ExcelAnalysisStopException e) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Custom stop!");
}
}
return xlsReadContext.readWorkbookHolder().getActualSheetDataList();
}

6
src/main/java/com/alibaba/excel/analysis/v03/handlers/BofRecordHandler.java

@ -23,10 +23,14 @@ public class BofRecordHandler extends AbstractXlsRecordHandler {
@Override
public void processRecord(XlsReadContext xlsReadContext, Record record) {
BOFRecord br = (BOFRecord)record;
XlsReadWorkbookHolder xlsReadWorkbookHolder = xlsReadContext.xlsReadWorkbookHolder();
if (br.getType() == BOFRecord.TYPE_WORKBOOK) {
xlsReadWorkbookHolder.setReadSheetIndex(null);
return;
}
if (br.getType() != BOFRecord.TYPE_WORKSHEET) {
return;
}
XlsReadWorkbookHolder xlsReadWorkbookHolder = xlsReadContext.xlsReadWorkbookHolder();
// Init read sheet Data
initReadSheetDataList(xlsReadWorkbookHolder);
Integer readSheetIndex = xlsReadWorkbookHolder.getReadSheetIndex();

2
src/main/java/com/alibaba/excel/analysis/v03/handlers/DummyRecordHandler.java

@ -8,6 +8,7 @@ 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.metadata.CellData;
import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
@ -30,6 +31,7 @@ public class DummyRecordHandler extends AbstractXlsRecordHandler implements Igno
xlsReadContext.readSheetHolder().getGlobalConfiguration(), xlsReadSheetHolder.getCellMap()));
xlsReadContext.analysisEventProcessor().endRow(xlsReadContext);
xlsReadSheetHolder.setCellMap(new LinkedHashMap<Integer, Cell>());
xlsReadSheetHolder.setTempRowType(RowTypeEnum.EMPTY);
} else if (record instanceof MissingCellDummyRecord) {
MissingCellDummyRecord mcdr = (MissingCellDummyRecord)record;
xlsReadSheetHolder.getCellMap().put(mcdr.getColumn(),

7
src/main/java/com/alibaba/excel/analysis/v03/handlers/FormulaRecordHandler.java

@ -11,6 +11,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.excel.analysis.v03.IgnorableXlsRecordHandler;
import com.alibaba.excel.constant.BuiltinFormats;
import com.alibaba.excel.context.xls.XlsReadContext;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.Cell;
@ -52,6 +53,12 @@ public class FormulaRecordHandler extends AbstractXlsRecordHandler implements Ig
case NUMERIC:
tempCellData.setType(CellDataTypeEnum.NUMBER);
tempCellData.setNumberValue(BigDecimal.valueOf(frec.getValue()));
Integer dataFormat =
xlsReadContext.xlsReadWorkbookHolder().getFormatTrackingHSSFListener().getFormatIndex(frec);
tempCellData.setDataFormat(dataFormat);
tempCellData.setDataFormatString(BuiltinFormats.getBuiltinFormat(dataFormat,
xlsReadContext.xlsReadWorkbookHolder().getFormatTrackingHSSFListener().getFormatString(frec),
xlsReadContext.readSheetHolder().getGlobalConfiguration().getLocale()));
cellMap.put((int)frec.getColumn(), tempCellData);
break;
case ERROR:

19
src/main/java/com/alibaba/excel/analysis/v07/handlers/RowTagHandler.java

@ -20,14 +20,25 @@ public class RowTagHandler extends AbstractXlsxTagHandler {
@Override
public void startElement(XlsxReadContext xlsxReadContext, String name, Attributes attributes) {
xlsxReadContext.readRowHolder(
new ReadRowHolder(PositionUtils.getRowByRowTagt(attributes.getValue(ExcelXmlConstants.ATTRIBUTE_R)),
RowTypeEnum.DATA, xlsxReadContext.readSheetHolder().getGlobalConfiguration(), null));
int rowIndex = PositionUtils.getRowByRowTagt(attributes.getValue(ExcelXmlConstants.ATTRIBUTE_R));
Integer lastIndex = xlsxReadContext.readSheetHolder().getRowIndex();
if (lastIndex != null) {
while (lastIndex + 1 < rowIndex) {
xlsxReadContext.readRowHolder(new ReadRowHolder(lastIndex + 1, RowTypeEnum.EMPTY,
xlsxReadContext.readSheetHolder().getGlobalConfiguration(), new LinkedHashMap<Integer, Cell>()));
xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext);
xlsxReadContext.xlsxReadSheetHolder().setCellMap(new LinkedHashMap<Integer, Cell>());
lastIndex++;
}
}
xlsxReadContext.readSheetHolder().setRowIndex(rowIndex);
}
@Override
public void endElement(XlsxReadContext xlsxReadContext, String name) {
xlsxReadContext.readRowHolder().setCellMap(xlsxReadContext.xlsxReadSheetHolder().getCellMap());
xlsxReadContext.readRowHolder(new ReadRowHolder(xlsxReadContext.readSheetHolder().getRowIndex(),
RowTypeEnum.DATA, xlsxReadContext.readSheetHolder().getGlobalConfiguration(),
xlsxReadContext.xlsxReadSheetHolder().getCellMap()));
xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext);
xlsxReadContext.xlsxReadSheetHolder().setCellMap(new LinkedHashMap<Integer, Cell>());
}

2
src/main/java/com/alibaba/excel/read/builder/ExcelReaderBuilder.java

@ -205,9 +205,9 @@ public class ExcelReaderBuilder extends AbstractExcelReaderParameterBuilder<Exce
* @return
*/
public <T> List<T> doReadAllSync() {
ExcelReader excelReader = build();
SyncReadListener syncReadListener = new SyncReadListener();
registerReadListener(syncReadListener);
ExcelReader excelReader = build();
excelReader.readAll();
excelReader.finish();
return (List<T>)syncReadListener.getList();

8
src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java

@ -1,6 +1,5 @@
package com.alibaba.excel.read.metadata.holder;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.InputStream;
import java.util.HashSet;
@ -126,16 +125,9 @@ public class ReadWorkbookHolder extends AbstractReadHolder {
super(readWorkbook, null, readWorkbook.getConvertAllFiled());
this.readWorkbook = readWorkbook;
if (readWorkbook.getInputStream() != null) {
if (readWorkbook.getInputStream().markSupported()) {
this.inputStream = readWorkbook.getInputStream();
} else {
this.inputStream = new BufferedInputStream(readWorkbook.getInputStream());
}
}
this.file = readWorkbook.getFile();
if (file == null && inputStream == null) {
throw new ExcelAnalysisException("File and inputStream must be a non-null.");
}
if (readWorkbook.getMandatoryUseInputStream() == null) {
this.mandatoryUseInputStream = Boolean.FALSE;
} else {

59
src/main/java/com/alibaba/excel/support/ExcelTypeEnum.java

@ -3,12 +3,13 @@ package com.alibaba.excel.support;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.poi.poifs.filesystem.FileMagic;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.exception.ExcelCommonException;
import com.alibaba.excel.read.metadata.ReadWorkbook;
/**
* @author jipengfei
@ -29,45 +30,57 @@ public enum ExcelTypeEnum {
this.setValue(value);
}
public static ExcelTypeEnum valueOf(File file, InputStream inputStream, ExcelTypeEnum excelType) {
public static ExcelTypeEnum valueOf(ReadWorkbook readWorkbook) {
ExcelTypeEnum excelType = readWorkbook.getExcelType();
if (excelType != null) {
return excelType;
}
File file = readWorkbook.getFile();
InputStream inputStream = readWorkbook.getInputStream();
if (file == null && inputStream == null) {
throw new ExcelAnalysisException("File and inputStream must be a non-null.");
}
try {
FileMagic fileMagic;
if (file != null) {
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file));
try {
fileMagic = FileMagic.valueOf(bufferedInputStream);
} finally {
bufferedInputStream.close();
if (!file.exists()) {
throw new ExcelAnalysisException("File " + file.getAbsolutePath() + " not exists.");
}
if (!FileMagic.OLE2.equals(fileMagic) && !FileMagic.OOXML.equals(fileMagic)) {
String fileName = file.getName();
if (fileName.endsWith(XLSX.getValue())) {
return XLSX;
} else if (fileName.endsWith(XLS.getValue())) {
return XLS;
} else {
throw new ExcelCommonException("Unknown excel type.");
}
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file));
try {
return recognitionExcelType(bufferedInputStream);
} finally {
bufferedInputStream.close();
}
}
} else {
fileMagic = FileMagic.valueOf(inputStream);
if (!inputStream.markSupported()) {
inputStream = new BufferedInputStream(inputStream);
readWorkbook.setInputStream(inputStream);
}
return recognitionExcelType(inputStream);
} catch (ExcelCommonException e) {
throw e;
} catch (ExcelAnalysisException e) {
throw e;
} catch (Exception e) {
throw new ExcelCommonException(
"Convert excel format exception.You can try specifying the 'excelType' yourself", e);
}
}
private static ExcelTypeEnum recognitionExcelType(InputStream inputStream) throws Exception {
FileMagic fileMagic = FileMagic.valueOf(inputStream);
if (FileMagic.OLE2.equals(fileMagic)) {
return XLS;
}
if (FileMagic.OOXML.equals(fileMagic)) {
return XLSX;
}
} catch (IOException e) {
if (excelType != null) {
return excelType;
}
throw new ExcelCommonException(
"Convert excel format exception.You can try specifying the 'excelType' yourself", e);
}
if (excelType != null) {
return excelType;
}
throw new ExcelCommonException(
"Convert excel format exception.You can try specifying the 'excelType' yourself");
}

149
src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java

@ -27,6 +27,7 @@ import com.alibaba.excel.util.StringUtils;
import com.alibaba.excel.util.WriteHandlerUtils;
import com.alibaba.excel.write.metadata.fill.AnalysisCell;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import net.sf.cglib.beans.BeanMap;
@ -47,28 +48,36 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
/**
* Fields to replace in the template
*/
private Map<Integer, List<AnalysisCell>> templateAnalysisCache = new HashMap<Integer, List<AnalysisCell>>(8);
private Map<String, List<AnalysisCell>> templateAnalysisCache = new HashMap<String, List<AnalysisCell>>(8);
/**
* Collection fields to replace in the template
*/
private Map<Integer, List<AnalysisCell>> templateCollectionAnalysisCache =
new HashMap<Integer, List<AnalysisCell>>(8);
private Map<String, List<AnalysisCell>> templateCollectionAnalysisCache =
new HashMap<String, List<AnalysisCell>>(8);
/**
* Style cache for collection fields
*/
private Map<Integer, Map<AnalysisCell, CellStyle>> collectionFieldStyleCache =
new HashMap<Integer, Map<AnalysisCell, CellStyle>>(8);
private Map<String, Map<AnalysisCell, CellStyle>> collectionFieldStyleCache =
new HashMap<String, Map<AnalysisCell, CellStyle>>(8);
/**
* Row height cache for collection
*/
private Map<Integer, Short> collectionRowHeightCache = new HashMap<Integer, Short>(8);
private Map<String, Short> collectionRowHeightCache = new HashMap<String, Short>(8);
/**
* Last index cache for collection fields
*/
private Map<Integer, Map<AnalysisCell, Integer>> collectionLastIndexCache =
new HashMap<Integer, Map<AnalysisCell, Integer>>(8);
private Map<String, Map<AnalysisCell, Integer>> collectionLastIndexCache =
new HashMap<String, Map<AnalysisCell, Integer>>(8);
private Map<Integer, Integer> relativeRowIndexMap = new HashMap<Integer, Integer>(8);
private Map<String, Integer> relativeRowIndexMap = new HashMap<String, Integer>(8);
/**
* The data prefix that is populated this time
*/
private String currentDataPrefix;
/**
* The unique data encoding for this fill
*/
private String currentUniqueDataFlag;
public ExcelWriteFillExecutor(WriteContext writeContext) {
super(writeContext);
@ -79,9 +88,22 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
fillConfig = FillConfig.builder().build(true);
}
fillConfig.init();
if (data instanceof Collection) {
Object realData;
if (data instanceof FillWrapper) {
FillWrapper fillWrapper = (FillWrapper)data;
currentDataPrefix = fillWrapper.getName();
realData = fillWrapper.getCollectionData();
} else {
realData = data;
currentDataPrefix = null;
}
currentUniqueDataFlag = uniqueDataFlag(writeContext.writeSheetHolder().getSheetNo(), currentDataPrefix);
// processing data
if (realData instanceof Collection) {
List<AnalysisCell> analysisCellList = readTemplateData(templateCollectionAnalysisCache);
Collection collectionData = (Collection)data;
Collection collectionData = (Collection)realData;
if (CollectionUtils.isEmpty(collectionData)) {
return;
}
@ -93,7 +115,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
doFill(analysisCellList, iterator.next(), fillConfig, getRelativeRowIndex());
}
} else {
doFill(readTemplateData(templateAnalysisCache), data, fillConfig, null);
doFill(readTemplateData(templateAnalysisCache), realData, fillConfig, null);
}
}
@ -102,8 +124,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
return;
}
int maxRowIndex = 0;
Integer sheetNo = writeContext.writeSheetHolder().getSheetNo();
Map<AnalysisCell, Integer> collectionLastIndexMap = collectionLastIndexCache.get(sheetNo);
Map<AnalysisCell, Integer> collectionLastIndexMap = collectionLastIndexCache.get(currentUniqueDataFlag);
for (AnalysisCell analysisCell : analysisCellList) {
if (collectionLastIndexMap != null) {
Integer lastRowIndex = collectionLastIndexMap.get(analysisCell);
@ -132,7 +153,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
return;
}
sheet.shiftRows(maxRowIndex + 1, lastRowIndex, number, true, false);
for (AnalysisCell analysisCell : templateAnalysisCache.get(writeContext.writeSheetHolder().getSheetNo())) {
for (AnalysisCell analysisCell : templateAnalysisCache.get(currentUniqueDataFlag)) {
if (analysisCell.getRowIndex() > maxRowIndex) {
analysisCell.setRowIndex(analysisCell.getRowIndex() + number);
}
@ -206,14 +227,13 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
}
private Integer getRelativeRowIndex() {
Integer sheetNo = writeContext.writeSheetHolder().getSheetNo();
Integer relativeRowIndex = relativeRowIndexMap.get(sheetNo);
Integer relativeRowIndex = relativeRowIndexMap.get(currentUniqueDataFlag);
if (relativeRowIndex == null) {
relativeRowIndex = 0;
} else {
relativeRowIndex++;
}
relativeRowIndexMap.put(sheetNo, relativeRowIndex);
relativeRowIndexMap.put(currentUniqueDataFlag, relativeRowIndex);
return relativeRowIndex;
}
@ -222,13 +242,12 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
if (WriteTemplateAnalysisCellTypeEnum.COMMON.equals(analysisCell.getCellType())) {
return cachedSheet.getRow(analysisCell.getRowIndex()).getCell(analysisCell.getColumnIndex());
}
Integer sheetNo = writeContext.writeSheetHolder().getSheetNo();
Sheet sheet = writeContext.writeSheetHolder().getSheet();
Map<AnalysisCell, Integer> collectionLastIndexMap = collectionLastIndexCache.get(sheetNo);
Map<AnalysisCell, Integer> collectionLastIndexMap = collectionLastIndexCache.get(currentUniqueDataFlag);
if (collectionLastIndexMap == null) {
collectionLastIndexMap = new HashMap<AnalysisCell, Integer>(16);
collectionLastIndexCache.put(sheetNo, collectionLastIndexMap);
collectionLastIndexCache.put(currentUniqueDataFlag, collectionLastIndexMap);
}
boolean isOriginalCell = false;
Integer lastRowIndex;
@ -269,10 +288,10 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
} else {
row = sheet.createRow(lastRowIndex);
}
checkRowHeight(analysisCell, fillConfig, isOriginalCell, row, sheetNo);
checkRowHeight(analysisCell, fillConfig, isOriginalCell, row);
WriteHandlerUtils.afterRowCreate(writeContext, row, null, Boolean.FALSE);
} else {
checkRowHeight(analysisCell, fillConfig, isOriginalCell, row, sheetNo);
checkRowHeight(analysisCell, fillConfig, isOriginalCell, row);
}
}
Cell cell = row.getCell(lastColumnIndex);
@ -282,10 +301,10 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
WriteHandlerUtils.afterCellCreate(writeContext, cell, null, null, Boolean.FALSE);
}
Map<AnalysisCell, CellStyle> collectionFieldStyleMap = collectionFieldStyleCache.get(sheetNo);
Map<AnalysisCell, CellStyle> collectionFieldStyleMap = collectionFieldStyleCache.get(currentUniqueDataFlag);
if (collectionFieldStyleMap == null) {
collectionFieldStyleMap = new HashMap<AnalysisCell, CellStyle>(16);
collectionFieldStyleCache.put(sheetNo, collectionFieldStyleMap);
collectionFieldStyleCache.put(currentUniqueDataFlag, collectionFieldStyleMap);
}
if (isOriginalCell) {
collectionFieldStyleMap.put(analysisCell, cell.getCellStyle());
@ -298,31 +317,27 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
return cell;
}
private void checkRowHeight(AnalysisCell analysisCell, FillConfig fillConfig, boolean isOriginalCell, Row row,
Integer sheetNo) {
if (!analysisCell.getFirstColumn() || !WriteDirectionEnum.VERTICAL.equals(fillConfig.getDirection())) {
private void checkRowHeight(AnalysisCell analysisCell, FillConfig fillConfig, boolean isOriginalCell, Row row) {
if (!analysisCell.getFirstRow() || !WriteDirectionEnum.VERTICAL.equals(fillConfig.getDirection())) {
return;
}
if (isOriginalCell) {
collectionRowHeightCache.put(sheetNo, row.getHeight());
collectionRowHeightCache.put(currentUniqueDataFlag, row.getHeight());
return;
}
Short rowHeight = collectionRowHeightCache.get(sheetNo);
Short rowHeight = collectionRowHeightCache.get(currentUniqueDataFlag);
if (rowHeight != null) {
row.setHeight(rowHeight);
}
}
private List<AnalysisCell> readTemplateData(Map<Integer, List<AnalysisCell>> analysisCache) {
Integer sheetNo = writeContext.writeSheetHolder().getSheetNo();
List<AnalysisCell> analysisCellList = analysisCache.get(sheetNo);
private List<AnalysisCell> readTemplateData(Map<String, List<AnalysisCell>> analysisCache) {
List<AnalysisCell> analysisCellList = analysisCache.get(currentUniqueDataFlag);
if (analysisCellList != null) {
return analysisCellList;
}
Sheet sheet = writeContext.writeSheetHolder().getCachedSheet();
analysisCellList = new ArrayList<AnalysisCell>();
List<AnalysisCell> collectionAnalysisCellList = new ArrayList<AnalysisCell>();
Set<Integer> firstColumnCache = new HashSet<Integer>();
Map<String, Set<Integer>> firstRowCache = new HashMap<String, Set<Integer>>(8);
for (int i = 0; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
if (row == null) {
@ -333,32 +348,26 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
if (cell == null) {
continue;
}
String preparedData =
prepareData(cell, analysisCellList, collectionAnalysisCellList, i, j, firstColumnCache);
String preparedData = prepareData(cell, i, j, firstRowCache);
// Prevent empty data from not being replaced
if (preparedData != null) {
cell.setCellValue(preparedData);
}
}
}
templateAnalysisCache.put(sheetNo, analysisCellList);
templateCollectionAnalysisCache.put(sheetNo, collectionAnalysisCellList);
return analysisCache.get(sheetNo);
return analysisCache.get(currentUniqueDataFlag);
}
/**
* To prepare data
*
* @param cell
* @param analysisCellList
* @param collectionAnalysisCellList
* @param rowIndex
* @param columnIndex
* @param firstColumnCache
* @param firstRowCache
* @return Returns the data that the cell needs to replace
*/
private String prepareData(Cell cell, List<AnalysisCell> analysisCellList,
List<AnalysisCell> collectionAnalysisCellList, int rowIndex, int columnIndex, Set<Integer> firstColumnCache) {
private String prepareData(Cell cell, int rowIndex, int columnIndex, Map<String, Set<Integer>> firstRowCache) {
if (!CellType.STRING.equals(cell.getCellTypeEnum())) {
return null;
}
@ -404,8 +413,12 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
if (StringUtils.isEmpty(variable)) {
continue;
}
if (variable.startsWith(COLLECTION_PREFIX)) {
variable = variable.substring(1);
int collectPrefixIndex = variable.indexOf(COLLECTION_PREFIX);
if (collectPrefixIndex > -1) {
if (collectPrefixIndex != 0) {
analysisCell.setPrefix(variable.substring(0, collectPrefixIndex));
}
variable = variable.substring(collectPrefixIndex + 1);
if (StringUtils.isEmpty(variable)) {
continue;
}
@ -422,13 +435,13 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
}
lastPrepareDataIndex = suffixIndex + 1;
}
return dealAnalysisCell(analysisCell, value, rowIndex, lastPrepareDataIndex, length, analysisCellList,
collectionAnalysisCellList, firstColumnCache, preparedData);
return dealAnalysisCell(analysisCell, value, rowIndex, lastPrepareDataIndex, length, firstRowCache,
preparedData);
}
private String dealAnalysisCell(AnalysisCell analysisCell, String value, int rowIndex, int lastPrepareDataIndex,
int length, List<AnalysisCell> analysisCellList, List<AnalysisCell> collectionAnalysisCellList,
Set<Integer> firstColumnCache, StringBuilder preparedData) {
int length, Map<String, Set<Integer>> firstRowCache, StringBuilder preparedData) {
Integer sheetNo = writeContext.writeSheetHolder().getSheetNo();
if (analysisCell != null) {
if (lastPrepareDataIndex == length) {
analysisCell.getPrepareDataList().add(StringUtils.EMPTY);
@ -436,12 +449,29 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
analysisCell.getPrepareDataList().add(convertPrepareData(value.substring(lastPrepareDataIndex)));
analysisCell.setOnlyOneVariable(Boolean.FALSE);
}
String uniqueDataFlag = uniqueDataFlag(sheetNo, analysisCell.getPrefix());
if (WriteTemplateAnalysisCellTypeEnum.COMMON.equals(analysisCell.getCellType())) {
List<AnalysisCell> analysisCellList = templateAnalysisCache.get(uniqueDataFlag);
if (analysisCellList == null) {
analysisCellList = new ArrayList<AnalysisCell>();
templateAnalysisCache.put(uniqueDataFlag, analysisCellList);
}
analysisCellList.add(analysisCell);
} else {
if (!firstColumnCache.contains(rowIndex)) {
analysisCell.setFirstColumn(Boolean.TRUE);
firstColumnCache.add(rowIndex);
Set<Integer> uniqueFirstRowCache = firstRowCache.get(uniqueDataFlag);
if (uniqueFirstRowCache == null) {
uniqueFirstRowCache = new HashSet<Integer>();
firstRowCache.put(uniqueDataFlag, uniqueFirstRowCache);
}
if (!uniqueFirstRowCache.contains(rowIndex)) {
analysisCell.setFirstRow(Boolean.TRUE);
uniqueFirstRowCache.add(rowIndex);
}
List<AnalysisCell> collectionAnalysisCellList = templateCollectionAnalysisCache.get(uniqueDataFlag);
if (collectionAnalysisCellList == null) {
collectionAnalysisCellList = new ArrayList<AnalysisCell>();
templateCollectionAnalysisCache.put(uniqueDataFlag, collectionAnalysisCellList);
}
collectionAnalysisCellList.add(analysisCell);
}
@ -460,7 +490,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
List<String> prepareDataList = new ArrayList<String>();
analysisCell.setPrepareDataList(prepareDataList);
analysisCell.setCellType(WriteTemplateAnalysisCellTypeEnum.COMMON);
analysisCell.setFirstColumn(Boolean.FALSE);
analysisCell.setFirstRow(Boolean.FALSE);
return analysisCell;
}
@ -470,4 +500,11 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
return prepareData;
}
private String uniqueDataFlag(Integer sheetNo, String wrapperName) {
if (StringUtils.isEmpty(wrapperName)) {
return sheetNo.toString() + "-";
}
return sheetNo + "-" + wrapperName;
}
}

19
src/main/java/com/alibaba/excel/write/metadata/fill/AnalysisCell.java

@ -16,7 +16,8 @@ public class AnalysisCell {
private List<String> prepareDataList;
private Boolean onlyOneVariable;
private WriteTemplateAnalysisCellTypeEnum cellType;
private Boolean firstColumn;
private String prefix;
private Boolean firstRow;
public int getColumnIndex() {
return columnIndex;
@ -58,6 +59,14 @@ public class AnalysisCell {
this.onlyOneVariable = onlyOneVariable;
}
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public WriteTemplateAnalysisCellTypeEnum getCellType() {
return cellType;
}
@ -66,12 +75,12 @@ public class AnalysisCell {
this.cellType = cellType;
}
public Boolean getFirstColumn() {
return firstColumn;
public Boolean getFirstRow() {
return firstRow;
}
public void setFirstColumn(Boolean firstColumn) {
this.firstColumn = firstColumn;
public void setFirstRow(Boolean firstRow) {
this.firstRow = firstRow;
}
@Override

44
src/main/java/com/alibaba/excel/write/metadata/fill/FillWrapper.java

@ -0,0 +1,44 @@
package com.alibaba.excel.write.metadata.fill;
import java.util.Collection;
/**
* Multiple lists are supported when packing
*
* @author Jiaju Zhuang
**/
public class FillWrapper {
/**
* The collection prefix that needs to be filled.
*/
private String name;
/**
* Data that needs to be filled.
*/
private Collection collectionData;
public FillWrapper(Collection collectionData) {
this.collectionData = collectionData;
}
public FillWrapper(String name, Collection collectionData) {
this.name = name;
this.collectionData = collectionData;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Collection getCollectionData() {
return collectionData;
}
public void setCollectionData(Collection collectionData) {
this.collectionData = collectionData;
}
}

10
src/test/java/com/alibaba/easyexcel/test/core/dataformat/DateFormatTest.java

@ -12,6 +12,7 @@ import org.slf4j.LoggerFactory;
import com.alibaba.easyexcel.test.util.TestFileUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
/**
*
@ -44,9 +45,10 @@ public class DateFormatTest {
private void readCn(File file) {
List<DateFormatData> list =
EasyExcel.read(file, DateFormatData.class, null).locale(Locale.CHINA).sheet().doReadSync();
System.out.println(JSON.toJSONString(list));
for (DateFormatData data : list) {
Assert.assertEquals(data.getDate(), data.getDateStringCn());
Assert.assertEquals(data.getNumber(), data.getNumberStringCn());
Assert.assertEquals(data.getDateStringCn(), data.getDate());
Assert.assertEquals(data.getNumberStringCn(), data.getNumber());
}
}
@ -54,8 +56,8 @@ public class DateFormatTest {
List<DateFormatData> list =
EasyExcel.read(file, DateFormatData.class, null).locale(Locale.US).sheet().doReadSync();
for (DateFormatData data : list) {
Assert.assertEquals(data.getDate(), data.getDateStringUs());
Assert.assertEquals(data.getNumber(), data.getNumberStringUs());
Assert.assertEquals(data.getDateStringUs(), data.getDate());
Assert.assertEquals(data.getNumberStringUs(), data.getNumber());
}
}
}

44
src/test/java/com/alibaba/easyexcel/test/core/fill/FillDataTest.java

@ -19,6 +19,7 @@ import com.alibaba.excel.enums.WriteDirectionEnum;
import com.alibaba.excel.write.merge.LoopMergeStrategy;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
/**
*
@ -39,6 +40,10 @@ public class FillDataTest {
private static File horizontalFillTemplate07;
private static File fileHorizontal03;
private static File horizontalFillTemplate03;
private static File fileComposite07;
private static File compositeFillTemplate07;
private static File fileComposite03;
private static File compositeFillTemplate03;
@BeforeClass
public static void init() {
@ -54,6 +59,10 @@ public class FillDataTest {
horizontalFillTemplate07 = TestFileUtil.readFile("fill" + File.separator + "horizontal.xlsx");
fileHorizontal03 = TestFileUtil.createNewFile("fillHorizontal03.xls");
horizontalFillTemplate03 = TestFileUtil.readFile("fill" + File.separator + "horizontal.xls");
fileComposite07 = TestFileUtil.createNewFile("fileComposite07.xlsx");
compositeFillTemplate07 = TestFileUtil.readFile("fill" + File.separator + "composite.xlsx");
fileComposite03 = TestFileUtil.createNewFile("fileComposite03.xls");
compositeFillTemplate03 = TestFileUtil.readFile("fill" + File.separator + "composite.xls");
}
@Test
@ -86,6 +95,41 @@ public class FillDataTest {
horizontalFill(fileHorizontal03, horizontalFillTemplate03);
}
@Test
public void t07CompositeFill07() {
compositeFill(fileComposite07, compositeFillTemplate07);
}
@Test
public void t08CompositeFill03() {
compositeFill(fileComposite03, compositeFillTemplate03);
}
private void compositeFill(File file, File template) {
ExcelWriter excelWriter = EasyExcel.write(file).withTemplate(template).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build();
excelWriter.fill(new FillWrapper("data1", data()), fillConfig, writeSheet);
excelWriter.fill(new FillWrapper("data1", data()), fillConfig, writeSheet);
excelWriter.fill(new FillWrapper("data2", data()), writeSheet);
excelWriter.fill(new FillWrapper("data2", data()), writeSheet);
excelWriter.fill(new FillWrapper("data3", data()), writeSheet);
excelWriter.fill(new FillWrapper("data3", data()), writeSheet);
Map<String, Object> map = new HashMap<String, Object>();
map.put("date", "2019年10月9日13:28:28");
excelWriter.fill(map, writeSheet);
excelWriter.finish();
List<Object> list = EasyExcel.read(file).ignoreEmptyRow(false).sheet().headRowNumber(0).doReadSync();
Map<String, String> map0 = (Map<String, String>)list.get(0);
Assert.assertEquals("张三", map0.get(21));
Map<String, String> map27 = (Map<String, String>)list.get(27);
Assert.assertEquals("张三", map27.get(0));
Map<String, String> map29 = (Map<String, String>)list.get(29);
Assert.assertEquals("张三", map29.get(3));
}
private void horizontalFill(File file, File template) {
ExcelWriter excelWriter = EasyExcel.write(file).withTemplate(template).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();

8
src/test/java/com/alibaba/easyexcel/test/core/head/ListHeadDataListener.java

@ -29,10 +29,10 @@ public class ListHeadDataListener extends AnalysisEventListener<Map<Integer, Str
public void doAfterAllAnalysed(AnalysisContext context) {
Assert.assertEquals(list.size(), 1);
Map<Integer, String> data = list.get(0);
Assert.assertEquals(data.get(0), "字符串0");
Assert.assertEquals(data.get(1), "1.0");
Assert.assertEquals(data.get(2), "2020-01-01 01:01:01");
Assert.assertEquals(data.get(3), "额外数据");
Assert.assertEquals("字符串0", data.get(0));
Assert.assertEquals("1", data.get(1));
Assert.assertEquals("2020-01-01 01:01:01", data.get(2));
Assert.assertEquals("额外数据", data.get(3));
LOGGER.debug("First row:{}", JSON.toJSONString(list.get(0)));
}
}

33
src/test/java/com/alibaba/easyexcel/test/demo/fill/FillTest.java

@ -15,6 +15,7 @@ import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.enums.WriteDirectionEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
/**
* 写的填充写法
@ -179,6 +180,38 @@ public class FillTest {
excelWriter.finish();
}
/**
* 组合填充填充
*
* @since 2.2.0
*/
@Test
public void compositeFill() {
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
// {} 代表普通变量 {.} 代表是list的变量 {前缀.} 前缀可以区分不同的list
String templateFileName =
TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "composite.xlsx";
String fileName = TestFileUtil.getPath() + "compositeFill" + System.currentTimeMillis() + ".xlsx";
ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build();
// 如果有多个list 模板上必须有{前缀.} 这里的前缀就是 data1,然后多个list必须用 FillWrapper包裹
excelWriter.fill(new FillWrapper("data1", data()), fillConfig, writeSheet);
excelWriter.fill(new FillWrapper("data1", data()), fillConfig, writeSheet);
excelWriter.fill(new FillWrapper("data2", data()), writeSheet);
excelWriter.fill(new FillWrapper("data2", data()), writeSheet);
excelWriter.fill(new FillWrapper("data3", data()), writeSheet);
excelWriter.fill(new FillWrapper("data3", data()), writeSheet);
Map<String, Object> map = new HashMap<String, Object>();
map.put("date", "2019年10月9日13:28:28");
excelWriter.fill(map, writeSheet);
// 别忘记关闭流
excelWriter.finish();
}
private List<FillData> data() {
List<FillData> list = new ArrayList<FillData>();
for (int i = 0; i < 10; i++) {

22
src/test/java/com/alibaba/easyexcel/test/temp/FillTempTest.java

@ -14,7 +14,6 @@ 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.fill.FillConfig;
/**
* 写的填充写法
@ -34,18 +33,12 @@ public class FillTempTest {
public void complexFill() {
// 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替
// {} 代表普通变量 {.} 代表是list的变量
String templateFileName = "D:\\test\\complex.xlsx";
String templateFileName = "D:\\test\\simple.xlsx";
String fileName = TestFileUtil.getPath() + "complexFill" + System.currentTimeMillis() + ".xlsx";
ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
// 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行,然后下面的数据往后移动。默认 是false,会直接使用下一行,如果没有则创建。
// forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了,所以慎用
// 简单的说 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
// 如果数据量大 list不是最后一行 参照下一个
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
excelWriter.fill(data(), fillConfig, writeSheet);
// excelWriter.fill(data2(), fillConfig, writeSheet);
excelWriter.fill(teamp(), writeSheet);
Map<String, Object> map = new HashMap<String, Object>();
map.put("date", "2019年10月9日13:28:28");
map.put("total", 1000);
@ -106,6 +99,17 @@ public class FillTempTest {
return list;
}
private List<TempFillData> teamp() {
List<TempFillData> list = new ArrayList<TempFillData>();
for (int i = 0; i < 10; i++) {
TempFillData fillData = new TempFillData();
list.add(fillData);
fillData.setName("张三");
fillData.setNumber(5.2);
}
return list;
}
private List<FillData> data() {
List<FillData> list = new ArrayList<FillData>();
for (int i = 0; i < 10; i++) {

15
src/test/java/com/alibaba/easyexcel/test/temp/TempFillData.java

@ -0,0 +1,15 @@
package com.alibaba.easyexcel.test.temp;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import lombok.Data;
/**
* @author Jiaju Zhuang
*/
@Data
@ContentRowHeight(30)
public class TempFillData {
private String name;
private double number;
}

4
src/test/java/com/alibaba/easyexcel/test/temp/read/CommentTest.java

@ -24,10 +24,10 @@ public class CommentTest {
@Test
public void comment() throws Exception {
File file = new File("D:\\test\\comment.xls");
File file = new File("D:\\test\\listHead07.xlsx");
List<Map<Integer, CellData>> datas = EasyExcel.read(file).doReadAllSync();
for (Map<Integer, CellData> data : datas) {
LOGGER.info("数据:{}", JSON.toJSONString(data.get(0)));
LOGGER.info("数据:{}", JSON.toJSONString(data));
}
}

BIN
src/test/resources/demo/fill/composite.xlsx

Binary file not shown.

BIN
src/test/resources/fill/composite.xls

Binary file not shown.

BIN
src/test/resources/fill/composite.xlsx

Binary file not shown.

2
update.md

@ -13,7 +13,7 @@
* 兼容部分比较特殊的excel
* 同时传入了`List<List<String>>`和`class`的head,会通过index去匹配注解
* 修复读取转换器的并发问题
*
* 填充支持多个List对象
# 2.1.4
* 新增参数`useDefaultListener` 可以排除默认对象转换

Loading…
Cancel
Save