当前位置:网站首页>【无标题】
【无标题】
2022-04-23 06:45:00 【代码的代】
Java 导入复杂的excel表数据到数据库
看下要导入到数据库的excel表数据有多复杂?直接上图!
如果要导入到数据库就要解析成我需要的样子,如下图所示。
经过对比,不拿发现我们就需要对图一的excel进行解析,直接上代码!
controller层
@PostMapping("/xfkylImport")
@ApiOperation(value = "导入复杂的excel表数据")
public R<Boolean> xfkylImport(@ApiParam(value = "文件对象") @RequestBody MultipartFile file) {
Boolean aBoolean = importTableService.xfkylImport(file);
return R.OK(aBoolean);
}
service层
/** * 导入复杂的excel表数据 * * @param file 文件 * @return 结果 */
public Boolean xfkylImport(MultipartFile file) {
//查询编码表:excel没有单位编号 ,所以只能先查编码表,后面把编码表的单位编号塞到要导入的对应的表数据中
List<IcDwbmk> icDwbmks = icDwbmkService.listAll();
Workbook workbook;
try {
//根据file创建excel
workbook = WorkbookFactory.create(file.getInputStream());
} catch (Exception e) {
throw new CustomException("导入失败,请检查导入模板是否正确");
}
//获取第一个sheet页
Sheet xssSheet0 = workbook.getSheetAt(0);
//获取第一行和最后一行
int rows1 = xssSheet0.getFirstRowNum();
int rows2 = xssSheet0.getLastRowNum();
//创建临时对象接收参数用
List<IcDreportXfkylVo> entities = new ArrayList<>();
List<String> str = new ArrayList<>();
// 一下操作开始:j代表excel的行,k代表excel的列
//循环遍历:舍弃第一行表头数据
for (int j = rows1 + 1; j <= rows2; j++) {
//创建临时对象
IcDreportXfkylVo excelVo = new IcDreportXfkylVo();
//获取当前行
Row row3 = xssSheet0.getRow(j);
//当前行没数据直接结束此次循环
if (null == row3) continue;
//遍历行所有的列
int firstCellNum = row3.getFirstCellNum();
int lastCellNum = row3.getLastCellNum();
//循环列数:舍弃第一列,这里根据业务需求 lastCellNum - 2 操作
for (int k = firstCellNum + 1; k < lastCellNum - 2; k++) {
//获取单元格的值,不管是否合并的单元格,都可以获取
String value = getSheelValue(xssSheet0, j, k);
//列数据为空,结束此次循环
if (StrUtil.isBlank(value)) continue;
//解析excel中的日期值,并存入集合中
if (j == 1 && k == 1) {
//日期格式化
Date date = Convert.toDate(value);
String datee = DateUtil.format(date, "yyyy-MM-dd");
str.add(datee);
}
//舍弃这两列
if (k == 10 || k > 17) continue;
// =========== 条件满足直接结束循环 start(根据实际需求来)===========
if ("数据日期".equals(value)) continue;
if ("测试类别一".equals(value)) continue;
if ("测试类别二".equals(value)) continue;
if (j < 4) continue;
if (j == 5) continue;
if (j > 12) continue;
// =========== 条件满足直接结束循环 end(根据实际需求来)===========
//获取第一列的单位名称与编码表中的名称相匹配,如果相同就取出编码表中的单位编号
if (k == 1) {
//有一个名称对应不上,手动进行改名。
if ("某某公司1".equals(value)) {
value = "某某公司2";
}
//取出每个单位对应的编号
String finalValue = value;
String s = icDwbmks.stream().filter(a -> finalValue.contains(a.getDwmc())).map(IcDwbmk::getDwbh).collect(Collectors.joining());
excelVo.setDwbh(s);
excelVo.setDwmc(value.replace("某某公司2", "某某公司1"));
}
try {
if (StringUtils.isNumeric(value)) {
//把当前列的值赋值给对应的属性字段,每一列对应的值 并以list的形式存储
if (k == 2) excelVo.setSjlx1(Integer.valueOf(value));
if (k == 3) excelVo.setSjlx2(Integer.valueOf(value));
if (k == 4) excelVo.setSjlx3(Integer.valueOf(value));
if (k == 5) excelVo.setSjlx4(Integer.valueOf(value));
if (k == 6) excelVo.setSjlx5(Integer.valueOf(value));
if (k == 7) excelVo.setSjlx6(Integer.valueOf(value));
if (k == 8) excelVo.setSjlx7(Integer.valueOf(value));
if (k == 9) excelVo.setSjlx8(Integer.valueOf(value));
if (k == 11) excelVo.setSjlx9(Integer.valueOf(value));
if (k == 12) excelVo.setSjlx10(Integer.valueOf(value));
if (k == 13) excelVo.setSjlx11(Integer.valueOf(value));
if (k == 14) excelVo.setSjlx12(Integer.valueOf(value));
if (k == 15) excelVo.setSjlx13(Integer.valueOf(value));
if (k == 16) excelVo.setSjlx14(Integer.valueOf(value));
}
} catch (Exception e) {
throw new CustomException("导入失败,请检查导入模板是否正确");
}
}
//j 每循环一次就会存入一次集合数据,这里面会有大量的空对象,后面要对空对象进行清空操作
entities.add(excelVo);
}
if (entities.size() > 0) {
// excel 解析完成:清空集合里面的空对象
entities.removeAll(Collections.singleton(new IcDreportXfkylVo()));
//遍历:把日期值赋值到数据中
for (IcDreportXfkylVo item :
entities) {
item.setDatee(str.get(0));
}
//手动捕捉异常
try {
//批量插入数据
Integer integer = icDreportXfkylMapper.insertBatch(entities);
if (integer > 0) {
return true;
}
} catch (Exception e) {
throw new CustomException("导入失败,请检查导入模板是否正确");
}
}
throw new CustomException("导入失败,请检查导入的excel表数据是否正确");
}
/** * 获取单元格内容,包括合并单元格的 * * @param sheet sheet表单 * @param row 当前行下标 * @param col 当前列下标 * @return 结果 */
public String getSheelValue(Sheet sheet, int row, int col) {
//获取合并区域的数量
int mergedRegions = sheet.getNumMergedRegions();
//遍历合并区域的数量
for (int i = 0; i < mergedRegions; i++) {
//指定索引处的合并区域
CellRangeAddress region = sheet.getMergedRegion(i);
//行开始下标
int firstRow = region.getFirstRow();
//行结束下标
int lastRow = region.getLastRow();
//列开始下标
int firstColumn = region.getFirstColumn();
//列结束下标
int lastColumn = region.getLastColumn();
if (row >= firstRow && row <= lastRow) {
if (col >= firstColumn && col <= lastColumn) {
Row fRow = sheet.getRow(firstRow);
Cell cell = fRow.getCell(firstColumn);
//所有内容已字符串形式处理
cell.setCellType(CellType.STRING);
//以字符串形式获取单元格的值
return cell.getStringCellValue();
}
}
}
Cell cell = sheet.getRow(row).getCell(col);
//所有内容已字符串形式处理
cell.setCellType(CellType.STRING);
return cell.getStringCellValue();
}
经过service层的解析,这里就已经成功完成了图二的效果,最终效果都在 “entities” 这个List集合中了,然后把这个集合数据批量插入到数据库就搞定了。
有类似需求的朋友,直接把我代码拷贝然后根据自己的需求改下,最后根据debug一步步的调试,最终就会成功的。
版权声明
本文为[代码的代]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_46044938/article/details/124315384
边栏推荐
- BUFFCTF文件中的秘密1
- 面试学习路线
- Internal network security attack and defense: a practical guide to penetration testing (5): analysis and defense of horizontal movement in the domain
- Principle of sentinel integrating Nacos to update data dynamically
- 求3个字符串(每串不超过20个字符)中的最大者。
- Série de pénétration Intranet: icmpsh du tunnel Intranet
- Intranet penetration series: icmptunnel of Intranet tunnel (Master James Barlow's)
- Intranet security attack and defense: a practical guide to penetration testing (6): domain controller security
- BUUCTF [极客大挑战 2019]EasySQL1
- Talk about the essence of interface idempotent and consumption idempotent
猜你喜欢
内网渗透系列:内网隧道之icmpsh
Série de pénétration Intranet: icmpsh du tunnel Intranet
LeetCode 1611. 使整数变为 0 的最少操作次数
Feign源码分析
CTF attack and defense world brush questions 51-
C problem of marking the position of polygons surrounded by multiple rectangles
内网渗透系列:内网隧道之icmptunnel(jamesbarlow师傅的)
Intranet penetration series: dns2tcp of Intranet tunnel
sentinel集成nacos动态更新数据原理
Simplify exporting to SVG data files and all images in SVG folder
随机推荐
Interview learning route
Intranet penetration series: dns2tcp of Intranet tunnel
LeetCoed18. 四数之和
面试学习路线
LeetCode15. 三数之和
內網滲透系列:內網隧道之icmpsh
Three minutes to teach you to use Houdini fluid > > to solve particle fluid droplets
Internal network security attack and defense: a practical guide to penetration testing (VII): cross domain attack analysis and defense
Research on system and software security (3)
NIH降血脂指南《your guide to lowering your Cholesterol with TLC》笔记(持续更新中)
Go语学习笔记 - 结构体 | 从零开始Go语言
vivo,硬件安全的爱与雷霆
Intranet penetration series: icmptunnel of Intranet tunnel (by master dhavalkapil)
Intranet penetration series: dnscat2 of Intranet tunnel
MySQL -- the secret of lock -- how to lock data
国基北盛-openstack-容器云-环境搭建
[极客大挑战 2019]Havefun1
How does Apache Hudi accelerate traditional batch mode?
FUEL: Fast UAV Exploration using Incremental Frontier Structure and Hierarchical Planning
雲計算技能大賽 -- openstack私有雲環境 第一部分