Browse Source

* `fill`的情况新增 `afterRowDispose`事件

pull/2177/head
Jiaju Zhuang 3 years ago
parent
commit
fc59b8601f
  1. 2
      src/main/java/com/alibaba/excel/annotation/write/style/ContentLoopMerge.java
  2. 28
      src/main/java/com/alibaba/excel/write/executor/ExcelWriteFillExecutor.java
  3. 6
      src/main/java/com/alibaba/excel/write/handler/RowWriteHandler.java
  4. 21
      src/main/java/com/alibaba/excel/write/merge/LoopMergeStrategy.java
  5. 36
      src/test/java/com/alibaba/easyexcel/test/core/fill/annotation/FillAnnotationData.java
  6. 92
      src/test/java/com/alibaba/easyexcel/test/core/fill/annotation/FillAnnotationDataTest.java
  7. 47
      src/test/java/com/alibaba/easyexcel/test/temp/large/TempLargeDataTest.java
  8. BIN
      src/test/resources/fill/annotation.xls
  9. BIN
      src/test/resources/fill/annotation.xlsx
  10. 1
      update.md

2
src/main/java/com/alibaba/excel/annotation/write/style/ContentLoopMerge.java

@ -20,7 +20,7 @@ public @interface ContentLoopMerge {
* *
* @return * @return
*/ */
int eachRow() default -1; int eachRow() default 1;
/** /**
* Extend column * Extend column

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

@ -200,6 +200,9 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
} }
Set<String> dataKeySet = new HashSet<>(dataMap.keySet()); Set<String> dataKeySet = new HashSet<>(dataMap.keySet());
RowWriteHandlerContext rowWriteHandlerContext = WriteHandlerUtils.createRowWriteHandlerContext(writeContext,
null, relativeRowIndex, Boolean.FALSE);
for (AnalysisCell analysisCell : analysisCellList) { for (AnalysisCell analysisCell : analysisCellList) {
CellWriteHandlerContext cellWriteHandlerContext = WriteHandlerUtils.createCellWriteHandlerContext( CellWriteHandlerContext cellWriteHandlerContext = WriteHandlerUtils.createCellWriteHandlerContext(
writeContext, null, analysisCell.getRowIndex(), null, analysisCell.getColumnIndex(), writeContext, null, analysisCell.getRowIndex(), null, analysisCell.getColumnIndex(),
@ -215,7 +218,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadClazz(), variable); writeContext.currentWriteHolder().excelWriteHeadProperty().getHeadClazz(), variable);
cellWriteHandlerContext.setExcelContentProperty(excelContentProperty); cellWriteHandlerContext.setExcelContentProperty(excelContentProperty);
createCell(analysisCell, fillConfig, cellWriteHandlerContext); createCell(analysisCell, fillConfig, cellWriteHandlerContext, rowWriteHandlerContext);
cellWriteHandlerContext.setOriginalValue(value); cellWriteHandlerContext.setOriginalValue(value);
cellWriteHandlerContext.setOriginalFieldClass(FieldUtils.getFieldClass(dataMap, variable, value)); cellWriteHandlerContext.setOriginalFieldClass(FieldUtils.getFieldClass(dataMap, variable, value));
@ -236,7 +239,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
cellWriteHandlerContext.setExcelContentProperty(ExcelContentProperty.EMPTY); cellWriteHandlerContext.setExcelContentProperty(ExcelContentProperty.EMPTY);
cellWriteHandlerContext.setIgnoreFillStyle(Boolean.TRUE); cellWriteHandlerContext.setIgnoreFillStyle(Boolean.TRUE);
createCell(analysisCell, fillConfig, cellWriteHandlerContext); createCell(analysisCell, fillConfig, cellWriteHandlerContext, rowWriteHandlerContext);
Cell cell = cellWriteHandlerContext.getCell(); Cell cell = cellWriteHandlerContext.getCell();
for (String variable : analysisCell.getVariableList()) { for (String variable : analysisCell.getVariableList()) {
@ -288,6 +291,11 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
} }
WriteHandlerUtils.afterCellDispose(cellWriteHandlerContext); WriteHandlerUtils.afterCellDispose(cellWriteHandlerContext);
} }
// In the case of the fill line may be called many times
if (rowWriteHandlerContext.getRow() != null) {
WriteHandlerUtils.afterRowDispose(rowWriteHandlerContext);
}
} }
private Integer getRelativeRowIndex() { private Integer getRelativeRowIndex() {
@ -302,13 +310,16 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
} }
private void createCell(AnalysisCell analysisCell, FillConfig fillConfig, private void createCell(AnalysisCell analysisCell, FillConfig fillConfig,
CellWriteHandlerContext cellWriteHandlerContext) { CellWriteHandlerContext cellWriteHandlerContext, RowWriteHandlerContext rowWriteHandlerContext) {
Sheet cachedSheet = writeContext.writeSheetHolder().getCachedSheet(); Sheet cachedSheet = writeContext.writeSheetHolder().getCachedSheet();
if (WriteTemplateAnalysisCellTypeEnum.COMMON.equals(analysisCell.getCellType())) { if (WriteTemplateAnalysisCellTypeEnum.COMMON.equals(analysisCell.getCellType())) {
Row row = cachedSheet.getRow(analysisCell.getRowIndex()); Row row = cachedSheet.getRow(analysisCell.getRowIndex());
cellWriteHandlerContext.setRow(row); cellWriteHandlerContext.setRow(row);
Cell cell = row.getCell(analysisCell.getColumnIndex()); Cell cell = row.getCell(analysisCell.getColumnIndex());
cellWriteHandlerContext.setCell(cell); cellWriteHandlerContext.setCell(cell);
rowWriteHandlerContext.setRow(row);
rowWriteHandlerContext.setRowIndex(analysisCell.getRowIndex());
return;
} }
Sheet sheet = writeContext.writeSheetHolder().getSheet(); Sheet sheet = writeContext.writeSheetHolder().getSheet();
@ -345,7 +356,8 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
throw new ExcelGenerateException("The wrong direction."); throw new ExcelGenerateException("The wrong direction.");
} }
Row row = createRowIfNecessary(sheet, cachedSheet, lastRowIndex, fillConfig, analysisCell, isOriginalCell); Row row = createRowIfNecessary(sheet, cachedSheet, lastRowIndex, fillConfig, analysisCell, isOriginalCell,
rowWriteHandlerContext);
cellWriteHandlerContext.setRow(row); cellWriteHandlerContext.setRow(row);
cellWriteHandlerContext.setRowIndex(lastRowIndex); cellWriteHandlerContext.setRowIndex(lastRowIndex);
@ -375,16 +387,17 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
} }
private Row createRowIfNecessary(Sheet sheet, Sheet cachedSheet, Integer lastRowIndex, FillConfig fillConfig, private Row createRowIfNecessary(Sheet sheet, Sheet cachedSheet, Integer lastRowIndex, FillConfig fillConfig,
AnalysisCell analysisCell, boolean isOriginalCell) { AnalysisCell analysisCell, boolean isOriginalCell, RowWriteHandlerContext rowWriteHandlerContext) {
rowWriteHandlerContext.setRowIndex(lastRowIndex);
Row row = sheet.getRow(lastRowIndex); Row row = sheet.getRow(lastRowIndex);
if (row != null) { if (row != null) {
checkRowHeight(analysisCell, fillConfig, isOriginalCell, row); checkRowHeight(analysisCell, fillConfig, isOriginalCell, row);
rowWriteHandlerContext.setRow(row);
return row; return row;
} }
row = cachedSheet.getRow(lastRowIndex); row = cachedSheet.getRow(lastRowIndex);
if (row == null) { if (row == null) {
RowWriteHandlerContext rowWriteHandlerContext = WriteHandlerUtils.createRowWriteHandlerContext(writeContext, rowWriteHandlerContext.setRowIndex(lastRowIndex);
lastRowIndex, null, Boolean.FALSE);
WriteHandlerUtils.beforeRowCreate(rowWriteHandlerContext); WriteHandlerUtils.beforeRowCreate(rowWriteHandlerContext);
if (fillConfig.getForceNewRow()) { if (fillConfig.getForceNewRow()) {
@ -405,6 +418,7 @@ public class ExcelWriteFillExecutor extends AbstractExcelWriteExecutor {
WriteHandlerUtils.afterRowCreate(rowWriteHandlerContext); WriteHandlerUtils.afterRowCreate(rowWriteHandlerContext);
} else { } else {
checkRowHeight(analysisCell, fillConfig, isOriginalCell, row); checkRowHeight(analysisCell, fillConfig, isOriginalCell, row);
rowWriteHandlerContext.setRow(row);
} }
return row; return row;
} }

6
src/main/java/com/alibaba/excel/write/handler/RowWriteHandler.java

@ -58,7 +58,8 @@ public interface RowWriteHandler extends WriteHandler {
Integer relativeRowIndex, Boolean isHead) {} Integer relativeRowIndex, Boolean isHead) {}
/** /**
* Called after all operations on the row have been completed.This method is not called when fill the data. * Called after all operations on the row have been completed.
* In the case of the fill , may be called many times.
* *
* @param context * @param context
*/ */
@ -68,7 +69,8 @@ public interface RowWriteHandler extends WriteHandler {
} }
/** /**
* Called after all operations on the row have been completed.This method is not called when fill the data. * Called after all operations on the row have been completed.
* In the case of the fill , may be called many times.
* *
* @param writeSheetHolder * @param writeSheetHolder
* @param writeTableHolder Nullable.It is null without using table writes. * @param writeTableHolder Nullable.It is null without using table writes.

21
src/main/java/com/alibaba/excel/write/merge/LoopMergeStrategy.java

@ -1,13 +1,10 @@
package com.alibaba.excel.write.merge; package com.alibaba.excel.write.merge;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress;
import com.alibaba.excel.metadata.property.LoopMergeProperty; import com.alibaba.excel.metadata.property.LoopMergeProperty;
import com.alibaba.excel.write.handler.AbstractRowWriteHandler;
import com.alibaba.excel.write.handler.RowWriteHandler; import com.alibaba.excel.write.handler.RowWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.handler.context.RowWriteHandlerContext;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.util.CellRangeAddress;
/** /**
* The regions of the loop merge * The regions of the loop merge
@ -55,15 +52,15 @@ public class LoopMergeStrategy implements RowWriteHandler {
} }
@Override @Override
public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, public void afterRowDispose(RowWriteHandlerContext context) {
Integer relativeRowIndex, Boolean isHead) { if (context.getHead() || context.getRelativeRowIndex() == null) {
if (isHead) {
return; return;
} }
if (relativeRowIndex % eachRow == 0) { if (context.getRelativeRowIndex() % eachRow == 0) {
CellRangeAddress cellRangeAddress = new CellRangeAddress(row.getRowNum(), row.getRowNum() + eachRow - 1, CellRangeAddress cellRangeAddress = new CellRangeAddress(context.getRowIndex(),
context.getRowIndex() + eachRow - 1,
columnIndex, columnIndex + columnExtend - 1); columnIndex, columnIndex + columnExtend - 1);
writeSheetHolder.getSheet().addMergedRegionUnsafe(cellRangeAddress); context.getWriteSheetHolder().getSheet().addMergedRegionUnsafe(cellRangeAddress);
} }
} }

36
src/test/java/com/alibaba/easyexcel/test/core/fill/annotation/FillAnnotationData.java

@ -0,0 +1,36 @@
package com.alibaba.easyexcel.test.core.fill.annotation;
import java.util.Date;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.format.NumberFormat;
import com.alibaba.excel.annotation.write.style.ContentLoopMerge;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
/**
* @author Jiaju Zhuang
*/
@Getter
@Setter
@EqualsAndHashCode
@ContentRowHeight(100)
public class FillAnnotationData {
@ExcelProperty("日期")
@DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
private Date date;
@ExcelProperty(value = "数字")
@NumberFormat("#.##%")
private Double number;
@ContentLoopMerge(columnExtend = 2)
@ExcelProperty("字符串1")
private String string1;
@ExcelProperty("字符串2")
private String string2;
}

92
src/test/java/com/alibaba/easyexcel/test/core/fill/annotation/FillAnnotationDataTest.java

@ -0,0 +1,92 @@
package com.alibaba.easyexcel.test.core.fill.annotation;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.alibaba.easyexcel.test.util.TestFileUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.util.DateUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.CellRangeAddress;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
/**
* @author Jiaju Zhuang
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class FillAnnotationDataTest {
private static File file07;
private static File file03;
private static File fileTemplate07;
private static File fileTemplate03;
@BeforeClass
public static void init() {
file07 = TestFileUtil.createNewFile("fillAnnotation07.xlsx");
file03 = TestFileUtil.createNewFile("fillAnnotation03.xls");
fileTemplate07 = TestFileUtil.readFile("fill" + File.separator + "annotation.xlsx");
fileTemplate03 = TestFileUtil.readFile("fill" + File.separator + "annotation.xls");
}
@Test
public void t01ReadAndWrite07() throws Exception {
readAndWrite(file07, fileTemplate07);
}
@Test
public void t02ReadAndWrite03() throws Exception {
readAndWrite(file03, fileTemplate03);
}
private void readAndWrite(File file, File fileTemplate) throws Exception {
EasyExcel.write().file(file).head(FillAnnotationData.class).withTemplate(fileTemplate).sheet().doFill(data());
Workbook workbook = WorkbookFactory.create(file);
Sheet sheet = workbook.getSheetAt(0);
Row row1 = sheet.getRow(1);
Assert.assertEquals(2000, row1.getHeight(), 0);
Cell cell10 = row1.getCell(0);
Date date = cell10.getDateCellValue();
Assert.assertEquals(DateUtils.parseDate("2020-01-01 01:01:01").getTime(), date.getTime());
String dataFormatString = cell10.getCellStyle().getDataFormatString();
Assert.assertEquals("yyyy年MM月dd日HH时mm分ss秒", dataFormatString);
Cell cell11 = row1.getCell(1);
Assert.assertEquals(99.99, cell11.getNumericCellValue(), 2);
boolean hasMerge = false;
for (CellRangeAddress mergedRegion : sheet.getMergedRegions()) {
if (mergedRegion.getFirstRow() == 1 && mergedRegion.getLastRow() == 1
&& mergedRegion.getFirstColumn() == 2 && mergedRegion.getLastColumn() == 3) {
hasMerge = true;
}
}
Assert.assertTrue(hasMerge);
}
private List<FillAnnotationData> data() throws Exception {
List<FillAnnotationData> list = new ArrayList<>();
FillAnnotationData data = new FillAnnotationData();
data.setDate(DateUtils.parseDate("2020-01-01 01:01:01"));
data.setNumber(99.99);
data.setString1("string1");
data.setString2("string2");
list.add(data);
list.add(data);
list.add(data);
list.add(data);
list.add(data);
return list;
}
}

47
src/test/java/com/alibaba/easyexcel/test/temp/large/TempLargeDataTest.java

@ -133,7 +133,7 @@ public class TempLargeDataTest {
ExcelWriter excelWriter = EasyExcel.write(fileWriteTemp07, ExcelWriter excelWriter = EasyExcel.write(fileWriteTemp07,
com.alibaba.easyexcel.test.core.large.LargeData.class).build(); com.alibaba.easyexcel.test.core.large.LargeData.class).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build(); WriteSheet writeSheet = EasyExcel.writerSheet().build();
for (int j = 0; j < 2; j++) { for (int j = 0; j < 5000; j++) {
excelWriter.write(data(), writeSheet); excelWriter.write(data(), writeSheet);
} }
excelWriter.finish(); excelWriter.finish();
@ -141,6 +141,51 @@ public class TempLargeDataTest {
}); });
} }
@Test
public void t04WriteExcelNo() throws Exception {
IntStream.rangeClosed(0, 10000).forEach(index -> {
ExcelWriter excelWriter = EasyExcel.write(fileWriteTemp07,
com.alibaba.easyexcel.test.core.large.LargeData.class).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
for (int j = 0; j < 50; j++) {
excelWriter.write(data(), writeSheet);
}
excelWriter.finish();
LOGGER.info("{} 完成", index);
});
}
@Test
public void t04WriteExcelPoi() throws Exception {
IntStream.rangeClosed(0, 10000).forEach(index -> {
try (FileOutputStream fileOutputStream = new FileOutputStream(fileWritePoi07)) {
SXSSFWorkbook workbook = new SXSSFWorkbook(500);
//workbook.setCompressTempFiles(true);
SXSSFSheet sheet = workbook.createSheet("sheet1");
for (int i = 0; i < 100 * 50; i++) {
SXSSFRow row = sheet.createRow(i);
for (int j = 0; j < 25; j++) {
String str = "str-" + j + "-" + i;
//if (i + 10000 == j) {
SXSSFCell cell = row.createCell(j);
cell.setCellValue(str);
//System.out.println(str);
//}
}
if (i % 5000 == 0) {
LOGGER.info("{} write success.", i);
}
}
workbook.write(fileOutputStream);
workbook.dispose();
workbook.close();
} catch (Exception e) {
e.printStackTrace();
}
LOGGER.info("{} 完成", index);
});
}
private List<LargeData> data() { private List<LargeData> data() {
List<LargeData> list = new ArrayList<>(); List<LargeData> list = new ArrayList<>();

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

Binary file not shown.

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

Binary file not shown.

1
update.md

@ -1,5 +1,6 @@
# 3.0.4 # 3.0.4
* 调整读写默认大小,防止大批量写的时候可能会full gc * 调整读写默认大小,防止大批量写的时候可能会full gc
* `fill`的情况新增 `afterRowDispose`事件
# 3.0.3 # 3.0.3
* 修复`HeadStyle`无效的bug * 修复`HeadStyle`无效的bug

Loading…
Cancel
Save