记一次excel自定义导入实现
本篇博客的背景和目的:
最近由于公司产品优化升级,为给用户更好的输入批量更新体验,需要开发一个自定义批量更新的功能,在这里将开发思路记下来,一方面供各位小伙伴参考,另一方面自己需要的时候翻出来看看。
注:当前功能仅支持单表批量更新
设计思路:
-
设计一个表,用于存放操作字段的信息,例如:在数据库的字段名、页面显示时候的名称、字段所对应的数据库、实体类中该字段的数据类型(字符串、字典…)、是否是更新时依赖的条件等
-
用户操作下载自定义更新模板,部分代码如下,导出用到了hutool的excel工具类
// 获取所有条件列,由于用户选择中,这些条件列不会显示,用户只是需要选择自己需要更新的列,所以需要查询一下
ArbitraryImportItem item = new ArbitraryImportItem();
item.setModule(module);
item.setIsCondition("1"); // 是条件
List<ArbitraryImportItem> importItemList = arbitraryImportItemService.findList(item);
logger.error("importItemList------->{}", importItemList==null?null:importItemList.size());
if(Collections3.isEmpty(importItemList)) {
redirectAttributes.addFlashAttribute("message", "参数有误,请重新操作");
return importRedirect(request);
}
// 获取选择的列
List<ArbitraryImportItem> importItemIdsList = arbitraryImportItemService.getByIds(arbitraryImportItem);
LinkedList<ArbitraryImportItem> linkedList = Lists.newLinkedList();
linkedList.addAll(importItemList); // 将条件类和用户选择的列统一放到list中,条件列在最前边
linkedList.addAll(importItemIdsList);
List<String> titleRow = CollUtil.newArrayList();
// List<String> tableColumnRow = CollUtil.newArrayList(); // 模板内容尽量少的让用户看到他们看不懂的东西
List<String> dataRow = CollUtil.newArrayList();
for (ArbitraryImportItem importItem : linkedList) {
titleRow.add(importItem.getShowName());
// tableColumnRow.add(importItem.getTableColumn());
String dataText = "";
String attributeType = importItem.getAttributeType();
switch (attributeType) {
case "text":
dataText = "********";
break;
case "dict":
List<Dict> dictList = DictUtils.getDictList(importItem.getDictType());
dataText = Collections3.isEmpty(dictList)?"":dictList.get(0).getLabel();
break;
case "area":
dataText = "110000";
break;
case "college":
dataText = "机械学院";
break;
case "major":
dataText = "自动化专业";
break;
case "date":
dataText = "2022-07-26 10:00:00";
break;
default:
break;
}
dataRow.add(dataText);
}
List<List<String>> rows = CollUtil.newArrayList(titleRow, dataRow);
String filename = "自定义导入更新模板.xls";
ExcelWriter writer = ExcelUtil.getWriter();
writer.setColumnWidth(-1, 25);
writer.setDefaultRowHeight(22);
writer.write(rows, true);
ServletOutputStream out = null;
try {
response.setContentType("application/vnd.ms-excel;charset=utf-8");
response.setHeader("Content-Disposition","attachment;filename=\"" + new String(filename.getBytes("gb2312"), "ISO8859-1" ) + "\"");
out = response.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
redirectAttributes.addFlashAttribute("message", "系统错误,请重新操作");
return importRedirect(request);
}
writer.flush(out, true);
writer.close();
IoUtil.close(out);
- 用户根据模板进行填写,完成后进行导入,导入数据的操作思路是:通过poi获取标题行,然后用标题行的每个标题跟数据库中设置的显示标题做比对,只要有不一样的,就返回导入失败。比对成功,将对应的类信息有顺序的存入list中。然后开始获取每一行的数据,获取到的每一行数据分成两个map进行存储,一个map存放更新的键值对,另一个map存放条件键值对,最后将两个map在封装到一个map中传到dao层进行操作
最终结构:Map<updateDataOrSqlWhereData, Map<table_column_name, value>>
最终传到dao层的是这个封装后的map和操作的数据库表名
主要sql
<update id="importModuleSave" parameterType="java.util.Map">
update ${tableName} set
<foreach collection="map.updateData" item="val" index="key" separator=",">
${key} = #{val}
</foreach>
<where>
<foreach collection="map.updateWhere" item="val" index="key" separator=" ">
and ${key} = #{val}
</foreach>
</where>
</update>
<update id="batchImportModuleSave" parameterType="java.util.List">
<foreach collection="list" item="item" index="index" separator =";">
update ${tableName} set
<foreach collection="item.updateData" item="val" index="key" separator=",">
${key} = #{val}
</foreach>
<where>
<foreach collection="item.updateWhere" item="val" index="key" separator=" ">
and ${key} = #{val}
</foreach>
</where>
</foreach>
</update>
到此本功能就完成了,小伙伴们有什么简介可以在评论去提出来,交流促进成长