excel单元格行合并
List<Map<String, String>> compareDatas = new ArrayList<>();
statisticsSummary.forEach(item -> {
Map<String, String> data = (Map<String, String>) JSON.parse(JSON.toJSONString(item));
compareDatas.add(data);
});
ExcelUtil.mergeRowsCellContent(sheet, compareDatas, 1, 0, Lists.newArrayList("", "classify"));
/**
* @param sheet 需要合并的excel
* @param listData 数据内容
* @param startRows 需要计算的起始行(数据所在行的下标,下标从0开始算起)
* @param startCols 需要计算的起始列,从需要比对的字段列开始算起,若是从0开始,且要合并的列不是第一列,则需要在比对字段中使用""占位列数
* @param compareFields 需要对比的code字段,假如有多个字段需要比对,且不是相邻行的则需要用 "a","","c" 形式,第一列和第三列需要合并,第二列不需要合并
* @Description: 合并行方法
* @MethodName: mergeCellContent
*/
public static void mergeRowsCellContent(XSSFSheet sheet, List<Map<String, String>> listData, int startRows, int startCols, List<String> compareFields) {
if (startRows < 1 || CollectionUtils.isEmpty(compareFields) || CollectionUtils.isEmpty(listData)) {
return;
}
// 数据合并计算需要减去 1
startRows = startRows - 1;
//备份上一条数据
Map<String, String> lastDataMap = new HashMap<>();
//需要合并的行数记录
Map<String, Integer> mergeRows = new HashMap<>();
for (int i = 0; i < listData.size(); i++) {
//当前行数据
Map<String, String> entity = listData.get(i);
for (int a = 0; a < compareFields.size(); a++) {
//首行不做判断合并处理
if (i == 0) {
break;
}
//将上下两行同列数据强制转换为字符串进行比较,相同设置单元格合并
String field = compareFields.get(a);
if (StringUtils.isEmpty(field)) {
continue;
}
addMergeRegion(sheet, listData, startRows, startCols, lastDataMap, mergeRows, i, entity, a, field);
}
lastDataMap.putAll(entity);
}
}
/**
* @param sheet
* @param listData
* @param startRows
* @param startCols
* @param lastDataMap
* @param mergeRows
* @param i
* @param entity
* @param a
* @param field
* @return boolean
* @Description: 添加单元格合并
* @MethodName: addMergeRegion
*/
private static void addMergeRegion(XSSFSheet sheet, List<Map<String, String>> listData, int startRows, int startCols, Map<String, String> lastDataMap,
Map<String, Integer> mergeRows, int i, Map<String, String> entity, int a, String field) {
String lastCode = StringUtils.defaultIfEmpty(lastDataMap.get(field), "");
String thisCode = StringUtils.defaultIfEmpty(entity.get(field), "");
String key = a + "###" + field;
//避免合并判断标识为空,为空
if (StringUtils.isEmpty(lastCode) || StringUtils.isEmpty(thisCode)) {
return;
}
boolean lastOne = (i == listData.size() - 1);
//非最后一行的以及上下两行code相同,累加需要合并行数
if (!lastOne && lastCode.equals(thisCode)) {
Integer fieldRows = mergeRows.getOrDefault(key, 0);
fieldRows = fieldRows + 1;
mergeRows.put(key, fieldRows);
return;
}
//获取需要合并的行数
Integer fieldRows = mergeRows.getOrDefault(key, 0);
mergeRows.put(key, 0);
//不需要合并且不是最后一行,直接跳过
if (fieldRows == 0 && !lastOne) {
return;
}
//起始行
int mergeStartRow = (startRows + i - fieldRows);
//结束行
int mergeEndRow = (startRows + i);
//起始列
int mergeStartCol = (startCols + a);
//结束列
int mergeEndCol = (startCols + a);
//最后一行,且需要和前一行合并,结束行需要+1
if (lastOne && lastCode.equals(thisCode)) {
mergeEndRow = mergeEndRow + 1;
}
// 最后一行,且不需要和前一行合并,且起始行等于结束行,直接返回
if (lastOne && !lastCode.equals(thisCode) && mergeStartRow == mergeEndRow) {
return;
}
CellRangeAddress cra = new CellRangeAddress(mergeStartRow, mergeEndRow, mergeStartCol, mergeEndCol);
try {
//在sheet里设置合并单元格
sheet.addMergedRegion(cra);
} catch (Exception exception) {
log.error("合并单元格失败:error:", exception);
}
}