说明:此文章是对ruoyi分离版后台功能,导出excel文件,导出对象的子列表的补充
若依文档:
后台手册 | RuoYi
导出文件结果
:::color4
补充文档场景:
如上图所示,角色中的字段“角色编号”,“角色名称”,“角色字符”作为子集填充到用户中,改变角色子集的显示顺序,将子集放到“用户名称”和“邮箱”中间时,导出的文件为空
:::
在自定义注解 Excel 中添加字段
/*** 是否需要合并行 与 needMerge 以及 子列表不兼容*/
public boolean lineMerge() default false;/*** 合并行的依据的主键*/
public boolean lineMergeId() default false;
修改 ExcelUtil.fillExcelData方法
public void fillExcelData(int index, Row row) {int startNo = index * sheetSize;int endNo = Math.min(startNo + sheetSize, list.size());int rowNo = (1 + rownum) - startNo;String objIdValve = "";//注解中 lineMergeId 为true的value 合并单元格使用int mergeStartRow = 0;//合并单元格 起始行for (int i = startNo; i < endNo; i++) {rowNo = isSubList() ? (i > 1 ? rowNo + 1 : rowNo + i) : i + 1 + rownum - startNo;row = sheet.createRow(rowNo);// 得到导出对象.T vo = (T) list.get(i);Collection<?> subList = null;if (isSubList()) {if (isSubListValue(vo)) {subList = getListCellValue(vo);subMergedLastRowNum = subMergedLastRowNum + subList.size();} else {subMergedFirstRowNum++;subMergedLastRowNum++;}}int column = 0;boolean mergeCells = false;//合并单元格 当前单元格是否需要合并for (Object[] os : fields) {Field field = (Field) os[0];Excel excel = (Excel) os[1];/*** 合并单元格判断条件处理*/if (excel.lineMergeId()) {try {Object value = getTargetValue(vo, field, excel);if (!objIdValve.equals(value.toString())) {objIdValve = value.toString();mergeCells = false;mergeStartRow = rowNo;} else {mergeCells = true;}} catch (Exception e) {log.error("合并单元格导出主键获取失败,导出Excel失败{}", e);}}if (Collection.class.isAssignableFrom(field.getType()) && StringUtils.isNotNull(subList)) {boolean subFirst = false;for (Object obj : subList) {if (subFirst) {rowNo++;row = sheet.createRow(rowNo);}List<Field> subFields = FieldUtils.getFieldsListWithAnnotation(obj.getClass(), Excel.class);int subIndex = 0;for (Field subField : subFields) {if (subField.isAnnotationPresent(Excel.class)) {subField.setAccessible(true);Excel attr = subField.getAnnotation(Excel.class);this.addCell(attr, row, (T) obj, subField, column + subIndex);}subIndex++;}subFirst = true;}this.subMergedFirstRowNum = this.subMergedFirstRowNum + subList.size();} else {this.addCell(excel, row, vo, field, column++);}/*** 合并单元格操作*/if (excel.lineMerge() && mergeCells) {if (rowNo - mergeStartRow > 1) {List<CellRangeAddress> cellList = new ArrayList<>(sheet.getMergedRegions());for (int i1 = 0; i1 < cellList.size(); i1++) {CellRangeAddress ca = cellList.get(i1);if (mergeStartRow == ca.getFirstRow() && rowNo - 1 == ca.getLastRow() && column - 1 == ca.getFirstColumn() && column - 1 == ca.getLastColumn()) {sheet.removeMergedRegion(i1);}}}sheet.addMergedRegion(new CellRangeAddress(mergeStartRow, rowNo, column - 1, column - 1));}}}}
具体使用方式
在用户编号 @Excel注解中添加 lineMergeId = true,合并单元格的行以此为合并依据,没有此标记则不会执行合并单元格
在需要合并的列中的@Excel注解中添加 lineMerge = true
注:自定义注解 Excel中原有 needMerge字段 以及 ExcelUtil中的子列表不兼容
@Data
public class SysUser{@Excel(name = "用户编号", lineMergeId = true, width = 20, lineMerge = true)private String userId;@Excel(name = "用户名称", width = 20, lineMerge = true)private String userName;@Excel(name = "邮箱", width = 20, lineMerge = true)private String email;@Excel(name = "角色编号")private String roleId;@Excel(name = "角色名称")private String roleName;@Excel(name = "角色字符")private String roleKey;
}