上面方法不行
我最新的版本,业务上已使用过。去年写的,略微复杂:
public class CustomLoopMergeStrategy extends AbstractMergeStrategy {
private LinkedList<Integer> eachRow;
private int columnIndex;
private int maxColumn;
private LinkedList<Integer> totalRows;
public CustomLoopMergeStrategy(List<Integer> eachRow, int columnIndex, int maxColumn) {
if (eachRow.stream().anyMatch(row -> row < 1)) {
throw new IllegalArgumentException("EachRows must be greater than 1");
}
this.eachRow = new LinkedList<>(eachRow);
this.columnIndex = columnIndex;
this.maxColumn = maxColumn;
final int[] acc = {0};
this.totalRows = eachRow.stream().map(item -> {
int result = item + acc[0], item1 = item + acc[0];
acc[0] = item1;
if (item == 1) {
result = 0;
}
return result;
}).filter(i -> i != 0).collect(Collectors.toCollection(LinkedList::new));
}
@Override
protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
if (totalRows.isEmpty() || eachRow.isEmpty() || head.getColumnIndex() > maxColumn) {
return;
}
if (head.getColumnIndex() == maxColumn && eachRow.getFirst() == 1) {
eachRow.removeFirst();
return;
}
if (relativeRowIndex >= totalRows.getFirst()) {
totalRows.removeFirst();
eachRow.removeFirst();
}
if (head.getColumnIndex() == columnIndex && !totalRows.isEmpty() && !eachRow.isEmpty()
&& relativeRowIndex == totalRows.getFirst() - eachRow.getFirst()) {
CellRangeAddress cellRangeAddress = new CellRangeAddress(cell.getRowIndex(),
cell.getRowIndex() + eachRow.getFirst() - 1, cell.getColumnIndex(), cell.getColumnIndex());
sheet.addMergedRegion(cellRangeAddress);
}
}
}
使用的地方:
List<Integer> eachRows = data.stream()
.collect(Collectors.groupingBy(BaseDTO::getGroupId))
.entrySet().stream().sorted(Map.Entry.comparingByKey())
.map(entry -> entry.getValue().size())
.collect(Collectors.toList());
IntStream.range(0, mergeColumns).forEach(idx ->
excelWriterBuilder.registerWriteHandler(new CustomLoopMergeStrategy(eachRows, idx, mergeColumns)));