parent
43e8e93525
commit
27ee418b60
@ -0,0 +1,107 @@ |
|||||||
|
package com.hfkj.common.utils; |
||||||
|
|
||||||
|
import com.alibaba.excel.metadata.CellData; |
||||||
|
import com.alibaba.excel.metadata.Head; |
||||||
|
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; |
||||||
|
|
||||||
|
public class ExcelFillCellMergeStrategyUtils implements CellWriteHandler { |
||||||
|
|
||||||
|
/** |
||||||
|
* 需要合并列的下标,从0开始 |
||||||
|
*/ |
||||||
|
private int[] mergeColumnIndex; |
||||||
|
/** |
||||||
|
* 从第几行开始合并,表头下标为0 |
||||||
|
*/ |
||||||
|
private int mergeRowIndex; |
||||||
|
|
||||||
|
public ExcelFillCellMergeStrategyUtils(int mergeRowIndex, int[] mergeColumnIndex) { |
||||||
|
this.mergeRowIndex = mergeRowIndex; |
||||||
|
this.mergeColumnIndex = mergeColumnIndex; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> list, Cell cell, Head head, Integer integer, Boolean aBoolean) { |
||||||
|
//当前行
|
||||||
|
int curRowIndex = cell.getRowIndex(); |
||||||
|
//当前列
|
||||||
|
int curColIndex = cell.getColumnIndex(); |
||||||
|
|
||||||
|
if (curColIndex == 0) { |
||||||
|
Row preRow = cell.getSheet().getRow(curRowIndex - 1); |
||||||
|
if (preRow == null) { |
||||||
|
// 当获取不到上一行数据时,使用缓存sheet中数据
|
||||||
|
preRow = writeSheetHolder.getCachedSheet().getRow(curRowIndex - 1); |
||||||
|
} |
||||||
|
if (preRow != null) { |
||||||
|
if (cell.getStringCellValue().equals(preRow.getCell(0).getStringCellValue())) { |
||||||
|
for (int i = 0; i < mergeColumnIndex.length; i++) { |
||||||
|
if (curColIndex == mergeColumnIndex[i]) { |
||||||
|
mergeWithPrevRow(writeSheetHolder, cell, i, i); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
// preRow.getCell(curColIndex);
|
||||||
|
|
||||||
|
/* if (curRowIndex > mergeRowIndex) { |
||||||
|
for (int i = 0; i < mergeColumnIndex.length; i++) { |
||||||
|
if (curColIndex == mergeColumnIndex[i]) { |
||||||
|
mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
}*/ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) { |
||||||
|
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,186 @@ |
|||||||
|
package com.hfkj.common.utils; |
||||||
|
|
||||||
|
import com.alibaba.excel.metadata.Head; |
||||||
|
import com.alibaba.excel.write.merge.AbstractMergeStrategy; |
||||||
|
import org.apache.commons.lang3.StringUtils; |
||||||
|
import org.apache.poi.ss.usermodel.Cell; |
||||||
|
import org.apache.poi.ss.usermodel.Sheet; |
||||||
|
import org.apache.poi.ss.util.CellRangeAddress; |
||||||
|
|
||||||
|
import java.util.*; |
||||||
|
|
||||||
|
/** |
||||||
|
* @className: MergeCellStrategyHandler |
||||||
|
* @author: HuRui |
||||||
|
* @date: 2024/8/2 |
||||||
|
**/ |
||||||
|
public class MergeCellStrategyHandler extends AbstractMergeStrategy { |
||||||
|
/** |
||||||
|
* 相同列合并 |
||||||
|
*/ |
||||||
|
private boolean alikeColumn; |
||||||
|
|
||||||
|
/** |
||||||
|
* 相同行合并 |
||||||
|
*/ |
||||||
|
private boolean alikeRow; |
||||||
|
|
||||||
|
/** 开始进行合并的行index */ |
||||||
|
private int rowIndex; |
||||||
|
|
||||||
|
/** 跨行合并的列index */ |
||||||
|
private Set<Integer> columns; |
||||||
|
|
||||||
|
private int currentRowIndex = 0; |
||||||
|
|
||||||
|
public MergeCellStrategyHandler(boolean alikeColumn, boolean alikeRow, int rowIndex, Set<Integer> columns){ |
||||||
|
this.alikeColumn = alikeColumn; |
||||||
|
this.alikeRow = alikeRow; |
||||||
|
this.rowIndex = rowIndex; |
||||||
|
this.columns = columns; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 指定是否进行跨列合并单元格 |
||||||
|
* @param alikeColumn |
||||||
|
* @param rowIndex |
||||||
|
*/ |
||||||
|
public MergeCellStrategyHandler(boolean alikeColumn, int rowIndex){ |
||||||
|
this(alikeColumn, false, rowIndex, new HashSet<>()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 指定是否进行跨行合并单元格 |
||||||
|
* @param alikeRow |
||||||
|
* @param rowIndex |
||||||
|
* @param columns |
||||||
|
*/ |
||||||
|
public MergeCellStrategyHandler(boolean alikeRow, int rowIndex, Set<Integer> columns){ |
||||||
|
this(false, alikeRow, rowIndex, columns); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected void merge(Sheet sheet, Cell cell, Head head, Integer integer) { |
||||||
|
int rowId = cell.getRowIndex(); |
||||||
|
currentRowIndex = rowId == currentRowIndex ? currentRowIndex : rowId; |
||||||
|
if (rowIndex > rowId) { |
||||||
|
return; |
||||||
|
} |
||||||
|
int columnId = cell.getColumnIndex(); |
||||||
|
// 列合并
|
||||||
|
if (alikeColumn && columnId > 0) { |
||||||
|
String currentCellVal = this.getCellVal(cell); |
||||||
|
Cell preCell = cell.getRow().getCell(columnId - 1); |
||||||
|
String preCellVal = this.getCellVal(preCell); |
||||||
|
if (null != currentCellVal && null != preCellVal && StringUtils.isNotBlank(preCellVal) && StringUtils.isNotBlank(currentCellVal)) { |
||||||
|
// 当前单元格内容与上一个单元格内容相等,进行合并处理
|
||||||
|
if (preCellVal.equals(currentCellVal)) { |
||||||
|
CellRangeAddress rangeAddress = new CellRangeAddress(currentRowIndex, currentRowIndex, columnId - 1, columnId); |
||||||
|
rangeAddress = this.findExistAddress(sheet, rangeAddress, currentCellVal); |
||||||
|
if (null != rangeAddress) { |
||||||
|
sheet.addMergedRegion(rangeAddress); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
// 行合并
|
||||||
|
if (alikeRow && rowIndex < rowId && columns.contains(columnId)) { |
||||||
|
String currentCellVal = this.getCellVal(cell); |
||||||
|
Cell preCell = sheet.getRow(rowId - 1).getCell(columnId); |
||||||
|
String preCellVal = this.getCellVal(preCell); |
||||||
|
if (null != currentCellVal && null != preCellVal && !preCellVal.isBlank() && !currentCellVal.isBlank()) { |
||||||
|
// 当前单元格内容与上一行单元格内容相等,进行合并处理
|
||||||
|
if (preCellVal.equals(currentCellVal)) { |
||||||
|
//sheet.validateMergedRegions();
|
||||||
|
CellRangeAddress rangeAddress = new CellRangeAddress(currentRowIndex - 1, currentRowIndex, columnId, columnId); |
||||||
|
rangeAddress = this.findExistAddress(sheet, rangeAddress, currentCellVal); |
||||||
|
if (null != rangeAddress) { |
||||||
|
sheet.addMergedRegion(rangeAddress); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 合并单元格地址范围,发现存在相同的地址则进行扩容合并 |
||||||
|
* |
||||||
|
* @param isColumn true:跨列合并 false:跨行合并 |
||||||
|
* @param sheet |
||||||
|
* @param rangeAddress : |
||||||
|
* @param currentVal 当前单元格中的值 |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
private CellRangeAddress findExistAddress(Sheet sheet, CellRangeAddress rangeAddress, String currentVal) { |
||||||
|
List<CellRangeAddress> mergedRegions = sheet.getMergedRegions(); |
||||||
|
int existIndex = 0; |
||||||
|
Map<Integer, CellRangeAddress> existIdexMap = new LinkedHashMap<>(); |
||||||
|
if (null != mergedRegions && !mergedRegions.isEmpty()) { |
||||||
|
//验证当前合并的单元格是否存在重复(fixme 重复问题待处理!!!)
|
||||||
|
for (CellRangeAddress mergedRegion : mergedRegions) { |
||||||
|
if (mergedRegion.intersects(rangeAddress)) { |
||||||
|
existIdexMap.put(existIndex, mergedRegion); |
||||||
|
} |
||||||
|
existIndex++; |
||||||
|
} |
||||||
|
} |
||||||
|
if (existIdexMap.isEmpty()) { |
||||||
|
return rangeAddress; |
||||||
|
} |
||||||
|
List<Integer> existIndexList = new ArrayList<>(existIdexMap.size()); |
||||||
|
for (Map.Entry<Integer, CellRangeAddress> addressEntry : existIdexMap.entrySet()) { |
||||||
|
CellRangeAddress exist = addressEntry.getValue(); |
||||||
|
// 自动进行单元格合并处理
|
||||||
|
int firstRow = rangeAddress.getFirstRow(); |
||||||
|
int lastRow = rangeAddress.getLastRow(); |
||||||
|
int firstColumn = rangeAddress.getFirstColumn(); |
||||||
|
int lastColumn = rangeAddress.getLastColumn(); |
||||||
|
|
||||||
|
int firstRow1 = exist.getFirstRow(); |
||||||
|
int lastRow1 = exist.getLastRow(); |
||||||
|
int firstColumn1 = exist.getFirstColumn(); |
||||||
|
int lastColumn1 = exist.getLastColumn(); |
||||||
|
// 跨行合并 最后一列相等, 行不相等
|
||||||
|
if (lastRow > lastRow1 && lastColumn == lastColumn1) { |
||||||
|
// 检查进行跨行合并的单元格是否已经存在跨列合并
|
||||||
|
if (lastColumn > 0 && firstColumn1 != lastColumn1) { |
||||||
|
// 获取当前单元格的前一列单元格
|
||||||
|
String cellVal = this.getCellVal(sheet.getRow(lastRow).getCell(lastColumn - 1)); |
||||||
|
if (null != cellVal && cellVal.equals(currentVal)) { |
||||||
|
exist.setLastRow(lastRow); |
||||||
|
} |
||||||
|
} else { |
||||||
|
exist.setLastRow(lastRow); |
||||||
|
} |
||||||
|
rangeAddress = exist; |
||||||
|
existIndexList.add(addressEntry.getKey()); |
||||||
|
} |
||||||
|
|
||||||
|
// 跨列合并 行相等,列不相等
|
||||||
|
if (lastColumn > lastColumn1 && firstRow == firstRow1 ) { |
||||||
|
exist.setLastColumn(lastColumn); |
||||||
|
rangeAddress = exist; |
||||||
|
existIndexList.add(addressEntry.getKey()); |
||||||
|
} |
||||||
|
} |
||||||
|
// 移除已经存在且冲突的合并数据
|
||||||
|
if (existIndexList.isEmpty()) { |
||||||
|
rangeAddress = null; |
||||||
|
}else { |
||||||
|
sheet.removeMergedRegions(existIdexMap.keySet()); |
||||||
|
} |
||||||
|
return rangeAddress; |
||||||
|
} |
||||||
|
|
||||||
|
private String getCellVal(Cell cell) { |
||||||
|
String val = null; |
||||||
|
try { |
||||||
|
val = cell.getStringCellValue(); |
||||||
|
}catch (Exception e){ |
||||||
|
System.out.printf("读取单元格内容失败:行%d 列%d %n", (cell.getRowIndex() + 1), (cell.getColumnIndex() + 1)); |
||||||
|
} |
||||||
|
return val; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue