//注意点 判断合并的列值最好在第一列
/**
* @param: downloadPath
* @param: templateStr
* @param: map
* @param: mergeColumns 需要合并的列
* @param: mergeRowIndex 从第几行开始合并
* @param: column 判断合并的列值
* @return void
**/
public static void dynamicDataDownloadFile(String downloadPath, String templateStr, Map<String, Object> map, int[] mergeColumns, int mergeRowIndex,Integer dataColumnBy) {
// 模板文件路径
String templatePath = RuoYiConfig.getUploadPath()+File.separator+templateStr;
ExcelWriter excelWriter = EasyExcelFactory.write(downloadPath).withTemplate(templatePath).registerWriteHandler(new ExcelFillCellMergeStrategy(dataColumnBy,mergeRowIndex,mergeColumns)).build();
WriteSheet writeSheet = EasyExcelFactory.writerSheet(0).build();
FillConfig fillConfig = FillConfig.builder().build();
Map<String,Object> fillData = map;
// 列表型填充
int i = 1;
// list型数据填充结束标识,true代表结束
boolean flag = false;
// 多个list标识,true代表有多个
boolean listFlag = false;
// 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存 此处默认为true,兼容历史代码
boolean forceFlag = (boolean) fillData.getOrDefault("forceFlag", true);
// 纵向列表,表名集合
String listName = "list" + i;
if (!listFlag && fillData.containsKey("list2")) {
listFlag = true;
// 多表时,也要配置,以防数据重叠
forceFlag = true;
}
Object list0 = fillData.get(listName);
if (Objects.isNull(list0)) {
flag = true;
}
List<Map<String, Object>> list = (List<Map<String, Object>>) list0;
if (forceFlag) {
fillConfig.setForceNewRow(Boolean.TRUE);
}
fillConfig.setDirection(WriteDirectionEnum.VERTICAL);
excelWriter.fill(fillData, fillConfig, writeSheet);
excelWriter.fill(list, fillConfig, writeSheet);
// 单元格型填充
Object map3 = fillData.get("map");
if (Objects.nonNull(map3)) {
excelWriter.fill(map3, writeSheet);
}
excelWriter.finish();
}
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import java.util.List;
import java.util.Objects;
/**
* @title: ExcelFillCellMergeStrategy
* @projectName asbproject
*/
public class ExcelFillCellMergeStrategy implements CellWriteHandler {
/** 需要进行单元格合并的列数组 **/
private int[] mergeColumnIndex;
/** 单元格合并从第几行开始 **/
private int mergeRowIndex;
private Integer mergeDataByIndex;
public ExcelFillCellMergeStrategy() {
}
public ExcelFillCellMergeStrategy(int mergeRowIndex, int[] mergeColumnIndex) {
this.mergeRowIndex = mergeRowIndex;
this.mergeColumnIndex = mergeColumnIndex;
}
public ExcelFillCellMergeStrategy(Integer mergeDataByIndex,int mergeRowIndex, int[] mergeColumnIndex) {
this.mergeRowIndex = mergeRowIndex;
this.mergeColumnIndex = mergeColumnIndex;
this.mergeDataByIndex = mergeDataByIndex;
}
@Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
int curRowIndex = cell.getRowIndex();
int curColIndex = cell.getColumnIndex();
if (curRowIndex > mergeRowIndex) {
for (int i = 0; i < mergeColumnIndex.length; i++) {
if (curColIndex == mergeColumnIndex[i]) {
mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex, mergeDataByIndex);
break;
}
}
}
}
/**
* 当前单元格向上合并
*
* @param writeSheetHolder
* @param cell
* 当前单元格
* @param curRowIndex
* 当前行
* @param curColIndex
* 当前列
*/
/**
* 当前单元格向上合并
*
* @param writeSheetHolder
* @param cell
* 当前单元格
* @param curRowIndex
* 当前行
* @param curColIndex
* 当前列
*/
private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex, int mergeDataByIndex) {
Object curData =
cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();
Row preRow = cell.getSheet().getRow(curRowIndex - 1);
Row curRow = cell.getSheet().getRow(curRowIndex );
if (preRow == null) {
// 当获取不到上一行数据时,使用缓存sheet中数据
preRow = writeSheetHolder.getCachedSheet().getRow(curRowIndex - 1);
}
if (curRow == null) {
// 当获取不到本行数据时,使用缓存sheet中数据
curRow = writeSheetHolder.getCachedSheet().getRow(curRowIndex );
}
Cell preCell = preRow.getCell(curColIndex);
Object preData =
preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() : preCell.getNumericCellValue();
// 将当前单元格数据与上一个单元格数据比较(20221122 当合并数据的逻辑发生改变---根据某一列的数据相同来决定是否合并)
Boolean dataBool = Objects.nonNull(mergeDataByIndex) ? equalsPreData(preRow,curRow,mergeDataByIndex) : preData.equals(curData);
if (dataBool) {
Sheet sheet = writeSheetHolder.getSheet();
List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
boolean isMerged = false;
for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {
CellRangeAddress cellRangeAddr = mergeRegions.get(i);
// 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元
if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {
sheet.removeMergedRegion(i);
cellRangeAddr.setLastRow(curRowIndex);
sheet.addMergedRegion(cellRangeAddr);
isMerged = true;
}
}
// 若上一个单元格未被合并,则新增合并单元
if (!isMerged) {
CellRangeAddress cellRangeAddress =
new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex, curColIndex);
sheet.addMergedRegion(cellRangeAddress);
}
}
}
private Boolean equalsPreData(Row preRow, Row curRow, int mergeDataByIndex) {
Cell preCell = preRow.getCell(mergeDataByIndex);
Cell curCell = curRow.getCell(mergeDataByIndex);
if (null == preCell || null == curCell) {
return false;
}
Object preData =
preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() : preCell.getNumericCellValue();
Object curData =
curCell.getCellTypeEnum() == CellType.STRING ? curCell.getStringCellValue() : curCell.getNumericCellValue();
return preData.equals(curData);
}
}