当前位置:网站首页>EasyExcel dynamic parsing and save table columns
EasyExcel dynamic parsing and save table columns
2022-08-02 23:02:00 【blue shirt dyed red dust】
背景
The data in one table is derived from exported tables from multiple other systems,The peculiarity is that most of the fields are the same(The exported headers may be different),Only some of the few fields are unique to each system.Do a functional analysis around this
分析:Most fields are the same,Then there are the actual table fields,The only difference is that the names may vary from system to system,Few fields unique to each system,can be classified as dynamic fields.
总结:
- 公共字段(translation header:
@ExcelProperty
Multiple headers can be specified(@ExcelProperty(value = {"发货数量", "采购数量(台)"})
)) - 动态字段(There needs to be a corresponding relationship between the field name and the header of the dynamic field in each system,Consider using a dictionary,For salesman configuration,If you add other dynamic fields later, configure them directly in the dictionary,No further development is required)
注意:Since the actual header of the fixed field in the newly connected system cannot be controlled and expected,So if the public header of the new access system is inconsistent with the table fields,需要在
@ExcelProperty(value = {})
Add a new header to
效果
字典配置:
数据表结果:
Common fields are stored using regular database table fields,Dynamic fields use extra column storage JSON
串.
代码
- 引入pom坐标
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.1.0</version>
</dependency>
- 创建实体类
public class AgentDeliverOrderImportVo {
@ExcelProperty(value = {"订单编号"}, order = 1)
private String deliverNo;
@ExcelProperty(value = {"发货数量", "采购数量(台)"}, order = 14)
@ColumnName(name = {"发货数量", "采购数量(台)"})
private Integer deliverCount;
/**
* 动态字段(Business line number distinction)
*/
private String dynamicFields;
private Date createTime;
private String createBy;
}
- Because there are indeterminate columns,所以只能使用
EasyExcel
A write that does not create an object,那么
public String test(MultipartFile file) throws IOException {
//Suppose you get dictionary values from a dictionary
Map<String, String> dictMap = new HashMap<>();
dictMap.put("项目", "xm");
dictMap.put("Hi pay for the order number", "hyfddbh");
try (InputStream inputStream = file.getInputStream()) {
EasyExcel.read(inputStream, new ReadListener<Map<String, String>>(){
private Map<Integer, String> fieldHead;
//获取表头
@Override
public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
Map<Integer, String> integerStringMap = ConverterUtils.convertToStringMap(headMap, context);
log.info("解析到一条头数据:{}", JSON.toJSONString(integerStringMap));
fieldHead = ExcelParsing.setFieldHead(integerStringMap, AgentDeliverOrderImportVo.class);
log.info("Post-conversion header data:{}", JSONObject.toJSONString(fieldHead));
}
//获取数据
@Override
public void invoke(Map<String, String> map, AnalysisContext analysisContext) {
log.info("解析到一条数据:{}", JSON.toJSONString(map));
Map<String, String> valueMap = ExcelParsing.setFieldValue(fieldHead, dictMap, map);
log.info("Convert a piece of data:{}", JSONObject.toJSONString(valueMap));
log.info("Convert a piece of dynamic data:{}", JSONObject.toJSONString(ExcelParsing.getValueMap(valueMap, AgentDeliverOrderImportVo.class)));
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}).sheet().doRead();
}
return "完成";
}
/**
* @author Surpass
* @Description: excel处理类
* @date 27/07/2022 15:04
*/
class ExcelParsing {
/**
* Convert Chinese in public fields into database table fields,动态字段(其他字段保留)
* @param headMap {1:"姓名", 2:"年龄"}
* @param obj AgentDeliverOrderImportVo(导入实体类)
* @return java.util.Map<java.lang.String, java.lang.String> {1:"name", 2:"年龄"}
* @author Surpass
* @date 01/08/2022 17:10
*/
public static Map<Integer, String> setFieldHead(Map<Integer, String> headMap, Class<?> obj) {
Field[] fields = obj.getDeclaredFields();
for (Field field : fields) {
ExcelProperty annotation = field.getAnnotation(ExcelProperty.class);
if (annotation == null) {
continue;
}
//There are cases where translation fields exist,A field corresponds to several headers(尽量避免)
List<String> valueList = Arrays.asList(annotation.value());
for (Map.Entry<Integer, String> entry : headMap.entrySet()) {
if (valueList.contains(entry.getValue())) {
headMap.put(entry.getKey(), field.getName());
}
}
}
return headMap;
}
/**
* 获取数据(平铺),Refers to dynamic fieldskv和公共字段kv在同一级
* @param headMap {1:"name", 2:"年龄"}
* @param dictMap {"年龄":"age"}
* @param valueMap {1:"广州****公司", 2:"23"}
* @return java.util.Map<java.lang.String, java.lang.String>
* @author Surpass
* @date 01/08/2022 17:10
*/
public static Map<String, String> setFieldValue(Map<Integer, String> headMap,
Map<String, String> dictMap,
Map<String, String> valueMap) {
Map<Integer, String> valueIntegerMap = valueMap.entrySet().stream().collect(
Collectors.toMap(item -> Integer.valueOf(String.valueOf(item.getKey())),
item -> StrUtil.nullToEmpty(item.getValue()))
);
Map<String, String> valueResultMap = new HashMap<>(valueMap.size());
Iterator<Map.Entry<Integer, String>> iterator = valueIntegerMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Integer, String> entry = iterator.next();
//动态字段
if (dictMap != null && dictMap.containsKey(headMap.get(entry.getKey()))) {
valueResultMap.put(dictMap.get(headMap.get(entry.getKey())), entry.getValue());
continue;
}
//公共字段
valueResultMap.put(headMap.get(entry.getKey()), entry.getValue());
iterator.remove();
}
return valueResultMap;
}
/**
* 获取数据(表结构),Refers to dynamic fieldskvhas been added to the database table field dynamicFields 中
* @param obj AgentDeliverOrderImportVo(导入实体类)
* @param valueMap {"name":"广州****公司", "age":"23"}
* @return java.util.Map<java.lang.String, java.lang.String>
* 返回结果: {"name":"广州****公司","dynamicFields":{"age":"23"}}
* @author Surpass
* @date 01/08/2022 17:10
*/
public static Map<String, Object> getValueMap(Map<String, String> valueMap,
Class<?> obj) {
Map<String, Object> resultMap = new HashMap<>(valueMap);
List<String> commonFieldList = new ArrayList<>();
Field[] fields = obj.getDeclaredFields();
for (Field field : fields) {
ExcelProperty annotation = field.getAnnotation(ExcelProperty.class);
if (annotation == null) {
continue;
}
commonFieldList.add(field.getName());
}
//Filter out public fields in entities
Map<String, String> dynamicMap = valueMap.entrySet().stream()
.filter(item -> !commonFieldList.contains(item.getKey()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
resultMap.put("dynamicFields", dynamicMap);;
return resultMap;
}
}
After parsing, the data of this document is consistent with the database table,Then our subsequent operation is the regular checksum insertion logic.
At present, there is a disadvantage that the dynamic fields stored in this way are not suitable for conditional queries,影响不是很大.
总结
本文介绍了使用 EasyExcel
components to import,Implements the import of public column and dynamic column combination types,and how to store the function,Mainly use reflection and dictionary to maintain the correspondence between headers and fields of public columns and dynamic columns, respectively,Use this relationship to parse the data.
边栏推荐
- The so-called fighting skill again gao also afraid of the chopper - partition, depots, table, and the merits of the distributed
- MOSN 反向通道详解
- LM小型可编程控制器软件(基于CoDeSys)笔记二十五:plc的数据存储区(数字量输入通道部分)
- Wintun:一款惊艳的 WireGuard 虚拟网卡接口驱动
- 对话亚洲高校首个博士论文奖-裘捷中丨KDD2022
- Fiddle设置接口数据用指定工具查看;Sublime Text设置json数据格式化转换
- 线程安全(上)
- 译出我精彩 | 7月墨力翻译计划获奖名单公布
- 【数据分析】:什么是数据分析?
- golang刷leetcode 经典(10) tire树与ac自动机
猜你喜欢
OpenCV开发中的内存管理问题
ShardingSphere-proxy +PostgreSQL implements read-write separation (static strategy)
如何解决图像分类中的类别不均衡问题?不妨试试分开学习表征和分类器
Caldera(一)配置完成的虚拟机镜像及admin身份简单使用
Triacetin是什么化学材料
idea 配置resin
牛客题目——滑动窗口的最大值、矩阵最长递增路径、顺时针旋转矩阵、接雨水问题
SQL Server安装教程
【Psychology · Characters】Issue 1
Leetcode刷题——单调栈问题(739每日温度问题、496下一个更大元素I、503下一个更大元素 II)
随机推荐
日志框架学习
ShardingSphere-proxy +PostgreSQL implements read-write separation (static strategy)
所谓武功再高也怕菜刀-分区、分库、分表和分布式的优劣
【LeetCode】622. 设计循环队列
Leetcode刷题——23. 合并K个升序链表
即时通讯开发移动端网络短连接的优化手段
基于“无依赖绝对定位”实现的圣杯三栏布局
顺序查找和折半查找,看这篇就够了
MaxCompute 的SQL 引擎参数化视图具体有哪些增强功能?
es 读流程源码解析
golang 源码分析:uber-go/ratelimit
J9 digital theory: the Internet across chain bridge has what effect?
J9 Digital Currency Theory: Identifying Web3's New Scarcity: Open Source Developers
软件测试分类
Five data structures of Redis and their corresponding usage scenarios
什么是乙二醇二乙酸酯(EGDA)?
Leetcode刷题——单调栈问题(739每日温度问题、496下一个更大元素I、503下一个更大元素 II)
SQL 嵌套 N 层太长太难写怎么办?
AI Scientist: Automatically discover hidden state variables of physical systems
B站HR对面试者声称其核心用户都是生活中的Loser