亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

java EasyExcel實現(xiàn)動態(tài)列解析和存表

 更新時間:2023年06月15日 17:28:32   作者:我是一顆小虎牙_  
這篇文章主要為大家介紹了java EasyExcel實現(xiàn)動態(tài)列解析和存表示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

背景

一個表中的數(shù)據(jù)來源于多個其他系統(tǒng)的導出表,其中的特點就是大多數(shù)的字段都是一樣的(可能導出的表頭不一樣),只有部分少數(shù)字段是每個系統(tǒng)自己獨有的。圍繞這個做一次功能性分析

分析:大多數(shù)字段是一樣的,那么就是實際的表字段,唯一的區(qū)別就是各系統(tǒng)內(nèi)的名字可能不一樣,少數(shù)每個系統(tǒng)獨有的字段,可以歸為動態(tài)字段。

總結:

  • 公共字段(翻譯表頭:@ExcelProperty 可以指定多個表頭( @ExcelProperty(value = {"發(fā)貨數(shù)量", "采購數(shù)量(臺)"}) ))
  • 動態(tài)字段(需要有每個系統(tǒng)內(nèi)動態(tài)字段的字段名稱和表頭的對應關系,考慮使用字典,供業(yè)務員配置,后續(xù)如果新添加其他動態(tài)字段直接在字典中配置,無需另行開發(fā))

注意:由于無法控制和預料固定字段在新接入的系統(tǒng)中的實際表頭,所以如果新接入系統(tǒng)的公共表頭與表字段不一致,需要在 @ExcelProperty(value = {}) 中添加新的表頭

效果

字典配置:

數(shù)據(jù)表結果:

公共字段使用常規(guī)的數(shù)據(jù)庫表字段存儲,動態(tài)字段使用額外列存 JSON 串。

代碼

引入pom坐標

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.1.0</version>
</dependency>

創(chuàng)建實體類

public class AgentDeliverOrderImportVo {
    @ExcelProperty(value = {"訂單編號"}, order = 1)
    private String deliverNo;
    @ExcelProperty(value = {"發(fā)貨數(shù)量", "采購數(shù)量(臺)"}, order = 14)
    @ColumnName(name = {"發(fā)貨數(shù)量", "采購數(shù)量(臺)"})
    private Integer deliverCount;
    /**
     * 動態(tài)字段(業(yè)務線編號區(qū)分)
     */
    private String dynamicFields;
    private Date createTime;
    private String createBy;
}
  • 因為存在不確定的列,所以只能使用 EasyExcel 的不創(chuàng)建對象的寫,那么
public String test(MultipartFile file) throws IOException {
    //假設從字典中獲取字典值
    Map<String, String> dictMap = new HashMap<>();
    dictMap.put("項目", "xm");
    dictMap.put("嗨一付訂單編號", "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("解析到一條頭數(shù)據(jù):{}", JSON.toJSONString(integerStringMap));
                fieldHead = ExcelParsing.setFieldHead(integerStringMap, AgentDeliverOrderImportVo.class);
                log.info("轉化后頭數(shù)據(jù):{}", JSONObject.toJSONString(fieldHead));
            }
            //獲取數(shù)據(jù)
            @Override
            public void invoke(Map<String, String> map, AnalysisContext analysisContext) {
                log.info("解析到一條數(shù)據(jù):{}", JSON.toJSONString(map));
                Map<String, String> valueMap = ExcelParsing.setFieldValue(fieldHead, dictMap, map);
                log.info("轉化一條數(shù)據(jù):{}", JSONObject.toJSONString(valueMap));
                log.info("轉化一條動態(tài)數(shù)據(jù):{}", 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 {
    /**
     * 將公共字段中的中文轉換成數(shù)據(jù)庫表字段,動態(tài)字段(其他字段保留)
     * @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;
            }
            //存在翻譯字段的情況,一個字段對應好幾個表頭(盡量避免)
            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;
    }
    /**
     * 獲取數(shù)據(jù)(平鋪),指動態(tài)字段kv和公共字段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();
            //動態(tài)字段
            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;
    }
    /**
     * 獲取數(shù)據(jù)(表結構),指動態(tài)字段kv已經(jīng)加入到數(shù)據(jù)庫表字段 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());
        }
        //過濾掉實體中的公共字段
        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;
    }
}

經(jīng)過解析以后這個文檔的數(shù)據(jù)已經(jīng)和數(shù)據(jù)庫表一致了,那么我們后續(xù)的操作就是常規(guī)的校驗和插入邏輯了。

目前有一個缺點就是這樣存的動態(tài)字段不好做條件查詢,影響不是很大。

總結

本文介紹了使用 EasyExcel 組件來進行導入,實現(xiàn)公共列和動態(tài)列組合類型的導入,以及如何存儲的功能,主要利用反射和字典分別來維護公共列和動態(tài)列的表頭和字段的對應關系,利用此關系對數(shù)據(jù)進行解析。

以上就是java EasyExcel實現(xiàn)動態(tài)列解析和存表的詳細內(nèi)容,更多關于java EasyExcel動態(tài)列存表的資料請關注腳本之家其它相關文章!

相關文章

  • Java如何使用JWT實現(xiàn)Token認證機制

    Java如何使用JWT實現(xiàn)Token認證機制

    JWT(JSON Web Token)是一種用于在網(wǎng)絡上安全地傳輸信息的簡潔的、URL 安全的表示方法,本文主要介紹了Java如何使用JWT實現(xiàn)Token認證機制,需要的可以參考下
    2024-10-10
  • 詳解Spring @Autowired 注入小技巧

    詳解Spring @Autowired 注入小技巧

    這篇文章主要介紹了詳解Spring @Autowired 注入小技巧,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • Spring中的NamespaceHandler接口及相關軟件包說明

    Spring中的NamespaceHandler接口及相關軟件包說明

    這篇文章主要介紹了Spring中的NamespaceHandler接口及相關軟件包說明,NamespaceHandler 接口,DefaultBeanDefinitionDocumentReader 使用該接口來處理在spring xml 配置文件中自定義的命名空間,需要的朋友可以參考下
    2023-12-12
  • SpringBoot項目導入aliyun oss starter依賴后啟動報錯問題

    SpringBoot項目導入aliyun oss starter依賴后啟動報錯問題

    這篇文章主要介紹了SpringBoot項目導入aliyun oss starter依賴后啟動報錯問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Java基礎學習之構造方法詳解

    Java基礎學習之構造方法詳解

    這篇文章主要為大家詳細介紹了Java基礎學習中構造方法的概述及注意事項,文中的示例代碼講解詳細,對我們學習Java有一定幫助,需要的可以參考一下
    2022-08-08
  • 關于Java中的實體類要?implements?Serializable的原因分析

    關于Java中的實體類要?implements?Serializable的原因分析

    這篇文章主要介紹了Java中的實體類為什么要?implements?Serializable,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-06-06
  • JavaWeb實現(xiàn)文件上傳與下載的方法

    JavaWeb實現(xiàn)文件上傳與下載的方法

    這篇文章主要介紹了JavaWeb實現(xiàn)文件上傳與下載的方法的相關資料,需要的朋友可以參考下
    2016-01-01
  • springboot整合redis修改分區(qū)的操作流程

    springboot整合redis修改分區(qū)的操作流程

    這篇文章主要介紹了springboot整合redis修改分區(qū)的操作流程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • 對arraylist中元素進行排序實例代碼

    對arraylist中元素進行排序實例代碼

    這篇文章主要介紹了對arraylist中元素進行排序實例代碼,還是比較不錯的,這里分享給大家,供需要的朋友參考。
    2017-11-11
  • java郵件亂碼的徹底解決方案

    java郵件亂碼的徹底解決方案

    在本篇文章里小編給大家整理的是關于java郵件亂碼的徹底解決方案,需要的朋友們可以學習下。
    2019-12-12

最新評論