Java导出Excel模板,导出数据到指定模板,通过模板导入数据(一)已经讲述了一般Excel的导入导出,此处就不在额外讲述了。这篇来讲述合并操作,仅以列合并示例。
1. 导出模板
这个和Java导出Excel模板,导出数据到指定模板,通过模板导入数据(一)的讲述的导出模板是一样的
2. 导出数据到模板中
2.1 首先自己制造一个导出的excel模板,模板和Java导出Excel模板,导出数据到指定模板,通过模板导入数据(一)讲述的模板一样,而合并单元格是通过代码实现的。
2.2 导出数据接口编写
/**
* 导出数据
*
* @param excelParam 导出入参
* @param response HttpServletResponse对象
* @throws Exception 导出异常
*/
@PostMapping(value = "/export", produces = "application/octet-stream")
public void export(@RequestBody @Validated TeamsExcelParam excelParam, HttpServletResponse response) throws Exception {
List resultList = teamsService.list(excelParam);
String title = "班组";
Map outerMap = new HashMap<>(2);
outerMap.put("title", title);
List children = new ArrayList();
if (resultList.size() > 0) {
List dataIds = resultList.stream().map(Teams::getDataId).collect(Collectors.toList());
//查询所有的子
children = teamsPersonnelService.listByTeamsIds(dataIds);
}
List
说明:
for循环中进行数据处理,子不同,父可能会有很多相同的。
mergeRowIndex = 2 是指行的下标(下标从0开始)。从第二行开始对相同数据进行合并操作。
mergeColumnIndex = {0, 1, 2, 3} 是指要合并的列的下标(下标从0开始)。
具体列的合并逻辑见Java导出Excel模板,导出数据到指定模板,通过模板导入数据(一)中的工具类 ExcelFillCellMergeStrategyUtils.java 中的mergeWithPrevRow方法。
3. 数据导入
3.1 创建数据导入模板
导入模板的下载见 Java导出Excel模板,导出数据到指定模板,通过模板导入数据(一)
3.2 创建数据导入监听类
数据的校验全部放在监听类中进行处理,如需要用的其他业务参数,直接通过在controller中实例化该监听类时传递到构造方法中。
TeamsReadExcelListener.java
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.Cell;
import com.lonzh.util.excel.ExcelUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import java.util.*;
/**
* 班组数据导入监听
*
* @author DaiHaijiao
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Slf4j
public class TeamsReadExcelListener extends AnalysisEventListener {
/**
* 解析的数据集合
*/
List dataList = new ArrayList();
/**
* 班组职位字典数据
*/
static List dictDataList;
/**
* 部门及人员信息
*/
static List departmentUserList;
public static TeamsReadExcelListener newBean(List dictDatas, List deptUserList) {
departmentUserList = deptUserList;
dictDataList = dictDatas;
return new TeamsReadExcelListener();
}
/**
* 读取excel每一行都会触发本方法
*
* @param data 行数据
* @param context AnalysisContext
*/
@SneakyThrows
@Override
public void invoke(Object data, AnalysisContext context) {
Teams excelData = new Teams();
// 当前数据行号,从0开始
Integer rowIndex = context.readRowHolder().getRowIndex();
// 获取行中每一列数据
Map cellMap = context.readRowHolder().getCellMap();
String rowNo = cellMap.get(0) + "";
boolean ifNeedCheckParent = true;
if (dataList.size() > 0) {
Teams excelDataTemp = dataList.get(dataList.size() - 1);
//rowNo是临时添加的字段仅用户导入时的业务判断处理(数据库并没有此字段)
if (rowNo.equalsIgnoreCase(excelDataTemp.getRowNo()) || "null".equalsIgnoreCase(rowNo)) {
//当前添加的是子
ifNeedCheckParent = false;
excelData = dataList.get(dataList.size() - 1);
}
}
LinkedHashMap dataTemp = (LinkedHashMap) data;
for (int i = 0; i < dataTemp.size(); i++) {
this.parseColumnData(rowIndex, i, dataTemp.get(i), excelData, ifNeedCheckParent);
}
if (ifNeedCheckParent) {
// 解析完一行数据后,添加到集合中
dataList.add(excelData);
}
}
/**
* 解析列值
*
* @param rowIndex 行号
* @param columnIndex 列号
* @param columnData 列值,object类型
* @param excelData 实例对象
* @param ifNeedCheckParent 是否需要校验父属性
* @throws Exception 逻辑异常
*/
private void parseColumnData(Integer rowIndex, Integer columnIndex, Object columnData, Teams excelData, boolean ifNeedCheckParent) throws Exception {
// 逐列判断并使用正确的类型接收value,列号从0开始
if (columnIndex == 0 && ifNeedCheckParent) {
//rowNo是临时添加的字段仅用户导入时的业务判断处理(数据库并没有此字段)
excelData.setRowNo(ExcelUtils.getStringValue(columnData));
} else if (columnIndex == 1 && ifNeedCheckParent) {
//班组名称
excelData.setTeamsName(ExcelUtils.checkValue(columnData, rowIndex, columnIndex, "班组名称", 64, null));
} else if (columnIndex == 2 && ifNeedCheckParent) {
//所属部门
String value = ExcelUtils.checkValue(columnData, rowIndex, columnIndex, "所属部门", null, null);
DepartmentWithUserDTO departmentWithUser = departmentUserList.stream().filter(item -> value.equals(item.getDepartmentName())).findFirst().orElse(null);
if (null == departmentWithUser) {
throw new Exception("第" + (rowIndex + 1) + "行,第" + (columnIndex + 1) + "列,所属部门[" + value + "]有误(该部门不属于当前登录用户所属公司)");
}
excelData.setDepartment(departmentWithUser.getDataId());
excelData.setDepartmentName(departmentWithUser.getDepartmentName());
excelData.setUnitId(departmentWithUser.getParentId());
} else if (columnIndex == 3 && ifNeedCheckParent) {
//班组职责描述
excelData.setTeamsDescription(ExcelUtils.checkValue(columnData, rowIndex, columnIndex, "班组职责描述", 1024, null));
} else {
List children = excelData.getDetailList();
if (null == children) {
children = new ArrayList<>();
}
//子的数据
if (columnIndex == 4) {
//班组职位
String value = ExcelUtils.checkValue(columnData, rowIndex, columnIndex, "班组职位", null, null);
DictData dictData = dictDataList.stream().filter(item -> value.equals(item.getDictLabel())).findFirst().orElse(null);
if (null == dictData) {
throw new Exception("第" + (rowIndex + 1) + "行,第" + (columnIndex + 1) + "列,班组职位[" + value + "]有误");
}
TeamsPersonnel child = new TeamsPersonnel();
child.setTeamsDescription(dictData.getDataId());
children.add(child);
} else if (columnIndex == 5) {
//人员姓名
String value = ExcelUtils.checkValue(columnData, rowIndex, columnIndex, "工号", 30, null);
List userList = new ArrayList();
departmentUserList.forEach(item -> {
if (Arrays.asList(3, 4, 5).contains(item.getDepartmentType())) {
userList.addAll(item.getUserList());
}
});
UserSelect user = userList.stream().filter(item -> value.equals(item.getFullname())).findFirst().orElse(null);
if (null == user) {
throw new Exception("第" + (rowIndex + 1) + "行,第" + (columnIndex + 1) + "列人员姓名[" + value + "]有误(该姓名不属于该部门)");
}
TeamsPersonnel child = children.get(children.size() - 1);
child.setEmployeeId(user.getDataId());
}
excelData.setDetailList(children);
}
}
/**
* excel解析后置处理器,在excel解析完成后执行一次
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
System.out.println("excel解析后置处理器");
}
}
3.3 数据导入接口编写
/**
* 导入数据
*
* @param file excel文件
* @return 是否成功
*/
@PostMapping("/import")
@ResponseBody
@Transactional(rollbackFor = Exception.class)
public Object importExcel(@RequestParam("file") @NotNull MultipartFile file) {
Map map = new HashMap<>(8);
//班组职位字典数据
List dictDataList = dictDataService.queryDataByType("TEAM_POSITIONS");
//获取当前公司id
String departmentId = departmentService.getNowUserDepartmentsId();
//查询部门及相关下的人
List departmentUserList = departmentService.listDeptWithUsers(departmentId);
TeamsReadExcelListener excelListener = TeamsReadExcelListener.newBean(dictDataList, departmentUserList);
try {
EasyExcel.read(file.getInputStream()).sheet(0).headRowNumber(1).registerReadListener(excelListener).doRead();
} catch (Exception e) {
e.printStackTrace();
map.put("code", "100");
map.put("msg", "请求失败");
return map;
}
List dataList = excelListener.getDataList();
if (dataList.size() == 0) {
map.put("code", "500");
map.put("msg", "导入数据不能为空");
return map;
}
boolean result = true;
int baseY = 100;
int y = dataList.size() / baseY + 1;
int z = dataList.size() % 100;
for (int i = 0; i < y; i++) {
if (i != y - 1) {
result = teamsService.insertMore(dataList.subList(i * baseY, (i + 1) * baseY));
} else {
result = dataList.subList(i * baseY, i * baseY + z).size() == 0 ? true : teamsService.insertMore(dataList.subList(i * baseY, i * baseY + z));
}
if (!result) {
map.put("code", "500");
map.put("msg", "数据导入失败");
return map;
}
}
List itemList = new ArrayList();
for (Teams item : dataList) {
item.getDetailList().forEach(personnel -> {
personnel.setTeamsId(item.getDataId());
});
itemList.addAll(item.getDetailList());
}
y = itemList.size() / baseY + 1;
z = itemList.size() % 100;
for (int i = 0; i < y; i++) {
if (i != y - 1) {
result = teamsPersonnelService.insertMore(itemList.subList(i * baseY, (i + 1) * baseY));
} else {
result = itemList.subList(i * baseY, i * baseY + z).size() == 0 ? true : teamsPersonnelService.insertMore(itemList.subList(i * baseY, i * baseY + z));
}
if (!result) {
map.put("code", "500");
map.put("msg", "数据导入失败");
return map;
}
}
map.put("code", "200");
map.put("msg", "请求成功");
return map;
}
列合并操作的简单使用大致如上,可以参考学习使用。