9 changed files with 421 additions and 24 deletions
@ -0,0 +1,114 @@ |
|||||
|
package com.epmet.commons.tools.utils.poi.excel.handler; |
||||
|
|
||||
|
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; |
||||
|
|
||||
|
/** |
||||
|
* desc:单元格合并策略 |
||||
|
* @author liujianjun |
||||
|
*/ |
||||
|
public class ExcelFillCellMergeStrategy implements CellWriteHandler { |
||||
|
|
||||
|
private int[] mergeColumnIndex; |
||||
|
private int mergeRowIndex; |
||||
|
|
||||
|
public ExcelFillCellMergeStrategy() { |
||||
|
} |
||||
|
|
||||
|
public ExcelFillCellMergeStrategy(int mergeRowIndex, int[] mergeColumnIndex) { |
||||
|
this.mergeRowIndex = mergeRowIndex; |
||||
|
this.mergeColumnIndex = mergeColumnIndex; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { |
||||
|
// 隐藏id列
|
||||
|
writeSheetHolder.getSheet().setColumnHidden(0, true); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> list, Cell cell, Head head, Integer integer, Boolean aBoolean) { |
||||
|
int curRowIndex = cell.getRowIndex(); |
||||
|
int curColIndex = cell.getColumnIndex(); |
||||
|
int size = list.size(); |
||||
|
System.out.println(size); |
||||
|
if (mergeColumnIndex == null) { |
||||
|
if (curRowIndex > 2) { |
||||
|
mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex); |
||||
|
} |
||||
|
}else{ |
||||
|
if (curRowIndex > mergeRowIndex) { |
||||
|
for (int i = 0; i < mergeColumnIndex.length; i++) { |
||||
|
if (curColIndex == mergeColumnIndex[i]) { |
||||
|
mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 当前单元格向上合并 |
||||
|
* |
||||
|
* @param writeSheetHolder |
||||
|
* @param cell 当前单元格 |
||||
|
* @param curRowIndex 当前行 |
||||
|
* @param curColIndex 当前列 |
||||
|
*/ |
||||
|
private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) { |
||||
|
//writeSheetHolder.getExcelWriteHeadProperty().
|
||||
|
// 当前行的第一个Cell
|
||||
|
Cell curFirstCell = cell.getSheet().getRow(curRowIndex).getCell(0); |
||||
|
Object curFirstData = curFirstCell.getCellType() == CellType.STRING ? curFirstCell.getStringCellValue() : curFirstCell.getNumericCellValue(); |
||||
|
// 上一行的第一个Cell
|
||||
|
Cell preFirstCell = cell.getSheet().getRow(curRowIndex - 1).getCell(0); |
||||
|
Object preFirstData = preFirstCell.getCellType() == CellType.STRING ? preFirstCell.getStringCellValue() : preFirstCell.getNumericCellValue(); |
||||
|
|
||||
|
if (curFirstData.equals(preFirstData)) { |
||||
|
Object curData = cell.getCellType() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue(); |
||||
|
Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex); |
||||
|
Object preData = preCell.getCellType() == CellType.STRING ? preCell.getStringCellValue() : preCell.getNumericCellValue(); |
||||
|
// 将当前单元格数据与上一个单元格数据比较
|
||||
|
Boolean dataBool = preData.equals(curData); |
||||
|
//此处需要注意:因为我是按照序号确定是否需要合并的,所以获取每一行第一列数据和上一行第一列数据进行比较,如果相等合并
|
||||
|
Boolean bool = cell.getRow().getCell(0).getStringCellValue().equals(cell.getSheet().getRow(curRowIndex - 1).getCell(0).getStringCellValue()); |
||||
|
if (dataBool && bool) { |
||||
|
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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
@ -0,0 +1,213 @@ |
|||||
|
package com.epmet.commons.tools.utils.poi.excel.handler; |
||||
|
|
||||
|
/** |
||||
|
* desc: |
||||
|
* |
||||
|
* @author: LiuJanJun |
||||
|
* @date: 2022/4/26 1:36 下午 |
||||
|
* @version: 1.0 |
||||
|
*/ |
||||
|
|
||||
|
import com.alibaba.excel.enums.CellDataTypeEnum; |
||||
|
import com.alibaba.excel.metadata.Head; |
||||
|
import com.alibaba.excel.metadata.data.CellData; |
||||
|
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; |
||||
|
import java.util.stream.IntStream; |
||||
|
|
||||
|
/** |
||||
|
* 相同值合并策略 |
||||
|
*/ |
||||
|
|
||||
|
public class ExcelMergeStrategy implements CellWriteHandler { |
||||
|
|
||||
|
/** |
||||
|
* 合并起始行 |
||||
|
*/ |
||||
|
|
||||
|
private int mergeRowIndex; |
||||
|
/** |
||||
|
* 多少行合并一次 |
||||
|
*/ |
||||
|
|
||||
|
private int eachRow; |
||||
|
|
||||
|
/** |
||||
|
* 合并字段的下标 |
||||
|
*/ |
||||
|
|
||||
|
private int[] mergeColumnIndex; |
||||
|
|
||||
|
public ExcelMergeStrategy(int mergeRowIndex, int[] mergeColumnIndex, int eachRow) { |
||||
|
|
||||
|
if (mergeRowIndex < 0) { |
||||
|
|
||||
|
throw new IllegalArgumentException("mergeRowIndex must be greater than 0"); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
if (eachRow < 0) { |
||||
|
|
||||
|
throw new IllegalArgumentException("eachRow must be greater than 0"); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
this.mergeRowIndex = mergeRowIndex; |
||||
|
|
||||
|
this.mergeColumnIndex = mergeColumnIndex; |
||||
|
|
||||
|
this.eachRow = eachRow; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
|
||||
|
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) { |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
|
||||
|
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { |
||||
|
} |
||||
|
|
||||
|
// @Override
|
||||
|
public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { |
||||
|
|
||||
|
int curRowIndex = cell.getRowIndex(); |
||||
|
|
||||
|
//当前列
|
||||
|
|
||||
|
int curColIndex = cell.getColumnIndex(); |
||||
|
|
||||
|
//合并条件:
|
||||
|
|
||||
|
//1.当前行>合并起始行,默认标题行(0)不参加合并
|
||||
|
|
||||
|
//2.间隔行(eachRow)的上下两条不参加合并
|
||||
|
|
||||
|
//2.1间隔行(eachRow)==0时,不设置间隔
|
||||
|
|
||||
|
if (isMerge(curRowIndex)) { |
||||
|
|
||||
|
IntStream.range(0, mergeColumnIndex.length).anyMatch(i -> { |
||||
|
|
||||
|
if (curColIndex == mergeColumnIndex[i]) { |
||||
|
|
||||
|
mergeWithPrevRow(writeSheetHolder, cellData, cell, curRowIndex, curColIndex); |
||||
|
|
||||
|
return true; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 判断是否合并 |
||||
|
* <p> |
||||
|
* 1.当前位置必须大于开始位置:curRowIndex > mergeRowIndex |
||||
|
* <p> |
||||
|
* 2.根据eachRow 判断数据分割的间隔 |
||||
|
* <p> |
||||
|
* 2.1如果根据eachRow=0,默认不合并 |
||||
|
* <p> |
||||
|
* 2.2如果1如果根据eachRow>0,分割后的第一条数据不会与之前的合并:(curRowIndex-mergeRowIndex)%eachRow==0 |
||||
|
* |
||||
|
* @return |
||||
|
*/ |
||||
|
|
||||
|
private boolean isMerge(Integer curRowIndex) { |
||||
|
if ((curRowIndex > mergeRowIndex) && eachRow > 0) { |
||||
|
|
||||
|
if ((curRowIndex - mergeRowIndex) % eachRow == 0) { |
||||
|
|
||||
|
return false; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
|
||||
|
} |
||||
|
return false; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, CellData cellData, Cell cell, int curRowIndex, int curColIndex) { |
||||
|
|
||||
|
//获取当前行的当前列的数据和上一行的当前列列数据,通过上一行数据是否相同进行合并
|
||||
|
|
||||
|
Object curData = cellData.getType() == CellDataTypeEnum.STRING ? cellData.getStringValue() : cellData.getNumberValue(); |
||||
|
|
||||
|
Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex); |
||||
|
|
||||
|
Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() : |
||||
|
|
||||
|
preCell.getNumericCellValue(); |
||||
|
|
||||
|
// 比较当前行的第一列的单元格与上一行是否相同,相同合并当前单元格与上一行
|
||||
|
|
||||
|
if (Objects.equals(curData, preData)) { |
||||
|
|
||||
|
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); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
Loading…
Reference in new issue