parent
48431670fc
commit
f6f120d9e6
@ -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